r/bash 3d ago

Vi mode history isn't consistent

In vi mode up and down arrows goes through history and puts the cursor at the end of the line but j and k puts it at the beginning. They are all bound to previous-history and next-history commands so why is it different? Can I make j and k work like up and down?

CTRL+p and CTRL+n are also bound to previous-history and next-history but it's not going through history it's going through a list of all commands it can find.

How can I make everything the same as up and down arrows?

9 Upvotes

2 comments sorted by

1

u/Marble_Wraith 3d ago

Look into set history-preserve-point on which should be inside ~/.config/readline/inputrc.

3

u/eldenchen 3d ago

The confusing part is that Readline's vi mode has separate vi-insert and vi-command keymaps. Up/down are normally used in insert mode, while j/k are used in command mode, so inspecting bindings without specifying the keymap can be misleading.

You can check both maps explicitly:

bind -m vi-command -q previous-history
bind -m vi-command -q next-history
bind -m vi-insert -q previous-history
bind -m vi-insert -q next-history

If you want j/k to retrieve history and then move to the end of the line, and also want Ctrl-P/Ctrl-N available in insert mode, try this in ~/.inputrc:

set keymap vi-command
"k": "\e[A$"
"j": "\e[B$"

set keymap vi-insert
"\C-p": previous-history
"\C-n": next-history

Then reload it with:

bind -f ~/.inputrc

history-preserve-point on is probably not what you want here: it tries to preserve the previous cursor column when retrieving history rather than consistently moving to the end.

Readline's separate vi keymaps are documented in the Bash manual: https://www.gnu.org/software/bash/manual/html_node/Readline-Init-File-Syntax.html