Saturday, March 22, 2014

Closures in VimL


I’ve talked about Anonymous Functions in VimL before, but what about closures?

What is necessary for a language to be able to say that it supports closures? What is sufficient for someone to be able to fake their way through it?

Here is the first example from Wikipedia’s Closure article:


def start(x):
    def increment(y):
        return x+y
    return increment

first_inc = start(0)
second_inc = start(8)

first_inc(3)   # returns 3
second_inc(3)  # returns 11

# The x value remains the same for new calls to the function:
first_inc(1)   # returns 1
second_inc(2)  # returns 10

Here is a faked-up alternative in VimL:


function! Start(x)
  let obj = {}
  let obj.x = a:x
  func obj.increment(y)
    return self.x + a:y
  endfunc
  return obj
endfunction

let first_inc = Start(0)
let second_inc = Start(8)

echo first_inc.increment(3)
echo second_inc.increment(3)

echo first_inc.increment(1)
echo second_inc.increment(2)

Okay, so not really what you think of as a closure, but it lets you get similar things done. Wikipedia says:
Closures are typically implemented with a special data structure that contains a pointer to the function code, plus a representation of the function’s lexical environment (i.e., the set of available variables) at the time when the closure was created.
— Wikipedia
The manual marshalling in our object-oriented implementation above probably doesn’t count, but it’s a similar idea… isn’t it?

Vim certainly has First Class Functions and with VimaholicsAnonymous, it has Anonymous Functions… Does it have closures? If not… does it matter? Can you achieve something similar using its prototypal object notation?

Sunday, March 2, 2014

Welcome to the Search Party

Enhanced searches, highlights and matches for Vim

Raimondi and I wrote a nifty little plugin and, well, we’d like to invite you to join the SearchParty.

SearchParty has these awesome features:

Visual Searches

  • * Searches for the next occurrence of the currently selected visual text.
  • # Searches for the prior occurrence of the currently selected visual text.
  • & Starts a :substitute using the currently selected visual text.
I’ve had a goodly amount of <3 on #vim for the visual & command.

Literal Search

<leader>/ prompts for a literal string to search for. This does NOT use a regular expression, so the characters you type here will be searched for literally without any magic interpretation. The <Up> key scrolls through the prior literal search history.

This one is a real crowd pleaser. People come for the highlight candy, but they stay for Literal Search.

Ranged Search


    :7,12 RSearch foo
Searches for "foo" only within the range from lines 7 through 12, both inclusive. The default range is % (the whole buffer).

Tip The normal next and previous keys (n and N) cycle within the range.

Multiple Replacements

<leader>mp prompts for a Search term and then prompts for space separated Replacement terms (use \\ to escape desired spaces). The current line is then duplicated as many times as there are replacements, minus one, and the Search term is then replaced on each line with each successive Replacement.

Perhaps an example would far better explain this:

Given the line:

   Don't credit it on the sunshine

With the cursor on that line, the command:

<leader>mp

Followed by:

Search:credit
Replace:blame

Will produce:

   Don't blame it on the sunshine

That’s no better than :s/// I know, but with the cursor still on the same line, check it:

<leader>mp

Followed by:

Search:sunshine
Replace:moonlight good\ times

Will produce:

   Don't blame it on the sunshine
   Don't blame it on the moonlight
   Don't blame it on the good times

Note Blaming it on the boogie is left as an exercise for the reader.

Search Highlighting

IIRC, this is where SearchParty all began — the ability to easily highlight the word under the cursor without silly machinations like: *#
  • <C-L> Temporarily clears search highlight.
  • <C-BSlash> Toggles search highlighting.
  • <leader>* Highlights all occurrences of word under the cursor.
  • <leader>mah Toggle automatic highlight of all occurrences of word under cursor.
  • <leader>g* Highlights all occurrences of WORD under the cursor.
Note You might think that <leader>mah is a bit verbose but toggling automatic word highlighting is not something I think you’ll need to do very often. If it does bother you, though, this mapping and all of the mappings in SearchParty are <Plug> maps, so you can customise them to your own tastes. Instructions for doing so are in the plugin docs.

Highlighting Print Command

Modern grep commands highlight the search term within the resulting lines (if you so desire). With SearchParty, Vim’s :g// command does too now:

    :g/something/P
Will show the matching lines with all occurrences of "something" on those lines highlighted.

Tip This command can also be used for an arbitrary range and it will highlight the most recent search pattern (@/) within those lines. E.g.:

    :10,20P

Set Search

Sometimes you’d like to highlight that word over there without having to go there, use <leader>* on it, and come back. <leader>ms is the answer.

Matches

This is one of my personal favourites — the ability to have up to six different strings highlighted in big, bold, bright colours all across the screen wherever they appear. The <leader>mm command prompts you for a string (kindly inserting the current word for you) to highlight. If you go past six then the first one is forgotten and replaced with your latest string (cycling like this ad infinitum). I find this useful for ensuring that a few particularly important strings don’t escape my attention throughout a document.

M.A.S.H.

Lastly, we have the Motion Activated Search Highlighter: when you press n/N/#/*/g#/g*, it highlights the match under the cursor differently to all the other matches on screen (if you have :set hlsearch activated). If you don’t use hlsearch, then it will still highlight the current match.

I really like this feature. I used to find it difficult to see where my cursor was when it was within a highlighted search term — the other similarly highlighted blobs would all compete for my attention. M.A.S.H makes this a no-brainer now.

SearchParty

So, welcome to the party. Grab yourself a buffer and get highlighting, make some matches or MASH out on the lounge. Enjoy your evening.