VIM is here to stay

After doing a bit more reading on the subject, it turns out that not only Sublime Text (ST) is closed, it is also very expensive and might disappear any time. I am not willing to build my workflow around tools like that. A sentiment Astrid user should appreciate.

However I do think Sublime text has some very nice features. Below I will discuss several ways to transfer these items to vim.

The Project approach

A nice feature of ST is the project approach. It would be very nice to have VIM take into account you project structure and allow easy reference to the project root. Currently I have implemented this using the local vimrc plugin. This plugin will read a .vimrc in the current directory or any of the parent directories.

You can then put a .vimrc in the root of your project to add project specific customisations. For the Simpletask Android project I am currently using the following:

" vimrc in project root
" loaded by https://github.com/MarcWeber/vim-addon-local-vimrc

set tags=tags;/
let s:script_path = expand('<sfile>:p:h') . "/" 
let g:ctrlp_custom_ignore = {
  \ 'dir':  '\vbuild$',
  \ }

nnoremap <leader>f :call FuzzyFindFromProjectRoot()<CR>

function! FuzzyFindFromProjectRoot()
    execute "CtrlP ".s:script_path
endfunction

function! ExecuteInProjectRoot(cmdline)
     execute ":cd ".s:script_path
     execute ":!start cmd /c ".a:cmdline
endfunction

function! AndroidMonitor()
    let l:filename = s:script_path."local.properties"
    execute "vimgrep /\\v^sdk\\.dir=(.*)\s*$/j ".l:filename
    for i in getqflist()
        echo "found ". i.text
        let l:cmd = split(i.text,"=")[1]
        execute ":!start cmd /c " . l:cmd . "\\tools\\monitor.bat"
        break
    endfor
endfunction

command! -nargs=1 ExecuteInProjectRoot :call ExecuteInProjectRoot(<f-args>)
command! InstallFreeRelease :call ExecuteInProjectRoot("gradlew installFreeRelease")
command! UpdateCTags :call ExecuteInProjectRoot("ctags")
command! AndroidMonitor :call AndroidMonitor()

The real intelligence is in the line:

let s:script_path = expand(':p:h') . "/"

This stores the path of the .vimrc file in the project root so it can be used from other parts of the script. A nice example of how this can be useful is by the <leader>f map which starts FuzzyFinder from the root of the project regardless of what the current directory in the project is.

This covers part of the Ctrl-P functionality from ST, however another great feature is the ability to quickly navigate to a certain spot within a file using the @ syntax. FuzzyFinder supports the brilliant FufTag which uses the built-in VIM support for tags to navigate in files. This does need some additional setup to make it work nicely though.

In the Simpletask Android project I only want FuzzyFinder to display tags in the project. To achieve this I add the line:

set tags=tags;/

to the project specific .vimrc. This means that VIM will look for the tags file with the name tags in this or any parent directory. To create this file I use Exuberant CTags in combination with the :UpdateCTags command as defined in the project .vimrc.

Without some additional configuration of CTags this will not work, because:

  • Ctags by default doesn’t scan recursively
  • Ctags by default doesn’t pick up definitions in string or layout resources.

This can be remedied by adding a .ctags file in the root of the project with the following contents:

--langdef=XML
--langmap=XML:.xml
--regex-XML=/id="([a-zA-Z0-9_]+)"/\1/d,definition/
--regex-XML=/name="([a-zA-Z0-9_]+)"/\1/d,definition/
--regex-XML=/id="@\+id\/([a-zA-Z0-9_]+)"/\1/d,definition/
--exclude=build
--recurse=yes

Besides recursively scanning, this also ignores the build directory, because I generally don’t need to switch to build artifacts and R.java clutters up the results.

tip

It makes sense to map the FufTag command to a leader map (I use <leader>t)

If you make any changes in the structure of the project, the ctags file can be updated, by calling the UpdateCTags command.

Using build variants

Coming soon

Setting up .vimrc

Coming soon.

 
comments powered by Disqus