Restore the Previously Canceled Command in Zsh

Last updated on December 10, 2016

In zsh, it is often annoying that we can't easily restore the command we just canceled by Ctrl-C: canceled commands are not recorded into the history file and thus cannot be restored by searching previous commands. To make the restoration possible, zsh provides a variable ZLE_LINE_ABORTED which keeps a record of the last command that was canceled—everything looks so simple. However, for some reasons, such as canceling stuck tab completion, we often push Ctrl-C for more than once—but ZLE_LINE_ABORTED would become empty if Ctrl-C is used on an empty line! Thanks to the great extensibility of zsh, we can solve this issue by tweaking zle-line-init (add the following to your ~/.zshrc):

function zle-line-init {
  # Your other zle-line-init configuration ...

  # Store the last non-empty aborted line in MY_LINE_ABORTED
  if [[ -n $ZLE_LINE_ABORTED ]]; then
    MY_LINE_ABORTED="$ZLE_LINE_ABORTED"
  fi

  # Restore aborted line on the first undo.
  if [[ -n $MY_LINE_ABORTED ]]; then
    local savebuf="$BUFFER" savecur="$CURSOR"
    BUFFER="$MY_LINE_ABORTED"
    CURSOR="$#BUFFER"
    zle split-undo
    BUFFER="$savebuf" CURSOR="$savecur"
  fi
}
zle -N zle-line-init
  • Line 1: Define the zle-line-init widget which will be executed every time when the a new command line is ready to take input.
  • Line 5-7: If ZLE_LINE_ABORTED is non-empty, save it to MY_LINE_ABORTED.
  • Line 10-16: If MY_LINE_ABORTED is non-empty, the initial undo will restore the contents in MY_LINE_ABORTED. Also see man zshzle for an explanation of split-undo.
  • Line 18: Install the widget zle-line-init.

Now type any command and push Ctrl-C twice and undo (bound to Ctrl-/ by default): your canceled command is back!

Note that if you use zsh-autosuggestions this code snippet somehow breaks it. Adding _zsh_autosuggest_widget_clear before the end of zle-line-init would fix it.

References

Leave a Reply

Your email address will not be published. Required fields are marked *