zsh shortcut 'ctrl + A' not working - shell

I recently switch from bash to zsh shell. To be more precise, the oh-my-zsh
Very nice, but the shortcut I most often use; jumping to the beginning/end of the line doesn't work anymore. From the docs it should be
ctrl + A --> beginning
ctrl + E --> end
However, when I do that I get the following
$~> my-command
$~> my-command^A # did a ctrl + A here
Although I see this working by everybody else, on my system something seems to be different. Any suggestions what that might be ?

If you're wondering why this happened: You likely have $EDITOR or $VISUAL set to vi/vim which made zsh default to the vi keymap which doesn't use ctrl+a for moving the caret.
Adding bindkey -e to ~/.zshrc will restore the old behavior (emacs keymap).

you don't have to config the Ctrl+A behavior if you use default keymap (emacs keymap). It does what you are expecting.
However if you set your zle to use vi keymap, you have to define the keybind for vi-beginning-of-line. same for Ctrl+E.
So check which keymap did you set in config. If it was vi, try pressing ESC then ^ and $ should do what you want.

zsh .zshrc
bindkey "^A" vi-beginning-of-line

Related

ZSH shell and CLion/PyCharm integration, movement around terminal

I'm trying to use zsh in the CLion terminal window (changed my shell to /bin/zsh)
But when I try to move around using Ctrl + Left, Ctrl + Right, Ctrl + E... I get the literal characters D, C and Ctrl + E opens the "Recent files" UI
Is there any way around this? I'd like to use the movement keystrokes as I can with bash.
Tempoz,
Check out the offical Zsh Line Editor doc and the Z-Shell Line Editor guide for tons of detail.
To start, you can see your current mappings by typing bindkey at your prompt. There are two start modes: emacs [default], and vi. If you want to use vi mode, add this to your ~/.zshrc
bindkey -v
and source it (or restart your shell, or restart your IDE). Check out how the bindkey output has changed.
If you decide you want to change or augment your key mappings, use bind in your ~/.zshrc to reassign, or add to your key map.
# Example key binding change
# bindkey key-sequence editor-command
bindkey '^Z' vi-kill-line
You will also probably want to fix your $PATH - all the JetBrains products do it incorrectly. See this answer: https://stackoverflow.com/a/51006003/1089228

"Home" and "End" in IntelliJ terminal on Mac with zsh

I would like to bind fn+→ and fn+← to "End" and "Home" in the IntelliJ terminal on my Mac (this is the very same combination that iTerm uses).
If this is not possible, I could also live with ⌘+→ and ⌘+←.
I know that ctrl+e and ctrl+a can be used for jumping to the start and end of a line but for convenience I'd like to use the same combinations as within iTerm.
Edit
Interestingly, my keymap shows ↖ and ↘ as keybord shortcut for Move Caret to Line End and Move Caret to Line Start - it works in the editor - but it does not work in the terminal:
Edit 2
I found out that the problem occurs only with zsh - when I use bash, fn+→ and fn+← work as expected. Any ideas where IntelliJ and zsh might conflict here? It works with the very same zsh configuration in iTerm.
After searching for a while, I stumbled over this post
https://youtrack.jetbrains.com/issue/IDEA-118848
that covers the issue, a fix was proposed here
https://github.com/robbyrussell/oh-my-zsh/issues/4784#issuecomment-180940049
Following this fix, I added
bindkey "^[[H" beginning-of-line
bindkey "^[[F" end-of-line
to my .zshrc and now everything works like a charm.
Default OS X bindings have fn+→ and fn+← to "End" and "Home" respectively.
If that is not the case for you, please update from keymap in settings panel.
Titled arrow shown in keymap binding means fn+→ or fn+← (based on direction of the arrow).

How to change shortcut for iTerm2 clear lines?

