Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a vim equivalent to bash's '!$'?

Tags:

bash

vim

sh

I often find myself doing something like this while developing:

:e <file>
:vsplit <the_same_file>  "reopen/re-edit with a vertical split

As a few responders have pointed out, there's a much better way to do this: :vs<CR>. Suppose for a moment there weren't.

If I were opening files in my shell, I'd use the !$ history expansion to capture the last argument of the previous command, like this:

$ echo "Hello" "stackoverflow"
Hello stackoverflow
$ echo "I'm posting on !$"
I'm posting on stackoverflow

This expansion, and the many others like it, utterly redefined the way I used the command line. Are there equivalents in vim? I know % aliases the current file. What about past-command arguments?

like image 629
Christopher Avatar asked Aug 28 '13 17:08

Christopher


2 Answers

As far as I know Vim does not have history expansion.

The natural thing to do then is to use the tools Vim gives us on the command line. And we have options!

  • <Up> arrow filtering
  • Command-line editing commands
    • CTRL-W to delete a word backwards
    • <Left> and <Right> to move around, CTRL-B and CTRL-E to move to start/end of line
  • Use the command-line window q: (or CTRL-F when already on the command line) for ultimate history editing power
  • Find idiomatic alternative solutions in the Vim spirit for the specific problem at hand
    • Automatically expanded tokens like % and # are a good example

However, if you really want Bash-style history expansion you can hack something together with command-line <expr> abbreviations fairly easily (at least for the simpler cases).

The history expansion items I use most often (frankly not very often):

  • !!, the most recent command line
  • !-2, the second most recent command line
  • !*, all arguments but the first of the previous command line
  • !$, the last argument of the previous command line

Here's how you can implement them as expression abbreviations:

cnoreabbr <expr> !!  getcmdtype() == ':' ? @: : '!*'
cnoreabbr <expr> !-2 getcmdtype() == ':' ? histget(':', -2) : '!-2'
cnoreabbr <expr> !*  getcmdtype() == ':' ? join(split(@:,'\s\+')[1:], ' ') : '!*'
cnoreabbr <expr> !$  getcmdtype() == ':' ? split(@:,'\s\+')[-1] : '!$'

And here's how your example would work in Vim:

:echo "Hello Stackoverflow"
Hello Stackoverflow
:echo "I'm posting on !$<Enter>
I'm posting on Stackoverflow

Of course, use functions for more complex expressions if you really decide to go down this route.

like image 182
glts Avatar answered Oct 02 '22 06:10

glts


Using :vsp with no arguments splits the current window.

Not exactly what you're asking for, but I often use % which is the current filename:

:e some_file
:vsp %

See :help cmdline-special

like image 32
glenn jackman Avatar answered Oct 02 '22 06:10

glenn jackman