Why do I have to press C-b twice to move one char back in bash emacs mode? - bash

I am using emacs key-bindings in bash. To move one character back, I have to press C-b twice. Is there a way to avoid this ?
I am having the same problem while running emacs editor also. If I start a C-s forward search and I enter some wrong characters that are not in the file, emacs shows search failed, and to correct the characters, I have to press Backspace key twice. Is there a solution for this too ?

Related

How to set up Iterm / vim so that vim can recognize alt key mapping?

I have read a couple of different solutions to get the alt modifiers working on mac/iterm in vim.
The first solution I see posted online is to map the special characters produced by the alt key within .vimrc. This work-around almost works but I encountered a problem with alt-e. On macos catalina, and USA keyboard, when I type alt-e it produces a ´ character and then waits to for more input. If I then type a j for example, the ´ turns into j́. This waiting for more input is problematic for mapping alt-e in vim.
The other solution I see online is to configure iterm to send the Esc+ codes with alt key presses. As it turns out, this Esc code is the same code sent to vim when you press Esc, which means mapping alt characters would have the unwanted effects such as literally pressing Esc + the character to trigger the same keybind.
How could I get this to work?

Delete (forward) character iTerm2 OSX

I am using iTerm2 on OSX, and I am using an external keyboard with a Del (not to be confused with Backspace). The Del key works fine in OSX but in Terminal and iTerm, it inserts "~" instead of deleting forwards one character. This is easily fixable in Terminal, but in iTerm, there is no key binding or escape sequence that allows me to delete a character to the right of the cursor (the equivalent Unix command is Ctrl D). Is there any way I can simulate deleting forwards one character in iTerm?
If you are using zsh, try adding these lines to your ~/.zshrc file, then close and reopen the terminal:
bindkey "^[[3~" delete-char
bindkey "^[3;5~" delete-char
These should enable your delete key on any keyboard, without manual keyboard mappings to the hex command 0x04, which has the problem that it closes the session if the input is empty.
Why this? Because it seems that zsh doesn't read /etc/inputrc with the key bindings by default.
Like Gajus said, using Ctrl-D to delete one backspace forward also closes the terminal tab if there's no input which can be very frustrating.
I am using zsh, but adding the lines ricpacca suggested to .zshrc didn't work for me.
What I did instead is to map Ctrl-Delete to send the hex codes "0x06 0x08".
0x06 translates to "move one character forward", and 0x08 is just a normal backspace.
Thought I'd share my solution for any other frustrated iTerm2 users that scoured the internet to no avail.
You can add a iTerm Keyboard Mapping in Global Preferences or a Profile-based one for the key to send a Ctrl-D (0x04)
i.e: Here I am mapping Ctrl-Delete to Erase (Ctrl-D/0x04) like an Extended Keyboard's Del key:

Bash shell command inline correction

When typing a (long) command in the bash shell, if you were to make a mistake early in the line, is there a way to correct that mistake without having to navigate back to it? For example, lets say you have just entered something like this, but not yet pressed return:
git commit =m 'Some really long commit message, perhaps spanning multiple lines'
where you have accidentally typed = instead of -, would it be possible to append something to the end of the command before you press enter that would perform an in-line substitution to correct the mistake? This would be really handy to avoid having to do something annoying like
Pressing Ctrl+C and then rebuilding the command using a combination of copy and paste.
Pressing the left arrow a huge bunch of times so that it can be corrected before pressing enter.
One solution (in theory) would be to pipe the contents of the whole command through sed, however I am not sure how to capture the command as a string of text that could then be used in this manner.
What I would do : ctrl+a
then move the cursor after the =, then hit ctrl+w.
The latest delete the previous word.
Multiple shortcuts can help here:
Use ctrl+a to go to the beginning of the line
Use alt+b and alt+f to move forward and backward one word at a time
Use alt+e to open an editor ($EDITOR) containing your current command, edit it, then close your editor.

Vim in Mac OS X Terminal: Move cursor word by word

