Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Look at http://vimcasts.org/blog/2010/12/a-text-object-for-ruby-blocks/

… (and http://amaras-tech.co.uk/people/morgan/article/84 for a quick howto on setup). Thanks for the link Orlando.
  • Loading branch information...
commit f2b2c6f99257ad9ba90b3996f306faa0a9f95340 1 parent 5ef6ba2
@kusor authored
View
587 autoload/textobj/user.vim
@@ -0,0 +1,587 @@
+" textobj-user - Support for user-defined text objects
+" Version: 0.3.9
+" Copyright (C) 2007-2010 kana <http://whileimautomaton.net/>
+" License: So-called MIT/X license {{{
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be included
+" in all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+" }}}
+" Interfaces "{{{1
+" simple "{{{2
+
+function! textobj#user#move(pattern, flags, previous_mode)
+ call s:prepare_movement(a:previous_mode)
+
+ let i = v:count1
+ while 0 < i
+ let result = searchpos(a:pattern, a:flags.'W')
+ let i = i - 1
+ endwhile
+ return result
+endfunction
+
+
+" FIXME: growing the current selection like iw/aw, is/as, and others.
+" FIXME: countable.
+" FIXME: In a case of a:pattern matches with one character.
+function! textobj#user#select(pattern, flags, previous_mode)
+ call s:prepare_selection(a:previous_mode)
+ let ORIG_POS = s:gpos_to_spos(getpos('.'))
+
+ let posf_tail = searchpos(a:pattern, 'ceW')
+ let posf_head = searchpos(a:pattern, 'bW')
+ call cursor(ORIG_POS)
+ let posb_head = searchpos(a:pattern, 'bcW')
+ let posb_tail = searchpos(a:pattern, 'eW')
+
+ " search() family with 'c' flag may not be matched to a pattern which
+ " matches to multiple lines. To choose appropriate range, we have to check
+ " another range whether it contains the cursor or not.
+ if (a:flags =~# 'b'
+ \ || (s:range_containsp(posb_head, posb_tail, ORIG_POS)
+ \ && s:range_validp(posb_head, posb_tail)))
+ let [pos_head, pos_tail] = [posb_head, posb_tail]
+ else
+ let [pos_head, pos_tail] = [posf_head, posf_tail]
+ endif
+
+ if s:range_validp(pos_head, pos_tail)
+ execute 'normal!' s:wise('v')
+ call cursor(pos_head)
+ normal! o
+ call cursor(pos_tail)
+ return [pos_head, pos_tail]
+ else
+ return s:cancel_selection(a:previous_mode, ORIG_POS)
+ endif
+endfunction
+
+
+
+
+" pair "{{{2
+
+" FIXME: NIY, but is this necessary?
+" function! textobj#user#move_pair(pattern1, pattern2, flags)
+" endfunction
+
+
+" BUGS: With o_CTRL-V, this may not work properly.
+function! textobj#user#select_pair(pattern1, pattern2, flags, previous_mode)
+ call s:prepare_selection(a:previous_mode)
+ let ORIG_POS = s:gpos_to_spos(getpos('.'))
+
+ " adjust the cursor to the head of a:pattern2 if it's already in the range.
+ let pos2c_tail = searchpos(a:pattern2, 'ceW')
+ let pos2c_head = searchpos(a:pattern2, 'bcW')
+ if !s:range_validp(pos2c_head, pos2c_tail)
+ return s:cancel_selection(a:previous_mode, ORIG_POS)
+ endif
+ if s:range_containsp(pos2c_head, pos2c_tail, ORIG_POS)
+ let more_flags = 'c'
+ else
+ let more_flags = ''
+ call cursor(ORIG_POS)
+ endif
+
+ " get the positions of a:pattern1 and a:pattern2.
+ let pos2p_head = searchpairpos(a:pattern1, '', a:pattern2, 'W'.more_flags)
+ let pos2p_tail = searchpos(a:pattern2, 'ceW')
+ if !s:range_validp(pos2p_head, pos2p_tail)
+ return s:cancel_selection(a:previous_mode, ORIG_POS)
+ endif
+ call cursor(pos2p_head)
+ let pos1p_head = searchpairpos(a:pattern1, '', a:pattern2, 'bW')
+ let pos1p_tail = searchpos(a:pattern1, 'ceW')
+ if !s:range_validp(pos1p_head, pos1p_tail)
+ return s:cancel_selection(a:previous_mode, ORIG_POS)
+ endif
+
+ " select the range, then adjust if necessary.
+ if a:flags =~# 'i'
+ if s:range_no_text_without_edgesp(pos1p_tail, pos2p_head)
+ return s:cancel_selection(a:previous_mode, ORIG_POS)
+ endif
+ call s:range_select(pos1p_tail, pos2p_head)
+
+ " adjust the range.
+ let whichwrap_orig = &whichwrap
+ let &whichwrap = '<,>'
+ execute "normal! \<Left>o\<Right>"
+ let &whichwrap = whichwrap_orig
+ else
+ call s:range_select(pos1p_head, pos2p_tail)
+ endif
+ return
+endfunction
+
+
+
+
+function! textobj#user#define(pat0, pat1, pat2, guideline) "{{{2
+ let pat0 = s:rhs_escape(a:pat0)
+ let pat1 = s:rhs_escape(a:pat1)
+ let pat2 = s:rhs_escape(a:pat2)
+ for function_name in keys(a:guideline)
+ let _lhss = a:guideline[function_name]
+ if type(_lhss) == type('')
+ let lhss = [_lhss]
+ else
+ let lhss = _lhss
+ endif
+
+ for lhs in lhss
+ if function_name == 'move-to-next'
+ execute 'nnoremap' s:mapargs_single_move(lhs, pat0, '', 'n')
+ execute 'vnoremap' s:mapargs_single_move(lhs, pat0, '', 'v')
+ execute 'onoremap' s:mapargs_single_move(lhs, pat0, '', 'o')
+ elseif function_name == 'move-to-next-end'
+ execute 'nnoremap' s:mapargs_single_move(lhs, pat0, 'e', 'n')
+ execute 'vnoremap' s:mapargs_single_move(lhs, pat0, 'e', 'v')
+ execute 'onoremap' s:mapargs_single_move(lhs, pat0, 'e', 'o')
+ elseif function_name == 'move-to-prev'
+ execute 'nnoremap' s:mapargs_single_move(lhs, pat0, 'b', 'n')
+ execute 'vnoremap' s:mapargs_single_move(lhs, pat0, 'b', 'v')
+ execute 'onoremap' s:mapargs_single_move(lhs, pat0, 'b', 'o')
+ elseif function_name == 'move-to-prev-end'
+ execute 'nnoremap' s:mapargs_single_move(lhs, pat0, 'be', 'n')
+ execute 'vnoremap' s:mapargs_single_move(lhs, pat0, 'be', 'v')
+ execute 'onoremap' s:mapargs_single_move(lhs, pat0, 'be', 'o')
+ elseif function_name == 'select-next' || function_name == 'select'
+ execute 'vnoremap' s:mapargs_single_select(lhs, pat0, '', 'v')
+ execute 'onoremap' s:mapargs_single_select(lhs, pat0, '', 'o')
+ elseif function_name == 'select-prev'
+ execute 'vnoremap' s:mapargs_single_select(lhs, pat0, 'b', 'v')
+ execute 'onoremap' s:mapargs_single_select(lhs, pat0, 'b', 'o')
+ elseif function_name == 'select-pair-all'
+ execute 'vnoremap' s:mapargs_pair_select(lhs, pat1, pat2, 'a', 'v')
+ execute 'onoremap' s:mapargs_pair_select(lhs, pat1, pat2, 'a', 'o')
+ elseif function_name == 'select-pair-inner'
+ execute 'vnoremap' s:mapargs_pair_select(lhs, pat1, pat2, 'i', 'v')
+ execute 'onoremap' s:mapargs_pair_select(lhs, pat1, pat2, 'i', 'o')
+ else
+ throw 'Unknown function name: ' . string(function_name)
+ endif
+ endfor
+ endfor
+endfunction
+
+
+
+
+function! textobj#user#plugin(plugin_name, obj_specs) "{{{2
+ if a:plugin_name =~# '\L'
+ throw '{plugin} contains non-lowercase alphabet: ' . string(a:plugin_name)
+ endif
+ let plugin = a:plugin_name
+ let Plugin = substitute(a:plugin_name, '^\(\l\)', '\u\1', 0)
+
+ let g:__textobj_{plugin} = s:plugin.new(a:plugin_name, a:obj_specs)
+
+ execute
+ \ 'command! -bang -bar -nargs=0 Textobj'.Plugin.'DefaultKeyMappings'
+ \ 'call g:__textobj_'.plugin.'.define_default_key_mappings("<bang>" == "!")'
+ call g:__textobj_{plugin}.define_interface_key_mappings()
+ if (!has_key(a:obj_specs, '*no-default-key-mappings*'))
+ \ && (!exists('g:textobj_'.plugin.'_no_default_key_mappings'))
+ execute 'Textobj'.Plugin.'DefaultKeyMappings'
+ endif
+
+ return g:__textobj_{plugin}
+endfunction
+
+
+
+
+
+
+
+
+" Misc. "{{{1
+" pos "{{{2
+
+" Terms:
+" gpos [bufnum, lnum, col, off] - a value returned by getpos()
+" spos [lnum, col] - a value returned by searchpos()
+" pos same as spos
+function! s:gpos_to_spos(gpos)
+ return a:gpos[1:2]
+endfunction
+
+
+function! s:pos_headp(pos)
+ return a:pos[1] <= 1
+endfunction
+
+function! s:pos_lastp(pos)
+ return a:pos[1] == len(getline(a:pos[0]))
+endfunction
+
+
+function! s:pos_le(pos1, pos2) " less than or equal
+ return ((a:pos1[0] < a:pos2[0])
+ \ || (a:pos1[0] == a:pos2[0] && a:pos1[1] <= a:pos2[1]))
+endfunction
+
+
+
+
+" range "{{{2
+
+function! s:range_containsp(range_head, range_tail, target_pos)
+ return (s:pos_le(a:range_head, a:target_pos)
+ \ && s:pos_le(a:target_pos, a:range_tail))
+endfunction
+
+
+function! s:range_no_text_without_edgesp(range_head, range_tail)
+ let [hl, hc] = a:range_head
+ let [tl, tc] = a:range_tail
+ return ((hl == tl && hc - tc == -1)
+ \ || (hl - tl == -1
+ \ && (s:pos_lastp(a:range_head) && s:pos_headp(a:range_tail))))
+endfunction
+
+
+function! s:range_validp(range_head, range_tail)
+ let NULL_POS = [0, 0]
+ return (a:range_head != NULL_POS) && (a:range_tail != NULL_POS)
+endfunction
+
+
+function! s:range_select(range_head, range_tail)
+ execute 'normal!' s:wise('v')
+ call cursor(a:range_head)
+ normal! o
+ call cursor(a:range_tail)
+endfunction
+
+
+
+
+" for textobj#user#define() "{{{2
+
+function! s:rhs_escape(pattern)
+ let r = a:pattern
+ let r = substitute(r, '<', '<LT>', 'g')
+ let r = substitute(r, '|', '<Bar>', 'g')
+ return r
+endfunction
+
+
+function! s:mapargs_single_move(lhs, pattern, flags, previous_mode)
+ return printf('<silent> %s :<C-u>call textobj#user#move(%s, %s, %s)<CR>',
+ \ a:lhs,
+ \ string(a:pattern), string(a:flags), string(a:previous_mode))
+endfunction
+
+function! s:mapargs_single_select(lhs, pattern, flags, previous_mode)
+ return printf('<silent> %s :<C-u>call textobj#user#select(%s, %s, %s)<CR>',
+ \ a:lhs,
+ \ string(a:pattern), string(a:flags), string(a:previous_mode))
+endfunction
+
+function! s:mapargs_pair_select(lhs, pattern1, pattern2, flags, previous_mode)
+ return printf(
+ \ '<silent> %s :<C-u>call textobj#user#select_pair(%s,%s,%s,%s)<CR>',
+ \ a:lhs,
+ \ string(a:pattern1), string(a:pattern2),
+ \ string(a:flags), string(a:previous_mode)
+ \ )
+endfunction
+
+
+
+
+" for textobj#user#plugin() "{{{2
+" basics "{{{3
+let s:plugin = {}
+
+function s:plugin.new(plugin_name, obj_specs)
+ let _ = extend({'name': a:plugin_name, 'obj_specs': a:obj_specs},
+ \ s:plugin, 'keep')
+ call _.normalize()
+ return _
+endfunction
+
+function s:plugin.normalize()
+ for [obj_name, specs] in items(self.obj_specs)
+ for [spec_name, spec_info] in items(specs)
+ if spec_name =~# '^\(move-[npNP]\|select\(\|-[ai]\)\)$'
+ if type(spec_info) == type('')
+ let specs[spec_name] = [spec_info]
+ endif
+ endif
+
+ if spec_name =~# '^\*.*-function\*$'
+ if spec_info =~# '^s:'
+ if has_key(specs, '*sfile*')
+ let specs[spec_name] = substitute(spec_info,
+ \ '^s:',
+ \ s:snr_prefix(specs['*sfile*']),
+ \ '')
+ else
+ echoerr 'Script-local function is given without *sfile*:'
+ \ string(spec_name) '/' string(spec_info)
+ endif
+ else
+ " Nothing to do.
+ endif
+ endif
+
+ unlet spec_info " to avoid E706.
+ endfor
+ endfor
+endfunction
+
+
+function! s:plugin.define_default_key_mappings(banged_p) "{{{3
+ for [obj_name, specs] in items(self.obj_specs)
+ for [spec_name, spec_info] in items(specs)
+ let rhs = self.interface_mapping_name(obj_name, spec_name)
+ if spec_name =~# '^\*.*\*$'
+ " ignore
+ elseif spec_name =~# '^move-[npNP]$'
+ for lhs in spec_info
+ call s:map(a:banged_p, lhs, rhs)
+ endfor
+ elseif spec_name =~# '^select\(\|-[ai]\)$'
+ for lhs in spec_info
+ call s:objmap(a:banged_p, lhs, rhs)
+ endfor
+ else
+ throw 'Unknown command: ' . string(spec_name)
+ endif
+
+ unlet spec_info " to avoid E706.
+ endfor
+ endfor
+endfunction
+
+
+function! s:plugin.define_interface_key_mappings() "{{{3
+ let RHS_PATTERN = ':<C-u>call g:__textobj_' . self.name . '.%s'
+ \ . '("%s", "%s", "<mode>")<Return>'
+ let RHS_FUNCTION = ':<C-u>call <SID>select_function_wrapper('
+ \ . 'g:__textobj_' . self.name . '.obj_specs["%s"]["%s"],'
+ \ . '"<mode>"'
+ \ . ')<Return>'
+
+ for [obj_name, specs] in items(self.obj_specs)
+ for spec_name in filter(keys(specs), 'v:val[0] != "*" && v:val[-1] != "*"')
+ " lhs
+ let lhs = '<silent> ' . self.interface_mapping_name(obj_name, spec_name)
+
+ " rhs
+ let _ = '*' . spec_name . '-function*'
+ if has_key(specs, _)
+ let rhs = printf(RHS_FUNCTION, obj_name, _)
+ elseif has_key(specs, '*pattern*')
+ if spec_name =~# '^move-[npNP]$'
+ let flags = ''
+ let flags .= (spec_name =~ '[pP]$' ? 'b' : '')
+ let flags .= (spec_name =~ '[NP]$' ? 'e' : '')
+ let impl_fname = 'move'
+ elseif spec_name ==# 'select'
+ let flags = ''
+ let impl_fname = 'select'
+ elseif spec_name =~# '^select-[ai]$'
+ let flags = ''
+ let flags .= (spec_name =~ 'a$' ? 'a' : '')
+ let flags .= (spec_name =~ 'i$' ? 'i' : '')
+ let impl_fname = 'select_pair'
+ else
+ echoerr 'Unknown spec:' string(spec_name)
+ continue
+ endif
+ let rhs = printf(RHS_PATTERN, impl_fname, obj_name, flags)
+ else
+ " skip to allow to define user's own {rhs} of the interface mapping.
+ continue
+ endif
+
+ " map
+ if spec_name =~# '^move'
+ let MapFunction = function('s:noremap')
+ else " spec_name =~# '^select'
+ let MapFunction = function('s:objnoremap')
+ endif
+ call MapFunction(1, lhs, rhs)
+ endfor
+ endfor
+endfunction
+
+
+function! s:plugin.interface_mapping_name(obj_name, spec_name) "{{{3
+ let _ = printf('<Plug>(textobj-%s-%s-%s)',
+ \ self.name,
+ \ a:obj_name,
+ \ substitute(a:spec_name, '^\(move\|select\)', '', ''))
+ let _ = substitute(_, '-\+', '-', 'g')
+ let _ = substitute(_, '-\ze)$', '', '')
+ return _
+endfunction
+
+
+" *pattern* implementations "{{{3
+function! s:plugin.move(obj_name, flags, previous_mode)
+ let specs = self.obj_specs[a:obj_name]
+ call textobj#user#move(specs['*pattern*'], a:flags, a:previous_mode)
+endfunction
+
+function! s:plugin.select(obj_name, flags, previous_mode)
+ let specs = self.obj_specs[a:obj_name]
+ call textobj#user#select(specs['*pattern*'], a:flags, a:previous_mode)
+endfunction
+
+function! s:plugin.select_pair(obj_name, flags, previous_mode)
+ let specs = self.obj_specs[a:obj_name]
+ call textobj#user#select_pair(specs['*pattern*'][0], specs['*pattern*'][1],
+ \ a:flags, a:previous_mode)
+endfunction
+
+
+" map wrappers "{{{3
+function! s:_map(map_commands, forced_p, lhs, rhs)
+ for _ in a:map_commands
+ execute 'silent!' (_) (a:forced_p ? '' : '<unique>') a:lhs
+ \ substitute(a:rhs, '<mode>', _[0], 'g')
+ endfor
+endfunction
+
+
+function! s:noremap(forced_p, lhs, rhs)
+ let v = s:proper_visual_mode(a:lhs)
+ call s:_map(['nnoremap', v.'noremap', 'onoremap'], a:forced_p, a:lhs, a:rhs)
+endfunction
+
+function! s:objnoremap(forced_p, lhs, rhs)
+ let v = s:proper_visual_mode(a:lhs)
+ call s:_map([v.'noremap', 'onoremap'], a:forced_p, a:lhs, a:rhs)
+endfunction
+
+
+function! s:map(forced_p, lhs, rhs)
+ let v = s:proper_visual_mode(a:lhs)
+ call s:_map(['nmap', v.'map', 'omap'], a:forced_p, a:lhs, a:rhs)
+endfunction
+
+function! s:objmap(forced_p, lhs, rhs)
+ let v = s:proper_visual_mode(a:lhs)
+ call s:_map([v.'map', 'omap'], a:forced_p, a:lhs, a:rhs)
+endfunction
+
+
+" *select-function* wrapper "{{{3
+function! s:select_function_wrapper(function_name, previous_mode)
+ let ORIG_POS = s:gpos_to_spos(getpos('.'))
+ call s:prepare_selection(a:previous_mode)
+
+ let _ = function(a:function_name)()
+ if _ is 0
+ call s:cancel_selection(a:previous_mode, ORIG_POS)
+ else
+ let [motion_type, start_position, end_position] = _
+ execute 'normal!' s:wise(motion_type)
+ call setpos('.', start_position)
+ normal! o
+ call setpos('.', end_position)
+ endif
+endfunction
+
+
+
+
+" Etc "{{{2
+
+function! s:prepare_movement(previous_mode)
+ if a:previous_mode ==# 'v'
+ normal! gv
+ endif
+endfunction
+
+function! s:prepare_selection(previous_mode)
+ if a:previous_mode ==# 'v'
+ execute 'normal!' "gv\<Esc>"
+ endif
+endfunction
+
+
+function! s:cancel_selection(previous_mode, orig_pos)
+ if a:previous_mode ==# 'v'
+ normal! gv
+ else " if a:previous_mode ==# 'o'
+ call cursor(a:orig_pos)
+ endif
+endfunction
+
+
+function! s:snr_prefix(sfile)
+ redir => result
+ silent scriptnames
+ redir END
+
+ for line in split(result, '\n')
+ let _ = matchlist(line, '^\s*\(\d\+\):\s*\(.*\)$')
+ if a:sfile ==# _[2]
+ return printf("\<SNR>%d_", _[1])
+ endif
+ endfor
+
+ return 's:'
+endfunction
+
+
+function! s:wise(default)
+ return (exists('v:motion_force') && v:motion_force != ''
+ \ ? v:motion_force
+ \ : a:default)
+endfunction
+
+
+function! s:proper_visual_mode(lhs)
+ " Return the mode prefix of proper "visual" mode for a:lhs key sequence.
+ " a:lhs should not be defined in Select mode if a:lhs starts with
+ " a printable character. Otherwise a:lhs may be defined in Select mode.
+
+ " a:lhs may be prefixed with :map-arguments such as <buffer>.
+ " It's necessary to remove them to determine the first character in a:lhs.
+ let s1 = substitute(
+ \ a:lhs,
+ \ '\v^(\<(buffer|silent|special|script|expr|unique)\>\s*)*',
+ \ '',
+ \ ''
+ \ )
+ " All characters in a:lhs are printable characters, so it's necessary to
+ " convert <>-escaped notation into corresponding characters.
+ let s2 = substitute(s1,
+ \ '^\(<[^<>]\+>\)',
+ \ '\=eval("\"\\" . submatch(1) . "\"")',
+ \ '')
+ return s2 =~# '^\p' ? 'x' : 'v'
+endfunction
+
+
+
+
+
+
+
+
+" __END__ "{{{1
+" vim: foldmethod=marker
View
41 doc/tags
@@ -29,6 +29,9 @@
:NERDTreeFromBookmark NERD_tree.txt /*:NERDTreeFromBookmark*
:NERDTreeMirror NERD_tree.txt /*:NERDTreeMirror*
:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle*
+:TextobjRubyblockDefaultKeyMappings textobj-rubyblock.txt /*:TextobjRubyblockDefaultKeyMappings*
+<Plug>(textobj-rubyblock-a) textobj-rubyblock.txt /*<Plug>(textobj-rubyblock-a)*
+<Plug>(textobj-rubyblock-i) textobj-rubyblock.txt /*<Plug>(textobj-rubyblock-i)*
NERDTree NERD_tree.txt /*NERDTree*
NERDTree-? NERD_tree.txt /*NERDTree-?*
NERDTree-A NERD_tree.txt /*NERDTree-A*
@@ -128,8 +131,46 @@ fugitive-revision fugitive.txt /*fugitive-revision*
fugitive-statusline fugitive.txt /*fugitive-statusline*
fugitive-~ fugitive.txt /*fugitive-~*
fugitive.txt fugitive.txt /*fugitive.txt*
+g:textobj_rubyblock_no_default_key_mappings textobj-rubyblock.txt /*g:textobj_rubyblock_no_default_key_mappings*
textile-changelog textile.txt /*textile-changelog*
textile-commands textile.txt /*textile-commands*
textile-credits textile.txt /*textile-credits*
textile-requirements textile.txt /*textile-requirements*
textile.txt textile.txt /*textile.txt*
+textobj#user#define() textobj-user.txt /*textobj#user#define()*
+textobj#user#move() textobj-user.txt /*textobj#user#move()*
+textobj#user#plugin() textobj-user.txt /*textobj#user#plugin()*
+textobj#user#select() textobj-user.txt /*textobj#user#select()*
+textobj#user#select_pair() textobj-user.txt /*textobj#user#select_pair()*
+textobj-rubyblock textobj-rubyblock.txt /*textobj-rubyblock*
+textobj-rubyblock-bugs textobj-rubyblock.txt /*textobj-rubyblock-bugs*
+textobj-rubyblock-changelog textobj-rubyblock.txt /*textobj-rubyblock-changelog*
+textobj-rubyblock-contents textobj-rubyblock.txt /*textobj-rubyblock-contents*
+textobj-rubyblock-customizing textobj-rubyblock.txt /*textobj-rubyblock-customizing*
+textobj-rubyblock-interface textobj-rubyblock.txt /*textobj-rubyblock-interface*
+textobj-rubyblock-introduction textobj-rubyblock.txt /*textobj-rubyblock-introduction*
+textobj-rubyblock-mappings textobj-rubyblock.txt /*textobj-rubyblock-mappings*
+textobj-rubyblock.txt textobj-rubyblock.txt /*textobj-rubyblock.txt*
+textobj-user textobj-user.txt /*textobj-user*
+textobj-user-bugs textobj-user.txt /*textobj-user-bugs*
+textobj-user-changelog textobj-user.txt /*textobj-user-changelog*
+textobj-user-changelog-0.0 textobj-user.txt /*textobj-user-changelog-0.0*
+textobj-user-changelog-0.1 textobj-user.txt /*textobj-user-changelog-0.1*
+textobj-user-changelog-0.2 textobj-user.txt /*textobj-user-changelog-0.2*
+textobj-user-changelog-0.2.1 textobj-user.txt /*textobj-user-changelog-0.2.1*
+textobj-user-changelog-0.2.2 textobj-user.txt /*textobj-user-changelog-0.2.2*
+textobj-user-changelog-0.3 textobj-user.txt /*textobj-user-changelog-0.3*
+textobj-user-changelog-0.3.1 textobj-user.txt /*textobj-user-changelog-0.3.1*
+textobj-user-changelog-0.3.2 textobj-user.txt /*textobj-user-changelog-0.3.2*
+textobj-user-changelog-0.3.3 textobj-user.txt /*textobj-user-changelog-0.3.3*
+textobj-user-changelog-0.3.4 textobj-user.txt /*textobj-user-changelog-0.3.4*
+textobj-user-changelog-0.3.5 textobj-user.txt /*textobj-user-changelog-0.3.5*
+textobj-user-changelog-0.3.6 textobj-user.txt /*textobj-user-changelog-0.3.6*
+textobj-user-changelog-0.3.7 textobj-user.txt /*textobj-user-changelog-0.3.7*
+textobj-user-changelog-0.3.8 textobj-user.txt /*textobj-user-changelog-0.3.8*
+textobj-user-changelog-0.3.9 textobj-user.txt /*textobj-user-changelog-0.3.9*
+textobj-user-contents textobj-user.txt /*textobj-user-contents*
+textobj-user-function textobj-user.txt /*textobj-user-function*
+textobj-user-interface textobj-user.txt /*textobj-user-interface*
+textobj-user-introduction textobj-user.txt /*textobj-user-introduction*
+textobj-user.txt textobj-user.txt /*textobj-user.txt*
View
151 doc/textobj-rubyblock.txt
@@ -0,0 +1,151 @@
+*textobj-rubyblock.txt* Text objects for ruby blocks
+
+Version 0.0.1
+
+CONTENTS *textobj-rubyblock-contents*
+
+Introduction |textobj-rubyblock-introduction|
+Interface |textobj-rubyblock-interface|
+Mappings |textobj-rubyblock-mappings|
+Examples |textobj-rubyblock-examples|
+Bugs |textobj-rubyblock-bugs|
+Changelog |textobj-rubyblock-changelog|
+
+
+==============================================================================
+INTRODUCTION *textobj-rubyblock-introduction*
+
+The *textobj-rubyblock* plugin provides two new |text-objects| which are
+triggered by `ar` and `ir` respectively. These follow Vim convention, so that
+`ar` selects _all_ of a ruby block, and `ir` selects the _inner_ portion of a
+rubyblock.
+
+In ruby, a block is always closed with the `end` keyword. Ruby blocks may be
+opened using one of several keywords, including `module`, `class`, `def` `if`
+and `do`. This example demonstrates a few of these:
+>
+ module Foo
+ class Bar
+ def Baz
+ [1,2,3].each do |i|
+ i + 1
+ end
+ end
+ end
+ end
+<
+Suppose your cursor was positioned on the word `def` in this snippet. Typing
+`var` would enable visual mode selecting _all_ of the method definition. Your
+selection would comprise the following lines:
+>
+ def Baz
+ [1,2,3].each do |i|
+ i + 1
+ end
+ end
+<
+Whereas if you typed `vir`, you would select everything _inside_ of the method
+definition, which looks like this:
+>
+ [1,2,3].each do |i|
+ i + 1
+ end
+<
+Note that the `ar` and `ir` text objects always enable _visual line_ mode,
+even if you were in visual character or block mode before you triggered the
+rubyblock text object.
+
+Note too that the `ar` and `ir` text objects always position your cursor on
+the `end` keyword. If you want to move to the top of the selection, you can do
+so with the `o` key.
+
+# Limitations #
+
+Some text objects in Vim respond to a count. For example, the `a{` text object
+will select _all_ of the current `{}` delimited block, but if you prefix it
+with the number 2 (e.g. `v2i{`) then it will select all of the block that
+contains the current block. The rubyblock text object does not respond in this
+way if you prefix a count. This is due to a limitation in vimscript #2100.
+
+However, you can achieve a similar effect by repeating the rubyblock
+text-object manually. So if you press `var` to select the current ruby block,
+you can expand your selection outwards by repeating `ar`, or contract your
+selection inwards by repeating `ir`.
+
+
+# Requirements: #
+
+- Vim 7.2 or later
+- |textobj-user| 0.3.7 or later (vimscript#2100)
+- |matchit.vim|
+
+Matchit.vim is distributed with Vim, but is not enabled by default. If you add
+the following line to your vimrc file, then it will enable matchit.vim each
+time Vim starts up:
+>
+ runtime macros/matchit.vim
+<
+Latest version:
+http://github.com/nelstrom/vim-textobj-rubyblock
+
+
+==============================================================================
+INTERFACE *textobj-rubyblock-interface*
+
+------------------------------------------------------------------------------
+MAPPINGS *textobj-rubyblock-mappings*
+
+These key mappings are defined in Visual mode and Operator-pending mode.
+
+<Plug>(textobj-rubyblock-a) *<Plug>(textobj-rubyblock-a)*
+ Select the ruby block including the opening and closing lines.
+
+<Plug>(textobj-rubyblock-i) *<Plug>(textobj-rubyblock-i)*
+ Select the inner lines of a ruby block. The opening and closing
+ lines are not included.
+
+==============================================================================
+CUSTOMIZING *textobj-rubyblock-customizing*
+
+ *g:textobj_rubyblock_no_default_key_mappings*
+ *:TextobjRubyblockDefaultKeyMappings*
+
+ This plugin will define the following key mappings in Visual mode and
+ Operator-pending mode automatically. If you don't want these key
+ mappings, define |g:textobj_rubyblock_no_default_key_mappings| before
+ this plugin is loaded (e.g. in your |vimrc|). You can also use
+ |:TextobjRubyblockDefaultKeyMappings| to redefine these key mappings.
+ This command doesn't override existing {lhs}s unless [!] is given.
+
+ {lhs} {rhs} ~
+ ----- ---------------------- ~
+ ar <Plug>(textobj-rubyblock-a)
+ ir <Plug>(textobj-rubyblock-i)
+
+ Suppose that you didn't like using `ar` and `ir` to trigger the
+ rubyblock text objects, and instead wanted to map them to `ae` and
+ `ie`. You could achieve this by placing the following in your vimrc
+ file:
+
+ let g:textobj_rubyblock_no_default_key_mappings = 1
+ xmap ae <Plug>(textobj-rubyblock-a)
+ omap ae <Plug>(textobj-rubyblock-a)
+ xmap ie <Plug>(textobj-rubyblock-i)
+ omap ie <Plug>(textobj-rubyblock-i)
+
+==============================================================================
+BUGS *textobj-rubyblock-bugs*
+
+- [count] is just ignored.
+
+- See |textobj-user-bugs| for further information.
+
+==============================================================================
+CHANGELOG *textobj-rubyblock-changelog*
+
+0.0.1 2010-12-27
+ - First release.
+
+==============================================================================
+vim:tw=78:ts=8:ft=help:norl:fen:fdl=0:fdm=marker:
+
View
401 doc/textobj-user.txt
@@ -0,0 +1,401 @@
+*textobj-user.txt* Support for user-defined text objects
+
+Version 0.3.9
+Script ID: 2100
+Copyright (C) 2007-2010 kana <http://whileimautomaton.net/>
+License: So-called MIT/X license {{{
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+}}}
+
+CONTENTS *textobj-user-contents*
+
+Introduction |textobj-user-introduction|
+Interface |textobj-user-interface|
+ Functions |textobj-user-functions|
+Bugs |textobj-user-bugs|
+Changelog |textobj-user-changelog|
+
+
+
+
+==============================================================================
+INTRODUCTION *textobj-user-introduction*
+
+*textobj-user* is a Vim plugin to SUPPORT writing user-defined text objects,
+especially, simple text objects which can be defined by regular expression.
+
+Note that this plugin only provides functions to support writing user-defined
+text objects, and this plugin does not provide any useful text objects. That
+is your work.
+
+
+Requirements:
+- Vim 7.0 or later
+
+Latest version:
+http://github.com/kana/vim-textobj-user
+
+Document in HTML format:
+http://kana.github.com/config/vim/textobj-user.html
+
+
+
+
+==============================================================================
+INTERFACE *textobj-user-interface*
+
+------------------------------------------------------------------------------
+FUNCTIONS *textobj-user-function*
+
+ *textobj#user#move()*
+textobj#user#move({pattern}, {flags}, {previous-mode})
+ Move the cursor to the appropriate object defined by {pattern}.
+
+ {flags} is a string, which can contain the following character flags:
+ char meaning ~
+ ---- ------- ~
+ 'b' search backward instead of forward.
+ 'e' move to the end of the match.
+
+ {previous-mode} is a string representing the "previous" mode,
+ that is, which mode of mapping causes the calling of this function.
+ For example, if this function is called via a mapping for
+ Operator-pending mode, {previous-mode} must be 'o'.
+ char meaning ~
+ ---- ------- ~
+ 'n' Normal mode
+ 'o' Operator-pending mode
+ 'v' Visual mode
+
+ Return value is same as |searchpos()|.
+
+ *textobj#user#select()*
+textobj#user#select({pattern}, {flags}, {prevous-mode})
+ Select the appropriate object defined by {pattern}.
+ If the cursor is already in the range of an object, select it.
+ If the cursor is not in the range of an object, select the nearest
+ object after the cursor.
+
+ {flags} is a string, which can contain the following character flags:
+ char meaning ~
+ ---- ------- ~
+ 'b' select the nearest object BEFORE the cursor if the
+ cursor is not in the range of an object.
+
+ For the detail of {previous-mode}, see |textobj#user#move()|.
+
+ Return value is not defined.
+
+ *textobj#user#select_pair()*
+textobj#user#select_pair({pattern1}, {pattern2}, {flags}, {previous-mode})
+ Select the appropriate object which starts with {pattern1} and ends
+ with {pattern2}.
+
+ {flags} is a string, which can contain the following character flags:
+ char meaning ~
+ ---- ------- ~
+ 'a' select the range including {pattern1} and {pattern2},
+ like |at|.
+ 'i' select the range excluding {pattern1} and {pattern2},
+ like |it|. This is the default behavior unless 'a' is
+ explicitly specified. If the cursor is not in a text
+ between {pattern1} and {pattern2}, this function does
+ nothing.
+
+ For the detail of {previous-mode}, see |textobj#user#move()|.
+
+ Return value is not defined.
+
+ *textobj#user#define()*
+textobj#user#define({pattern}, {pattern1}, {pattern2}, {guideline})
+ Support function to define key mappings for the text object defined by
+ {pattern}, or {pattern1} and {pattern2}. {guideline} is a dictionary
+ consists of key-value pairs where key is a string to represent the
+ name of function and value is a list of strings (each string
+ represents {lhs} for corresponding key).
+
+ function name meaning ~
+ ------------- ------- ~
+ 'move-to-next' textobj#user#move({pattern}, '')
+ 'move-to-prev' textobj#user#move({pattern}, 'b')
+ 'move-to-next-end' textobj#user#move({pattern}, 'e')
+ 'move-to-prev-end' textobj#user#move({pattern}, 'be')
+ 'select' synonym for 'select-next'
+ 'select-next' textobj#user#select({pattern}, '',
+ {previous-mode})
+ 'select-prev' textobj#user#select({pattern}, 'b',
+ {previous-mode})
+ 'select-pair-all' textobj#user#select_pair({pattern1},
+ {pattern2},
+ 'a', {previous-mode})
+ 'select-pair-inner' textobj#user#select_pair({pattern1},
+ {pattern2},
+ 'i', {previous-mode})
+
+ Example: >
+ call textobj#user#define('foo', '', '',
+ \ {'move-to-next': 'gj',
+ \ 'move-to-prev': 'gk',
+ \ 'select': ['ig', 'ag']})
+<
+ *textobj#user#plugin()*
+textobj#user#plugin({plugin}, {obj-specs})
+ Define key mappings and a command to support writing a plugin which
+ provides various user-defined text objects.
+
+ Example: If textobj#user#plugin() is called like the following: >
+
+ call textobj#user#plugin('foo', {
+ \ 'cdata': {
+ \ '*pattern*': ['<!\[CDATA\[', '\]\]>'],
+ \ 'select-a': 'aC',
+ \ 'select-i': 'iC',
+ \ },
+ \ 'date': {
+ \ '*pattern*': '\<\d\{4}-\d\{2}-\d\{2}\>',
+ \ 'select': ['ad', 'id'],
+ \ },
+ \ 'helptag': {
+ \ '*pattern*': '\*[^*]\+\*',
+ \ 'move-n': ',j',
+ \ 'move-p': ',k',
+ \ 'move-N': ',J',
+ \ 'move-P': ',K',
+ \ },
+ \ '-': {
+ \ '*select-function*': 'SelectFoo',
+ \ 'select': ['ax', 'ix'],
+ \ },
+ \ })
+<
+ (1) New command :TextobjFooDefaultKeyMappings will be defined.
+ This command defines the following key mappings as the default
+ ones for the new text objects (this command doesn't override
+ existing {lhs}s unless "!" is given): >
+
+ omap aC <Plug>(textobj-foo-cdata-a)
+ vmap aC <Plug>(textobj-foo-cdata-a)
+ omap iC <Plug>(textobj-foo-cdata-i)
+ vmap iC <Plug>(textobj-foo-cdata-i)
+ omap ad <Plug>(textobj-foo-date)
+ vmap ad <Plug>(textobj-foo-date)
+ omap id <Plug>(textobj-foo-date)
+ vmap id <Plug>(textobj-foo-date)
+ omap ax <Plug>(textobj-foo)
+ vmap ax <Plug>(textobj-foo)
+ omap ix <Plug>(textobj-foo)
+ vmap ix <Plug>(textobj-foo)
+ map ,j <Plug>(textobj-foo-helptag-n)
+ map ,k <Plug>(textobj-foo-helptag-p)
+ map ,J <Plug>(textobj-foo-helptag-N)
+ map ,K <Plug>(textobj-foo-helptag-P)
+<
+ (2) New variable g:__textobj_foo will be defined. This is
+ a dictionary which contains various functions and values.
+
+ (3) Key mappings <Plug>(textobj-foo-...) which execute
+ appropriate actions will be defined if "*pattern*" or
+ "*{spec}-function*" is given for a {spec}. Otherwise,
+ <Plug>(textobj-foo-...) will not be defined.
+
+ (4) :TextobjFooDefaultKeyMappings will be executed unless
+ {specs} contains the key "*no-default-key-mappings" or the
+ variable g:textobj_foo_no_default_key_mappings is defined.
+
+ {plugin} is the name of a plugin. It must be a string which consits
+ of only lowercase alphabets.
+
+ {obj-specs} is a dictionary (and given value is cached by this
+ plugin, so you have to pass copied one if necessary). In this
+ dictionary, each key/value pair expresses one text object:
+ - each key is a string of the name of the text object, and
+ - each value (called as "specs") is a dictionary which denotes some
+ details of the text object.
+
+ The following specs are available:
+
+ "move-n" {lhs} or [{lhs}, ...]
+ A string which is a key sequence to move the cursor to the
+ next text object. If the value is a list of strings, each
+ string is mapped to move the cursor.
+
+ "move-p" {lhs} or [{lhs}, ...]
+ "move-N" {lhs} or [{lhs}, ...]
+ "move-P" {lhs} or [{lhs}, ...]
+ Like "move-n", but each string is treated as a key sequence to
+ move the cursor to the previous text object, the end of the
+ next text object, or the end of the previous text object.
+
+ "select" {lhs} or [{lhs}, ...]
+ Like "move-n", but each string is treated as a key sequence to
+ select the text object.
+
+ "select-a" {lhs} or [{lhs}, ...]
+ "select-i" {lhs} or [{lhs}, ...]
+ Like "select", but each string is treated as a key sequence
+ to select "a" text object or "inner" text object.
+
+ "*pattern*" {regexp} or [{regexp}, {regexp}]
+ A regular expression which matches to a text object. If the
+ value is a list of two regular expressions, it denotes that
+ the text object starts with the first regular expression and
+ ends with the second regular expression.
+
+ "*no-default-key-mappings*" anything
+ If this key exists, :Textobj{Plugin}DefaultKeyMappings will
+ not be executed when textobj#user#plugin() is called. The
+ corresponding value doesn't matter.
+
+ "*{spec}-function*" {fname}
+ If this key exists, use the function named {fname} instead of
+ the default algorithm based on regular expression to select
+ a text for {spec}.
+
+ The function must take no argument and it must return a list
+ to denote the area to be selected or 0 to denote that there is
+ nothing to select. The detail of a list is as follows:
+ [motion_type, start_position, end_position]
+ - "motion_type" denotes the default type of motion. Valid
+ values are "v", "V" or "\<C-v>". The meaning of the values
+ are characterwise, linewise or blockwise.
+ - "start_position" denotes the start position of the area to
+ be selected. The detail of this value is the same as
+ |getpos()|.
+ - "end_position" is like "start_position", but it denotes the
+ end position of the area to be selected.
+
+ Example definition: >
+ funcion! SelectSomething()
+ if SomethinWrong()
+ return 0
+ endif
+
+ return ['v', getpos("'["), getpos("']")]
+ endfunction
+<
+ "*sfile*" {string}
+ Value must be expand('<sfile>'). This value is used to
+ calculate <SNR> prefix for script-local functions which are
+ specified "*{spec}-function*".
+
+
+
+
+==============================================================================
+BUGS *textobj-user-bugs*
+
+- textobj#user#select() and textobj#user#select_pair() override the current
+ {Visual}, unlike built-in text objects such as iw/aw, is/as, and so forth.
+
+- textobj#user#select() and textobj#user#select_pair() cannot be used with
+ [count].
+
+- textobj#user#select_pair() with |o_CTRL-V| may not work properly.
+
+
+
+
+==============================================================================
+CHANGELOG *textobj-user-changelog*
+
+0.3.9 2010-04-19T22:02:03+09:00 *textobj-user-changelog-0.3.9*
+ - |textobj#user#plugin()|: Fix not to define key mappings in Select
+ mode if appropriate. Now it works smoothly with plugins which
+ utilize and depend on the default behavior in Select mode.
+
+0.3.8 2009-07-18T10:02:40+09:00 *textobj-user-changelog-0.3.8*
+ - Fix a bug that it was not possible to select any range which starts
+ with the end of a line.
+ - |textobj#user#plugin()|: Fix a bug that it did not accept
+ any function which is not script-local as a value for
+ "*{spec}-function*".
+
+0.3.7 2008-10-24T02:25:59+09:00 *textobj-user-changelog-0.3.7*
+ - |textobj#user#select()|: Fix a bug that it didn't select an object
+ which: (1) matches to multiple lines and (2) contains the cursor.
+ - |textobj#user#select()|, |textobj#user#select_pair()|,
+ |textobj#user#plugin()| with "*{spec}-function*":
+ Support |o_v| and others. To use this feature, you have to apply
+ the following patch to Vim:
+ http://github.com/kana/vim/commits/hack/vimvar-motion_force
+
+0.3.6 2008-08-31T03:17:55+09:00 *textobj-user-changelog-0.3.6*
+ - Remove unnecessary messages for some cases. They were just for
+ debugging.
+
+0.3.5 2008-08-24T23:01:45+09:00 *textobj-user-changelog-0.3.5*
+ Incompatible changes with 0.3.4 or ealier:
+ - |textobj#user#plugin()|: Change the specification of functions for
+ "*{spec}-function*".
+
+ Other changes:
+ - |textobj#user#plugin()|: Add missing description of functions for
+ "*{spec}-function*".
+
+0.3.4 2008-06-26T14:13:33+09:00 *textobj-user-changelog-0.3.4*
+ - |textobj#user#plugin()|:
+ - Add "*{spec}-function*" to customize the way to move the cursor or
+ to select a text by the given function instead of regular
+ expression based selection.
+
+0.3.3 2008-06-11T21:16:53+09:00 *textobj-user-changelog-0.3.3*
+ - |textobj#user#plugin()|:
+ - Rename the spec "*pattern*" instead of "pattern".
+ - Fix incorrect processing on "*no-default-key-mappings*".
+
+0.3.2 2008-06-11T02:53:41+09:00 *textobj-user-changelog-0.3.2*
+ - |textobj#user#plugin()|: Change the names of interface mappings for
+ the text object of which name is '-'.
+ Old: <Plug>(textobj-{plugin}---a)
+ New: <Plug>(textobj-{plugin}-a)
+
+0.3.1 2008-06-08T22:05:02+09:00 *textobj-user-changelog-0.3.1*
+ - |textobj#user#plugin()|: Execute :Textobj{Plugin}DefaultKeyMappings
+ if necessary.
+
+0.3 2008-06-04T21:16:02+09:00 *textobj-user-changelog-0.3*
+ - |textobj#user#plugin()|: New.
+ - |textobj#user#define()|: Now obsolete. Use textobj#user#define().
+
+0.2.2 2008-06-02T06:26:12+09:00 *textobj-user-changelog-0.2.2*
+ - Fix wrong sentences in the document.
+
+0.2.1 2008-05-22T00:17:24+09:00 *textobj-user-changelog-0.2.1*
+ - textobj#user#select_pair(): Fix the bug that it selects wrong text
+ in Operator-pending mode.
+
+0.2 2008-01-07T08:44:14+09:00 *textobj-user-changelog-0.2*
+ - textobj#user#select(): Fix the wrong selecting in Operator-pending
+ mode.
+ - textobj#user#move(): Modify to be able to use in Visual and
+ Operator-pending mode.
+
+0.1 2007-11-16T01:17:45+09:00 *textobj-user-changelog-0.1*
+ - Modify to be autoloaded.
+ - Change the names of all API.
+
+0.0 2007-10-15T20:41:34+09:00 *textobj-user-changelog-0.0*
+ - First release.
+
+
+
+
+==============================================================================
+vim:tw=78:ts=8:ft=help:norl:fen:fdl=0:fdm=marker:
View
58 plugin/textobj/rubyblock.vim
@@ -0,0 +1,58 @@
+if exists('g:loaded_textobj_rubyblock') "{{{1
+ finish
+endif
+
+" Interface "{{{1
+call textobj#user#plugin('rubyblock', {
+\ '-': {
+\ '*sfile*': expand('<sfile>:p'),
+\ 'select-a': 'ar', '*select-a-function*': 's:select_a',
+\ 'select-i': 'ir', '*select-i-function*': 's:select_i'
+\ }
+\ })
+
+" Misc. "{{{1
+let s:comment_escape = '\v^[^#]*'
+let s:block_openers = '\zs(<def>|<if>|<do>|<module>|<class>)'
+let s:start_pattern = s:comment_escape . s:block_openers
+let s:end_pattern = s:comment_escape . '\zs<end>'
+let s:skip_pattern = 'getline(".") =~ "\\w\\s\\+if"'
+
+function! s:select_a()
+ let s:flags = 'W'
+
+ call searchpair(s:start_pattern,'',s:end_pattern, s:flags, s:skip_pattern)
+ let end_pos = getpos('.')
+
+ " Jump to match
+ normal %
+ let start_pos = getpos('.')
+
+ return ['V', start_pos, end_pos]
+endfunction
+
+function! s:select_i()
+ let s:flags = 'W'
+ if expand('<cword>') == 'end'
+ let s:flags = 'cW'
+ endif
+
+ call searchpair(s:start_pattern,'',s:end_pattern, s:flags, s:skip_pattern)
+
+ " Move up one line, and save position
+ normal k^
+ let end_pos = getpos('.')
+
+ " Move down again, jump to match, then down one line and save position
+ normal j^%j
+ let start_pos = getpos('.')
+
+ return ['V', start_pos, end_pos]
+endfunction
+
+" Fin. "{{{1
+
+let g:loaded_textobj_rubyblock = 1
+
+" __END__
+" vim: foldmethod=marker
Please sign in to comment.
Something went wrong with that request. Please try again.