diff options
-rw-r--r-- | app/aerc.go | 10 | ||||
-rw-r--r-- | app/compose.go | 8 | ||||
-rw-r--r-- | app/msgviewer.go | 7 | ||||
-rw-r--r-- | commands/patch/list.go | 113 | ||||
-rw-r--r-- | config/cmds.go | 22 | ||||
-rw-r--r-- | lib/pama/list.go | 59 |
6 files changed, 202 insertions, 17 deletions
diff --git a/app/aerc.go b/app/aerc.go index 046c7871..c7307540 100644 --- a/app/aerc.go +++ b/app/aerc.go @@ -873,9 +873,9 @@ func (aerc *Aerc) isExKey(event *tcell.EventKey, exKey config.KeyStroke) bool { return event.Modifiers() == exKey.Modifiers && event.Key() == exKey.Key } -// cmdFallbackSearch checks cmds for the first executable availabe in PATH. An error is +// CmdFallbackSearch checks cmds for the first executable availabe in PATH. An error is // returned if none are found -func cmdFallbackSearch(cmds []string) (string, error) { +func CmdFallbackSearch(cmds []string, silent bool) (string, error) { var tried []string for _, cmd := range cmds { if cmd == "" { @@ -885,8 +885,10 @@ func cmdFallbackSearch(cmds []string) (string, error) { _, err := exec.LookPath(params[0]) if err != nil { tried = append(tried, cmd) - warn := fmt.Sprintf("cmd '%s' not found in PATH, using fallback", cmd) - PushWarning(warn) + if !silent { + warn := fmt.Sprintf("cmd '%s' not found in PATH, using fallback", cmd) + PushWarning(warn) + } continue } return cmd, nil diff --git a/app/compose.go b/app/compose.go index 75f90f12..35fdd9bf 100644 --- a/app/compose.go +++ b/app/compose.go @@ -1320,13 +1320,7 @@ func (c *Composer) showTerminal() error { if c.editor != nil { c.editor.Destroy() } - cmds := []string{ - config.Compose.Editor, - os.Getenv("EDITOR"), - "vi", - "nano", - } - editorName, err := cmdFallbackSearch(cmds) + editorName, err := CmdFallbackSearch(config.EditorCmds(), false) if err != nil { c.acct.PushError(fmt.Errorf("could not start editor: %w", err)) } diff --git a/app/msgviewer.go b/app/msgviewer.go index abed93fd..e45a6d3e 100644 --- a/app/msgviewer.go +++ b/app/msgviewer.go @@ -421,12 +421,7 @@ func NewPartViewer( pagerin io.WriteCloser term *Terminal ) - cmds := []string{ - config.Viewer.Pager, - os.Getenv("PAGER"), - "less -Rc", - } - pagerCmd, err := cmdFallbackSearch(cmds) + pagerCmd, err := CmdFallbackSearch(config.PagerCmds(), false) if err != nil { acct.PushError(fmt.Errorf("could not start pager: %w", err)) return nil, err diff --git a/commands/patch/list.go b/commands/patch/list.go new file mode 100644 index 00000000..6dcc06e8 --- /dev/null +++ b/commands/patch/list.go @@ -0,0 +1,113 @@ +package patch + +import ( + "bufio" + "fmt" + "io" + "os/exec" + "time" + + "git.sr.ht/~rjarry/aerc/app" + "git.sr.ht/~rjarry/aerc/config" + "git.sr.ht/~rjarry/aerc/lib/pama" + "git.sr.ht/~rjarry/aerc/lib/pama/models" + "git.sr.ht/~rjarry/aerc/lib/ui" + "git.sr.ht/~rjarry/go-opt" + "github.com/gdamore/tcell/v2" +) + +type List struct { + All bool `opt:"-a"` +} + +func init() { + register(List{}) +} + +func (List) Aliases() []string { + return []string{"list", "ls"} +} + +func (l List) Execute(args []string) error { + m := pama.New() + current, err := m.CurrentProject() + if err != nil { + return err + } + + projects := []models.Project{current} + if l.All { + projects, err = m.Projects("") + if err != nil { + return err + } + } + + app.PushStatus(fmt.Sprintf("Current project: %s", current.Name), 30*time.Second) + + createWidget := func(r io.Reader) (ui.DrawableInteractive, error) { + pagerCmd, err := app.CmdFallbackSearch(config.PagerCmds(), true) + if err != nil { + return nil, err + } + + cmd := opt.SplitArgs(pagerCmd) + pager := exec.Command(cmd[0], cmd[1:]...) + pager.Stdin = r + + term, err := app.NewTerminal(pager) + if err != nil { + return nil, err + } + start := time.Now() + term.OnClose = func(err error) { + if time.Since(start) > 250*time.Millisecond { + app.CloseDialog() + return + } + term.OnEvent = func(_ tcell.Event) bool { + app.CloseDialog() + return true + } + } + return term, nil + } + + viewer, err := createWidget(m.NewReader(projects)) + if err != nil { + viewer = app.NewListBox( + "Press <Esc> or <Enter> to close. "+ + "Start typing to filter.", + numerify(m.NewReader(projects)), app.SelectedAccountUiConfig(), + func(_ string) { app.CloseDialog() }, + ) + } + + app.AddDialog(app.NewDialog( + ui.NewBox(viewer, "Patch Management", "", + app.SelectedAccountUiConfig(), + ), + // start pos on screen + func(h int) int { + return h / 8 + }, + // dialog height + func(h int) int { + return h - 2*h/8 + }, + )) + + return nil +} + +func numerify(r io.Reader) []string { + var lines []string + nr := 1 + scanner := bufio.NewScanner(r) + for scanner.Scan() { + s := scanner.Text() + lines = append(lines, fmt.Sprintf("%3d %s", nr, s)) + nr++ + } + return lines +} diff --git a/config/cmds.go b/config/cmds.go new file mode 100644 index 00000000..16208914 --- /dev/null +++ b/config/cmds.go @@ -0,0 +1,22 @@ +package config + +import ( + "os" +) + +func EditorCmds() []string { + return []string{ + Compose.Editor, + os.Getenv("EDITOR"), + "vi", + "nano", + } +} + +func PagerCmds() []string { + return []string{ + Viewer.Pager, + os.Getenv("PAGER"), + "less -Rc", + } +} diff --git a/lib/pama/list.go b/lib/pama/list.go new file mode 100644 index 00000000..950f130d --- /dev/null +++ b/lib/pama/list.go @@ -0,0 +1,59 @@ +package pama + +import ( + "errors" + "io" + "strings" + + "git.sr.ht/~rjarry/aerc/lib/pama/models" + "git.sr.ht/~rjarry/aerc/log" +) + +func (m PatchManager) Projects(name string) ([]models.Project, error) { + all, err := m.store().Projects() + if err != nil { + return nil, storeErr(err) + } + if len(name) == 0 { + return all, nil + } + var projects []models.Project + for _, p := range all { + if strings.Contains(p.Name, name) { + projects = append(projects, p) + } + } + if len(projects) == 0 { + return nil, errors.New("No projects found.") + } + return projects, nil +} + +func (m PatchManager) NewReader(projects []models.Project) io.Reader { + cur, err := m.CurrentProject() + currentName := cur.Name + if err != nil { + log.Warnf("could not get current project: %v", err) + currentName = "" + } + + readers := make([]io.Reader, 0, len(projects)) + for _, p := range projects { + rc, err := m.rc(p.RevctrlID, p.Root) + if err != nil { + log.Errorf("project '%s' failed with: %v", p.Name, err) + continue + } + + notes := make(map[string]string) + for _, c := range p.Commits { + if !rc.Exists(c.ID) { + notes[c.ID] = "Rebase needed" + } + } + + active := p.Name == currentName && len(projects) > 1 + readers = append(readers, p.NewReader(active, notes)) + } + return io.MultiReader(readers...) +} |