├── .gitignore ├── README.markdown ├── VimFlavor ├── addon-info.json ├── autoload └── textobj │ └── indblock.vim ├── doc └── textobj-indblock.txt └── plugin └── textobj └── indblock.vim /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | textobj-indblock 2 | ================ 3 | 4 | This Vim plugin provides text objects to act on a block of indentation 5 | whitespace based on the indentation of the current line. 6 | 7 | This plugin supplements and closely follows the example of the 8 | [textobj-indent][1] plugin. 9 | 10 | In general, that plugin is more useful but on some occasions it can be 11 | preferable to act on indentation whitespace directly. 12 | 13 | [1]: https://github.com/kana/vim-textobj-indent 14 | 15 | Usage 16 | ----- 17 | 18 | As usual, on-line documentation is available at `:h textobj-indblock`. 19 | 20 | But as they say, a picture is worth a thousand words. Have a GIF: 21 | 22 | ![demo](https://raw.github.com/glts/vim-textobj-indblock/gh-pages/images/demo.gif) 23 | 24 | The GIF shows the effects of the two text objects 'inner/a block of 25 | indentation whitespace' in Visual mode, `vio` and `vao` by default. ('o' 26 | is right next to 'i' for 'indent'.) 27 | 28 | Requirements 29 | ------------ 30 | 31 | * Vim 7.3 or later 32 | * [textobj-user][2] Vim plugin 33 | 34 | [2]: https://github.com/kana/vim-textobj-user 35 | 36 | Installation 37 | ------------ 38 | 39 | Move the files into their respective directories inside your `~/.vim` 40 | directory (or your `$HOME\vimfiles` directory if you're on Windows). 41 | 42 | This plugin plays well with plugin managers. For example, with 43 | [pathogen.vim][3] the installation is as simple as this: 44 | 45 | git clone git://github.com/glts/vim-textobj-indblock.git ~/.vim/bundle/textobj-indblock 46 | 47 | Don't forget to install textobj-user, too, if you haven't already. 48 | 49 | [3]: http://www.vim.org/scripts/script.php?script_id=2332 50 | -------------------------------------------------------------------------------- /VimFlavor: -------------------------------------------------------------------------------- 1 | flavor 'kana/vim-textobj-user', '~> 0.4' 2 | -------------------------------------------------------------------------------- /addon-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "textobj-indblock", 3 | "description": "Text objects for blocks of indentation whitespace", 4 | "author": "glts <676c7473@gmail.com>", 5 | "version": "1.1.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/glts/vim-textobj-indblock.git" 9 | }, 10 | "dependencies": { 11 | "textobj-user": {} 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /autoload/textobj/indblock.vim: -------------------------------------------------------------------------------- 1 | " textobj-indblock - Text objects for blocks of indentation whitespace 2 | " Author: glts <676c7473@gmail.com> 3 | " Date: 2013-04-07 4 | 5 | function! s:Select(include_blank, same_indent) 6 | 7 | let cursor_line = line('.') 8 | 9 | " Search forward for a line with indent 10 | if indent(cursor_line) == 0 11 | let next_line = cursor_line 12 | while indent(next_line) == 0 13 | if next_line == line('$') 14 | return 0 15 | endif 16 | let next_line += 1 17 | endwhile 18 | let cursor_line = next_line 19 | endif 20 | 21 | let ind_width = indent(cursor_line) 22 | 23 | " Find top and bottom line for block 24 | let top_line = cursor_line 25 | while top_line > 0 26 | if s:IsExpansible(top_line-1, ind_width, a:include_blank, a:same_indent) 27 | let top_line -= 1 28 | else 29 | break 30 | endif 31 | endwhile 32 | 33 | let bottom_line = cursor_line 34 | let last_line = line('$') 35 | while bottom_line < last_line 36 | if s:IsExpansible(bottom_line+1, ind_width, a:include_blank, a:same_indent) 37 | let bottom_line += 1 38 | else 39 | break 40 | endif 41 | endwhile 42 | 43 | " Calculate indent column (in bytes) and screen column offset 44 | let [ind_col, offset] = s:GetIndentColOffset(ind_width, matchstr(getline(bottom_line), '^\s*')) 45 | 46 | return [ "\", 47 | \ [0, top_line, 1, 0], 48 | \ [0, bottom_line, ind_col, offset] ] 49 | endfunction 50 | 51 | function! s:IsExpansible(line, indent, include_blank, same_indent) 52 | if a:same_indent 53 | return a:include_blank 54 | \ ? (s:IsBlank(a:line) || indent(a:line) == a:indent) 55 | \ : indent(a:line) == a:indent 56 | else 57 | return a:include_blank 58 | \ ? (s:IsBlank(a:line) || indent(a:line) >= a:indent) 59 | \ : indent(a:line) >= a:indent 60 | endif 61 | endfunction 62 | 63 | function! s:IsBlank(line) 64 | return getline(a:line) =~# '^\s*$' 65 | endfunction 66 | 67 | function! s:GetIndentColOffset(ind_width, ind_string) 68 | let ind_col = 0 69 | let ind_virtcol = 0 70 | let char_width = 1 71 | 72 | for char in split(a:ind_string, '\zs') 73 | let ind_virtcol += char_width - 1 74 | let char_width = (char =~# '\t' ? (&tabstop - (ind_virtcol % &tabstop)) : 1) 75 | let ind_col += 1 76 | let ind_virtcol += 1 77 | if (ind_virtcol + char_width) > a:ind_width 78 | break 79 | endif 80 | endfor 81 | let ind_virtcol = !ind_virtcol ? 1 : ind_virtcol 82 | 83 | let offset = a:ind_width - ind_virtcol 84 | 85 | return [ind_col ? ind_col : 1, offset] 86 | endfunction 87 | 88 | function! textobj#indblock#select_a() 89 | return s:Select(1, 0) 90 | endfunction 91 | 92 | function! textobj#indblock#select_i() 93 | return s:Select(0, 0) 94 | endfunction 95 | 96 | function! textobj#indblock#select_same_a() 97 | return s:Select(1, 1) 98 | endfunction 99 | 100 | function! textobj#indblock#select_same_i() 101 | return s:Select(0, 1) 102 | endfunction 103 | -------------------------------------------------------------------------------- /doc/textobj-indblock.txt: -------------------------------------------------------------------------------- 1 | *textobj-indblock.txt* Text objects for blocks of indentation whitespace 2 | 3 | Author: glts <676c7473@gmail.com> 4 | License: Same terms as Vim itself (see |license|) 5 | 6 | ============================================================================== 7 | DESCRIPTION *textobj-indblock* 8 | 9 | This plugin provides text objects to select a block of indentation whitespace 10 | based on the indentation of the current line. 11 | 12 | Given a source fragment like the following, with the cursor resting on "200", 13 | |(textobj-indblock-a)| will select the Visual block indicated with the 14 | middots. > 15 | 16 | foreach my $q (@$questions) { 17 | if ($q->answered()) { 18 | ········my $upvotes = 0; 19 | ········foreach (@{ $q->answers() }) { $upvotes += $_->upvotes() } 20 | ········ 21 | ········push @good_answers, $q if $upvotes > 200; 22 | } 23 | } 24 | 25 | The text objects in this plugin closely follow the precedent set by the 26 | |textobj-indent| plugin by Kana Natsuno: 27 | 28 | http://github.com/kana/vim-textobj-indent 29 | 30 | See the documentation there to learn more. 31 | 32 | This plugin depends on the |textobj-user| plugin, v0.4.0 (Vim script ID 2100). 33 | 34 | ============================================================================== 35 | INTERFACE *textobj-indblock-interface* 36 | 37 | What follows is the mapping interface for Visual and Operator-pending mode. 38 | 39 | (textobj-indblock-a) *(textobj-indblock-a)* 40 | Selects a (Visual) block of indentation whitespace. 41 | Includes lines with the same or greater amount of 42 | indentation, and empty lines. 43 | 44 | When the current line is not indented or is empty, the 45 | next line that does have indentation will be used. 46 | 47 | Note that Vim cannot by default select only part of a 48 | tab or select past the end of the line. Thus, in 49 | certain situations the Visual block will be skewed or 50 | reduced. You can work around this by setting 51 | 'virtualedit' to "block" or "all". 52 | 53 | (textobj-indblock-i) *(textobj-indblock-i)* 54 | Same as |(textobj-indblock-a)|, but doesn't 55 | include unindented or empty lines. 56 | 57 | (textobj-indblock-same-a) *(textobj-indblock-same-a)* 58 | (textobj-indblock-same-i) *(textobj-indblock-same-i)* 59 | Same as |(textobj-indblock-a)| and 60 | |(textobj-indblock-i)|, but selects only blocks 61 | with the exact same amount of indentation. 62 | 63 | The following are the default mappings. Hint: "o" is right next to "i" (for 64 | "indent"). 65 | 66 | {lhs} {rhs} ~ 67 | ----- ---------------------- ~ 68 | ao (textobj-indblock-a) 69 | io (textobj-indblock-i) 70 | aO (textobj-indblock-same-a) 71 | iO (textobj-indblock-same-i) 72 | 73 | *g:textobj_indblock_no_default_key_mappings* 74 | *:TextobjIndblockDefaultKeyMappings* 75 | This plugin defines Visual and Operator-pending mode mappings in the usual 76 | fashion. See the |textobj-user| documentation for more info. 77 | 78 | ============================================================================== 79 | CHANGELOG *textobj-indblock-changelog* 80 | 81 | 1.1.0 2013-04-08 82 | Updated to textobj-user 0.4.0. 83 | Minor doc fixes. 84 | Better support for different plugin managers. 85 | 86 | 1.0.0 2012-12-08 87 | Initial release. 88 | 89 | ============================================================================== 90 | vim:tw=78:ts=8:ft=help:norl: 91 | -------------------------------------------------------------------------------- /plugin/textobj/indblock.vim: -------------------------------------------------------------------------------- 1 | " textobj-indblock - Text objects for blocks of indentation whitespace 2 | " Author: glts <676c7473@gmail.com> 3 | " Date: 2013-11-15 4 | " GetLatestVimScripts: 2100 1 textobj-user 5 | " GetLatestVimScripts: 4348 1 :AutoInstall: textobj-indblock 6 | 7 | if exists('g:loaded_textobj_indblock') 8 | finish 9 | endif 10 | 11 | if exists(':NeoBundleDepends') == 2 12 | NeoBundleDepends 'kana/vim-textobj-user' 13 | endif 14 | 15 | call textobj#user#plugin('indblock', { 16 | \ '-': { 17 | \ 'select-a-function': 'textobj#indblock#select_a', 18 | \ 'select-a': 'ao', 19 | \ 'select-i-function': 'textobj#indblock#select_i', 20 | \ 'select-i': 'io', 21 | \ }, 22 | \ 'same': { 23 | \ 'select-a-function': 'textobj#indblock#select_same_a', 24 | \ 'select-a': 'aO', 25 | \ 'select-i-function': 'textobj#indblock#select_same_i', 26 | \ 'select-i': 'iO', 27 | \ } 28 | \ }) 29 | 30 | let g:loaded_textobj_indblock = 1 31 | --------------------------------------------------------------------------------