Implement :edit in compose screen

This commit is contained in:
Drew DeVault 2019-05-26 11:58:14 -04:00
parent 3cf6c82633
commit 887ff6550d
4 changed files with 80 additions and 28 deletions

View File

@ -8,11 +8,17 @@ GOFLAGS?=
GOSRC := \ GOSRC := \
$(wildcard *.go) \ $(wildcard *.go) \
$(wildcard commands/*.go) \ $(wildcard commands/*.go) \
$(wildcard config/*.go) \ $(wildcard commands/account/*.go) \
$(wildcard commands/compose/*.go) \
$(wildcard commands/msgview/*.go) \
$(wildcard config/terminal/*.go) \
$(wildcard lib/*.go) \ $(wildcard lib/*.go) \
$(wildcard lib/ui/*.go) \
$(wildcard ui/*.go) \ $(wildcard ui/*.go) \
$(wildcard widgets/*.go) \ $(wildcard widgets/*.go) \
$(wildcard worker/*.go) \ $(wildcard worker/*.go) \
$(wildcard worker/imap/*.go) \
$(wildcard worker/types/*.go) \
go.mod go.sum go.mod go.sum
aerc: $(GOSRC) aerc: $(GOSRC)

21
commands/compose/edit.go Normal file
View File

@ -0,0 +1,21 @@
package compose
import (
"errors"
"git.sr.ht/~sircmpwn/aerc/widgets"
)
func init() {
register("edit", CommandEdit)
}
func CommandEdit(aerc *widgets.Aerc, args []string) error {
if len(args) != 1 {
return errors.New("Usage: edit")
}
composer, _ := aerc.SelectedTab().(*widgets.Composer)
composer.ShowTerminal()
composer.FocusTerminal()
return nil
}

View File

@ -72,6 +72,7 @@ $ex = <semicolon>
# Keybindings used when reviewing a message to be sent # Keybindings used when reviewing a message to be sent
y = :send<Enter> y = :send<Enter>
n = :abort<Enter> n = :abort<Enter>
q = :abort<Enter>
e = :edit<Enter> e = :edit<Enter>
a = :attach<Enter> a = :attach<Enter>

View File

@ -27,7 +27,8 @@ type Composer struct {
to *headerEditor to *headerEditor
} }
config *config.AccountConfig acct *config.AccountConfig
config *config.AercConfig
defaults map[string]string defaults map[string]string
editor *Terminal editor *Terminal
@ -75,34 +76,22 @@ func NewComposer(conf *config.AercConfig,
return nil return nil
} }
editorName := conf.Compose.Editor
if editorName == "" {
editorName = os.Getenv("EDITOR")
}
if editorName == "" {
editorName = "vi"
}
editor := exec.Command(editorName, email.Name())
term, _ := NewTerminal(editor)
grid.AddChild(headers).At(0, 0) grid.AddChild(headers).At(0, 0)
grid.AddChild(term).At(1, 0)
c := &Composer{ c := &Composer{
config: acct, acct: acct,
editor: term, config: conf,
email: email, email: email,
grid: grid, grid: grid,
worker: worker, worker: worker,
// You have to backtab to get to "From", since you usually don't edit it // You have to backtab to get to "From", since you usually don't edit it
focused: 1, focused: 1,
focusable: []ui.DrawableInteractive{from, to, subject, term}, focusable: []ui.DrawableInteractive{from, to, subject},
} }
c.headers.to = to c.headers.to = to
c.headers.from = from c.headers.from = from
c.headers.subject = subject c.headers.subject = subject
c.ShowTerminal()
term.OnClose = c.termClosed
return c return c
} }
@ -136,6 +125,9 @@ func (c *Composer) SetContents(reader io.Reader) *Composer {
} }
func (c *Composer) FocusTerminal() *Composer { func (c *Composer) FocusTerminal() *Composer {
if c.editor == nil {
return c
}
c.focusable[c.focused].Focus(false) c.focusable[c.focused].Focus(false)
c.focused = 3 c.focused = 3
c.focusable[c.focused].Focus(true) c.focusable[c.focused].Focus(true)
@ -194,7 +186,7 @@ func (c *Composer) Focus(focus bool) {
} }
func (c *Composer) Config() *config.AccountConfig { func (c *Composer) Config() *config.AccountConfig {
return c.config return c.acct
} }
func (c *Composer) Worker() *types.Worker { func (c *Composer) Worker() *types.Worker {
@ -288,11 +280,36 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
} }
func (c *Composer) termClosed(err error) { func (c *Composer) termClosed(err error) {
// TODO: do we care about that error (note: yes, we do)
c.grid.RemoveChild(c.editor) c.grid.RemoveChild(c.editor)
c.grid.AddChild(newReviewMessage(c)).At(1, 0) c.review = newReviewMessage(c, err)
c.grid.AddChild(c.review).At(1, 0)
c.editor.Destroy() c.editor.Destroy()
c.editor = nil c.editor = nil
c.focusable = c.focusable[:len(c.focusable)-1]
if c.focused >= len(c.focusable) {
c.focused = len(c.focusable) - 1
}
}
func (c *Composer) ShowTerminal() {
if c.editor != nil {
return
}
if c.review != nil {
c.grid.RemoveChild(c.review)
}
editorName := c.config.Compose.Editor
if editorName == "" {
editorName = os.Getenv("EDITOR")
}
if editorName == "" {
editorName = "vi"
}
editor := exec.Command(editorName, c.email.Name())
c.editor, _ = NewTerminal(editor) // TODO: handle error
c.editor.OnClose = c.termClosed
c.grid.AddChild(c.editor).At(1, 0)
c.focusable = append(c.focusable, c.editor)
} }
func (c *Composer) PrevField() { func (c *Composer) PrevField() {
@ -359,7 +376,7 @@ type reviewMessage struct {
grid *ui.Grid grid *ui.Grid
} }
func newReviewMessage(composer *Composer) *reviewMessage { func newReviewMessage(composer *Composer, err error) *reviewMessage {
grid := ui.NewGrid().Rows([]ui.GridSpec{ grid := ui.NewGrid().Rows([]ui.GridSpec{
{ui.SIZE_EXACT, 2}, {ui.SIZE_EXACT, 2},
{ui.SIZE_EXACT, 1}, {ui.SIZE_EXACT, 1},
@ -367,12 +384,19 @@ func newReviewMessage(composer *Composer) *reviewMessage {
}).Columns([]ui.GridSpec{ }).Columns([]ui.GridSpec{
{ui.SIZE_WEIGHT, 1}, {ui.SIZE_WEIGHT, 1},
}) })
if err != nil {
grid.AddChild(ui.NewText(err.Error()).
Color(tcell.ColorRed, tcell.ColorDefault))
grid.AddChild(ui.NewText("Press [q] to close this tab.")).At(1, 0)
} else {
// TODO: source this from actual keybindings?
grid.AddChild(ui.NewText( grid.AddChild(ui.NewText(
"Send this email? [y]es/[n]o/[e]dit/[a]ttach file")).At(0, 0) "Send this email? [y]es/[n]o/[e]dit")).At(0, 0)
grid.AddChild(ui.NewText("Attachments:"). grid.AddChild(ui.NewText("Attachments:").
Reverse(true)).At(1, 0) Reverse(true)).At(1, 0)
// TODO: Attachments // TODO: Attachments
grid.AddChild(ui.NewText("(none)")).At(2, 0) grid.AddChild(ui.NewText("(none)")).At(2, 0)
}
return &reviewMessage{ return &reviewMessage{
composer: composer, composer: composer,