817

There are a plethora of questions where people talk about common tricks, notably "Vim+ctags tips and tricks".

However, I don't refer to commonly used shortcuts that someone new to Vim would find cool. I am talking about a seasoned Unix user (be they a developer, administrator, both, etc.), who thinks they know something 99% of us never heard or dreamed about. Something that not only makes their work easier, but also is COOL and hackish. After all, Vim resides in the most dark-corner-rich OS in the world, thus it should have intricacies that only a few privileged know about and want to share with us.

Community
  • 1
  • 1
  • Launch another editor or commands by using !commandName – Sachin Chourasiya Dec 07 '09 at 10:44
  • 11
    :Sex Split window and open integrated file explorer (horizontal split) – user3218088 Jun 16 '14 at 09:51
  • 3
    This question seems to be pretty constructive - by looking at the number of upvotes... , voted to reopen - maybe some even cooler answer arrives - which can be upvoted if useful - hence giving more value to SOF. Ordering the answers by votes I have learned a lot of cool stuff in just 5 minutes... really valuable stuff here, why close something this valuable ? How is this not constructive ? – jhegedus Oct 17 '15 at 07:11
  • Here's some obscure tips that I can think of: http://pastebin.com/BGGkBmVw – Braden Best Feb 04 '16 at 17:24
  • 7
    Ridiculous that this question is closed. Talk about legalism. – Lepidopterist Apr 21 '16 at 16:10
  • 2
    I think this question is very constructive but, more appropriate at Quora. – Diogo Melo May 20 '16 at 20:12
  • 1
    :Vex Split window and open integrated file explorer (vertical split) – Mike W Jan 04 '17 at 17:13
  • 2
    Why are there 2(as of now) votes to delete this question? What good would it possibly do? – Akavall Jan 09 '17 at 05:52
  • Instead of voting to delete, a "**NOTE: This question is NOT on-topic for Stack Overflow. Do not ask similar questions in the future.**" should suffice. – user202729 Sep 29 '18 at 15:35

70 Answers70

795

Might not be one that 99% of Vim users don't know about, but it's something I use daily and that any Linux+Vim poweruser must know.

Basic command, yet extremely useful.

:w !sudo tee %

I often forget to sudo before editing a file I don't have write permissions on. When I come to save that file and get a permission error, I just issue that vim command in order to save the file without the need to save it to a temp file and then copy it back again.

You obviously have to be on a system with sudo installed and have sudo rights.

