Skip to content

Commit

Permalink
Version 0.1: Initial upload
Browse files Browse the repository at this point in the history
  • Loading branch information
mahlonsmith authored and vim-scripts committed Nov 6, 2010
0 parents commit 3d23bd2
Show file tree
Hide file tree
Showing 2 changed files with 383 additions and 0 deletions.
23 changes: 23 additions & 0 deletions README
@@ -0,0 +1,23 @@
This is a mirror of http://www.vim.org/scripts/script.php?script_id=2286

Specky is a small collection of Vim functions to help make behavioral testing streamlined and easy when working with ruby and rspec.

Here are some of the things you can do with Specky, with a single key stroke:

* Switch back and forth from code to testing spec
* Run the spec, with results going to a new, syntax highlighted buffer
* Jump quickly to spec failures and failure detail
* View rdoc of the word under the cursor
* Dynamically switch string types for the word under the cursor (double quoted, quoted, symbol)
* Create comment banners quickly

Specky also includes a couple of conveniences to make your everyday programming tasks smooooth and pleasurable, such as:

* File detection for spec files (that are named in the traditional *_spec.rb fashion.)
* Syntax highlighting for rspec and rdoc
* "Snippets" for rspec, using the Snipmate (vimscript #2540) plugin.

You can see a screencast of Specky here: http://projects.martini.nu/vim-stuff/wiki/SpeckyCast

This is my first official VIM plugin. Advice/props/criticisms all equally appreciated, but please let me know if you're using it! (mahlon@martini.nu)

360 changes: 360 additions & 0 deletions plugin/specky.vim
@@ -0,0 +1,360 @@
" vim: set noet nosta sw=4 ts=4 fdm=marker :
"
" Specky!
" Mahlon E. Smith <mahlon@martini.nu>
" $Id: specky.vim 75 2008-07-07 04:37:52Z mahlon $
"
" Some documentation {{{
"
" ------------------------------------------------------
" What's this?
" ------------------------------------------------------
"
" Specky is a small collection of functions to help make behaviorial testing
" streamlined and easy when working with ruby and rspec.
"
" ------------------------------------------------------
" Okay then, what does it do?
" ------------------------------------------------------
"
" By default? Nothing, unless you are comfortable using the menus. I decided
" the easiest way to cherry pick the functions that you'd like was to enable
" them via key bindings. By doing this Specky won't make assumptions about
" your current bindings, and won't stomp on anything you don't want it to.
"
" After you've configured your bindings, here are some of the things you can
" now do with a single key stroke:
"
" - Switch back and forth from code to testing spec
" - Run the spec, with results going to a new buffer
" - View rdoc of the word under the cursor
" - Dynamically switch string types for the word under the cursor
" (double quoted, quoted, symbol)
"
" ------------------------------------------------------
" Configuration
" ------------------------------------------------------
"
" Here are all of the available configuration options.
" Note that you must at least set the *Key binding variables to enable the
" functions. Everything else is optional. Put these into your ~/.vimrc, or
" wherever else you store this kind of stuff.
"
"
" g:speckySpecSwitcherKey
" -----------------------
" Setting this enables spec to code switching, and visa versa.
"
" Switching uses path searching instead of reliance on directory structure
" in your project. The idea here is that you'd :chdir into your project
" directory. Spec files just need to end in '_spec.rb'.
"
" aRubyClass.rb ---> aRubyClass_spec.rb
"
"
" g:speckyQuoteSwitcherKey
" ------------------------
" Setting this enables quote style switching.
"
" If you aren't in ruby mode, this just changes the word under the cursor
" back and forth from double quoting to single quoting.
"
" In ruby mode, symbols are also put into the rotation.
"
" "string" -> 'string' -> :string
"
"
" g:speckyRunRdocKey
" ------------------
" Setting this enables the display of rdoc documentation for the current
" word under the cursor.
"
"
" g:speckyRunRdocCmd
" ------------------
" If you prefer an rdoc display program other than 'ri', you can set it
" with this variable.
"
"
" g:speckyRunRdocFlags
" --------------------
" Any additional flags for the g:speckyRunRdocCmd program.
"
"
" g:speckyRunSpecKey
" ------------------
" Settings this variable allows you to run 'spec' on the current buffer.
"
"
" g:speckySpecFlags
" -----------------
" Any additional flags for the 'spec' program. Defaults to '-fp'.
"
"
" g:speckyVertSplit
" -----------------
" For both spec and rdoc commands, split the window vertically instead of
" horizontally.
"
"
"
" Here's what my config looks like:
"
" let g:speckySpecSwitcherKey = '<C-S>x'
" let g:speckyQuoteSwitcherKey = "<C-S>'"
" let g:speckyRunRdocKey = '<C-S>r'
" let g:speckyRunRdocCmd = 'fri'
" let g:speckyRunRdocFlags = '-L -f plain'
" let g:speckyRunSpecKey = '<C-S>s'
" let g:speckySpecFlags = '-fp -r loadpath.rb'
" let g:speckyVertSplit = 1


" }}}
" Hook up the functions to the user supplied key bindings. {{{
"
if exists( 'g:speckySpecSwitcherKey' )
exec 'map ' . g:speckySpecSwitcherKey . ' :call <SID>:SpecSwitcher()<CR>'
endif

if exists( 'g:speckyQuoteSwitcherKey' )
exec 'map ' . g:speckyQuoteSwitcherKey . ' :call <SID>:QuoteSwitcher()<CR>'
endif

if exists( 'g:speckyRunSpecKey' )
exec 'map ' . g:speckyRunSpecKey . ' :call <SID>:RunSpec()<CR>'
endif

if exists( 'g:speckyRunRdocKey' )
exec 'map ' . g:speckyRunRdocKey . ' :call <SID>:RunRdoc()<CR>'
endif


"}}}
" Menu configuration {{{
"
let s:menuloc = '&Plugin.&specky'
execute 'menu ' . s:menuloc . '.&Jump\ to\ code/spec :call <SID>:SpecSwitcher()<CR>'
execute 'menu ' . s:menuloc . '.Run\ &spec :call <SID>:RunSpec()<CR>'
execute 'menu ' . s:menuloc . '.&RDoc\ lookup :call <SID>:RunRdoc()<CR>'
execute 'menu ' . s:menuloc . '.Rotate\ &quote\ style :call <SID>:QuoteSwitcher()<CR>'


" }}}
" specky:SpecSwitcher() {{{
"
" When in ruby code or an rspec BDD file, try and search recursively through
" the filesystem (within the current working directory) to find the
" respectively matching file. (code to spec, spec to code.)
"
" This operates under the assumption that you've used chdir() to put vim into
" the top level directory of your project.
"
function! <SID>:SpecSwitcher()

" If we aren't in a ruby file (specs are ruby-mode too) then we probably
" don't care too much about this function.
"
if &ft != 'ruby'
call s:err( "Not currently in ruby-mode." )
return
endif

" Ensure that we can always search recursively for files to open.
"
let l:orig_path = &path
set path=**

" Get the current buffer name, and determine if it is a spec file.
"
" /tmp/something/whatever/rubycode.rb ---> rubycode.rb
" A requisite of the specfiles is that they match to the class/code file,
" this emulates the eigenclass stuff, but doesn't require the same
" directory structures.
"
" rubycode.rb ---> rubycode_spec.rb
"
let l:filename = matchstr( bufname('%'), '[0-9A-Za-z_.-]*$' )
let l:is_spec_file = match( l:filename, '_spec.rb$' ) == -1 ? 0 : 1

if l:is_spec_file
let l:other_file = substitute( l:filename, '_spec\.rb$', '\.rb', '' )
else
let l:other_file = substitute( l:filename, '\.rb$', '_spec\.rb', '' )
endif

let l:bufnum = bufnr( l:other_file )
if l:bufnum == -1
" The file isn't currently open, so let's search for it.
execute 'find ' . l:other_file
else
" We've already got an open buffer with this file, just go to it.
execute 'buffer' . l:bufnum
endif

" Restore the original path.
"
execute 'set path=' . l:orig_path
endfunction


" }}}
" specky:QuoteSwitcher() {{{
"
" Wrap the word under the cursor in quotes. If in ruby mode,
" cycle between quoting styles and symbols.
"
" variable -> "variable" -> 'variable' -> :variable
"
function! <SID>:QuoteSwitcher()
let l:type = strpart( expand("<cWORD>"), 0, 1 )
let l:word = expand("<cword>")

if l:type == '"'
" Double quote to single
"
execute ":normal viWs'" . l:word . "'"

elseif l:type == "'"
if &ft == "ruby"
" Single quote to symbol
"
execute ':normal viWs:' . l:word
else
" Single quote to double
"
execute ':normal viWs"' . l:word . '"'
end

else
" Whatever to double quote
"
execute ':normal viWs"' . l:word . '"'
endif

" Move the cursor back into the cl:word
"
call cursor( 0, getpos('.')[2] - 1 )
endfunction


" }}}
" specky:RunSpec() {{{
"
" Run this function while in a spec file to run the specs within vim.
"
function! <SID>:RunSpec()

if !executable( 'spec' )
call s:err( '"spec" was not found in your $PATH.' )
return
endif

let l:spec = bufname('%')
let l:buf = 'specky:specrun'
let l:bufnum = bufnr( l:buf )

" Squash the old buffer, if it exists.
"
if buflisted( l:buf )
execute 'bd! ' . l:buf
endif

execute ( exists('g:speckyVertSplit') ? 'vert new ' : 'new ') . l:buf
execute 'setlocal buftype=nofile bufhidden=delete noswapfile filetype=spec'

" Default flags for spec
"
if !exists( 'g:speckySpecFlags' )
let g:speckySpecFlags = '-fp'
endif

" Call spec and gather up the output
"
let l:cmd = 'spec ' . g:speckySpecFlags . ' ' . l:spec
let l:output = system( l:cmd )
call append( 0, split( l:output, "\n" ) )
call append( 0, 'Output of: ' . l:cmd )
execute 'normal gg'

" Lockdown the buffer
"
execute 'setlocal nomodifiable'
endfunction


" }}}
" specky:RunRdoc() {{{
"
" Get documentation for the word under the cursor.
"
function! <SID>:RunRdoc()

" If we aren't in a ruby file (specs are ruby-mode too) then we probably
" don't care too much about this function.
"
if ( &ft != 'ruby' && &ft != 'rdoc' )
call s:err( "Not currently in ruby-mode." )
return
endif

" Set defaults
"
if !exists( 'g:speckyRunRdocCmd' )
let g:speckyRunRdocCmd = 'ri'
endif

if !exists( 'g:speckyRunRdocFlags' )
let g:speckyRunRdocFlags = ''
endif

if !executable( g:speckyRunRdocCmd )
call s:err( '"' . g:speckyRunRdocCmd . '" was not found in your $PATH.' )
return
endif

let l:buf = 'specky:rdoc'
let l:bufname = bufname('%')

if ( match( l:bufname, l:buf ) != -1 )
" Already in the rdoc buffer. This allows us to lookup
" something like Kernel#require.
"
let l:word = expand('<cWORD>')
else
" Not in the rdoc buffer. This allows us to lookup
" something like 'each' in some_hash.each { ... }
"
let l:word = expand('<cword>')
endif

" Squash the old buffer, if it exists.
"
if buflisted( l:buf )
execute 'bd! ' . l:buf
endif

execute ( exists('g:speckyVertSplit') ? 'vert new ' : 'new ') . l:buf
execute 'setlocal buftype=nofile bufhidden=delete noswapfile filetype=rdoc'

" Call the documentation and gather up the output
"
let l:cmd = g:speckyRunRdocCmd . ' ' . g:speckyRunRdocFlags . ' ' . l:word
let l:output = system( l:cmd )
call append( 0, split( l:output, "\n" ) )
execute 'normal gg'

" Lockdown the buffer
"
execute 'setlocal nomodifiable'
endfunction


" }}}
" s:err( msg ) "{{{
" Notify of problems in a consistent fashion.
"
function! s:err( msg )
echohl WarningMsg|echomsg 'specky: ' . a:msg|echohl None
endfunction "}}}

0 comments on commit 3d23bd2

Please sign in to comment.