diff options
-rw-r--r-- | commands/compose/attach.go | 93 | ||||
-rw-r--r-- | config/aerc.conf | 8 | ||||
-rw-r--r-- | config/compose.go | 1 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 13 | ||||
-rw-r--r-- | doc/aerc.1.scd | 6 |
5 files changed, 118 insertions, 3 deletions
diff --git a/commands/compose/attach.go b/commands/compose/attach.go index 99898d5d..967b7902 100644 --- a/commands/compose/attach.go +++ b/commands/compose/attach.go @@ -1,9 +1,12 @@ package compose import ( + "bufio" "errors" "fmt" + "io" "os" + "os/exec" "path/filepath" "strings" @@ -28,12 +31,19 @@ func (Attach) Complete(aerc *widgets.Aerc, args []string) []string { return commands.CompletePath(path) } -func (Attach) Execute(aerc *widgets.Aerc, args []string) error { +func (a Attach) Execute(aerc *widgets.Aerc, args []string) error { if len(args) == 1 { return fmt.Errorf("Usage: :attach <path>") } - path := strings.Join(args[1:], " ") + if args[1] == "-m" { + return a.openMenu(aerc, args[2:]) + } + + return a.addPath(aerc, strings.Join(args[1:], " ")) +} + +func (a Attach) addPath(aerc *widgets.Aerc, path string) error { path, err := homedir.Expand(path) if err != nil { logging.Errorf("failed to expand path '%s': %v", path, err) @@ -76,3 +86,82 @@ func (Attach) Execute(aerc *widgets.Aerc, args []string) error { return nil } + +func (a Attach) openMenu(aerc *widgets.Aerc, args []string) error { + filePickerCmd := aerc.Config().Compose.FilePickerCmd + if filePickerCmd == "" { + return fmt.Errorf("no file-picker-cmd defined") + } + + if strings.Contains(filePickerCmd, "%s") { + verb := "" + if len(args) > 0 { + verb = args[0] + } + filePickerCmd = strings.ReplaceAll(filePickerCmd, "%s", verb) + } + + picks, err := os.CreateTemp("", "aerc-filepicker-*") + if err != nil { + return err + } + + filepicker := exec.Command("sh", "-c", filePickerCmd+" >&3") + filepicker.ExtraFiles = append(filepicker.ExtraFiles, picks) + + t, err := widgets.NewTerminal(filepicker) + if err != nil { + return err + } + t.OnClose = func(err error) { + defer func() { + if err := picks.Close(); err != nil { + logging.Errorf("error closing file: %v", err) + } + if err := os.Remove(picks.Name()); err != nil { + logging.Errorf("could not remove tmp file: %v", err) + } + }() + + aerc.CloseDialog() + + if err != nil { + logging.Errorf("terminal closed with error: %v", err) + return + } + + _, err = picks.Seek(0, io.SeekStart) + if err != nil { + logging.Errorf("seek failed: %v", err) + } + + scanner := bufio.NewScanner(picks) + for scanner.Scan() { + f := strings.TrimSpace(scanner.Text()) + if _, err := os.Stat(f); err != nil { + continue + } + logging.Infof("File picker attaches: %v", f) + err := a.addPath(aerc, f) + if err != nil { + logging.Errorf("attach failed "+ + "for file %s: %v", f, err) + } + + } + } + + aerc.AddDialog(widgets.NewDialog( + t, + // start pos on screen + func(h int) int { + return h / 8 + }, + // dialog height + func(h int) int { + return h - 2*h/8 + }, + )) + + return nil +} diff --git a/config/aerc.conf b/config/aerc.conf index adfa1e12..8b153ad8 100644 --- a/config/aerc.conf +++ b/config/aerc.conf @@ -338,6 +338,14 @@ header-layout=To|From,Subject # This parameter can also be set per account in accounts.conf. address-book-cmd= +# Specifies the command to be used to select attachments. Any occurence of '%s' +# in the file-picker-cmd will be replaced the argument <arg> to :attach -m +# <arg>. +# +# The command must output the selected files to standard output, one file per +# line. +file-picker-cmd= + # # Allow to address yourself when replying # diff --git a/config/compose.go b/config/compose.go index 31ee0a8b..f9c1ba90 100644 --- a/config/compose.go +++ b/config/compose.go @@ -14,6 +14,7 @@ type ComposeConfig struct { AddressBookCmd string `ini:"address-book-cmd"` ReplyToSelf bool `ini:"reply-to-self"` NoAttachmentWarning *regexp.Regexp `ini:"-"` + FilePickerCmd string `ini:"file-picker-cmd"` } func defaultComposeConfig() ComposeConfig { diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index f18b5110..513f7373 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -555,6 +555,19 @@ These options are configured in the *[compose]* section of aerc.conf. Default: none +*file-picker-cmd* + Specifies the command to be used to select attachments. Any occurence of + '%s' in the file-picker-cmd will be replaced with the argument <arg> + to :attach -m <arg>. + + The command must output the selected files to standard output, + one file per line. + + Example: + file-picker-cmd=fzf --multi --query=%s + + Default: none + *reply-to-self* If set to false, do not mail yourself when replying (e.g., if replying to emails previously sent by yourself, address your replies to the diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index 4f9b6a7f..c1efc954 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -479,10 +479,14 @@ message list, the message in the message viewer, etc). *abort* Close the composer without sending, discarding the message in progress. -*attach* <path> +*attach* [-m [<arg>] | <path>] Attaches the file at the given path to the email. The path can contain globbing syntax described at https://godocs.io/path/filepath#Match. + *-m* [<arg>] + Runs the 'file-picker-cmd' to select files to be attached. + Requires an argument when 'file-picker-cmd' contains the '%s' verb. + *attach-key* Attaches the public key for the configured account to the email. |