Skip to content

Conversation

@nojhan
Copy link
Collaborator

@nojhan nojhan commented Jan 11, 2025

Allows the user to remove default spaces in some parameters.

Why?

When a configuration variable defaults as a space, it cannot be set to an empty string by the end user. The only way to effectively remove the default space is to use Unicode's empty character (U+0000).

Example:

# Use any character: OK
A="." ; A="${A:-" "}" ; echo "[$A]"
[.]
# Use an empty string = NOK
A="" ; A="${A:-" "}" ; echo "[$A]"
[ ]
# Use Unicode's empty character = OK
A="" ; A="${A:-" "}" ; echo "[$A]"
[]

In Liquid Prompt, the configuration variables managing spacing are set like that (see LP_MARK_PREFIX, LP_MARK_ENV_VAR_SEP). In the default theme, using an empty character would just work. So far so good.

But for themes using right alignment, it is necessary to compute the width of the displayed string. This is done by first running __lp_strip_escapes, to get rid of escaped sequences, and then get the length of the remaining string.

However, an empty character, while technically not really displayed, would still amount to the length computed by the shell, effectively ruining the expected behavior.

This patch proposes to consider that the empty character is akin to escaped sequences, and as such should be removed by __lp_strip_escapes, which effectively fix the aforementioned behavior.

Technical checklist:

  • code follows our shell standards:
    • careful quoting
    • string substitutions may be done differently in Bash and Zsh (use _LP_SHELL_*)
  • tests and checks have been added, ran, and their warnings fixed:
    • unit tests have been updated (see tests/test_*.sh files)
    • ran tests.sh
    • ran shellcheck.sh (requires shellcheck).
  • documentation have been updated accordingly:
    • functions and attributes are documented in alphabetical order
    • new sections are documented in the default theme
    • tag .. versionadded:: X.Y or .. versionchanged:: Y.Z
    • functions signatures have arguments, returned code, and set value(s)
    • attributes have types and defaults
    • ran docs/docs-lint.sh (requires Python 3 and requirements.txt
      installed (cd docs/; python3 -m venv venv; . venv/bin/activate; pip install -r requirements.txt))

@nojhan nojhan self-assigned this Jan 11, 2025
@nojhan nojhan changed the title fix(_lp_strip_escape): remove Unicode empty character fix(_lp_strip_escapes): remove Unicode's empty character Jan 12, 2025
@nojhan nojhan changed the title fix(_lp_strip_escapes): remove Unicode's empty character fix(__lp_strip_escapes): remove Unicode's empty character Jan 12, 2025
Allows the user to set configuration parameters that default to space(s) into an empty string
without messing with displayed text length computation.
@nojhan nojhan requested a review from Rycieos January 12, 2025 12:57
@nojhan nojhan added bug enhancement Feature request labels Jan 12, 2025
@nojhan nojhan marked this pull request as ready for review January 12, 2025 12:57
@Rycieos
Copy link
Collaborator

Rycieos commented Jan 23, 2025

This seems to me to be over-complicating the problem. If the problem is the inability to set certain config values to the empty string, then there is a much easier way to solve it.

From the Bash docs:

When not performing substring expansion, using the form described below (e.g., ‘:-’), Bash tests for a parameter that is unset or null [empty string]. Omitting the colon results in a test only for a parameter that is unset. Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.

All of our config options are checked with ${LP_VAR:-"default"} syntax, and so nothing is allowed to be set to the empty string (other than those that default to the empty string).

So, it seems to me the much easier solution is to change the assignment of those config variables from :- to -.

Not all would need changing. Any config option that controls how Liquid Prompt works needs to never be null. But config options that are meant to be used as strings to display to the user should be changed. So I think these variables would be appropriate for that treatment:

liquidprompt/liquidprompt

Lines 647 to 749 in b4e1d34

