Skip to content

Instantly share code, notes, and snippets.

@thinca
Created April 25, 2009 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thinca/101659 to your computer and use it in GitHub Desktop.
Save thinca/101659 to your computer and use it in GitHub Desktop.
" Vim additional ftplugin: javascript/textobj-function
" Author : thinca <http://d.hatena.ne.jp/thinca/>
" License: Creative Commons Attribution 2.1 Japan License
" <http://creativecommons.org/licenses/by/2.1/jp/deed.en>
let s:save_cpo = &cpo
set cpo&vim
if !exists('*g:textobj_function_javascript_select')
function! g:textobj_function_javascript_select(object_type)
return s:select_{a:object_type}()
endfunction
function! s:select_a()
let c = v:count1
let range = 0
while c
unlet! r
let r = s:function_range()
if type(r) == type(0)
break
endif
call setpos('.', r[1])
call s:left()
unlet! range
let range = r
let c -= 1
endwhile
return range
endfunction
function! s:select_i()
let range = s:select_a()
if type(range) == type(0)
return 0
endif
let type = 'v'
let endpos = range[2]
call setpos('.', endpos)
if s:cursor_char() != '}'
" Expression closures: function() expr
let b = s:head
let e = endpos
else
let linewise = 0
if getline('.')[:col('.') - 2] =~ '^\s*$'
normal! k$
let linewise = 1
else
call s:left()
endif
let e = getpos('.')
call setpos('.', endpos)
normal! %
if getline('.')[col('.'):] =~ '^\s*$'
normal! j0
if linewise
let type = 'V'
endif
else
normal! l
endif
let b = getpos('.')
endif
return [type, b, e]
endfunction
function! s:function_range()
let start = getpos('.')
while search('\<function\>', 'bcW') != 0
let b = getpos('.')
call search('\v<function>\s*\k*\s*\(', 'ceW')
normal! %
while search('\S', 'W') != 0 && s:cursor_syn() == 'Comment'
endwhile
if s:cursor_char() == '{'
normal! %
else
" Expression closures: function() expr
let s:head = getpos('.') " to inner
let c = ''
while c !~ '[,;)}]'
call search('[[({,;)}]', 'W')
let c = s:cursor_char()
if c =~ '[[({]' && s:cursor_syn() !~ '\%(Constant\|Comment\)'
normal! %
endif
endwhile
call search('\S', 'bW')
endif
let e = getpos('.')
if e[1] < start[1] || (e[1] == start[1] && e[2] < start[2])
call setpos('.', b)
call s:left()
continue
endif
return ['v', b, e]
endwhile
return 0
endfunction
function! s:left()
if col('.') == 1
if line('.') != 1
normal! k$
endif
else
normal! h
endif
endfunction
function! s:cursor_char()
return getline('.')[col('.') - 1]
endfunction
function! s:cursor_syn()
return synIDattr(synIDtrans(synID(line('.'), col('.'), 0)), 'name')
endfunction
endif
let b:textobj_function_select = function('g:textobj_function_javascript_select')
if exists('b:undo_ftplugin')
let b:undo_ftplugin .= ' | '
else
let b:undo_ftplugin = ''
endif
let b:undo_ftplugin .= 'unlet b:textobj_function_select'
let &cpo = s:save_cpo
unlet s:save_cpo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment