From 09cfced24745dd7aea086a292ab042f070ce4fbb Mon Sep 17 00:00:00 2001 From: Mark Vander Stel Date: Mon, 16 Nov 2020 12:09:33 -0500 Subject: [PATCH] Rework color code generation The actual escape sequence generation is the same, but add a new function lp_terminal_format(), which generates a static sequence for formatting the terminal. It is designed for alternate themes, with Powerline specifically in mind. The function will return nothing if tput is not available. --- liquidprompt | 192 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 129 insertions(+), 63 deletions(-) diff --git a/liquidprompt b/liquidprompt index 3be52930..5a4847c4 100755 --- a/liquidprompt +++ b/liquidprompt @@ -121,104 +121,67 @@ _LP_SED_EXTENDED=r # 3. Load the configuration __lp_source_config() { - # TermInfo feature detection - typeset -a af_colors ab_colors - local af_color ab_color - - # TODO handle this case better. With no colors, no need for any escaping - if ! command -v tput >/dev/null; then - echo "liquidprompt: 'tput' not available; will not be able to format terminal" >&2 - fi - - local ti_sgr0="$( { tput sgr0 || tput me ; } 2>/dev/null )" - local ti_bold="$( { tput bold || tput md ; } 2>/dev/null )" - _LP_TI_BELL="$( { tput bel || tput bl ; } 2>/dev/null )" - if tput setaf 0 >/dev/null 2>&1; then - foreground_color() { af_color="${af_colors[$1+1]:=$(tput setaf "$1")}"; } - elif tput AF 0 >/dev/null 2>&1; then - # FreeBSD - foreground_color() { af_color="${af_colors[$1+1]:=$(tput AF "$1")}"; } - elif tput AF 0 0 0 >/dev/null 2>&1; then - # OpenBSD - foreground_color() { af_color="${af_colors[$1+1]:=$(tput AF "$1" 0 0)}"; } - else - echo "liquidprompt: terminal $TERM does not support foreground colors" >&2 - foreground_color() { : ; } - fi - if tput setab 0 >/dev/null 2>&1; then - background_color() { ab_color="${ab_colors[$1+1]:=$(tput setab "$1")}"; } - elif tput AB 0 >/dev/null 2>&1; then - # FreeBSD - background_color() { ab_color="${ab_colors[$1+1]:=$(tput AB "$1")}"; } - elif tput AB 0 0 0 >/dev/null 2>&1; then - # OpenBSD - background_color() { ab_color="${ab_colors[$1+1]:=$(tput AB "$1" 0 0)}"; } - else - echo "liquidprompt: terminal $TERM does not support background colors" >&2 - background_color() { : ; } - fi + local af_color= ab_color= # Colors: variables are local so they will have a value only # during config loading and will not conflict with other values # with the same names defined by the user outside the config. - local BOLD="${_LP_OPEN_ESC}${ti_bold}${_LP_CLOSE_ESC}" + local BOLD="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${_LP_CLOSE_ESC}" # Foreground colors - foreground_color 0 + __lp_foreground_color 0 local BLACK="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_GRAY="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_GRAY="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" - foreground_color 1 + __lp_foreground_color 1 local RED="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_RED="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" - foreground_color 0 - background_color 1 + local BOLD_RED="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" + __lp_foreground_color 0 + __lp_background_color 1 local WARN_RED="${_LP_OPEN_ESC}${af_color}${ab_color}${_LP_CLOSE_ESC}" - foreground_color 7 - local CRIT_RED="${_LP_OPEN_ESC}${ti_bold}${af_color}${ab_color}${_LP_CLOSE_ESC}" - foreground_color 3 - local DANGER_RED="${_LP_OPEN_ESC}${ti_bold}${af_color}${ab_color}${_LP_CLOSE_ESC}" + __lp_foreground_color 7 + local CRIT_RED="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${ab_color}${_LP_CLOSE_ESC}" + __lp_foreground_color 3 + local DANGER_RED="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${ab_color}${_LP_CLOSE_ESC}" - foreground_color 2 + __lp_foreground_color 2 local GREEN="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_GREEN="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_GREEN="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" - foreground_color 3 + __lp_foreground_color 3 local YELLOW="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_YELLOW="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_YELLOW="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" - foreground_color 4 + __lp_foreground_color 4 local BLUE="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_BLUE="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_BLUE="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" - foreground_color 5 + __lp_foreground_color 5 local PURPLE="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" local MAGENTA="${PURPLE}" - local PINK="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local PINK="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" local BOLD_PURPLE="${PINK}" local BOLD_MAGENTA="${PINK}" - foreground_color 6 + __lp_foreground_color 6 local CYAN="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_CYAN="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_CYAN="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" - foreground_color 7 + __lp_foreground_color 7 local WHITE="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - local BOLD_WHITE="${_LP_OPEN_ESC}${ti_bold}${af_color}${_LP_CLOSE_ESC}" + local BOLD_WHITE="${_LP_OPEN_ESC}${_LP_TI_BOLD-}${af_color}${_LP_CLOSE_ESC}" # NO_COL is special: it will be used at runtime, not just during config loading - NO_COL="${_LP_OPEN_ESC}${ti_sgr0}${_LP_CLOSE_ESC}" + NO_COL="${_LP_OPEN_ESC}${_LP_TI_RESET-}${_LP_CLOSE_ESC}" # compute the hash of the hostname # and get the corresponding number in [1-6] (red,green,yellow,blue,purple or cyan) # FIXME Add more formats (bold? 256 colors?) # cksum is separated with tab on SunOS, space on others local cksum="$(hostname | cksum)" - foreground_color "$(( 1 + ${cksum%%[$' \t']*} % 6 ))" + __lp_foreground_color "$(( 1 + ${cksum%%[$' \t']*} % 6 ))" LP_COLOR_HOST_HASH="${_LP_OPEN_ESC}${af_color}${_LP_CLOSE_ESC}" - unset -f foreground_color background_color - # Default values (globals) LP_BATTERY_THRESHOLD=${LP_BATTERY_THRESHOLD:-75} @@ -261,6 +224,7 @@ __lp_source_config() { LP_ENABLE_FQDN=${LP_ENABLE_FQDN:-0} LP_DISABLED_VCS_PATHS=("${LP_DISABLED_VCS_PATHS[@]-}") LP_ENABLE_SUDO=${LP_ENABLE_SUDO:-0} + LP_ENABLE_COLOR=${LP_ENABLE_COLOR:-1} LP_MARK_DEFAULT="${LP_MARK_DEFAULT:-$_LP_MARK_SYMBOL}" LP_MARK_BATTERY="${LP_MARK_BATTERY:-"⌁"}" @@ -406,6 +370,52 @@ lp_activate() { } >/dev/null fi + # TermInfo feature detection + _lp_af_colors=() _lp_ab_colors=() + + __lp_foreground_color() { return 2 ; } + __lp_background_color() { return 2 ; } + + # TODO handle this case better. With no colors, no need for any escaping + if ! command -v tput >/dev/null; then + echo "liquidprompt: 'tput' not available; will not be able to format terminal" >&2 + LP_ENABLE_COLOR=0 + else + _LP_TI_RESET="$( { tput sgr0 || tput me ; } 2>/dev/null )" + _LP_TI_BOLD="$( { tput bold || tput md ; } 2>/dev/null )" + _LP_TI_UNDERLINE="$( { tput smul || tput us ; } 2>/dev/null )" + _LP_TI_COLORS="$( tput colors 2>/dev/null )" + _LP_TI_COLORS=${_LP_TI_COLORS:-8} + + _LP_TI_BELL="$( { tput bel || tput bl ; } 2>/dev/null )" + + if tput setaf 0 >/dev/null 2>&1; then + __lp_foreground_color() { af_color="${_lp_af_colors[$1+1]:=$(tput setaf "$1")}"; } + elif tput AF 0 >/dev/null 2>&1; then + # FreeBSD + __lp_foreground_color() { af_color="${_lp_af_colors[$1+1]:=$(tput AF "$1")}"; } + elif tput AF 0 0 0 >/dev/null 2>&1; then + # OpenBSD + __lp_foreground_color() { af_color="${_lp_af_colors[$1+1]:=$(tput AF "$1" 0 0)}"; } + else + echo "liquidprompt: terminal $TERM does not support foreground colors" >&2 + fi + if tput setab 0 >/dev/null 2>&1; then + __lp_background_color() { ab_color="${_lp_ab_colors[$1+1]:=$(tput setab "$1")}"; } + elif tput AB 0 >/dev/null 2>&1; then + # FreeBSD + __lp_background_color() { ab_color="${_lp_ab_colors[$1+1]:=$(tput AB "$1")}"; } + elif tput AB 0 0 0 >/dev/null 2>&1; then + # OpenBSD + __lp_background_color() { ab_color="${_lp_ab_colors[$1+1]:=$(tput AB "$1" 0 0)}"; } + else + echo "liquidprompt: terminal $TERM does not support background colors" >&2 + fi + fi + + # If tput doesn't exist or lookup failed, still try to send bell + _LP_TI_BELL=${_LP_TI_BELL:-$'\a'} + __lp_source_config # Disable feature if the tool is not installed @@ -615,6 +625,62 @@ _lp_sb() { [[ -n "$1" ]] && echo -nE " $1 " } +# Generates a terminal escape sequence to format the terminal. +lp_terminal_format() { # fg, bg, bold, underline, fallback_fg, fallback_bg + lp_terminal_format= + (( LP_ENABLE_COLOR )) || return 2 + + local af_color ab_color fg=$1 bg=${2:-"-1"} previous_af_color=${_lp_last_af_color-} + + lp_terminal_format=${_LP_OPEN_ESC}${_LP_TI_RESET} + + if (( $fg >= _LP_TI_COLORS )) && [[ -n ${5-} ]]; then + _lp_last_af_color=$5 + elif (( $fg == -2 )); then + : # do nothing, _lp_last_af_color already correct + elif (( $fg == -3 )); then + _lp_last_af_color=$_lp_last_ab_color + elif (( $fg >= 0 )); then + _lp_last_af_color=$fg + else # -1 + _lp_last_af_color=-1 + fi + + if (( ${_lp_last_af_color:-"-1"} >= 0 )); then + __lp_foreground_color "$_lp_last_af_color" && lp_terminal_format+=$af_color + fi + + if (( $bg >= _LP_TI_COLORS )) && [[ -n ${6-} ]]; then + _lp_last_ab_color=$6 + elif (( $bg == -2 )); then + : # do nothing, _lp_last_ab_color already correct + elif (( $bg == -3 )); then + _lp_last_ab_color=$previous_af_color + elif (( $bg >= 0 )); then + _lp_last_ab_color=$bg + else # -1 + _lp_last_ab_color=-1 + fi + + if (( ${_lp_last_ab_color:-"-1"} >= 0 )); then + __lp_background_color "$_lp_last_ab_color" && lp_terminal_format+=$ab_color + fi + + # It turns out there are sequences to reset bold and underline to normal + # (\E[22m and \E[24m in xterm), but they aren't universally supported. This + # means we must reset to all defaults then enable if they are wanted. + # Explicit is safer anyway. + if (( ${3:-0} )); then + lp_terminal_format+=$_LP_TI_BOLD + fi + + if (( ${4:-0} )); then + lp_terminal_format+=$_LP_TI_UNDERLINE + fi + + lp_terminal_format+=$_LP_CLOSE_ESC +} + ########################## # Working Directory Path # ##########################