Let's link vi and chrome using vimscript

It has been almost an year since I started using vi (or vim). It is one of those decisions that really changed the way I perceived development environments. I feel that, in terms of possibilities vi dwarfs every other editor in the market and the vi community is really helpful and cool!

In my current work, I spend a lot of time looking at tests to understand the intent. Most of the time, I need to navigate from the test to the specification in order to understand the context. This is an annoying repititive process and as a vi user and a Software Engineer, it’s a cardinal rule that one must thrive to do less and automate repititive tasks as much as possible. Following is my solution.

This is how our typical test looks like,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class TestName1:
    REQUIREMENT = ['req1', "req2"]

    def Body():
        # Actual test


class TestName2:
    REQUIREMENT = ['req1', "req2",
    "req3", 'req4']

    def Body():
        # Actual test

The process that I would follow to search for the requirments tagged against the test is simple.

  1. Copy the requirement
  2. Search it in our requirement management system

I wrote the following vimscript to automate the process for me. (For this example, the script simply starts a google search using the requirement. At work, I use the correct URL for our requirements management system search.)

vimscript

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
let s:browser_path='/cygdrive/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe'
let s:search_url='https://www.google.com/search?q='

function! OpenRequirement()
    let cur_pos = getpos(".")

    " Find the start of the test
    let test_start_line = search('class', 'bcW')

    " Find the line with requirements and copy the requirements
    let line = search('REQUIREMENT', 'W')
    execute 'normal! f["ayi['
    call setpos(".", cur_pos)
    let requirements = @a
    let requirements = substitute(requirements, "\n", "", "g")
    let requirements = substitute(requirements, "'*", "", "g")
    let requirements = substitute(requirements, '"*', "", "g")
    let requirements = substitute(requirements, '\s*', "", "g")
    let req_list = split(requirements, ",")
    for req in req_list
        " Append requirement in the URL
        execute "silent !" . s:browser_path . " " . s:search_url . req
    endfor
    redraw!
    echo "Opening requirements:"
    for req in req_list
        echo req
    endfor
endfunction

nnoremap <leader>rrr :call OpenRequirement()<CR>

Step by step explanation of the vimscript:

  • Save current position of the cursor
  • Search backwords (b), starting from current line (c), without wrap-around (W) for the word class to find the start of the test and set the cursor on that line.
  • Search for the line with REQUIREMENT from the cursor position
  • Copy the string inside [ ]
f["ayi[ means Find square bracket copy everything in square bracket to register a
  • Retore the position of the cursor
  • Get the value in register a
  • Remove all new lines, quotation marks and spaces from the string
  • Split the string to create a list of requirements
  • Open the browser with search_url + requirement as an argument for each requirement
  • Redraw the whole vim window
  • Provide feedback to user
  • Finally, I map \rrr key stroke to call the OpenRequirement function

The working script looks like

working_vim

I’m sure that there is a better way to do the pattern substitution. However, it doesn’t work as I expected. I’ll modify the post once I improve it.

This shows how awesome vim is. It’s very easy to make your repititive tasks easy. I’ve a fully fledged plugin for work which has all sort of tricks I use to build, test, debug and with this even to search for requirements. If you are a vi user, I encourage you to experiment in vimscript to make your life easier. If you are not a vi user, you are missing out!

Happy hacking!

  • Pradeepa

comments powered by Disqus