Mercurial > dotfiles.old
changeset 87:aefa231684d9
Add extra motions
author | zegervdv <zegervdv@me.com> |
---|---|
date | Fri, 01 Aug 2014 07:08:40 +0200 |
parents | 3a37086414bd |
children | d561c94bdefd |
files | vimrc |
diffstat | 1 files changed, 136 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/vimrc Sat Aug 02 10:56:31 2014 +0200 +++ b/vimrc Fri Aug 01 07:08:40 2014 +0200 @@ -246,8 +246,143 @@ endfunction " }}} set foldtext=MyFoldText() +" Next and Last {{{ +" +" Motion for "next/last object". "Last" here means "previous", not "final". +" Unfortunately the "p" motion was already taken for paragraphs. +" +" Next acts on the next object of the given type, last acts on the previous +" object of the given type. These don't necessarily have to be in the current +" line. +" +" Currently works for (, [, {, and their shortcuts b, r, B. +" +" Next kind of works for ' and " as long as there are no escaped versions of +" them in the string (TODO: fix that). Last is currently broken for quotes +" (TODO: fix that). +" +" Some examples (C marks cursor positions, V means visually selected): +" +" din' -> delete in next single quotes foo = bar('spam') +" C +" foo = bar('') +" C +" +" canb -> change around next parens foo = bar('spam') +" C +" foo = bar +" C +" +" vin" -> select inside next double quotes print "hello ", name +" C +" print "hello ", name +" VVVVVV + +onoremap an :<c-u>call <SID>NextTextObject('a', '/')<cr> +xnoremap an :<c-u>call <SID>NextTextObject('a', '/')<cr> +onoremap in :<c-u>call <SID>NextTextObject('i', '/')<cr> +xnoremap in :<c-u>call <SID>NextTextObject('i', '/')<cr> + +onoremap al :<c-u>call <SID>NextTextObject('a', '?')<cr> +xnoremap al :<c-u>call <SID>NextTextObject('a', '?')<cr> +onoremap il :<c-u>call <SID>NextTextObject('i', '?')<cr> +xnoremap il :<c-u>call <SID>NextTextObject('i', '?')<cr> + + +function! s:NextTextObject(motion, dir) + let c = nr2char(getchar()) + let d = '' + + if c ==# "b" || c ==# "(" || c ==# ")" + let c = "(" + elseif c ==# "B" || c ==# "{" || c ==# "}" + let c = "{" + elseif c ==# "r" || c ==# "[" || c ==# "]" + let c = "[" + elseif c ==# "'" + let c = "'" + elseif c ==# '"' + let c = '"' + else + return + endif + + " Find the next opening-whatever. + execute "normal! " . a:dir . c . "\<cr>" + + if a:motion ==# 'a' + " If we're doing an 'around' method, we just need to select around it + " and we can bail out to Vim. + execute "normal! va" . c + else + " Otherwise we're looking at an 'inside' motion. Unfortunately these + " get tricky when you're dealing with an empty set of delimiters because + " Vim does the wrong thing when you say vi(. + + let open = '' + let close = '' + + if c ==# "(" + let open = "(" + let close = ")" + elseif c ==# "{" + let open = "{" + let close = "}" + elseif c ==# "[" + let open = "\\[" + let close = "\\]" + elseif c ==# "'" + let open = "'" + let close = "'" + elseif c ==# '"' + let open = '"' + let close = '"' + endif + + " We'll start at the current delimiter. + let start_pos = getpos('.') + let start_l = start_pos[1] + let start_c = start_pos[2] + + " Then we'll find it's matching end delimiter. + if c ==# "'" || c ==# '"' + " searchpairpos() doesn't work for quotes, because fuck me. + let end_pos = searchpos(open) + else + let end_pos = searchpairpos(open, '', close) + endif + + let end_l = end_pos[0] + let end_c = end_pos[1] + + call setpos('.', start_pos) + + if start_l == end_l && start_c == (end_c - 1) + " We're in an empty set of delimiters. We'll append an "x" + " character and select that so most Vim commands will do something + " sane. v is gonna be weird, and so is y. Oh well. + execute "normal! ax\<esc>\<left>" + execute "normal! vi" . c + elseif start_l == end_l && start_c == (end_c - 2) + " We're on a set of delimiters that contain a single, non-newline + " character. We can just select that and we're done. + execute "normal! vi" . c + else + " Otherwise these delimiters contain something. But we're still not + " sure Vim's gonna work, because if they contain nothing but + " newlines Vim still does the wrong thing. So we'll manually select + " the guts ourselves. + let whichwrap = &whichwrap + set whichwrap+=h,l + + execute "normal! va" . c . "hol" + + let &whichwrap = whichwrap + endif + endif +endfunction " }}} - +" }}} " Vim Math plugin; make simple calculations {{{ vmap <expr> ++ VMATH_YankAndAnalyse() nmap ++ vip++