(Useful) Stupid Vim Tricks?
haroldag writes "I thoroughly enjoyed the recent post about Unix tricks, so I ask Slashdot vim users, what's out there? :Sex, :b#, marks, ctags. Any tricks worth sharing?"
← Back to Stories (view on slashdot.org)
Why bother asking slashdot when all the best Vim tips have been collected and compiled? http://vim.wikia.com/wiki/Best_Vim_Tips
Also, you can do use "ma" to mark the beginning line, "mb" to mark the ending line, and then:
:'a,'bs/FROM/TO/g
Sometimes it's best to just let stupid people be stupid.
There are far too many "essential" commands in vim, but if I had to pick the two that make the most difference, I would pick * and =. * searches for the word under the cursor and = indents the selected text (most useful for programming).
:ret over highlighted text will reformat using the tabbing rules set up in your .vimrc files. Quite handy when you have legacy code and new code mixed together leaving a big mess when opened in a viewer with different settings.
:se ff=unix
And, to remove the ^M from files that came from windows:
Am I just a vim noob? After doing a search and loving the nice highlighting, is there a way to unhighlight the search term without doing a "/lkasjdfkjdfdf"? In less(1), you'd hit <esc>u but haven't found anything for vim.
The tricks I use in vi/vim are mostly the arcane flags.
will not search past the top or bottom.
will make a nice indentation shiftwidth, especially for using the indent command (>). Works great for programming, especially with autoindent (:set ai). But when programming with autoindent, you often need to unindent one shiftwidth... do that by typing control-D at the beginning of the line. You can go to the very beginning of an autoindented line with 0 control-D.
will turn on/off hidden characters, and show end of lines. Great for finding tabs or spaces at the end of a line.
will turn on line numbering.
Of course, if you want actual line numbers in your file, in *nix you'd use
:%!cat -n
%
when pressed over a parenthesis, finds the matching parenthesis or brackets
Now, I want someone to write a lisp interpreter based in vi macros. That way we can port emacs to vi.
v, V and ctrl-V (various visual selection modes for copy-paste)
zf, zo, zc: fold creation, open, close (hides sections of your code)
~: (toggle case)
u, ctrl-r: undo, redo
"vimdiff" or "vim -d": (visual diff of two files)
One of vi's best features is the '.' command to repeat what you last did. You can do 'dd' to delete a line, then press '.' (dot) to do it again. Or '100.' to do it 100 times. Typing in numbers before a command repeats the command. Typing in '100ihello[esc]' will insert 'hello' 100 times. Then typing dot will give you 100 more.
On a modern vi you can press up-arrow after pressing colon to get your previous colon command back for editing.
Some examples of changing things on various lines:
Don't forget you can precede your search-replace statement with a line range, like
%10,20s/From/To/
%.,$s/F/T/
I know the emacs vs. vi holy war is a funny old meme, but why not just use a modern-style editor? We have these powerful graphical desktops with very standard interfaces. I'm sure the old classics give you a lot of power (Actually, I don't know that much about vim, but I understand you can run Eliza, NetHack, or a Lisp interpreter in emacs), but who wants to learn a bunch of obscure commands and meta-keystrokes? If you just need to edit some text, there are simpler solutions. Me, I use Kate.
move up to the top line of the block to be delete
mm (sets a marker "m")
move down to the last line in the block
d`m (deletes to marker "m", and that's the grave below the tilde, not the back-quote)
:help sex
e.g. it give you a file exploring pane above the buffer you are currently using.
Very cool. I didn't know how to mark a range like that before.
And, while we're having fun with search and replace, ^ will match the beginning of a line, so if you mark as above, and then change the command to: :'a,'bs/^/#/
you will have commented out a section of your code without having to insert a comment character independently on each line. :'a,'bs/^#//
Reverse it with:
to remove the comments.
Also, you don't have to use the / command as a separator. Anything typed after s will become the separator, so if you want to, say, change all your Windows paths to Unix paths, instead of starting with: :%s/\\/\//g
which, while undeniably cool, can be more easily written as: :%s;\\;/;g
which is a little easier to read.
Two other interesting bits:
u all by itself will undo the last command. Handy when you're testing your commands before posting them to Slashdot.
Also, Slashdot's editor will remove the newlines before any line that starts with a :
In my examples, I put each command on it's own line, but Slashdot keeps appending them to the previous line. Weird.
If the masses can keep you down, you're not the Ubermensch.
Not directly related to VIM itself but, Firefox plugin called Vimperator...gives web browsing vimlike commands
Also g/foo/s/bar/baz/g
For all the lines that match foo, replace bar with baz
With this form, the equivalent of %s/bar/baz/g is g/bar/s//baz/g
Another useful :g command is g/foo/d to delete all lines with foo
(in vim only), Ctrl-A and Ctrl-X find the next number on the line starting at the cursor, and then increment or decrement it respectively.
Apart from being weird, these are surprisingly useful sometimes, e.g. toggling "#if 0" to "#if 1"...
To create a comment block:
:'a,.s/^/#/ - to create comment block
:'a,.s/^#// - to remove comment block
move cursor to the start of the comment block
ma - creates a mark called "a"
scroll down to the end of the comment block
basically puts # at the start of every line from mark a to your current cursor position. You can get creative and use this method for tons of things, indenting, substituting words within a given scope, comment blocks, etc.
:%s/foo/bar/g go through all the file and replace foo by bar :12,20s/foo/bar/
from line 12 to 20 replace foo for bar :s/foo/bar/g
in the current line replace foo for bar
the g after the last / means to replace all the occurrences of foo vby bar and not only the first one.
I much rather use Visual mode for this, as I hate having to remember line numbers. Just hit 'V', highlight the region, and then type ':s/FROM/TO/g'. Vim does the rest.
For all your vi/Emacs flamewar needs, try http://wordwarvi.sourceforge.net/ Full disclosure, I'm the author of that game.
These are useful with prefixes: :r!pwd (read `pwd` into to document) :%!sort (sort all lines) :'$lt;'>!sort | uniq (sort last visual selection, notice the pipe)
Another useful thing you can do is to bind a filter to a script, in your .vimrc, so you can yy pp a line, and get an instant commented debug line.
map :.! ~/scripts/javascript-debug.pl==
#!/usr/bin/perl
while() {
($line = $_ ) =~ s/^\s+|\s+$//g;
($quote = $line) =~ s/'/\\'/g;
print "console.log('DEBUG: $quote ', $line);\n";
}
Note: My normal script has half a dozen regexps in the middle, for stripping out semicolons, function declarations, return statements, such that what gets printed is almost always a valid code statememnt. However slashdot can't tell my regexps apart from line line-noise and kept complaining about too many junk characters.
However its possible to write similar scripts for various languages, and for other simple tasks such as wrapping a for statement around an array variable.
:sh works well when you don't know root, but have sudo privs.
Actually I fix this one within .bashrc, and create a wrapper function around vim, that detects if the file is editable or not, and asks if you want to prefix an sudo.
argc () {
count=0;
for arg in "$@"; do
if [[ ! "$arg" =~ '-' ]]; then count=$(($count+1)); fi;
done;
echo $count;
}
vi () { if [[ `argc "$@"` > 1 ]]; then /usr/bin/vim $@; /usr/bin/vim; /usr/bin/vim $@; /usr/bin/vim $*; /usr/bin/vim $*;
elif [ $1 = '' ]; then
elif [ ! -f $1 ] || [ -w $1 ]; then
else
echo -n "File is readonly. Edit as root? (Y/n): "
read -n 1 yn; echo;
if [ "$yn" = 'n' ] || [ "$yn" = 'N' ];
then
else sudo
fi
fi
}
All my favorites, right here: http://limestone.truman.edu/~dbindner/mirror/#Vi-Ref
# change foo to bar for all occurrences in the rest of :s/foo/bar/g
# the file from where the cursor is
No, that only works on the current line. perhaps :.,$s/foo/bar/g
When you want to move the words around in a line you can do something like this.
If you use "your" to mean "you're", you're doing it (using the English language) incorrectly.
Comments the lines in quite many languages
For C I use this
:'<,'>s+^+//+
Some examples of changing things on various lines:
In vim (unsure if its new or in the original vi) a % means do this on all lines.
eg: :%s/^/foo/
places "foo" at the start of every line.
--Question Authority--
You can get the traditional vi here:
http://ex-vi.sourceforge.net/
Everyone is aware of commands such as dw which will delete a word. Many are aware that the valid generalization of that command is d<movement>. Few people are aware that <movement> means pretty much anything which moves your cursor. For example, d/sometext<return>. Use your imagination; anything which moves your cursor.
Vim works wonderful together with X. Besides the graphical version (gvim), it's also possible to start vim in a terminal like xterm, konsole or gnome-terminal. With the right options, it's still aware of the X clipboard, the mouse, et cetera. However it's quite a pain in the ass to find out what's wrong when it doesn't work. Here's a guide for using and fixing it.
vim has one default clipboard, but has an extra one under any a-z character. The two X clipboards are available too, but under a special character. To paste the X clipboards, paste either the + or * clipboard:
This is the X clipboard for which you just select something with the mouse: [Escape]"+p
The star buffer contains the X clipboard for which you selected with the mouse, then right-clicked and selected 'copy', or pressed a shortcut like CTRL-C or similar: [Escape]"*p
If this doesn't work, check the following things:
Vim is started in compatibility mode. Solution: don't use 'vi' to start, use 'vim'. On RedHat and CentOS, it's not enough to start 'vim', use 'vimx'. If this program is not present, be sure to install the package 'vim-X11'.
$ ssh -v -X remotemachine
debug1: Requesting X11 forwarding with authentication spoofing.
debug1: Remote: No xauth program; cannot forward with spoofing.
8 of 13 people found this answer helpful. Did you?
try MacVIM which is an excellent port
It's quite easy
I/A - insert at start /end of line
P/p - paste before / after cursor
"*y / "*p - yank & paste to / from the windows clipboard
vat/vit select around/inside a text block like html tags
vi" select inside speech marks
ciB correct inside curly brackets pair
the list goes on, the point is to treat each key as an atom of a command, and learn how they can be combined.
!python % - run current file through python
ggVG= - reindent current buffer
^wv/s - split window
^6 - switch to last touched buffer
http://www.viemu.com/vi-vim-cheat-sheet.gif
Ctrl-w + s for split horizontal, Ctrl-W + v for split vertical. Ctrl-w then moves between the panes, and in each pane you can split it again to your hearts content. Also :edit to edit a new file, if you open multiple files like vim *.txt then :next will move to the next file.
Very useful :![cmd] to execute a command back on the shell, like :!tail /var/some/log to check errors while fixing them in your code.
Also nice to see a little firefox kickback to VIM - in firefox hit / to search through the document, shortcute for ctrl-f/splat-f
In vim/gvim, I think the most useful thing I have ever used is the recording capability. It works great for editing HTML. If you have 10 lines that look very similar (such as a list of navigation links), start recording, edit the first line making sure that you end your statement with 'j' so that it moves to the next line, then finish recording and you can execute that recording for the next 9 lines.
To start recording, type 'q' and then a number such as '1'. This will record your next keystrokes into memory bank 1. When you're done typing, just hit 'q' to finish recording.
So, if you had
<h1>Foo</h1>
<h1>Foo</h1>
<h1>Foo</h1>
<h1>Foo</h1>
and you wanted
<h1>Foo Bar</h1>
<h1>Foo Bar</h1>
<h1>Foo Bar</h1>
<h1>Foo Bar</h1>
you would hit 'q1' to begin recording in bank 1, '^' to start at the beginning, 'l' (as in ell) 6 times to move six characters to the right, 'a' to insert after the last 'o' of "Foo", ' Bar' to insert the string, 'esc' 'j' to finish and move down one line, 'q' to finish recording, then '3@1' to execute the operation in bank 1 three times.
I can't count the number of times I have used this functionality! Makes coding immensely easier.
Got a problem? Call a monkey!