├── .gitignore ├── LICENSE ├── README.md ├── doc └── skipit.txt └── plugin └── skipit.vim /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Maxim Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-skipit 2 | Skip text in INSERT mode. 3 | 4 | If you have `g:skipit_default_mappings` set to 1 then while INSERT mode on press 5 | `l` to skip everything until parentheses, bars or quotes and place 6 | cursor right after them. 7 | 8 | ## Example 9 | 10 | ![vim-skipit example](http://i.imgur.com/agJQSXp.gif) 11 | 12 | `|` is the cursor position. 13 | 14 | ```python 15 | def make_me_|cappuccino_coffee(temperature): 16 | ``` 17 | 18 | I want to rename function and insert one more parameter so I issue: 19 | ``` 20 | ct_ 21 | latte 22 | ``` 23 | 24 | ```python 25 | def make_me_latte|_coffee(temperature): 26 | ``` 27 | 28 | Here I press `l` and skip `_coffee(` 29 | 30 | ```python 31 | def make_me_latte_coffee(|temperature): 32 | ``` 33 | 34 | Then add some `sugar, ` 35 | 36 | ```python 37 | def make_me_latte_coffee(sugar, |temperature): 38 | ``` 39 | 40 | And I am ready to exit INSERT mode. `` 41 | 42 | ## Installation 43 | Using `vim-plug`: 44 | ``` 45 | call plug#begin('~/.vim/plugged') 46 | Plug 'habamax/vim-skipit' 47 | call plug#end() 48 | ``` 49 | -------------------------------------------------------------------------------- /doc/skipit.txt: -------------------------------------------------------------------------------- 1 | *skipit.txt* Skip text in INSERT mode. 2 | 3 | Author: Maxim Kim 4 | License: MIT 5 | 6 | The plugin lets you bind a key to move cursor to the opening braces, quotes 7 | etc. 8 | 9 | If you have g:skipit_default_mappings set to 1 then while INSERT mode on press 10 | l to skip everything until parentheses, bars or quotes and place 11 | cursor right after them. 12 | 13 | Example: 14 | 15 | | is the cursor position. 16 | 17 | def make_me_|cappuccino_coffee(temperature): 18 | 19 | I want to rename function and insert one more parameter so I issue: 20 | ct_ 21 | latte 22 | 23 | def make_me_latte|_coffee(temperature): 24 | 25 | Here I press l and skip _coffee( 26 | 27 | def make_me_latte_coffee(|temperature): 28 | 29 | Then add some sugar 30 | 31 | def make_me_latte_coffee(sugar, |temperature): 32 | 33 | And I am ready to exit INSERT mode. 34 | 35 | The skipped delimiters are ([{<"|'`>}]). Also, there are 'forward direction' delimiters - ([{<"|'` - and 'back direction' delimiters - "|'`>}]) - which affect how other skip features work. 36 | 37 | Skipit can be used to skip many consecutive delimiters at once until it finds a non-delimiter character - by default this feature is mapped to L. For example: 38 | 39 | |[ { foo: "bar" } ] 40 | 41 | Typing L results in 42 | 43 | [ {| foo: "bar" } ] 44 | 45 | Again: 46 | 47 | [ { foo: "|bar" } ] 48 | 49 | Again: 50 | 51 | [ { foo: "bar"| } ] 52 | 53 | One last time: 54 | 55 | [ { foo: "bar" } ]| 56 | 57 | This also works with multiline. 58 | 59 | Jumping back is supported also, with the analogous h and H 60 | 61 | *i_CTRL-L_l* 62 | CTRL-L l Skip text and place cursor right after the next delimiter 63 | Use (SkipItForward) to remap: 64 | imap (SkipItForward) 65 | 66 | *i_CTRL-L_L* 67 | CTRL-L L Skip text and place cursor right after the next delimiter and all the consecutive delimiters of the same direction 68 | Use (SkipAllForward) to remap: 69 | imap (SkipAllForward) 70 | 71 | *i_CTRL-L_h* 72 | CTRL-L h Skip text and place cursor right before the previous delimiter 73 | Use (SkipItBack) to remap: 74 | imap (SkipItBack) 75 | 76 | *i_CTRL-L_H* 77 | CTRL-L H Skip text and place cursor right before the previous delimiter and all the consecutive delimiters of the same direction 78 | Use (SkipAllBack) to remap: 79 | imap (SkipAllBack) 80 | 81 | *g:skipit_multiline* 82 | By default l skips text across lines. You can change this behaviour by 83 | setting: 84 | let g:skipit_multiline = 0 85 | in your .vimrc 86 | 87 | You can turn on default mappings: 88 | let g:skipit_default_mappings = 1 89 | 90 | It should be set up before plugin is loaded, for ex: 91 | let g:skipit_default_mappings = 1 92 | Plug 'habamax/vim-skipit' 93 | 94 | I personally don't use default mappings and just bind (SkipItForward) to 95 | a key easily pressed. 96 | 97 | vim:tw=78:et:ft=help:norl: 98 | -------------------------------------------------------------------------------- /plugin/skipit.vim: -------------------------------------------------------------------------------- 1 | " skipit.vim - Skip text till after ([{<"|'>}]) 2 | " Maintainer: Maxim Kim 3 | 4 | if exists("g:loaded_skipit") || &cp || v:version < 700 5 | finish 6 | endif 7 | let g:loaded_skipit = 1 8 | 9 | if !exists("g:skipit_default_mappings") 10 | let g:skipit_default_mappings = 0 11 | endif 12 | 13 | if !exists('g:skipit_multiline') 14 | let g:skipit_multiline = 1 15 | endif 16 | 17 | let s:quotes = '"''`|' 18 | let s:beginning_delimiters = '[{(<' 19 | let s:ending_delimiters = '\])}>' 20 | 21 | fun! s:skip_it_forward() 22 | let pattern='\v['.s:beginning_delimiters.s:ending_delimiters.s:quotes.']' 23 | let pos = s:findnext(pattern) 24 | 25 | if pos != [0, 0] 26 | call setpos('.', [0, pos[0], pos[1]+1, 0]) 27 | else 28 | call setpos('.', [0, line('.'), col('$')]) 29 | endif 30 | endfun 31 | 32 | fun! s:skip_it_back() 33 | let pattern = '\v['.s:beginning_delimiters.s:ending_delimiters.s:quotes.']' 34 | let pos = s:findprev(pattern) 35 | 36 | if pos != [0, 0] 37 | call setpos('.', [0, pos[0], pos[1], 0]) 38 | else 39 | call setpos('.', [0, line('.'), 0]) 40 | endif 41 | endfun 42 | 43 | fun! s:skip_all_forward() 44 | let pattern = '\v['.s:beginning_delimiters.s:ending_delimiters.s:quotes.']' 45 | let pos = s:findnext(pattern) 46 | 47 | if pos != [0, 0] 48 | " Keep looking forward and find the true stop position 49 | " First find out if we found a beginning delimiter or an ending 50 | " delimiter, and keep looking for the same type of delimiter 51 | let delimiters='' 52 | if(s:isin(s:getcharat(pos), s:beginning_delimiters)) 53 | let delimiters .= s:beginning_delimiters 54 | elseif(s:isin(s:getcharat(pos), s:ending_delimiters)) 55 | let delimiters .= s:ending_delimiters 56 | endif 57 | 58 | " All ignorable delimeters 59 | let all_delimiters = delimiters.s:quotes." \t\n" 60 | " Initialize the position for iterating the current buffer 61 | let curlinepos=pos[0] 62 | let curpos=pos[1] 63 | let lastlinepos=line('$') 64 | let stop=0 65 | while (curlinepos <= lastlinepos && !stop) 66 | let curline=getline(curlinepos) 67 | while (curpos <= len(curline) && !stop) 68 | let curchar=s:getcharat([curlinepos, curpos]) 69 | if(s:isin(curchar, all_delimiters)) 70 | if(s:isin(curchar, delimiters)) 71 | let pos=[curlinepos, curpos] 72 | endif 73 | let curpos=curpos+1 74 | else 75 | let stop=1 76 | endif 77 | endwhile 78 | let curlinepos=curlinepos+1 79 | let curpos=1 80 | endwhile 81 | call setpos('.', [0, pos[0], pos[1]+1, 0]) 82 | else 83 | call setpos('.', [0, line('.'), col('$')]) 84 | endif 85 | endfun 86 | 87 | fun! s:skip_all_back() 88 | let pattern = '\v['.s:beginning_delimiters.s:ending_delimiters.s:quotes.']' 89 | let pos = s:findprev(pattern) 90 | 91 | if pos != [0, 0] 92 | " Keep looking forward and find the true stop position 93 | " First find out if we found a beginning delimiter or an ending 94 | " delimiter, and keep looking for the same type of delimiter 95 | let delimiters='' 96 | if(s:isin(s:getcharat(pos), s:beginning_delimiters)) 97 | let delimiters .= s:beginning_delimiters 98 | elseif(s:isin(s:getcharat(pos), s:ending_delimiters)) 99 | let delimiters .= s:ending_delimiters 100 | endif 101 | 102 | " All ignorable delimeters 103 | let all_delimiters = delimiters.s:quotes." \t\n" 104 | " Initialize the position for iterating the current buffer 105 | let curlinepos=pos[0] 106 | let curpos=pos[1] 107 | let stop=0 108 | while (curlinepos >=1 && !stop) 109 | let curline=getline(curlinepos) 110 | while (curpos >= 1 && !stop) 111 | let curchar=s:getcharat([curlinepos, curpos]) 112 | if(s:isin(curchar, all_delimiters)) 113 | if(s:isin(curchar, delimiters)) 114 | let pos=[curlinepos, curpos] 115 | endif 116 | let curpos=curpos-1 117 | else 118 | let stop=1 119 | endif 120 | endwhile 121 | let curlinepos=curlinepos-1 122 | if(curlinepos > 1) 123 | let curpos=len(getline(curlinepos)) 124 | endif 125 | endwhile 126 | call setpos('.', [0, pos[0], pos[1], 0]) 127 | else 128 | call setpos('.', [0, line('.'), 0]) 129 | endif 130 | endfun 131 | 132 | fun! s:findnext(pattern) 133 | if(g:skipit_multiline) 134 | " c - accept matches at the current cursor 135 | return searchpos(a:pattern, 'ecW') 136 | else 137 | return searchpos(a:pattern, 'ec', line('.')) 138 | endif 139 | endfun 140 | 141 | fun! s:findprev(pattern) 142 | if(g:skipit_multiline) 143 | return searchpos(a:pattern, 'beW') 144 | else 145 | return searchpos(a:pattern, 'be', line('.')) 146 | endif 147 | endfun 148 | 149 | fun! s:getcharat(pos) 150 | return getline(a:pos[0])[a:pos[1] - 1] 151 | endfun 152 | 153 | fun! s:isin(char, string) 154 | return stridx(a:string, a:char) >= 0 155 | endfun 156 | 157 | inoremap (SkipItForward) :call skip_it_forward() 158 | inoremap (SkipItBack) :call skip_it_back() 159 | inoremap (SkipAllForward) :call skip_all_forward() 160 | inoremap (SkipAllBack) :call skip_all_back() 161 | 162 | if g:skipit_default_mappings 163 | if !hasmapto('(SkipItForward)') && maparg('l','i') ==# '' 164 | imap l (SkipItForward) 165 | endif 166 | 167 | if !hasmapto('(SkipItBack)') && maparg('h','i') ==# '' 168 | imap h (SkipItBack) 169 | endif 170 | 171 | if !hasmapto('(SkipAllForward)') && maparg('L','i') ==# '' 172 | imap L (SkipAllForward) 173 | endif 174 | 175 | if !hasmapto('(SkipAllBack)') && maparg('H','i') ==# '' 176 | imap H (SkipAllBack) 177 | endif 178 | endif 179 | --------------------------------------------------------------------------------