Thursday, January 20, 2011

modeline on steroids

Modeline is a great tool. Yet, sometimes it is also quite limiting: it can change only limited number of options. My most often gripe - one can't change the 'makeprg' to add the target (for what in past I attempted to use the workaround).

Reading through the modeline documentation, I have found an idea how to improve the modeline to allow to execute random VIM commands, not just setting few options.

Here it goes.

function! CustomModeLine(cid)
        let i = &modelines
        let lln = line("$")
        if i > lln | let i = lln | endif
        while i>0
                let l = getline(lln-i+1)
                if l =~ a:cid
                        exec strpart(l, stridx(l, a:cid)+strlen(a:cid))
                let i = i-1

au BufReadPost * :call CustomModeLine("VIM666:")

Now, after adding that to the .vimrc, one can put something like this in the last lines (among &modelines last of them) of the source file:

// VIM666:set makeprg=make\ aaaa
// VIM666:sy keyword cType block_id_t

When opening the file in VIM, the scriptlet would find the lines and :execute them. First would add to the makeprg a default target "aaaa", second would make symbol "block_id_t" to be highlighted as a C/C++ type (typedef from my pet not-really-a-project).

Why the VIM666:?

Well. VIM creator has allowed the modelines to change only limited set of options for the reason:

No other commands than "set" are supported, for security reasons (somebody
might create a Trojan horse text file with modelines). And not all options
can be set. For some options a flag is set, so that when it's used the
|sandbox| is effective.

Thus, randomizing the "VIM666" into something more random and unpredictable is strongly advised. Sadly, :sandbox isn't configurable and thus incapable of disallowing only certain actions - at the moment it is all-or-nothing type of command in VIM.

No comments: