3

I'm using Zsh with Zim. I've set up a key binding for editing the current command in Neovim by placing the following into .zshrc:

bindkey -v
export VISUAL=nvim
autoload edit-command-line; zle -N edit-command-line
bindkey -M vicmd v edit-command-line

With this, when I finish editing the command, the end result is placed under the original, like in the screenshot below.

Example with two lines, with a command on each one.

What I'd like to have instead is that the the end result replaces the original line. The main reason for this is that I'm using Powerlevel10k with transient prompt enabled. This feature doesn't work in this particular case.

3

Disclaimer: I'm the author of Powerlevel10k.

When transient prompt is enabled, Powerlevel10k should truncate prompt when you finish editing the command in an external editor. It doesn't, however. I've just fixed it thanks to your report.

Now back to your original question.

What I'd like to have instead is that the the end result replaces the original line.

You'll need to define a custom zle widget for that. Here's one implementation:

function edit-command-line-inplace() {
  if [[ $CONTEXT != start ]]; then
    if (( ! ${+widgets[edit-command-line]} )); then
      autoload -Uz edit-command-line
      zle -N edit-command-line
    fi
    zle edit-command-line
    return
  fi
  () {
    emulate -L zsh -o nomultibyte
    local editor=("${(@Q)${(z)${VISUAL:-${EDITOR:-vi}}}}") 
    case $editor in
      (*vim*)
        "${(@)editor}" -c "normal! $(($#LBUFFER + 1))go" -- $1
      ;;
      (*emacs*)
        local lines=("${(@f)LBUFFER}") 
        "${(@)editor}" +${#lines}:$((${#lines[-1]} + 1)) $1
      ;;
      (*)
        "${(@)editor}" $1
      ;;
    esac
    BUFFER=$(<$1)
    CURSOR=$#BUFFER
  } =(<<<"$BUFFER") </dev/tty
}

You can bind it the same way as you did with edit-command-line:

zle -N edit-command-line-inplace
bindkey -M vicmd v edit-command-line-inplace

Note that edit-command-line-inplace defers to edit-command-line if it's impossible to update the command line inplace. For example, try typing echo 'first line, hit Enter and then invoke edit-command-line-inplace. There is no way to update the first line of the command, so edit-command-line-inplace will behave the same way as edit-command-line.

Edit: The first version of edit-command-line-inplace that I've posted explicitly invoked nvim to edit the command line. I've updated the code to respect VISUAL and EDITOR environment variables.

3
  • I use code -n -w to use with edit-command-line. How can I use vscode with edit-command-line-inplace. – blueray Sep 7 '20 at 8:27
  • 1
    @blueray I've updated the implementation of edit-command-line-inplace to respect VISUAL and EDITOR environment variables. If you set VISUAL="code -n -w" in your ~/.zshrc, it should work. – Roman Perepelitsa Sep 9 '20 at 8:01
  • I think I know you from zsh mailing list. – blueray Sep 9 '20 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.