vim notes :: why i use an editor from the 1990's

contents

a text editor is a tool for editing plain text files. they have features like file and file system navigation, file io, modification, undo, search and replace, spelling and grammar checking, and more. but in this article we're talking about a type of editor referred to as source code editor. beyond the aforementioned functions their features include code detection, syntax highlighting, indentation and formatting, brace matching, code completion, etc.

IDE is an acronym for integrated development environment, it's a suite of programs that work together in a "portable environment" that assists you in writing software. an editor is just one component of an IDE's toolchain. main features include things like code completion, code navigation, error checking, debugging, build automation, versioning, etc. most IDEs are designed for a specific language or related subset of them.

being a long time programmer of a variety of languages i have used both at different times in my career. some "corporate" languages (cough microsoft! cough) like visual basic force you to use their IDE designed for their proprietary suite of tools. but many non-compiled and scripting languages let you write their code however you like. some editors like sublime text can be used for a multitude of languages while others like racket are designed to work with only one.

if you sit around coding java all day, i'm sorry, then maybe using and full blown IDE like Eclipse , Android Studio , or IntelliJ is for you. but on any given day at my current job i will edit files in php, javascript/json, css/sass/stylus, shell scripts, markdown, config files, and a variety of others. i want an editor flexible enough to handle a wide variety of programming languages.

if you adhere to the unix philosophy "dotadiw" or "Do One Thing and Do It Well", many IDE features break this separation of concerns. don't get me wrong, i understand that one of the most alluring attributes of an IDE is that you have your entire toolchain all in one place sharing the same user interface. but i subscribe to the unix as my ide mentality. as a shell user, your tools already work in the same common ui paradigm of text streams and files as persistent objects. i don't need my editor to understand the intricacies of any language, it just needs to know how to query and interpret or simply display the responses of external tools.

another important factor for me is remote editing. even though we live in the future where your production website code is automatically deployed via post commit hooks in version control software, you still find yourself poking around and tweaking the code on remote machines. most *nix based/like operating systems come with ed , vi/vim , emacs , nano , and sometimes a few other editors. ed the standard editor is too terse and nano is too simple for me. i already feel like i have carpal tunnel syndrome, so emacs is out. it also seems bloated to me, being that it's an editor as well as a client for mail, irc, news, web, etc. while vim is often available, sometimes only vi or micro-versions are available like nvi , the busybox tiny-vi clone, or the ATARI/UNIX/MS-DOS/OS2/QNX xvi implementation.

i choose vi/vim the shell based, fast, extensible, multi-language editor focused just on editing code that's available on any *nix based operating system as well as other platforms. vi is a modal editor, meaning it works differently depending on the current mode. it operates in either insert mode where typing text appends it to the document or normal mode where keystrokes are interpreted as commands used to navigate and edit the document.

your first challenge when using vim is learning the motions: h , j , k , l are used to move the cursor position up , down , left , and right . you can still use the arrow keys but vim masters will flame you saying things like: "you loose precious seconds (of your life) moving your hands from the home row to reach down for the arrows." like the motions, normal mode commands can be simple like w to jump forward a word. or more complex combinations of operators, counts and motions, for instance 2d3w deletes six words.

vi style editors promote a keyboard focused workflow that doesn't rely on multiple simultaneous key presses or the mouse. which for shell users just makes sense. vim (Vi IMproved) is an extended version of the vi editor adding new modes like visual for highlighting and replace also known as overtype mode, among others. it also adds features like syntax highlighting, file completion and comparison (vimdiff), regular expressions, folding, compressed file editing, horizontal and vertical split or tabbed windows, multi-level branched undo/repo history, mouse support (for heretics) and a lot more.

in normal mode ex commands are prefaced with a colon. depending on your settings, when you press : and start typing then press the tab key to activate the completion and suggestion engines. entering :w and pressing tab will give your suggestions like :wincmd , :write , :wq , and more. user defined functions must begin with a capital letter, and also will be available for completion. if you want to exit command input mode with out running anything press ^c (in this notation ^ is ctrl ). when entering commands in a .vimrc file the colon notation is implied. for the rest of this article i will omit them from commands in that style. to get the master list of all ex commands enter help holy-grail .

i think it's important to say: "vim is an editor, not an IDE". you can go wild extending vim with plugins and make vim into an IDE, but at it's core it's just an editor. use it how you like, but it's main goal is to edit text.

the mark of intelligence is not knowing everything, but knowing how to find the answers for yourself. my shell command history is littered with requests for man pages. i just ran vim .zhistory and %s/;man//gn , it yielded 15 results. so 1.5% of all my commands were asking for help. vim also has amazing documentation. enter the help command to view the help overview in a new buffer. the pages are just text so you navigate and search them as usual. you can search help with h pattern , if you set wildmenu tab completions will display a selectable list of suggestions.

