| @ -0,0 +1,242 @@ | |||
| #!/bin/bash | |||
| # vim: tw=80 ts=2 sw=2: | |||
| set -eu | |||
| 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}'" | |||
| done | |||
| echo "]" | |||
| } | |||
| # colorscheme NAME FG_COLOR BG_COLOR ANSI_COLORS | |||
| function colorscheme() { | |||
| NAME="$1" | |||
| FG_COLOR="$2" | |||
| BG_COLOR="$3" | |||
| ANSI_COLORS="$4" | |||
| echo "${NAME};${FG_COLOR};${BG_COLOR};${ANSI_COLORS}" | |||
| } | |||
| function unpack_colorscheme_field(){ | |||
| PACKED="$1" | |||
| FIELD="$2" | |||
| echo "${PACKED}" | cut -d ';' -f "${FIELD}" | |||
| } | |||
| # colorscheme_name COLORSCHEME | |||
| function colorscheme_name() { | |||
| unpack_colorscheme_field "$1" 1 | |||
| } | |||
| # colorscheme_fg_color COLORSCHEME | |||
| function colorscheme_fg_color() { | |||
| unpack_colorscheme_field "$1" 2 | |||
| } | |||
| # colorscheme_bg_color COLORSCHEME | |||
| function colorscheme_bg_color() { | |||
| unpack_colorscheme_field "$1" 3 | |||
| } | |||
| # colorscheme_ansi_colors COLORSCHEME | |||
| function colorscheme_ansi_colors() { | |||
| unpack_colorscheme_field "$1" 4 | |||
| } | |||
| GRUVBOX8_COLORSCHEME=$(colorscheme "gruvbox8" \ | |||
| "#ebdbb2" \ | |||
| "#1d2021" \ | |||
| $(ansi_colors \ | |||
| "#1d2021" \ | |||
| "#cc241d" \ | |||
| "#98971a" \ | |||
| "#d79921" \ | |||
| "#458588" \ | |||
| "#b16286" \ | |||
| "#689d6a" \ | |||
| "#a89984" \ | |||
| "#928374" \ | |||
| "#fb4934" \ | |||
| "#b8bb26" \ | |||
| "#fabd2f" \ | |||
| "#83a598" \ | |||
| "#d3869b" \ | |||
| "#8ec07c" \ | |||
| "#ebdbb2" | |||
| ) | |||
| ) | |||
| COLORSCHEMES=( | |||
| "${GRUVBOX8_COLORSCHEME}" | |||
| ) | |||
| # log ARGS... | |||
| # echo for stderr | |||
| function log() { | |||
| echo 1>&2 "$@" | |||
| } | |||
| # die ARGS... | |||
| # log then exit with an error code | |||
| function die() { | |||
| log "$@" | |||
| exit 1 | |||
| } | |||
| function get_profile_property() { | |||
| PROFILE="$1" | |||
| PROPERTY="$2" | |||
| dconf read "${PROFILE}${PROPERTY}" | |||
| } | |||
| # 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" | |||
| } | |||
| # 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. | |||
| 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 | |||
| continue | |||
| fi | |||
| if [ "${CHOSEN_NUMBER}" -gt "${MAX_NUMBER}" ]; then | |||
| continue | |||
| fi | |||
| echo "${CHOSEN_NUMBER}" | |||
| break | |||
| done | |||
| } | |||
| # choose_profile | |||
| # Echoes the path to a valid gnome-terminal profile to modify. | |||
| function choose_profile() { | |||
| # Build an array of profile subdirectories. | |||
| PROFILES=() | |||
| for PROFILE_SUBDIR in $(dconf list "${ROOT_DCONF_DIR}"); do | |||
| 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}") | |||
| 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}") | |||
| 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" | |||
| 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 | |||
| # by name or UUID. If unspecified, the program searches for profiles. If there | |||
| # exists a single profile, the program uses it. Otherwise, an interactive | |||
| # choice is presented to the user. | |||
| # | |||
| # - font get | |||
| # - font set FONT | |||
| # - foreground-color get | |||
| # - foreground-color set COLOR | |||
| # - background-color get | |||
| # - background-color set COLOR | |||
| # - palette get | |||
| # - palette set COLORS | |||
| # - colorscheme show NAME | |||
| # - colorscheme apply NAME | |||
| # | |||
| # The colorscheme subcommand should probably read colorschemes from files | |||
| # instead, for easier integration with other people's colorschemes. Otherwise | |||
| # all colorschemes need to be defined in this script. The main question is the | |||
| # file format. We'd like something easy enough to write, that does not execute | |||
| # 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}") | |||
| PROFILE=$(choose_profile) | |||
| apply_colorscheme "${PROFILE}" "${COLORSCHEME}" | |||
| } | |||
| main "$@" | |||