Saturday, February 09, 2013

vimunit and gutter plugin updates.

I've been struggling my way through some plugin updates the last couple months, and I think...I think I'm about to a stopping place. For now anyway.

vimUnit

I took over the vimUnit plugin from Staale Flock a few years back and apart from a couple bugfixes I hadn't done much, until recently. I've made several updates to this plugin, the major new features/changes being:

  • Its fail fast: previously assertions for this unit testing framework were a little wonky. Most unit testing libraries out there will 'fail fast': when a failed assertion is encountered in a test case, the whole test case stops. But the old implementation of this library did nothing of the kind; this leads to overly verbose and extraneous assertions.
  • Stack traces: I did some low level vim hacking to introduce simple stack traces into failed tests. Now you have a good idea of the line number and underlying functions that cause a failed assertion.
  • Command line tool: testing vim functions inside of vim can lead to many possible IMO dirty editing environments. The command line tool ensures that when you run tests you don't mess up your current editor, and your tests always execute in a clean vim environment.
  • Shiny new website: http://dsummersl.github.com/vimunit/

Sluice

Several years back I wrote a gutter plugin that would automatically show you all matches for the current word under your cursor and any searches you may have performed. Well, I've done a pretty complete rewrite to support graphical icons as well as git modifications in the gutter. Still working out documentation and such, but definitely worth checking out. I'd love some feedback.


Friday, July 01, 2011

Conditionally applying macro recordings.

I make and use recordings in Vim all the time. I cannot imagine my daily work-a-day life without them. The most common reason for using recordings is to perform a complex modification of a semi-formatted dataset: SQL result sets, CSV, TSV, XML, HTML, etc...

As with most things in Vim when you find some new way feature, you find that you probably already had the parts laying before you, but hadn't quite had the 'manual' to put all the parts together. Recently I found a new way to do so conditionally, that I thought I'd share; its one of those methods that has probably been staring me in the face for-ever, and I just didn't see it.

So. What am I talking about? Conditional Macros. Lets break it down:

Macros

Plain and simple. Here is a simple problem that I think requires a macro. Suppose you have some lines of text like the following:

List A: 108 unique colors, 387 total colors
List B: 266 unique colors, 1343 total colors
List C: 361 unique colors, 2554 total colors
List D: 174 unique colors, 1221 total colors
List E: 301 unique colors, 2665 total colors

