You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
447 lines
14 KiB
447 lines
14 KiB
#!/usr/bin/env bash |
|
# Copyright (c) 2016-present Arctic Ice Studio <development@arcticicestudio.com> |
|
# Copyright (c) 2016-present Sven Greb <code@svengreb.de> |
|
|
|
# Project: Nord GNOME Terminal |
|
# Repository: https://github.com/arcticicestudio/nord-gnome-terminal |
|
# License: MIT |
|
|
|
set -e |
|
|
|
# Appends the given profile UUID to the profile list. |
|
# |
|
# @param $1 the UUID to be appended |
|
# @return none |
|
# @since 0.2.0 |
|
append_profile_uuid_to_list() { |
|
local uuid list |
|
uuid="$1" |
|
list=$(gsettings get "$GSETTINGS_PROFILELIST_PATH" list) |
|
gsettings set "$GSETTINGS_PROFILELIST_PATH" list "${list%]*}, '$uuid']" |
|
} |
|
|
|
# Writes the Nord GNOME Terminal theme colors and configurations as dconf key-value pairs to the target profile. |
|
# |
|
# @globread profile_name |
|
# @return none |
|
# @since 0.2.0 |
|
apply() { |
|
local \ |
|
nord0="#2E3440" \ |
|
nord1="#3B4252" \ |
|
nord3="#4C566A" \ |
|
nord4="#D8DEE9" \ |
|
nord5="#E5E9F0" \ |
|
nord6="#ECEFF4" \ |
|
nord7="#8FBCBB" \ |
|
nord8="#88C0D0" \ |
|
nord9="#81A1C1" \ |
|
nord11="#BF616A" \ |
|
nord13="#EBCB8B" \ |
|
nord14="#A3BE8C" \ |
|
nord15="#B48EAD" |
|
local \ |
|
nord0_rgb="rgb(46,52,64)" |
|
nord1_rgb="rgb(59,66,82)" |
|
nord4_rgb="rgb(216,222,233)" |
|
nord8_rgb="rgb(136,192,208)" |
|
|
|
_write palette "['$nord1', '$nord11', '$nord14', '$nord13', '$nord9', '$nord15', '$nord8', '$nord5', '$nord3', '$nord11', '$nord14', '$nord13', '$nord9', '$nord15', '$nord7', '$nord6']" |
|
log 4 "Applied Nord color palette" |
|
|
|
_write background-color "'$nord0'" |
|
_write foreground-color "'$nord4'" |
|
_write use-transparent-background "false" |
|
log 4 "Applied background- and foreground colors" |
|
|
|
_write bold-color "'$nord4'" |
|
_write bold-color-same-as-fg "true" |
|
log 4 "Applied bold color and configuration" |
|
|
|
_write use-theme-colors "false" |
|
_write use-theme-background "false" |
|
_write use-theme-transparency "false" |
|
log 4 "Applied system theme compability configuration" |
|
|
|
_write cursor-colors-set "true" |
|
_write cursor-foreground-color "'$nord1_rgb'" |
|
_write cursor-background-color "'$nord4_rgb'" |
|
log 4 "Applied cursor colors and configuration" |
|
|
|
_write highlight-colors-set "true" |
|
_write highlight-foreground-color "'$nord0_rgb'" |
|
_write highlight-background-color "'$nord8_rgb'" |
|
log 4 "Applied highlight colors and configuration" |
|
|
|
_write "$NORD_GNOME_TERMINAL_VERSION_DCONF_KEY" "'$NORD_GNOME_TERMINAL_VERSION'" |
|
log 4 "Set Nord GNOME Terminal version key of the '$profile_name' profile" |
|
|
|
log 3 "Applied theme colors and configurations" |
|
} |
|
|
|
# Applies the Nord GNOME Terminal theme with version comparison. |
|
# |
|
# @param $1 the version string to compare against |
|
# @return none |
|
# @since 0.2.0 |
|
apply_version_compared() { |
|
local version |
|
version=$1 |
|
case "$(vercomp "$NORD_GNOME_TERMINAL_VERSION" "$version"; echo $?)" in |
|
0) |
|
log 3 "Reinstalling Nord GNOME Terminal since the version equaled the version of the '$profile_name' profile!"; |
|
apply; |
|
log 2 "Reinstalled Nord GNOME Terminal version $NORD_GNOME_TERMINAL_VERSION for the '$profile_name' profile!"; |
|
exit 0;; |
|
1) |
|
log 4 "The script version is newer than the currently installed theme ($NORD_GNOME_TERMINAL_VERSION > $version)" |
|
apply; |
|
log 2 "The '$profile_name' profile has been updated successfully from version $version to $NORD_GNOME_TERMINAL_VERSION"; |
|
exit 0;; |
|
2) |
|
log 1 "The detected Nord GNOME Terminal version $version of the '$profile_name' profile is greater than the version that will be applied!"; |
|
printf "${_ctb}> [?]${_ct} Override current profile version %s with script version %s? (${_ctb}y${_cr}/${_ctb}n${_cr})" "$version" "$NORD_GNOME_TERMINAL_VERSION" |
|
read -r -n 1 -s confirmation; |
|
echo |
|
case $confirmation in |
|
[Yy]* ) |
|
apply; |
|
log 2 "Nord GNOME Terminal version $NORD_GNOME_TERMINAL_VERSION has been successfully applied!"; |
|
exit 0;; |
|
[Nn]* ) |
|
log 0 "Installation canceled by user!"; |
|
exit 1;; |
|
* ) |
|
log 0 "'$confirmation' is not a valid input!"; |
|
exit 1;; |
|
esac |
|
esac |
|
} |
|
|
|
# Checks the GNOME Terminal version for the required migration compability (>= 3.8). |
|
# |
|
# @globwrite gnome_terminal_version |
|
# @return 0 if the version is compatible (>= 3.8), 1 otherwise |
|
# @since 0.2.0 |
|
check_migrated_version_comp() { |
|
gnome_terminal_version="$(expr "$(LANGUAGE=en_US.UTF-8 gnome-terminal --version)" : '^[^[:digit:]]* \(\([[:digit:]]*\.*\)*\)')" |
|
if [[ ("$(echo "$gnome_terminal_version" | cut -d"." -f1)" = "3" && \ |
|
"$(echo "$gnome_terminal_version" | cut -d"." -f2)" -ge 8) || \ |
|
"$(echo "$gnome_terminal_version" | cut -d"." -f1)" -ge 4 ]]; then |
|
log 3 "Detected compatible GNOME Terminal version $gnome_terminal_version (>= 3.8 dconf migrated)" |
|
return 0 |
|
else |
|
log 1 "Detected incompatible GNOME Terminal version $gnome_terminal_version (< 3.8)" |
|
return 1 |
|
fi |
|
} |
|
|
|
# Cleans up the script execution by unsetting declared functions and variables. |
|
# |
|
# @return none |
|
# @since 0.2.0 |
|
cleanup() { |
|
log 4 "Cleaning up script execution by unsetting declared functions and variables" |
|
unset -v _cr _ct _ctb _ct_highlight _ct_primary _ctb_error _ctb_highlight _ctb_primary _ctb_success _ctb_warning |
|
unset -v NORD_GNOME_TERMINAL_SCRIPT_OPTS NORD_GNOME_TERMINAL_VERSION NORD_GNOME_TERMINAL_VERSION_DCONF_KEY NORD_PROFILE_VISIBLE_NAME log_level DEPENDENCIES DCONF_PROFILE_BASE_PATH GSETTINGS_PROFILELIST_PATH gnome_terminal_version profile_name profile_uuid |
|
unset -f append_profile_uuid_to_list apply check_migrated_version_comp cleanup clone_default_profile get_profiles get_profile_uuid_by_name log print_help validate_dependencies vercomp _write |
|
} |
|
|
|
# Clones the default profile, generates and saves the new UUID and adds it to the profile list. |
|
# |
|
# @globwrite profile_uuid |
|
# @since 0.2.0 |
|
clone_default_profile() { |
|
local uuid |
|
uuid="$(gsettings get "$GSETTINGS_PROFILELIST_PATH" default | tr -d \')" |
|
profile_uuid="$(uuidgen)" |
|
dconf dump "$DCONF_PROFILE_BASE_PATH"/:"$uuid"/ | dconf load "$DCONF_PROFILE_BASE_PATH"/:"$profile_uuid"/ |
|
dconf write "$DCONF_PROFILE_BASE_PATH"/:"$profile_uuid"/visible-name "'$NORD_PROFILE_VISIBLE_NAME'" |
|
append_profile_uuid_to_list "$profile_uuid" |
|
log 3 "Cloned the default profile '$uuid' with new UUID '$profile_uuid'" |
|
} |
|
|
|
# Gets the current Nord GNOME Terminal version. |
|
# |
|
# @globread NORD_GNOME_TERMINAL_VERSION_DCONF_KEY DCONF_PROFILE_BASE_PATH |
|
# @param $1 the UUID of the profile to check |
|
# @since 0.2.0 |
|
get_current_version() { |
|
local uuid version |
|
uuid=$1 |
|
version= |
|
printf "$(dconf read $DCONF_PROFILE_BASE_PATH/:"$uuid"/$NORD_GNOME_TERMINAL_VERSION_DCONF_KEY | tr -d "'")" |
|
return 0 |
|
} |
|
|
|
# Gets the available GNOME Terminal profiles. |
|
# |
|
# @globwrite profiles |
|
# @return none |
|
# @since 0.2.0 |
|
get_profiles() { |
|
profiles=($(gsettings get "$GSETTINGS_PROFILELIST_PATH" list | tr -d "[]\',")) |
|
log 3 "Available profile UUIDs: ${profiles[*]}" |
|
} |
|
|
|
# Gets the UUID for the given profile name. |
|
# |
|
# @param $1 the name of the profile to get the UUID from |
|
# @return the UUID of the profile, none otherwise |
|
# @since 0.2.0 |
|
get_profile_uuid_by_name() { |
|
local name=$1 |
|
for idx in "${!profiles[@]}"; do |
|
if [[ "$(dconf read "$DCONF_PROFILE_BASE_PATH"/:"${profiles[idx]}"/visible-name)" == "'$name'" ]]; then |
|
printf "%s" "${profiles[idx]}" |
|
return 0 |
|
fi |
|
done |
|
} |
|
|
|
# Prints a message with a prefixed label to STDOUT/STDERR for the given log level. |
|
# |
|
# When no log level is specified, "DEFAULT" is used. |
|
# The minimum log level is defined by the "log_level" global. |
|
# |
|
# Log Levels: |
|
# 0 ERROR |
|
# 1 WARNING |
|
# 2 SUCCESS |
|
# 3 INFO |
|
# 4 DEBUG |
|
# |
|
# @globread |
|
# log_level |
|
# _cr |
|
# _ct |
|
# _ctb |
|
# _ctb_error |
|
# _ctb_highlight |
|
# _ctb_primary |
|
# _ctb_success |
|
# _ctb_warning |
|
# @return none |
|
# @since 0.2.0 |
|
log () { |
|
declare -a label color |
|
local num_regex='^[0-9]+$' |
|
local level=$1 |
|
label=([0]="[ERR]" [1]="[WARN]" [2]="[SUCCESS]" [3]="[INFO]" [4]="[DEBUG]") |
|
color=([0]="$_ctb_error" [1]="$_ctb_warning" [2]="$_ctb_success" [3]="$_ctb_primary" [4]="$_ctb_highlight") |
|
|
|
if [[ $level =~ $num_regex ]]; then |
|
shift |
|
if [[ -n ${log_level} && ${log_level} -ge ${level} ]]; then |
|
printf "${color[$level]}${label[$level]} ${_ct}%s${_cr}\n" "$@" |
|
fi |
|
else |
|
printf "${_ctb}> ${_ct}%s${_cr}\n" "$@" |
|
fi |
|
} |
|
|
|
# Prints the help- and usage information. |
|
# |
|
# @return none |
|
# @since 0.2.0 |
|
print_help() { |
|
echo -e -n "\ |
|
\r${_ctb}Usage: ${_ct_primary}${0##*/} ${_ctb_subtle}[OPTIONS] |
|
${_ctb_highlight}-h${_ct},${_ctb_highlight} --help ${_ct} |
|
Show the help |
|
|
|
${_ctb_highlight}-l${_ct},${_ctb_highlight} --loglevel <LOG_LEVEL>${_ct},${_ctb_highlight} --loglevel=<LOG_LEVEL> ${_ct} |
|
Set the log level |
|
${_ctb_primary}0 ${_ctb}ERROR${_cr} The script will run in silent mode, only error messages are shown |
|
${_ctb_primary}1 ${_ctb}WARNING${_cr} Shows warning messages |
|
${_ctb_primary}2 ${_ctb}SUCCESS${_cr} Shows success messages (default) |
|
${_ctb_primary}3 ${_ctb}INFO${_cr} Shows additional information messages |
|
${_ctb_primary}4 ${_ctb}DEBUG${_cr} Runs the script in debug mode showing additional debug messages |
|
|
|
${_ctb_highlight}-p${_ct},${_ctb_highlight} --profile <PROFILE_NAME>${_ct},${_ctb_highlight} --profile=<PROFILE_NAME>${_ct} |
|
The name of the profile to install the theme to. If not specified a new profile as clone of the 'default' profile will be created.${_cr}\n" |
|
} |
|
|
|
# Validates all required dependencies. |
|
# |
|
# @param $1 array of required dependencies to validate |
|
# @return 0 if all required dependencies are validated, 1 otherwise |
|
# @since 0.2.0 |
|
validate_dependencies() { |
|
declare -a missing_deps deps=("${!1}") |
|
for exec in "${deps[@]}"; do |
|
if ! command -v "${exec}" > /dev/null 2>&1; then |
|
missing_deps+=(${exec}) |
|
fi |
|
done |
|
if [ ${#missing_deps[*]} -eq 0 ]; then |
|
log 3 "Validated required dependencies: ${deps[*]}" |
|
return 0 |
|
else |
|
log 1 "Missing required dependencies: ${_ct_highlight}${missing_deps[*]}${_cr}" |
|
return 1 |
|
fi |
|
} |
|
|
|
# Compares whether the given version string is greater than, equal to or less than the given comparative version string. |
|
# |
|
# @param $1 the version string to be compared |
|
# @param $2 the version string to compare against |
|
# @return 0 if the versions are equal, 1 if the version is greater or 2 if the version is less than the comparative |
|
# version |
|
# @ since 0.2.0 |
|
vercomp() { |
|
# v1 equals v2 |
|
if [[ "$1" == "$2" ]]; then |
|
return 0 |
|
fi |
|
|
|
local IFS=. |
|
local i v1=($1) v2=($2) |
|
|
|
# Fill empty fields with zeros |
|
for ((i=${#v1[@]}; i<${#v2[@]}; i++)); do |
|
v1[i]=0 |
|
done |
|
|
|
for ((i=0; i<${#v1[@]}; i++)); do |
|
if [[ -z ${v2[i]} ]]; then |
|
# Fill empty fields with zeros |
|
v2[i]=0 |
|
fi |
|
|
|
# v1 is greater than v2 |
|
if ((10#${v1[i]} > 10#${v2[i]})); then |
|
return 1 |
|
fi |
|
# v1 is less than v2 |
|
if ((10#${v1[i]} < 10#${v2[i]})); then |
|
return 2 |
|
fi |
|
done |
|
return 0 |
|
} |
|
|
|
# Shorthand function to write the given key-value pair to the profile. |
|
# |
|
# @globread DCONF_PROFILE_BASE_PATH profile_uuid |
|
# @param $1 the profile key to be written |
|
# @param $2 the value to be assigned to the given profile key |
|
# @return none |
|
# @since 0.2.0 |
|
_write() { |
|
local key="$1" |
|
local value="$2" |
|
dconf write "$DCONF_PROFILE_BASE_PATH/:$profile_uuid/$key" "$value" |
|
} |
|
|
|
# Catches terminal interrupt- and termination signals and prints a message before exiting the script execution. |
|
# |
|
# @return 1 |
|
# @since 0.2.0 |
|
trap 'printf "${_ctb_error}User aborted.${_cr}\n" && exit 1' SIGINT SIGTERM |
|
|
|
# Exit hook that runs the 'cleanup' function before exiting the script. |
|
# |
|
# @since 0.2.0 |
|
trap cleanup EXIT |
|
|
|
declare -a DEPENDENCIES profiles |
|
|
|
_cr="\e[0m" |
|
_ct="\e[0;37m" |
|
_ctb="\e[1;37m" |
|
_ct_highlight="\e[0;34m" |
|
_ct_primary="\e[0;36m" |
|
_ctb_error="\e[1;31m" |
|
_ctb_highlight="\e[1;34m" |
|
_ctb_primary="\e[1;36m" |
|
_ctb_subtle="\e[1;30m" |
|
_ctb_success="\e[1;32m" |
|
_ctb_warning="\e[1;33m" |
|
|
|
NORD_GNOME_TERMINAL_SCRIPT_OPTS=$(getopt -o hl:p: --long help,loglevel:,profile: -n 'nord.sh' -- "$@") |
|
NORD_GNOME_TERMINAL_VERSION=0.1.0 |
|
NORD_GNOME_TERMINAL_VERSION_DCONF_KEY=nord-gnome-terminal-version |
|
NORD_PROFILE_VISIBLE_NAME="Nord" |
|
log_level=2 |
|
|
|
# List of required executable dependencies |
|
DEPENDENCIES=(dconf expr gsettings uuidgen) |
|
|
|
# The dconf- and GSettings paths |
|
DCONF_PROFILE_BASE_PATH=/org/gnome/terminal/legacy/profiles: |
|
GSETTINGS_PROFILELIST_PATH=org.gnome.Terminal.ProfilesList |
|
|
|
# The detected GNOME Terminal version |
|
gnome_terminal_version= |
|
|
|
# The profile name and UUID to apply the theme on |
|
profile_name= |
|
profile_uuid= |
|
|
|
eval set -- "$NORD_GNOME_TERMINAL_SCRIPT_OPTS" |
|
while true; do |
|
case "$1" in |
|
--loglevel=* ) log_level=${1#*=}; shift ;; |
|
-l | --loglevel ) log_level=$2; shift ;; |
|
-h | --help ) print_help; exit 0; break ;; |
|
--profile=* ) profile_name=${1#*=}; shift ;; |
|
-p | --profile ) profile_name=$2; shift ;; |
|
-- ) shift; break ;; |
|
* ) break ;; |
|
esac |
|
shift |
|
done |
|
|
|
if validate_dependencies DEPENDENCIES[@]; then |
|
|
|
if ! check_migrated_version_comp; then |
|
log 0 "The installed GNOME Terminal version '$gnome_terminal_version' is not compatible with the required (dconf migrated) version >= 3.8!" |
|
exit 1 |
|
fi |
|
|
|
# Check for available profiles and validate that at least the default profile is available |
|
get_profiles |
|
if [[ ${#profiles[*]} -eq 0 ]]; then |
|
log 1 "No profiles found!" |
|
log 0 "There must be at least one default profile!" |
|
exit 1 |
|
fi |
|
|
|
# Validate- and resolve the UUID if a profile name has been passed |
|
if [[ -n $profile_name ]]; then |
|
profile_uuid="$(get_profile_uuid_by_name "$profile_name")" |
|
if [[ -n $profile_uuid ]]; then |
|
log 3 "Resolved profile '$profile_name' to UUID '$profile_uuid'" |
|
curr_ver="$(get_current_version "$profile_uuid")" |
|
if [[ -n $curr_ver ]]; then |
|
apply_version_compared "$curr_ver" |
|
else |
|
apply |
|
log 2 "Nord GNOME Terminal version $NORD_GNOME_TERMINAL_VERSION has been successfully applied to the '$profile_name' profile" |
|
exit 0 |
|
fi |
|
else |
|
log 0 "$profile_name is not a valid profile name!"; |
|
exit 1 |
|
fi |
|
fi |
|
|
|
# Check for an already existing 'Nord' profile and update it |
|
profile_uuid="$(get_profile_uuid_by_name $NORD_PROFILE_VISIBLE_NAME)" |
|
if [[ -n $profile_uuid ]]; then |
|
profile_name="$NORD_PROFILE_VISIBLE_NAME" |
|
log 4 "Found already existing '$NORD_PROFILE_VISIBLE_NAME' profile with UUID '$profile_uuid'" |
|
log "Updating already existing '$NORD_PROFILE_VISIBLE_NAME' profile" |
|
apply_version_compared "$(get_current_version $profile_uuid)" |
|
fi |
|
|
|
clone_default_profile |
|
apply |
|
log 2 "Nord GNOME Terminal version $NORD_GNOME_TERMINAL_VERSION has been successfully applied to the newly created '$NORD_PROFILE_VISIBLE_NAME' profile" |
|
exit 0 |
|
else |
|
log 0 "Required dependencies were not fulfilled: ${DEPENDENCIES[*]}" |
|
exit 1 |
|
fi
|
|
|