bash: vim mode instead of vi mode? - bash

I noticed when in vi mode in bash (i.e. the mode enabled with "set -o vi"), that some commands, such as "diw", that work in vim but not in vi, don't work on the bash command line. Is there an easy way to configure bash so that its keybindings will support vim commands? I would like to be able to enter vim commands on the command line without having to actually start the vim program, as described in this question.

The best way of doing this that I know of would be to use athame.
It can be a surprisingly powerful experience in some cases. I particularly like it for interacting with a repl.
Athame patches your shell to add full Vim support by routing your keystrokes through an actual Vim process. Athame can currently be used to patch readline (used by bash, gdb, python, etc) and/or zsh (which doesn't use readline).
Alternatively I find spacemacs with the eshell to be a reasonably functional if strange solution.

Teach vi-command-mode diw to any software that uses readline (such as bash) by adding this to your ~/.inputrc:
set keymap vi-command
"diw": "bde"

First, the "vi mode" you get with set -o vi is not vi itself. It's an incomplete approximation of vi's behavior built into readline, the command-line editing library used by bash under the hood.
Second, because it is incomplete there's no reason whatsoever to expect every vi command to work.
Third, no, there's no "vim mode" so even less reason to expect any vim commands to work.
Fourth, if you absolutely want to edit the current command-line with Vim-like commands, why don't you go all the way and… actually use Vim:
<C-x><C-e>
That said, $ man readline tells you everything you need to customize its behavior and add bindings.

You can use ble.sh. Which is a command line editor written in pure Bash which replaces the default GNU Readline. I like to call it "zsh for bash".
Appart from vim-style navigation it gives you:
Enhanced completion
Syntax highlighting
Other interesting features
After installation don't forget to add (recommended) to your .bashrc:
# at the start of your .bashrc file
[[ $- == *i* ]] && source /usr/share/blesh/ble.sh --noattach
...
#for vim-style mode
set -o vi
...
#at the end of your .bashrc file
[[ ${BLE_VERSION-} ]] && ble-attach
or you can just:
# at the start of your .bashrc file
source /usr/share/blesh/ble.sh
but this may not work as expected - read this.

Related

Ctrl-P doesn't work on vi mode of command line editing on mac terminal

https://www.gnu.org/software/bash/manual/html_node/Readline-vi-Mode.html
said we could do set -o vi to use vi mode instead of emacs mode for command line editing.
And the help: ex-edit-index sais
c_CTRL-P CTRL-P after using 'wildchar' with multiple matches:
go to previous match, otherwise: recall older
command-line from history.
However when I press CTRL-P I just got ^P
May I know why ?
Readline's "vi mode" is neither vi nor Vim. It is a partial emulation of vi shoehorned into the command line context.
That <C-p> you are referring to is a Vim command so there is no reason whatsoever to expect it to do anything in that context. Vim's documentation is totally irrelevant in this case.
Search for Vim Mode bindings in $ man readline for the actual bindings at your disposal in that "mode".

How to open a file in linux without specifiying editor?

I have emacs as my defualt editor in linux, and I also have alias in my .cshrc file.
alias e "emacs -mm"
Sometime I just want to hit the file name in the command line and open it in emacs directly with out the editor beign metioned.
Example instead of
$ e foo.cc&
What I want is to open
$foo.cc
May be this is lazy to do but it saves a lot time if you have so many files to handle. Thanks for the help.
You probably cannot open a file with $foo.cc (and that would be ambiguous for a shell script script.sh: would script.sh means "edit the file script.sh" or "run the shell script script.sh" ?). However,
You might want to use xdg-open, or the $EDITOR variable (see environ(7)). If you always have a single emacs running, you might set EDITOR to emacsclient in your ~/.bashrc (if using /bin/bash) or your ~/.zshrc (if using /bin/zsh)
BTW many editors (including emacs, gedit, vim) are able to edit several files, i.e. $EDITOR *.c
And depending upon your login shell (zsh, fish, or bash) you could set up a shell function or alias to simply type e foo.c; I feel that it is not worth the effort, since with autocompletion I just have to type 3 keys e m tab to get emacs (and often the up arrows are enough)
Actually I start only once every day emacs then open many files inside it (and also I compile inside emacs)
BTW, you should avoid csh since it is considered harmful. Install a good interactive shell (e.g. with sudo aptitude install zsh zsh-doc) and use once chsh(1) to make it your login shell.

How to extend bash's vi mode

I want to customize vi mode in bash. Two things I want to do very badly.
Map Esc to CAPS_LOCK and CAPS_LOCK to SHIFT+CAPS_LOCK
Use 'm' to mark current directory to a character 'a-z' and use ' to cd to that directory.
In general, is there a way to extend vi mode in bash?
Bash uses GNU readline to provide a usable command line prompt. Readline supports vi mode that provides a basic set of keys and a modal interface for it.
Mappings of caps lock and others is not bash's or readline's job. If you are willing to make those bindings global, you can use Xmodmap to achieve satisfactory results.
As for the second question: Unfortunately, the configurability of readline is very limited. But you could achieve something like that by writing functions that you init via a loop.
The following kind of works:
Set_Ma () {
DIR_a=`pwd`
}
Go_Ma (){
cd "$DIR_a"
}
set -o vi
bind -m vi-command -x '"ma":"Set_Ma"'
bind -m vi-command -x '"'"'"'a":"Go_Ma"'
You won't see any effect immediately after typing 'a because it doesn't redraw the prompt to match new CWD. You could also use an associative array for storing the marks but I won't go there.
May I suggest jumping in the ZSH bandwagon. Zsh doesn't use readline. Instead they wrote a more flexible library for line editing that can be properly scripted by ordinary zsh functions.
You can change options from within vi by using the ex command :set. In addition, whenever vi is started up, it reads a file in your home directory called .exrc for further operating instructions. By placing :set commands in this file, you can modify the way vi acts whenever you use it.
You can also set up .exrc files in local directories to initialize various options that you want to use in different environments. For example, you might define one set of options for editing English text, but another set for editing source programs. The .exrc file in your home directory will be executed first, then the one in your current directory.
Finally, any commands stored in the shell variable EXINIT will be executed by vi on startup. If there is a conflict between settings made in .exrc and EXINIT, those in .exrc take precedence.
Hope this might help you
Thanks

macvim shell (:sh) only displays character codes / escape sequences

Just compiled MacVim with homebrew. Here's what it looks like when I :sh and then type ls:
http://cloud.jtmkrueger.com/image/2N0S0T3k3l1J
As you can see, it's just character codes.
UPDATE
I run oh-my-zsh
Tried installing the plugin named here:
http://vim.1045645.n5.nabble.com/ANSI-colors-td1219411.html
Didn't seem to help
ANOTHER UPDATE
Upon removing my zsh syntax highlighting plugin It seems to work ok. Is there a way to turn off zsh plugins when using oh-my-zsh only when it's a vim 'dumb terminal'?
When you do :sh in GVim or MacVim, you don't get a real terminal emulator.
It's "dumb" and there's no way to make it understand those escape sequences. You better get used to it or ask (with convincing arguments and a ready-made patch) on the vim-dev mailing list.
You might want to try the ConqueTerm plugin which does its best to interpret ANSI sequences, even inside MacVim.
Just for the reference, :h guioptions now support the following flag:
'!' External commands are executed in a terminal window. Without
this flag the MS-Windows GUI will open a console window to
execute the command. The Unix GUI will simulate a dumb
terminal to list the command output.
The terminal window will be positioned at the bottom, and grow
upwards as needed.
Set :set go+=!, run :sh, and be surprised :).
What you see is actually not just character codes, but your usual shell prompt which contains color codes. You can probably disable it by redefining PS1 or remove your modified definition in ~/.bashrc.
If you would like to use a color prompt on the command line, but not in MacVim you can fix this in ~/.bashrc by setting PS1 differently when inside vim (from here)
if [ $VIM ]; then
export PS1='\h:\w\$ '
fi
You could try the following, instead of ls, type command ls; it shouldn't show the escapes codes.
If it works you can simple create a new file in a folder in your path, say vls, with the following contents:
#!/bin/sh
command ls $#
after that chmod +x vls and again, if it is in your path, you should be able to use that from vim.