I have followed the guidance in Is there any way in the OS X Terminal to move the cursor word by word? and now in terminal I can move cursor word by word.
However, in Vim, I am only able to move backward word by word. I cannot move forward word by word, no matter I set \033f to option+cursor-right or shift+cursor-right. The only workaround I figured out is to go to normal mode and click <w> to move to next word. Any idea about how to fix that? Thanks.
w is not a workaround. It's the primary way to move word by word (see also: W, b, B, e, E). What you want is a workaround that won't help you learn Vim at all.
Some may argue that moving around with VIM native keyboard shortcuts is not a workaround, but for me it sure is both very inconvenient and very inefficient. Especially the part where you need to switch between insert mode and normal mode just to move to the next word.
That's why I came up with a solution based on this answer on SuperUser. The idea is to map input provided by the Terminal.app directly in VIM. The answer on SU shows what to put into your vimrc file for the Home/End keys to work as expected.
My tweaked version below includes the Option+arrow (or Alt+arrow) navigation on words. I've tried to mimic the behavior of Terminal's moving around as close as I could get. So pressing Option+Right (Alt+Right) will move the caret to the next character after the word (as opposed to the last character of the word, which is VIMs w native bahavior).
let tp=$TERM_PROGRAM
if tp == 'Apple_Terminal'
:" map Mac OS X Terminal.app
" map Home/End:
:map <ESC>[H <Home>
:map <ESC>[F <End>
" small 'o' letter in <C-o> means no exit from the insert mode
:imap <ESC>[H <C-o><Home>
:imap <ESC>[F <C-o><End>
:cmap <ESC>[H <Home>
:cmap <ESC>[F <End>
" map Option+Left/Option+Right:
" for this to work you must have the bindings in Settings > Keyboard set
" as follows:
" 'option cursor left' to '\033b'
" 'option cursor right' to '\033f'
:map <ESC>f el
:imap <ESC>b <C-o>b
:imap <ESC>f <C-o>el
:cmap <ESC>f el
endif
As a small, but significant bonus you get Home/End navigation without exiting the insert mode. Tested on 10.8.5.
Let me clear a few things up for you. Bash (the shell program running inside the terminal) has the behavior you are used to. (Using Alt+f to move forward by word, and Alt+b to move backward by word.) This was originally done to be like Emacs. You can use the command
set -o vi
to switch to vim behavior. In this mode, you can use Esc to switch to normal mode, and move around like in vim; then press i to go back to insert mode.
So don't be surprised that Vim isn't trying to act like Emacs. The whole power behind vim lies behind these simple motions.

Fastest way(s) to move the cursor on a terminal command line?

What is the best way to move around on a given very long command line in the terminal?
Say I used the arrow key or Ctrl-R to get this long command line:
./cmd --option1 --option2 --option3 --option4 --option5 --option6 --option7 --option8 --option9 --option10 --option11 --option12 --option13 --option14 --option15 --option16 --option17 --option18 --option19 --option20 --option21 --option22 --option23 --option24 --option25 --option26 --option27 --option28 --option29 --option30 --option31 --option32 --option33 --option34 --option35 --option36 --option37 --option38 --option39 --option40 --option41 --option42 --option43 --option44 --option45 --option46 --option47 --option48 --option49 --option50
Now I need to move (starting from the beginning or the end of the line) the cursor to --option25 to modify something there.
What is the fastest way to get there? What I usually do is Ctrl-A to get to the beginning and then repeatedly Alt-F to move forward, word by word (or Ctrl-E to go the end and Alt-B to then go backward). But on a long line that takes too much time. There must be a way to search and jump directly to the part I need to modify, e.g. option25?
To be clear, you don't want a "fast way to move the cursor on a terminal command line".
What you actually want is a fast way to navigate over command line in you shell program.
Bash is very common shell, for example.
It uses Readline library to implement command line input. And so to say, it is very convenient to know Readline bindings since it is used not only in bash. For example, gdb also uses Readline to process input.
In Readline documentation you can find all navigation related bindings (and more):
http://www.gnu.org/software/bash/manual/bash.html#Readline-Interaction
Short copy-paste if the link above goes down:
Bare Essentials
Ctrl-b Move back one character.
Ctrl-f Move forward one character.
[DEL] or [Backspace] Delete the character to the left of the cursor.
Ctrl-d Delete the character underneath the cursor.
Ctrl-_ or C-x C-u Undo the last editing command. You can undo all the way back to an empty line.
Movement
Ctrl-a Move to the start of the line.
Ctrl-e Move to the end of the line.
Meta-f Move forward a word, where a word is composed of letters and digits.
Meta-b Move backward a word.
Ctrl-l Clear the screen, reprinting the current line at the top.
Kill and yank
Ctrl-k Kill the text from the current cursor position to the end of the line.
M-d Kill from the cursor to the end of the current word, or, if between words, to the end of the next word. Word boundaries are the same as those used by M-f.
M-[DEL] Kill from the cursor the start of the current word, or, if between words, to the start of the previous word. Word boundaries are the same as those used by M-b.
Ctrl-w Kill from the cursor to the previous whitespace. This is different than M- because the word boundaries differ.
Ctrl-y Yank the most recently killed text back into the buffer at the cursor.
M-y Rotate the kill-ring, and yank the new top. You can only do this if the prior command is C-y or M-y.
M is Meta key.
For Max OS X Terminal you can enable "Use option as meta key" in Settings/Keyboard for that.
For Linux its more complicated.
Update
Also note, that Readline can operate in two modes:
emacs mode (which is the default)
vi mode
To switch Bash to use vi mode:
$ set -o vi
Personaly I prefer vi mode since I use vim for text editing.
Bonus
In macOS Terminal app (and in iTerm too) you can Option-Click to move the cursor (cursor will move to clicked position). This even works inside vim.
Since this hasn't been closed yet, here are a few more options.
Use Ctrl+x followed by Ctrl+e to open the current line in the editor specified by $FCEDIT or $EDITOR or emacs (tried in that order).
If you ran the command earlier, hit Ctrl+r for a reverse history search and type option25 (in this case). The line will be displayed. Hit Tab to start editing at this point.
Use history expansion with the s/// modifier. E.g. !-2:s/--option25/--newoption/ would rerun the second-to-last command, but replace option25. To modify the last ./cmd command, use the !string syntax: !./cmd:s/--option25/--newoption/
Any delimiter may be used in place of / in the substitution.
If editing the previous line, you can use quick substitution: ^--option25^--newoption
Character search. This was mentioned by Pax, and can be done in regular emacs-mode with Ctrl+] for forward search, and Ctrl+Alt+] for backward search.
I recommend the second option. Ctrl+r is really handy and fast, no mucking about with editors, and you see the results before the command is run (unlike the history expansions).
Hold down the Option key and click where you'd like the cursor to move, and Terminal rushes the cursor that precise spot.
I tend to prefer vi editing mode (since those keystrokes are embedded into my spinal cord now (the brain's not used at all), along with the CTRL-K, CTRL-X from WordStar 3.3 :-). You can use the command line set -o vi to activate it (and set -o emacs to revert).
In Vi, it would be (ESC-K to get the line up first of course) "f5;;B" (without the double quotes).
Of course, you have to understand what's on the line to get away with this. Basically, it's
f5 to find the first occurrence of "5" (in --option5).
; to find the next one (in --option15).
; to find the next one (in --option25).
B to back up to the start of the word.
Let's see if the emacs aficionados can come up with a better solution, less than 5 keystrokes (although I don't want to start a religious war).
Have you thought about whether you'd maybe like to put this horrendously long command into a script? :-)
Actually, I can go one better than that: "3f5B" to find the third occurrence of "5" then back up to the start of the word.
Use Meta-b / Meta-f to move backward/forward by a word respectively.
In OSX, Meta translates as ESC, which sucks.
But alternatively, you can open terminal preferences -> settings -> profile -> keyboard and check "use option as meta key"
After running the command once, run fc
It will launch $EDITOR with the previous command, then you can use your regular editor to modify the command. When you save and exit, the file will be executed.
..but, as Pax said - the command line isn't particularly good for editing absurdly long lines - why not make the command into a script?
If you want to move forward a certain number of words, hit M-<n> (M- is for Meta and its usually the escape key) then hit a number. This sends a repeat argument to readline, so you can repeat whatever command you want - if you want to go forward then hit M-<n> M-f and the cursor will move forward <n> number of words.
E.g.
$|echo "two three four five six seven"
$ M-4
(arg: 4) echo "two three four five six seven"
$ M-f
$ echo "two three four| five six seven"
So for your example from the cursor at the beginning of the line you would hit, M-26 M-f and your cursor would be at --option25| -or- from the end of the line M-26 M-b would put your cursor at --|option25
Incremental history searching
in terminal enter:
gedit ~/.inputrc
then copy paste and save
"\e[A": history-search-backward
"\e[B": history-search-forward
"\e[C": forward-char
"\e[D": backward-char
all you need to do to find a previous command is to enter say the first 2 or 3 letters and upward arrow will take you there quickly say i want:
for f in *.mid ; do timidity "$f"; done
all i need to do is enter
fo
and hit upward arrow command will soon appear
It might not be the fastest, but this need to be here, some reading about ANSI cursor movements
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
- Position the Cursor:
\033[<L>;<C>H
Or
\033[<L>;<C>f
puts the cursor at line L and column C.
- Move the cursor up N lines:
\033[<N>A
- Move the cursor down N lines:
\033[<N>B
- Move the cursor forward N columns:
\033[<N>C
- Move the cursor backward N columns:
\033[<N>D
- Clear the screen, move to (0,0):
\033[2J or \033c
- Erase to end of line:
\033[K
- Save cursor position:
\033[s
- Restore cursor position:
\033[u
(...)
Try putting in the following line of code at the prompt (it's a little clearer what it does if the prompt is several lines down the terminal when you put this in): echo -en "\033[7A\033[1;35m BASH \033[7B\033[6D" This should move the cursor seven lines up screen, print the word " BASH ", and then return to where it started to produce a normal prompt.
Examples:
Move the cursor back 7 lines:
echo -e "\033[7A"
Move the cursor to line 10, column 5:
echo -e "\033[10;5H"
Quickly echo colors codes, to colorize a program:
echo -e "\033[35;42m" ; ifconfig
using option key and using a click the place you want to place the cursor with mouse or touchpad is you are using Mac build-in terminal.
One option is to use M-x shell in emacs. That provides all editing facilities and keystrokes that emacs has, so C-s can be used to search the text option25, for example.
(But I'd still prefer to be in the real terminal shell instead if someone can point me to good search and edit facilities.)
Use the mouse
Sometimes, the easiest way to edit a commandline is using a mouse. Some previous answers give a command to open your current line in your $EDITOR. For me (zhs with grml config) that combination is Alt+e. If you enable mouse in your editor, you can make use of it.
To enable mouse in Vim, add this to your ~/.vimrc
set mouse=a
set ttymouse=xterm2
If you then want to do a text selection in terminal (instead of passing the mouseclick to vim), hold Shift when you click; this is terminal specific, of course.
Sysadmins should not be afraid of the mouse.
In Cygwin, you can activate such feature by right-clicking the window. In the pop-up window, select Options... -> Mouse -> activate Clicks place command line cursor -> Apply.
From now on, simply clicking the left mouse button at some position within the command line will place the cursor there.
first:
export EDITOR='nano -m'
then:
CTRL+X CTRL+E in sequence.
You current line will open in nano editor with mouse enable. You can click in any part of text and edit
then CTRL+X to exit and y to confirm saving.
I made a script to make the command line cursor move on mouse click :
Enable xterm mouse tracking reporting
Set readline bindings to consume the escape sequence generated by clicks
It can be found on github
More info on another post
Will work if echo -e "\e[?1000;1006;1015h" # Enable tracking print escape sequences on terminal when clicking with mouse

Resources