aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2023-02-03 13:14:35 +0100
committerRobin Jarry <robin@jarry.cc>2023-02-20 14:48:42 +0100
commit6cfbc87d8ab0be8d264d81b0b1f26e7b96719dfc (patch)
treec09b6b671bd90504ce0e90512b39b31f650f37fb /widgets
parentd74400ac07a9f149e89fdf2b7232ffc6871f8553 (diff)
downloadaerc-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.go175
-rw-r--r--widgets/dirtree.go55
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() {