diff --git a/config/aerc.conf.in b/config/aerc.conf.in index 08d1dbc..1f5c87d 100644 --- a/config/aerc.conf.in +++ b/config/aerc.conf.in @@ -94,6 +94,12 @@ next-message-on-delete=true # default: @SHAREDIR@/stylesets/ stylesets-dirs=@SHAREDIR@/stylesets/ +# Uncomment to use box-drawing characters for vertical and horizontal borders. +# +# Default: spaces +# border-char-vertical=│ +# border-char-horizontal=─ + # Sets the styleset to use for the aerc ui elements. # # Default: default diff --git a/config/config.go b/config/config.go index 9be55c6..cbd5860 100644 --- a/config/config.go +++ b/config/config.go @@ -53,6 +53,9 @@ type UIConfig struct { StyleSetDirs []string `ini:"stylesets-dirs" delim:":"` StyleSetName string `ini:"styleset-name"` style StyleSet + // customize border appearance + BorderCharVertical rune `ini:"-"` + BorderCharHorizontal rune `ini:"-"` } type ContextType int @@ -358,6 +361,9 @@ func (config *AercConfig) LoadConfig(file *ini.File) error { if err := ui.MapTo(&config.Ui); err != nil { return err } + if err := validateBorderChars(ui, &config.Ui); err != nil { + return err + } } for _, sectionName := range file.SectionStrings() { if !strings.Contains(sectionName, "ui:") { @@ -372,6 +378,9 @@ func (config *AercConfig) LoadConfig(file *ini.File) error { if err := uiSection.MapTo(&uiSubConfig); err != nil { return err } + if err := validateBorderChars(uiSection, &uiSubConfig); err != nil { + return err + } contextualUi := UIConfigContext{ UiConfig: uiSubConfig, @@ -461,6 +470,26 @@ func (config *AercConfig) LoadConfig(file *ini.File) error { return nil } +func validateBorderChars(section *ini.Section, config *UIConfig) error { + for key, val := range section.KeysHash() { + switch key { + case "border-char-vertical": + char := []rune(val) + if len(char) != 1 { + return fmt.Errorf("%v must be one and only one character", key) + } + config.BorderCharVertical = char[0] + case "border-char-horizontal": + char := []rune(val) + if len(char) != 1 { + return fmt.Errorf("%v must be one and only one character", key) + } + config.BorderCharHorizontal = char[0] + } + } + return nil +} + func LoadConfigFromFile(root *string, sharedir string) (*AercConfig, error) { if root == nil { _root := path.Join(xdg.ConfigHome(), "aerc") @@ -524,6 +553,9 @@ func LoadConfigFromFile(root *string, sharedir string) (*AercConfig, error) { CompletionPopovers: true, StyleSetDirs: []string{path.Join(sharedir, "stylesets")}, StyleSetName: "default", + // border defaults + BorderCharVertical: ' ', + BorderCharHorizontal: ' ', }, ContextualUis: []UIConfigContext{}, diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index f659e60..e95a86c 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -192,6 +192,13 @@ These options are configured in the *[ui]* section of aerc.conf. Default: 250ms +*border-char-vertical* +*border-char-horizontal* + Set stylable characters (via the 'border' element) for vertical and + horizontal borders. + + Default: spaces + *stylesets-dirs* The directories where the stylesets are stored. The config takes a colon-separated list of dirs. diff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd index ff23aa3..4e1a2b5 100644 --- a/doc/aerc-stylesets.7.scd +++ b/doc/aerc-stylesets.7.scd @@ -128,7 +128,7 @@ styling. | spinner : The style for the loading spinner. | border -: The style used to draw borders. *Only the background color is used*. +: The style used to draw borders. *Only the background color is used unless you customize border-char-vertical and/or border-char-horizontal in aerc.conf*. | selector_default : The default style for the selector ui element. | selector_focused diff --git a/lib/ui/borders.go b/lib/ui/borders.go index 1b69a8e..886a171 100644 --- a/lib/ui/borders.go +++ b/lib/ui/borders.go @@ -50,22 +50,25 @@ func (bordered *Bordered) Draw(ctx *Context) { width := ctx.Width() height := ctx.Height() style := bordered.uiConfig.GetStyle(config.STYLE_BORDER) + verticalChar := bordered.uiConfig.BorderCharVertical + horizontalChar := bordered.uiConfig.BorderCharHorizontal + if bordered.borders&BORDER_LEFT != 0 { - ctx.Fill(0, 0, 1, ctx.Height(), ' ', style) + ctx.Fill(0, 0, 1, ctx.Height(), verticalChar, style) x += 1 width -= 1 } if bordered.borders&BORDER_TOP != 0 { - ctx.Fill(0, 0, ctx.Width(), 1, ' ', style) + ctx.Fill(0, 0, ctx.Width(), 1, horizontalChar, style) y += 1 height -= 1 } if bordered.borders&BORDER_RIGHT != 0 { - ctx.Fill(ctx.Width()-1, 0, 1, ctx.Height(), ' ', style) + ctx.Fill(ctx.Width()-1, 0, 1, ctx.Height(), verticalChar, style) width -= 1 } if bordered.borders&BORDER_BOTTOM != 0 { - ctx.Fill(0, ctx.Height()-1, ctx.Width(), 1, ' ', style) + ctx.Fill(0, ctx.Height()-1, ctx.Width(), 1, horizontalChar, style) height -= 1 } subctx := ctx.Subcontext(x, y, width, height) diff --git a/widgets/compose.go b/widgets/compose.go index 69a2dcc..d3e57c5 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -679,9 +679,10 @@ func (c *Composer) updateGrid() { c.grid.RemoveChild(c.heditors) } borderStyle := c.config.Ui.GetStyle(config.STYLE_BORDER) + borderChar := c.config.Ui.BorderCharHorizontal c.heditors = heditors c.grid.AddChild(c.heditors).At(0, 0) - c.grid.AddChild(ui.NewFill(' ', borderStyle)).At(1, 0) + c.grid.AddChild(ui.NewFill(borderChar, borderStyle)).At(1, 0) } func (c *Composer) reloadEmail() error { diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index fc4529c..dba2bc6 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -106,14 +106,15 @@ func NewMessageViewer(acct *AccountView, } borderStyle := acct.UiConfig().GetStyle(config.STYLE_BORDER) + borderChar := acct.UiConfig().BorderCharHorizontal grid.AddChild(header).At(0, 0) if msg.PGPDetails() != nil { grid.AddChild(NewPGPInfo(msg.PGPDetails(), acct.UiConfig())).At(1, 0) - grid.AddChild(ui.NewFill(' ', borderStyle)).At(2, 0) + grid.AddChild(ui.NewFill(borderChar, borderStyle)).At(2, 0) grid.AddChild(switcher).At(3, 0) } else { - grid.AddChild(ui.NewFill(' ', borderStyle)).At(1, 0) + grid.AddChild(ui.NewFill(borderChar, borderStyle)).At(1, 0) grid.AddChild(switcher).At(2, 0) }