Vim Tricks – Googling with keywordprg

Most vim users are familiar with the man page lookup; K under the cursor or on visual selection. For anyone who needs a quick refrersher lets take a look at the help docs (help :K)

              *K*
K     Run a program to lookup the keyword under the
      cursor.  The name of the program is given with the
      'keywordprg' (kp) option (default is "man").  The
      keyword is formed of letters, numbers and the
      characters in 'iskeyword'.  The keyword under or
      right of the cursor is used.  The same can be done
      with the command
        :!{program} {keyword}

So we can see that the default program (keywordprg / kp) is defaulted to “man” and the keyword is determined by what is right under the cursor when it is used. The other important thing to not is the fact we could invoke man or whatever program we want using :!program_name but that’s not as fun as reconfiguring the default behavior to do what we want.

Let’s imagine that for some reason we find ourselves copying sections of text and searching google for the results. Rather than doing this over and over why not just change the keywordprg to a custom bash script to do what we want. First thing’s first lets write a simple bash script to open up the browser (I assume every OS has some way to open a browers with a given URL; This is written on an Ubuntu machine but if I were on a Mac I’d use open and test / google to make sure the syntax works as expected)

#!/bin/bash
firefox "https://www.google.com/serach?q=$1"

Give it a handy name like googleShit, move it into your PATH and and pop open that ~/.vimrc to change your default keywordprg

set keywordprg=googleShit

And now when you use K inside a new vim session you will be googling contents rather than looking up the man pages! If you find yourself repeating a task under the cursor or in visual mode pretty handy trick to have in the utility belt. Use a little imagination and you can come up with something to improve your daily workflow.

matchadd vs match

The target of this post is to clear up any confusion about the subtle differences between matchadd and match/2match/3match. This is not meant for the novice vim user but folks that have some experience with vimL. I’ll try to keep it as simple as possible for anyone interested in some of vim’s inner workings.

From :help match we get the following information:

:mat[ch] {group} /{pattern}/
        Define a pattern to highlight in the current window.  It will
        be highlighted with {group}.  Example:
            :highlight MyGroup ctermbg=green guibg=green
            :match MyGroup /TODO/
        Instead of // any character can be used to mark the start and
        end of the {pattern}.  Watch out for using special characters,
        such as '"' and '|'.

        {group} must exist at the moment this command is executed.

        The {group} highlighting still applies when a character is
        to be highlighted for 'hlsearch', as the highlighting for
        matches is given higher priority than that of 'hlsearch'.
        Syntax highlighting (see 'syntax') is also overruled by
        matches.

From the definition it should be pretty clear that match is responsible for applying defined highlights to the current window. The {group} argument is simply the name of the highlight group definition you would like to use on a given {pattern}.

To visualize a list of all available highlight groups you can use :highlight. This is really handy when programatically trying to add hightlight groups for a plugin. As you can see from the screenshot below our colorscheme has redefined the majority of the groups and :hi does a great job showing all of the possibile combinations.

Using that information we could use any one of the groups and apply a match in our current buffer. Let’s take a look at using the ErrorMsg highlight group to match the entire contents of a line.

:match ErrorMsg /\%13l/

If you have not used match before take a moment now to play around with it in your own vim session and get a feel for how vim reacts to all different types of scenarios. Which match takes priority when running consecutive matches on the same pattern?

One of the main limitations with using match is that you cannot continuously apply new matches and have the previous ones stick. Because of this it is not the most suitable option for creating any sort of full fledged highlighting plugin. If you read the help section below match you will encounter :2match and :3match which is meant to provide a way to manage 3 seperate highlight groups. Unfortunately these functions suffer from the same shortcoming we saw with the original match.

In order to compensate for the limitation on match you can create more complex patterns to include multiple line selections (/patern1\&pattern2/) or whatever else you would normally do inside of the typical vim search regex (remember a touch of magic is only a \M away with this type of searching). If you’d like to see evidence of the hacks that are possible while using check out the first iteration of vim-poi (fresh-start branch is ready for testing and this logic will all be replaced with the smarter and better matchadd pattern)

  for i in b:poi_lines{a:group}
    let c += 1
    if c == 1
      let s:build_string = s:build_string.'/\%'.string(i["line_num"]).'l\&\M'.i["content"]
    else
      let s:build_string = s:build_string.'\%'.string(i["line_num"]).'l\&\M'.i["content"]
    endif
    if c == len(b:poi_lines{a:group})
      let s:build_string = s:build_string.'/'
    else
      let s:build_string = s:build_string.'\|'
    endif
  endfor