diff options
author | Robin Jarry <robin@jarry.cc> | 2022-12-27 22:59:10 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-02-20 14:48:42 +0100 |
commit | d2e74cdb91e140b50d14c3a8b315cde272f32587 (patch) | |
tree | 4f4a20c02f60b67d7a8eb967bb45d789a057453b /config | |
parent | 6af06c9dfec03e923589d34187ba8358e3423d5c (diff) | |
download | aerc-d2e74cdb91e140b50d14c3a8b315cde272f32587.tar.gz |
statusline: add column based render format
In the spirit of commit 535300cfdbfc ("config: add columns based index
format"), reuse the column definitions and table widget.
Add automatic translation of render-format to column definitions. Allow
empty columns to be compatible with the %m (mute) flag.
Rename the State object to AccountState to be more precise. Reuse that
object in state.TempateData to expose account state info. Move actual
status line rendering in StatusLine.Draw().
Add new template fields for status specific data:
{{.ConnectionInfo}}
Connection state.
{{.ContentInfo}}
General status information (e.g. filter, search)
{{.StatusInfo}}
Combination of {{.ConnectionInfo}} and {{.StatusInfo}}
{{.TrayInfo}}
General on/off information (e.g. passthrough, threading,
sorting)
{{.PendingKeys}}
Currently pressed key sequence that does not match any key
binding and/or is incomplete.
Display a warning on startup if render-format has been converted to
status-columns.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Diffstat (limited to 'config')
-rw-r--r-- | config/aerc.conf | 26 | ||||
-rw-r--r-- | config/columns.go | 15 | ||||
-rw-r--r-- | config/statusline.go | 138 | ||||
-rw-r--r-- | config/templates.go | 6 | ||||
-rw-r--r-- | config/ui.go | 2 |
5 files changed, 177 insertions, 10 deletions
diff --git a/config/aerc.conf b/config/aerc.conf index 43d17727..38049b77 100644 --- a/config/aerc.conf +++ b/config/aerc.conf @@ -279,10 +279,30 @@ #client-threads-delay=50ms [statusline] -# Describes the format string for the statusline. # -# Default: [%a] %S %>%T -#render-format=[%a] %S %>%T +# Describes the format for the status line. This is a comma separated list of +# column names with an optional align and width suffix. See [ui].index-columns +# for more details. To completely mute the status line except for push +# notifications, explicitly set status-columns to an empty string. +# +# Default: left<*,center:=,right>* +#status-columns=left<*,center:=,right>* + +# +# Each name in status-columns must have a corresponding column-$name setting. +# All column-$name settings accept golang text/template syntax. See +# aerc-templates(7) for available template attributes and functions. +# +# Default settings +#column-left=[{{.Account}}] {{.StatusInfo}} +#column-center={{.PendingKeys}} +#column-right={{.TrayInfo}} + +# +# String separator inserted between columns. +# See [ui].column-separator for more details. +# +#column-separator=" " # Specifies the separator between grouped statusline elements. # diff --git a/config/columns.go b/config/columns.go index 55efa2a7..e1389bc0 100644 --- a/config/columns.go +++ b/config/columns.go @@ -2,6 +2,7 @@ package config import ( "bytes" + "crypto/sha256" "fmt" "reflect" "regexp" @@ -113,7 +114,7 @@ func ParseColumnDefs(key *ini.Key, section *ini.Section) ([]*ColumnDef, error) { columns = append(columns, c) } if len(columns) == 0 { - return nil, fmt.Errorf("%s cannot be empty", key.Name()) + return nil, nil } return columns, nil } @@ -156,3 +157,15 @@ func ColumnDefsToIni(defs []*ColumnDef, keyName string) string { return s.String() } + +var templateFieldNameRe = regexp.MustCompile(`\{\{\.?(\w+)\}\}`) + +func columnNameFromTemplate(s string) string { + match := templateFieldNameRe.FindStringSubmatch(s) + if match == nil { + h := sha256.New() + h.Write([]byte(s)) + return fmt.Sprintf("%x", h.Sum(nil)[:3]) + } + return strings.ReplaceAll(strings.ToLower(match[1]), "info", "") +} diff --git a/config/statusline.go b/config/statusline.go index 483241c0..7cc2140c 100644 --- a/config/statusline.go +++ b/config/statusline.go @@ -1,21 +1,50 @@ package config import ( + "regexp" + "strings" + + "git.sr.ht/~rjarry/aerc/lib/templates" "git.sr.ht/~rjarry/aerc/log" "github.com/go-ini/ini" ) type StatuslineConfig struct { + StatusColumns []*ColumnDef `ini:"-"` + ColumnSeparator string `ini:"column-separator"` + Separator string `ini:"separator"` + DisplayMode string `ini:"display-mode"` + // deprecated RenderFormat string `ini:"render-format"` - Separator string - DisplayMode string `ini:"display-mode"` } func defaultStatuslineConfig() *StatuslineConfig { + left, _ := templates.ParseTemplate("column-left", `[{{.Account}}] {{.StatusInfo}}`) + center, _ := templates.ParseTemplate("column-center", `{{.PendingKeys}}`) + right, _ := templates.ParseTemplate("column-right", `{{.TrayInfo}}`) return &StatuslineConfig{ - RenderFormat: "[%a] %S %>%T", - Separator: " | ", - DisplayMode: "", + StatusColumns: []*ColumnDef{ + { + Name: "left", + Template: left, + Flags: ALIGN_LEFT | WIDTH_AUTO, + }, + { + Name: "center", + Template: center, + Flags: ALIGN_CENTER | WIDTH_FIT, + }, + { + Name: "right", + Template: right, + Flags: ALIGN_RIGHT | WIDTH_AUTO, + }, + }, + ColumnSeparator: " ", + Separator: " | ", + DisplayMode: "text", + // deprecated + RenderFormat: "", } } @@ -29,7 +58,106 @@ func parseStatusline(file *ini.File) error { if err := statusline.MapTo(&Statusline); err != nil { return err } + + if key, err := statusline.GetKey("status-columns"); err == nil { + columns, err := ParseColumnDefs(key, statusline) + if err != nil { + return err + } + Statusline.StatusColumns = columns + } else if Statusline.RenderFormat != "" { + columns, err := convertRenderFormat() + if err != nil { + return err + } + Statusline.StatusColumns = columns + log.Warnf("%s %s", + "The [statusline] render-format setting has been replaced by status-columns.", + "render-format will be removed in aerc 0.17.") + Warnings = append(Warnings, Warning{ + Title: "DEPRECATION WARNING: [statusline].render-format", + Body: ` +The render-format setting is deprecated. It has been replaced by status-columns. + +Your configuration in this instance was automatically converted to: + +[statusline] +` + ColumnDefsToIni(columns, "status-columns") + ` +Your configuration file was not changed. To make this change permanent and to +dismiss this deprecation warning on launch, copy the above lines into aerc.conf +and remove index-format from it. See aerc-config(5) for more details. + +index-format will be removed in aerc 0.17. +`, + }) + } + out: log.Debugf("aerc.conf: [statusline] %#v", Statusline) return nil } + +var ( + renderFmtRe = regexp.MustCompile(`%(-?\d+)?(\.\d+)?[acdmSTp]`) + statuslineMute = false +) + +func convertRenderFormat() ([]*ColumnDef, error) { + var columns []*ColumnDef + + tokens := strings.Split(Statusline.RenderFormat, "%>") + + left := renderFmtRe.ReplaceAllStringFunc( + tokens[0], renderVerbToTemplate) + left = strings.TrimSpace(left) + t, err := templates.ParseTemplate("column-left", left) + if err != nil { + return nil, err + } + columns = append(columns, &ColumnDef{ + Name: "left", + Template: t, + Flags: ALIGN_LEFT | WIDTH_AUTO, + }) + + if len(tokens) == 2 { + right := renderFmtRe.ReplaceAllStringFunc( + tokens[1], renderVerbToTemplate) + right = strings.TrimSpace(right) + t, err := templates.ParseTemplate("column-right", right) + if err != nil { + return nil, err + } + columns = append(columns, &ColumnDef{ + Name: "right", + Template: t, + Flags: ALIGN_RIGHT | WIDTH_AUTO, + }) + } + + if statuslineMute { + columns = nil + } + + return columns, nil +} + +func renderVerbToTemplate(verb string) (template string) { + switch verb[len(verb)-1] { + case 'a': + template = `{{.Account}}` + case 'c': + template = `{{.ConnectionInfo}}` + case 'd': + template = `{{.Folder}}` + case 'S': + template = `{{.StatusInfo}}` + case 'T': + template = `{{.TrayInfo}}` + case 'p': + template = `{{cwd}}` + case 'm': + statuslineMute = true + } + return template +} diff --git a/config/templates.go b/config/templates.go index 3fce9857..0f3870c5 100644 --- a/config/templates.go +++ b/config/templates.go @@ -104,3 +104,9 @@ func (d *dummyData) OriginalHeader(string) string { return "" } func (d *dummyData) Recent(...string) int { return 1 } func (d *dummyData) Unread(...string) int { return 3 } func (d *dummyData) Exists(...string) int { return 14 } +func (d *dummyData) Connected() bool { return false } +func (d *dummyData) ConnectionInfo() string { return "" } +func (d *dummyData) ContentInfo() string { return "" } +func (d *dummyData) StatusInfo() string { return "" } +func (d *dummyData) TrayInfo() string { return "" } +func (d *dummyData) PendingKeys() string { return "" } diff --git a/config/ui.go b/config/ui.go index b59c9b09..d4b36f34 100644 --- a/config/ui.go +++ b/config/ui.go @@ -494,7 +494,7 @@ func indexVerbToTemplate(verb rune) (f, name string) { f = "%" + string(verb) } if name == "" { - name = "wtf" + name = columnNameFromTemplate(f) } return } |