for the most part, vi just works the way it's designed, while vim is highly configurable. many distributions include a basic config file, but user defined configurations are loaded from the .vimrc file in the home directory ~ of the user running the program. keep that in mind when running sudo vim or the more appropriate sudoedit (symlinks ftw). user configurations range from very simple vanilla ones to files hunderes of lines long brimming with comments, settings, custom key mappings, functions, plugins and the like. my vim guru taught me that when learning how to use vim you should start with a minimal configuration to learn how the editor itself works. then, when you gain a deeper understand, slowly begin to tweak it to your liking.

it is common to first set nocompatible and enable vim's extended features, though in newer versions this is set automatically upon loading a user defined .vimrc file. other common settings include custom indentation sizes with shiftwidth , tabstop , and expandtab .

you can also define your own commands to automate common tasks or quickly perform complex ones. one i use pretty often mapped to J is command J :%!python -mjson.tool this takes the contents of the current buffer and passes it to the python utility to pretty print a json file then reads back in it's results and replaces the current buffer with it's output.

you can also remap commands and completely configure it to work exactly the way you like. i try not to use these because you tend to rely on them then get frustrated if they are not set or available in your current instance. early in my vim pilgrimage i was setting nnoremap ; : this allows you to prefix your ex commands with ; as opposed to the default : , i call it lazy shifting. but this would trip me up every time i was in vi . but since vim uses both ; and : things can get crazy quick. still, some swear by things like nnoremap <C-j> <C-w>j for faster and more semantic window movements. and vim gives you the freedom to do so.

and this is just scratching the surface of what's possible. while i suggest looking at other peoples dotfiles and learning new things, i don't advise using someone else's exact .vimrc . you should understand, and want, every line in that file since it dictates exactly how your editor will function.

since vim is configured by a simple text file, when it comes to editing on remote machines you can just use the default settings but it's trivial to add your own config file. you can copy+paste the contents manually, use a tool like curl or rsync to retrieve it and write it to a file curl -sL http://git.io/.vimrc-min-curl > ~/.vimrc , or if you are like me and keep your dotfiles under version control you can just do a git clone (and a sparse checkout if you only want one program's configs) and stow or symlink the files into place.

vim is endowed with a plugin system written in it's own language vimscript . it has a long history of working in different ways, but as of this writing vundle is the current standard. it allows you to install, remove, and configure plugins from your .vimrc file. the BundleInstall command will even clone all the necessary files from github or vim.org for you. plugins can be simple or very complex. the number of plugins and their complexity will effect load time, so keep it light. i often disable plugins when editing on remote machines.

some of my favorite plugins include:

gitgutter which shows a git diff in the 'gutter' (sign column). it shows whether each line has been added, modified, and where lines have been removed. you can also stage and revert individual hunks.

