A Small but Effective Tweak to Vim’s snipMate plugin

February 6th, 2010 No comments

Already awesome

If you haven’t tried snipMate, you have to give it a test-drive.  If you want to define a new ruby class in Vim, type “cla<tab>” and you’re presented with your choice of class templates:

Enter a number, and the code is automagically generated for you.

The tweak

By default, hitting enter at the menu cancels the snippet.  However, a user can already easily cancel using escape, and this probably won’t happen all that often anyway (I don’t think ever for me).  So I altered the code to choose the first (most common) snippet if no number is entered.  This saves me a non-home-row keystroke in almost 100% of my usage.

The code

In plugin/snipMate.vim, comment out the last line of the s:ChooseSnippet function and add two lines in it’s place:

fun s:ChooseSnippet(scope, trigger)
  [snip...]
  " Original last line (which cancels on enter) commented out
  "return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1]

  " Two lines added to choose first snippet if none are selected
  let snip_to_return = num == -1 ? 0 : num
  return s:multi_snips[a:scope][a:trigger][snip_to_return][1]
endf

Pretty simple, huh? Oh, just remember to save a copy of the changed lines somewhere.  When you update the plugin, your changes will be erased and you’ll have to re-paste them.

Categories: Software Engineering Tags:

Autospec with custom directory/file names

January 17th, 2010 No comments

Autotest is a great time-saver when doing BDD (or TDD for the less-enlightened, lol).  Autospec seemlessly integrates Rspec.  However, if you don’t use the expected “spec/*_spec.rb” structure, autotest will not find your specs – or examples, as I call them.

It is very easy to use whatever structure you want using the following steps:

Telling Autotest to use Rspec as the test runner

The first thing you want to happen is for Autotest to use Rspec as the test runner.  This usually happens automatically using autospec, which tests for the presence of the spec directory.  Since we do not want a spec directory, we must tell explicitly tell Autotest to do this.  So:

Step 1: in your project directory create a file autotest/discover.rb with the following line:

Autotest.add_discovery { "rspec" }

Teaching Autotest about our custom directory structure

In order to do this, we have two options.  If we want to use the same structure for all our projects, we can put a file in our home directory, otherwise we can add custom files to each project directory.

Step 2: create a file .autotest with the following code:


class Autotest::Rspec < Autotest remove_method :consolidate_failures def consolidate_failures(failed) filters = new_hash_of_arrays failed.each do |spec, trace| if trace =~ /\n(\.\/)?(.*example\.rb):[\d]+:/ filters[$2] << spec end end return filters end remove_method :add_options_if_present def add_options_if_present # :nodoc: File.exist?("examples/spec.opts") ? "-O examples/spec.opts " : "" end end Autotest.add_hook(:initialize) {|at| %w{.git .svn .hg .swp .DS_Store ._* tmp}.each do |exception| at.add_exception(exception) end at.clear_mappings # take out the default (test/test*rb) at.add_mapping(%r%^(examples|third_party)/.*_example.rb$%) { |filename, _| filename } at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| ["examples/#{m[1]}_example.rb"] } at.add_mapping(%r%^examples/(example_helper|shared/.*)\.rb$%) { at.files_matching %r%^(examples|third_party)/.*_example\.rb$% } #nil }

Let’s take it piece by piece:


def consolidate_failures(failed)
  filters = new_hash_of_arrays
  failed.each do |spec, trace|
    if trace =~ /\n(\.\/)?(.*example\.rb):[\d]+:/
      filters[$2] << spec
    end
  end
  return filters
end

This method tells Autotest which test files have failed by pulling the file names out of the test output. Since autospec looks for *_spec.rb files, it will not find our custom files. I use *_example.rb filenames, so you should replace that part of the regex with whatever you use.


def add_options_if_present # :nodoc:
    File.exist?("examples/spec.opts") ? "-O examples/spec.opts " : ""
  end

This method tells Rspec where to find an option file. Again, replace the details with whatever you use.

In Autotest.add_hook(:initialize):

  %w{.git .svn .hg .swp .DS_Store ._* tmp}.each do |exception|
    at.add_exception(exception)
  end

This tells Autotest to ignore certain files that are irrelevent to testing

at.clear_mappings

This tells Autotest not to use any other mappings i.e. the default test/test*rb, or Rspec’s spec/*_spec.rb

at.add_mapping(%r%^(examples|third_party)/.*_example.rb$%) { |filename, _|
  filename
}
at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
  ["examples/#{m[1]}_example.rb"]
}
at.add_mapping(%r%^examples/(example_helper|shared/.*)\.rb$%) {
  at.files_matching %r%^(examples|third_party)/.*_example\.rb$%
}

This is the meat of the customization. It tells Autospec, based on which files have changed, which tests to run. Replace my regexes with your custom matches.

The end

Once you have added both these files, running autospec from your project directory will work as it should!

Fixing Parallels Desktop Start menu and Spotlight Clash

December 13th, 2009 No comments

Parallels Desktop crystal mode is awesome.  When combined with the “Mac look” option, you don’t even know you’re in Windows…

The only issue I ran into is that when you hit CMD+Space for Spotlight, the Windows Start menu pops up and makes Spotlight disappear.  The fix was easy enough:

  1. Exit crystal mode
  2. Go to Parallels Preferences menu
  3. Under the Keyboard & Mouse tab, create two shortcuts
    1. Change the Cmd -> Win shortcut to whatever you want to open the Windows Start menu (you can see I set it to Ctrl+Space above, in the spirit of Spotlight)
    2. Create a dummy Cmd shortcut to Ctrl (basically to have it od nothing in Windows).  This will just have Parallels forward the Cmd to the Mac side and open Spotlight.
Categories: Mac Tags:

Cucumber.vim

December 12th, 2009 No comments

Awesome plug-in!  Uh, ok… but what the heck does it do?!?!  Here’s a list of the goodness:

  • syntax highlighting

  • Jump to steps
    • CTRL-] opens the step definition in the current window
    • CTRL-W ] opens it in a split window (optionally hold CTRL with the ‘]’)
    • CTRL-W opens in a split preview window
  • Autocomplete – it seems from the source that it should work, but I can’t get it going.  I posted a question on the cucumber mailing list.
    Categories: Software Engineering Tags: ,

    Customizing autospec

    December 12th, 2009 No comments

    To use autospec with a non-standard directory structure, edit the two files in the /path/to/rspec/lib/autotest:

    • discover.rb
    • rspec.rb
    Categories: Ruby Tags: ,

    Ruby, Vim, and Windows

    December 11th, 2009 No comments

    It is unbelievably easy to create a wicked setup, although I spent half a day googling to narrow it down to the exsentials:

    Downloads

    1. Ruby with the One-click installer.
    2. Vim’s self-installing Windows executable (this comes with many customizations you read about online, and ruby support, included)
    3. snipMate, a plug-in that automatically expands common Ruby constructs (e.g. you type ‘cla<tab>,’ which becomes class…end with placeholders!)
    4. superTab, another plug-in that allows you to use tab to auto-complete Ruby code
    5. wombat, a great color scheme

    Global configurations

    Add the following to /path/to/vim/_vimrc:

    note: the autocomplete menu colors, and vim’s default font are disgusting, hence the changes.

    Ruby-specific Configurations

    In /path/to/vim/vim[version]/ftplugin/ruby.vim, add:

    • the first line sets up superTabs to look in the right place for Ruby completions
    • the second line adds line numbers to vim (note: setlocal instead of set to leave non-ruby files with default configurations)
    • the third line, changes the ridiculous 8-space tabs to 2

    That’s it!  Happy coding :)

    Categories: Ruby, Software Engineering Tags: , ,

    RubyCocoa and Interface Builder

    December 4th, 2009 No comments

    There isn’t much info out there about compatibility, but here’s the rundown after a few hours of experimentation and research:

    • MacRuby: fully integrated (according to Apple’s docs), so classes, outlets and actions automatically appear in IB
    • RubyCocoa
      • Nibs: there is a utility that adds classes, actions, and outlets to IB
      • Xibs: we’re out of luck, you must add items to IB manually
    Categories: Ruby Tags: ,

    BDD in the field

    December 3rd, 2009 2 comments

    I am on fire about Ruby.  I always hated Objective-C’s weirdness (coming from C++), and read the most awesome idea recently – given the amazing power of modern computers (now pay attention, this is the good part): writing code in anything but the highest level, easiest language is… premature optimization!!!  The instant I read that statement (sorry to the author, I can’t remember where), I knew it was true.  Add that you can drop down from Ruby to lower level languages where you need extra speed, and that MacRuby and HotCoca are going to make it ridiculously easy to use Cocoa via Ruby and…

    That’s it – I’m hooked.  To get myself up to speed in Ruby and Cocoa, I’m re-writing the examples from Aaron Hillegass’s awesome book Cocoa Programming for Mac OS X.  I’ll be writing about the intricacies of BDD in Ruby using Xcode, and I’ll be posting all the code, as well as custom file and project templates for Xcode.

    Change selection in Safari via JavaScript

    November 19th, 2009 No comments

    It’s easy to get the current selection with Javascript. It’s easy to select an entire node.

    But what if you want to create a selection that spans multiple elements?

    Easy (after a few hours of bumbling around, lol):

    1. Select the text in the element where you want the block to start (I used window.find())
    2. Save the start point in a range object with setStart
    3. Repeat 1 & 2 with the end point, setting the end of the range object
    4. Select the (multi-node) range object you just created with window.getSelection().addRange()

    Get the code here.

    Enjoy!

    Categories: Mac Tags: ,

    Add missing Ruby file templates to Xcode

    November 16th, 2009 No comments

    If your file templates are missing from Xcode (I’m using 3.2.1), run the following commands in terminal, restart Xcode, and they will be there!

    sudo mkdir /Library/Application\ Support/Developer/Shared/Xcode/File\ Templates/

    sudo mkdir /Library/Application\ Support/Developer/3.0/Xcode/File\ Templates/

    svn co http://svn.macosforge.org/repository/ruby/MacRuby/
    trunk/misc/xcode-templates/File%20Templates /Library/Application\ Support/Developer/Shared/Xcode/File\ Templates/

    sudo cp -r /Library/Application\ Support/Developer/Shared/Xcode/File\ Templates/* /Library/Application\ Support/Developer/3.0/Xcode/File\ Templates/

    Categories: Ruby Tags: ,