diff options
author | Robin Jarry <robin@jarry.cc> | 2023-09-11 17:34:51 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-09-19 16:49:59 +0200 |
commit | de0b75d191f4f789d3870dae00871244d20aaf10 (patch) | |
tree | 8604ebfd38f0903df7a951471743cfd07dccd21d | |
parent | 20e425406541e3fc7c4decad3da9373d378c7164 (diff) | |
download | aerc-de0b75d191f4f789d3870dae00871244d20aaf10.tar.gz aerc-de0b75d191f4f789d3870dae00871244d20aaf10.zip |
msgviewer: add styles for part selector
Allow styling the part selector mime type and (if any) attachment
filename. Remove custom alignment code since now both can be
differentiated easily with colors and/or attributes.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Inwit <inwit@sindominio.net>
-rw-r--r-- | config/style.go | 19 | ||||
-rw-r--r-- | doc/aerc-stylesets.7.scd | 9 | ||||
-rw-r--r-- | stylesets/blue | 6 | ||||
-rw-r--r-- | stylesets/default | 3 | ||||
-rw-r--r-- | stylesets/dracula | 6 | ||||
-rw-r--r-- | stylesets/nord | 5 | ||||
-rw-r--r-- | stylesets/pink | 6 | ||||
-rw-r--r-- | stylesets/solarized | 2 | ||||
-rw-r--r-- | widgets/msgviewer.go | 52 | ||||
-rw-r--r-- | widgets/msgviewer_test.go | 68 |
10 files changed, 75 insertions, 101 deletions
diff --git a/config/style.go b/config/style.go index f50126bd..3f117fc0 100644 --- a/config/style.go +++ b/config/style.go @@ -46,6 +46,10 @@ const ( STYLE_DIRLIST_UNREAD STYLE_DIRLIST_RECENT + STYLE_PART_SWITCHER + STYLE_PART_FILENAME + STYLE_PART_MIMETYPE + STYLE_COMPLETION_DEFAULT STYLE_COMPLETION_GUTTER STYLE_COMPLETION_PILL @@ -91,6 +95,10 @@ var StyleNames = map[string]StyleObject{ "dirlist_unread": STYLE_DIRLIST_UNREAD, "dirlist_recent": STYLE_DIRLIST_RECENT, + "part_switcher": STYLE_PART_SWITCHER, + "part_filename": STYLE_PART_FILENAME, + "part_mimetype": STYLE_PART_MIMETYPE, + "completion_default": STYLE_COMPLETION_DEFAULT, "completion_gutter": STYLE_COMPLETION_GUTTER, "completion_pill": STYLE_COMPLETION_PILL, @@ -330,6 +338,9 @@ func NewStyleSet() StyleSet { case STYLE_MSGLIST_PILL: // msglist_pill.reverse=true conf.base.Reverse = true + case STYLE_PART_MIMETYPE: + // part_mimetype.dim=true + conf.base.Dim = true case STYLE_COMPLETION_PILL: // completion_pill.reverse=true conf.base.Reverse = true @@ -351,6 +362,14 @@ func NewStyleSet() StyleSet { selected := *conf // *.selected.reverse=toggle selected.base.Reverse = !conf.base.Reverse + switch so { + case STYLE_PART_MIMETYPE: + // part_mimetype.selected.dim=false + selected.base.Dim = false + case STYLE_PART_FILENAME: + // part_filename.selected.bold=true + selected.base.Bold = true + } ss.selected[so] = &selected } return ss diff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd index 3050eab7..1a505233 100644 --- a/doc/aerc-stylesets.7.scd +++ b/doc/aerc-stylesets.7.scd @@ -119,6 +119,12 @@ styling. : The style used for directories with unread messages | *dirlist_recent* : The style used for directories with recent messages +| *part_switcher* +: Background for the part switcher in the message viewer. +| *part_filename* +: Attachment file name in the part switcher. +| *part_mimetype* +: Attachment/part MIME type in the part switcher. | *completion_default* : The default style for the completion engine. | *completion_gutter* @@ -356,6 +362,9 @@ msglist_unread.bold=true msglist_deleted.fg=gray msglist_result.fg=green msglist_pill.reverse=true +part_mimetype.dim=true +part_mimetype.selected.dim=false +part_filename.selected.bold=true completion_pill.reverse=true tab.reverse=true border.reverse = true diff --git a/stylesets/blue b/stylesets/blue index 46e04b46..4ffcbc87 100644 --- a/stylesets/blue +++ b/stylesets/blue @@ -37,6 +37,12 @@ msglist_marked.bg=#005f87 msglist_marked.selected.bg=#005fff msglist_pill.reverse=true +part_*.fg=#ffffff +part_mimetype.fg=#005f87 +part_*.selected.fg=#ffffff +part_*.selected.bg=#005f87 +part_filename.selected.bold=true + completion_pill.reverse=true selector_focused.bold=true selector_focused.bg=#005f87 diff --git a/stylesets/default b/stylesets/default index c0d6f909..74bbe97a 100644 --- a/stylesets/default +++ b/stylesets/default @@ -32,6 +32,9 @@ #msglist_result.fg=green #msglist_pill.reverse=true +#part_mimetype.dim=true +#part_mimetype.selected.dim=false +#part_filename.selected.bold=true #completion_pill.reverse=true #tab.reverse=true diff --git a/stylesets/dracula b/stylesets/dracula index 8b8788e9..73623547 100644 --- a/stylesets/dracula +++ b/stylesets/dracula @@ -37,6 +37,12 @@ msglist_marked.bg=#BD93F9 msglist_marked.selected.bg=#9956f5 msglist_pill.reverse=true +part_*.fg=#ffffff +part_mimetype.fg=#44475A +part_*.selected.fg=#ffffff +part_*.selected.bg=#44475A +part_filename.selected.bold=true + completion_pill.reverse=false selector_focused.bold=false selector_focused.bg=#44475A diff --git a/stylesets/nord b/stylesets/nord index e9c7e853..a1fdf882 100644 --- a/stylesets/nord +++ b/stylesets/nord @@ -48,6 +48,11 @@ tab.selected.fg=#2c3441 dirlist_unread.fg=#64A6B3 dirlist_recent.fg=#64A6B3 +part_*.fg=#ffffff +part_mimetype.fg=#394353 +part_*.selected.fg=#ffffff +part_filename.selected.bold=true + [viewer] url.underline=true header.bold=true diff --git a/stylesets/pink b/stylesets/pink index 9fd8c213..deaae5ac 100644 --- a/stylesets/pink +++ b/stylesets/pink @@ -37,6 +37,12 @@ msglist_marked.bg=#de4e85 msglist_marked.selected.bg=#c93687 msglist_pill.reverse=true +part_*.fg=#ffffff +part_mimetype.fg=#de4e85 +part_*.selected.fg=#ffffff +part_*.selected.bg=#de4e85 +part_filename.selected.bold=true + completion_pill.reverse=true selector_focused.bold=true selector_focused.bg=#de4e85 diff --git a/stylesets/solarized b/stylesets/solarized index dcd8606f..9874e2d8 100644 --- a/stylesets/solarized +++ b/stylesets/solarized @@ -33,6 +33,8 @@ tab.bg=#eee8d5 tab.fg=#586e75 tab.selected.bg=#b58900 tab.selected.fg=#002b36 +part_mimetype.fg=#b58900 +part_filename.selected.bold=true [viewer] diff_add.fg=#859900 # green diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index c94d57a3..41cb639e 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -422,18 +422,32 @@ func (ps *PartSwitcher) Draw(ctx *ui.Context) { ps.parts[ps.selected].Draw(ctx) return } + + var styleSwitcher, styleFile, styleMime tcell.Style + // TODO: cap height and add scrolling for messages with many parts ps.height = ctx.Height() y := ctx.Height() - height for i, part := range ps.parts { - style := ps.mv.uiConfig.GetStyle(config.STYLE_DEFAULT) if ps.selected == i { - style = ps.mv.uiConfig.GetStyleSelected(config.STYLE_DEFAULT) + styleSwitcher = ps.mv.uiConfig.GetStyleSelected(config.STYLE_PART_SWITCHER) + styleFile = ps.mv.uiConfig.GetStyleSelected(config.STYLE_PART_FILENAME) + styleMime = ps.mv.uiConfig.GetStyleSelected(config.STYLE_PART_MIMETYPE) + } else { + styleSwitcher = ps.mv.uiConfig.GetStyle(config.STYLE_PART_SWITCHER) + styleFile = ps.mv.uiConfig.GetStyle(config.STYLE_PART_FILENAME) + styleMime = ps.mv.uiConfig.GetStyle(config.STYLE_PART_MIMETYPE) } - ctx.Fill(0, y+i, ctx.Width(), 1, ' ', style) + ctx.Fill(0, y+i, ctx.Width(), 1, ' ', styleSwitcher) left := len(part.index) * 2 - name := formatMessagePart(part.part.FullMIMEType(), part.part.FileName(), ctx.Width()-left) - ctx.Printf(left, y+i, style, "%s", name) + if part.part.FileName() != "" { + name := runewidth.Truncate(part.part.FileName(), + ctx.Width()-left-1, "…") + left += ctx.Printf(left, y+i, styleFile, "%s ", name) + } + t := "(" + part.part.FullMIMEType() + ")" + t = runewidth.Truncate(t, ctx.Width()-left, "…") + ctx.Printf(left, y+i, styleMime, "%s", t) } ps.parts[ps.selected].Draw(ctx.Subcontext( 0, 0, ctx.Width(), ctx.Height()-height)) @@ -500,34 +514,6 @@ func (ps *PartSwitcher) Cleanup() { } } -func formatMessagePart(mime, filename string, width int) string { - lname := runewidth.StringWidth(filename) - lmime := runewidth.StringWidth(mime) - - switch { - case width <= 0: - return "" - - case filename == "": - return runewidth.Truncate(mime, width, "…") - - case lname+lmime+3 <= width: - // simple scenario - everything fits - return fmt.Sprintf("%s (%s)", - runewidth.FillRight(filename, width-lmime-3), mime) - - case lname+3 < width: - // file name fits + we have space for parentheses and at least - // one symbol of mime - return fmt.Sprintf("%s (%s)", filename, - runewidth.Truncate(mime, width-lname-3, "…")) - - default: - // ok, we don't have space even for the file name - return runewidth.Truncate(filename, width, "…") - } -} - func (mv *MessageViewer) Event(event tcell.Event) bool { return mv.switcher.Event(event) } diff --git a/widgets/msgviewer_test.go b/widgets/msgviewer_test.go deleted file mode 100644 index f6d01edb..00000000 --- a/widgets/msgviewer_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package widgets - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFormatMessageNoFilename(t *testing.T) { - assert.Equal(t, "mime/type", formatMessagePart("mime/type", "", 24)) - assert.Equal(t, "m/type", formatMessagePart("m/type", "", 24)) - assert.Equal(t, "2", formatMessagePart("2", "", 24)) - assert.Equal(t, "2", formatMessagePart("2", "", 20)) -} - -func TestFormatMessageNoFilenameNotEnoguhSpace(t *testing.T) { - assert.Equal(t, "mime/type", formatMessagePart("mime/type", "", 24)) - assert.Equal(t, "mime/type", formatMessagePart("mime/type", "", 9)) - assert.Equal(t, "mime/ty…", formatMessagePart("mime/type", "", 8)) - assert.Equal(t, "mime/…", formatMessagePart("mime/type", "", 6)) - assert.Equal(t, "m…", formatMessagePart("mime/type", "", 2)) - assert.Equal(t, "…", formatMessagePart("mime/type", "", 1)) - - assert.Equal(t, "", formatMessagePart("mime/type", "", 0)) - assert.Equal(t, "", formatMessagePart("mime/type", "", -1)) - assert.Equal(t, "", formatMessagePart("mime/type", "", -10)) -} - -func TestFormatMessagePartSimpleCases(t *testing.T) { - assert.Equal(t, "filename.doc (mime/type)", formatMessagePart("mime/type", "filename.doc", 24)) - assert.Equal(t, "имяфайла.док (mime/type)", formatMessagePart("mime/type", "имяфайла.док", 24)) - assert.Equal(t, "file.doc (m/type)", formatMessagePart("m/type", "file.doc", 24)) - assert.Equal(t, "1 (2)", formatMessagePart("2", "1", 24)) - assert.Equal(t, "1 (2)", formatMessagePart("2", "1", 20)) - assert.Equal(t, "1 (2)", formatMessagePart("2", "1", 5)) -} - -func TestFormatMessagePartNotEnoughSpaceForMime(t *testing.T) { - assert.Equal(t, "filename.doc (mime/type)", formatMessagePart("mime/type", "filename.doc", 30)) - assert.Equal(t, "filename.doc (mime/type)", formatMessagePart("mime/type", "filename.doc", 25)) - assert.Equal(t, "filename.doc (mime/type)", formatMessagePart("mime/type", "filename.doc", 24)) - assert.Equal(t, "filename.doc (mime/ty…)", formatMessagePart("mime/type", "filename.doc", 23)) - assert.Equal(t, "имяфайла.док (mime/ty…)", formatMessagePart("mime/type", "имяфайла.док", 23)) - assert.Equal(t, "filename.doc (m…)", formatMessagePart("mime/type", "filename.doc", 17)) - assert.Equal(t, "filename.doc (…)", formatMessagePart("mime/type", "filename.doc", 16)) - assert.Equal(t, "имяфайла.док (…)", formatMessagePart("mime/type", "имяфайла.док", 16)) - assert.Equal(t, "filename.doc", formatMessagePart("mime/type", "filename.doc", 15)) - assert.Equal(t, "filename.doc", formatMessagePart("mime/type", "filename.doc", 14)) - assert.Equal(t, "filename.doc", formatMessagePart("mime/type", "filename.doc", 13)) - assert.Equal(t, "filename.doc", formatMessagePart("mime/type", "filename.doc", 12)) - assert.Equal(t, "имяфайла.док", formatMessagePart("mime/type", "имяфайла.док", 12)) -} - -func TestFormatMessagePartNotEnoughSpaceForFilename(t *testing.T) { - assert.Equal(t, "filename.d…", formatMessagePart("mime/type", "filename.doc", 11)) - assert.Equal(t, "filename…", formatMessagePart("mime/type", "filename.doc", 9)) - assert.Equal(t, "f…", formatMessagePart("mime/type", "filename.doc", 2)) - assert.Equal(t, "…", formatMessagePart("mime/type", "filename.doc", 1)) - - assert.Equal(t, "", formatMessagePart("mime/type", "filename.doc", 0)) - assert.Equal(t, "", formatMessagePart("mime/type", "filename.doc", -1)) - assert.Equal(t, "", formatMessagePart("mime/type", "filename.doc", -10)) - - assert.Equal(t, "имяфайла.д…", formatMessagePart("mime/type", "имяфайла.док", 11)) - assert.Equal(t, "имяфайла…", formatMessagePart("mime/type", "имяфайла.док", 9)) - assert.Equal(t, "и…", formatMessagePart("mime/type", "имяфайла.док", 2)) - assert.Equal(t, "…", formatMessagePart("mime/type", "имяфайла.док", 1)) -} |