Robert Basic's blog

Posts tagged 'vim'

Force Python version in Vim

by Robert Basic on January 12, 2017.

Vim can be compiled with Python support. Vim can be compiled with both Python 2 and Python 3 support.

At the same time.

But not really.

Vim can have both of them, but use only one at a time. If you start using one version, there is no way to switch to the other one.

The silly thing is that if you simply ask Vim which version does it support, the first one asked and supported is going to be the one loaded and used. Trying to use the other one from that point will result in an error.

if has('python')
elif has('python3')
endif

Guess which one is loaded? Python 2.

Try calling Python 3 and ka-boom!

:py3 print('hello')
E836: This Vim cannot execute :py3 after using :python

Switch the order around:

if has('python3')
elif has('python')
endif

And now? Yup, Python 3.

Why is this ridiculous? Because if you have a bunch of Vim plugins loaded, the first one that asks for a specific Python version wins! Reorder the plugins and suddenly a different Python version is loaded.

Gotta love the software development world.

Luckily, this can also be used to fix the problem itself.

How?

Force one of the Python versions from the top of your .vimrc file:

if has('python3')
endif

Now you can have a little bit of sanity and be sure what Python version is Vim going to use. Of course, doing this might break plugins written solely for Python 2, so do it at your own risk.

Happy hackin’!

Tags: python, vim, vimrc.
Categories: Development, Software.

Editing Vim macros

by Robert Basic on December 15, 2016.

Vim macros are a powerful thing — they let us record keystrokes and play them back later. These macros are recorded to named registers.

One thing I realised about them, is that they can be edited after they have been recorded. This is possible because macros “lives” in the register.

Say, for example, you record a macro of 20+ keystrokes, play it back, only to realize that there’s a single error in the steps. Re-recording the entire macro can be difficult. Instead, paste the contents of that register somewhere, edit it, and then yank it back to that same register.

