Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I use the vi keybindings in my tcsh shell.

Now, I don't know which vi mode I'm in (insert mode or command mode), which leads to a lot of frustration.

Does anyone know of a way to show the current vi mode in the shell? (by including in the prompt or something)

share|improve this question
up vote 3 down vote accepted

I don't believe there is any way to determine visually what mode your in, but if you modify your behavior a little it won't matter.

If you want to be in command mode, press ESC before typing a command.

If you want to be in insert mode, press ESC and i before typing content.

You will end up pressing ESC a lot, but every vi user I've ever met does that anyway.

share|improve this answer
The problem is that, in the shell, the extra ESCs are not ignored - when I give an extra ESC, then type a command (say h to move left), it simply gives a beep and doesn't do anything. – sundar Aug 13 '09 at 12:50
By "extra ESC", I mean pressing ESC when I'm already in command mode - which I do a lot since I don't know what mode I'm in. – sundar Aug 13 '09 at 12:50
You are correct. I've used it so long that I don't even notice that behaviour any longer. Again, the simplest answer. If you hit ESC and h and nothing happens, hit h again. I think that opens up another question. Why does pressing ESC while in the 'command' mode of the vi keybindings cause the next character to not be interpreted correctly? vi itself doesn't do this. I can type ESC 10 times and the next command still works as anticipated. – Bob Weber Aug 13 '09 at 22:54
Another tip, turn off the bell. It is incredibly annoying just for the reason you describe - and because it beeps on tab completion. There are various ways of doing this depending on your environment. – Bob Weber Aug 13 '09 at 23:01
Ok, I'm currently giving this solution a try. Mapping Caps Lock to Escape has made implementing this easier, but I'm yet to get used to ESC-i for insert mode. I hope I will soon. >If you hit ESC and h and nothing happens, hit h again The problem with this is, it is quite frustrating and breaks the flow a lot. It's an extra thing that I have to think about in addition to the command I'm forming. I prefer vi keybindings for the very reason that they're in my muscle memory and give one less thing to think about - this sort of breaks that purpose itself... – sundar Aug 16 '09 at 23:56

I've had a look through the documentation, and I'd have to say I couldn't find any way to detect and display the current vi-mode. I do hope you have a pleasant surprise and someone comes up with a solution, but I certainly can't see a way to do what you ask.

I think there is a way to do this, but it is massive overkill for a tiny annoyance, and I don't think that's what you had in mind when you posed this question. If this is true, stop reading now and enjoy your life.

OTOH, if this really is your pet peeve, and it's driving you crazy, and you really absolutely desperately wanna gonna smack this problem, here's my idea of how to go about it:

  1. Get a copy of Advanced Programming in the UNIX(R) Environment by W. Richard Stevens.
  2. Read the chapters on Streams and Terminal I/O.
  3. Download the source code to the aforementioned book, which includes an example of a stream that can be layered onto a terminal.
  4. Implement your handling for the Esc key combination (or both mode change keypresses), and indicate it via a bell or background manipulation of the current line.

In brief, Unix implements terminal I/O as a full-duplex I/O stream between the device driver and the user process, into which modules can be inserted. It is organized as a stack, so you can layer as many streams as you want. The sum of the injected streams creates your terminal I/O behaviour.

When a character is entered, the first module gets to inspect it and pass it on (if it wants to). When the response arrives in the opposite direction, it again gets a chance to inspect and pass it on. This is how a Ctrl-C gets handled at a higher level to a normal character key.

You can create a binary implementing a stream module, that when invoked runs silently in the foreground, inspecting and passing on all keystrokes, performing your preferred action on the keystrokes you care about. For all intents and purposes, it'll appear as if you're working on the shell. Oooh. You can invoke this binary on the last (or first, or any) line of your .tcshrc and you wouldn't even know it's there.

There's a good primer here, but I couldn't find much on this topic, probably because it's past its prime.

share|improve this answer

This page has a fairly detailed script which sets up what you want (and more) in zsh. Perhaps it could be adapted to work with tcsh (I am not terribly familiar with that shell).

share|improve this answer
I'm not familiar with tcsh either, but I think the page you showed uses zsh widgets (with zle). I don't think other shells have that, but if they do, that would definitely do the trick. – BrianH Aug 14 '09 at 19:21

Command-Line Editing with tcsh

There are two main modes for editing the command line,
based on the two most commonly used text editors, Emacs and vi.

With the vi bindings, you must switch between insert and command modes;
different commands are useful in each mode.

vi mode has two submodes, insert and command mode.

  • Default mode is insert.
  • You can toggle between the modes by pressing Esc.
  • Alternatively, in command mode,
    typing 'a' (append) or 'i' (insert) will return you to insert mode

More notes on the tcsh customization page already linked above.

share|improve this answer
Your links go to copyrighted O'Reilly books... – BrianH Aug 14 '09 at 19:20

I had the same exact problem and by accident have found the solution. Although this thread is old, I couldn't find any other website that offered a solution, so I assume posting on this thread is okay.

Just reset the settings of your terminal program or shell. I'm currently using PuTTY, and I just deleted my saved settings for my saved connection, and recreated a saved session. Worked like a charm.

Hope this helps!

share|improve this answer

Please see my answer on SO. Bash 4.4 / Readline 7.0 will add support for this functionality, and in the interim I've published patched versions of Bash 4.3 / Readline 6.3 to github.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.