123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- if !exists("g:go_textobj_enabled")
- let g:go_textobj_enabled = 1
- endif
- if !exists("g:go_textobj_include_function_doc")
- let g:go_textobj_include_function_doc = 1
- endif
- if !exists("g:go_textobj_include_variable")
- let g:go_textobj_include_variable = 1
- endif
- " ( ) motions
- " { } motions
- " s for sentence
- " p for parapgrah
- " < >
- " t for tag
- function! go#textobj#Function(mode) abort
- let offset = go#util#OffsetCursor()
- let fname = shellescape(expand("%:p"))
- if &modified
- " Write current unsaved buffer to a temp file and use the modified content
- let l:tmpname = tempname()
- call writefile(go#util#GetLines(), l:tmpname)
- let fname = l:tmpname
- endif
- let bin_path = go#path#CheckBinPath('motion')
- if empty(bin_path)
- return
- endif
- let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
- let command .= " -mode enclosing"
- if g:go_textobj_include_function_doc
- let command .= " -parse-comments"
- endif
- let out = go#util#System(command)
- if go#util#ShellError() != 0
- call go#util#EchoError(out)
- return
- endif
- " if exists, delete it as we don't need it anymore
- if exists("l:tmpname")
- call delete(l:tmpname)
- endif
- " convert our string dict representation into native Vim dictionary type
- let result = eval(out)
- if type(result) != 4 || !has_key(result, 'fn')
- return
- endif
- let info = result.fn
- if a:mode == 'a'
- " anonymous functions doesn't have associated doc. Also check if the user
- " want's to include doc comments for function declarations
- if has_key(info, 'doc') && g:go_textobj_include_function_doc
- call cursor(info.doc.line, info.doc.col)
- elseif info['sig']['name'] == '' && g:go_textobj_include_variable
- " one liner anonymous functions
- if info.lbrace.line == info.rbrace.line
- " jump to first nonblack char, to get the correct column
- call cursor(info.lbrace.line, 0 )
- normal! ^
- call cursor(info.func.line, col("."))
- else
- call cursor(info.func.line, info.rbrace.col)
- endif
- else
- call cursor(info.func.line, info.func.col)
- endif
- normal! v
- call cursor(info.rbrace.line, info.rbrace.col)
- return
- endif
- " rest is inner mode, a:mode == 'i'
- " if the function is a one liner we need to select only that portion
- if info.lbrace.line == info.rbrace.line
- call cursor(info.lbrace.line, info.lbrace.col+1)
- normal! v
- call cursor(info.rbrace.line, info.rbrace.col-1)
- return
- endif
- call cursor(info.lbrace.line+1, 1)
- normal! V
- call cursor(info.rbrace.line-1, 1)
- endfunction
- function! go#textobj#FunctionJump(mode, direction) abort
- " get count of the motion. This should be done before all the normal
- " expressions below as those reset this value(because they have zero
- " count!). We abstract -1 because the index starts from 0 in motion.
- let l:cnt = v:count1 - 1
- " set context mark so we can jump back with '' or ``
- normal! m'
- " select already previously selected visual content and continue from there.
- " If it's the first time starts with the visual mode. This is needed so
- " after selecting something in visual mode, every consecutive motion
- " continues.
- if a:mode == 'v'
- normal! gv
- endif
- let offset = go#util#OffsetCursor()
- let fname = shellescape(expand("%:p"))
- if &modified
- " Write current unsaved buffer to a temp file and use the modified content
- let l:tmpname = tempname()
- call writefile(go#util#GetLines(), l:tmpname)
- let fname = l:tmpname
- endif
- let bin_path = go#path#CheckBinPath('motion')
- if empty(bin_path)
- return
- endif
- let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
- let command .= ' -shift ' . l:cnt
- if a:direction == 'next'
- let command .= ' -mode next'
- else " 'prev'
- let command .= ' -mode prev'
- endif
- if g:go_textobj_include_function_doc
- let command .= " -parse-comments"
- endif
- let out = go#util#System(command)
- if go#util#ShellError() != 0
- call go#util#EchoError(out)
- return
- endif
- " if exists, delete it as we don't need it anymore
- if exists("l:tmpname")
- call delete(l:tmpname)
- endif
- " convert our string dict representation into native Vim dictionary type
- let result = eval(out)
- if type(result) != 4 || !has_key(result, 'fn')
- return
- endif
- " we reached the end and there are no functions. The usual [[ or ]] jumps to
- " the top or bottom, we'll do the same.
- if type(result) == 4 && has_key(result, 'err') && result.err == "no functions found"
- if a:direction == 'next'
- keepjumps normal! G
- else " 'prev'
- keepjumps normal! gg
- endif
- return
- endif
- let info = result.fn
- " if we select something ,select all function
- if a:mode == 'v' && a:direction == 'next'
- keepjumps call cursor(info.rbrace.line, 1)
- return
- endif
- if a:mode == 'v' && a:direction == 'prev'
- if has_key(info, 'doc') && g:go_textobj_include_function_doc
- keepjumps call cursor(info.doc.line, 1)
- else
- keepjumps call cursor(info.func.line, 1)
- endif
- return
- endif
- keepjumps call cursor(info.func.line, 1)
- endfunction
- " vim: sw=2 ts=2 et
|