From 92509905ab41c0adf7297ba8b1e7d5b94944b4d2 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 9 Feb 2021 15:58:56 +0100 Subject: [PATCH] feature: add the dotmatrix theme The dotmatrix theme is basically the look of "powerline", but done right on the user experience side. The main idea is to highlight what's important, instead of displaying too much things because fancy colors everywhere is fun. To achieve that, the dotmatrix theme has been very carefully designed: - it uses three four modules: host/path, machine state, environment, version control. - it uses a consistent visual grammar (using 3 separators and 3 colors). - it follows good practices for color blindness. The current code use a similar approach to the one used for the powerline theme, but needs a refactoring. --- themes/dotmatrix/dotmatrix.theme | 887 ++++++++++++++++++ .../liquidprompt_dotmatrix_design.odt | Bin 0 -> 17088 bytes 2 files changed, 887 insertions(+) create mode 100644 themes/dotmatrix/dotmatrix.theme create mode 100644 themes/dotmatrix/liquidprompt_dotmatrix_design.odt diff --git a/themes/dotmatrix/dotmatrix.theme b/themes/dotmatrix/dotmatrix.theme new file mode 100644 index 0000000..0c819fb --- /dev/null +++ b/themes/dotmatrix/dotmatrix.theme @@ -0,0 +1,887 @@ + +######################################################################## +# API +######################################################################## + +_lp_dotmatrix_theme_activate() { + + LP_ENABLE_VCS_DIFFSTATS=${LP_ENABLE_UNCOMMITED:-0} + + DOTMATRIX_DISPLAY_TEXT=${DOTMATRIX_DISPLAY_TEXT:-"T"} + DOTMATRIX_DISPLAY_X11=${DOTMATRIX_DISPLAY_X11:-"X"} + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-"⌂"} + DOTMATRIX_MARK_STASH=${DOTMATRIX_MARK_STASH:-"✝"} + DOTMATRIX_MARK_UNTRACKED=${DOTMATRIX_MARK_UNTRACKED:-"?"} # ⛶ + DOTMATRIX_DIFF=${DOTMATRIX_DIFF:-"≠"} + + # Sets of characters + DOTMATRIX_VARIANT=${DOTMATRIX_VARIANT:-"dotmatrix"} + if [[ "${DOTMATRIX_VARIANT}" == "dotmatrix" ]] ; then + DOTMATRIX_SPACED=${DOTMATRIX_SPACED:-0} + + # Dotmatrix theme + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-"⌂"} + DOTMATRIX_USER_LOCAL=${DOTMATRIX_USER_LOCAL:-"♟"} + DOTMATRIX_VCS=${DOTMATRIX_VCS:-"╟┘"} + DOTMATRIX_MARK=${DOTMATRIX_MARK:-"■"} + DOTMATRIX_LINE=${DOTMATRIX_LINE:-"━"} + DOTMATRIX_PLUG=${DOTMATRIX_PLUG:-"▛"} + DOTMATRIX_SOFT=${DOTMATRIX_SOFT:-"╱"} + DOTMATRIX_MEAN=${DOTMATRIX_MEAN:-"▞"} + # Separator arrays (left center right + [[ -z ${DOTMATRIX_LINK[@]+x} ]] && DOTMATRIX_LINK=("▙" " " "▜") + [[ -z ${DOTMATRIX_OPEN[@]+x} ]] && DOTMATRIX_OPEN=("▙" " ▚ " "▜") + [[ -z ${DOTMATRIX_DANG[@]+x} ]] && DOTMATRIX_DANG=("▙" " □ " "▜") + [[ -z ${DOTMATRIX_ENDS[@]+x} ]] && DOTMATRIX_ENDS=("▛▞▗ ▝" "▖ ▘▞▟") + + elif [[ "${DOTMATRIX_VARIANT}" == "text" ]] ; then + DOTMATRIX_SPACED=${DOTMATRIX_SPACED:-0} + + # Dotmatrix theme + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-"lcl"} + DOTMATRIX_USER_LOCAL=${DOTMATRIX_USER_LOCAL:-"me"} + DOTMATRIX_VCS=${DOTMATRIX_VCS:-"VCS"} + DOTMATRIX_MARK=${DOTMATRIX_MARK:-">"} + DOTMATRIX_LINE=${DOTMATRIX_LINE:-"━"} + DOTMATRIX_PLUG=${DOTMATRIX_PLUG:-"▌"} + DOTMATRIX_SOFT=${DOTMATRIX_SOFT:-"╱"} + DOTMATRIX_MEAN=${DOTMATRIX_MEAN:-"┃"} + # Separator arrays (left center right + [[ -z ${DOTMATRIX_LINK[@]+x} ]] && DOTMATRIX_LINK=("▌" "<" "▐") + [[ -z ${DOTMATRIX_OPEN[@]+x} ]] && DOTMATRIX_OPEN=("▌" "<<" "▐") + [[ -z ${DOTMATRIX_DANG[@]+x} ]] && DOTMATRIX_DANG=("▌" "<<<" "▐") + [[ -z ${DOTMATRIX_ENDS[@]+x} ]] && DOTMATRIX_ENDS=("▌···" "···▐") + + + elif [[ "${DOTMATRIX_VARIANT}" == "chevron" ]] ; then + DOTMATRIX_SPACED=${DOTMATRIX_SPACED:-1} + + # Powerline chevron theme + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-""} + DOTMATRIX_USER_LOCAL=${DOTMATRIX_USER_LOCAL:-""} + DOTMATRIX_VCS=${DOTMATRIX_VCS:-""} + DOTMATRIX_MARK=${DOTMATRIX_MARK:-""} + DOTMATRIX_LINE=${DOTMATRIX_LINE:-"━"} + DOTMATRIX_PLUG=${DOTMATRIX_PLUG:-""} + DOTMATRIX_SOFT=${DOTMATRIX_SOFT:-"╱"} + DOTMATRIX_MEAN=${DOTMATRIX_MEAN:-""} + [[ -z ${DOTMATRIX_LINK[@]+x} ]] && DOTMATRIX_LINK=("" "" "") + [[ -z ${DOTMATRIX_OPEN[@]+x} ]] && DOTMATRIX_OPEN=("" "" "") + [[ -z ${DOTMATRIX_DANG[@]+x} ]] && DOTMATRIX_DANG=("" "" "") + [[ -z ${DOTMATRIX_ENDS[@]+x} ]] && DOTMATRIX_ENDS=("" "") + + elif [[ "${DOTMATRIX_VARIANT}" == "round" ]] ; then + DOTMATRIX_SPACED=${DOTMATRIX_SPACED:-1} + + # Powerline round theme + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-""} + DOTMATRIX_USER_LOCAL=${DOTMATRIX_USER_LOCAL:-""} + DOTMATRIX_VCS=${DOTMATRIX_VCS:-""} + DOTMATRIX_MARK=${DOTMATRIX_MARK:-""} + DOTMATRIX_LINE=${DOTMATRIX_LINE:-"━"} + DOTMATRIX_PLUG=${DOTMATRIX_PLUG:-""} + DOTMATRIX_SOFT=${DOTMATRIX_SOFT:-"╱"} + DOTMATRIX_MEAN=${DOTMATRIX_MEAN:-""} + [[ -z ${DOTMATRIX_LINK[@]+x} ]] && DOTMATRIX_LINK=("█" "" "") + [[ -z ${DOTMATRIX_OPEN[@]+x} ]] && DOTMATRIX_OPEN=("█" "" "") + [[ -z ${DOTMATRIX_DANG[@]+x} ]] && DOTMATRIX_DANG=("█" "" "") + [[ -z ${DOTMATRIX_ENDS[@]+x} ]] && DOTMATRIX_ENDS=("" "") + + elif [[ "${DOTMATRIX_VARIANT}" == "slant" ]] ; then + DOTMATRIX_SPACED=${DOTMATRIX_SPACED:-1} + + # Powerline slanted theme + DOTMATRIX_HOST_LOCAL=${POWERLINE_HOST_LOCAL:-""} + DOTMATRIX_USER_LOCAL=${DOTMATRIX_USER_LOCAL:-""} + DOTMATRIX_VCS=${DOTMATRIX_VCS:-""} + DOTMATRIX_MARK=${DOTMATRIX_MARK:-""} + DOTMATRIX_LINE=${DOTMATRIX_LINE:-"━"} + DOTMATRIX_PLUG=${DOTMATRIX_PLUG:-""} + DOTMATRIX_SOFT=${DOTMATRIX_SOFT:-"╱"} + DOTMATRIX_MEAN=${DOTMATRIX_MEAN:-""} + [[ -z ${DOTMATRIX_LINK[@]+x} ]] && DOTMATRIX_LINK=("" "" "") + [[ -z ${DOTMATRIX_OPEN[@]+x} ]] && DOTMATRIX_OPEN=("" "" "") + [[ -z ${DOTMATRIX_DANG[@]+x} ]] && DOTMATRIX_DANG=("" "" "") + [[ -z ${DOTMATRIX_ENDS[@]+x} ]] && DOTMATRIX_ENDS=("" "") + + fi + + # Number of spaces to add + if [[ ${DOTMATRIX_SPACED} == 0 ]] ; then + DOTMATRIX_SPACE_VOID="" + DOTMATRIX_SPACE_FILL="" + DOTMATRIX_SPACE_PATH=${DOTMATRIX_SPACE_PATH:-""} + DOTMATRIX_SPACE_FIELD=${DOTMATRIX_SPACE_FIELD:-""} + + elif [[ ${DOTMATRIX_SPACED} == 1 ]] ; then + DOTMATRIX_SPACE_VOID=" " + DOTMATRIX_SPACE_FILL="█" + DOTMATRIX_SPACE_PATH=${DOTMATRIX_SPACE_PATH:-" "} + DOTMATRIX_SPACE_FIELD=${DOTMATRIX_SPACE_FIELD:-""} + else + DOTMATRIX_SPACE_VOID=$(printf '%0.s ' $(seq 1 ${DOTMATRIX_SPACED})) # Regular space + DOTMATRIX_SPACE_FILL=$(printf '%0.s█' $(seq 1 ${DOTMATRIX_SPACED})) # Inverted space + DOTMATRIX_SPACE_PATH=${DOTMATRIX_SPACE_PATH:-"${DOTMATRIX_SPACE_VOID}"} + DOTMATRIX_SPACE_FIELD=${DOTMATRIX_SPACE_FIELD:-""} + fi + + + # Color arrays defaults fg bg b u ffg fbg + [[ -z ${DOTMATRIX_COLOR_DARK[@]+x} ]] && DOTMATRIX_COLOR_DARK=(252 239 0 0 15 0) + [[ -z ${DOTMATRIX_COLOR_LITE[@]+x} ]] && DOTMATRIX_COLOR_LITE=(239 252 0 0 0 15) + [[ -z ${DOTMATRIX_COLOR_GLOW[@]+x} ]] && DOTMATRIX_COLOR_GLOW=( 0 252 1 0 0 15) + [[ -z ${DOTMATRIX_COLOR_NOTE[@]+x} ]] && DOTMATRIX_COLOR_NOTE=( 15 33 0 0 15 12) + [[ -z ${DOTMATRIX_COLOR_WARN[@]+x} ]] && DOTMATRIX_COLOR_WARN=(196 220 1 0 0 11) + [[ -z ${DOTMATRIX_COLOR_FAIR[@]+x} ]] && DOTMATRIX_COLOR_FAIR=( 0 244 0 0 0 8) + + [[ -z ${DOTMATRIX_COLOR_PATH_SHORT[@]+x} ]] && DOTMATRIX_COLOR_PATH_SHORT=(252 239 0 0 0 15) + [[ -z ${DOTMATRIX_COLOR_PATH_VCS[@]+x} ]] && DOTMATRIX_COLOR_PATH_VCS=(252 239 0 1 0 15) + [[ -z ${DOTMATRIX_COLOR_PATH_LAST[@]+x} ]] && DOTMATRIX_COLOR_PATH_LAST=(15 239 1 0 0 15) + + [[ -z ${DOTMATRIX_COLOR_LINE[@]+x} ]] && DOTMATRIX_COLOR_LINE=(244 -1 0 0 15 -1) + # [[ -z ${DOTMATRIX_COLOR_LINE_START[@]+x} ]] && DOTMATRIX_COLOR_LINE_START=(255 -1 1 0 15 -1) + # [[ -z ${DOTMATRIX_COLOR_LINE_END[@]+x} ]] && DOTMATRIX_COLOR_LINE_END=(232 -1 1 0 15 -1) + + [[ -z ${DOTMATRIX_COLOR_MARK[@]+x} ]] && DOTMATRIX_COLOR_MARK=(15 -1 0 0 15 -1) + + [[ -z ${DOTMATRIX_COLOR_SEP_DARK[@]+x} ]] && DOTMATRIX_COLOR_SEP_DARK=( 0 -2 0 0 0 -2) + [[ -z ${DOTMATRIX_COLOR_SEP_FAIR[@]+x} ]] && DOTMATRIX_COLOR_SEP_FAIR=(244 -2 0 0 0 -2) + [[ -z ${DOTMATRIX_COLOR_SEP_LITE[@]+x} ]] && DOTMATRIX_COLOR_SEP_LITE=( 15 -2 0 0 15 -2) + + __dotmatrix_activate_display + __dotmatrix_activate_connection + __dotmatrix_activate_user + __dotmatrix_activate_multiplexer + __dotmatrix_activate_hostname +} + + +_lp_dotmatrix_theme_directory() { + lp_terminal_format "${DOTMATRIX_COLOR_LITE[@]}" + __dotmatrix_directory_FS + __dotmatrix_directory_path +} + + +_lp_dotmatrix_theme_prompt() { + + local header inline prompt + + # Arguments: fg, bg, bold, underline, fallback_fg, fallback_bg + # Color codes can be any integer in 256 XTerm's system colors in [0–255]. + # Special color codes: + # -1 : no color + # -2 : previously set color + # -3 : swap fg and bg + local lp_terminal_format + + #################################################################### + # HEADER (LEFT) + #################################################################### + + header="" + header+="${_DOTMATRIX_DISPLAY}" + header+="${_DOTMATRIX_CONNECTION}" + header+="${_DOTMATRIX_USER}" + header+="${_DOTMATRIX_MULTIPLEXER}" + header+="${_DOTMATRIX_HOSTNAME}" + header+="${_DOTMATRIX_FS}" + header+="${_DOTMATRIX_PATH} " + + if _lp_dirstack; then + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + header+="${dotmatrix_sep}" + __dotmatrix_make_field "${lp_dirstack}" "${DOTMATRIX_COLOR_LITE[@]}" + header+="${dotmatrix_field}" + else + # Recall a dark format to correctly reset sections history + # to match the path's section colors. + lp_terminal_format "${DOTMATRIX_COLOR_DARK[@]}" + fi + + __dotmatrix_make_sep_last + header+="${dotmatrix_sep}" + + #################################################################### + # HEADER SIDE (RIGHT) + #################################################################### + + __dotmatrix_make_sep_side "" + side="${dotmatrix_sep}" + + # battery / load / temperature + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_DARK[@]}" + local blt_plug="${dotmatrix_sep}" + + local battery="" + if _lp_battery ; then + __dotmatrix_make_field "$lp_battery" "${DOTMATRIX_COLOR_DARK[@]}" + battery="${dotmatrix_field}${LP_MARK_BATTERY}" + fi + + local load="" + if _lp_load ; then + __dotmatrix_make_field "$lp_load" "${DOTMATRIX_COLOR_DARK[@]}" + load="${dotmatrix_field}${LP_MARK_LOAD}" + fi + + local temperature="" + if _lp_temperature ; then + __dotmatrix_make_field "$lp_temperature" "${DOTMATRIX_COLOR_DARK[@]}" + temperature="${dotmatrix_field}${LP_MARK_TEMP}" + fi + + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_DARK[@]}" + # Non-bracketed variables are intentionals, + # so that if the variable is null, it does not count in the arguments array. + __dotmatrix_join_fields "$dotmatrix_sep" $battery $load $temperature + if [[ -n "$dotmatrix_join_fields" ]] ; then + side+="${blt_plug}${dotmatrix_join_fields}" + else + lp_terminal_format "${DOTMATRIX_COLOR_FAIR[@]}" + side+="${lp_terminal_format}" + fi + + # jobs: detached / running / stopped + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + local djc_plug="${dotmatrix_sep}" + + local detached_sessions="" + if _lp_detached_sessions ; then + if [[ -n "${lp_detached_sessions}" && "${lp_detached_sessions}" > 0 ]] ; then + __dotmatrix_make_field "${lp_detached_sessions}d" "${DOTMATRIX_COLOR_LITE[@]}" + detached_sessions="${dotmatrix_field}" + fi + fi + + local running_jobs="" + local stopped_jobs="" + if _lp_jobcount ; then + if [[ -n "${lp_running_jobs}" && "${lp_running_jobs}" > 0 ]] ; then + __dotmatrix_make_field "${lp_running_jobs}&" "${DOTMATRIX_COLOR_LITE[@]}" + running_jobs="${dotmatrix_field}" + fi + + if [[ -n "${lp_stopped_jobs}" && "${lp_stopped_jobs}" > 0 ]] ; then + __dotmatrix_make_field "${lp_stopped_jobs}z" "${DOTMATRIX_COLOR_LITE[@]}" + stopped_jobs="${dotmatrix_field}" + fi + fi + + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_LITE[@]}" + __dotmatrix_join_fields "$dotmatrix_sep" ${detached_sessions} ${running_jobs} ${stopped_jobs} + if [[ -n "$dotmatrix_join_fields" ]] ; then + side+="${djc_plug}${dotmatrix_join_fields}" + else + lp_terminal_format "${DOTMATRIX_COLOR_FAIR[@]}" + side+="${lp_terminal_format}" + fi + + # clock + if _lp_time ; then + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_DARK[@]}" + side+="${dotmatrix_sep}" + if _lp_analog_time ; then + __dotmatrix_make_field "$lp_analog_time" "${DOTMATRIX_COLOR_DARK[@]}" + side+="$dotmatrix_field" + else + __dotmatrix_make_field "$lp_time" "${DOTMATRIX_COLOR_DARK[@]}" + side+="$dotmatrix_field" + fi + fi + + # Merge side in header + local side_as_text="$(_lp_as_text "${side}")" + local head_as_text="$(_lp_as_text "${header}")" + # FIXME within SSH, COLUMNS seems to be broken + local head_width=$((${COLUMNS}-${#side_as_text}-${#head_as_text})) + #-6)) # Why -6? I have no idea. + if [[ $head_width -lt 0 ]] ; then + head_width=0 + fi + + local spaced_side+=$(printf "%.0s " $(seq ${head_width})) + + header+="${spaced_side}${side}" + + #################################################################### + # IN LINE + #################################################################### + + inline="$LP_PS1_PREFIX" + + local lp_terminal_format + lp_terminal_format "${DOTMATRIX_COLOR_LINE[@]}" + + local inline_width + if _lp_software_collections ; then + inline+="${inline} ${lp_software_collections} " + fi + if _lp_python_env ; then + inline+="${inline} ${lp_python_env} " + fi + local as_text="$(_lp_as_text "${inline}")" + inline_width=$((${COLUMNS}-${#as_text})) + + # Fill up the remaining space. + inline+="${lp_terminal_format}$(printf "%.0s${DOTMATRIX_LINE}" $(seq ${inline_width}))" + + # Gradient line: too slow (or not enough optimized? check COLUMNS change before recompute?) + # for i in $(seq ${inline_width}) ; do + # local dash_color=() + # for c in $(seq 0 $((${#DOTMATRIX_COLOR_LINE_START[@]}-1)) ); do + # f=$(bc -l <<< "$i / ${inline_width}") + # a=${DOTMATRIX_COLOR_LINE_START[c]} + # b=${DOTMATRIX_COLOR_LINE_END[c]} + # j=$(LC_ALL=C;printf "%.*f" 0 "$(bc -l <<< "($a)+(($b)-($a))*($f)")") + # dash_color+=($j) + # done + # + # lp_terminal_format ${dash_color[@]} + # inline+="${lp_terminal_format}${inline}" + # done + + #################################################################### + # PROMPT LINE + #################################################################### + + prompt="" + lp_terminal_format "${DOTMATRIX_COLOR_DARK[@]}" + prompt+="${lp_terminal_format}·" # Put internet here when (if) it's done. + + local net_sep_color="${DOTMATRIX_COLOR_LITE[@]}" + if _lp_find_vcs && _lp_vcs_commits_off_remote ; then + + if _lp_http_proxy ; then + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_LITE[@]}" + prompt+="${dotmatrix_sep}" + else + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + prompt+="${dotmatrix_sep}" + fi + else + if _lp_http_proxy ; then + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_DARK[@]}" + prompt+="${dotmatrix_sep}" + else + __dotmatrix_make_sep_mid "${DOTMATRIX_COLOR_DARK[@]}" + prompt+="${dotmatrix_sep}${DOTMATRIX_SPACE_VOID}" + fi + + fi + + __dotmatrix_prompt_vcs + prompt+="${_DOTMATRIX_VCS}" + + if _lp_runtime_format ; then + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_NOTE[@]}" + __dotmatrix_make_field "${lp_runtime_format}" "${DOTMATRIX_COLOR_NOTE[@]}" + prompt+="${dotmatrix_sep}${dotmatrix_field}" + fi + + if _lp_error ; then + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_WARN[@]}" + __dotmatrix_make_field "${lp_error}" "${DOTMATRIX_COLOR_WARN[@]}" + prompt+="${dotmatrix_sep}${dotmatrix_field}" + fi + + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_MARK[@]}" + prompt+="${dotmatrix_sep}" + lp_terminal_format "${DOTMATRIX_COLOR_MARK[@]}" + prompt+="${lp_terminal_format}${DOTMATRIX_MARK}" + prompt+="${NO_COL}" + + # Assemble and setup + PS1="\n${header}\n${inline}\n${prompt} " +} + + +######################################################################## +# Functions called at "activate" stage. +######################################################################## + +__dotmatrix_activate_display() { + if _lp_connected_display ; then + __dotmatrix_make_field "${DOTMATRIX_DISPLAY_X11}" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_DISPLAY=${dotmatrix_field} + else + __dotmatrix_make_field "${DOTMATRIX_DISPLAY_TEXT}" "${DOTMATRIX_COLOR_DARK[@]}" + _DOTMATRIX_DISPLAY=${dotmatrix_field} + fi +} + + +__dotmatrix_activate_connection() { + _lp_user + user_type=$? + local user_color + case $user_type in + 0) # logged-in user + user_color=(${DOTMATRIX_COLOR_DARK[@]}) + ;; + 1) # other user + user_color=(${DOTMATRIX_COLOR_NOTE[@]}) + ;; + 2) # root + user_color=(${DOTMATRIX_COLOR_WARN[@]}) + ;; + esac + + + local connection + _lp_connection + case "$lp_connection" in + lcl) + __dotmatrix_make_sep_plug "${user_color[@]}" + connection="${dotmatrix_sep}" + ;; + su) + _dotmatrix_make_sep_link "${user_color[@]}" + connection="${dotmatrix_sep}" + ;; + ssh) + __dotmatrix_make_sep_open "${user_color[@]}" + connection="${dotmatrix_sep}" + ;; + tel) + _dotmatrix_make_sep_dang "${user_color[@]}" + connection="${dotmatrix_sep}" + ;; + *) + __dotmatrix_make_sep_plug "${user_color[@]}" + connection="${dotmatrix_sep}" + ;; + esac + + _DOTMATRIX_CONNECTION="${connection}" +} + + +__dotmatrix_activate_user() { + _lp_user + user_type=$? + case $user_type in + 0) # logged-in user + if [[ -z "${lp_username}" ]] ; then # Honors LP_USER_ALWAYS + __dotmatrix_make_field "${DOTMATRIX_USER_LOCAL}" "${DOTMATRIX_COLOR_DARK[@]}" + _DOTMATRIX_USER="${dotmatrix_field}" + else + __dotmatrix_make_field "${lp_username}" "${DOTMATRIX_COLOR_DARK[@]}" + _DOTMATRIX_USER="${dotmatrix_field}" + fi + ;; + 1) # other user + _lp_username_color + __dotmatrix_make_field "${lp_username_color}" "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_USER="${dotmatrix_field}" + ;; + 2) # root + _lp_username + __dotmatrix_make_field "${lp_username}" "${DOTMATRIX_COLOR_WARN[@]}" + _DOTMATRIX_USER="${dotmatrix_field}" + ;; + esac + return $user_type +} + + +__dotmatrix_activate_hostname() { + local hostname + if _lp_hostname; then + case "$lp_connection" in + ssh) + hostname="${lp_hostname}" + ;; + tel) + hostname="${lp_hostname}" + ;; + *) + hostname+="${DOTMATRIX_HOST_LOCAL}" + ;; + esac + else + hostname="${DOTMATRIX_HOST_LOCAL}" + fi + + __dotmatrix_make_field "${hostname}" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_HOSTNAME="${dotmatrix_field}" +} + + +__dotmatrix_activate_multiplexer() { + local multiplexer + if _lp_multiplexer ; then + case "$lp_multiplexer" in + tmux) + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_LITE[@]}" + multiplexer="${dotmatrix_sep}" + ;; + screen) + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_LITE[@]}" + multiplexer="${dotmatrix_sep}" + ;; + *) + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_LITE[@]}" + multiplexer="${dotmatrix_sep}" + ;; + esac + else + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + multiplexer="${dotmatrix_sep}" + fi + + _DOTMATRIX_MULTIPLEXER="${multiplexer}" +} + + +######################################################################## +# Functions called at directory change. +######################################################################## + +__dotmatrix_directory_FS() { + local fs + if (( LP_ENABLE_PERM )); then + if _lp_chroot ; then + if [[ -w "${PWD}" ]]; then + __dotmatrix_make_sep_open "${DOTMATRIX_COLOR_DARK[@]}" + fs="${dotmatrix_sep}" + else + _dotmatrix_make_sep_dang "${DOTMATRIX_COLOR_DARK[@]}" + fs="${dotmatrix_sep}" + fi + else + if [[ -w "${PWD}" ]]; then + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_DARK[@]}" + fs="${dotmatrix_sep}" + else + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_DARK[@]}" + fs="${dotmatrix_sep}" + fi + fi + fi + _DOTMATRIX_FS="${fs}" +} + + +__dotmatrix_directory_path() { + local lp_terminal_format + + lp_terminal_format "${DOTMATRIX_COLOR_DARK[@]}" + local path_format="${lp_terminal_format}" + + lp_terminal_format "${DOTMATRIX_COLOR_SEP_DARK[@]}" + local separator_format=$lp_terminal_format + + lp_terminal_format "${DOTMATRIX_COLOR_PATH_SHORT[@]}" + local shortened_format=$lp_terminal_format + + lp_terminal_format "${DOTMATRIX_COLOR_PATH_VCS[@]}" + local vcs_format=$lp_terminal_format + + lp_terminal_format "${DOTMATRIX_COLOR_PATH_LAST[@]}" + local last_dir_format=$lp_terminal_format + + local lp_path_format + _lp_path_format "$path_format" "$last_dir_format" "$vcs_format" "$shortened_format" \ + "${DOTMATRIX_SPACE_PATH}${DOTMATRIX_SOFT}${DOTMATRIX_SPACE_PATH}" "$separator_format" + + _DOTMATRIX_PATH=${lp_path_format} +} + + +######################################################################## +# Functions called at prompt update. +######################################################################## + +__dotmatrix_prompt_vcs() { + if _lp_find_vcs ; then + local lp_vcs_details_color + + _lp_smart_mark + + # Mark & commits off remote + local has_commit= + if _lp_vcs_commits_off_remote; then + __dotmatrix_make_field "${DOTMATRIX_VCS}${lp_smart_mark}" "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_VCS="${dotmatrix_field}" + + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}" + + if (( LP_ENABLE_VCS_DIFFSTATS )) ; then + if [[ "$lp_vcs_commit_ahead" -ne "0" && "$lp_vcs_commit_behind" -ne "0" ]]; then + __dotmatrix_make_field "+$lp_vcs_commit_ahead" "${DOTMATRIX_COLOR_NOTE[@]}" + has_commit+="${dotmatrix_field}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_NOTE[@]}" + has_commit+="${dotmatrix_sep}" + __dotmatrix_make_field "-$lp_vcs_commit_behind" "${DOTMATRIX_COLOR_NOTE[@]}" + has_commit+="${dotmatrix_field}" + + elif [[ "$lp_vcs_commit_ahead" -ne "0" ]]; then + __dotmatrix_make_field "+$lp_vcs_commit_ahead" "${DOTMATRIX_COLOR_NOTE[@]}" + has_commit+="${dotmatrix_field}" + + elif [[ "$lp_vcs_commit_behind" -ne "0" ]]; then + __dotmatrix_make_field "-$lp_vcs_commit_behind" "${DOTMATRIX_COLOR_NOTE[@]}" + has_commit+="${dotmatrix_field}" + fi + _DOTMATRIX_VCS+="${has_commit}" + else + __dotmatrix_make_field "${DOTMATRIX_DIFF}" "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + fi # LP_ENABLE_VCS_DIFFSTATS + + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}" + + else # No commit off remote + __dotmatrix_make_field "${DOTMATRIX_VCS}${lp_smart_mark}" "${DOTMATRIX_COLOR_DARK[@]}" + _DOTMATRIX_VCS="${dotmatrix_field}" + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}" + fi # commits off remote + + # Branch:bookmark/tag + if _lp_vcs_branch; then + __dotmatrix_make_field "${lp_vcs_branch}" "${DOTMATRIX_COLOR_GLOW[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + + if _lp_vcs_bookmark; then + __dotmatrix_make_field ":${lp_vcs_bookmark}" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + fi + if _lp_vcs_tag; then + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_LITE[@]}" + __dotmatrix_make_field "${lp_vcs_tag}" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}${dotmatrix_field}" + fi + + elif _lp_vcs_bookmark; then + __dotmatrix_make_field "${lp_vcs_bookmark}" "${DOTMATRIX_COLOR_GLOW[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + elif _lp_vcs_tag; then + __dotmatrix_make_field "${lp_vcs_tag}" "${DOTMATRIX_COLOR_GLOW[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + else + _lp_vcs_commit_id + branch="${lp_vcs_commit_id:0:7}" + __dotmatrix_make_field "${lp_vcs_commit_id:0:7}" "${DOTMATRIX_COLOR_GLOW[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + fi # vcs branch + + # Diff stats + local ret has_lines= + if _lp_vcs_uncommitted_files; then + __dotmatrix_make_sep_link "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}" + + _lp_vcs_unstaged_lines; ret=$? + # Only show unstaged changes if the VCS supports staging, otherwise + # show uncommitted changes + if (( ret == 0 )); then + if [[ "$lp_vcs_unstaged_i_lines" == "$lp_vcs_unstaged_d_lines" ]] ; then + # If same number of lines inserted and deleted: display a single number. + __dotmatrix_make_field "±$lp_vcs_unstaged_i_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines="${dotmatrix_field}" + else + __dotmatrix_make_field "+$lp_vcs_unstaged_i_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines="${dotmatrix_field}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_NOTE[@]}" + has_lines+="$dotmatrix_sep" + __dotmatrix_make_field "-$lp_vcs_unstaged_d_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines+="${dotmatrix_field}" + fi + + elif (( ret == 1 )); then + __dotmatrix_make_field "±0" "${DOTMATRIX_COLOR_DARK[@]}" + has_lines="+${dotmatrix_field}" + else + _lp_vcs_uncommitted_lines + if [[ "$lp_vcs_uncommitted_i_lines" == "$lp_vcs_uncommitted_d_lines" ]] ; then + __dotmatrix_make_field "±$lp_vcs_uncommitted_i_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines="${dotmatrix_field}" + else + __dotmatrix_make_field "+$lp_vcs_uncommitted_i_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines="${dotmatrix_field}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_NOTE[@]}" + has_lines+="$dotmatrix_sep" + __dotmatrix_make_field "-$lp_vcs_uncommitted_d_lines" "${DOTMATRIX_COLOR_NOTE[@]}" + has_lines+="${dotmatrix_field}" + fi + fi + if (( LP_ENABLE_VCS_DIFFSTATS )) ; then + _DOTMATRIX_VCS+="${has_lines}" + else + __dotmatrix_make_field "${DOTMATRIX_DIFF}" "${DOTMATRIX_COLOR_NOTE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + fi # LP_ENABLE_VCS_DIFFSTATS + fi # uncommitted files + + # Stash / untracked / head + local stash= untracked= head= + if _lp_vcs_stash_count; then + stash="$DOTMATRIX_MARK_STASH" + fi + if _lp_vcs_untracked_files; then + untracked="$DOTMATRIX_MARK_UNTRACKED" + fi + if _lp_vcs_head_status; then + head="$lp_vcs_head_status" + # if [[ -n "${lp_vcs_head_details-}" ]]; then + # pass + # fi + fi + if [[ -n "$stash" || -n "$untracked" || -n "$head" ]] ; then + if [[ -z "$has_lines" ]] ; then + __dotmatrix_make_sep_mid "${DOTMATRIX_COLOR_SEP_FAIR[@]}" + _DOTMATRIX_VCS+=" $dotmatrix_sep " + else + __dotmatrix_make_sep_plug "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="$dotmatrix_sep" + fi + fi + + if [[ -n "$stash" ]] ; then + __dotmatrix_make_field "$stash" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="$dotmatrix_field" + if [[ -n "$untracked" ]] ; then + __dotmatrix_make_field "$untracked" "${DOTMATRIX_COLOR_LITE[@]}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}${dotmatrix_field}" + fi + if [[ -n "$head" ]] ; then + __dotmatrix_make_field "$head" "${DOTMATRIX_COLOR_LITE[@]}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}${dotmatrix_field}" + fi + else # no stash + if [[ -n "$untracked" ]] ; then + __dotmatrix_make_field "$untracked" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + if [[ -n "$head" ]] ; then + __dotmatrix_make_field "$head" "${DOTMATRIX_COLOR_LITE[@]}" + __dotmatrix_make_sep_soft "${DOTMATRIX_COLOR_SEP_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_sep}${dotmatrix_field}" + fi + else # no untracked + if [[ -n "$head" ]] ; then + __dotmatrix_make_field "$head" "${DOTMATRIX_COLOR_LITE[@]}" + _DOTMATRIX_VCS+="${dotmatrix_field}" + fi + fi + fi # stash + return 1 + else + _DOTMATRIX_VCS="" + return 0 + fi # find_vcs +} + +######################################################################## +# Helper functions +######################################################################## + +__dotmatrix_join_fields() { + dotmatrix_join_fields="" + local sep=${1-} + shift + if [[ -n "$@" ]] ; then + local first_field=${1-} + shift + dotmatrix_join_fields="${first_field}" + for f in "$@"; do + dotmatrix_join_fields+="${sep}${f}" + done + fi +} + +__dotmatrix_make_field() { # string, (color array) + local lp_terminal_format string=${1-} + shift + + [[ -z $string ]] && return 1 + + lp_terminal_format "$@" + + dotmatrix_field="${lp_terminal_format}${DOTMATRIX_SPACE_FIELD}${string}${DOTMATRIX_SPACE_FIELD}" +} + +__dotmatrix_make_sep_plug() { # color + # fg, bg, bold, underline, fallback_fg, fallback_bg + # 0 = set last color to current color + # -1 = set color to last color + # -2 = keep last color + # -3 = set last fg to last bg (and conversely) + local lp_terminal_format sep + sep="${DOTMATRIX_PLUG}" + if [[ "${_lp_last_ab_color-}" == "${2-}" ]] ; then + sep="${DOTMATRIX_MEAN}" + fi + lp_terminal_format -3 "${2-}" 0 0 -1 "${6-}" + dotmatrix_sep="${DOTMATRIX_SPACE_VOID}${lp_terminal_format}${sep}${DOTMATRIX_SPACE_VOID}" +} + +__dotmatrix_make_sep_link() { # color + local lp_terminal_format + dotmatrix_sep="" + + lp_terminal_format -3 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${DOTMATRIX_SPACE_VOID}${lp_terminal_format}${DOTMATRIX_LINK[0]}" + + lp_terminal_format 244 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_LINK[1]}" + + lp_terminal_format "${2-}" -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_LINK[2]}${DOTMATRIX_SPACE_FILL}" +} + +__dotmatrix_make_sep_open() { # color + local lp_terminal_format + + lp_terminal_format -3 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${DOTMATRIX_SPACE_VOID}${lp_terminal_format}${DOTMATRIX_OPEN[0]}" + + lp_terminal_format 244 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_OPEN[1]}" + + lp_terminal_format "${2-}" -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_OPEN[2]}${DOTMATRIX_SPACE_FILL}" +} + +__dotmatrix_make_sep_dang() { # color + local lp_terminal_format + + lp_terminal_format -3 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${DOTMATRIX_SPACE_VOID}${lp_terminal_format}${DOTMATRIX_DANG[0]}" + + lp_terminal_format 220 -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_DANG[1]}" + + lp_terminal_format "${2-}" -1 0 0 -1 "${6-}" + dotmatrix_sep+="${lp_terminal_format}${DOTMATRIX_DANG[2]}${DOTMATRIX_SPACE_FILL}" +} + +__dotmatrix_make_sep_soft() { # color + local lp_terminal_format + lp_terminal_format "${1-}" -2 0 0 "${5-}" + dotmatrix_sep="${lp_terminal_format}${DOTMATRIX_SOFT}" +} + +__dotmatrix_make_sep_mid() { # color + local lp_terminal_format + lp_terminal_format "${1-}" -2 0 0 "${5-}" + dotmatrix_sep="${lp_terminal_format}${DOTMATRIX_MEAN}" +} + +__dotmatrix_make_sep_last() { # no arg + local lp_terminal_format + lp_terminal_format -3 -1 0 0 -3 -1 + dotmatrix_sep="${lp_terminal_format}${DOTMATRIX_ENDS[0]}${NO_COL}" +} + +__dotmatrix_make_sep_side() { # no arg + local lp_terminal_format + lp_terminal_format "${DOTMATRIX_COLOR_SEP_FAIR[@]}" + dotmatrix_sep="${lp_terminal_format}${DOTMATRIX_ENDS[1]}" +} + diff --git a/themes/dotmatrix/liquidprompt_dotmatrix_design.odt b/themes/dotmatrix/liquidprompt_dotmatrix_design.odt new file mode 100644 index 0000000000000000000000000000000000000000..fdbd497b0700ea94f5815525f6c20bdc01856cf0 GIT binary patch literal 17088 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 literal 0 HcmV?d00001