28 comments

[ 3.5 ms ] story [ 73.1 ms ] thread
All you need is set -o vi ;)
I'm a heavy vi user, but I just couldn't get used to that!

Maybe I should use ed first. BTW I recently came across a contractor that routinely used ed because 'I want to know what's going on!'

No, all you need is a file called ~/.inputrc with at least the following contents:

  set editing-mode vi
This causes any program that has its own command line (like bash, psql, etc) and uses the readline library (like bash, psql, etc) to have an editable command line with vi edit behavior.

In man bash, search for /^READLINE (READLINE at the beginning of a line).

Side note: if you want a nice TOC of bash or anything else, run this from the command line:

  man -P cat bash |grep -E "^[^ ]"
Or if you're into the whole minimalism thing:

  man -P "grep -E '^[^ ]'" bash
Or if you're into the whole reusability/automation thing:

  $ cat ~/bin/toc
  #! /usr/bin/env bash

  man -P "grep -E '^[^ ]'" $1
And then

  $ toc bash
The biggest issue[1] I've found with vi(m)-like modes in shells and readline is the lack of any feedback as to which mode you're in. That, and my tendency to use C-c as an alternative to esc in vim has...unfortunate consequences in the shell, although I could potentially rebind it.

[1] Actually, the biggest is 'discovered it set by default on a server you occasionally adminster, and taking far too long to realise why you're typing largely gibberish'

esc esc esc generally assures me that I'm in normal mode, even on the command line. :)
When I'll make my vi clone, I'll call it lo, because all you need is lovi.
Slight errata: This part of the pipeline: `bind -l | sed 's/.*/bind -q \0/' | /bin/bash 2>&1 | grep -v warning:`

...can be replaced with `bind -P`.

Also, \e represents ESC; tab is represented by \t.

nice!

Have updated. Schoolboy error with tab/escape...

However, do you know why tab-tab works as complete?

Sweet! You might consider using this command for a more human digestible listing:

    $ stty -a | awk 'BEGIN{RS="[;\n]+ ?"}; /= ..$/'
    intr = ^C
    quit = ^\
    erase = ^?
    kill = ^U
    eof = ^D
    swtch = ^Z
    susp = ^Z
    rprnt = ^R
    werase = ^W
    lnext = ^V
    flush = ^O
How come, actually, that ^R does the history search, even though it has been set to redraw the current line?
Thanks! Yeah I have no idea! I only just realised that ^H works because of a bash binding, while stty takes it from the erase key (which is rendered as '?').
Anyone looking for the zsh equivalent of the `bind -P | grep` command, it's just `bindkey`.
I found these two references a long time ago, great intro to readline and how to setup an effective .inputrc: http://www.chemie.fu-berlin.de/chemnet/use/info/octave/octav... and http://www.ukuug.org/events/linux2003/papers/bash_tips/

Since then, .inputrc has been an indispensable part of my dotfiles! This one alone saves so much headache:

    # Incremental search with Up and Down: add to ~/.inputrc
    "\e[A": history-search-backward
Isn't this ctrl-r by default? With ctrl-shift-r to search forward?
no, by default ctrl-r searches through your history based on subsequent keystrokes. although if you're good with it, it's just as fast as up/down arrows.
I think it's different. With these ones you can start typing a cmd, say 'dd ' and then hit up and it will got through all of the previous commands that started with 'dd '.

    "\e[A": history-search-backward
    "\e[B": history-search-forward
I'm on a mac using iTerm so I also have:

    "\ed": backward-kill-word
and have added a shortcut to iTerm to send escape-d when I hit alt-delete. It's like a softer version of ctrl-w, which I've found indispensable since I started using it. It's actually more consistent with the standard Mac alt-delete
C-r is reverse-search-history. You press C-r and start typing your search pattern to trigger an incremental search. Most recent command matching the pattern anywhere in the command is selected.

In contrast, history-search-backword requires you to start typing your pattern followed by the keystroke it was bound to. The most recent command that starts with your search pattern is selected.

Made a reddit thread to find .inputrc hacks or nice ideas. No success. I like having custom keybindings in the shell. But ultimately I will miss emacs when doing so.
I've increased my productivity recently by starting to use ctrl+p and ctrl+n for the previous and next command instead of the arrow keys, combined with ctrl+j for <enter> it has really made everything just a bit easier on the fingers.
Interesting - has it made so much of a difference as to be worth the pain of transition?
I think it took me about 10 minutes to get used to it, it really is rather convenient. I still use <enter> very often when typing regular commands, but when I cycle through previous commands with ctrp+p/n it is much easier to hit ctrl+j.

Also, because my hands stay on the regular keys I don't have to look at my keyboard when switching betweeen typing commands and going through the history. It just feels more natural.

use `set -o vi` to use vim binding, if you don't like emacs :)
I've tried that a couple of times in the past but I just couldn't make it work for me. I guess it's vi instead of vim, so it felt really crippled in comparison. I seem to recall there was no normal / insert context either so you didn't know which mode you were in.

I'd be willing to try again if anyone had any good pointers for how to use it effectively though.

Toying with \e* nearly broke bash/xterm .. probably because of too many chars on screen and completion.