diff options
author | Robin Jarry <robin@jarry.cc> | 2023-02-03 13:14:35 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-02-20 14:48:42 +0100 |
commit | 6cfbc87d8ab0be8d264d81b0b1f26e7b96719dfc (patch) | |
tree | c09b6b671bd90504ce0e90512b39b31f650f37fb /widgets | |
parent | d74400ac07a9f149e89fdf2b7232ffc6871f8553 (diff) | |
download | aerc-6cfbc87d8ab0be8d264d81b0b1f26e7b96719dfc.tar.gz |
dirlist: use templates instead of % mini language
Replace dirlist-format with two settings: dirlist-left & dirlist-right.
These two settings take aerc-templates(7) and may be left empty.
Add automatic translation of dirlist-format to these new settings.
Display a warning on startup if dirlist-format has been converted.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/dirlist.go | 175 | ||||
-rw-r--r-- | widgets/dirtree.go | 55 |
2 files changed, 107 insertions, 123 deletions
diff --git a/widgets/dirlist.go b/widgets/dirlist.go index 93db0763..1e1a8a61 100644 --- a/widgets/dirlist.go +++ b/widgets/dirlist.go @@ -1,13 +1,12 @@ package widgets import ( + "bytes" "context" - "fmt" "math" "os" "regexp" "sort" - "strings" "time" "github.com/gdamore/tcell/v2" @@ -16,6 +15,8 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/format" + "git.sr.ht/~rjarry/aerc/lib/state" + "git.sr.ht/~rjarry/aerc/lib/templates" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" @@ -184,70 +185,6 @@ func (dirlist *DirectoryList) Invalidate() { ui.Invalidate() } -func (dirlist *DirectoryList) getDirString(name string, width int, recentUnseen func() string) string { - percent := false - rightJustify := false - formatted := "" - doRightJustify := func(s string) { - formatted = runewidth.FillRight(formatted, width-len(s)) - formatted = runewidth.Truncate(formatted, width-len(s), "…") - } - for _, char := range dirlist.UiConfig(name).DirListFormat { - switch char { - case '%': - if percent { - formatted += string(char) - percent = false - } else { - percent = true - } - case '>': - if percent { - rightJustify = true - } - case 'N': - name = format.CompactPath(name, os.PathSeparator) - fallthrough - case 'n': - if percent { - if rightJustify { - doRightJustify(name) - rightJustify = false - } - formatted += name - percent = false - } - case 'r': - if percent { - rString := recentUnseen() - if rightJustify { - doRightJustify(rString) - rightJustify = false - } - formatted += rString - percent = false - } - default: - formatted += string(char) - } - } - return formatted -} - -func (dirlist *DirectoryList) getRUEString(name string) string { - r, u, e := dirlist.GetRUECount(name) - rueString := "" - switch { - case r > 0: - rueString = fmt.Sprintf("%d/%d/%d", r, u, e) - case u > 0: - rueString = fmt.Sprintf("%d/%d", u, e) - case e > 0: - rueString = fmt.Sprintf("%d", e) - } - return rueString -} - // Returns the Recent, Unread, and Exist counts for the named directory func (dirlist *DirectoryList) GetRUECount(name string) (int, int, int) { msgStore, ok := dirlist.MsgStore(name) @@ -262,8 +199,9 @@ func (dirlist *DirectoryList) GetRUECount(name string) (int, int, int) { } func (dirlist *DirectoryList) Draw(ctx *ui.Context) { + uiConfig := dirlist.UiConfig("") ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', - dirlist.UiConfig("").GetStyle(config.STYLE_DIRLIST_DEFAULT)) + uiConfig.GetStyle(config.STYLE_DIRLIST_DEFAULT)) if dirlist.spinner.IsRunning() { dirlist.spinner.Draw(ctx) @@ -271,8 +209,8 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) { } if len(dirlist.dirs) == 0 { - style := dirlist.UiConfig("").GetStyle(config.STYLE_DIRLIST_DEFAULT) - ctx.Printf(0, 0, style, dirlist.UiConfig("").EmptyDirlist) + style := uiConfig.GetStyle(config.STYLE_DIRLIST_DEFAULT) + ctx.Printf(0, 0, style, uiConfig.EmptyDirlist) return } @@ -284,9 +222,14 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) { textWidth -= 1 } if textWidth < 0 { - textWidth = 0 + return } + listCtx := ctx.Subcontext(0, 0, textWidth, ctx.Height()) + var data state.TemplateData + + data.SetAccount(dirlist.acctConf) + for i, name := range dirlist.dirs { if i < dirlist.Scroll() { continue @@ -296,27 +239,13 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) { break } - dirStyle := []config.StyleObject{} - s := dirlist.getRUEString(name) - switch strings.Count(s, "/") { - case 1: - dirStyle = append(dirStyle, config.STYLE_DIRLIST_UNREAD) - case 2: - dirStyle = append(dirStyle, config.STYLE_DIRLIST_RECENT) - } - style := dirlist.UiConfig(name).GetComposedStyle( - config.STYLE_DIRLIST_DEFAULT, dirStyle) - if name == dirlist.selecting { - style = dirlist.UiConfig(name).GetComposedStyleSelected( - config.STYLE_DIRLIST_DEFAULT, dirStyle) - } - ctx.Fill(0, row, textWidth, 1, ' ', style) - - dirString := dirlist.getDirString(name, textWidth, func() string { - return s - }) - - ctx.Printf(0, row, style, dirString) + data.SetFolder(name) + data.SetRUE([]string{name}, dirlist.GetRUECount) + left, right, style := dirlist.renderDir( + name, uiConfig, &data, + name == dirlist.selecting, listCtx.Width(), + ) + listCtx.Printf(0, row, style, "%s %s", left, right) } if dirlist.NeedScrollbar() { @@ -325,6 +254,70 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) { } } +func (dirlist *DirectoryList) renderDir( + path string, conf *config.UIConfig, data *state.TemplateData, + selected bool, width int, +) (string, string, tcell.Style) { + var left, right string + var buf bytes.Buffer + + var styles []config.StyleObject + var style tcell.Style + + r, u, _ := dirlist.GetRUECount(path) + switch { + case r > 0: + styles = append(styles, config.STYLE_DIRLIST_RECENT) + case u > 0: + styles = append(styles, config.STYLE_DIRLIST_UNREAD) + } + conf = conf.ForFolder(path) + if selected { + style = conf.GetComposedStyleSelected( + config.STYLE_DIRLIST_DEFAULT, styles) + } else { + style = conf.GetComposedStyle( + config.STYLE_DIRLIST_DEFAULT, styles) + } + + err := templates.Render(conf.DirListLeft, &buf, data) + if err != nil { + log.Errorf("dirlist-left: %s", err) + left = err.Error() + style = conf.GetStyle(config.STYLE_ERROR) + } else { + left = buf.String() + } + buf.Reset() + err = templates.Render(conf.DirListRight, &buf, data) + if err != nil { + log.Errorf("dirlist-right: %s", err) + right = err.Error() + style = conf.GetStyle(config.STYLE_ERROR) + } else { + right = buf.String() + } + buf.Reset() + + lwidth := runewidth.StringWidth(left) + rwidth := runewidth.StringWidth(right) + + if lwidth+rwidth+1 > width { + if rwidth > 3*width/4 { + rwidth = 3 * width / 4 + } + lwidth = width - rwidth - 1 + right = runewidth.FillLeft(right, rwidth) + right = format.TruncateHead(right, rwidth, "…") + left = runewidth.FillRight(left, lwidth) + left = runewidth.Truncate(left, lwidth, "…") + } else { + left = runewidth.FillRight(left, width-rwidth-1) + } + + return left, right, style +} + func (dirlist *DirectoryList) drawScrollbar(ctx *ui.Context) { gutterStyle := tcell.StyleDefault pillStyle := tcell.StyleDefault.Reverse(true) diff --git a/widgets/dirtree.go b/widgets/dirtree.go index e9fbf061..0c7f090a 100644 --- a/widgets/dirtree.go +++ b/widgets/dirtree.go @@ -8,6 +8,7 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" + "git.sr.ht/~rjarry/aerc/lib/state" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/worker/types" @@ -51,8 +52,9 @@ func (dt *DirectoryTree) UpdateList(done func([]string)) { } func (dt *DirectoryTree) Draw(ctx *ui.Context) { + uiConfig := dt.UiConfig("") ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', - dt.UiConfig("").GetStyle(config.STYLE_DIRLIST_DEFAULT)) + uiConfig.GetStyle(config.STYLE_DIRLIST_DEFAULT)) if dt.DirectoryList.spinner.IsRunning() { dt.DirectoryList.spinner.Draw(ctx) @@ -61,8 +63,8 @@ func (dt *DirectoryTree) Draw(ctx *ui.Context) { n := dt.countVisible(dt.list) if n == 0 || dt.listIdx < 0 { - style := dt.UiConfig("").GetStyle(config.STYLE_DIRLIST_DEFAULT) - ctx.Printf(0, 0, style, dt.UiConfig("").EmptyDirlist) + style := uiConfig.GetStyle(config.STYLE_DIRLIST_DEFAULT) + ctx.Printf(0, 0, style, uiConfig.EmptyDirlist) return } @@ -80,46 +82,35 @@ func (dt *DirectoryTree) Draw(ctx *ui.Context) { textWidth -= 1 } if textWidth < 0 { - textWidth = 0 + return } + treeCtx := ctx.Subcontext(0, 0, textWidth, ctx.Height()) + var data state.TemplateData + + data.SetAccount(dt.acctConf) + + n = 0 for i, node := range dt.list { + if n > treeCtx.Height() { + break + } rowNr := dt.countVisible(dt.list[:i]) if rowNr < dt.Scroll() || !isVisible(node) { continue } - row := rowNr - dt.Scroll() - if row >= ctx.Height() { - break - } - name := dt.displayText(node) - - dirStyle := []config.StyleObject{} path := dt.getDirectory(node) - s := dt.getRUEString(path) - switch strings.Count(s, "/") { - case 1: - dirStyle = append(dirStyle, config.STYLE_DIRLIST_UNREAD) - case 2: - dirStyle = append(dirStyle, config.STYLE_DIRLIST_RECENT) - } - style := dt.UiConfig(path).GetComposedStyle( - config.STYLE_DIRLIST_DEFAULT, dirStyle) - if i == dt.listIdx { - style = dt.UiConfig(path).GetComposedStyleSelected( - config.STYLE_DIRLIST_DEFAULT, dirStyle) - } - ctx.Fill(0, row, textWidth, 1, ' ', style) + data.SetFolder(dt.displayText(node)) + data.SetRUE([]string{path}, dt.GetRUECount) - dirString := dt.getDirString(name, textWidth, func() string { - if path != "" { - return s - } - return "" - }) + left, right, style := dt.renderDir( + path, uiConfig, &data, + i == dt.listIdx, treeCtx.Width(), + ) - ctx.Printf(0, row, style, dirString) + treeCtx.Printf(0, n, style, "%s %s", left, right) + n++ } if dt.NeedScrollbar() { |