about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorChris Vittal <chris@vittal.dev>2020-10-27 14:56:44 -0400
committerReto Brunner <reto@labrat.space>2020-11-01 09:50:58 +0100
commitf9bba3d17d4ac8c12e01adccc06566a46546e995 (patch)
tree3d96a7e74f668739544ffe45b70cc96696dd4f99
parent743683a0c19c75ba87d65b6d0c9be117d0224a3e (diff)
downloadaerc-f9bba3d17d4ac8c12e01adccc06566a46546e995.tar.gz
Apply relevant msglist styles in order
Allow styles to be layered over a base style. The list of styles to
apply is layered over the base style in order, such that if the layer
does not differ from the base it is not used. The order that these
styles are applied in is, from first to last:

msglist_default
msglist_unread
msglist_read    (exclusive with unread, so technically the same level)
msglist_flagged
msglist_deleted
msglist_marked

So, msglist_marked style dominates.

This fixes an issue where the msglist_deleted style was not being applied.
-rw-r--r--config/config.go9
-rw-r--r--config/style.go50
-rw-r--r--doc/aerc-stylesets.7.scd21
-rw-r--r--widgets/msglist.go27
4 files changed, 90 insertions, 17 deletions
diff --git a/config/config.go b/config/config.go
index 3ae26c1..bb83579 100644
--- a/config/config.go
+++ b/config/config.go
@@ -699,3 +699,12 @@ func (uiConfig UIConfig) GetStyle(so StyleObject) tcell.Style {
 func (uiConfig UIConfig) GetStyleSelected(so StyleObject) tcell.Style {
 	return uiConfig.style.Selected(so)
 }
+
+func (uiConfig UIConfig) GetComposedStyle(base StyleObject,
+	styles []StyleObject) tcell.Style {
+	return uiConfig.style.Compose(base, styles)
+}
+
+func (uiConfig UIConfig) GetComposedStyleSelected(base StyleObject, styles []StyleObject) tcell.Style {
+	return uiConfig.style.ComposeSelected(base, styles)
+}
diff --git a/config/style.go b/config/style.go
index caf9e4f..af7241d 100644
--- a/config/style.go
+++ b/config/style.go
@@ -31,9 +31,9 @@ const (
 	STYLE_MSGLIST_DEFAULT
 	STYLE_MSGLIST_UNREAD
 	STYLE_MSGLIST_READ
+	STYLE_MSGLIST_FLAGGED
 	STYLE_MSGLIST_DELETED
 	STYLE_MSGLIST_MARKED
-	STYLE_MSGLIST_FLAGGED
 
 	STYLE_DIRLIST_DEFAULT
 
@@ -67,9 +67,9 @@ var StyleNames = map[string]StyleObject{
 	"msglist_default": STYLE_MSGLIST_DEFAULT,
 	"msglist_unread":  STYLE_MSGLIST_UNREAD,
 	"msglist_read":    STYLE_MSGLIST_READ,
+	"msglist_flagged": STYLE_MSGLIST_FLAGGED,
 	"msglist_deleted": STYLE_MSGLIST_DELETED,
 	"msglist_marked":  STYLE_MSGLIST_MARKED,
-	"msglist_flagged": STYLE_MSGLIST_FLAGGED,
 
 	"dirlist_default": STYLE_DIRLIST_DEFAULT,
 
@@ -180,6 +180,31 @@ func (s *Style) Set(attr, val string) error {
 	return nil
 }
 
+func (s Style) composeWith(styles []*Style) Style {
+	newStyle := s
+	for _, st := range styles {
+		if st.Fg != s.Fg {
+			newStyle.Fg = st.Fg
+		}
+		if st.Bg != s.Bg {
+			newStyle.Bg = st.Bg
+		}
+		if st.Bold != s.Bold {
+			newStyle.Bold = st.Bold
+		}
+		if st.Blink != s.Blink {
+			newStyle.Blink = st.Blink
+		}
+		if st.Underline != s.Underline {
+			newStyle.Underline = st.Underline
+		}
+		if st.Reverse != s.Reverse {
+			newStyle.Reverse = st.Reverse
+		}
+	}
+	return newStyle
+}
+
 type StyleSet struct {
 	objects  map[StyleObject]*Style
 	selected map[StyleObject]*Style
@@ -213,6 +238,27 @@ func (ss StyleSet) Selected(so StyleObject) tcell.Style {
 	return ss.selected[so].Get()
 }
 
+func (ss StyleSet) Compose(so StyleObject, sos []StyleObject) tcell.Style {
+	base := *ss.objects[so]
+	styles := make([]*Style, len(sos))
+	for i, so := range sos {
+		styles[i] = ss.objects[so]
+	}
+
+	return base.composeWith(styles).Get()
+}
+
+func (ss StyleSet) ComposeSelected(so StyleObject,
+	sos []StyleObject) tcell.Style {
+	base := *ss.selected[so]
+	styles := make([]*Style, len(sos))
+	for i, so := range sos {
+		styles[i] = ss.selected[so]
+	}
+
+	return base.composeWith(styles).Get()
+}
+
 func findStyleSet(stylesetName string, stylesetsDir []string) (string, error) {
 	for _, dir := range stylesetsDir {
 		stylesetPath, err := homedir.Expand(path.Join(dir, stylesetName))
diff --git a/doc/aerc-stylesets.7.scd b/doc/aerc-stylesets.7.scd
index e3e7b1f..818bf69 100644
--- a/doc/aerc-stylesets.7.scd
+++ b/doc/aerc-stylesets.7.scd
@@ -107,12 +107,12 @@ styling.
 :  Unread messages in a message list.
 |  msglist_read
 :  Read messages in a message list.
+|  msglist_flagged
+:  The messages with the flagged flag.
 |  msglist_deleted
 :  The messages marked as deleted.
 |  msglist_marked
 :  The messages with the marked flag.
-|  msglist_flagged
-:  The messages with the flagged flag.
 |  dirlist_default
 :  The default style for directories in the directory list.
 |  completion_default
@@ -175,6 +175,23 @@ If we specify the global style selected modifer using fnmatch as below:
 
 This toggles the reverse switch for selected version of all the style objects.
 
+## Layered styles
+Some styles, (currently only the `msglist\*` ones) are applied in layers. If
+a style differs from the base (in this case `msglist_default`) then that style
+applies, unless overridden by a higher layer. The order that `msglist` styles
+are applied in is, from first to last:
+
+```
+msglist_default
+msglist_unread
+msglist_read
+msglist_flagged
+msglist_deleted
+msglist_marked
+```
+
+So, the marked style will override all other msglist styles.
+
 ## Colors
 The color values are set using the values accepted by the tcell library.
 The values can be one of the following.
diff --git a/widgets/msglist.go b/widgets/msglist.go
index b7c10d7..61738a8 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -108,12 +108,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
 			config.UI_CONTEXT_SUBJECT: msg.Envelope.Subject,
 		})
 
-		so := config.STYLE_MSGLIST_DEFAULT
-
-		// deleted message
-		if _, ok := store.Deleted[msg.Uid]; ok {
-			so = config.STYLE_MSGLIST_DELETED
-		}
+		msg_styles := []config.StyleObject{}
 		// unread message
 		seen := false
 		flagged := false
@@ -127,25 +122,31 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
 		}
 
 		if seen {
-			so = config.STYLE_MSGLIST_READ
+			msg_styles = append(msg_styles, config.STYLE_MSGLIST_READ)
 		} else {
-			so = config.STYLE_MSGLIST_UNREAD
+			msg_styles = append(msg_styles, config.STYLE_MSGLIST_UNREAD)
 		}
 
 		if flagged {
-			so = config.STYLE_MSGLIST_FLAGGED
+			msg_styles = append(msg_styles, config.STYLE_MSGLIST_FLAGGED)
+		}
+
+		// deleted message
+		if _, ok := store.Deleted[msg.Uid]; ok {
+			msg_styles = append(msg_styles, config.STYLE_MSGLIST_DELETED)
 		}
 
 		// marked message
 		if store.IsMarked(msg.Uid) {
-			so = config.STYLE_MSGLIST_MARKED
+			msg_styles = append(msg_styles, config.STYLE_MSGLIST_MARKED)
 		}
 
-		style := uiConfig.GetStyle(so)
-
+		var style tcell.Style
 		// current row
 		if row == ml.store.SelectedIndex()-ml.scroll {
-			style = uiConfig.GetStyleSelected(so)
+			style = uiConfig.GetComposedStyleSelected(config.STYLE_MSGLIST_DEFAULT, msg_styles)
+		} else {
+			style = uiConfig.GetComposedStyle(config.STYLE_MSGLIST_DEFAULT, msg_styles)
 		}
 
 		ctx.Fill(0, row, ctx.Width(), 1, ' ', style)