Created
December 6, 2012 15:57
-
-
Save gorkunov/4225560 to your computer and use it in GitHub Desktop.
Smart Selection for VIM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" About: | |
" | |
" How often do you forget which keys you should use to select/modify strings | |
" in the ' or " or in other pairs? I often use viw/ciw instead of vi'/vi" for | |
" the first time because it easier for my fingers (but after that I remember | |
" about vi'). This script allows you always use the same shortcut for all | |
" cases. When you want to select string in the ' use viv. Do you want to | |
" select all in the '()'? Use viv. All in the '[]'? Use viv. | |
" | |
" How it works: | |
" | |
" Script searches first unpair symbol from the left of the current cursor | |
" position and than runs target command with this symbol. You can use i or a | |
" modifiers for commands too. | |
" | |
" Available commands: | |
" | |
" vi* -> viv | |
" va* -> vav | |
" ci* -> civ | |
" ca* -> cav | |
" di* -> div | |
" da* -> dav | |
" ya* -> yiv | |
" ya* -> yav | |
" Where * is in <, >, ", ', `, (, ), [, ], {, } or t as tag | |
" | |
" NOTE: After v* commands you also can press v again and script extends selection | |
" to the next pairs. | |
" | |
" Author: @gorkunov ([email protected]) | |
" | |
" | |
let s:pairs = { '<' : '>', '"': '"', "'": "'", '`': '`', '(': ')', '[': ']', '{': '}' } | |
function! s:SmartPairs(type, mod, ...) | |
let all = keys(s:pairs) + values(s:pairs) | |
if a:0 > 0 | |
let str = getline(a:1) | |
let cur = len(str) | |
else | |
let str = getline('.') | |
let cur = col('.') - 1 | |
let s:line = line('.') | |
let s:type = a:type | |
let s:mod = a:mod | |
let s:stops = [] | |
endif | |
while cur >= 0 | |
let cur = cur - 1 | |
let ch = str[cur] | |
if index(all, ch) < 0 | |
continue | |
endif | |
if len(s:stops) && get(s:pairs, ch, '') == s:stops[-1].symbol | |
call remove(s:stops, -1) | |
" tags workaround | |
if ch == '<' | |
" closed tag | |
if str[cur + 1] == '/' | |
call add(s:stops, { 'symbol': 'c', 'position': [s:line, cur + 1] }) | |
else | |
if len(s:stops) && s:stops[-1].symbol == 'c' | |
call remove(s:stops, -1) | |
else | |
call add(s:stops, { 'symbol': 't', 'position': [s:line, cur + 1] }) | |
endif | |
endif | |
endif | |
elseif str[cur - 1] != '\' | |
call add(s:stops, { 'symbol': ch, 'position': [s:line, cur + 1] }) | |
endif | |
endwhile | |
call s:ApplyPairs() | |
endfunction | |
function! s:ApplyPairs() | |
let stop = get(s:stops, 0) | |
if type(stop) == type({}) && (has_key(s:pairs, stop.symbol) || stop.symbol == 't') | |
call remove(s:stops, 0) | |
execute "normal! " . stop.position[0] . "G" . stop.position[1] . "|" | |
execute "normal! " . s:type . s:mod . stop.symbol | |
elseif s:line > 1 | |
let s:line = s:line - 1 | |
call s:SmartPairs(s:type, s:mod, s:line) | |
endif | |
endfunction | |
function! s:NextPairs() | |
call s:ApplyPairs() | |
endfunction | |
nnoremap <silent> viv :call <SID>SmartPairs('v', 'i')<CR> | |
nnoremap <silent> vav :call <SID>SmartPairs('v', 'a')<CR> | |
nnoremap <silent> div :call <SID>SmartPairs('d', 'i')<CR> | |
nnoremap <silent> dav :call <SID>SmartPairs('d', 'a')<CR> | |
nnoremap <silent> civ :call <SID>SmartPairs('c', 'i')<CR>a | |
nnoremap <silent> cav :call <SID>SmartPairs('c', 'a')<CR>a | |
nnoremap <silent> yiv :call <SID>SmartPairs('y', 'i')<CR> | |
nnoremap <silent> yav :call <SID>SmartPairs('y', 'a')<CR> | |
vnoremap <silent> v <ESC>:call <SID>NextPairs()<CR> |
I like this idea a lot, if I understand correctly it selects the nearest matching pair. I use di" or ci" mostly and rarely vi" but it looks like SmartSelect
could easily be generalised to take another parameter which would be the first letter in the command, e.g SmartSelect('c', 'i')
, of course the name of the function would need to change as well.
@krisleech thanks for suggestions :) I added deleting and changing to the script and also fixed some bugs.
Added extending selection for 'v' commands
Migrated to plugin https://github.com/gorkunov/smartpairs.vim!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
e.g.