├── 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 | 
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 | Mapping |
57 | Block |
58 |
59 |
60 | i;m |
61 | select the most inner definition |
62 |
63 |
64 | i;c |
65 | select class blocks |
66 |
67 |
68 | i;f |
69 | select function blocks |
70 |
71 |
72 | i;e |
73 | select an expression |
74 |
75 |
76 | i;s |
77 | select an statement |
78 |
79 |
80 | i;p |
81 | select an parameter and a template parameter |
82 |
83 |
84 | i;n |
85 | select a namespace |
86 |
87 |
88 | i;u |
89 | select an element under cursor |
90 |
91 |
92 | i;a |
93 | select expression, statement, function, class or namespace |
94 |
95 |
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 |
--------------------------------------------------------------------------------