LP_MARK_DEFAULT="${LP_MARK_DEFAULT:-$_LP_MARK_SYMBOL}"
LP_MARK_BATTERY="${LP_MARK_BATTERY:-""}"
LP_MARK_ADAPTER="${LP_MARK_ADAPTER:-""}"
LP_MARK_LOAD="${LP_MARK_LOAD:-""}"
LP_MARK_TEMP="${LP_MARK_TEMP:-"θ"}"
LP_MARK_PROXY="${LP_MARK_PROXY:-""}"
LP_MARK_ENV_VARS_OPEN="${LP_MARK_ENV_VARS_OPEN:-"("}"
LP_MARK_ENV_VARS_SEP="${LP_MARK_ENV_VARS_SEP:-" "}"
LP_MARK_ENV_VARS_CLOSE="${LP_MARK_ENV_VARS_CLOSE:-")"}"
LP_MARK_HG="${LP_MARK_HG:-""}"
LP_MARK_SVN="${LP_MARK_SVN:-""}"
LP_MARK_GIT="${LP_MARK_GIT:-"±"}"
LP_MARK_VCSH="${LP_MARK_VCSH:-"|"}"
LP_MARK_FOSSIL="${LP_MARK_FOSSIL:-""}"
LP_MARK_BZR="${LP_MARK_BZR:-""}"
LP_MARK_DISABLED="${LP_MARK_DISABLED:-""}"
LP_MARK_UNTRACKED="${LP_MARK_UNTRACKED:-"*"}"
LP_MARK_STASH="${LP_MARK_STASH:-"+"}"
LP_MARK_VCS_REMOTE="${LP_MARK_VCS_REMOTE:-""}"
LP_MARK_BRACKET_OPEN="${LP_MARK_BRACKET_OPEN:-"["}"
LP_MARK_BRACKET_CLOSE="${LP_MARK_BRACKET_CLOSE:-"]"}"
LP_MARK_MULTIPLEXER_OPEN="${LP_MARK_MULTIPLEXER_OPEN:-"$LP_MARK_BRACKET_OPEN"}"
LP_MARK_MULTIPLEXER_CLOSE="${LP_MARK_MULTIPLEXER_CLOSE:-"$LP_MARK_BRACKET_CLOSE"}"
LP_MARK_SHORTEN_PATH="${LP_MARK_SHORTEN_PATH:-""}"
LP_MARK_PREFIX="${LP_MARK_PREFIX:-" "}"
LP_MARK_PERM="${LP_MARK_PERM:-":"}"
LP_MARK_DIRSTACK="${LP_MARK_DIRSTACK:-""}"
LP_MARK_SHLVL="${LP_MARK_SHLVL:-""}"
LP_MARK_WIFI="${LP_MARK_WIFI:-"📶"}"
LP_MARK_DEV_OPEN="${LP_MARK_DEV_OPEN:-"<"}"
LP_MARK_DEV_CLOSE="${LP_MARK_DEV_CLOSE:-">"}"
LP_MARK_DEV_MID="${LP_MARK_DEV_MID:-"|"}"
LP_MARK_MODULES_OPEN="${LP_MARK_MODULES_OPEN:-""}"
LP_MARK_MODULES_SEP="${LP_MARK_MODULES_SEP:-":"}"
LP_MARK_MODULES_CLOSE="${LP_MARK_MODULES_CLOSE:-""}"
LP_MARK_CMAKE="${LP_MARK_CMAKE:-":"}"
LP_MARK_KUBECONTEXT=${LP_MARK_KUBECONTEXT:-""}
LP_MARK_JOBS_SEPARATOR="${LP_MARK_JOBS_SEPARATOR:-"/"}"
LP_MARK_OS_SEP=${LP_MARK_OS_SEP:-"/"}
LP_MARK_OS=( ${LP_MARK_OS[@]+"${LP_MARK_OS[@]}"} )
LP_MARK_DISK="${LP_MARK_DISK:-"🖴 "}"
LP_MARK_RAM="${LP_MARK_RAM:-"M"}"
LP_COLOR_CMAKE_DEBUG=${LP_COLOR_CMAKE_DEBUG:-$MAGENTA}
LP_COLOR_CMAKE_RWDI=${LP_COLOR_CMAKE_RWDI:-$BLUE}
LP_COLOR_CMAKE_RELEASE=${LP_COLOR_CMAKE_RELEASE:-$CYAN}
LP_COLOR_PATH=${LP_COLOR_PATH:-$NO_COL}
lp_terminal_format 8 -1 0 0 -1
LP_COLOR_PATH_SEPARATOR=${LP_COLOR_PATH_SEPARATOR:-$lp_terminal_format}
LP_COLOR_PATH_SHORTENED=${LP_COLOR_PATH_SHORTENED:-$lp_terminal_format}
lp_terminal_format -1 -1 1 0
LP_COLOR_PATH_VCS_ROOT=${LP_COLOR_PATH_VCS_ROOT:-$lp_terminal_format}
LP_COLOR_PATH_LAST_DIR=${LP_COLOR_PATH_LAST_DIR:-$lp_terminal_format}
LP_COLOR_PATH_ROOT=${LP_COLOR_PATH_ROOT:-$BOLD_YELLOW}
LP_COLOR_PROXY=${LP_COLOR_PROXY:-$BOLD_BLUE}
LP_COLOR_ENV_VARS_UNSET=${LP_COLOR_ENV_VARS_UNSET:-$BLUE}
LP_COLOR_ENV_VARS_SET=${LP_COLOR_ENV_VARS_SET:-$BOLD_BLUE}
LP_COLOR_JOB_D=${LP_COLOR_JOB_D:-$YELLOW}
LP_COLOR_JOB_R=${LP_COLOR_JOB_R:-$BOLD_YELLOW}
LP_COLOR_JOB_Z=${LP_COLOR_JOB_Z:-$BOLD_YELLOW}
LP_COLOR_ERR=${LP_COLOR_ERR:-$PURPLE}
LP_COLOR_ERR_MEANING=${LP_COLOR_ERR_MEANING:-$LP_COLOR_ERR}
LP_COLOR_MARK=${LP_COLOR_MARK:-$BOLD}
LP_COLOR_MARK_ROOT=${LP_COLOR_MARK_ROOT:-$BOLD_RED}
LP_COLOR_MARK_SUDO=${LP_COLOR_MARK_SUDO:-$LP_COLOR_MARK_ROOT}
LP_COLOR_USER_LOGGED=${LP_COLOR_USER_LOGGED:-""}
LP_COLOR_USER_ALT=${LP_COLOR_USER_ALT:-$BOLD}
LP_COLOR_USER_ROOT=${LP_COLOR_USER_ROOT:-$BOLD_YELLOW}
LP_COLOR_HOST=${LP_COLOR_HOST:-""}
LP_COLOR_SSH=${LP_COLOR_SSH:-$BLUE}
LP_COLOR_SU=${LP_COLOR_SU:-$BOLD_YELLOW}
LP_COLOR_TELNET=${LP_COLOR_TELNET:-$WARN_RED}
LP_COLOR_X11_ON=${LP_COLOR_X11_ON:-$GREEN}
LP_COLOR_X11_OFF=${LP_COLOR_X11_OFF:-$YELLOW}
LP_COLOR_WRITE=${LP_COLOR_WRITE:-$GREEN}
LP_COLOR_NOWRITE=${LP_COLOR_NOWRITE:-$RED}
LP_COLOR_UP=${LP_COLOR_UP:-$GREEN}
LP_COLOR_COMMITS=${LP_COLOR_COMMITS:-$YELLOW}
LP_COLOR_COMMITS_BEHIND=${LP_COLOR_COMMITS_BEHIND:-$BOLD_RED}
LP_COLOR_CHANGES=${LP_COLOR_CHANGES:-$RED}
LP_COLOR_DIFF=${LP_COLOR_DIFF:-$PURPLE}
LP_COLOR_CHARGING_ABOVE=${LP_COLOR_CHARGING_ABOVE:-$GREEN}
LP_COLOR_CHARGING_UNDER=${LP_COLOR_CHARGING_UNDER:-$YELLOW}
LP_COLOR_DISCHARGING_ABOVE=${LP_COLOR_DISCHARGING_ABOVE:-$YELLOW}
LP_COLOR_DISCHARGING_UNDER=${LP_COLOR_DISCHARGING_UNDER:-$RED}
LP_COLOR_TIME=${LP_COLOR_TIME:-$BLUE}
LP_COLOR_IN_MULTIPLEXER=${LP_COLOR_IN_MULTIPLEXER:-$BOLD_BLUE}
LP_COLOR_RUNTIME=${LP_COLOR_RUNTIME:-$YELLOW}
LP_COLOR_VIRTUALENV=${LP_COLOR_VIRTUALENV:-$CYAN}
LP_COLOR_NODE_VENV=${LP_COLOR_NODE_VENV:-$LP_COLOR_VIRTUALENV}
LP_COLOR_RUBY_VENV=${LP_COLOR_RUBY_VENV:-$LP_COLOR_VIRTUALENV}
LP_COLOR_PERL_VENV=${LP_COLOR_PERL_VENV:-$LP_COLOR_VIRTUALENV}
LP_COLOR_TERRAFORM=${LP_COLOR_TERRAFORM:-$PINK}
LP_COLOR_CONTAINER=${LP_COLOR_CONTAINER:-$BOLD_BLUE}
LP_COLOR_DIRSTACK=${LP_COLOR_DIRSTACK:-$BOLD_YELLOW}
LP_COLOR_KUBECONTEXT=${LP_COLOR_KUBECONTEXT:-$CYAN}
LP_COLOR_AWS_PROFILE=${LP_COLOR_AWS_PROFILE:-$YELLOW}
LP_COLOR_MODULES=${LP_COLOR_MODULES:-$BLUE}
LP_COLOR_SHLVL=${LP_COLOR_SHLVL:-$BOLD_GREEN}
LP_COLOR_DISK=${LP_COLOR_DISK:-$BOLD_RED}
LP_COLOR_DISK_UNITS=${LP_COLOR_DISK_UNITS:-$RED}
LP_COLOR_RAM=${LP_COLOR_RAM:-$BOLD_RED}
LP_COLOR_RAM_UNITS=${LP_COLOR_RAM_UNITS:-$RED}

Note that LP_MARK_ENV_VAR_SEP is not a valid config option. Is this an option from one of your themes?

Now, I imagine that you might still want the removal of the empty character. (By the way, which character are you using? U+200B ZERO WIDTH SPACE? That should probably be in the comment pointing out the empty character.) After all, you might need to use it in a theme for some reason, or maybe somehow it ends up in a data string, and then length calculations would be incorrect. However, I can think of a good reason not to remove it: there are many Unicode characters that are more than one "character" wide, but a string length check shows only one character. This empty character could be used to "fix" those calculations. That sounds dangerously hacky, but something to consider.

And anyway, it seems you are only removing one certain character, and there are multiple zero width characters in Unicode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug enhancement Feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants