2

Can I make the right-arrow key fill in an argument-at-a-time from the previous command line?

$ mogrify -resize 50% file.jpg
$

pressing right arrow now should fill in mogrify, pressing right arrow again should fill in all the way up to mogrify -resize, if I were to press it again mogrify -resize 50% etc.

and in the case that the command line so far does not match the directly preceding command line, it should fill in from the most recent matching command

$ mogrify -resize 50% file.jpg
$ echo hi
$ mo

Pressing right arrow should fill in mogrify not echo.

how can zsh be configured to support this?

1 Answer 1

2

The following code makes Right act normally unless it's at the end of the command line. If it is at the end of the command line, it looks for the previous matching history line starting with the text on the current line (it must be the exact same text, including whitespace). If it finds one, it inserts the next part of the matching line up to the beginning of the next word. With a numeric argument N, it pulls from the Nth matching line.

function immediate-complete-word-from-full-history {
  emulate -L zsh
  setopt extended_glob
  local line=${${history[(R)${(b)LBUFFER}*]}[${NUMERIC:-1}]}
  local blank=$' \t\n\f'
  if [[ -z $line ]]; then return; fi
  line=${line#$LBUFFER}
  LBUFFER+=${line%"${line##[^$blank]##[$blank]#}"}
}

function forward-char-or-immediate-complete-word-from-full-history {
  if [[ -n $RBUFFER ]]; then
    zle forward-char
  else
    immediate-complete-word-from-full-history
  fi
}

zle -N forward-char-or-immediate-complete-word-from-full-history
bindkey '\e[C' forward-char-or-immediate-complete-word-from-full-history
bindkey '\eOC' forward-char-or-immediate-complete-word-from-full-history

Known bug: this doesn't work well with history lines that contain a line break because fc outputs the line break as \n, which is indistinguishable from actually having \n inside the line. A fully correct solution would have to pull lines from $history.

3
  • @StéphaneChazelas Ah, neat, history has magic to make it expand in historical order. I should have checked. Sep 25, 2021 at 10:16
  • This seems to fill up to a space instead of an entire argument, filling /Folder\ instead of /Folder\ Name or 'one instead of 'one two' Oct 4, 2021 at 10:09
  • 1
    @theonlygusti Indeed, it fills up to whitespace. If you want to use shell words, you can use words=("${(@z)line}") to split the history line into words (assuming it's syntactically correct). Then you need to figure out how much of it to grab. A difficulty is that this erases information about the whitespace between words, and if that doesn't match then the history prefix lookup won't match if you press <Right> again. I figure spliting into words is good enough for interactive use: if you have an argument with spaces, you can keep pressing <Right> until you reach the end of the argument. Oct 4, 2021 at 10:45

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.