@ -3,106 +3,246 @@
set -eu
set -eu
# CONSTANTS
# =========
# DConf directory in which gnome-terminal profile configuration is stored.
ROOT_DCONF_DIR = '/org/gnome/terminal/legacy/profiles:/'
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
done
echo "]"
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 "
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
# choose_number BASE_PROMPT MIN MAX
# Asks the user to choose a number between MIN and MAX, inclusive.
# Asks the user to choose a number between MIN and MAX, inclusive.
# BASE_PROMPT should not end in a newline.
# BASE_PROMPT should not end in a newline.
@ -110,6 +250,7 @@ function choose_number() {
PROMPT = " $1 "
PROMPT = " $1 "
MIN_NUMBER = " $2 "
MIN_NUMBER = " $2 "
MAX_NUMBER = " $3 "
MAX_NUMBER = " $3 "
while true; do
while true; do
read -p " $1 [ ${ MIN_NUMBER } to ${ MAX_NUMBER } ]: " CHOSEN_NUMBER
read -p " $1 [ ${ MIN_NUMBER } to ${ MAX_NUMBER } ]: " CHOSEN_NUMBER
if [ " ${ CHOSEN_NUMBER } " -lt " ${ MIN_NUMBER } " ] ; then
if [ " ${ CHOSEN_NUMBER } " -lt " ${ MIN_NUMBER } " ] ; then
@ -133,81 +274,42 @@ function choose_profile() {
PROFILES += ( " ${ ROOT_DCONF_DIR } ${ PROFILE_SUBDIR } " )
PROFILES += ( " ${ ROOT_DCONF_DIR } ${ PROFILE_SUBDIR } " )
done
done
NUM_PROFILES = " ${# PROFILES [@] } "
NUM_PROFILES = " ${# PROFILES [@] } "
if [ " ${ NUM_PROFILES } " -eq 0 ] ; then
if [ " ${ NUM_PROFILES } " -eq 0 ] ; then
die "Error: found no gnome-terminal profiles to style."
die "Error: found no gnome-terminal profiles to style."
fi
fi
if [ " ${ NUM_PROFILES } " -eq 1 ] ; then
if [ " ${ NUM_PROFILES } " -eq 1 ] ; then
PROFILE = " ${ PROFILES [0] } "
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. "
log " Found single gnome-terminal profile ${ PROFILE_NAME } , using it. "
echo " ${ PROFILE } "
echo " ${ PROFILE } "
return
return
fi
fi
log "Available gnome-terminal profiles:"
log "Available gnome-terminal profiles:"
for i in $( seq 1 " ${ NUM_PROFILES } " ) ; do
for i in $( seq 1 " ${ NUM_PROFILES } " ) ; do
PROFILE = " ${ PROFILES [ $(( $i - 1 )) ] } "
PROFILE = " ${ PROFILES [ $(( $i - 1 )) ] } "
PROFILE_NAME = $( get_ profile_name " ${ PROFILE } " )
PROFILE_NAME = $( profile_get _name " ${ PROFILE } " )
log " # $i : ${ PROFILE_NAME } "
log " # $i : ${ PROFILE_NAME } "
done
done
choose_number "Choose a profile" 1 " ${ NUM_PROFILES } "
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( ) {
function main( ) {
if [ " $# " -le 0 ] ; then
if [ " $# " -le 0 ] ; then
die "USAGE: style-gnome-terminal COLORSCHEME_NAM E"
die "USAGE: style-gnome-terminal CONFIG_FILE"
fi
fi
# TODO: Subcommands:
# TODO: Subcommands:
#
#
# Profiles:
# Profiles:
#
#
# - profile list
# - profile list
# - profile show NAME_OR_ID
# - profile show NAME_OR_ID
#
#
# Styling:
# Styling:
#
#
# These all take an optional [profile NAME_OR_ID] clause to specify a profile
# 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
# arbitrary code (rules our source-ing .sh files containing variables), that
# does not require onerous dependencies to parse.
# does not require onerous dependencies to parse.
COLORSCHEME_NAME = " $1 "
COLORSCHEME = $( find_colorscheme " ${ COLORSCHEME_NAME } " )
CONFIG_FILE = " $1 "
PROFILE = $( choose_profile)
PROFILE = $( choose_profile)
apply_colorscheme " ${ PROFILE } " " ${ COLORSCHEM E } "
profile_apply_config " ${ PROFILE } " " ${ CONFIG_FI LE } "
}
}
main " $@ "
main " $@ "