From 30fe1d6e1440867199cfb2daf54d9a8676173c41 Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Sat, 9 Jan 2021 19:21:32 +0100 Subject: [PATCH] Improve style-gnome-terminal.sh. Configurations are now parsed from very simple files, instead of being defined inline in the script (however cleverly). Config file and profile manipulation is now encapsulated in tiny libraries. This should allow implementation of other subcommands without too much effort. --- README.md | 4 +- style-gnome-terminal.sh | 339 ++++++++++++++++++++++++++-------------- styles/gruvbox8.conf | 21 +++ 3 files changed, 244 insertions(+), 120 deletions(-) create mode 100644 styles/gruvbox8.conf diff --git a/README.md b/README.md index f66e91e..d65f705 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,10 @@ $ ln -s ~/dotfiles/tmux.conf ~/.tmux.conf ## Configure gnome-terminal +Install the [Hack font](https://github.com/source-foundry/Hack). + Run the following command: ```sh -$ ~/dotfiles/style-gnome-terminal.sh gruvbox8 +$ ~/dotfiles/style-gnome-terminal.sh styles/gruvbox8.conf ``` diff --git a/style-gnome-terminal.sh b/style-gnome-terminal.sh index 82276e9..27fe6f3 100755 --- a/style-gnome-terminal.sh +++ b/style-gnome-terminal.sh @@ -3,106 +3,246 @@ set -eu +# CONSTANTS +# ========= + +# DConf directory in which gnome-terminal profile configuration is stored. ROOT_DCONF_DIR='/org/gnome/terminal/legacy/profiles:/' -# ansi_colors COLOR1 ... COLOR16 -function ansi_colors() { - echo -n "['$1'" - for i in {2..16}; do - echo -n ",'${!i}'" +# The names of ANSI color properties in config files. +# Order matters. These correspond to the ANSI color codes. +ANSI_COLOR_PROPERTIES=( + "ansi-colors-black" + "ansi-colors-red" + "ansi-colors-green" + "ansi-colors-yellow" + "ansi-colors-blue" + "ansi-colors-purple" + "ansi-colors-cyan" + "ansi-colors-white" + "ansi-colors-bright-black" + "ansi-colors-bright-red" + "ansi-colors-bright-green" + "ansi-colors-bright-yellow" + "ansi-colors-bright-blue" + "ansi-colors-bright-purple" + "ansi-colors-bright-cyan" + "ansi-colors-bright-white" +) + +# LOGGING +# ======= + +# log ARGS... +# echo for stderr +function log() { + echo 1>&2 "$@" +} + +# die ARGS... +# log then exit with an error code +function die() { + log "$@" + exit 1 +} + + +# CONFIG +# ====== +# +# Configuration files have a very basic grammar: +# +# PROPERTY_NAME = VALUE +# +# The functions below allow reading config file contents. + +# config_get_property FILE PROPERTY +# Echoes the given property from the given config file. +function config_get_property() { + FILE="$1" + PROPERTY="$2" + + sed -n "s:^${PROPERTY} *= *\(\.*\):\1:p" < "${FILE}" +} + +# config_get_property_or_die FILE PROPERTY +# config_get_property, except dies if the property is not found. +function config_get_property_or_die() { + FILE="$1" + PROPERTY="$2" + + RESULT=$(config_get_property "${FILE}" "${PROPERTY}") + if [ -z "$RESULT" ]; then + die "Error: cannot find property '${PROPERTY}' in file '${FILE}'." + fi + + echo "${RESULT}" +} + +# config_get_font FILE +function config_get_font() { + FILE="$1" + config_get_property "${FILE}" "font" +} + +# config_get_foreground_color FILE +function config_get_foreground_color() { + FILE="$1" + config_get_property "${FILE}" "foreground-color" +} + +# config_get_background_color FILE +function config_get_background_color() { + FILE="$1" + config_get_property "${FILE}" "background-color" +} + +# join_ansi_colors COLOR1 ... COLOR16 +# Echoes "[${COLOR1}, ..., ${COLOR16}]". +function join_ansi_colors () { + echo -n "[$1" + for i in {2..16}; do + echo -n ", ${!i}" # Get the i-th argument to this function. done echo "]" } -# colorscheme NAME FG_COLOR BG_COLOR ANSI_COLORS -function colorscheme() { - NAME="$1" - FG_COLOR="$2" - BG_COLOR="$3" - ANSI_COLORS="$4" +# config_get_ansi_colors FILE +function config_get_ansi_colors() { + FILE="$1" + + ANSI_COLORS=() + for PROPERTY in "${ANSI_COLOR_PROPERTIES[@]}"; do + COLOR=$(config_get_property_or_die "${FILE}" "${PROPERTY}") + ANSI_COLORS+=("${COLOR}") + done - echo "${NAME};${FG_COLOR};${BG_COLOR};${ANSI_COLORS}" + join_ansi_colors "${ANSI_COLORS[@]}" } -function unpack_colorscheme_field(){ - PACKED="$1" - FIELD="$2" - echo "${PACKED}" | cut -d ';' -f "${FIELD}" + +# PROFILE +# ======= +# +# Gnome-terminal profile preferences are read and written through dconf. +# +# In the following functions, profiles are referenced by their dconf directory +# paths (ending in a '/' character). + +# profile_get_property PROFILE PROPERTY +# Echoes the given property from the given gnome-terminal profile. +function profile_get_property() { + PROFILE="$1" + PROPERTY="$2" + + dconf read "${PROFILE}${PROPERTY}" } -# colorscheme_name COLORSCHEME -function colorscheme_name() { - unpack_colorscheme_field "$1" 1 +# profile_set_property PROFILE PROPERTY VALUE +# Sets the given profile's given property to the given value. +function profile_set_property() { + PROFILE="$1" + PROPERTY="$2" + VALUE="$3" + + dconf write "${PROFILE}${PROPERTY}" "${VALUE}" } -# colorscheme_fg_color COLORSCHEME -function colorscheme_fg_color() { - unpack_colorscheme_field "$1" 2 +# profile_get_name PROFILE +# Echoes the human-readable name for the given gnome-terminal profile. +function profile_get_name() { + PROFILE="$1" + profile_get_property "${PROFILE}" "visible-name" } -# colorscheme_bg_color COLORSCHEME -function colorscheme_bg_color() { - unpack_colorscheme_field "$1" 3 +# profile_set_name PROFILE VALUE +# Sets the human-readable name for the given gnome-terminal profile. +function profile_set_name() { + PROFILE="$1" + VALUE="$2" + profile_set_property "${PROFILE}" "visible-name" "${VALUE}" } -# colorscheme_ansi_colors COLORSCHEME -function colorscheme_ansi_colors() { - unpack_colorscheme_field "$1" 4 +# profile_get_font PROFILE +# Echoes the font for the given gnome-terminal profile. +function profile_get_font() { + PROFILE="$1" + profile_get_property "${PROFILE}" "font" } -GRUVBOX8_COLORSCHEME=$(colorscheme "gruvbox8" \ - "#ebdbb2" \ - "#1d2021" \ - $(ansi_colors \ - "#1d2021" \ - "#cc241d" \ - "#98971a" \ - "#d79921" \ - "#458588" \ - "#b16286" \ - "#689d6a" \ - "#a89984" \ - "#928374" \ - "#fb4934" \ - "#b8bb26" \ - "#fabd2f" \ - "#83a598" \ - "#d3869b" \ - "#8ec07c" \ - "#ebdbb2" - ) -) +# profile_set_font PROFILE VALUE +# Sets the font for the given gnome-terminal profile. +function profile_set_font() { + PROFILE="$1" + VALUE="$2" + profile_set_property "${PROFILE}" "font" "${VALUE}" +} -COLORSCHEMES=( - "${GRUVBOX8_COLORSCHEME}" -) +# profile_get_foreground_color PROFILE +# Echoes the foreground color for the given gnome-terminal profile. +function profile_get_foreground_color() { + PROFILE="$1" + profile_get_property "${PROFILE}" "foreground-color" +} -# log ARGS... -# echo for stderr -function log() { - echo 1>&2 "$@" +# profile_set_foreground_color PROFILE VALUE +# Sets the foreground color for the given gnome-terminal profile. +function profile_set_foreground_color() { + PROFILE="$1" + VALUE="$2" + profile_set_property "${PROFILE}" "foreground-color" "${VALUE}" } -# die ARGS... -# log then exit with an error code -function die() { - log "$@" - exit 1 +# profile_get_background_color PROFILE +# Echoes the background color for the given gnome-terminal profile. +function profile_get_background_color() { + PROFILE="$1" + profile_get_property "${PROFILE}" "background_color" } -function get_profile_property() { +# profile_set_background_color PROFILE VALUE +# Sets the background color for the given gnome-terminal profile. +function profile_set_background_color() { PROFILE="$1" - PROPERTY="$2" + VALUE="$2" + profile_set_property "${PROFILE}" "background-color" "${VALUE}" +} - dconf read "${PROFILE}${PROPERTY}" +# profile_get_ansi_colors PROFILE +# Echoes the ANSI color palette for the given gnome-terminal profile. +function profile_get_ansi_colors() { + PROFILE="$1" + profile_get_property "${PROFILE}" "palette" } -# get_profile_name PROFILE -# Echoes the human-readable name for a gnome-terminal profile subdirectory. -function get_profile_name() { - get_profile_property "$1" "visible-name" +# profile_set_ansi_colors PROFILE VALUE +# Sets the ANSI color palette for the given gnome-terminal profile. +function profile_set_ansi_colors() { + PROFILE="$1" + VALUE="$2" + profile_set_property "${PROFILE}" "palette" "${VALUE}" +} + +# profile_apply_config PROFILE CONFIG_FILE +# Applies the given configuration to the given gnome-terminal profile. +function profile_apply_config() { + PROFILE="$1" + CONFIG_FILE="$2" + + FONT=$(config_get_font "${CONFIG_FILE}") + FOREGROUND_COLOR=$(config_get_foreground_color "${CONFIG_FILE}") + BACKGROUND_COLOR=$(config_get_background_color "${CONFIG_FILE}") + ANSI_COLORS=$(config_get_ansi_colors "${CONFIG_FILE}") + + profile_set_font "${PROFILE}" "${FONT}" + profile_set_foreground_color "${PROFILE}" "${FOREGROUND_COLOR}" + profile_set_background_color "${PROFILE}" "${BACKGROUND_COLOR}" + profile_set_ansi_colors "${PROFILE}" "${ANSI_COLORS}" } +# INTERACTIVE USE +# =============== + # choose_number BASE_PROMPT MIN MAX # Asks the user to choose a number between MIN and MAX, inclusive. # BASE_PROMPT should not end in a newline. @@ -110,6 +250,7 @@ function choose_number() { PROMPT="$1" MIN_NUMBER="$2" MAX_NUMBER="$3" + while true; do read -p "$1 [${MIN_NUMBER} to ${MAX_NUMBER}]: " CHOSEN_NUMBER if [ "${CHOSEN_NUMBER}" -lt "${MIN_NUMBER}" ]; then @@ -133,81 +274,42 @@ function choose_profile() { PROFILES+=("${ROOT_DCONF_DIR}${PROFILE_SUBDIR}") done NUM_PROFILES="${#PROFILES[@]}" - + if [ "${NUM_PROFILES}" -eq 0 ]; then die "Error: found no gnome-terminal profiles to style." fi if [ "${NUM_PROFILES}" -eq 1 ]; then PROFILE="${PROFILES[0]}" - PROFILE_NAME=$(get_profile_name "${PROFILE}") + PROFILE_NAME=$(profile_get_name "${PROFILE}") log "Found single gnome-terminal profile ${PROFILE_NAME}, using it." echo "${PROFILE}" return fi log "Available gnome-terminal profiles:" - + for i in $(seq 1 "${NUM_PROFILES}"); do PROFILE="${PROFILES[$(($i - 1))]}" - PROFILE_NAME=$(get_profile_name "${PROFILE}") + PROFILE_NAME=$(profile_get_name "${PROFILE}") log " #$i: ${PROFILE_NAME}" done choose_number "Choose a profile" 1 "${NUM_PROFILES}" } -# find_colorscheme COLORSCHEME_NAME -# Echoes the colorscheme if it exists. -# Dies otherwise with a useful message. -function find_colorscheme() { - COLORSCHEME_NAME="$1" - - NAMES=() - for COLORSCHEME in "${COLORSCHEMES[@]}"; do - NAME=$(colorscheme_name ${COLORSCHEME}) - NAMES+=("${NAME}") - - if [ "${NAME,,}" == "${NAME,,}" ]; then - echo "${COLORSCHEME}" - return - fi - done - - log "Error: no such colorscheme '${COLORSCHEME_NAME}'. Options are:" - for NAME in "${NAMES[@]}"; do - log " - ${NAME}" - done - exit 1 -} - -# apply_colorscheme PROFILE COLORSCHEME -# Applies the given packed colorscheme to the given gnome-terminal profile. -function apply_colorscheme() { - PROFILE="$1" - COLORSCHEME="$2" - - FG_COLOR=$(colorscheme_fg_color "${COLORSCHEME}") - BG_COLOR=$(colorscheme_bg_color "${COLORSCHEME}") - ANSI_COLORS=$(colorscheme_ansi_colors "${COLORSCHEME}") - - dconf write "${PROFILE}foreground-color" "'${FG_COLOR}'" - dconf write "${PROFILE}background-color" "'${BG_COLOR}'" - dconf write "${PROFILE}palette" "${ANSI_COLORS}" -} - function main() { if [ "$#" -le 0 ]; then - die "USAGE: style-gnome-terminal COLORSCHEME_NAME" + die "USAGE: style-gnome-terminal CONFIG_FILE" fi # TODO: Subcommands: - # + # # Profiles: - # + # # - profile list # - profile show NAME_OR_ID - # + # # Styling: # # These all take an optional [profile NAME_OR_ID] clause to specify a profile @@ -233,10 +335,9 @@ function main() { # arbitrary code (rules our source-ing .sh files containing variables), that # does not require onerous dependencies to parse. - COLORSCHEME_NAME="$1" - COLORSCHEME=$(find_colorscheme "${COLORSCHEME_NAME}") + CONFIG_FILE="$1" PROFILE=$(choose_profile) - apply_colorscheme "${PROFILE}" "${COLORSCHEME}" + profile_apply_config "${PROFILE}" "${CONFIG_FILE}" } main "$@" diff --git a/styles/gruvbox8.conf b/styles/gruvbox8.conf new file mode 100644 index 0000000..4748a67 --- /dev/null +++ b/styles/gruvbox8.conf @@ -0,0 +1,21 @@ +font = "Hack Regular 12" + +foreground-color = "#ebdbb2" +background-color = "#1d2021" + +ansi-colors-black = "#1d2021" +ansi-colors-red = "#cc241d" +ansi-colors-green = "#98971a" +ansi-colors-yellow = "#d79921" +ansi-colors-blue = "#458588" +ansi-colors-purple = "#b16286" +ansi-colors-cyan = "#689d6a" +ansi-colors-white = "#a89984" +ansi-colors-bright-black = "#928374" +ansi-colors-bright-red = "#fb4934" +ansi-colors-bright-green = "#b8bb26" +ansi-colors-bright-yellow = "#fabd2f" +ansi-colors-bright-blue = "#83a598" +ansi-colors-bright-purple = "#d3869b" +ansi-colors-bright-cyan = "#8ec07c" +ansi-colors-bright-white = "#ebdbb2"