" Text object creation {{{ " XXX: use virtualedit here, it should greatly simplify things let s:text_object_number = 0 function Textobj(char, callback) let s:text_object_number += 1 function s:textobj_{s:text_object_number}(inner, operator, count, callback) try let pos = getpos('.') sandbox let [startline, startcol, endline, endcol] = function(a:callback)(a:inner, a:count) catch /no-match/ return finally call setpos('.', pos) endtry if startline == endline let objlength = endcol - startcol + 1 else let lines = getline(startline + 1, endline - 1) let lines = [strpart(getline(startline), startcol - 1)] + \ lines + \ [strpart(getline(endline), 0, endcol)] let objlength = 0 for line in lines let objlength += strlen(line) + 1 endfor let objlength -= 1 endif let whichwrap = &whichwrap set whichwrap+=s if startcol > strlen(getline(startline)) let startcol = 1 let startline += 1 let objlength -= 1 endif call cursor(startline, startcol) exe 'normal! '.a:operator.objlength.' ' if a:operator == 'c' normal! l startinsert elseif a:operator == 'v' exe "normal! \" endif let &whichwrap = whichwrap endfunction exe 'onoremap a'.a:char.' :call textobj_'.s:text_object_number.'(0, v:operator, v:prevcount, "'.a:callback.'")' exe 'onoremap i'.a:char.' :call textobj_'.s:text_object_number.'(1, v:operator, v:prevcount, "'.a:callback.'")' exe 'xnoremap a'.a:char.' :call textobj_'.s:text_object_number.'(0, "v", v:prevcount, "'.a:callback.'")' exe 'xnoremap i'.a:char.' :call textobj_'.s:text_object_number.'(1, "v", v:prevcount, "'.a:callback.'")' endfunction " }}} " Text object definitions {{{ " / for regex {{{ function s:textobj_regex(inner, count) let pos = getpos('.') let line = strpart(getline(pos[1]), 0, pos[2]) let lines = getline(1, pos[1] - 1) + [line] let linenum = pos[1] for line in reverse(lines) let objstart = match(line, '.*\zs\\\@" endif return s:textobj_arg(a:inner, a:count) elseif curchar =~ '\s' normal! W return s:textobj_arg(a:inner, a:count) endif let line = strpart(getline(pos[1]), 0, pos[2]) let lines = getline(1, pos[1] - 1) + [line] let linenum = pos[1] for line in reverse(lines) let argbegin = matchend(line, '.*\%(,\s*\|(\)') + 1 if argbegin != 0 while argbegin > strlen(line) let linenum += 1 let line = getline(linenum) let argbegin = matchend(line, '^\s*') + 1 endwhile break endif let linenum -= 1 endfor if argbegin == 0 throw 'no-match' endif let argstartline = linenum let line = strpart(getline(pos[1]), pos[2] - 1) let lines = [line] + getline(pos[1] + 1, line('$')) let linenum = pos[1] for line in lines let argend = match(line, '\zs.\?\%(,\|)\)') + 1 if argend != 0 if linenum == pos[1] let argend += pos[2] - 1 endif if argend == 1 && getline(linenum)[argend - 1] == ')' let linenum -= 1 let argend = strlen(getline(linenum)) endif break endif let linenum += 1 endfor if argend == 0 throw 'no-match' endif let argendline = linenum if a:inner == 0 let endline = getline(argendline) let startline = getline(argstartline) if argend >= strlen(endline) let argend = 0 let argendline += 1 let endline = getline(argendline) endif if endline[argend] == ')' && startline[argbegin - 2] != '(' let argbegin = match(strpart(startline, 0, argbegin - 1), '\s*$') while argbegin == 0 let argstartline -= 1 let startline = getline(argstartline) let argbegin = strlen(startline) endwhile elseif endline[argend] != ')' let argend += matchend(strpart(endline, argend + 1), '^\s*') + 1 if startline[argbegin - 2] == '(' for line in [strpart(endline, argend)] + \ getline(argendline + 1, line('$')) let argincr = matchend(line, '\s*\ze\S') if argincr != -1 let argend += argincr break endif let argendline += 1 let argend = 0 endfor endif endif if argend >= strlen(endline) if argendline == argstartline let newbegin = matchend(strpart(endline, 0, argbegin), '.*,') if newbegin != -1 let argbegin = newbegin + 1 endif endif let argend = 0 let argendline += 1 endif endif return [argstartline, argbegin, argendline, argend] endfunction " }}} " }}} " Text object creation {{{ if exists("g:Textobj_regex_enable") && g:Textobj_regex_enable call Textobj('/', "textobj_regex") endif if exists("g:Textobj_fold_enable") && g:Textobj_fold_enable call Textobj('f', "textobj_fold") endif if exists("g:Textobj_arg_enable") && g:Textobj_arg_enable call Textobj(',', "textobj_arg") endif " }}}