DJ McMayhem's solution inspired me to write my own that relies on ctags and on matchit to do a proper analysis of function boundaries.
The difficult part has been already done by lh-dev and lh-tags for several years:
- the current file is parsed through ctags with the right options
- we look for all function definitions in the tags database which is restricted to the tags obtained for the current file
- thanks to the DB, we have the start line numbers for all functions (well the
template
and inline
part may be missed by ctags)
- with a simple iterative search (a binary search could have been done, but well, files are supposed to be "short"), the beginning of the current function is found
- And thanks to matchit plugin, its final line is found as well -- I see that universal ctags is offering a
end
field that can be used with C, C++, Python, and Vim that could also be used to find the end of a function.
Note that any parts of this algorithm could be overridden on a file-type basis. i.e. the boundaries detection of python functions could search for def
and analyse indentation, we could just search for function
in javascript, and so on -- In other words, the current version also works with Java, Vim and some other languages (I still have some work to do for Python)
So I define now two new mappings: a visual mode mapping, and an operator-pending mode mapping:
onoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr>
xnoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr><esc>gv
Which rely on:
function! lh#dev#_select_current_function() abort
let fn = lh#dev#find_function_boundaries(line('.'))
exe fn.lines[0]
normal! v
exe fn.lines[1]
endfunction
I spare you the several hundred lines of code of lh#dev#find_function_boundaries()
And thanks to DJ McMayhem's mapping
" Note that my vim settings requires two backslashes here instead of one
vnoremap / <esc>/\\%V
we can do a vif/pattern
to search for pattern
in the current function.
We can also delete functions with dif
, yank them with yif
, etc.
Here is what it looks like when applied on a realistic C++ function (i.e. not 0 indented):