akinomyoga / ble.sh

Bash Line Editor―a line editor written in pure Bash with syntax highlighting, auto suggestions, vim modes, etc. for Bash interactive sessions.
BSD 3-Clause "New" or "Revised" License
2.62k stars 83 forks source link

ble/prompt: Undefined named sequence: \q{user/currentmode} #467

Closed theshatterstone closed 3 months ago

theshatterstone commented 3 months ago

ble/prompt: Undefined named sequence: \q{user/currentmode}

I get this as a message in the top right corner on every bash startup. I use the set-up-status-line function to get the current vi mode so I can have it displayed in my prompt (but NOT in a modeline or status line). It works but the error message is very annoying so any solution, including a dirty hack to supress or otherwise get rid of the message would be very appreciated. Thanks.

My Config:

# 
# Ble.sh config file
#

# Use vi(m) keybinds
bleopt default_keymap=vi

# Disable bell
bleopt edit_bell=vbell
bleopt edit_vbell=

# Add vi mode indicator to prompt
#\q{keymap:vi/mode-indicator}  # Example result: -- INSERT --
#PS1="\[$(tput bold)\]\[\033[38;5;249m\]\w\[$(tput sgr0)\]\n\[$(tput sgr0)\]\[$(tput bold)\]\[\033[38;5;25m\]>\[$(tput sgr0)\] \[$(tput sgr0)\]"

# blerc
function user/set-up-status-line {

  # Hide the normal mode name
  bleopt keymap_vi_mode_show=

  # Update prompts on the mode change
  bleopt keymap_vi_mode_update_prompt=1

  function ble/prompt/backslash:user/currentmode {
    local mode; ble/keymap:vi/script/get-mode
    case $mode in
    (*n)  ble/prompt/print $'\e[1mNormal\e[m' ;;
    (*i)  ble/prompt/print $'\e[1mInsert\e[m' ;;
    (*v)  ble/prompt/print $'\e[1mVisual\e[m' ;;
    (*V)  ble/prompt/print $'\e[1mV-Line\e[m' ;;
    (*^V) ble/prompt/print $'\e[1mV-Bloq\e[m' ;;
    (*s)  ble/prompt/print $'\e[1mSelect\e[m' ;;
    (*S)  ble/prompt/print $'\e[1mS-Line\e[m' ;;
    (*^S) ble/prompt/print $'\e[1mS-Bloq\e[m' ;;
    (R)   ble/prompt/print $'\e[1mRPlace\e[m' ;;
    (^R)  ble/prompt/print $'\e[1mVPlace\e[m' ;;
    (*)   ble/prompt/print $'\e[1m??????\e[m' ;;
    esac
  }

  # In this example, we put the mode string, date and time, and the
  # current working directory in the status line.
  bleopt prompt_status_line=

}
blehook/eval-after-load keymap_vi user/set-up-status-line

# Function to determine the vi mode and set PS1 accordingly
precmd() {
  # Get the last command's exit status
  exit_status=$?

  # Set the prompt symbol based on the exit status
  if [ $exit_status -eq 0 ]; then
    symbol="\[\033[0m\][\[\033[1;38;5;81m\]\q{user/currentmode}\[\033[0m\]]\[\033[1;38;5;81m\]"
  else
    symbol="\[\033[0m\][\[\033[1;38;5;196m\]\q{user/currentmode}\[\033[1;38;5;196m\]]\[\033[0m\]"
  fi

  # Dark blue > symbol
  prompt_char="\[\033[1;34m\]>\[\033[0m\]"

  # Set the PS1 variable
  PS1="\n\[\033[38;5;223m\]\w\n${symbol} ${prompt_char} "
}

# Trap PROMPT_COMMAND to set the prompt before displaying it
PROMPT_COMMAND=precmd

# Enable vi mode in bash
set -o vi
akinomyoga commented 3 months ago

You can use \q{user/currentmode} only after you define the function ble/prompt/backslash:user/currentmode. In the above setup, you define the function ble/prompt/backslash:user/currentmode through the keymap_vi load hook, which is called after precmd and the first prompt. You use \q{user/currentmode} in precmd, but the function ble/prompt/backslash:user/currentmode is not defined for the first call of precmd. This causes the error.

To solve the problem, for example, one may consider defining the function ble/prompt/backslash:user/currentmode outside the keymap_vi load hook. However, there is a reason that the above ble/prompt/backslash:user/currentmode was defined through the keymap_vi load hook: the function ble/keymap:vi/script/get-mode called by ble/prompt/backslash:user/currentmode is only available after the vi module is loaded. Then, you can use ble/function#try ble/keymap:vi/script/get-mode to call ble/keymap:vi/script/get-mode only when it is available.

function ble/prompt/backslash:user/currentmode {
  local mode=
  ble/function#try ble/keymap:vi/script/get-mode
  case $mode in
  (*n)  ble/prompt/print $'\e[1mNormal\e[m' ;;
  (*i)  ble/prompt/print $'\e[1mInsert\e[m' ;;
  (*v)  ble/prompt/print $'\e[1mVisual\e[m' ;;
  (*V)  ble/prompt/print $'\e[1mV-Line\e[m' ;;
  (*^V) ble/prompt/print $'\e[1mV-Bloq\e[m' ;;
  (*s)  ble/prompt/print $'\e[1mSelect\e[m' ;;
  (*S)  ble/prompt/print $'\e[1mS-Line\e[m' ;;
  (*^S) ble/prompt/print $'\e[1mS-Bloq\e[m' ;;
  (R)   ble/prompt/print $'\e[1mRPlace\e[m' ;;
  (^R)  ble/prompt/print $'\e[1mVPlace\e[m' ;;
  (*)   ble/prompt/print $'\e[1m??????\e[m' ;;
  esac
}
theshatterstone commented 3 months ago

Adding that function outside of the hook fixes it! Thanks. (Also, I removed the user/currentmode function from the keymap_vi load hook as it's not needed anymore and it still works). Closing this issue. Thank you!