Bash usage of vi or emacs

From a programming standpoint, when you set the bash shell to use vi or emacs via
set -o vi
or
set -o emacs
What is actually going on here? I've been reading a book where it claims the bash shell uses either of these editors for the input to the shell itself, but I thought it may have used readline.
Bash is still using readline. Readline uses either emacs or vi mode and setting the mode switches between the various editor modes. You can check the lib/readline folder in the base source code to see the various key bindings.
According to the man page BASH_BUILTINS(1) (on Fedora 8):
set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
... (skipping all the single letter options)
-o option-name
The option-name can be one of the following:
...
emacs Use an emacs-style command line editing interface. This is
enabled by default when the shell is interactive, unless the
shell is started with the --noediting option.
...
vi Use a vi-style command line editing interface.
I interpret that to mean that bash is directly interpreting the commands for line editing. This option simply sets which command set to use. See the man page for readline(3).
It uses the keystrokes that are familiar to users of one of those editors to edit the command line.
Readline is the facility that provides that feature to Bash and other programs.
From man bash:
READLINE
This is the library that handles reading input when using an interac‐
tive shell, unless the --noediting option is given at shell invocation.
Line editing is also used when using the -e option to the read builtin.
By default, the line editing commands are similar to those of emacs. A
vi-style line editing interface is also available. Line editing can be
enabled at any time using the -o emacs or -o vi options to the set
builtin (see SHELL BUILTIN COMMANDS below). To turn off line editing
after the shell is running, use the +o emacs or +o vi options to the
set builtin.
From what I know, readline is what provides the line-editing functionality for bash.
One proviso: when you press v in vi command mode, you get the full blown vi editor to edit your command line.
From man bash:
READLINE
This is the library that handles reading input when using an interactive shell, unless the --noediting option is given at shell invocation. By default, the line editing commands are similar to those of emacs. A vi-style line editing interface is also available. To turn off line editing after the shell is running, use the +o emacs or +o vi options to the set builtin.
When the shell presents you with a prompt (unless you're in non-editing mode), you're already using readline. You'll either be in emacs mode or vi insert mode (which is why you can just use ESC to get back to vi command mode).

Resources