Articles tagged “vim”

Ctrl-C is not Escape

I’d like to think I’m not one to be pedantic about things, but there’s one common misconception that has been making the rounds that annoys me to no end. Ctrl-c is not equivalent to Escape. There are two key differences that can be demonstrated by the following two snippets.

Ctrl-c skips any pending insert mode abbreviations.

In a vim session type the following:

:iabbrev teh the

This is a common misspelling and an oft used abbreviation. Now enter insert mode and type teh<Space>. Notice that the space completed the abbreviation and it now says the instead of teh. Now do the same but instead insert teh<Esc>. The abbreviation still happens. Do the same with teh<Ctrl-c>. The abbreviation is not completed.

Ctrl-c does not fire the InsertLeave autocmd event.

Dump the following snipped into “cursorline.vim” and launch vim with “vim -u cursorline.vim”.

augroup CursorLine     
    autocmd!
    autocmd InsertEnter * set nocursorline
    autocmd InsertLeave * set cursorline
augroup END
set cursorline

This snippet enables ‘cursorline’ while in normal mode and disables it in insert mode. If you go into insert mode and exit with Esc you’ll notice that the cursorline is re-enabled, however, if you enter insert mode and exit with Ctrl-c you’ll see that it is never re-enabled.

These two things probably don’t seem that important to you, but what about the developers of the plugins you use? If you’re using a plugin that relies on either of these two features you’re risking some functionality breaking by using Ctrl-c. If you must use something other than Escape, use Ctrl-[ instead as these are equivalent.

Published on May 13, 2012 Comments

· · ·

Idiomatic vimscript

For those who may be interested, I’ve created a repo on GitHub where I plan to dump small functions and scripts I write while helping people on irc or on Stack Overflow. In these scripts I will try my hardest to use “best practices” so they can be used as examples when writing your own scripts.

Please let me know if you notice anything you would do differently. The point of this is to serve as digestable examples of proper vimscript.

Check it out at vimscript-snippets.

Published on November 07, 2011 Comments

· · ·

CtrlP - A Game Changer

Recently I was searching for a fuzzy-finding plugin to make working with projects a little easier. I posted a quick hack that I still use every now and then, however I’ve recently discovered a rather new plugin called CtrlP.

For the uninitiated, fuzzy-finding plugins allow you to open a file by only typing enough pieces of the path to uniquely identify a file. Sometimes this is as little as one or two characters. I wasn’t really sold on this behavior until I tried using them at work where we have many files with similar names. A plugin like this makes dealing with such situations much easier to deal with than tab-completion alone.

CtrlP is written entirely in vimscript. This is a big plus for me because many of the machines at work aren’t built with +python or +ruby which some of the other fuzzy-finding plugins require. Although it’s written in vimscript it caches directory and filenames for larger directories and can be configured to always use a cache. This means it’s quite slow on first launch in larger directories but is very fast on subsequent calls.

Another big plus is the configurability CtrlP offers. There are (currently) 22 options provided to configure everything from mappings to how caching should work. You can even delegate the file indexing out to a faster external mechanism if you so choose.

Couple all of this with an active and responsive developer that provides excellent documentation and you’ve got my current favorite script.

Published on September 12, 2011 Comments

· · ·

Lowercase User Defined Commands

I’ve never liked the fact that vim doesn’t allow users to define commands that start with a lowercase letter. Every time I create one I end up having to also make a cnoreabbrev that lets me use my lowercase version. This has the ugly side effect of having text transform as you type. It also will make the cursor jump around if you’re doing more than changing the case of things. For example:

cnoreabbrev ack ack<c-\>esubstitute(getcmdline(), '^ack\>', 'Ack!', '')<enter>

This allows me to type “:ack ” and have it automatically change to “:Ack! ” as soon as I press <space>. The text changes automatically and my cursor jumps to the right two spaces instead of just one. Obviously this is a small inconvenience but it is an annoying one for me.

I have come up with a bit of a hacky workaround for this that allows more transparency and I thought I’d share in case someone out there is as stubborn as me. The following function will run a substitution on the current command line:

function! CommandLineSubstitute()
    let cl = getcmdline()
    if exists('g:command_line_substitutes')
        for [k, v] in g:command_line_substitutes
            if match(cl, k) == 0
                let cl = substitute(cl, k, v, "")
                break
            endif
        endfor
    endif
    return cl
endfunction

This function reads search/replace pairs from a global variable you set in your .vimrc. That global variable looks something like this:

" note that line continuation is only possible without 'C' in 'cpoptions'
let g:command_line_substitutes = [
    \ ['^ack ', 'Ack! '],
    \ ['^ee \(.\+\)', 'e **/\1*'],
    \ ['^h ', 'vertical help '],
\]

The last thing we need to do is a single map to call this function whenever we press <enter> on the command line:

cnoremap <enter> <c-\>eCommandLineSubstitute()<enter><enter>

While this configuration is a bit ugly, it saves me the inconvenience of having a bunch of abbreviations lying around and makes the substitution transparent to me.

I’ve only been using this for a few hours but I haven’t hit any issues thus far. If you try this out and have problems or if you know of a way to simplify it please let me know in the comments.

Published on August 03, 2011 Comments

· · ·

Poor Man’s Fuzzy Finder

I recently realized I have been using a very simple replacement for the Command-T/Fuzzy Finder type plugins for quite some time, however I had never made it convenient for myself to do so. Today I pushed a small change to my .vimrc that I think will make things a little easier for me.

nnoremap <leader>ff :e **/*<left>
nnoremap <leader>fp :<c-p><left>

The first map allows me to quickly search for a file (by partial name) anywhere under the current directory using <leader>ff. If there are multiple files found that match the glob, vim will throw E77. If that happens I can use <leader>fp to load the previous fuzzy-find on the command line with my cursor where it needs to be for me to make the search more specific.

Obviously this solution is nowhere near as complete as a plugin dedicated to this task, however it’s as complete as I need it to be.

Published on August 01, 2011 Comments

· · ·

New Project: bufstat

I recently wrote a vim plugin called bufstat that keeps a list of open buffers in your statusline. It offers a variety of options for customizing the display of the buffer list as well as a few different ways to sort the list. You can even provide your own sorting function if you feel so inclined. This is how bufstat looks in my configuration:

vim with bufstat

So far I’ve had a few users give me some positive feedback but I could always use feedback of any kind. If you’d like to try it out it’s hosted on github as vim-bufstat. Install it like you would any other plugin.

The documentation should be accurate and up to date but if there are any questions please let me know. You’ll probably want to read at least the intro and usage sections of the doc so you’ll know what to expect.

Published on May 25, 2011 Comments

· · ·

Vim Plugin Management

Anyone who as looked at my vim config knows I rely on quite a list of plugins. While vim has an excellent plugin system, it fails to have an excellent plugin management system. There are a few scripts out there that attempt to fill this void. I have not used them all, but these are the ones I’ve heard of:

Being the stubborn ass that I am, I refused to use these types of scripts for a long time. I had my own home-baked solution of putting every plugin in it’s own subfolder and manipulating the runtimepath to include these folders. This kept my vimdir rather clean and allowed me to do a few fancy things such as keeping git-hosted plugins as submodules of my dotfiles repo. Doing so allowed me to update all git plugins from their origin with one easy command.

As it turns out, this is essentially how pathogen works. An added bonus with pathogen is that it provides a few functions to generate helptags for all plugins that include a doc directory. This is something my manual method never did and was always a pain in the ass to do. As a result, I have now switched to pathogen, and I recommend anyone looking for a clean solution to vim plugins to do the same.

However, I have found a downside to pathogen for those of us stuck in the stone ages. In order to use it, you must be running vim7. This means that when running vim6 pathogen will fail, and any plugins you have that should be loaded for vim6 will not be loaded, unless you manually load them. This wasn’t a problem previously as I was already appending to rtp for every plugin and had version tests around each plugin’s settings. Below are a couple of snippets from my vimrc that show how I have configured pathogen and TagList to play well together in both vim6 and vim7.

Set up pathogen (update)

silent! call pathogen#runtime_append_all_bundles()
filetype off

Configure TagList

if v:version >= 600
    " Taglist
    if v:version < 700
        " Pathogen doesn't work with
        " vim 6 but Taglist does
        set rtp+=~/.vim/plugin-git/taglist
    endif

    " TagList options
endif

If anyone knows of a cleaner way to deal with this sort of setup on both vim6 and vim7 I’d love to hear it. I personally find this two part solution atrocious.

Published on October 12, 2010 Comments

· · ·

TIL: pedit

Often times I find myself editing a file and I suddenly realize I need to look up some data from some other file. Until today, I would normally do something along the lines of the following:

I continue editing my original file. When I find I no longer need the reference file, I need to switch to it and kill its window:

There is a better way. pedit path/to/file (or :ped if you’re lazy like me) will open a split window just as before, but cuts out the middle commands. Focus stays on the file I was working on with my cursor unmoved. The same scenario with :pedit is:

Four steps cut to two. This is why I use vim.

Published on October 10, 2010 Comments

· · ·

:help shell-window

Run this in vim. The help docs clearly state that vim will never have this feature. That sucks.

But, you say, “vim is an editor! Why should vim include a terminal emulator too? After all, vim is not emacs.” Here’s why: Because developing over ssh with vim is currently a pain in the ass. Sure, there are plenty of workarounds. Using gnu-screen to split the ssh session into multiple shells and/or multiple windows seems to be the most logical since I already use screen. Sounds good but it is horrible in practice…

Consider this situation: I have an ssh session to a server and am running screen in that session.

That’s too many keystrokes for such a small convenience. I could remedy the split problem by nesting screen sessions, but that only makes the keystroke problem worse, and that’s only counting what I’d have to do to view the things I want. I’m not sure I even know how to resize or move splits with screen without looking it up.

Now consider the same situation if vim had a shell-window.

Not only does this simplify the number of keystrokes I have to issue to jump between a full screen mail client and split vim+ipython, it also reduces the number of keybinds I have to remember. I’m already fluent in selecting, moving, and resizing vim splits.. I shouldn’t need to fumble with two sets of keybinds to accomplish the same task in screen.

The good news is I’m not the only one who wants this functionality. In fact, this is one of the most popular features that vim sponsors vote for (along with other IDE like features). There was even an unofficial patch for vim 7.0 that implemented this. Unfortunately I like to keep my software up to date and am not willing to run an old vim and lose features I use to get a feature I want.

So what can I do? There are multiple scripts out there that emulate a shell inside a vim buffer, conque and vimshell to name a few. These are OK, but not great. I applaud the effort put forth by the authors and hope they can continue to move forward with their projects, however I don’t think these solutions are the answer.

Looks like I need to man up and get my hands dirty — someone does anyway. A native vim solution is the only acceptable solution in my opinion. Until I can muster up the guts to dig into the vim source, I guess I’ll just complain to myself.

UPDATE: The author of conque sent an excellent comparison of the available shell options to the vim_use mailing list. You can find it here. I highly suggest subscribing to both vim_use and vim_dev to find out tips and tricks you wouldn’t otherwise know (if you can handle that volume of email).

Published on May 07, 2010 Comments

· · ·

Vim Tip: Navigation

Have you ever used vim to edit a large file and found yourself setting marks in a few areas to quickly jump between them? I have, and I find it highly annoying to have to remember those marks. Luckily, vim has a few tricks up it’s sleeve that make jumping around a little faster.

Firstly, see :help changelist and :help jumplist.

The changelist (obviously?) stores a list of recent changes to the file. You can even browse the list with :changes. You can jump back and forth through the changelist with g; and g,.

Similarly, the jumplist stores a list of jumps (:jumps) that you can navigate around using Ctrl+o and Ctrl+i.

The biggest difference I’ve noticed here is that the jumplist stores jumps across files whereas the changelist does not. Both of these features may be influenced by viminfo settings, but the default behavior is quite comfortable.

Have any other tips about jumping between sections of a file? If so, let me know.

Published on November 16, 2009 Comments

· · ·

Comments Revisited

A while back I posted a tip about how to quickly comment out a block of lines in vim. Since then I’ve gotten even more lazy and found an even quicker way that involves much less effort on my part. I think this originally came from a vim tip that I CBA to find now, so I’m reposting here to spread the love.

First, add a simple function to do the work:

" Toggle comments on a visual block
function! CommentLines()
    try
            execute ":s@^".g:StartComment." @\@g"
            execute ":s@ ".g:EndComment."$@@g"
    catch
            execute ":s@^@".g:StartComment." @g"
            execute ":s@$@ ".g:EndComment."@g"
    endtry
endfunction

This function comments starting at the beginning of the line. You can modify this behavior to suit your needs by changing the regular expression.

Next you’ll need to set the comment characters for the language you’re working in. My preferred way is to use autocmds to set these based on the current filetype.

" Set comment characters for common languages
autocmd FileType python,sh,bash,zsh,ruby,perl let StartComment="#" | let EndComment=""
autocmd FileType html let StartComment="<!--" | let EndComment="-->"
autocmd FileType php,cpp,javascript let StartComment="//" | let EndComment=""
autocmd FileType c,css let StartComment="/*" | let EndComment="*/"
autocmd FileType vim let StartComment="\"" | let EndComment=""
autocmd FileType ini let StartComment=";" | let EndComment=""

That’s it! Optionally (do this, really it’s stupid not to), you can add a keymap to quickly call our function.

vmap <Leader>c :call CommentLines()<CR>

Now to use this function, just select a visual block and hit your keymap to toggle comments on that block. Voila!

Note: If you need anything more complex than what this tip provides, check out the NERD Commenter. Everything I’ve read about it suggest that it’s excellent.

Published on September 22, 2009 Comments

· · ·

Git Diff and Vim

Now that I’ve seen the light and begun using git instead of subversion, I thought I’d post a follow up to my previous post about using vimdiff with subversion. That has by far been the most popular post on this site, so hopefully this will reach and help some of my fellow git users out there.

Setting up git to use vimdiff is virtually the same as with subversion. You need a vimdiff wrapper, and you need to tell git to use that wrapper as the diff program. First, the wrapper, gitvimdiff (anywhere in your path):

exec /usr/bin/vimdiff ${2} ${5}

After that, just need to edit your ~/.gitconfig file:

[diff]
  external = gitvimdiff
[pager]
  diff =

Big thanks to Jonathan Palardy for the info, I’ve just reproduced it here to help spread the word.

Published on July 13, 2009 Comments

· · ·

Vim Tip: Comments

I’ve posted a follow up to this tip that details a quicker way to comment in vim by using a simple function. Check it out here.

From the “holy crap why didn’t I find this before” category…

When editing in vim, if you find you need to comment out a block of code, try the following:

  1. Jump to the start of the line at the top or bottom of the block
  2. Press Ctrl+v to enter Visual Block mode
  3. Navigate to the end of the block. You’ll notice only the first column is highlighted (for the most part)
  4. Press I to enter Insert mode before the first non-blank character on the line
  5. Type whatever the comment syntax is for your language, eg. “//”
  6. Press Esc to get back to Normal mode.

You can follow similar steps to uncomment the same block,Ctrl+v to highlight the comment characters followed by x or any deletion command to remove the comment.

Published on February 12, 2009 Comments

· · ·

SVN Diff and Vim

Now that I’m starting to really get used to using svn for all my config files and web dev work, I’ve noticed I use the command svn diff a lot. By default this outputs a unified diff to stdout if any differences are found. While this is good information to have, it’s a really sucky way to display it — especially when we have tools like sdiff and vimdiff at our exposure.

sdiff simply takes the two input files and prints them out side by side with changes noted as characters in between the files. While this is much much better than the standard output of svn diff, vimdiff is still a better alternative because of it’s syntax highlighting.

vimdiff (or vim -d if you so choose) opens up vim in diff mode. This mode by default is two vertical split screens with one file in each screen. As usual, vim does some highlighting magic to make the output pretty and more meaningful. It also has a few commands to make your life easier when merging two versions of the same file (read up on do, dp, :diffget and :diffput).

Anyway, on to the point. To set up svn to use vimdiff as it’s default output you’ve got to do a few things. First, you need to create a wrapper around vimdiff. This is because of the way svn calls the diff utility, as far as I know there is no way around it. My vimdiff wrapper is below.

After that, you need to do one of two things:

OR

Published on December 22, 2008 Comments