For a simple example, let’s assume we want to add * around words. We record it to the register a by typing qa (the ^[ is the literal escape character):

bi&^[ea&^[

Play it back with @a and — oh no! that’s not a *, that’s a &!

Vim macro editing to the rescue:

:new # to open a new split
"ap # take the register named "a" and paste from it
:%s/&/*/g # replace all & with *
^v$"ay # jump to start of line, visual mode, jump to end of line, take the named register "a" and yank to it

If we now play back the macro again with @a, we see the *s wrapping the word on which the cursor was, just what we wanted.

Happy hackin’!

Tags: macro, registers, vim.
Categories: Development, Software.

Import custom Python modules in Vim plugins

by Robert Basic on June 16, 2016.

This took me a while to figure out so I’m writing it down for future self and anyone else who needs it.

I started writing a new Vim plugin that will use the Python interface as most of the work will be done there, mostly to keep my sanity.

Having a plugin layout such as:

.
├── lib
│   └── mypymodule
│       └── ham.py
└── plugin
    └── my-vim-plugin.vim

I want to be able to do a

from mypymodule import ham

from within the my-vim-plugin.vim file.

For that to happen the <sfile> command line special comes to rescue. It is the file name of the sourced file in Vim, that is, the file name of the Vim plugin. Using the :p and :h file name modifiers it gives us the full path to the plugin directory of our plugin.

" This will give something like
" /home/robert/projects/my-vim-plugin/plugin
let g:plugin_path = expand('<sfile>:p:h')

And here comes the kicker: the <sfile> needs to be expanded outside of our Vim function where it is used, otherwise the <sfile> points to the path of the file that called the Vim function.

In code, getting the path to the sourced file from within the Vim function would be incorrect:

" ./plugin/my-vim-plugin.vim
function! MyVimPlugin()
python << endpython

import vim

vim.command("let a:plugin_path = expand('<sfile>:p:h')
plugin_path = vim.eval("a:plugin_path")
print plugin_path

endpython
endfunction

because it would end up printing the current working directory from where the MyVimPlugin function is called.

The correct way to do is to get the path to the sourced file outside of the Vim function:

" ./plugin/my-vim-plugin.vim
let g:plugin_path = expand('<sfile>:p:h')

function! MyVimPlugin()
python << endpython

import vim

vim.command("let a:plugin_path = expand('<sfile>:p:h')
plugin_path = vim.eval("a:plugin_path")
print plugin_path

endpython
endfunction

This way the path is set at the time the plugin is sourced and not at the time when function is called.

Finally, to be able to import the mypymodule from the lib, we need to point to the lib directory and add it to the system paths. Complete example:

" ./plugin/my-vim-plugin.vim
let g:plugin_path = expand('<sfile>:p:h')

function! MyVimPlugin()
python << endpython

import os
import sys
import vim

" Get the Vim variable to Python
plugin_path = vim.eval("g:plugin_path")
" Get the absolute path to the lib directory
python_module_path = os.path.abspath('%s/../lib' % (plugin_path))
" Append it to the system paths
sys.path.append(python_module_path)

" And import!
from mypymodule import ham

endpython
endfunction

By the way, here’s the documentation for the Vim Python module.

Happy hackin’!

Tags: plugin, python, vim.
Categories: Development, Programming.

Vim Hugo helper

by Robert Basic on March 25, 2016.

I think I just wrote my first Vim plugin. OK, it’s more a bunch of Vim functions slapped together than an actual plugin, but gotta start somewhere, right?

Last week I converted this blog to a static web site and I’m using Hugo as the static website engine. Writing posts is a lot easier now, plus it’s written in Go, which I started learning a few weeks ago.

Vim Hugo helper is a plugin, collection of Vim functions that help me while writing posts. It will hopefully speed up a few recurring tasks such as drafting and undrafting posts, inserting code highlight blocks, etc. I guess I’ll be adding more to it in the future, but for now it has a total of 5 functions.

Front matter reorder

Hugo posts have a front matter which is basically meta data for the content. Hugo will create the front matter out of an archetype which is a template of sorts for the front matter. One thing I don’t like is that when a new post is created, the meta data is sorted alphabetically so the HugoHelperFrontMatterReorder function reorders it in the way that I do like.

Drafting/undrafting posts

The HugoHelperDraft and HugoHelperUndraft functions simply draft and undraft posts by setting the draft meta data in the front matter to either true or false.

Code highlight blocks

The HugoHelperHighlight(‘language’) function inserts the highlight shortcode that comes built-in with Hugo and sets the language of the highlight block.

Setting the date of the post

Finally, the HugoHelperDateIsNow function sets the date meta data of the post to the current date and time.

It’s not much, definitely has room for improvements, but I used it even when writing this very post, so I guess this helper is helpful.

Tags: hugo, plugin, vim.
Categories: Development, Programming.

Tags for PHP in Vim

by Robert Basic on March 09, 2016.

One thing I was missing for a long time in Vim is to be able to “jump to definition” in an easy and painless way.

The other thing I wanted to improve is to be able to tell easily where am I actually in the code base; to see the current class and method name of wherever the cursor was.

With a bit of googling and poking around, I finally came up with a perfect combo of 5 plugins (yep, five!) that enables me to do both, and a little bit of extra.

Tags made easy

Gutentags  is a brilliant Vim plugin that makes it so easy to have tags. Just install the plugin and boom! Tags! It will figure out things on it’s own and just generate the tags in the background. I use it daily for a fairly large code base and I never had any problems with the tags, or with Vim being unresponsive while the tags are being generated.

The only two settings I have set for it is what to exclude and where to store the tag files to not pollute the current project with them.

let g:gutentags_exclude = ['*.css', '*.html', '*.js']
let g:gutentags_cache_dir = '~/.vim/gutentags'

That’s it.

Jump to definition

Pair gutentags with CtrlP and it’s CtrlPTag method and we get jump to definition.

map <silent> <leader>jd :CtrlPTag<cr><c-\>w

Move to the method name we’re interested in, hit <leader>jd and it will jump to it’s definition. Tip: <C->w means “insert word under cursor”.

Where the hell am I?

My second requirement for displaying the current class and method name was a bit more difficult to fulfill. It takes the tagbar, tagbar-phpctags and lightline plugins as well as the phpctags tag generator to accomplish that.

Let the tagbar plugin know where the phpctags bin is:

let g:tagbar_phpctags_bin='~/.vim/phpctags'

This will make the tagbar plugin use phpctags to generate tags for the current file. To finally display the current tag in lightline, I wrote a simple tagbar component for it:

'tagbar': '%{tagbar#currenttag("[%s]", "", "f")}'

My complete lightline settings at the time of writing this can be found here.

Tags: gutentags, lightline, php, tagbar, tags, vim.
Categories: Development, Programming, Software.