~sircmpwn/aerc

widgets/compose: Support non-zero editor exit code v1 PROPOSED

Rather than fishing the aerc instance down into this widget, I'd rather
have it emit a Closed event or something similar, then remove the tab
from higher up.
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/aerc/%3C20190807192733.4195-1-kkuehler%40brave.com%3E/mbox | git am -3
Learn more about email & git

[PATCH] widgets/compose: Support non-zero editor exit code Export this patch

Kevin Kuehler
From: Kevin Kuehler <keur@ocf.berkeley.edu>

Abort the compose view and close the tab if the editor returns a
non-zero exit code. This can be achieved in vim by running :cq.

Fixes #258

Signed-off-by: Kevin Kuehler <keur@ocf.berkeley.edu>
---
 commands/account/compose.go |  2 +-
 commands/msg/reply.go       |  2 +-
 commands/msg/unsubscribe.go |  1 +
 widgets/aerc.go             |  2 +-
 widgets/compose.go          | 13 ++++++++++---
 widgets/terminal.go         | 11 ++++++++++-
 6 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/commands/account/compose.go b/commands/account/compose.go
index f615c0b..c7ad168 100644
--- a/commands/account/compose.go
+++ b/commands/account/compose.go
@@ -27,7 +27,7 @@ func (_ Compose) Execute(aerc *widgets.Aerc, args []string) error {
 	}
 	acct := aerc.SelectedAccount()
 	composer := widgets.NewComposer(
-		aerc.Config(), acct.AccountConfig(), acct.Worker(), nil)
+		aerc, aerc.Config(), acct.AccountConfig(), acct.Worker(), nil)
 	tab := aerc.NewTab(composer, "New email")
 	composer.OnHeaderChange("Subject", func(subject string) {
 		if subject == "" {
diff --git a/commands/msg/reply.go b/commands/msg/reply.go
index 029cb42..e213725 100644
--- a/commands/msg/reply.go
+++ b/commands/msg/reply.go
@@ -121,7 +121,7 @@ func (_ reply) Execute(aerc *widgets.Aerc, args []string) error {
 	}

 	composer := widgets.NewComposer(
-		aerc.Config(), acct.AccountConfig(), acct.Worker(), defaults)
+		aerc, aerc.Config(), acct.AccountConfig(), acct.Worker(), defaults)

 	if args[0] == "reply" {
 		composer.FocusTerminal()
diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go
index f18da07..15a9411 100644
--- a/commands/msg/unsubscribe.go
+++ b/commands/msg/unsubscribe.go
@@ -88,6 +88,7 @@ func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error {
 		"Subject": u.Query().Get("subject"),
 	}
 	composer := widgets.NewComposer(
+		aerc,
 		aerc.Config(),
 		acct.AccountConfig(),
 		acct.Worker(),
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 23dac3e..30a33e8 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -386,7 +386,7 @@ func (aerc *Aerc) Mailto(addr *url.URL) error {
 			defaults[header] = strings.Join(vals, ",")
 		}
 	}
-	composer := NewComposer(aerc.Config(),
+	composer := NewComposer(aerc, aerc.Config(),
 		acct.AccountConfig(), acct.Worker(), defaults)
 	composer.FocusSubject()
 	title := "New email"
diff --git a/widgets/compose.go b/widgets/compose.go
index c7e38b8..3692f8b 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -27,6 +27,7 @@ import (
 type Composer struct {
 	editors map[string]*headerEditor

+	aerc   *Aerc
 	acct   *config.AccountConfig
 	config *config.AercConfig

@@ -44,7 +45,7 @@ type Composer struct {
 	focused   int
 }

-func NewComposer(conf *config.AercConfig,
+func NewComposer(aerc *Aerc, conf *config.AercConfig,
 	acct *config.AccountConfig, worker *types.Worker, defaults map[string]string) *Composer {

 	if defaults == nil {
@@ -64,6 +65,7 @@ func NewComposer(conf *config.AercConfig,
 	}

 	c := &Composer{
+		aerc:     aerc,
 		editors:  editors,
 		acct:     acct,
 		config:   conf,
@@ -463,10 +465,15 @@ func (c *Composer) resetReview() {

 func (c *Composer) termClosed(err error) {
 	c.grid.RemoveChild(c.editor)
-	c.review = newReviewMessage(c, err)
-	c.grid.AddChild(c.review).At(1, 0)
 	c.editor.Destroy()
+	if c.editor.ExitCode() != 0 {
+		c.aerc.RemoveTab(c)
+		c.editor = nil
+		return
+	}
 	c.editor = nil
+	c.review = newReviewMessage(c, err)
+	c.grid.AddChild(c.review).At(1, 0)
 	c.focusable = c.focusable[:len(c.focusable)-1]
 	if c.focused >= len(c.focusable) {
 		c.focused = len(c.focusable) - 1
diff --git a/widgets/terminal.go b/widgets/terminal.go
index aa7c2ba..2016d40 100644
--- a/widgets/terminal.go
+++ b/widgets/terminal.go
@@ -96,6 +96,7 @@ type Terminal struct {
 	cursorShown bool
 	destroyed   bool
 	err         error
+	exitCode    int
 	focus       bool
 	pty         *os.File
 	start       chan interface{}
@@ -169,6 +170,10 @@ func (term *Terminal) flushTerminal() {
 	}
 }

+func (term *Terminal) ExitCode() int {
+	return term.exitCode
+}
+
 func (term *Terminal) Close(err error) {
 	if term.closed {
 		return
@@ -179,7 +184,11 @@ func (term *Terminal) Close(err error) {
 		term.pty = nil
 	}
 	if term.cmd != nil && term.cmd.Process != nil {
-		term.cmd.Process.Kill()
+		if term.cmd.Process != nil {
+			term.cmd.Process.Kill()
+		}
+		term.cmd.Wait() // Process is dead. We need this for an exit code
+		term.exitCode = term.cmd.ProcessState.ExitCode()
 		term.cmd = nil
 	}
 	if !term.closed && term.OnClose != nil {
--
2.22.0
Rather than fishing the aerc instance down into this widget, I'd rather
have it emit a Closed event or something similar, then remove the tab
from higher up.
View this thread in the archives