diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go index 205a255..cf3e4a8 100644 --- a/commands/msg/unsubscribe.go +++ b/commands/msg/unsubscribe.go @@ -119,6 +119,5 @@ func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error { } func unsubscribeHTTP(u *url.URL) error { - lib.OpenFile(u.String(), nil) - return nil + return lib.NewXDGOpen(u.String()).Start() } diff --git a/commands/msgview/open.go b/commands/msgview/open.go index 4aa6133..47b4369 100644 --- a/commands/msgview/open.go +++ b/commands/msgview/open.go @@ -1,7 +1,6 @@ package msgview import ( - "errors" "fmt" "io" "io/ioutil" @@ -28,10 +27,6 @@ func (Open) Complete(aerc *widgets.Aerc, args []string) []string { } func (Open) Execute(aerc *widgets.Aerc, args []string) error { - if len(args) != 1 { - return errors.New("Usage: open") - } - mv := aerc.SelectedTab().(*widgets.MessageViewer) p := mv.SelectedMessagePart() @@ -60,9 +55,22 @@ func (Open) Execute(aerc *widgets.Aerc, args []string) error { return } - lib.OpenFile(tmpFile.Name(), func(err error) { - aerc.PushError(" " + err.Error()) - }) + xdg := lib.NewXDGOpen(tmpFile.Name()) + // pass through any arguments the user provided to the underlying handler + if len(args) > 1 { + xdg.SetArgs(args[1:]) + } + err = xdg.Start() + if err != nil { + aerc.PushError(err.Error()) + return + } + go func() { + err := xdg.Wait() + if err != nil { + aerc.PushError(" " + err.Error()) + } + }() aerc.PushStatus("Opened", 10*time.Second) }) diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index 58f35bc..f678a0a 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -307,9 +307,9 @@ message list, the message in the message viewer, etc). Cycles between message parts being shown. The list of message parts is shown at the bottom of the message viewer. -*open* +*open* [args...] Saves the current message part in a temporary file and opens it - with the system handler. + with the system handler. Any given args are forwarded to the open handler *save* [-fp] Saves the current message part to the given path. diff --git a/lib/open.go b/lib/open.go index ebcf878..8a016eb 100644 --- a/lib/open.go +++ b/lib/open.go @@ -1,23 +1,62 @@ -// +build !darwin - package lib import ( "os/exec" + "runtime" ) -func OpenFile(filename string, onErr func(error)) { - cmd := exec.Command("xdg-open", filename) - err := cmd.Start() - if err != nil && onErr != nil { - onErr(err) - return +var openBin string = "xdg-open" + +func init() { + if runtime.GOOS == "darwin" { + openBin = "open" + } +} + +type xdgOpen struct { + args []string + errCh chan (error) + cmd *exec.Cmd +} + +// NewXDGOpen returns a handler for opening a file via the system handler xdg-open +// or comparable tools on other OSs than Linux +func NewXDGOpen(filename string) *xdgOpen { + errch := make(chan error, 1) + return &xdgOpen{ + errCh: errch, + args: []string{filename}, } - go func() { - err := cmd.Wait() - if err != nil && onErr != nil { - onErr(err) - } - }() +} + +// SetArgs sets additional arguments to the open command prior to the filename +func (xdg *xdgOpen) SetArgs(args []string) { + args = append([]string{}, args...) // don't overwrite array of caller + filename := xdg.args[len(xdg.args)-1] + xdg.args = append(args, filename) +} + +// Start the open handler. +// Returns an error if the command could not be started. +// Use Wait to wait for the commands completion and to check the error. +func (xdg *xdgOpen) Start() error { + xdg.cmd = exec.Command(openBin, xdg.args...) + err := xdg.cmd.Start() + if err != nil { + xdg.errCh <- err // for callers that just check the error from Wait() + close(xdg.errCh) + return err + } + go func() { + xdg.errCh <- xdg.cmd.Wait() + close(xdg.errCh) + }() + return nil +} + +// Wait for the xdg-open command to complete +// The xdgOpen must have been started +func (xdg *xdgOpen) Wait() error { + return <-xdg.errCh } diff --git a/lib/open_darwin.go b/lib/open_darwin.go deleted file mode 100644 index d98c898..0000000 --- a/lib/open_darwin.go +++ /dev/null @@ -1,21 +0,0 @@ -package lib - -import ( - "os/exec" -) - -func OpenFile(filename string, onErr func(error)) { - cmd := exec.Command("open", filename) - err := cmd.Start() - if err != nil && onErr != nil { - onErr(err) - return - } - - go func() { - err := cmd.Wait() - if err != nil && onErr != nil { - onErr(err) - } - }() -}