in normal mode when selecting an opening brace or bracket { pressing the % key will move to it's matching closing character. the plugin matchit extends this base functionality adding support for matching by whole words, regular expressions, and other language specific items for html, latex and others.

YouCompleteMe is a fast, as-you-type, fuzzy-search code completion engine. it's results hook into the omnicomplete system to provide semantic completions for many languages with the ability to configure to your needs.

syntastic is a syntax checking plugin that runs files through user configured external linters and displays any resulting errors to the user. this can be done on demand, or automatically as files are saved.

i personally like syntax highlighting. so setting syntax on is a must for me. depending on your terminal emulator vim can display from 16 to 256 colors. there are a lot of color schemes out there, i made my own called sourcerer. you add the files to ~/.vim/colors/ or put their contents directly in your .vimrc then set them with colorscheme sourcerer .

line numbering can be another important tool when debugging. to display them use set number , or add a exclamation point as a negation set number! to disable them. another new option is set relativenumber which numbers the lines relative to the cursor rather than absolutely. you can jump to any line by entering it's number as a command. jump to line 10 with :10 .

another visual configuration is your statusbar. while the default is "satisfactory" to get the job done. most ricers configure a nicer one. you can write your own, but there is a lot to take into account. meta data about the file like name, type and encoding, vim's current mode, file modifiability, and other very complex things like placement if multiple buffer windows are visible. so most people use a plugin. powerline and airline are very popular but i prefer to use lightline to create a custom one. like others i use the background color of the filename section of the bar to represent the current mode. i also use fugitive to add git branch and status information to the bar.

a buffer is the in-memory text of a file. you can have numerous buffers open at once. use ls to list the available ones. bn buffer next and bp buffer previous allow you to switch between them. bd buffer destroy will remove the current one.

a window is a viewport of a buffer. use sp and vs to horizontally or vertically split the screen to display multiple buffers. pressing winc and a motion hjkl to move your focus. you can also use ^w and the arrow keys to move around. or press ^ww to cycle through them. you can resize windows with winc or ^w and <>-+= for left, right, up, down, and equally respectively. but since this is a single increment it's better to prefix it with a count like 30winc> or 30^w> .

a tab is a collection of windows. tabe will open a new tab. tabn tab next and tabp tab previous will let you navigate between them. as you can see the concept builds from buffers (files) to windows (groups of buffers) to tabs (groups of windows).

you can execute shell commands within vim by prefixing the command with an exclamation point. to display the contents of your home directory enter !ls -lah ~/ . when you are done press enter and you will return to your previous view. if you combine this with the read command you write the results to the current buffer. to input the current epoch time use r !date +%s .

to open a new file you can use the edit command. set wildmode=longest,list,full , wildmenu and wildignorecase vim will give you case insensitive tab completion for filenames. entering e ~/.vimr and pressing tab will almost definitely complete to e ~/.vimrc and if it can't it will show you suggestions for things like e ~/.vimrc.bak and allow you to cycle and select the approprate one.

for finding files there is a built in directory viewer called Explore . you can use Sex , Vex , or Hex to open the explorer in a vertical or horizontal split or Tex to open in a new tab. but sometimes nothing beats using your normal tools. remember the shell is always just a ^z away. when you're ready to bring vim back to the foreground use the fg command. tools like ls and find can help you find what you're looking for quicker than just scrolling through a directory tree. the ls -R flag lists files recursively for quickly viewing larger directory trees. use a pager like less for multi-screen output. the find command allows to pass a name flag for filename pattern matching and iname for case insensitive matching. to find all markdown formatted readme files find -iname 'read*me.md' .

to search the current buffer prefix your pattern with a slash / . your pattern can be a string or regex. some examples /find , /end.$ and /[0-9][0-9] . if you set hlsearch your search results will be highlighted. if you set incsearch highlighting will occur live as you type. pressing n for next and N for previous lets you navigate through matches. use nohl to clear current highlighting (you will use that one a lot).

once again, when it comes to searching for text across multiple files there are better tools available in the shell than in your editor. grep is the classic for string and regex searching. use it's -R flag to search recursively and add the i flag to remove case sensitivity. you can also use the l flag to display the filename as opposed to the matching text. to find all files containing the phrase console.log in the www directory use grep -ilR console.log /var/www .

understanding how to search with the standard utilities that will be available on any machine is important. but when it comes to local searching i have been using the silver searcher's ag command, which boasts being an order of magnitude faster than tools like grep , awk , and ack , it automatically ignores version control files, and patterns defined in .gitignore files. it's syntax is simple ag pattern location so to search for class notation in php files in a given folder ag '$this->' ~/code/php -G php . the -G flag is pattern matching for file name and/or extension. the -c flag will display the file location and count of matches, i often pipe this into word count by line to get a count of the matching files ag -c something ~/some/where | wc -l .

ag has it's own plugin adding the Ag command to vim. it's results are displayed in a quickfix window. set let g:ag_highlight=1 your search results will be highlighted in the buffers as you open them. thoughtbot gave me the idea of mapping backslash \ to ag with nnoremap \ :Ag<SPACE> . so / searches the current buffer and \ searches another location.

gg=G

in normal mode, typing gg=G will reindent the entire file. this is a special case where = is an operator. just like d or y , it will act on any text that you move over with a cursor motion command. in this case, gg positions the cursor on the first line, then =G re-indents from the current cursor position to the end of the buffer.

remove all trailing white space (replace with nothing)

:%s/\s\+$//

remove duplicate blank lines

:g/^\s*$/d

toggle the spell checker

:setlocal spell! spell?

musings from my vim guru z3bra

gopher hole gopher://z3bra.org/notes/vim use a tool like cgo or just curl the articles directly e.g. curl gopher://z3bra.org/0/notes/vim/grammar.txt



no editor or IDE will make you a better programmer. no plugins, linters, or refactoring tools will make you write better code. they're all just tools to assit your brain. learning vim's motions and modal editing style might increase your overall coding speed, or it might be too complex and just annoy you.

inb4...

something something evil mode emacs users

your toolchain is a very personal thing, and you should use what works best for you. everything in this article is my opinion, and should be taken as such. others might agree or fervently dissagree with me. and that's fine. i just wanted to get my feelings out there about, what i consider, to be the best editor for programming.