11

In Bash, we can use Alt+number+. to select the nth argument of previous commands, and Alt+, to select the previous commands. They cycles through the history.

For example:

$ ls 1 2
$ echo 10 20

Now press and hold Alt, and press 0 then dot, it will show "echo". Without releasing Alt, press . again, it will show "ls". Use 1 in the same operation will show 10 and 1, etc. Pressing Alt and comma shows the whole command line in the history. Also Alt and . show the last argument of the commands in history.

Note that all of these operations just insert the argument (or whole command line) to the current cursor. They don't change what's already there in the current command line.

I am using Zsh and the latest Oh-My-Zsh package but it seems the behavior is different:

  • Zsh has the Alt+, to show the last argument of commands.

  • The Alt+0+. is the same as Bash (shows the comman), but Alt+number+. shows the last nth argument, i.e., Alt+1+. in above case shows 20 and 2.

  • The Alt+, doesn't display the whole commands in history.

How to do the same thing in Zsh? Thanks.

3
  • Alt-comma isn't bound to anything by default that I'm aware of. The default binding for "last command from history" is ctrl-p (and ctrl-n is next command in history for if you go too far back, etc.). (See Commands for History in the bash manual for example.) What does bind -q previous-history output for you? (I get previous-history can be invoked via "\C-p", "\eOA", "\e[A".) Commented Jan 3, 2016 at 1:15
  • zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html. Learn zle and bindkey. ZLE is far more powerful and customizable than bash/readline, that's the only thing I'll say.
    – 4ae1e1
    Commented Jan 3, 2016 at 1:19
  • Ctrl-p and Ctrl-n work the same as Bash. They just replace the current command line with last/next command from history. I guess I have to learn zle and bindkey. Just was surprised there were not these useful shortcuts. Commented Jan 3, 2016 at 4:39

1 Answer 1

12

Looking for this feature I came across this blogpost by Christian Neukirchen:

1. You probably know M-. to insert the last argument of the previous line. Sometimes, you want to insert a different argument. There are a few options: Use history expansion, e.g. !:-2 for the third word on the line before (use TAB to expand it if you are not sure), or use M-. with a prefix argument: M-2 M-.

Much nicer however is:

autoload -Uz copy-earlier-word
zle -N copy-earlier-word
bindkey "^[m" copy-earlier-word

Then, M-m will copy the last word of the current line, then the second last word, etc. But with M-. you can go back in lines too! Thus:

% echo a b c
% echo 1 2 3
% echo <M-.><M-.><M-m>
% echo b

Man, I wish I knew that earlier!

In this text, M is referring to the Meta key, aka Alt. So in theory this should work out of the box, as Christian says. So I went to try this and yes, it did work out of the box.

The zle widgets in charge of this behavior are insert-last-word ─which is ALT+.─ and digit-argument ─which is ALT+Number.

Here's the relevant bindkey output:

$ bindkey -L | grep '\^\[[.0-9]'
bindkey "^[." insert-last-word
bindkey "^[0" digit-argument
bindkey "^[1" digit-argument
bindkey "^[2" digit-argument
bindkey "^[3" digit-argument
bindkey "^[4" digit-argument
bindkey "^[5" digit-argument
bindkey "^[6" digit-argument
bindkey "^[7" digit-argument
bindkey "^[8" digit-argument
bindkey "^[9" digit-argument

so check that those appear and try again. You can update your original question with the output of the shown bindkey command to help narrow down the issue, or open one directly in oh-my-zsh with the details.

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