Skip to content

Latest commit

 

History

History
325 lines (227 loc) · 13.7 KB

theme_guide.md

File metadata and controls

325 lines (227 loc) · 13.7 KB

Theme Creation

Introduction

This guide will explain the configuration for Apollo and go over creating a basic theme. All configuration is done using zstyles, so I highly recommend reviewing the zsh/util documentation.

Reference

Syntax

Zstyle definitions assign a value to an attribute based on context, and the flexibility of this context is what makes it so useful. Below is a guide to describe the structure of context within Apollo.

zstyle ':apollo:<theme>:<line>:<prompt_side>:<module>:<mode>:<element>:<element/module_side>' attribute "value"
                   ^      ^        ^            ^        ^         ^              ^                ^
                   |      |        |            |        |         |              |                Attribute name
                   |      |        |            |        |         |              |
                   |      |        |            |        |         |              left or right side of module/element text if applicable. * for both
                   |      |        |            |        |         |
                   |      |        |            |        |         Subsection of module. Possibly module specific.
                   |      |        |            |        |
                   |      |        |            |        Module mode. Value of * applies to all modes
                   |      |        |            |
                   |      |        |            Module name. Value of * applies to all modules
                   |      |        |
                   |      |        left or right prompt. * for both
                   |      |
                   |      Prompt line number. * for all lines
                   |
                   Active theme or * for all themes

Options provided to all modules by framework

Every module has the following attributes available:

Attribute Type Description
min_width integer Minimum width to enforce on module.
always_show boolean Show module even when it contains empty output.
fg_color color Foreground color for module.
bg_color color Background color for module.
style list Style for module text (bold,standout,underline)
always_refresh boolean Force refresh of prompt on async update even if module text hasn't changed.

All modules include the following elements provided by the framework:

Element Description
main This is the module text itself
separator String to use as left module separator when NOT at beginning of line
begin String to use to left of module when at beginning of line
end String to use to right of module when at end of line
left:surround String to left of module text
right:surround String to right of module text

Two special elements can be set at the module level AND as extensions of individual regular elements:

Element Description
left:label String to left of module/element
right:label String to right of module/element

To better understand how these all fit together, here's a quick reference. The first is a look at the module as a whole, the second is a closer breakdown of module_text, which is made up of the elements inside the module:

{separator/begin}{left:surround}{left:label}{module_text}{right:label}{right:surround}{end}
{left:label}{element1_text}{right:label}{left:label}{element2_text}{right:label}{etc...}

Every element has the following attributes available:

Attribute Type Description
fg_color color Foreground color
bg_color color Background Color
text string String to display
style list Style for element text (bold,standout,underline)
blend* boolean Determines fg_color and bg_color from adjacent modules.
revblend* boolean Determines fg_color and bg_color from adjacent modules. Reversed colors compared to blend

*Overrides fg_color and bg_color. Only valid for begin/end and separator elements.

The "text" attribute will not have an effect in many cases if the text is dynamic and generated by the module, but any elements with static text may utilize the "text" attribute.

All other module options should be controlled via attributes at the module scope, even if they only impact an individual element in the module. This is done for the sake of providing a uniform configuration interface.

Examples:

zstyle ':apollo:example:*:*:*:*:surround:*' text " "

zstyle ':apollo:example:*:right:*:*:separator' text ""
zstyle ':apollo:example:*:right:*:*:separator' revblend "true"
zstyle ':apollo:example:*:left:*:*:separator' text ""
zstyle ':apollo:example:*:left:*:*:separator' blend "true"

zstyle ':apollo:example:*:*:*:*:begin' blend "true"
zstyle ':apollo:example:*:*:*:*:begin' text ""
zstyle ':apollo:example:*:*:*:*:end' blend "true"
zstyle ':apollo:example:*:*:*:*:end' text ""

Getting Started

Apollo will load additional configuration files from ${XDG_CONFIG_HOME}/.config/apollo/ or from ${HOME}/.config/apollo/ if XDG_CONFIG_HOME is not set. The file must have a .conf extension. This is where you should place any themes in development or for personal use. I highly recommend not setting module lists as part of the theme so that users can easily decide their own module lists without being theme dependent. I do however recommend testing themes with a variety of module configurations to ensure that it maintains the desired look. Module lists are defined by the following:

zstyle ':apollo:*:core:modules:left' modules 'root_indicator' 'context' 'public_ip' 'virtualenv' 'quota' 'newline' 'vi_mode' 'dir' 'ruler'
zstyle ':apollo:*:core:modules:right' modules 'command_execution_time' 'status' 'php_version' 'newline' 'background_jobs' 'git' 'date' 'clock'

Text

The vast majority of elements are defined by setting a "text" attribute. The text attributes accept any string and unicode characters are supported. Unicode characters can be added directly either by copying the glyphs or using unicode escape sequences within ANSI-C quotes. If you'd like to generate a full chart of unicode characters and their escape sequences, you can add the following function to your shell configuration:

