Skip to content
TildeMailv0.2.1

Themes

A theme is a palette of 20 colors. This page explains how to write a theme file and select it. The terminal interface reads the active theme when it starts and draws every role of it; :theme <name> switches the theme until you quit.

Create the folder ~/.config/tildemail/themes/ (tmail does not create it; the themes folder of the installation, if any, is read after it) and add one file per theme, named <name>.toml. A theme file has a [colors] table. A role the file leaves out takes the value of the built-in default theme (except top_bar_fg, top_bar_bg and conversation_bg, which follow the colors of the theme itself, see Roles), so a theme can set as few colors as you like:

~/.config/tildemail/themes/nord.toml
[colors]
background = "#2E3440"
foreground = "#D8DEE9"
accent = "#88C0D0"
error = "#BF616A"

Select it with the top-level theme key of config.toml:

theme = "nord"

Write theme before any table. Written after a [table] header, it belongs to that table, and tmail check warns that the key is misplaced.

Check the result with tmail themes list and tmail themes show <name> (see Commands).

The themes/ folder of the repository holds eight themes, made from well-known palettes: catppuccin-latte (light), dracula, gruvbox-dark, gruvbox-light, nord, solarized-dark, solarized-light and tokyo-night. Each sets every role. A color is a little lighter or darker than in the original palette where that was needed to give every text role a contrast of at least 4.5:1 against the background and the rows of a conversation, and of at least 3:1 against the selected row, and the tests check it.

To use them from a clone, copy the files: mkdir -p ~/.config/tildemail/themes && cp themes/*.toml ~/.config/tildemail/themes/. The release archives carry the same folder (copy it yourself, tmail does not read the archive), and the .deb installs it in /usr/share/tildemail/themes/, and tmail reads that folder after ~/.config/tildemail/themes/: theme = "nord" works right after the install, and a file of the same name in your own folder wins, so you can copy one and change it.

I kept the palette small on purpose: a few meaningful roles instead of a color for every element of the screen. The built-in default theme is dark.

Group Roles
Base background, foreground, muted, border
Accent and selection accent, selection_bg, selection_fg
Status error, warning, success, info
Mail unread, flagged, quote
PGP signature signature_good, signature_bad, signature_unknown
Top bar top_bar_fg, top_bar_bg
Conversations conversation_bg

Where each role is drawn:

Role Drawn in
background, foreground the background and the text of every pane
border the frames of the panes, the rule under the header in the reader, and the background of the selected row when its pane does not have the focus
muted the date, the hints on the last line, the flag and state columns of a read message, secondary text in the reader
accent the title of the pane that has the focus, the selection marker, the signed and encrypted marks, the selected attachment
selection_bg, selection_fg the selected row of the pane that has the focus
unread the subject and the state mark of an unread message, in bold
flagged the star of a flagged message
quote quoted lines in the reader
error error messages on the last line, and the Problem: line of a message that cannot be opened
warning, success, info messages of that kind on the last line; info also draws the attachments in the reader
signature_good, signature_bad, signature_unknown the Signature: line of the reader, and the trust line under Key:
top_bar_fg, top_bar_bg the bar at the top of the screen that your scripts fill with top_status (see Scripting); a theme that leaves them out gets its own foreground on its own border, the colors of the last line, so a light theme has a light bar. A script can override these two colors with top_status.set_colors
conversation_bg the background of the rows that belong to a conversation: the head with ▸ (n) and the messages shown under an open one. Single messages keep background, and the selected row keeps the selection color. A theme that leaves it out keeps its own background there, so a light theme is not tinted with the dark color of the default theme

The three signature roles keep a good signature apart from the others: signature_unknown covers an unknown key and an untrusted one, and signature_bad covers a bad or malformed signature.

A color is exactly # followed by six hex digits, in upper or lower case. Short forms (#RGB), alpha, color names and 256-color numbers are not accepted.

A theme can also change the small symbols of the interface, in a [symbols] table next to [colors]. A key you leave out keeps the symbol of the default theme, so a theme can change just one.

[symbols]
encrypted = "\uF023" # a padlock of a Nerd Font
rule = "-"
separator = " | "
Key Where it is drawn Default
unread unread message in the list ●
flagged flagged message ★
answered answered message ↩
signed signed message s
encrypted encrypted message, the padlock #
selection in front of the row you are on ▌
expandable, collapsible account of the sidebar, closed or open ▸, ▾
online, offline, error_mark connection of an account in the sidebar ●, ○, !
separator between the parts of the last line and the entries of the top bar │
bullet in front of an item of a bulleted list in the reader, followed by a space •
rule repeated to draw the line under the header of a message, a rule in the text and the line under the header of a table ─
ellipsis ends a text that was cut to fit: the list, the sidebar, the top bar, the last line and the reader …

Each symbol is a text of 1 to 8 characters without control or invisible characters (a zero-width space or a bidirectional mark, for instance); the file is invalid otherwise. What the screen can draw is stricter, because the columns of the list and of the sidebar are one cell wide: every symbol except separator must be exactly one cell wide, and separator one to five. A symbol that does not fit is not used: the one of the default theme is drawn instead and a warning in the log names the symbol. A wide emoji is two cells, a symbol with the emoji selector (U+FE0F) is refused, and expandable and collapsible take one character only; use a glyph of a Nerd Font or another one-cell symbol. Some symbols are still fixed: the quote mark of the reader (│), the junction ┼ and the vertical bar of a table, the arrow between the account and the folder in the last line, and the ellipsis of the help window and of the key hints.

  • The theme name is the file name without .toml. It may contain only letters, digits, _ and -, and it is case sensitive. Other *.toml files are skipped, and tmail themes list says so. Files that do not end in .toml are ignored.
  • default is reserved: a default.toml file is never used, and tmail themes list shows it as skipped.
  • Only regular files directly in the themes folder count; a symbolic link to a file is fine. Subfolders are ignored. A file larger than 64 KB is invalid.
  • A theme is invalid when it has an unknown key under [colors], a value that is not a #RRGGBB string, an unknown key or a value that is not a text of 1 to 8 characters under [symbols], or a TOML syntax error. The error names the theme and the key (Theme 'broken': unknown key colors.acent.). For a syntax error it gives only the position, never the content of the file.

A theme that cannot be used never stops the program. If theme names a missing, invalid or badly named theme, the code that loads the theme falls back to default and logs a warning with the reason. The terminal interface falls back to default when it loads the theme and posts the warning as a status message; tmail themes does not log it today.