skinp
  • 3,719
  • 3
  • 24
  • 19
  • 5
    This is my favorite bit of vi voodo, hands down. – ojrac Apr 07 '09 at 18:43
  • 2
    Great command, I have lost count of the number of times this has happened to me ever since I moved to Ubuntu from Slackware. – aks Apr 08 '09 at 11:19
  • 1
    Does not work in VIM for me. After about 2 seconds the password prompt times out and returns an error.
    [sudo] password for user:
    
    shell returned 1
    
    – cmcginty May 04 '09 at 20:09
  • @Casey, this can only help you if you already have a sudo, i.e. did something with it in the current session. – Maxim Sloyko Aug 06 '09 at 09:47
  • 120
    Arguably, that's even *better* than running vim as root! Upvoted! – Arafangion Sep 14 '09 at 00:06
  • 5
    Even better is using sudoedit in the first place. Otherwise, I'd use ":w !sudo dd of=%" since that doesn't bombard you with the file you're saving being cat to stdout. – jamessan Dec 27 '09 at 19:00
  • 27
    For a noob, what exactly does tee do? Would someone mind parseing out this command for me? – AndyL Mar 01 '10 at 14:38
  • 5
    tee creates a tee junction in your output. You can output to the screen and a file, for example. Best to search SO or google for a more detailed answer. Or ask a question! – Armstrongest May 10 '10 at 15:19
  • 2
    To map x!! to sudo write and quit use: `cmap x!! w !sudo tee %:q!` – Vitalii Fedorenko Dec 06 '10 at 01:02
  • 42
    cmap w!! w !sudo tee % – jm666 May 12 '11 at 06:09
  • 61
    You should never run `sudo vim`. Instead you should export `EDITOR` as vim and run `sudoedit`. – Gerardo Marset Jul 05 '11 at 00:49
  • 2
    I'm a beginner vim user and even i know this command, I think its a common command.Its a top rated command on [commandlinefu](http://www.commandlinefu.com/commands/browse/sort-by-votes) – tsukimi May 27 '12 at 05:54
  • 1
    Can anybody please explain % after tee? – maximus ツ Aug 13 '13 at 14:40
  • 9
    @maximus: vim replaces % by the name of the current buffer/file. – migu Sep 02 '13 at 20:42
  • 3
    @tsukimi wow, thanks for the link to http://commandlinefu.com ; What an awesome site! – nedR Feb 19 '14 at 17:47
  • Related: [How to save a file for which I have no write permissions?](http://vi.stackexchange.com/questions/475/how-to-save-a-file-for-which-i-have-no-write-permissions) at Vim SE – kenorb Feb 19 '15 at 11:22
  • Check explanation [here](https://sudousr.wordpress.com/2015/06/20/saving-read-only-file-edited-using-vim/)! – SD. Jan 05 '16 at 09:43
624

Something I just discovered recently that I thought was very cool:

:earlier 15m

Reverts the document back to how it was 15 minutes ago. Can take various arguments for the amount of time you want to roll back, and is dependent on undolevels. Can be reversed with the opposite command :later

Chad Birch
  • 69,230
  • 22
  • 145
  • 148
417

:! [command] executes an external command while you're in Vim.

But add a dot after the colon, :.! [command], and it'll dump the output of the command into your current window. That's : . !

For example:

:.! ls

I use this a lot for things like adding the current date into a document I'm typing:

:.! date
the Tin Man
  • 150,910
  • 39
  • 198
  • 279
Jeffrey Knight
  • 5,689
  • 5
  • 36
  • 46
  • One other command -- I don't want to open a separate reply: If you have a split window (:sp [filename] or :vert split [filename) you can swap window panes with ^w r – Jeffrey Knight May 01 '09 at 03:43
  • 75
    This is quite similar to :r! The only difference as far as I can tell is that :r! opens a new line, :.! overwrites the current line. – saffsd May 06 '09 at 14:41
  • @Jeffrey: Thanks... @saffsd: That single difference is a great thing: Now I can pass lines to sed or awk and have it replaced with the processed output... – sundar - Remember Monica Sep 23 '09 at 08:40
  • 7
    An alternative to `:.!date` is to write "date" on a line and then run `!$sh` (alternatively having the command followed by a blank line and run `!jsh`). This will pipe the line to the "sh" shell and substitute with the output from the command. – hlovdal Jan 25 '10 at 21:11
  • 44
    `:.!` is actually a special case of `:{range}!`, which filters a range of lines (the current line when the range is `.`) through a command and replaces those lines with the output. I find `:%!` useful for filtering whole buffers. – Nefrubyr Mar 25 '10 at 16:24
  • 2
    @sundar: Why pass a line to `sed`, when you can use the similar built-in `ed`/`ex` commands? Try running `:.s/old/new/g` ;-) – jabirali Jul 13 '10 at 04:30
  • 5
    And also note that '!' is like 'y', 'd', 'c' etc. i.e. you can do: !!, number!!, !motion (e.g. !Gshell_command replace from current line to end of file ('G') with output of shell_command). – aqn Apr 26 '13 at 20:52
  • Related: [How to dump output from external command into editor?](http://vi.stackexchange.com/questions/795/how-to-dump-output-from-external-command-into-editor) at Vim SE – kenorb Feb 19 '15 at 11:25
  • 2
    Did you know that you can double-bang (`!!`) to automatically fill out the `:.!`? Pretty convenient when you don't feel like typing all that out. It even works in `vim -u none` – Braden Best Feb 04 '16 at 15:54
316

Not exactly obscure, but there are several "delete in" commands which are extremely useful, like..

  • diw to delete the current word
  • di( to delete within the current parens
  • di" to delete the text between the quotes

Others can be found on :help text-objects

dbr
  • 153,498
  • 65
  • 266
  • 333
  • I knew the first one :) –  Apr 07 '09 at 20:37
  • @dbr: di( deletes the content inside the brackets. How can you delete only the brackets? I remember that it is possible too. – Léo Léopold Hertz 준영 Apr 07 '09 at 21:17
  • jholloway7: Thanks, mentioned that help page and linked to the text-objects vim docs. Masi: Not sure, daw will delete the brackets+contents, the closest command I can think of is `xf)x` (delete bracket, jump to next ) and delete again) – dbr Apr 08 '09 at 12:22
  • 8
    dab "delete arounb brackets", daB for around curly brackets, t for xml type tags, combinations with normal commands are as expected cib/yaB/dit/vat etc – sjh Apr 08 '09 at 15:33
  • 15
    @Masi: yi(va(p deletes only the brackets – Don Reba Apr 13 '09 at 21:41
  • 42
    This is possibly the biggest reason for me staying with Vim. That and its equivalent "change" commands: ciw , ci( , ci" , as well as dt and ct – thomasrutter Apr 26 '09 at 11:11
  • 4
    @thomasrutter: Why not dW/cW instead of dt? –  Oct 12 '10 at 16:40
  • 9
    @Masi: With the surround plugin: ds(. –  Oct 12 '10 at 16:43
  • 1
    +1 for diw, never occured to me to use i/a on words, used it only for (), <>, {} until now. ^^ – Sebastian Ärleryd Mar 31 '14 at 08:58
238

de Delete everything till the end of the word by pressing . at your heart's desire.

ci(xyz[Esc] -- This is a weird one. Here, the 'i' does not mean insert mode. Instead it means inside the parenthesis. So this sequence cuts the text inside parenthesis you're standing in and replaces it with "xyz". It also works inside square and figure brackets -- just do ci[ or ci{ correspondingly. Naturally, you can do di (if you just want to delete all text without typing anything. You can also do a instead of i if you want to delete the parentheses as well and not just text inside them.

ci" - cuts the text in current quotes

ciw - cuts the current word. This works just like the previous one except that ( is replaced with w.

C - cut the rest of the line and switch to insert mode.

ZZ -- save and close current file (WAY faster than Ctrl-F4 to close the current tab!)

ddp - move current line one row down

xp -- move current character one position to the right

U - uppercase, so viwU upercases the word

~ - switches case, so viw~ will reverse casing of entire word

Ctrl+u / Ctrl+d scroll the page half-a-screen up or down. This seems to be more useful than the usual full-screen paging as it makes it easier to see how the two screens relate. For those who still want to scroll entire screen at a time there's Ctrl+f for Forward and Ctrl+b for Backward. Ctrl+Y and Ctrl+E scroll down or up one line at a time.

Crazy but very useful command is zz -- it scrolls the screen to make this line appear in the middle. This is excellent for putting the piece of code you're working on in the center of your attention. Sibling commands -- zt and zb -- make this line the top or the bottom one on the sreen which is not quite as useful.

% finds and jumps to the matching parenthesis.

de -- delete from cursor to the end of the word (you can also do dE to delete until the next space)

bde -- delete the current word, from left to right delimiter

df[space] -- delete up until and including the next space

dt. -- delete until next dot

dd -- delete this entire line

ye (or yE) -- yanks text from here to the end of the word

ce - cuts through the end of the word

bye -- copies current word (makes me wonder what "hi" does!)

yy -- copies the current line

cc -- cuts the current line, you can also do S instead. There's also lower cap s which cuts current character and switches to insert mode.

viwy or viwc. Yank or change current word. Hit w multiple times to keep selecting each subsequent word, use b to move backwards

vi{ - select all text in figure brackets. va{ - select all text including {}s

vi(p - highlight everything inside the ()s and replace with the pasted text

b and e move the cursor word-by-word, similarly to how Ctrl+Arrows normally do. The definition of word is a little different though, as several consecutive delmiters are treated as one word. If you start at the middle of a word, pressing b will always get you to the beginning of the current word, and each consecutive b will jump to the beginning of the next word. Similarly, and easy to remember, e gets the cursor to the end of the current, and each subsequent, word.

similar to b/e, capital B and E move the cursor word-by-word using only whitespaces as delimiters.

capital D (take a deep breath) Deletes the rest of the line to the right of the cursor, same as Shift+End/Del in normal editors (notice 2 keypresses -- Shift+D -- instead of 3)

alex
  • 438,662
  • 188
  • 837
  • 957
  • 16
    **zt** is quite useful if you use it at the start of a function or class definition. – Nick Lewis Jul 17 '09 at 16:41
  • 9
    `vity` and `vitc` can be shortened to `yit` and `cit` respectively. – Nathan Fellman Sep 07 '09 at 08:27
  • viwy could also be yiw. viwc could also be ciw. But the vi... is probably easier to remember since you use it in a lot of cases. – Kimball Robinson Apr 16 '10 at 00:24
  • There's also "H" to take the cursor to the top line in the display, "M" to take it to the middle one, and "L" to put it on the bottom one. Not to be confused with "gg" and "G", which take you to the top or bottom of the buffer. – TMN Sep 17 '10 at 17:59
  • 33
    All the things you're calling "cut" is "change". eg: C is change until the end of the line. Vim's equivalent of "cut" is "delete", done with d/D. The main difference between change and delete is that delete leaves you in normal mode but change puts you into a sort of insert mode (though you're still in the change command which is handy as the whole change can be repeated with `.`). – Laurence Gonsalves Feb 19 '11 at 23:49
  • 1
    also, `zt` and `zb` become just as usefule as `zz` with a setting like `scrolloff=2` – sehe Mar 04 '12 at 21:37
  • 11
    I thought this was for a list of things that not many people know. yy is very common, I would have thought. – Almo May 29 '12 at 20:09
  • 19
    `bye` does not work when you are in the first character of the word. `yiw` always does. – Andrea Francia Jul 03 '12 at 20:50
  • 2
    I would argue most of these are not dark corners, every vim user should know most of these basic commands. – brianmearns Oct 03 '12 at 12:40
  • @LaurenceGonsalves: though C **does** yank as well. It's basically the same as `d*` then `i`. Also, the help doesn't explicitly call it "change" - is that official? – naught101 Feb 21 '13 at 23:19
  • @naught101 Yes, I know the c operator copies the text to the register before deleting. Like I said "The main difference between change and delete is that delete leaves you in normal mode but change puts you into a sort of insert mode (though you're still in the change command which is handy as the whole change can be repeated with .)" Actually, another difference is what happens if you have the `$` flag in `cpoptions` enabled. "Change" is the mnemonic I'd learned from vi, and seems to be pretty common. See http://stackoverflow.com/questions/7409134/english-mnemonics-to-vims-shortcuts – Laurence Gonsalves Feb 22 '13 at 19:22
  • 4
    Looking back at this answer, a listing of a random combination of operators and motion/object commands is is hardly "dark corners" of vim. If you think of these as individual commands, then you're doing it wrong. c, d, y and v are operators. e, w, t, f are motions. i(, ip, iw, i", and the same with a instead of i are objects. (These are all subsets of what vim actually offers -- I'm just mentioning ones that appear in this answer) Combine an operator with either a motion or an object (or self, except v) to create a command. From just the ones I've listed you can make over 50 commands. – Laurence Gonsalves Feb 22 '13 at 19:34
  • Best ever tips i've been seen – innuendoreplay Mar 27 '13 at 23:52
  • I would upvote for `ZZ` alone, yet the rest is hardly dark corner. – Profpatsch Apr 11 '13 at 18:20
  • Just for the record, you can do `cw` (change word) instead of `ciw`. – Braden Best Feb 04 '16 at 15:56
  • I really really love this because you listed it so I can read and try and repeat – Polamin Singhasuwich Apr 27 '16 at 07:59
  • How on earth is this related to the question in the original post? You can learn all of these from tutorials, there is nothing in this post from the "dark" corners of Vim. – A. Blizzard Jul 20 '20 at 14:01
207

One that I rarely find in most Vim tutorials, but it's INCREDIBLY useful (at least to me), is the

g; and g,

to move (forward, backward) through the changelist.

Let me show how I use it. Sometimes I need to copy and paste a piece of code or string, say a hex color code in a CSS file, so I search, jump (not caring where the match is), copy it and then jump back (g;) to where I was editing the code to finally paste it. No need to create marks. Simpler.

Just my 2cents.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Xavier Guardiola
  • 2,439
  • 3
  • 17
  • 11
188
:%!xxd

Make vim into a hex editor.

:%!xxd -r

Revert.

Warning: If you don't edit with binary (-b), you might damage the file. – Josh Lee in the comments.

MasterMastic
  • 19,099
  • 11
  • 59
  • 86
Bill Lynch
  • 72,481
  • 14
  • 116
  • 162
  • 9
    And how do you revert it back? – Christian Jul 07 '09 at 19:11
  • 40
    :!xxd -r //To revert back from HEX – Naga Kiran Jul 08 '09 at 13:46
  • 21
    I actually think it's `:%!xxd -r` to revert it back – Andreas Grech Nov 14 '09 at 10:37
  • @JoshLee: If one is careful not to traverse newlines, is it safe to not use the -b option? I ask because _sometimes_ I want to make a hex change, but I don't want to close and reopen the file to do so. – dotancohen Jun 07 '13 at 05:50
  • 4
    @dotancohen: If you don't want to close/reopen the file you can do :set binary – Bambu Nov 23 '14 at 23:58
  • Related: [How to edit binary files with Vim?](http://vi.stackexchange.com/questions/343/how-to-edit-binary-files-with-vim) at Vim SE – kenorb Feb 19 '15 at 11:25
  • I can never get `xxd -r` to revert properly. Every time I do, it corrupts the binary and 99% of the file goes missing. I'm guessing it's due to a `NUL` byte appearing somewhere, and strings being null-terminated. This happens even if I set binary and noeol from within vim. So, thanks @JoshLee for the `vim -b` tip, but I *still* don't trust `:%!xxd -r`. – Braden Best Feb 04 '16 at 16:04
133
gv

Reselects last visual selection.

AaronS
  • 445
  • 1
  • 6
  • 9
120

Sometimes a setting in your .vimrc will get overridden by a plugin or autocommand. To debug this a useful trick is to use the :verbose command in conjunction with :set. For example, to figure out where cindent got set/unset:

:verbose set cindent?

This will output something like:

cindent
    Last set from /usr/share/vim/vim71/indent/c.vim

This also works with maps and highlights. (Thanks joeytwiddle for pointing this out.) For example:

:verbose nmap U
n  U             <C-R>
        Last set from ~/.vimrc

:verbose highlight Normal
Normal         xxx guifg=#dddddd guibg=#111111 font=Inconsolata Medium 14
        Last set from ~/src/vim-holodark/colors/holodark.vim
Laurence Gonsalves
  • 125,464
  • 31
  • 220
  • 273
102

:%TOhtml

Creates an html rendering of the current file.

Eliran Malka
  • 14,498
  • 5
  • 72
  • 96
N 1.1
  • 12,004
  • 6
  • 39
  • 57
  • 2
    Related: [How to convert a source code file into HTML?](http://vi.stackexchange.com/questions/792/how-to-convert-a-source-code-file-into-html) at Vim SE – kenorb Feb 19 '15 at 11:27
  • This is awesome. Btw the `%` is unnecessary as the default parameter is the current buffer. `:help TOhtml` – JDG Nov 11 '20 at 19:26
101

Not sure if this counts as dark-corner-ish at all, but I've only just learnt it...

:g/match/y A

will yank (copy) all lines containing "match" into the "a/@a register. (The capitalization as A makes vim append yankings instead of replacing the previous register contents.) I used it a lot recently when making Internet Explorer stylesheets.

Aaron Thoma
  • 3,262
  • 30
  • 31
sjh
  • 2,180
  • 1
  • 17
  • 20
  • counts, counts as i haven't seen this one :) –  Apr 08 '09 at 15:51
  • Nice one. Never heard of it... Might be useful :P – skinp Apr 08 '09 at 16:53
  • 6
    You can use :g! to find lines that don't match a pattern e.x. :g!/set/normal dd (delete all lines that don't contain set) – tsukimi May 27 '12 at 06:17
  • 4
    Sometimes it's better to do what tsukimi said and just filter out lines that don't match your pattern. An abbreviated version of that command though: `:v/PATTERN/d` Explanation: `:v` is an abbreviation for `:g!`, and the `:g` command applies any ex command to lines. `:y[ank]` works and so does `:normal`, but here the most natural thing to do is just `:d[elete]`. – pandubear Oct 12 '13 at 08:39
  • You can also do `:g/match/normal "Ayy` -- the `normal` keyword lets you tell it to run normal-mode commands (which you are probably more familiar with). – Kimball Robinson Feb 05 '16 at 17:58
94

Want to look at your :command history?

q:

Then browse, edit and finally to execute the command.

Ever make similar changes to two files and switch back and forth between them? (Say, source and header files?)

:set hidden
:map <TAB> :e#<CR>

Then tab back and forth between those files.

idbrii
  • 9,440
  • 5
  • 50
  • 93
MikeyB
  • 3,196
  • 1
  • 24
  • 38
87

Vim will open a URL, for example

vim http://stackoverflow.com/

Nice when you need to pull up the source of a page for reference.

zzapper
  • 4,003
  • 5
  • 44
  • 41
Cercerilla
  • 1,293
  • 12
  • 13
  • 2
    For me it didn't open the source; instead it apparently used elinks to dump rendered page into a buffer, and then opened that. – Ivan Vučica Sep 21 '10 at 08:07
  • there's error when executed this command – Dzung Nguyen Jun 20 '12 at 10:04
  • 6
    Works better with a slash at the end. Neat trick! – Thomas Apr 19 '13 at 21:00
  • @Vdt: It'd be useful if you posted your error. If it's this one: "**error** (netrw) neither the wget nor the fetch command is available" you obviously need to make one of those tools available from your PATH environment variable. – Isaac Nequittepas Jun 03 '13 at 15:23
  • I find this one particularly useful when people send links to a paste service and forgot to select a syntax highlighting, I generally just have to open the link in vim after appending "&raw". – Dettorer Oct 29 '14 at 13:47
70

Macros can call other macros, and can also call itself.

eg:

qq0dwj@qq@q

...will delete the first word from every line until the end of the file.

This is quite a simple example but it demonstrates a very powerful feature of vim

tckmn
  • 52,184
  • 22
  • 101
  • 145
spence91
  • 67,587
  • 8
  • 25
  • 19
  • 3
    I didn't know macros could repeat themselves. Cool. Note: qx starts recording into register x (he uses qq for register q). 0 moves to the start of the line. dw delets a word. j moves down a line. @q will run the macro again (defining a loop). But you forgot to end the recording with a final "q", then actually run the macro by typing @q. – Kimball Robinson Apr 16 '10 at 00:39
  • 2
    I think that's intentional, as a nested and recursive macro. – Yktula Apr 18 '10 at 05:32
  • 7
    `qqqqqifuuh@qq@q` – Gerardo Marset Jul 05 '11 at 01:38
  • 6
    Another way of accomplishing this is to record a macro in register a that does some transformation to a single line, then linewise highlight a bunch of lines with V and type `:normal! @a` to applyyour macro to every line in your selection. – Nathan Long Aug 29 '11 at 15:33
  • I found this post googling recursive VIM macros. I could find no way to stop the macro other than killing the VIM process. – dotancohen May 14 '13 at 06:00
  • @dotancohen recursive macros end when they read end of file. ctrl D is a shortcut to inject this is most programs. – 2c2c Nov 23 '14 at 14:58
  • I have used macros for over 20 years and never knew this time saving festure. I wonder if it is supported in the original SysV version itself or an extension of Vim. – haridsv Feb 06 '16 at 18:45
  • Macros being used recursively is definitely a design choice, and they will keep doing so until they hit the end of the buffer. If your macro is recursive and stuck in an infinite loop, press ctrl+c to stop it rather than killing your entire vim process. – Stun Brick Aug 29 '18 at 10:20
56

^O and ^I

Go to older/newer position. When you are moving through the file (by searching, moving commands etc.) vim rember these "jumps", so you can repeat these jumps backward (^O - O for old) and forward (^I - just next to I on keyboard). I find it very useful when writing code and performing a lot of searches.

gi

Go to position where Insert mode was stopped last. I find myself often editing and then searching for something. To return to editing place press gi.

gf

put cursor on file name (e.g. include header file), press gf and the file is opened

gF

similar to gf but recognizes format "[file name]:[line number]". Pressing gF will open [file name] and set cursor to [line number].

^P and ^N

Auto complete text while editing (^P - previous match and ^N next match)

^X^L

While editing completes to the same line (useful for programming). You write code and then you recall that you have the same code somewhere in file. Just press ^X^L and the full line completed

^X^F

Complete file names. You write "/etc/pass" Hmm. You forgot the file name. Just press ^X^F and the filename is completed

^Z or :sh

Move temporary to the shell. If you need a quick bashing:

  • press ^Z (to put vi in background) to return to original shell and press fg to return to vim back
  • press :sh to go to sub shell and press ^D/exit to return to vi back
dimba
  • 24,103
  • 28
  • 127
  • 188
  • With `^X^F` my pet peeve is that filenames include `=` signs, making it do rotten things in many occasions (ini files, makefiles etc). I use `se isfname-==` to end that nuisance – sehe Mar 04 '12 at 21:50
  • 3
    +1 the built-in autocomplete is just sitting there waiting to be discovered. – joeytwiddle Jul 05 '14 at 22:10
56

Assuming you have Perl and/or Ruby support compiled in, :rubydo and :perldo will run a Ruby or Perl one-liner on every line in a range (defaults to entire buffer), with $_ bound to the text of the current line (minus the newline). Manipulating $_ will change the text of that line.

You can use this to do certain things that are easy to do in a scripting language but not so obvious using Vim builtins. For example to reverse the order of the words in a line:

:perldo $_ = join ' ', reverse split

To insert a random string of 8 characters (A-Z) at the end of every line:

:rubydo $_ += ' ' + (1..8).collect{('A'..'Z').to_a[rand 26]}.join

You are limited to acting on one line at a time and you can't add newlines.

Brian Carper
  • 66,618
  • 25
  • 158
  • 164
50
" insert range ip's
"
"          ( O O )
" =======oOO=(_)==OOo======

:for i in range(1,255) | .put='10.0.0.'.i | endfor
codygman
  • 822
  • 1
  • 12
  • 29
SergioAraujo
  • 8,735
  • 1
  • 46
  • 37
  • 2
    I don't see what this is good for (besides looking like a joke answer). Can anybody else enlighten me? – Ryan Edwards Nov 16 '11 at 00:42
  • 2
    open vim and then do ":for i in range(1,255) | .put='10.0.0.'.i | endfor" – codygman Nov 06 '12 at 08:33
  • 2
    @RyanEdwards filling /etc/hosts maybe – Ruslan Sep 30 '13 at 10:30
  • 27
    This is a terrific answer. Not the bit about creating the IP addresses, but the bit that implies that **VIM can use for loops in commands**. – dotancohen Nov 30 '14 at 14:56
  • 4
    Without ex-mode: `i10.0.0.1Y254p$}g` – BlackCap Aug 31 '17 at 07:54
  • @BlackCap the last `g` is supposed to be `G` (go to last line)? `` will only increment by one, so you'll end up with `10.0.0.1` on the first line, and `10.0.0.2` on the next 254 lines. – Stefan van den Akker Jul 20 '18 at 08:58
  • 1
    @StefanvandenAkker `}` goes to the last character on the last line, as opposed to `G` which goes to the first character on the last line. `g` is range increment- it increments the first line by 1, the next by 2 and so on.. – BlackCap Jul 20 '18 at 09:26
  • @BlackCap ah, I missed the `}`, sorry. `:help v_g_CTRL-A` shows the help for incrementing addition. Thanks for explaining! – Stefan van den Akker Jul 22 '18 at 08:41
49

Typing == will correct the indentation of the current line based on the line above.

Actually, you can do one = sign followed by any movement command. ={movement}

For example, you can use the % movement which moves between matching braces. Position the cursor on the { in the following code:

if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}

And press =% to instantly get this:

if (thisA == that) {
    //not indented
    if (some == other) {
        x = y;
    }
}

Alternately, you could do =a{ within the code block, rather than positioning yourself right on the { character.

Kimball Robinson
  • 3,104
  • 7
  • 42
  • 56
  • Hm, I didn't know this about the indentation. – Ehtesh Choudhury May 02 '11 at 00:48
  • No need, usually, to be exactly on the braces. Thought frequently I'd just `=}` or `vaBaB=` because it is less dependent. Also, `v}}:!astyle -bj` matches my code style better, but I can get it back into your style with a simple `%!astyle -aj` – sehe Mar 04 '12 at 22:03
  • 7
    `gg=G` is quite neat when pasting in something. – remmy Oct 19 '13 at 12:12
  • Related: [Re-indenting badly indented code](http://vi.stackexchange.com/questions/236/re-indenting-badly-indented-code) at Vim SE – kenorb Feb 19 '15 at 11:30
  • @kyrias Oh, I've been doing it like `ggVG=`. – Braden Best Feb 04 '16 at 16:16
47

This is a nice trick to reopen the current file with a different encoding:

:e ++enc=cp1250 %:p

Useful when you have to work with legacy encodings. The supported encodings are listed in a table under encoding-values (see help encoding-values). Similar thing also works for ++ff, so that you can reopen file with Windows/Unix line ends if you get it wrong for the first time (see help ff).

zoul
  • 96,282
  • 41
  • 242
  • 342
  • Never had to use this sort of a thing, but we'll certainly add to my arsenal of tricks... –  Apr 07 '09 at 18:43
  • great tip, thanks. For bonus points, add a list of common valid encodings. – Adriano Varoli Piazza Apr 07 '09 at 18:44
  • 2
    I have used this today, but I think I didn't need to specify "%:p"; just opening the file and :e ++enc=cp1250 was enough. I – Ivan Vučica Jul 08 '09 at 19:29
  • would :set encoding=cp1250 have the same effect? – laz Jul 08 '09 at 19:32
  • @laz: no, 'encoding' option defines the encoding that Vim uses to store all of its internal data like text in the buffers, registers, etc. 'fileencoding' defines the encoding of the current buffer. But if you set 'fenc' after opening a file, Vim will convert file from current encoding to the new one. So, the only way to open file using the specific encoding is to use ++enc option. – Paul Jul 23 '09 at 21:13
  • 1
    `:e +b %' is similarly useful for reopening in binary mode (no munging of newlines) – intuited Jun 04 '10 at 02:51
42
imap jj <esc>
Trumpi
  • 7,160
  • 5
  • 37
  • 50
  • 1
    It will exit edit mode when you press "jj" – Trumpi May 05 '09 at 12:57
  • 7
    how will you type jj then? :P – hasen Jun 12 '09 at 06:08
  • 6
    How often to you type jj? In English at least? – ojblass Jul 05 '09 at 18:29
  • 1
    You can type it slowly too and it works. Outstanding tip. – ojblass Jul 05 '09 at 18:32
  • 2
    I can't live without the jj mapping. I type my jjs with jj – Roberto Bonvallet Jul 21 '09 at 01:35
  • 50
    I remapped capslock to esc instead, as it's an otherwise useless key. My mapping was OS wide though, so it has the added benefit of never having to worry about accidentally hitting it. The only drawback IS ITS HARDER TO YELL AT PEOPLE. :) – Alex Oct 05 '09 at 05:32
  • 7
    @Alex: definitely, capslock is death. "wait, wtf? oh, that was ZZ?....crap." – intuited Jun 04 '10 at 04:18
  • 1
    @hasen easy, from insert mode jhjjrja – jbleners Jun 05 '11 at 18:37
  • @intuited that isn't really a problem, just `vim "+'0"` (use undofile and viminfo for added bonus). Now, `ZQ` _would_ be an accident but not as likely to happen by chance – sehe Mar 04 '12 at 21:46
  • 5
    @ojblass: Not sure how many people ever right matlab code in Vim, but `ii` and `jj` are commonly used for counter variables, because `i` and `j` are reserved for complex numbers. – brianmearns Oct 03 '12 at 12:45
  • 1
    I used `control-c` to exit insert mode, the only constrain is I cannot use `control-c` after I inserted text in Visual block mode. I need to use `esc` for this case. – attomos Sep 07 '13 at 14:07
  • I have almost the same mapping: imap kj I find it faster than jj and more natural than jk probably because I have more strength in my middle finger. The pattern middle finger then index finger is more simple. This simple mapping is one of my favourite so far. – Taurus Olson Oct 09 '13 at 12:21
  • The best one is: inoremap – alexzzp Dec 01 '13 at 12:10
  • 1
    While `` is really bad, I find `ctrl-[` comfortable enough not to look for replacements. Felt a little bit weird at first, but now it's a second nature. – Marcin Łoś Dec 09 '13 at 19:28
  • 3
    `jk` - once you go jk, you don't use anything else. I have `Shift+Space` to toggle insert mode, system-wide caps to esc, `jj` and built-in `C-[`. But `jk` beats them all. I've read it in the vim wikia, but ignored it, because I wouldn't be able to write jk! It's been a while since then and never ever needed to write jk literally. It should be a vim default :) imap jk vmap jk (exit visual mode!) – freeo Dec 10 '13 at 08:30
  • you don't have to type jj. Ctrl-c will also take you to the normal mode.. In-fact this is such faster way to toggle mode and yet so few do it. – vHalaharvi Mar 11 '15 at 17:29
  • I agree with @freeo that `jk` is better. I often find myself just doing `jkjkjkjk` over and over now, while thinking. It doesn't screw up cursor position, and it lets me know what window/pane I'm on. I mapped `jk` and `kj` to escape. To me, `jj` is inferior because the cursor is then 2 lines down. – Funkodebat Mar 30 '15 at 16:58
  • @Alex "I remapped capslock to esc instead, as it's an otherwise useless key." It's also a bastard of a key. How many times have you tried to use vim without knowing caps lock was on? Try to hit `u` and it does that weird shit that `U` does. Try to move right and you go to the bottom of the page. And it messes with you until you try to insert with `i`, which takes you to the beginning of the line rather than where you were, and then YOUR TYPING COMES OUT LIKE THIS. There's another reason to re- or un-map caps lock. – Braden Best Feb 04 '16 at 16:14
36

Let's see some pretty little IDE editor do column transposition.

:%s/\(.*\)^I\(.*\)/\2^I\1/

Explanation

\( and \) is how to remember stuff in regex-land. And \1, \2 etc is how to retrieve the remembered stuff.

>>> \(.*\)^I\(.*\)

Remember everything followed by ^I (tab) followed by everything.

>>> \2^I\1

Replace the above stuff with "2nd stuff you remembered" followed by "1st stuff you remembered" - essentially doing a transpose.

Jens
  • 61,963
  • 14
  • 104
  • 160
chaos
  • 115,791
  • 31
  • 292
  • 308
  • 1
    What does it do exactly? –  Apr 07 '09 at 18:18
  • 4
    Switches a pair of tab-separated columns (separator arbitrary, it's all regex) with each other. – chaos Apr 07 '09 at 18:33
  • 2
    The ^I is meant to be a tab, incidentally. – chaos Apr 07 '09 at 19:50
  • 41
    This is just a regex; plenty of IDEs have regex search-and-replace. – rlbond Apr 26 '09 at 04:11
  • 7
    @rlbond - It comes down to how good is the regex engine in the IDE. Vim's regexes are pretty powerful; others.. not so much sometimes. – romandas Jun 19 '09 at 16:58
  • 3
    The * will be greedy, so this regex assumes you have just two columns. If you want it to be nongreedy use {-} instead of * (see :help non-greedy for more information on the {} multiplier) – Kimball Robinson Apr 16 '10 at 00:32
  • 1
    @romandas: If all you want to do is column transposition, then you don't need a powerful regex engine. Just sayin. – intuited Jun 04 '10 at 02:53
  • 2
    @intuited - Of course. But I've never found that to be all I wanted. :) – romandas Jun 07 '10 at 00:31
  • 4
    This is actually a pretty simple regex, it's only escaping the group parentheses that makes it look complicated. – mk12 Jun 22 '12 at 17:31
31

Not exactly a dark secret, but I like to put the following mapping into my .vimrc file, so I can hit "-" (minus) anytime to open the file explorer to show files adjacent to the one I just edit. In the file explorer, I can hit another "-" to move up one directory, providing seamless browsing of a complex directory structures (like the ones used by the MVC frameworks nowadays):

map - :Explore<cr>

These may be also useful for somebody. I like to scroll the screen and advance the cursor at the same time:

map <c-j> j<c-e>
map <c-k> k<c-y>

Tab navigation - I love tabs and I need to move easily between them:

map <c-l> :tabnext<enter>
map <c-h> :tabprevious<enter>

Only on Mac OS X: Safari-like tab navigation:

map <S-D-Right> :tabnext<cr>
map <S-D-Left> :tabprevious<cr>
KKovacs
  • 100
  • 3
  • 7
27

Often, I like changing current directories while editing - so I have to specify paths less.

cd %:h
rampion
  • 82,104
  • 41
  • 185
  • 301
  • What does this do? And does it work with autchdir? – Leonard May 08 '09 at 01:54
  • 2
    I suppose it would override autochdir temporarily (until you switched buffers again). Basically, it changes directory to the root directory of the current file. It gives me a bit more manual control than autochdir does. – rampion May 08 '09 at 02:55
  • 1
    :set autochdir //this also serves the same functionality and it changes the current directory to that of file in buffer – Naga Kiran Jul 08 '09 at 13:44
27

I like to use 'sudo bash', and my sysadmin hates this. He locked down 'sudo' so it could only be used with a handful of commands (ls, chmod, chown, vi, etc), but I was able to use vim to get a root shell anyway:

bash$ sudo vi +'silent !bash' +q
Password: ******
root#
too much php
  • 81,874
  • 33
  • 123
  • 133
  • 9
    FWIW, sudoedit (or sudo -e) edits privileged files but runs your editor as your normal user. – RJHunter Jul 21 '09 at 00:53
  • 12
    yeah... I'd hate you too ;) you should only need a root shell VERY RARELY, unless you're already in the habit of running too many commands as root which means your permissions are all screwed up. – We Are All Monica Feb 22 '11 at 15:58
  • 5
    Why does your sysadmin even give you root? :D – d33tah Mar 30 '14 at 17:50
25

I often use many windows when I work on a project and sometimes I need to resize them. Here's what I use:

map + <C-W>+
map - <C-W>-

These mappings allow to increase and decrease the size of the current window. It's quite simple but it's fast.

Taurus Olson
  • 2,795
  • 1
  • 24
  • 21
23

Not an obscure feature, but very useful and time saving.

If you want to save a session of your open buffers, tabs, markers and other settings, you can issue the following:

mksession session.vim

You can open your session using:

vim -S session.vim
mohi666
  • 5,904
  • 8
  • 34
  • 44
23
:r! <command>

pastes the output of an external command into the buffer.

Do some math and get the result directly in the text:

:r! echo $((3 + 5 + 8))

Get the list of files to compile when writing a Makefile:

:r! ls *.c

Don't look up that fact you read on wikipedia, have it directly pasted into the document you are writing:

:r! lynx -dump http://en.wikipedia.org/wiki/Whatever
Roberto Bonvallet
  • 27,307
  • 5
  • 37
  • 57
  • 14
    ^R=3+5+8 in insert mode will let you insert the value of the expression (3+5+8) in text with fewer keystrokes. – Sudhanshu Jun 07 '10 at 08:40
  • How can I get the result/output to a different buffer than the current? – dcn Mar 27 '11 at 10:13
  • Related: [How to dump output from external command into editor?](http://vi.stackexchange.com/questions/795/how-to-dump-output-from-external-command-into-editor) at Vim SE – kenorb Feb 19 '15 at 11:31
21

Map F5 to quickly ROT13 your buffer:

map <F5> ggg?G``

You can use it as a boss key :).

jqno
  • 13,931
  • 7
  • 52
  • 76
19

I use vim for just about any text editing I do, so I often times use copy and paste. The problem is that vim by default will often times distort imported text via paste. The way to stop this is to use

:set paste

before pasting in your data. This will keep it from messing up.

Note that you will have to issue :set nopaste to recover auto-indentation. Alternative ways of pasting pre-formatted text are the clipboard registers (* and +), and :r!cat (you will have to end the pasted fragment with ^D).

It is also sometimes helpful to turn on a high contrast color scheme. This can be done with

:color blue

I've noticed that it does not work on all the versions of vim I use but it does on most.

maat
  • 26
  • 6
  • 11
    The "distortion" is happening because you have some form of automatic indentation enabled. Using `set paste` or specifying a key for the `pastetoggle` option is a common way to work around this, but the same effect can be achieved with `set mouse=a` as then Vim knows that the flood of text it sees is a paste triggered by the mouse. – jamessan Dec 28 '09 at 08:27
  • 1
    If you have gvim installed you can often (though it depends on what your options your distro compiles vim with) use the X clipboard directly from vim through the * register. For example `"*p` to paste from the X xlipboard. (It works from terminal vim, too, it's just that you might need the gvim package if they're separate) – remmy Oct 19 '13 at 12:15
  • 2
    @kyrias for the record, `*` is the `PRIMARY` ("middle-click") register. The *clipboard* is `+` – Braden Best Feb 04 '16 at 16:26
19

I just found this one today via NSFAQ:

Comment blocks of code.

Enter Blockwise Visual mode by hitting CTRL-V.

Mark the block you wish to comment.

Hit I (capital I) and enter your comment string at the beginning of the line. (// for C++)

Hit ESC and all lines selected will have // prepended to the front of the line.

Grant Limberg
  • 19,335
  • 10
  • 59
  • 84
  • I added # to comment out a block of code in ruby. How do I undo it. – Neeraj Singh Jun 17 '09 at 16:56
  • well, if you haven't done anything else to the file, you can simply type u for undo. Otherwise, I haven't figured that out yet. – Grant Limberg Jun 17 '09 at 19:29
  • 3
    You can just hit ctrl+v again, mark the //'s and hit x to "uncomment" – nos Jul 28 '09 at 20:00
  • 6
    I use NERDCommenter for this. – ZyX Mar 07 '10 at 14:18
  • @NeerajSingh: you can undo that by pressing CTR+V, selecting the column of #'s and press x to remove them. – d33tah Mar 30 '14 at 17:49
  • NERDCommentor is the way forward for commenting. `\cc` - comment line. `5\cc` comment 5 lines. `5\ci` - invert comment of next 5 lines (commented lines will be uncommented, and vice-versa). `5\cs` - block comment the next 5 lines of code. etc. etc. – cartbeforehorse Aug 24 '14 at 22:09
  • 1
    Commented out code is probably one of the worst types of comment you could possibly put in your code. There are better uses for the awesome block insert. – Braden Best Feb 04 '16 at 16:23
  • @BradenBest why do you say that? what are those better uses for awesome block insert – Pie Jul 28 '19 at 06:24
  • 1
    @Pie because commented out code is **dead code**. Dead code serves no useful purpose and creates clutter. You *think* you're preserving code you might want to bring back later, but there's always a better way. You can use your undo history, you can dupe the file, or you can use git, which has this functionality built in (`git checkout`). As for better uses for block insert, there aren't any set-in-stone. You just use it whenever you have multiple lines where you want to insert the same sequence of characters at the same place. – Braden Best Jul 29 '19 at 00:31
  • I'd be lying if I said I never comment out code. I'm guilty of that occasionally, too. But I recognize that it's bad practice, and I make a serious point to either delete it or bring it back when I'm done with whatever experiment I'm doing at the time. – Braden Best Jul 29 '19 at 00:33
11

Here's something not obvious. If you have a lot of custom plugins / extensions in your $HOME and you need to work from su / sudo / ... sometimes, then this might be useful.

In your ~/.bashrc:

export VIMINIT=":so $HOME/.vimrc"

In your ~/.vimrc:

if $HOME=='/root'
        if $USER=='root'
                if isdirectory('/home/your_typical_username')
                        let rtuser = 'your_typical_username'
                elseif isdirectory('/home/your_other_username')
                        let rtuser = 'your_other_username'
                endif
        else
                let rtuser = $USER
        endif
        let &runtimepath = substitute(&runtimepath, $HOME, '/home/'.rtuser, 'g')
endif

It will allow your local plugins to load - whatever way you use to change the user.

You might also like to take the *.swp files out of your current path and into ~/vimtmp (this goes into .vimrc):

if ! isdirectory(expand('~/vimtmp'))
   call mkdir(expand('~/vimtmp'))
endif
if isdirectory(expand('~/vimtmp'))
   set directory=~/vimtmp
else
   set directory=.,/var/tmp,/tmp
endif

Also, some mappings I use to make editing easier - makes ctrl+s work like escape and ctrl+h/l switch the tabs:

inoremap <C-s> <ESC>
vnoremap <C-s> <ESC>
noremap <C-l> gt
noremap <C-h> gT

viraptor
  • 30,857
  • 7
  • 96
  • 176
  • Just in case you didn't already know, ctrl+c already works like escape. – Kyle Challis Apr 02 '14 at 21:18
  • I prefer never to run vim as root/under sudo - and would just run the command from vim e.g. ``:!sudo tee %``, ``:!sudo mv % /etc`` or even launch a login shell ``:!sudo -i`` – shalomb Aug 24 '15 at 08:02
11

Ctrl-n while in insert mode will auto complete whatever word you're typing based on all the words that are in open buffers. If there is more than one match it will give you a list of possible words that you can cycle through using ctrl-n and ctrl-p.

philant
  • 31,604
  • 11
  • 64
  • 107
Niki Yoshiuchi
  • 14,935
  • 1
  • 30
  • 41
11

Want an IDE?

:make will run the makefile in the current directory, parse the compiler output, you can then use :cn and :cp to step through the compiler errors opening each file and seeking to the line number in question.

:syntax on turns on vim's syntax highlighting.

Tico
  • 2,686
  • 2
  • 30
  • 35
caskey
  • 11,131
  • 2
  • 24
  • 27
10
gg=G

Corrects indentation for entire file. I was missing my trusty <C-a><C-i> in Eclipse but just found out vim handles it nicely.

daltonb
  • 575
  • 6
  • 26
10

Variation of sudo write:

into .vimrc

cmap w!! w !sudo tee % >/dev/null

After reload vim you can do "sudo save" as

:w!!
jm666
  • 52,991
  • 14
  • 92
  • 160
9

Ability to run Vim on a client/server based modes.

For example, suppose you're working on a project with a lot of buffers, tabs and other info saved on a session file called session.vim.

You can open your session and create a server by issuing the following command:

vim --servername SAMPLESERVER -S session.vim

Note that you can open regular text files if you want to create a server and it doesn't have to be necessarily a session.

Now, suppose you're in another terminal and need to open another file. If you open it regularly by issuing:

vim new_file.txt

Your file would be opened in a separate Vim buffer, which is hard to do interactions with the files on your session. In order to open new_file.txt in a new tab on your server use this command:

vim --servername SAMPLESERVER --remote-tab-silent new_file.txt

If there's no server running, this file will be opened just like a regular file.

Since providing those flags every time you want to run them is very tedious, you can create a separate alias for creating client and server.

I placed the followings on my bashrc file:

alias vims='vim --servername SAMPLESERVER'
alias vimc='vim --servername SAMPLESERVER --remote-tab-silent'

You can find more information about this at: http://vimdoc.sourceforge.net/htmldoc/remote.html

mohi666
  • 5,904
  • 8
  • 34
  • 44
9

I often want to highlight a particular word/function name, but don't want to search to the next instance of it yet:

map m* *#
Scotty Allen
  • 11,695
  • 9
  • 34
  • 51
8

HOWTO: Auto-complete Ctags when using Vim in Bash. For anyone else who uses Vim and Ctags, I've written a small auto-completer function for Bash. Add the following into your ~/.bash_completion file (create it if it does not exist):

Thanks go to stylishpants for his many fixes and improvements.

_vim_ctags() {
    local cur prev

    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    case "${prev}" in
        -t)
            # Avoid the complaint message when no tags file exists
            if [ ! -r ./tags ]
            then
                return
            fi

            # Escape slashes to avoid confusing awk
            cur=${cur////\\/}

            COMPREPLY=( $(compgen -W "`awk -vORS=" "  "/^${cur}/ { print \\$1 }" tags`" ) )
            ;;
        *)
            _filedir_xspec
            ;;
    esac
}

# Files matching this pattern are excluded
excludelist='*.@(o|O|so|SO|so.!(conf)|SO.!(CONF)|a|A|rpm|RPM|deb|DEB|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MP?(E)G|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)'

complete -F _vim_ctags -f -X "${excludelist}" vi vim gvim rvim view rview rgvim rgview gview

Once you restart your Bash session (or create a new one) you can type:

Code:

~$ vim -t MyC<tab key>

and it will auto-complete the tag the same way it does for files and directories:

Code:

MyClass MyClassFactory
~$ vim -t MyC

I find it really useful when I'm jumping into a quick bug fix.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
michael
  • 10,929
  • 2
  • 24
  • 25
7

:setlocal autoread

Auto reloads the current buffer..especially useful while viewing log files and it almost serves the functionality of "tail" program in unix from within vim.

Checking for compile errors from within vim. set the makeprg variable depending on the language let's say for perl

:setlocal makeprg = perl\ -c \ %

For PHP

set makeprg=php\ -l\ %
set errorformat=%m\ in\ %f\ on\ line\ %l

Issuing ":make" runs the associated makeprg and displays the compilation errors/warnings in quickfix window and can easily navigate to the corresponding line numbers.

Naga Kiran
  • 8,006
  • 5
  • 39
  • 49
7

% is also good when you want to diff files across two different copies of a project without wearing out the pinkies (from root of project1):

:vert diffs /project2/root/%
Ben
  • 615
  • 3
  • 12
7

I use Vim for everything. When I'm editing an e-mail message, I use:

gqap (or gwap)

extensively to easily and correctly reformat on a paragraph-by-paragraph basis, even with quote leadin characters. In order to achieve this functionality, I also add:

-c 'set fo=tcrq' -c 'set tw=76'

to the command to invoke the editor externally. One noteworthy addition would be to add 'a' to the fo (formatoptions) parameter. This will automatically reformat the paragraph as you type and navigate the content, but may interfere or cause problems with errant or odd formatting contained in the message.

BenMorel
  • 30,280
  • 40
  • 163
  • 285
Gary Chambers
  • 1,199
  • 1
  • 10
  • 10
  • 1
    `autocmd FileType mail set tw=76 fo=tcrq` in your `~/.vimrc` will also work, if you can't edit the external editor command. – Andrew Ferrier Jul 14 '14 at 22:22
6
==========================================================
In normal mode
==========================================================
gf ................ open file under cursor in same window --> see :h path
Ctrl-w f .......... open file under cursor in new window
Ctrl-w q .......... close current window
Ctrl-w 6 .......... open alternate file --> see :h #
gi ................ init insert mode in last insertion position
'0 ................ place the cursor where it was when the file was last edited
jamessan
  • 37,987
  • 8
  • 79
  • 85
SergioAraujo
  • 8,735
  • 1
  • 46
  • 37
6

Due to the latency and lack of colors (I love color schemes :) I don't like programming on remote machines in PuTTY. So I developed this trick to work around this problem. I use it on Windows.

You will need

  • 1x gVim
  • 1x rsync on remote and local machines
  • 1x SSH private key auth to the remote machine so you don't need to type the password
  • 1x Pageant
  • 1x PuTTY

Setting up remote machine

Configure rsync to make your working directory accessible. I use an SSH tunnel and only allow connections from the tunnel:

address = 127.0.0.1
hosts allow = 127.0.0.1
port = 40000
use chroot = false
[bledge_ce]
    path = /home/xplasil/divine/bledge_ce
    read only = false

Then start rsyncd: rsync --daemon --config=rsyncd.conf

Setting up local machine

Install rsync from Cygwin. Start Pageant and load your private key for the remote machine. If you're using SSH tunelling, start PuTTY to create the tunnel. Create a batch file push.bat in your working directory which will upload changed files to the remote machine using rsync:

rsync --blocking-io *.cc *.h SConstruct rsync://localhost:40001/bledge_ce

SConstruct is a build file for scons. Modify the list of files to suit your needs. Replace localhost with the name of remote machine if you don't use SSH tunelling.

Configuring Vim That is now easy. We will use the quickfix feature (:make and error list), but the compilation will run on the remote machine. So we need to set makeprg:

set makeprg=push\ &&\ plink\ -batch\ xplasil@anna.fi.muni.cz\ \"cd\ /home/xplasil/divine/bledge_ce\ &&\ scons\ -j\ 2\"

This will first start the push.bat task to upload the files and then execute the commands on remote machine using SSH (Plink from the PuTTY suite). The command first changes directory to the working dir and then starts build (I use scons).

The results of build will show conviniently in your local gVim errors list.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Roman Plášil
  • 1,912
  • 2
  • 15
  • 27
6

Input a character from its hexadecimal value (insert mode):

<C-Q>x[type the hexadecimal byte]
Luper Rouch
  • 8,683
  • 5
  • 39
  • 55
6

Put this in your .vimrc to have a command to pretty-print xml:

function FormatXml()
    %s:\(\S\)\(<[^/]\)\|\(>\)\(</\):\1\3\r\2\4:g
    set filetype=xml
    normal gg=G
endfunction

command FormatXml :call FormatXml()
hasen
  • 148,751
  • 62
  • 182
  • 223
Trumpi
  • 7,160
  • 5
  • 37
  • 50
6

I was sure someone would have posted this already, but here goes.

Take any build system you please; make, mvn, ant, whatever. In the root of the project directory, create a file of the commands you use all the time, like this:

mvn install
mvn clean install
... and so forth

To do a build, put the cursor on the line and type !!sh. I.e. filter that line; write it to a shell and replace with the results.

The build log replaces the line, ready to scroll, search, whatever.

When you're done viewing the log, type u to undo and you're back to your file of commands.

Brad Cox
  • 384
  • 2
  • 6
  • This doesn't seem to fly on my system. Can you show an example only using the ls command? – ojblass Jul 05 '09 at 18:27
  • !!ls replaces current line with ls output (adding more lines as needed). – Brad Cox Jul 29 '09 at 19:30
  • 9
    Why wouldn't you just set `makeprg` to the proper tool you use for your build (if it isn't set already) and then use `:make`? `:copen` will show you the output of the build as well as allowing you to jump to any warnings/errors. – jamessan Dec 28 '09 at 08:29
5

set colorcolumn=+1 or set cc=+1 for vim 7.3

quabug
  • 156
  • 2
  • 8
  • A short explanation would be appreciated... I tried it and could be very usefull! You can even do something like `set colorcolumn=+1,+10,+20` :-) – Luc M Oct 31 '12 at 15:12
  • 2
    @LucM If you tried it why didn't *you* provide an explanation? – DBedrenko Oct 31 '14 at 16:17
  • 5
    `colorcolumn` allows you to specify columns that are highlighted (it's ideal for making sure your lines aren't too long). In the original answer, `set cc=+1` highlights the column after `textwidth`. See the [documentation](http://vimdoc.sourceforge.net/htmldoc/options.html#%27colorcolumn%27) for more information. – mjturner Aug 19 '15 at 11:16
4

:sp %:h - directory listing / file-chooser using the current file's directory

(belongs as a comment under rampion's cd tip, but I don't have commenting-rights yet)

searlea
  • 7,258
  • 4
  • 29
  • 33
  • 1
    ":e ." does the same thing for your current working directory which will be the same as your current file's directory if you set autochdir – bpw1621 Feb 19 '11 at 15:13
4

Just before copying and pasting to stackoverflow:

:retab 1
:% s/^I/ /g
:% s/^/    /

Now copy and paste code.

As requested in the comments:

retab 1. This sets the tab size to one. But it also goes through the code and adds extra tabs and spaces so that the formatting does not move any of the actual text (ie the text looks the same after ratab).

% s/^I/ /g: Note the ^I is tthe result of hitting tab. This searches for all tabs and replaces them with a single space. Since we just did a retab this should not cause the formatting to change but since putting tabs into a website is hit and miss it is good to remove them.

% s/^/    /: Replace the beginning of the line with four spaces. Since you cant actually replace the beginning of the line with anything it inserts four spaces at the beging of the line (this is needed by SO formatting to make the code stand out).

Martin York
  • 234,851
  • 74
  • 306
  • 532
  • so I guess this won't work if you use 'set expandtab' to force all tabs to spaces. – cmcginty Sep 22 '09 at 22:31
  • @Casey: The first two lines will not apply. The last line will make sure you can just cut and paste into SO. – Martin York Sep 23 '09 at 00:07
  • Note that you can achieve the same thing with `cat | awk '{print " " $line}'`. So try `:w ! awk '{print " " $line}' | xclip -i`. That's supposed to be four spaces between the `""` – Braden Best Feb 04 '16 at 16:40
4

When working on a project where the build process is slow I always build in the background and pipe the output to a file called errors.err (something like make debug 2>&1 | tee errors.err). This makes it possible for me to continue editing or reviewing the source code during the build process. When it is ready (using pynotify on GTK to inform me that it is complete) I can look at the result in vim using quickfix. Start by issuing :cf[ile] which reads the error file and jumps to the first error. I personally like to use cwindow to get the build result in a separate window.

Anders Holmberg
  • 246
  • 3
  • 7
4

A few useful ones:

:set nu # displays lines
:44     # go to line 44
'.      # go to last modification line

My favourite: Ctrl + n WORD COMPLETION!

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
dfens
  • 5,135
  • 4
  • 29
  • 48
3

Reuse

Motions to mix with other commands, more here.

tx
fx
Fx

Use your favorite tools in Vim.

:r !python anything you want or awk or Y something

Repeat in visual mode, powerful when combined with tips above.

;
hhh
  • 44,388
  • 56
  • 154
  • 251
3

map macros

I rather often find it useful to on-the-fly define some key mapping just like one would define a macro. The twist here is, that the mapping is recursive and is executed until it fails.

Example:

enum ProcStats
{
        ps_pid,
        ps_comm,
        ps_state,
        ps_ppid,
        ps_pgrp,
:map X /ps_<CR>3xixy<Esc>X

Gives:

enum ProcStats
{
        xypid,
        xycomm,
        xystate,
        xyppid,
        xypgrp,

Just an silly example :).

I am completely aware of all the downsides - it just so happens that I found it rather useful in some occasions. Also it can be interesting to watch it at work ;).

Marcus Borkenhagen
  • 6,246
  • 1
  • 28
  • 32
  • 1
    Macros are also allowed to be recursive and work in pretty much the same fashion when they are, so it's not particularly *necessary* to use a mapping for this. – 00dani Aug 02 '13 at 11:25
3

In insert mode, ctrl+x, ctrl+p will complete (with menu of possible completions if that's how you like it) the current long identifier that you are typing.

if (SomeCall(LONG_ID_ <-- type c-x c-p here
            [LONG_ID_I_CANT_POSSIBLY_REMEMBER]
             LONG_ID_BUT_I_NEW_IT_WASNT_THIS_ONE
             LONG_ID_GOSH_FORGOT_THIS
             LONG_ID_ETC
             ∶
bobbogo
  • 13,257
  • 3
  • 44
  • 53
3
In Insert mode 
<C-A>   - Increments the number under cursor 
<C-X>   - Decrements the number under cursor

It will be very useful if we want to generate sequential numbers in vim
Lets say if we want to insert lines 1-10 with numbers from 1 to 10 [like "1" on 1st line,"2" on 2nd line..]
insert "0" on the first line and copy the line and past 9 times So that all lines will show "0".

Run the following Ex command

:g/^/exe "norm " . line(".") . "\<C-A>"
Naga Kiran
  • 8,006
  • 5
  • 39
  • 49
3

I love :ls command.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
  • gives the current file name opened ? –  Dec 07 '09 at 10:51
  • `:ls` lists all the currently opened buffers. `:be` opens a file in a new buffer, `:bn` goes to the next buffer, `:bp` to the previous, `:b filename` opens buffer filename (it auto-completes too). buffers are distinct from tabs, which i'm told are more analogous to views. – Nona Urbiz Dec 20 '10 at 08:25
3

For making vim a little more like an IDE editor:

  • set nu - for line numbers in the left margin.
  • set cul - highlights the line containing the cursor.
mpe
  • 2,480
  • 1
  • 18
  • 17
  • 17
    How does that make Vim more like an IDE ?? – Rook May 11 '09 at 04:42
  • 1
    I did say "a little" :) But it is something many IDEs do, and some people like it, eg: http://www.eclipse.org/screenshots/images/JavaPerspective-WinXP.png – mpe May 12 '09 at 12:29
  • 1
    Yes, but that's like saying yank/paste functions make an editor "a little" more like an IDE. Those are editor functions. Pretty much everything that goes with the editor that concerns editing text and that particular area is an editor function. IDE functions would be, for example, project/files management, connectivity with compiler&linker, error reporting, building automation tools, debugger ... i.e. the stuff that doesn't actually do nothing with editing text. Vim has some functions & plugins so he can gravitate a little more towards being an IDE, but these are not the ones in question. – Rook May 12 '09 at 21:25
  • 5
    After all, an IDE = editor + compiler + debugger + building tools + ... – Rook May 12 '09 at 21:26
  • Also, just FYI, vim has an option to set invnumber. That way you don't have to "set nu" and "set nonu", i.e. remember two functions - you can just toggle. – Rook May 12 '09 at 21:31
  • Same goes for cursorline ... and a lot others. – Rook May 12 '09 at 21:32
  • this cursor line feature makes VIM ugly slow, actually unusable – robson3.14 Aug 25 '09 at 21:12
2

Try using perltidy for formatting by = normal-mode command

:set equalprg=perltidy
ZyX
  • 49,123
  • 7
  • 101
  • 128
2

Neither of the following is really diehard, but I find it extremely useful.

Trivial bindings, but I just can't live without. It enables hjkl-style movement in insert mode (using the ctrl key). In normal mode: ctrl-k/j scrolls half a screen up/down and ctrl-l/h goes to the next/previous buffer. The µ and ù mappings are especially for an AZERTY-keyboard and go to the next/previous make error.

imap <c-j> <Down>
imap <c-k> <Up>
imap <c-h> <Left>
imap <c-l> <Right>
nmap <c-j> <c-d>
nmap <c-k> <c-u>
nmap <c-h> <c-left>
nmap <c-l> <c-right>

nmap ù :cp<RETURN>
nmap µ :cn<RETURN>

A small function I wrote to highlight functions, globals, macro's, structs and typedefs. (Might be slow on very large files). Each type gets different highlighting (see ":help group-name" to get an idea of your current colortheme's settings) Usage: save the file with ww (default "\ww"). You need ctags for this.

nmap <Leader>ww :call SaveCtagsHighlight()<CR>

"Based on: http://stackoverflow.com/questions/736701/class-function-names-highlighting-in-vim
function SaveCtagsHighlight()
    write

    let extension = expand("%:e")
    if extension!="c" && extension!="cpp" && extension!="h" && extension!="hpp"
        return
    endif

    silent !ctags --fields=+KS *
    redraw!

    let list = taglist('.*')
    for item in list
        let kind = item.kind

        if     kind == 'member'
            let kw = 'Identifier'
        elseif kind == 'function'
            let kw = 'Function'
        elseif kind == 'macro'
            let kw = 'Macro'
        elseif kind == 'struct'
            let kw = 'Structure'
        elseif kind == 'typedef'
            let kw = 'Typedef'
        else
            continue
        endif

        let name = item.name
        if name != 'operator=' && name != 'operator ='
            exec 'syntax keyword '.kw.' '.name
        endif
    endfor
    echo expand("%")." written, tags updated"
endfunction

I have the habit of writing lots of code and functions and I don't like to write prototypes for them. So I made some function to generate a list of prototypes within a C-style sourcefile. It comes in two flavors: one that removes the formal parameter's name and one that preserves it. I just refresh the entire list every time I need to update the prototypes. It avoids having out of sync prototypes and function definitions. Also needs ctags.

"Usage: in normal mode, where you want the prototypes to be pasted:
":call GenerateProptotypes()
function GeneratePrototypes()
    execute "silent !ctags --fields=+KS ".expand("%")
    redraw!
    let list = taglist('.*')
    let line = line(".")
    for item in list
        if item.kind == "function"  &&  item.name != "main"
            let name = item.name
            let retType = item.cmd
            let retType = substitute( retType, '^/\^\s*','','' )
            let retType = substitute( retType, '\s*'.name.'.*', '', '' ) 

            if has_key( item, 'signature' )
                let sig = item.signature
                let sig = substitute( sig, '\s*\w\+\s*,',        ',',   'g')
                let sig = substitute( sig, '\s*\w\+\(\s)\)', '\1', '' )
            else
                let sig = '()'
            endif
            let proto = retType . "\t" . name . sig . ';'
            call append( line, proto )
            let line = line + 1
        endif
    endfor
endfunction


function GeneratePrototypesFullSignature()
    "execute "silent !ctags --fields=+KS ".expand("%")
    let dir = expand("%:p:h");
    execute "silent !ctags --fields=+KSi --extra=+q".dir."/* "
    redraw!
    let list = taglist('.*')
    let line = line(".")
    for item in list
        if item.kind == "function"  &&  item.name != "main"
            let name = item.name
            let retType = item.cmd
            let retType = substitute( retType, '^/\^\s*','','' )
            let retType = substitute( retType, '\s*'.name.'.*', '', '' ) 

            if has_key( item, 'signature' )
                let sig = item.signature
            else
                let sig = '(void)'
            endif
            let proto = retType . "\t" . name . sig . ';'
            call append( line, proto )
            let line = line + 1
        endif
    endfor
endfunction
RoaldFre
  • 185
  • 1
  • 7
2

I collected these over the years.

" Pasting in normal mode should append to the right of cursor
nmap <C-V>      a<C-V><ESC>
" Saving
imap <C-S>      <C-o>:up<CR>
nmap <C-S>      :up<CR>
" Insert mode control delete
imap <C-Backspace> <C-W>
imap <C-Delete> <C-O>dw
nmap    <Leader>o       o<ESC>k
nmap    <Leader>O       O<ESC>j
" tired of my typo
nmap :W     :w
Yada
  • 27,686
  • 20
  • 97
  • 138
2

Create a function to execute the current buffer using it's shebang (assuming one is set) and call it with crtl-x.

map <C-X> :call CallInterpreter()<CR>

au BufEnter *
\ if match (getline(1) , '^\#!') == 0 |
\   execute("let b:interpreter = getline(1)[2:]") |
\ endif

fun! CallInterpreter()
    if exists("b:interpreter")
        exec("! ".b:interpreter." %")
    endif
endfun
J.C. Yamokoski
  • 964
  • 8
  • 23
2

In order to copy a text from Vim to your clipboard for other application to use, select the text you want to copy in visual mode, and then press "+y. This way, you can easily paste your text to other applications.

This is particularly useful, if you have splitted the window vertically and you want to copy something from the right window. Using set mouse=r, won't help you with this situation, since it will select everything on the left window as well.

Note that your vim has to be compiled with xterm support.

mohi666
  • 5,904
  • 8
  • 34
  • 44
  • 1
    To test if your version of vim is compiled with the clipboard, do `vim --version | grep clipboard` and you should have the following arguments: `+clipboard` and `+xterm_clipboard`. – laughing_man Mar 21 '14 at 21:22
2

Use the right mouse key to toggle insert mode in gVim with the following settings in ~/.gvimrc :

"
"------------------------------------------------------------------
" toggle insert mode <--> 'normal mode with the <RightMouse>-key
"------------------------------------------------------------------
nnoremap  <RightMouse> <Insert>
inoremap  <RightMouse> <ESC>
"
Fritz G. Mehner
  • 14,814
  • 2
  • 30
  • 40
2

Replace all

  :%s/oldtext/newtext/igc

Give a to replace all :)

AIB
  • 5,562
  • 8
  • 29
  • 35
1

Mappings to make movements operate on the current screen line in wrap mode. I discovered this in a comment for a Vim tip some time ago, and it has proven quite handy.

function! ScreenMovement(movement)
  if &wrap
    return "g" . a:movement
  else
    return a:movement
  endif
endfunction
onoremap <silent> <expr> j ScreenMovement("j")
onoremap <silent> <expr> k ScreenMovement("k")
onoremap <silent> <expr> 0 ScreenMovement("0")
onoremap <silent> <expr> ^ ScreenMovement("^")
onoremap <silent> <expr> $ ScreenMovement("$")
nnoremap <silent> <expr> j ScreenMovement("j")
nnoremap <silent> <expr> k ScreenMovement("k")
nnoremap <silent> <expr> 0 ScreenMovement("0")
nnoremap <silent> <expr> ^ ScreenMovement("^")
nnoremap <silent> <expr> $ ScreenMovement("$")
Mark42
  • 37
  • 1
1

per this thread

To prefix a set of lines I use one of two different approaches:

One approach is the block select (mentioned by sth). In general, you can select a rectangular region with ctrl-V followed by cursor-movement. Once you've highlighted a rectangle, pressing shift-I will insert characters on the left side of the rectangle, or shift-A will append them on the right side of the rectangle. So you can use this technique to make a rectangle that includes the left-most column of the lines you want to prefix, hit shift-I, type the prefix, and then hit escape.

The other approach is to use a substitution (as mentioned by Brian Agnew). Brian's substitution will affect the entire file (the % in the command means "all lines"). To affect just a few lines the easiest approach is to hit shift-V (which enables visual-line mode) while on the first/last line, and then move to the last/first line. Then type:

:s/^/YOUR PREFIX/

The ^ is a regex (in this case, the beginning of the line). By typing this in visual line mode you'll see '<,'> inserted before the s automatically. This means the range of the substitution will be the visual selection.

Extra tip: if your prefix contains slashes, you can either escape them with backslash, or you can use a different punctuation character as the separator in the command. For example, to add C++ line comments, I usually write:

:s:^:// :

For adding a suffix the substitution approach is generally easier unless all of your lines are exactly the same length. Just use $ for the pattern instead of ^ and your string will be appended instead of pre-pended.

If you want to add a prefix and a suffix simultaneously, you can do something like this:

:s/.*/PREFIX & SUFFIX/

The .* matches the whole line. The & in the replacement puts the matched text (the whole line) back, but now it'll have your prefix and suffix added.

BTW: when commenting out code you'll probably want to uncomment it later. You can use visual-block (ctrl-V) to select the slashes and then hit d to delete them, or you can use a substitution (probably with a visual line selection, made with shift-V) to remove the leading slashes like this:

:s:// ::

Community
  • 1
  • 1
vehomzzz
  • 37,854
  • 69
  • 173
  • 207
1

Mine is using macros instead of searches - combining a macro with visual mode is sometimes more efficient.

lukaszkorecki
  • 1,533
  • 1
  • 14
  • 18
1

My favourite recipe to switch back and forth between windows:

function! SwitchPrevWin()
    let l:winnr_index = winnr()
    if l:winnr_index > 1
       let l:winnr_index -= 1
    else
       "set winnr_index to max window open
        let l:winnr_index = winnr('$')
    endif
    exe l:winnr_index . "wincmd w" 
endfunction

nmap <M-z> :call SwitchPrevWin()
imap <M-z> <ESC>:call SwitchPrevWin()

nmap <C-z> :wincmd w
imap <C-z> <ESC>:wincmd w
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
ken
  • 10,924
  • 5
  • 35
  • 32
1

I'd like to arrange some of my own config files in after-directory. It's especially useful for ftplugin.

You can avoid to write a long list of augroup in your .vimrc file instead of separate files for each type.

But, obviously, .vim/ftplugin directory do the same thing as .vim/after/ftplugin, but I'd prefer to leave .vim directory to vim plugins.

quabug
  • 156
  • 2
  • 8
1

Some of my must-haves are:

cscope + ctags + vim, which can be found on the web.

Some abreviations for quickly starting new code files such as:

ab cpph #include <iostream><CR>#include <string><CR>#include <cstdlib><CR>#include <cassert><CR>#include <vector><CR>#include <
stdexcept><CR>using namespace std;<CR>int main(int argc, char *argv[]) {
ab perlh #!/usr/bin/perl<CR>use strict;<CR>use warnings;<CR>
ab chdr #include <stdio.h><CR>#include <sys/types.h><CR>#include <unistd.h><CR>#include <stdlib.h><CR>#include <sys/stat.h><CR>
#include <sys/wait.h><CR>#include <string.h><CR>int main(int argc, char *argv[]) {
ab xhtmlhdr <?xml version="1.0" encoding="UTF-8"?><CR><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.o
rg/TR/xhtml1/DTD/xhtml1-strict.dtd"><CR><html xmlns="http://www.w3.org/1999/xhtml"><CR>  <head><CR>  <title></title><CR><link h
ref="style.css" rel="STYLESHEET" type="text/css"><CR></head>

For example cpph will insert a basic skeleton of a main.cc file

There is also my mapping of the function keys:

map <F1> <Esc>:w<CR>:perl $e = `./error.pl`; my ($f,$l,@w) = split(":",$e); my $w=join(":",@w); $curwin->Cursor($l,0); VIM::Msg($w);<CR>
map <F2> :wincmd w<CR>
map <F3> :wincmd s<CR>
map <F4> :wincmd v<CR>
map <F5> :wincmd o<CR>
map <F6> :sball<CR>
map <F7> :wq<CR>
map <F8> :wincmd q<CR>
map <F9> :wincmd -<CR>
map <F10> :wincmd +<CR>
map <F11> :wincmd <<CR>
map <F12> :wincmd ><CR>

In this case my F1 is mapped to put the cursor over the next error that needs to be corrected for a source code migration.

map _ ebi"^[ea"^[

This map would make _ quote a string

piotr
  • 5,381
  • 1
  • 30
  • 56