├── README.md ├── autoload └── textobj │ └── clang.vim └── ftplugin ├── c └── textobj_clang.vim └── cpp └── textobj_clang.vim /README.md: -------------------------------------------------------------------------------- 1 | Make text objects for various C and C++ blocks with power of clang 2 | ================================================================== 3 | 4 | This vim plugin makes text objects for various C and C++ blocks, function, class, namespace, expression, statement and so on. 5 | 6 | ## Dependencies 7 | 8 | - [vim-textobj-user](https://github.com/kana/vim-textobj-user) 9 | - [libclang-vim](https://github.com/rhysd/libclang-vim) 10 | 11 | If you use [neobundle.vim](https://github.com/Shougo/neobundle.vim), you can install this plugin easily as below. 12 | 13 | ```vim 14 | NeoBundleLazy 'rhysd/libclang-vim', { 15 | \ 'build' : { 16 | \ 'windows' : 'echo "Please build manually"', 17 | \ 'mac' : 'make', 18 | \ 'unix' : 'make', 19 | \ } 20 | \ } 21 | 22 | NeoBundleLazy 'rhysd/vim-textobj-clang', { 23 | \ 'depends' : ['kana/vim-textobj-user', 'rhysd/libclang-vim'], 24 | \ 'autoload' : { 25 | \ 'mappings' : [['xo', 'a;'], ['xo', 'i;']] 26 | \ } 27 | \ } 28 | ``` 29 | 30 | ## Simple operator-pending mappings `i;` and `a;` 31 | 32 | Operator-pending mappings `i;` and `a;` are available. `i;` selects the element under cursor. `a;` selects the most inner definition under cursor. 33 | 34 | For example, see below code. 35 | 36 | ```cpp 37 | int main() 38 | { 39 | return 0; 40 | } 41 | ``` 42 | 43 | When the cursor is placed at `return`, `i;` selects `return 0;` and `a;` selects whole `main()` function. 44 | This is very simple example. Clang can parse more complicated source files like Boost libraries. 45 | 46 | Screenshot: 47 | 48 | ![screenshot](http://gifzo.net/82IlUtfW1g.gif) 49 | 50 | ## More complicated operator-pending mappings 51 | 52 | If you set `g:textobj_clang_more_mappings` to `1`, many operator-pending mappings are defined. As a default, mappings in a below table are defined. You can control the number of the mappings with `g:textobj_clang_mapping_kinds`. 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
MappingBlock
i;mselect the most inner definition
i;cselect class blocks
i;fselect function blocks
i;eselect an expression
i;sselect an statement
i;pselect an parameter and a template parameter
i;nselect a namespace
i;uselect an element under cursor
i;aselect expression, statement, function, class or namespace
96 | 97 | ## License 98 | 99 | The MIT License (MIT) 100 | 101 | Copyright (c) 2014 rhysd 102 | 103 | Permission is hereby granted, free of charge, to any person obtaining a copy 104 | of this software and associated documentation files (the "Software"), to deal 105 | in the Software without restriction, including without limitation the rights 106 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 107 | copies of the Software, and to permit persons to whom the Software is 108 | furnished to do so, subject to the following conditions: 109 | 110 | The above copyright notice and this permission notice shall be included in 111 | all copies or substantial portions of the Software. 112 | 113 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 114 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 115 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 116 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 117 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 118 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 119 | THE SOFTWARE. 120 | 121 | -------------------------------------------------------------------------------- /autoload/textobj/clang.vim: -------------------------------------------------------------------------------- 1 | function! s:prepare_temp_file() 2 | if g:textobj_clang_include_headers 3 | let temp_name = expand('%:p:h') . substitute(tempname(), '\W', '_', 'g') . (&filetype ==# 'c' ? '.c' : '.cpp') 4 | call writefile(getline(1, '$'), temp_name) 5 | else 6 | let temp_name = tempname() . (&filetype ==# 'c' ? '.c' : '.cpp') 7 | call writefile(map(getline(1, '$'), 'v:val =~# "^\\s*#include\\s*\\(<[^>]\\+>\\|\"[^\"]\\+\"\\)" ? "" : v:val'), temp_name) 8 | endif 9 | 10 | return temp_name 11 | endfunction 12 | 13 | function! s:select_extent(func) 14 | let temp_name = s:prepare_temp_file() 15 | try 16 | let extent = call(a:func, [temp_name, line('.'), col('.')]) 17 | finally 18 | call delete(temp_name) 19 | endtry 20 | if empty(extent) || extent.start.file !=# extent.end.file 21 | return 0 22 | endif 23 | let pos = getpos('.') 24 | let start = [pos[0], extent.start.line, extent.start.column, pos[3]] 25 | let end = [pos[0], extent.end.line, extent.end.column, pos[3]] 26 | return ['v', start, end] 27 | endfunction 28 | 29 | function! textobj#clang#any_select_i() 30 | return s:select_extent('libclang#location#inner_definition_extent') 31 | endfunction 32 | 33 | function! textobj#clang#function_select_i() 34 | return s:select_extent('libclang#location#function_extent') 35 | endfunction 36 | 37 | function! textobj#clang#statement_select_i() 38 | return s:select_extent('libclang#location#statement_extent') 39 | endfunction 40 | 41 | function! textobj#clang#expression_select_i() 42 | return s:select_extent('libclang#location#expression_extent') 43 | endfunction 44 | 45 | function! textobj#clang#parameter_select_i() 46 | return s:select_extent('libclang#location#parameter_extent') 47 | endfunction 48 | 49 | function! textobj#clang#namespace_select_i() 50 | return s:select_extent('libclang#location#namespace_extent') 51 | endfunction 52 | 53 | function! textobj#clang#under_cursor_select_i() 54 | return s:select_extent('libclang#location#extent') 55 | endfunction 56 | 57 | function! textobj#clang#most_inner_select_i() 58 | return s:select_extent('libclang#location#class_extent') 59 | endfunction 60 | 61 | function! textobj#clang#any_select_i() 62 | let temp_name = s:prepare_temp_file() 63 | try 64 | let extents = filter(libclang#location#all_extents(temp_name, line('.'), col('.')), '!empty(v:val)') 65 | finally 66 | call delete(temp_name) 67 | endtry 68 | let len = len(extents) 69 | if len == 0 70 | return 0 71 | elseif len == 1 72 | let extent = extents[0] 73 | else 74 | let idx = 1 75 | while extents[idx] == extents[0] 76 | if idx == len - 1 | break | endif 77 | let idx += 1 78 | endwhile 79 | let extent = extents[idx] 80 | endif 81 | 82 | let pos = getpos('.') 83 | let start = [pos[0], extent.start.line, extent.start.column, pos[3]] 84 | let end = [pos[0], extent.end.line, extent.end.column, pos[3]] 85 | return ['v', start, end] 86 | endfunction 87 | -------------------------------------------------------------------------------- /ftplugin/c/textobj_clang.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_textobj_clang') 2 | finish 3 | endif 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | let g:textobj_clang_more_mappings = get(g:, 'textobj_clang_more_mappings', 0) 9 | let g:textobj_clang_include_headers = get(g:, 'textobj_clang_include_headers', 0) 10 | let s:spec = {} 11 | 12 | if g:textobj_clang_more_mappings 13 | let g:textobj_clang_mapping_kinds = get(g:, 'textobj_clang_kinds', ['any', 'class', 'function', 'expression', 'statement', 'parameter', 'namespace', 'under_cursor', 'most_inner']) 14 | for s:name in g:textobj_clang_mapping_kinds 15 | let s:spec[s:name] = { 16 | \ 'select-i' : 'i;'.s:name[0], 17 | \ '*select-i-function*' : 'textobj#clang#' . s:name . '_select_i', 18 | \ } 19 | endfor 20 | else 21 | let s:spec['-'] = { 22 | \ 'select-i' : 'i;', '*select-i-function*' : 'textobj#clang#under_cursor_select_i', 23 | \ 'select-a' : 'a;', '*select-a-function*' : 'textobj#clang#any_select_i', 24 | \ } 25 | endif 26 | 27 | call textobj#user#plugin('clang', s:spec) 28 | 29 | let &cpo = s:save_cpo 30 | unlet s:save_cpo 31 | 32 | let g:loaded_textobj_clang = 1 33 | -------------------------------------------------------------------------------- /ftplugin/cpp/textobj_clang.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_textobj_clang') 2 | finish 3 | endif 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | let g:textobj_clang_more_mappings = get(g:, 'textobj_clang_more_mappings', 0) 9 | let g:textobj_clang_include_headers = get(g:, 'textobj_clang_include_headers', 0) 10 | let s:spec = {} 11 | 12 | if g:textobj_clang_more_mappings 13 | let g:textobj_clang_mapping_kinds = get(g:, 'textobj_clang_kinds', ['any', 'class', 'function', 'expression', 'statement', 'parameter', 'namespace', 'under_cursor', 'most_inner']) 14 | for s:name in g:textobj_clang_mapping_kinds 15 | let s:spec[s:name] = { 16 | \ 'select-i' : 'i;'.s:name[0], 17 | \ '*select-i-function*' : 'textobj#clang#' . s:name . '_select_i', 18 | \ } 19 | endfor 20 | else 21 | let s:spec['-'] = { 22 | \ 'select-i' : 'i;', '*select-i-function*' : 'textobj#clang#under_cursor_select_i', 23 | \ 'select-a' : 'a;', '*select-a-function*' : 'textobj#clang#any_select_i', 24 | \ } 25 | endif 26 | 27 | call textobj#user#plugin('clang', s:spec) 28 | 29 | let &cpo = s:save_cpo 30 | unlet s:save_cpo 31 | 32 | let g:loaded_textobj_clang = 1 33 | --------------------------------------------------------------------------------