Tuesday, July 13, 2010

Vim pr0n: Sample NERD tree plugins

I'm a lazy wank, and additionally: a bastard.

Which brings us nicely to our next point: The NERD tree API. In version 4.0 I added an API to allow people to add functionality to the NERD tree in the form of plugins.

I did this because I was getting tired of politely telling people where to ram requests for features that I either A. Would never personally use and therefore would probably do a poor job of maintaining, or B. Thought were good ideas, but was not interested in taking the plugin in that direction.

As a result, I've ended up writing a lot of small NERD tree plugins for people who have requested such features. In this raving I'll post and explain a couple of the simpler examples.

API Technical Details

You can get technical information about the API from :help NERDTreeAPI. Here you will find the documentation on the interface functions and some short usage examples. I spent ages writing that shit, so go check it out!


I see you've ignored my advice. You suck! However, in a rare show of generosity, I'll summarize it for you.

At the time of this writing the following public functions are defined in the NERD tree core:

NERDTreeAddKeyMap({options})
NERDTreeAddMenuItem({options})
NERDTreeAddSubmenu({options})
NERDTreeAddMenuSeparator([{options}])
NERDTreeRender()

The first 4 deal with extending the NERD tree key set and menu system, while the last redraws the tree buffer (useful if you have changed the tree somehow and want to reflect that in the UI).

Additionally, the following public classes are available:

NERDTreePath
NERDTreeDirNode
NERDTreeFileNode
NERDTreeBookmark

These are what the NERD tree core uses to get most of its biznass done. I wont say any more about them other than check out the source code, and check out this blog post to see the coding conventions used and for a rundown of prototype OO in Vim.

Example 1: A key mapping to open a :shell

In this example we add a key mapping on 'S' to the NERD tree that launches the :shell command in the directory of the currently selected node.


Even though I commented the living shit out of the code, it's probably worth mentioning the three points in this code where we call the NERD tree API:
  • Lines 8–11. Here we set up the NERD tree key binding so that when the user hits 'S', the NERDTreeStartShell() function is invoked. The quickhelptext value is what appears in the quick help (i.e. when you hit '?') under the "Custom mappings" section.
  • Line 18. Here we call GetSelected() (a class method of NERDTreeDirNode). This gives us a NERDTreeDirNode instance representing the directory node the cursor is sitting on.
  • Line 26. Here we call n.path.str(...) which gives us a string representation of the NERDTreePath object for the node in question, suitable for use with a :cd command. There are a number of formats and options the str() method can take. Check out the method comments in NERD_tree.vim for details.

Example 2: A menu item to open images

In this example we add a menu item to view images with eog. We could easily extend this to support some default image viewers for MF Windows™ and Mac OSX, but for simplicity, that has been left out.



Here is an image of the above code in action (after hitting 'm' on an image node):

The code is responsible for the last 2 lines of the menu. Some highlights:
  • Lines 13 and 14 add the menu separator (the line of dashes).
  • Lines 17–21 add the (v)iew image menu item.
  • Lines 14 and 20 ensure that the menu items only appear when the cursor is over an image node.
  • Line 21 connects the menu item to the NERDTreeViewImageMenuItem() function which shells out to eog to open the image.

Final ravings

We've seen a couple of basic examples of NERD tree plugins that show how to add additional key mappings and menu items. I've written many more such plugins, which have mostly been for the purposes of integrating the tree with external programs (e.g. git and grep), or with other vim plugins (eg UTL). I've also written plugins that add slightly modified versions of existing key mappings, or even override the existing mappings.

One day I may stop watching pr0n long enough to clean up and post some more complex examples. Until then, try to behave yourselves, and flick me an email if you write any dynamite NERD tree plugins!

5 comments:

  1. Thanks for this bad ass post that most people are significantly less awesome for not reading. This is unfortunately quite convicting of the douchery I committed by submitting a new feature request on your github's issues page. Vim is awesome, but I'm a little too preoccupied to learn its syntax to write my own plugin for a file marking/execution system like netrw has. However, I'm intrigued by your mention of grep/git flavored plugins. Where might one find said plugins?

    ReplyDelete
  2. I'm comming from Sublime Text and loving Vim so far. The NERDTree plugin is one of the bests, no doubt!

    But, in the options menu ("m" key), I missed some great options, present in SideBarEnhancements, like:

    - copy the name of pointed file
    - copy the fullpath of pointed file
    - copy path as script when .js
    - copy path as link when .css

    Do you know if someone already did code to this options or you can show a way to a Vim n00b do this?

    Reagards!

    ReplyDelete
  3. SCript is great, BUT HOW ABOUT
    KEYMAP TO OPEN IMAGE while I am at the cursor of filename.Example: v key
    Thank you.

    ReplyDelete
  4. This post is helpful and made me laugh. But it was a bit long, so instead of reading it properly, I have scrolled to the bottom so I can join the other commenters in expelling my feature request upon an uncaring non-existent audience, and then go back to sleep with a bottle of vodka and a misplaced feeling of satisfaction:

    I want to press a button that toggles between viewing the tree of files normally, and viewing only those files/folders which are related to currently open buffers. I don't even know what button I want to use to do that yet.

    If you are a human person currently reading this comment then it is now your duty, nay your destiny, to implement said feature as a plugin to the NERDtree plugin, even if you don't know what a Vim is. Upon completion of your mission, you may contact me by replying here, although I will probably never read it. I thank you in advance.

    ReplyDelete