Ctrl + l is the default shortcut for clear lines in iTerm2, I want to change it to Cmd + l, but can't find this action:
BTW I'm using zsh.
Ctrl-L or "form feed" is part of the ANSI/VT100 protocol (http://wiki.bash-hackers.org/scripting/terminalcodes), it's not specific to iTerm2.
Your best best is to use Applescript to send Ctrl-L to the terminal when Cmd-L is pressed.
This is an zsh binding is not an iTerm binding. Ctrl+l is the default binding for the clear-screen widget in zsh. The fact that it also works in bash (and maybe other shells) is merely convention. In bash - or rather readline, bash's command line editor - it is the default binding for a command that is also named clear-screen.
Generally, you can change a key binding in zsh with the command bindkey KEYSEQUENCE WIDGET. Unfortunately not all modifiers might be supported by iTerm2 for use with the shell. You can test, whether it is supported by running cat -v and then pressing the desired key combination. If Cmd+l is supported, than the output shown should be more than just "l". If it something more or other than just "l", then you can use the output to bind it. For example if cat -v shows "^[l" than you can bind it with bindkey '^[l' clear-screen and if you want to remove the default binding, you can do so with bindkey -r '^l'.

bash/readline equivalent of escape-dot in vi-mode

Having recently switched to vi-mode in bash, the one thing I miss is esc . to get the last argument of the last command.
I know about ctrl _, but I always end up hitting ctrl - instead.
Is there another vi-mode equivalent for this?
I believe the closest solution to what you want is this:
In your .bashrc, right after "set -o vi"...
set -o vi
bind -m vi-command ".":insert-last-argument
This tells your bash to invoke the "insert-last-argument" action when '.' is used in vi-command mode. This of course means that you lose the normal "." functionality of VI; but if you are like me, you'll prefer this.
Addendum:
You may also want Ctrl-A, Ctrl-E, Ctrl-W and Ctrl-L to work (those were the ones I was missing the most):
bind -m vi-command ".":insert-last-argument
bind -m vi-insert "\C-l.":clear-screen
bind -m vi-insert "\C-a.":beginning-of-line
bind -m vi-insert "\C-e.":end-of-line
bind -m vi-insert "\C-w.":backward-kill-word
You can also use the following to restore the emacs "escape-dot inserts last argument" behaviour in vi mode:
bindkey -v '\e.' insert-last-word
By altering or adding ~/.inputrc
To restore certain bash goodies in vi-mode, simply alter or add ~/.inputrc like this:
set completion-ignore-case on
set show-all-if-ambiguous on
set show-all-if-unmodified on
set editing-mode vi
set keymap vi-insert
$if mode=vi
"\C-a": beginning-of-line
"\C-e": end-of-line
"\C-l": clear-screen
"\C-n": next-history
"\C-p": previous-history
"\C-w": backward-kill-word
"\e.": yank-last-arg
"\e_": yank-last-arg
$endif
Here are more bindable readline bash commands.
I always used alt . to get the last argument of the last command.
Also, the !$ will give you the last argument of the last command executed. There are a bunch of cool things you can do with the exclamation point, just check out the man page for bash and search for History Expansion.
How about just using $_ bash variable?
I'm pretty sure you can still use the equivalent for vi mode, which should be "ESC + ."

Is there a way to switch Bash or zsh from Emacs mode to vi mode with a keystroke?

I'd like to be able to switch temporarily from emacs mode to vi mode, since vi mode is sometimes better, but I'm usually half-way through typing something before I realize I want to use vi mode.
I don't want to switch permanently to vi mode, because I normally prefer emacs mode on the command line, mostly because it's what I'm used to, and over the years many of the keystrokes have become second nature. (As an editor I generally use emacs in viper mode, so that I can use both vi and emacs keystrokes, since I found myself accidentally using them in vi all the time, and screwing things up, and because in some cases I find vi keystrokes more memorable and handy, and in other cases emacs.)
You can create a toggle since the key bindings are separate between vi mode and emacs mode.
$ set -o emacs
$ bind '"\ee": vi-editing-mode'
$ set -o vi
$ bind '"\ee": emacs-editing-mode'
Now Alt-e (or Esc e) will toggle between modes.
Add this somewhere in your definition for PS1 so you have an indicator in your prompt of which mode you're in. It won't show the change immediately when you toggle modes, but it will update when a new prompt is issued.
$(set -o | grep emacs.*on >/dev/null 2>&1 && echo E || echo V)
Aha! I looked at the readline source, and found out that you can do this:
"\M-v": vi-editing-mode
"\M-e": emacs-editing-mode
There doesn't appear to be a toggle, but that's probably good enough!
For posterity's sake, here's my original answer, which could be useful for people trying to do things for which there is no readline function.
Here's a way you could set it up, clearing the current command line in the process. Not what you want, I know, but maybe it'll help someone else who finds this question. In ~/.inputrc:
"\M-v": "\C-k\C-uset -o vi\C-j" # alt (meta)-v: set vi mode
"\M-e": "\C-k\C-uset -o vi\C-j" # alt (meta)-e: set emacs mode
or to toggle...this should work:
"\M-t": "\C-k\C-u[[ \"$SHELLOPTS\" =~ '\\bemacs\\b' ]] && set -o vi || set -o emacs\C-j"
These are essentially aliases, taken one step farther to map to keys in readline so that you don't have to type an alias name and hit enter.
The following .inputrc lines allow Meta / Alt+E to switch between emacs and vi-insert modes.
Mooshing both j and k simultaneously will take you to vi-command mode.
Note: The only English word with "kj" is "blackjack", no words contain "jk")
set keymap emacs
"\ee": vi-editing-mode
"jk": "\eejk"
"kj": "\eejk"
set keymap vi-insert
"\ee": emacs-editing-mode
"jk": vi-movement-mode
"kj": vi-movement-mode
set keymap vi-command
"\ee": emacs-editing-mode
Note: If you add a binding under keymap emacs to vi-movement-mode to try to switch straight to vi-command mode, the prompt doesn't update if you have show-mode-in-prompt on, hence the above work-around is needed.
I finally found out how to toggle vi and emacs mode with a single key e.g. [alt]+[i] in zsh:
# in the .zshrc
# toggle vi and emacs mode
vi-mode() { set -o vi; }
emacs-mode() { set -o emacs; }
zle -N vi-mode
zle -N emacs-mode
bindkey '\ei' vi-mode # switch to vi "insert" mode
bindkey -M viins 'jk' vi-cmd-mode # (optionally) exit to vi "cmd" mode
bindkey -M viins '\ei' emacs-mode # switch to emacs mode

Resources