Suppose you wanted to compute the difference between the total colors and unique colors. So, in the case of the first line this would be 387 minus 108. You can do this once, sure. But suppose there are a couple thousand lines, and you want it all done, and done in Vim. No problem. You would record a macro like so:
  1. start your macro recording to register m (qm)
  2. go to the beginning of the line (^)
  3. move up to the first number (WW)
  4. store the first number in a register ("iyw)
  5. go to the second number (f, )
  6. store the second number in a register("oyw)
  7. compute the difference between the numbers (:let @s=@o-@i[carriage return])
  8. print out the result at the end of the line ($a == [control r]s[control c])
  9. move to the next line (j)
  10. stop recording (q)
If you were to examine register m, you would see:

^WW"iywf, "oyw:let @s=@o-@i[carriage return]$a == [control r]s[control c]j

And if you executed this macro (@m) for each line you would get something like this:

List A: 108 unique colors, 387 total colors == 279
List B: 266 unique colors, 1343 total colors == 1077
List C: 361 unique colors, 2554 total colors == 2193
List D: 174 unique colors, 1221 total colors == 1047
List E: 301 unique colors, 2665 total colors == 2364

To do several lines you would replay the macro by typing something like 5@m to do it five times, etc.

Conditional

When conditional modification pops to mind, I think of the global command (:g//). Whenever there is a match for the global command, it executes some arbitrary commds. So suppose you had text like the following:

...
...
Uninteresting line
List A: 108 unique colors, 387 total colors
Uninteresting line
Uninteresting line
List B: 266 unique colors, 1343 total colors
Uninteresting line
List C: 361 unique colors, 2554 total colors
Uninteresting line
Uninteresting line
...
...

You could just delete all the uninteresting lines like so:

:g/^Uninteresting line$/delete

Conditional Macros

Now, you could just delete everything not interesting and then run your macro on whatever is left. But a lot of times, you might find that you are interested in 'fixing' some lines but leaving the rest of the text unchanged. You can do this by combining the global command with a macro. So suppose you had:

...
...
Mildly interesting line
List A: 108 unique colors, 387 total colors
Mildly interesting line
Mildly interesting line
List B: 266 unique colors, 1343 total colors
...
...

To execute the macro you created, but only for the interesting lines you can combine the macro with the global command:

:g/^List/norm @m

Which would yield the desired result:

...
...
Mildly interesting line
List A: 108 unique colors, 387 total colors == 279
Mildly interesting line
Mildly interesting line
List B: 266 unique colors, 1343 total colors == 1077
...
...

Wednesday, March 23, 2011

New indenthl syntax plugin

I've still been getting comments on my original indenthl post, lo four or so years ago. Back when I wrote it I was an advocate of the 'set noet' (no expanded tabs - a tab means a tab!) form of consistency. Although I still prefer this method for its individual control (I like 2 char tabs, you like 4 char tabs, some fool likes 8 char tabs) I've noticed at my job people mix spaces and tabs (no we're not a python house, although we were a jython house for a while). The result: UGLY. Anyway, I'm beginning to see some of the virtues of a 'set et' world.

Thus saying, I've done some IndentHL syntax updates. It now has a couple new features (and settings!):
  • Error highlighting: if you have a line indented with a combination of tabs and spaces then this will highlight it as an error.
  • 'follow the expandtab' setting: If you turn off the expandtab setting then the syntax plugin will highlight anything that isn't TAB'd out as error prone. If you specify et then the syntax plugin will do its same 'indent level highlighting' it did before for spaces (using your shiftwidth setting), and it'll highlight in red anything thats tabbed.
  • A setting to turn off error highlighting: maybe you don't care about consistency. Well, you can turn it off.
  • I originally designed three different highlight modes (see my original post). You can now pick which one you want (as a setting).

Also, I moved this syntax project over to github. Of course, its over at vim.org as well.

Wednesday, November 10, 2010

Trying a new configuration scheme

So the other day I noticed this *amazing* plugin for looking at VIM's undo history. The guy says, if you aren't on pathogen get on it.

Round 1

pathogen is a simple Vim script that lets you put each plugin into one specific folder all on its own. Its own sandbox. I like this idea because as a user of many many plugins, debugging them can be troublesome: which files are related to the plugins, how, is it documented, etc. Its hard when every single plugin is dumped into your ~/.vim folder. Now each plugin is dumped into ~/.vim/bundle/.

I made a new .vim folder, and put pathogen in. Tried sticking in each plugin. What a pain, all this manual folder creation. Very very cumbersome. In fact, in the first round I couldn't get most of my plugins to even work. Everybody was complaining.

I gave up, went back to my old .vim folder.

Round 2

Looked around the internet a little more and found this blog entry at Tammeh Saleh which offered a solution: instead of manually porting all your plugins over, use a script (update_bundles.rb) to setup all of your github and vim.org scripts.

Genius, of course!

Tried the script out. Seemed like it might work out. Folders magically appeared in my ~/.vim/bundle folder. But. A lot of things still didn't work.

Upon investigation I realized that a good deal of the vim.org scripts I use are zipped, or tar.bz2'd or targ.gz, or vba.gz'd up. As wonderful as the ruby script was, it assumed that all vim.org scripts are zipped. Wrong.

I gave up, and stewed.

Round 3

Fine. I'll mod the script. Now I can totally blow away my ~/.vim/bundle folder and run this little ruby script and it completely regenerates regardless of zip/bzip/vimball/etc

Requires some slight manual intervention for vimball installation (it launches vim, runs the vimball install, you just have to :quit out after to get it on its way).

I think I'm happy.

Switching to pathogen also had another slight improvement. Some of my own personal duct tape type plugins got themselves checked into github for the first time. Probably should have done that awhile ago.

If you wanna try this out yourself I suggest you download my script, and read the Tammeh Saleh blog entry.

Tuesday, March 02, 2010

multiline matching

Similar to my previous post on adjacent nontrivial searches, I've recently had to do something similar except that I need to find things that are the same on adjacent lines.

For instance given the following:

1003065,PARKBT,99.00,0.00,0.00,,2009,1089.00
1003133,PARKBT,210.00,0.00,0.00,,2009,1470.00
1003234,PARKBT,180.00,0.00,0.00,,2009,1980.00
1003316,PARKAT,45.00,0.00,0.00,,2009,45.00
1003316,PARKBT,230.00,0.00,0.00,,2009,2705.00
1003360,PARKBT,210.00,0.00,0.00,,2009,1260.00
1003377,PARKBT,110.00,0.00,0.00,,2009,1210.00
1003404,PARKBT,180.00,0.00,0.00,,2009,1980.00


In this case I'm interested in finding matches where the number at the beginning is repeated in a couple more than once (the lines starting with 1003316). This is the resulting search: /^\v(\d+),.*$\_.^\1,

The trick here is to use the \_. to match the end of line, and then match zero width beginning of line.

Wednesday, January 27, 2010

Still no column level folding in VIM.

I used to think that VIM was right there on the 'cutting edge' of new editing concepts. I remember encountering Origami (the original project is dead I guess, can't find a good link) while I was in college. It have this novel idea of 'folding' lines so that you could hide large sections of a file. I thought, interesting. Not long after that feature was incorporated into VIM (no I'm not going to look up version numbers and embarrass/age myself!). A few years ago I had heard that someone had written a patch for VIM that enabled horizontal folding to offer similar advantages to the line level folding: simplification. I didn't think much of it, but stashed it away...confidant that *someday* it'd be part of VIM (if it were useful).

Well. Its been several years, and I just realized that Intelli has incorporated it into their own editor, and it is useful. Screenshot:


See the little <->? That's folding along the horizontal line. If you have the 'vi' plugin in Intellij it even acts like a fold: type 'zo' to open it. You get a lot longer string (sorry I'd type it out but blogger's editor doesn't like <> in that particular combination). I couldn't say I saw a use for horizontal folding before...but I do now! So much more readable with folding. I want it in VIM!

Note: I've been using the AnsiEsc.vim plugin for a little while, and I didn't even realize that it'd been specifically written to take advantage of Vince Negri's patch. Shame on me. One more reason to compile MacVim.


Wednesday, January 20, 2010

Macro Search take three (err, update)

Okay! So I've been hard at work on some new features. Make sure you've seen the first screencast - then get a video overview of the new 'under the cursor autosearch' feature by watching the changelog screencast I made:


But. I also left some features out. A mostly complete list of the new features:
  • A new 'under the cursor autosearch' feature. In short: you are shown all 'iskeyword' words in the file that match whatever 'word' is currently under your cursor.
  • Limited searches: the search and under cursor search plugins are limited to 100 matches so as not to kill you on larger files (searching for redundant things that match everywhere).
  • Colors! In GUI mode the intensity of the // and \\ colors will go UP when there are lots of matches in that region of the file. Dull == 1 match, brighter == more matches.
  • console coloring: the console doesn't support this level of granularity so I've given it a basic 8 color black/white/brown so that you get all the same basic functionality (minus the intensity telling you the # of matches).
  • hopefully more stable? Hopefully more complainy if you don't have +float or +signs support? One hopes :)
A screenshot of the plugin in console vim (uhh, this screenshot doesn't make *any* sense unles you've watched the screencasts so...get to it!):


If you're interested try it out - just drop it in git repository. I'd be interested in some feedback before I tack a version on it and stick it on vim.org's plugin site.