Cursor style switch on Linux virtual console
Problem
I have a ZLE widget as below for cursor styles between vicmd and viins keymap modes on Linux virtual console, but it doesn't work.
if [[ "$KEYMAP" == 'vicmd' ]]; then
# Normal mode
print -n '\033[?17;0;240c'
else
# Insert mode
print -n '\033[?2c'
fiFindings
After troubleshooting, I found the root cause is the following code in internal/p10k.zsh:
typeset -gi _p9k__can_hide_cursor=$(( $+terminfo[civis] && $+terminfo[cnorm] ))
if (( _p9k__can_hide_cursor )); then
# See https://github.com/romkatv/powerlevel10k/issues/1699
if [[ $terminfo[cnorm] == *$'\e[?25h'(|'\e'*) ]]; then
typeset -g _p9k__cnorm=$'\e[?25h'
else
typeset -g _p9k__cnorm=$terminfo[cnorm]
fi
fiThe civis and cnorm terminfo capabilities for the Linux virtual console are:
civis=$'\e[?25l\e[?1c'
cnorm=$'\e[?25h\e[?0c'The value of cnorm fails to match *$'\e[?25h'(|'\e'*) ]], so p10k always picks the full cnorm value, including \e[?0c which resets the cursor to its default style. I am not sure \e in the pattern is a typo or intended as is.
After changing '\e' to $'\e', the cursor switch triggers, but I find another issue that the cursor always become invisible soon. This is because _p9k_reset_prompt executes:
(( _p9k__can_hide_cursor )) && echoti civiswhich sends $'\e[?25l\e[?1c'. The \e[?25l part hides the cursor, while \e[?1c selects the invisible cursor style. However, my temporary workaround has $'\e[?0c' stripped from cnorm, causing the subsequent cursor restore (print -rn -- $_p9k__cnorm) to only sends $'\e[?25h' which doesn't restore the cursor style.
Reference
Source: romkatv/powerlevel10k