Showing posts with label Vim. Show all posts
Showing posts with label Vim. Show all posts

Sunday, April 6, 2008

GVim to convert code into html

Few are aware of the fact that gvim can generate html for the code inside the buffer. The command is :TOhtml; just type it in, and the html will promptly appear in a split window.

In the browser, the generated html should look exactly as you see it in gvim. By default it generates html that should work in old browsers too, but can be told to generate CSS stylesheets or even xhtml. Type :help TOhtml for more details.

It works only in gvim, though; not in vim. It is handy for posting snippets of code on the web.

Saturday, March 1, 2008

Why Vim's modes frustrate newbies

Some people say they hate the Vim's modes. Puzzling, because I consider the modes as the killer feature of Vim, something that makes it superior to Emacs.

Why modes rock

I spend most of the time in the normal mode. In this mode, undo is just u, delete line dd and move one word forward w. In Emacs these commands would all include ctrl, shift, alt or whatever. Inserting text is not what I spend most of the time in an editor on. Most of the time I need to quickly navigate around and make small modification to an already existing text. It is false economy to have the keys on the keyboard be bound to less often used functionality all the time.

When I reach the exact place where I need to enter some text, I press i to enter insert mode, type it, and immediately get back to normal mode (I get to normal mode by pressing ctrl-[ rather than ESC).

Why modes frustrate newbies

While pairing with people new to Vim I noticed that they leave it in whatever mode. So if they were inserting, they live it in insert mode. When they come back to Vim window (after inspecting results of a test run for example), they think they are typing normal-mode commands, but are actually in the insert mode typing text. Or the opposite situation: start typing and instead of inserting text they are rapidly killing one chunk of the file after another.

Experienced Vimers follow a convention. After doing something briefly in other mode, immediately go back to the normal mode. I never live Vim in the insert mode or any other mode than normal; when I get back to the Vim window I can always assume Vim is in the normal mode.

Saturday, November 24, 2007

Extract variable in Vim

I have automated the extract variable refactoring in Vim. Well, at least for languages where you don't have to declare types. This includes Python, the language I use at work. It can also be used with Ruby and other dynamic languages, as well as with languages featuring type inference, like Nemerle and Haskell.

Select (in visual mode) a value you want to extract, and press ctrl-e. This will pop up a dialog asking for the name of the variable. A line with the assignment will be added above and all occurrences of the value will be replaced with the given name. The replacement will happen only in the lines after the assignment.

To enable it, copy the snippet to your vimrc file.

function! ExtractVariable()
    let name = inputdialog("name please")
    if name != ""
        execute "normal O" . name . " = "
        normal p
        execute (line('.')+1) . ",$s/" . escape(getreg('"'), '/\') . "/" . name . "/" 
    endif
endfunction

noremap <c-e> y:call ExtractVariable()<cr>

Friday, September 28, 2007

Swap parameters script for Vim

I have published a script for Vim. The script is written in python. The job of the script is to swap parameters. A user can swap a parameter under the cursor with the next one (gs) or with the previous one (gS). One can also use this command preceded with count. If I wanted to swap first parameter of a function with the third, I would type 2gs.

The possibility of writing scripts for vim in python not only made it very easy for me to write that script, but also allowed for easy testing. I used py.test framework and made a suite of quite literate tests. Below is a beautified set of use/test cases generated from the tests.

Left column contains the line before typing gs, the right shows the result. Position of the cursor is depicted with green background.

fun(parm1, parm2) fun(parm2, parm1)
fun(parm1(), parm2) fun(parm2, parm1())
fun(parm1(), parm2) fun(parm2, parm1())
fun(parm1(arg,arg2), parm2) fun(parm2, parm1(arg,arg2))
fun(parm1(arg,arg2), parm2) fun(parm2, parm1(arg,arg2))
fun(parm1(arg,arg2), parm2) fun(parm2, parm1(arg,arg2))
fun(parm1(arg, arg2), parm2) fun(parm2, parm1(arg, arg2))
fun(arg1, arg2, arg3) fun(arg1, arg3, arg2)
array[arg1, arg2] array[arg2, arg1]
fun(parm1[], parm2) fun(parm2, parm1[])
fun(parm1[], parm2) fun(parm2, parm1[])
fun(parm1, array[]) fun(array[], parm1)
fun(a,b) fun(b,a)
[(p1, p2), p3] [p3, (p1, p2)]

Test cases for gS -- swap backwards.

fun(parm2, parm1) fun(parm1, parm2)
fun(parm2, parm1()) fun(parm1(), parm2)
fun(parm2, parm1()) fun(parm1(), parm2)
fun(parm2, parm1(arg,arg2)) fun(parm1(arg,arg2), parm2)
fun(parm2, parm1(arg,arg2)) fun(parm1(arg,arg2), parm2)
fun(parm2, parm1(arg,arg2)) fun(parm1(arg,arg2), parm2)
fun(parm2, parm1(arg, arg2)) fun(parm1(arg, arg2), parm2)
fun(arg1, arg2, arg3) fun(arg2, arg1, arg3)
fun(arg1, arg2, arg3) fun(arg1, arg3, arg2)
array[arg2, arg1] array[arg1, arg2]
fun(parm2, parm1[]) fun(parm1[], parm2)
fun(parm2, parm1[]) fun(parm1[], parm2)
fun(array[], parm1) fun(parm1, array[])
fun(b,a) fun(a,b)

In the tests I mark the position of the cursor by enclosing a character with || symbols. Here is the first test.

  5     def test_simple_case(self):
  6         self.assertSwaps("fun(par|m|1, parm2)",
  7                             "fun(parm2, parm|1|)")