A simple 'switch between source and spec file' command for textmate (with auto-creation!) (edit: now with really COOL auto-creation)
Turns out BDD involves quite a bit of switching back and forth between a spec and the relevant source file. I made a command similar to the “Go to unit” test command that ships with the Rails bundle. Same idea – hit some key combo, (I like Control + Option + Shift + S) and if you’re currently looking at a source file, you’ll be taken to it’s spec file and vice versa.
Update: A much much cleaner version of this command now lives in the official RSpec tmbundle.
This command uses file naming conventions to figure out where to go – so if you’re naming things in a non-standard way chances are things won’t work.
Since I don’t much like generators (for various reasons), I also added an additional (nifty) feature: If the corresponding file cannot be found, you are asked (go go CocoaDialog!) if we should just go ahead and create it. For added niftyness, the file is created with some (fairly un-assuming) template code. How handy is that?
Bugs
This is hot-off-the-presses so I haven’t yet had much time to work out possible bugs. I’ll update it as I do.
I’m also having some trouble getting FIXED Thanks to robbat2 and Infininight (from ##textmate !) for helping me figure this out.rescan_project
(actually an osascript for switching away and back from textmate –
that’s how the real thing works too – bizzare ain’t it?) to reliably
finish running before opening the new file using mate. So sometimes the new file will show up in a new window instead of your project window. Tips for work arounds would be welcome.
Finally,
I would really have liked to insert the template text as a snippet –
however – I cannot see a good way of doing so. Any snippet output gets
sent to the document that called the command – I couldn’t find any way
of changing this behavior. Let me know if you know of a better way. FIXED Now the templates are snazzy snippets! Thanks to ciaran for showing me the applescript.
Also added: mkdir -p as required.
The Command
Copy paste to a new command in the Bundle Editor. Use input ‘none’ and output ‘show tooltip’.
(yes I should provide a tmcommand – i just don’t have any static hosting setup atm)
#!/usr/bin/env ruby
@filepath = ENV['TM_FILEPATH']
def file_to_class_name(str)
str.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
end
if @filepath =~ /^(.*?)\/(app|spec)\/(controllers|helpers|models|views)\/(.*?)([^\/\.]+)\.(\w+)$/
@app_root, @source_or_spec, @type, @sub_path, @file_base_name, @extention = $1, $2, $3, $4, $5, $6
if @source_or_spec =="app"
# Source file
@target_base = "spec"
if @file_base_name[0] == ?_
@target_file = @file_base_name[1..-1] + "_partial_spec.rb"
else
@target_file = @file_base_name+"_spec.rb"
end
@file_type = "spec file"
else
# Spec file
@target_base = "app"
@target_ext = (@type == "views") ? ".rhtml" : ".rb"
if @file_base_name =~ /_partial_spec$/
@target_ext = @file_base_name.sub(/_partial_spec/,'') + @target_ext
else
@target_file = @file_base_name.sub(/_spec/,'') + @target_ext
end
@file_type = "source file"
end
@short_path = "#{@target_base}/#{@type}/#{@sub_path}#{@target_file}"
@open_path = "#{@app_root}/#{@short_path}"
if File.exists?(@open_path)
`mate #{@open_path}`
else
@ans = `#{ ENV['TM_SUPPORT_PATH'] }/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog yesno-msgbox --no-cancel --icon document --informative-text "APP_ROOT\/#{@short_path}" --text "Create missing #{@file_type}?"`
if @ans.to_s.chomp == "1"
@extra_depth = "/.." * @sub_path.split('/').length
if @target_base == "spec" && @type != "views"
@new_file = <<-RUBY
require File.dirname(__FILE__) + '/..#{@extra_depth}/spec_helper'
describe ${1:#{file_to_class_name @file_base_name}}${2: ,"${3:in a certain state}"} do
${4:before(${5::each}) do
$6
end}
${7:it "should ${8:do something interesting}" do
$0
end}
end
RUBY
elsif @target_base == "spec" && @type == "views"
@new_file = <<-RUBY
require File.dirname(__FILE__) + '/..#{@extra_depth}/spec_helper'
describe "${1:$2#{@sub_path}#{@file_base_name}}" do
${3:before(${4::each}) do
${5:render :partial=>'#{@sub_path}#{@file_base_name}'}
end}
${6:it "should ${7:do something interesting}" do
${8:response.should have_tag("${9:selector}")}
end}
end
RUBY
elsif @target_base == "app" && @type != "views"
case @type
when "controllers"
@classdef = "class ${1:#{file_to_class_name @file_base_name}} < ApplicationController"
when "models"
@classdef = "class ${1:#{file_to_class_name @file_base_name}} < ActiveRecord::Base"
when "helpers"
@classdef = "module ${1:#{file_to_class_name @file_base_name}}"
end
@new_file = <<-RUBY
#{@classdef}
$0
end
RUBY
else
@new_file = ""
end
`mkdir -p #{File.dirname @open_path}`
`touch #{@open_path}`
`osascript &>/dev/null -e 'tell app "SystemUIServer" to activate' -e 'tell app "TextMate" to activate'`
`mate #{@open_path}`
`osascript &>/dev/null -e "tell app \\"TextMate\\" to insert \\"#{@new_file.gsub("\n","\\n").gsub('$','\\$').gsub('"','\\\\\\\\\\\\"')}\\" as snippet true"`
else
puts "Cancelled"
end
end
else
puts "Can't recognize file: #{@filepath}"
end
- read more
- 11 May 2007 17:31
- no comments
Fast hash-pair macro
Protip: you can use :<tab>
to quickly write out a bunch of hash pairs in Ruby. Rails coding
especially tends to involve writing a fair amount of hash pairs. The
default snippet makes this a lot more pleasant (what big effect such a
small snippet can have).
However, for some odd reason, the last tab-stop in the default snippet is just a comma. I can’t imagine what purpose that has – it would be much nicer to first select the comma (so you can just delete it and move on to something else) and have another tab-stop after that that, right next to another double-colon so you can make a new pair instantly. So… here it is:
:${1:key} => ${2:"${3:value}"}${4:, :$5}
- read more
- 07 May 2007 22:28
- no comments
Older posts: 1 2
Copyright © Intractable Complexity
Powered by Typo