5

In bash, I used this:

% cat .inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward

I'd like the same behavior in .zsh, so I've tried these bindkeys:

"^[[A" history-beginning-search-backward
"^[[B" history-beginning-search-forward

These are ALMOST what I want, except when I just up arrow (with no entered text) to see the immediately previous command, the cursor is positioned at the beginning of the line, rather than the end.

'bindkey '^[[A' history-search-backward' is close, it puts the cursor at the end BUT it only searches for the first word, e.g. if I type 'ssh foo' it will return the most recent 'ssh' in the history, not the most recent line starting with 'ssh foo'. Also, this positions the cursor at the end of the line when I do search, which is also not what I want (both bash's history-search-backwards and zsh's history-beginning-search-backward keep the cursor where I stopped typ

is it possible to get the cursor positioned at the end of the line with the same functionality as history-beginning-search-backward?

2 Answers 2

6

Binding that to the Up key means that when it comes to editing a multi-line command, you wont be able to move the cursor up.

That's why the default widget bound to Up is up-line-or-history, which moves the cursor up if you're at the second line or below a multiline command and otherwise brings up the previous command from the history.

To change that so that when bringing up the previous command from the history, it brings up the one that has the same leading substring as what's left of the cursor, there are autoloadable widgets for that:

for direction (up down) {
  autoload $direction-line-or-beginning-search
  zle -N $direction-line-or-beginning-search
  key=$terminfo[kcu$direction[1]1]
  for key ($key ${key/O/[})
    bindkey $key $direction-line-or-beginning-search
}

(here querying terminfo for the sequence sent upon pressing Up or Down, and binding that as well as the variant with O replaced with [ to cover both keypad transmit modes as supported by most terminals).

Alternatively, you could redefine the up/down-line-or-history widgets to use those:

for direction (up down) {
  autoload $direction-line-or-beginning-search
  zle -N $direction-line-or-{history,beginning-search}
}

That would affect all key mappings that use those widgets, including Up / Down, but also Ctrl+P/N in emacs mode for instance.

2

In zsh, you can bind a key to a shell function. The shell function must be registered as a widget with zle -N. It has access to several variables with the content of the buffer, the clipboard, etc. It can call other widgets via the zle builtin.

This code (untested) puts the cursor at the end of the line after history-beginning-search-backward, but only if the buffer was originally empty. I'm not sure if that's exactly what you want, but if not it should be easy to adapt.

function history-beginning-search-backward-end-of-line {
  local original_buffer_length=$#BUFFER
  zle history-beginning-search-backward
  if ((original_buffer_length == 0)); then
    CURSOR=$#BUFFER
  fi
}
zle -N history-beginning-search-backward-end-of-line
bindkey "^[[A" history-beginning-search-backward-end-of-line

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .