Textmate to VIM

Where I explain how to reproduce over 110 commands from Textmate in VIM.

When I switched from Textmate to VIM I felt like a tourist lost on a Japanese subway without a guide, translator or hope. I was unable to find in VIM the features I'd come to love and rely on in Textmate. I yearned for ⌘ + T to summon my models, a project drawer to manage my files, and snippets to save my fingers.

Instead of accommodating my needs, VIM sat firm and unresponsive, save for a judgemental beep. Even though I was supposed to go cold turkey on Textmate, I met her by night for a guilty after-hours edit.

With time I learned to mimic nearly every Textmate feature in VIM, and then some. This guide isn't about the powerful functionality VIM has over-and-above Textmate; you'll figure this out with time. This guide is to help you do in VIM what you already can using Textmate, only with considerably less pain than I underwent.

This guide makes a few assumptions:

  1. 1.You are using a Mac.
  2. 2.You've installed Mac VIM. The easiest way is using Home Brew. brew install macvim
  3. 3.You've installed Janus, the community-maintained VIM distro with plugins and configurations useful to Rails programmers accustomed to Textmate.
  4. 4.You've created a ~/.vimrc.local file (for core VIM configurations), ~/.gvimrc.local (for configuring the graphics in VIM) and ~/.janus.rake (for adding or removing plugins in VIM). See my dotfiles for some commented examples. Better yet, use them as sensible defaults.
  5. 5.You've already learned the basics of VIM. If you haven't type vimtutor in your terminal for a 20 minute tutorial. Advanced training can be found be referring to the vim training resources below.
  6. 6.You were a power user of Textmate.
  7. 7.You are a Rails programmer switching from Textmate to VIM. About 30% of this guide is Rails specific.

This guide may only be reproduced with the express permission of Jack Kinsella - Rails Developer, Berlin

Some Preliminary Notes (Do Not Skip)

|Command | Shortcut in Textmate | Shortcut in Vim|

  • In general the keyboard shortcuts in Textmate require you to press the keys at the same time. Below, this is symbolised by a +. VIM's shortcuts, by contrast, typically require you to press the keys in quick succession, rather than at the same time. If you see 'dd' this means type d twice.

  • Whilst commands in Textmate are case insensitive, or rather the shift key is specified in the commands below, the commands in VIM are case sensitive. If I tell you to type Y then typing y will not suffice.

  • Unless otherwise specified, all the VIM commands assume you are in normal mode, the mode where you cannot type text into the file.

  • If I instruct you to add something to your vimrc.local or gvimrc.local files you will need to type :source ~/.vimrc.local or :source .gvimrc.local to reload VIM with your changes.

  • If I instruct you to add code to your .janus.rake file, you must cd into your ~/.vim directory and run rake for these changes to be installed.

  • Regular expressions in VIM differ from those in Textmate, and these are outside the scope of this guide. 90% of these differences will be alleviated if you add this to your .vimrc.local: nnoremap / /\v vnoremap / /\v

This automaticaly prefixes your search commands with \v (Technically, the commands map the key /, symbolising search, to /\v, meaning search with 'very magic' regex syntax. There are two entries since the remapping happens in two modes.). 'Very magic' regex syntax means that all ASCII characters except '0'-'9', 'a'-'z', 'A'-'Z' and '' have a special meaning. Without this you would need to escape many characters which are standard regex syntax in, say, Ruby._

Opening, Closing and Creating Files

| Open a file | ⌘ + 0 | :e FILENAME Use Tab completion after typing the first few letters. You may need to save your current file first. | | Create new file | File > new | ⌘ + T (new tab) You will be in a new file on a separate tab. Type something and then save with: :w newfilename :e newfilename Opens a new file in the current window._ | | Quit | ⌘ + q | :q This throws an error if you have not saved. use :wq to save and quit or :q! to quit without saving. | | Open project from command line | [cd to folder] mate . | [cd to folder] mvim . |

Saving Files

| Save file | ⌘ + S | :w | | Save file as | ⌘ + ⇧ + S | :w NEWFILENAME |

Undo / Redo

| Undo | ⌘ + Z | u | | Redo | ⇧ + ⌘ + Z | ⌃ + R |

File Renaming

| Rename a file | Focus on the project drawer and select a file. Press spacebar. Type a new name. | Start by "focusing on the NERDTree":#nerd_tree. Select the file you wish to rename (however you want: e.g. with a search or plain old jklh). Type 'm' to bring up a menu. Type 'm' again to chose to modify the file name. Type the new name of file and press enter. |

##(#nerd_tree). Project Drawer/ NERDTree

| Focus on project drawer | ⌃ + | "Switch tabs until selected":#switch_tabs | | Close/Open project drawer | ⌃ + ⌥ + ⌘ + D |\n| | Change size of project drawer | Use mouse to adjust size | [add this to your .vimrc] let NERDTreeWinSize=16 | | Create new in Project Drawer | ⌘ + ⇧ + N | Select Project Drawer. Highlight parent folder you'd like file to appear in. Type m the choose a from select menu and type desired filename | | Delete a file | Click on file and select "remove file" | Highlight undesired file file in Project Drawer. Type m then choose d from drop down menu.| | Opening a sub-folder | | Enter to open/close a directory | | Refresh project tree to reflect newly added files | Automatic | Nearly always automatic. Otherwise press r |

Clipboard

| Copy | ⌘ + C | yy Copies the current selection, or, if there is no selection, the current line | | Cut | ⌘ + X | d Technically this deletes the selection, but deleting in VIM saves the deleted text to a register where it can be now be pasted with p| | Paste | ⌘ + V | p Pastes below the current line P pastes above the current line "0p this pastes the last explicitly copied text. This is important since many commands, such as deleting text, override the paste buffer | | Paste from system clipboard | As above. | "*p VIM distinguishes between its internal clipboards (buffers) and the system's clipboard. | | Clipboard history | ⌘ + ⇧ + V | :reg Show a list of registers each of which can be pasted e.g. "8p pastes the contents of the register 8 |

##(#switch_tabs). Tabs

| New tab | Click on file in project drawer | ⌘ + ⇧ + T | | Drop tab | ⌃ + w | ⌃ + w | | Switch tabs left | ⇧ + ⌘ + ←| gT | | Switch tabs right | ⇧ + ⌘ + →| gt | | Go to tab | ⌘[1-9] | ⌘[1-9]|

Moving Around A File

| Go to beginning of line | ⌃ + A | ^ | | Go to end of line | ⌃ + E | $ | | Go to top of file | ⌘ + ↑ | gg | | Go to bottom of file | ⌘ + ↓ | G | | Move up one line (with caret at same position) | ⌃ + P | k | | Move down one line (with caret at same position) | ⌃ + N| j| | Go to line 20 | ⌘ + L [type a line - e.g. 20] | :20 | | Jump between words left | ⌥ + ← w | b or B Lowercase b goes back one word, where puntuation marks count as word separators. B is back one word where only spaces count as word separators. | |Jump between words right| ⌥ + →| w or W same distinction as above |

Selecting Text

| Begin selection | ⇧ [then use arrows to drag over desired text] | v [enters visual mode. use w to move forward one word. ) to move forward one sentence and % to move to next bracket close. also /apple to move forward to next occurrence of apple]| |Select all| ⌘ + A | ggVG | |Increase selection left one word| ⇧ + ⌥ + ← then alt + ← for each additional word| v(select)w then w for each additional word | |Select a vertical block| ⌥ + drag mouse | ⌃ + v |

Deleting Text

| Delete line | ⌘ + ⇧ + k | dd | | Delete character | Backspace Erases character to the left of the caret | x Erases character under caret | | Delete selected text | Backspace | d |

Moving Text Around

| Move selected text up |⌃ + ⌘ + ↑ (or ↓) | :m 22 moves current line to line 22. Easier if line numbers are on with :set number. Alternatively :m+ or :m+N or :m-N for moving 1 or N lines up or down| | Merge current line With Next Line | ⌃ + ⇧ +J | J | | Sort lines | ⌥ + ⌘ + R > sort in dialogue box | Where you have previously selected text !:sort Where you have nothing selecting and want to act on whole file :%!sort (% is a symbol representing the whole file) |

Searching Files

| Search file downwards for TOM | ⌃ + S TOM | /Tom Then press they enter key and then you can press n or N repeatedly to continue searching up or down| |Search file upwards for TOM | ⇧ + ⌃ + S TOM | ?TOM As above, n or N continue searching up or down | | Full screen | (Lion Only) | ⌘ + Enter | | Search entire project | ⌘ + ⇧ + F | ,a THINGSEARCHINGFOR (ack) | | Find a specific method | ⌘ + ⇧ + t | /def foo then use * to cycle through instances of the method name under the caret. This will not necessarily by definition # does the same but in the oppose direction|

Replacing Text in Files and in Entire Project

|Replace all "donut" with "eclair" in file| ⌘ F Find and replace box where you select 'Replace All'. | :%s/donut/eclair/g | |Replace all "donut" with "eclair" in file, ignoring case | ⌘ F Find and replace dialogue where you then select 'Ignore Case'and then 'Replace All'. | :%s/donut/eclair/gi | |Replace all "donut" with "eclair" in file, confirming each time | ⌘ F Find and replace box where you select 'Replace Next'. | :%s/donut/eclair/gc | |Replace "donut" with "eclair" in entire project| ⌘ + ⇧ + F | :Ack donut[Enter]. A window pops up with all instances of the term. into the ack search window. Type :bufdo %s/donut/eclair/gce. :q the ack search window once down to close it. Save current file first if VIM throws an error| |Replace "donut" with "eclair" in entire project| ⌘ + ⇧ + F | ,a donut[Enter] |

Ruby On Rails

Nearly all of this functionality is thanks to Tpope's Rails.vim plugin.

|Call Ruby On Rails generate script | "⌃ + Pipe [1..8]== |:Rgenerate [controller model scaffold] Blog | |Go To Last Migration| None | :Rmig | |Run migrations| ⌃ + ⇧ + Pipe |[when in a migration] :Rake | |Switch focus to project drawer| ⌘ + ⌥ + ` (check)| ⌃ + w ⌃ + w A good key remapping is to map this onto tab by adding this to your vimrc: noremap | |Insert erb's <%= | ⌃ + ⇧ + . | Type text you want to surround first and place caret some inside. yss= | |Insert erb's <% | ⌃ + ⇧ + . | yss- | |Run unit test caret inside of | ⇧ + ⌘ + R | :.Rake . here represents the current line. You can substitute this for other lines e.g. :40Rake TEST| |Go to test file (e.g. from user.rb to userspec.rb)| ⌥ + ⇧ + ⌘ + ↓ | :A (:AV in a new split, :AT new tab)| |Find related file| ⌥ + ⌘ + ↓ | :R _If typed within the Controller you'll be brought to the View corresponding to the method selected; If typed in view -> Controller; Migrations -> Next Migration; Typed in Model -> Schema. For something more precise see the following VIM only commands | |Go to related controller| ⌥ + ⇧ + ⌘ + ↓ | :Rco | |Go to related helper| As above | :Rhe | |Go to model under cursor| No equivalent| gf [e.g. you see Pos*t.first -> brought to #post.rb | |Go to stylesheet under cursor| No equivalent| gf [e.g. you see<%= stylesheetlinktag 'scaffold' %>-> brought to scaffold.css | |View Rails logs| No equivalent| :Rlogs :Rake logs:clear if takes too long to load| |Go to layout under cursor| No equivalent| gf e.g. you see layout :print -> brought to #print.html.erb | |Go to application.rb| No equivalent| :Renv| |Go to test.rb | No equivalent| :Renv t[tab to autofill out to test]| |Go to controller from link under cursor| No equivalent| gf e.g. you see <%= linkto "New", new_commentpath %> -> brought to #commentscontroller.rb_ | |Create a posts controller | No equivalent |:Rco posts! Note the exclamation mark which distinguishes this create command from the find command.| |Extract to partial| [Select text] ⌃ + H | [Select text] :Rextract PARTIAL_NAME |

Indentation

|Automatically indent code beautifully on whole file | ⌥ + ⌘ + B (Code Beautifier Plugin) | gg=G | |Fix indentation on selected area | No equivalent | = | |Fix indentation on a single line | No equivalent | == Compare with the above to note a pattern. Type a command once to apply it to visually selected areas. Type it twice to apply to the current line, which need not be selected. See also d and dd, y and yy | |Indent|⌘ + [ | > | |Unindent| ⌘ + ] | < |

Font Size, Line Numberings

|Bigger/Smaller Font| ⌘ +/- | [~/gvimrc.local] set guifont=Monaco:h18 You can replace 18 here with your desired font-size [Note that you can try this command out by typing it into a live VIM session just by preceding it with a :, e.g. :set..... Using ⌘ +/- in VIM makes the screen scale disproportionately | |Line numbering| ⌘ + ⇧ + L| :set number Turn on :set nonumber Turn off. Note the symmetry between turning the number on and off, the only different being the preceded "no". This is the same for all VIM set commands. As with other preferences this may be placed in vimrc.local |

Spell Checking

|Highlight incorrect spellings| ⌥ + ⌘ + ; | :set spell | |Next incorrect spelling | ⌘ + : | [Assuming you've enabled spell checking and can see highlighter errors] ] s Go to previous spelling error with [s | |Suggest correct spelling| Double click and select best spelling | z= Then choose the correct spelling from drop down menu|

Bookmarks

|Add bookmark| ⌘ + F2 (Never worked on my mac) | m[a-z] The letter in the range refers to this bookmark | |Jump to bookmark| F2 (next) + F2 (previous) | 'a Where a is a bookmark previously set. Type :marks to see all bookmarks |

Uppercase/Lowercase

|Upcase selected text|⌃ + ⇧ + U| u | |Downcase selected text|⌃ + ⇧ + U| U | |Switchcase of selected text | ⌃ + g | ~ | |Titlecase current text| ⌃ + ⌥ + U | No exact equivalent To titlecase the current line you can use :s :s/<(\w)(\w*)>/\u\1\L\2/g |

Auto-complete

All of the following commands assume you are in insert mode

|Auto-complete method| ⎋ after typing first few letters| Tab after typing first few letters| |Auto-complete filename| No equivalent | ⌃ + X ⌃ + F Only fills one directory at a time so you'll need to repeat for each additional one| |Auto-complete full line of code | No equivalent | ⌃ + X + l |

Commenting Code

|Comment Line or Selection| ⌘ + / | ⌘ + / |

Syntax Errors

|Check for syntax errors on saving (*life saver)| Validate On Save Plugin | Built In A grey bar appears right of the number column with an > beside the error |

Auto-closing Quotes, Html Tags, Brackets.

All of the following commands assume you are in insert mode

|Add opposing bracket or quotation mark| Typing a " will automatically add in closing. | Add this gist | |Close current html tag|⌘ + ⌥ + .| ⌃ + x + / Also you have auto tag creation. To create

type p then ⌃ + X Spacebar Assumes you have the following in your ~/.janus.rake file: _ vimplugin_task "ragtag", "git://github.com/tpope/vim-ragtag.git" _ |

CSS Colours

|View CSS colour wheel| ⌘ + ⇧ + C | No exact equivalent. vimplugintask "vim-css-color", 'git://github.com/skammer/vim-css-color.git' turns #acbdef into its correct colour|

Running Tests and Files

|Run tests for given file|⌘ + r | :Rake | |Run current file| ⌘ + R | :!ruby % Explanation: :! means execute what follows as if in shell. % expands to the currentfilename so you are executing `ruby currentfilename. This runs in a buffer in VIM making you unable to continue editing. |

Snippets

|Snippets (e.g. validates present of)| vp + TAB | vp ⌃ + ] Abbreviations same as in Textmate Non Rails snippets not working since the latest releases of snippets plugin clashes with Command-T search plugin. I've filed bug reports and if anyone has fixed this let me know. | |See All Available Snippers| Use Menu |:Rabbrev|

Syntax Highlighting

|Set syntax highlighting to (e.g.) textile| Varies depending on highlighter. Select manually at the bottom of the screen. | :set syntax=textile You probably won't need this since VIM will automatically figure out the appropriate syntax highlighter.| |Turn on syntax highlighting| No option to enable/disable | :syntax on| |Turn off syntax highlighting| No option | :syntax off|

Formatting

|Reformat selection to according to wrap settings |⌃Q |gq gqgq, i.e. the command twice, to reformat the current line|

Other

|Duplicate line/selection| ⌃ + ⇧ + D| yyp y copies line then p pastes in below. | |Add placeholder text|lorem + tab| lorem + enter Assumes you have add the following to your vimrc.local: " anytime 'lorem' is typed in, replace it with placeholder text abbr lorem Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras a ornare metus. In justo metus, auctor nec semper in, laoreet porttitor augue. Maecenas tortor libero, dignissim vel placerat sit amet, malesuada ut quam. Curabitur vitae velit lacus, sed imperdiet sapien. Sed posuere, odio nec pharetra adipiscing | |Overwrite Mode| ⇧ + ⌥ + O Then start typing text | R Then start typing text | |Edit ends of selected lines|⌘ + ⌥ + a| ⌃ + V to enter VISUAL-BLOCK mode, select your lines, $ to go to the end of the selection, A to enter EDIT mode at the end, ⎋ when you are finished_ | | Edit start of selected lines| No equivalent | Sane as above, except you press I instead of A| |Wrap selected text in P tags| ⇧ + ⌃ + W | ystp |

Help

|Search help for 'grep' | Click help menu and search for help | :help grep |

Email Me If I Left Something Out

Or if you can find a more idiomatic way of doing any of the above commands.

Recommended Resources For Learning Basic VIM

Remember the key is to train your fingers. Don't just read the text; open up a blank file and try out different commands. If you want to get good at VIM you need to have the confidence to tear a file to pieces your training sessions.


More Articles: Click here for full archive

Debugging Rails with Online or Third Party Tools

How Google Webmaster Tools, Google Search, New Relic, and email delivery reports can help you uncover errors in your web application


SEO and Internationalisation

Separate language from territory; clarify your international site structure to Google


Debugging Rails with Git

Source control software gives us a unique insight into changes in code and the human intention behind them.