unicode_chart() {

  local x y a

  for ((y=0;y<=65535;y++)); do
    for x in 0 1 2 3 4 5 6 7; do
      a=$(([##16]y))
      a="${(l:4::0:)a}"
      printf "%-10s %-10b" "\\u$a" "\\u$a "
      ((y++))
    done
    ((y--))
    echo
  done

  for ((y=65536;y<=1114109;y++)); do
    for x in 0 1 2 3 4 5 6 7; do
      a=$(([##16]y))
      printf "%-10s %-10b" "\\U$a" "\\U$a "
      ((y++))
    done
    ((y--))
    echo
  done

}

This generates 26MB of output, so I highly recommend redirecting output to a file.

Compatibility note: Unicode character support is highly dependent on terminal and font. Unfortunately there's no reliable way to test what an environment supports, so if your theme is dependent on a specific font, be sure to note it.

Colors

Every element accepts two different attributes for color, fg_color and bg_color. As you'd expect, these are for setting the color of the font and the background color. Each of them accepts one of the following values:

zstyle ':apollo:example:*' fg_color white
zstyle ':apollo:example:*:*:*:*:surround:*' fg_color blue
zstyle ':apollo:example:*:core:*' fg_color red
zstyle ':apollo:example:core:prompt:end' fg_color blue

Compatibility note: Just like with unicode characters, color support is very dependent on the terminal environment. Most modern environments support 24-bit truecolor, but support for 256 color palette is much better, and all terminals should support the base 8 color palette.

Styles

All elements support a style attribute. This attribute accepts a list of one or more of the following options:

  • bold
  • standout
  • underline

Decorations

Decorations consist of strings to place at the beginning and end of each prompt lines, as well as the separators between modules. These elements support the normal color attributes, as well as two additional attributes:

  • blend
  • revblend

These override the default color attributes, and instead inherit colors from the adjacent modules. For example to replicate the popular powerline style you can set the following:

zstyle ':apollo:example:*:*:*:*:begin' text ""
zstyle ':apollo:example:*:left:*:*:separator' text ""
zstyle ':apollo:example:*:right:*:*:separator' text ""
zstyle ':apollo:example:*:*:*:*:end' text ""

zstyle ':apollo:example:*:*:*:*:(begin|end)' blend "true"
zstyle ':apollo:example:*:left:*:*:separator' blend "true"
zstyle ':apollo:example:*:right:*:*:separator' revblend "true"

Decorations have a negligible performance impact, but if they're not used on your theme the logic can be disabled with the following:

zstyle ':apollo:example:core:decorations' disabled "true"

Labels

All modules, as well as the elements provided by modules, support left and right label text.

Surround

In addition to left and right labels, modules can add left and right surround strings.

zstyle ':apollo:example:*:*:*:*:surround:left' text "("
zstyle ':apollo:example:*:*:*:*:surround:right' text ")"

Multiline

Multiline prompts are supported by adding "newline" or "ruler" to the module lists. Ruler is only valid for the left module list, and the right list can not span more lines than the left. The ruler will display a configurable string spanning from the left prompt to the right. The string will repeat itself as needed to bridge the gap and resize with window changes.

zstyle ':apollo:example:*:core:ruler' text ""

Links

Multiline prompts can also add additional strings to the beginning and end of each line. These are intended for characters that visually tie the lines together but any strings is valid. This must also be explicitly enabled.

zstyle ':apollo:example:core:links' enabled "true"

zstyle ':apollo:example:*:*:core:links:none' text ""
zstyle ':apollo:example:*:left:core:links:top' text "╭─"
zstyle ':apollo:example:*:left:core:links:mid' text "├─"
zstyle ':apollo:example:*:left:core:links:str' text ""
zstyle ':apollo:example:*:left:core:links:bot' text "╰─"
zstyle ':apollo:example:*:right:core:links:top' text "─╮"
zstyle ':apollo:example:*:right:core:links:mid' text "─┤"
zstyle ':apollo:example:*:right:core:links:str' text ""
zstyle ':apollo:example:*:right:core:links:bot' text "─╯"

Prompt End

Prompt end allows for adding a string at the very end of the prompt just before the cursor.

zstyle ':apollo:example:core:prompt:end' text "> "

Scrollback theme

The scrollback theme setting sets the theme to use after executing a command and saving a line to the scrollback buffer. The value should point to an actual theme name, so if you'd like to customize this you should create a separate theme. This primarily provides a way of shrinking a multiline theme down to a single line theme to save space. Note that asynchronous modules will NOT run for a scrollback theme.

zstyle ':apollo:example:core:scrollback' theme "scrollback"

Basic Theme

This is a simple theme I created to demonstrate some of the settings mentioned above. It starts off with setting the general colors for the theme and then moves on to set more specific things.

zstyle ':apollo:bluefade:*' fg_color white
zstyle ':apollo:bluefade:*' bg_color blue

zstyle ':apollo:bluefade:*:*:*:*:begin' text "░▒▓"
zstyle ':apollo:bluefade:*:*:*:*:end' text "▓▒░"
zstyle ':apollo:bluefade:*:*:*:*:surround:*' text " "
zstyle ':apollo:bluefade:*:*:*:*:separator' text "|"
zstyle ':apollo:bluefade:*:*:*:*:(begin|end)' blend true

zstyle ':apollo:bluefade:*:core:ruler' bg_color none
zstyle ':apollo:bluefade:*:core:ruler' fg_color blue
zstyle ':apollo:bluefade:*:core:ruler' text "\|/_"

zstyle ':apollo:bluefade:core:scrollback' theme scrollback

Module Specific Settings

In general I recommend leaving module specific settings outside of the theme, as it would require users to override settings for the specific theme if they want something different. That said, it's generally fine to configure how something will display as long as you avoid deciding what will be displayed. For example it's fine to style individual elements for the git module, but setting the list of elements to display should be avoided in most cases. Ideally the user should be able to switch themes without it impacting the information displayed.

Faux Modules

It's technically possible to create a simple module using only zstyle. This is done by setting the main module text. You can set it to a static string, a variable, command substitution, or whatever other shell expression. Pay close attention to quoting. If it's something you want to evaluate on every run, it should be encased in single quotes or properly escaped. Otherwise it will only be evaluated when the style is set on startup. Keep in mind that since these "modules" don't have a cache key function, they won't make use of the module cache. Therefore this should only be used for simple tasks.

zstyle ':apollo:example:*:*:fake:*:main' text "\$variable"
zstyle ':apollo:example:*:*:fake:*:main' text '$(some_function)'