aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-08-27 13:11:02 -0600
committerJosh Rahm <rahm@google.com>2022-08-27 13:11:02 -0600
commit8a1c3a51721c2beb0f3bee92589ffbe88b8d3cbc (patch)
tree3805c8204c32eecb4cb4de99e0372bcf40dd5779
parent808365207f49b6c6aba766ffbaa6336a9410a860 (diff)
downloadfieldmarshal.vim-8a1c3a51721c2beb0f3bee92589ffbe88b8d3cbc.tar.gz
fieldmarshal.vim-8a1c3a51721c2beb0f3bee92589ffbe88b8d3cbc.tar.bz2
fieldmarshal.vim-8a1c3a51721c2beb0f3bee92589ffbe88b8d3cbc.zip
subwords.vim: More features
* Add ability to repeat motion with ,/; * Add ability to disable bindings * Change motions to +/-
-rw-r--r--plugin/subwords.vim95
1 files changed, 82 insertions, 13 deletions
diff --git a/plugin/subwords.vim b/plugin/subwords.vim
index e31796c..bab15cf 100644
--- a/plugin/subwords.vim
+++ b/plugin/subwords.vim
@@ -8,29 +8,88 @@
" of snake_case identifier will include the underscores (_). The 'i_' references
" the ci_
-onoremap <silent> i- :<c-u>exec "norm " . <sid>v_subword(v:true, v:false)<cr>
-vnoremap <silent> i- :<c-u>exec "norm " . <sid>v_subword(v:true, v:false)<cr>
-onoremap <silent> a- :<c-u>exec "norm " . <sid>v_subword(v:true, v:true)<cr>
-vnoremap <silent> a- :<c-u>exec "norm " . <sid>v_subword(v:true, v:true)<cr>
+onoremap <silent> <Plug>(inner-sub-word) :<c-u>exec "norm " . <sid>v_subword(v:true, v:false)<cr>
+vnoremap <silent> <Plug>(inner-sub-word) :<c-u>exec "norm " . <sid>v_subword(v:true, v:false)<cr>
+onoremap <silent> <Plug>(around-sub-word) :<c-u>exec "norm " . <sid>v_subword(v:true, v:true)<cr>
+vnoremap <silent> <Plug>(around-sub-word) :<c-u>exec "norm " . <sid>v_subword(v:true, v:true)<cr>
+
+if ! exists('g:subwords_include_bindings')
+ let g:subwords_include_bindings = 1
+endif
+
+if g:subwords_include_bindings
+ onoremap <silent> i- <Plug>(inner-sub-word)
+ vnoremap <silent> i- <Plug>(inner-sub-word)
+ onoremap <silent> a- <Plug>(around-sub-word)
+ vnoremap <silent> a- <Plug>(around-sub-word)
+endif
" These mappings are the same as above, except prefer_camel is turned off, so
" snake case is used in the case of a conflict.
-onoremap <silent> i_ :<c-u>exec "norm " . <sid>v_subword(v:false, v:false)<cr>
-vnoremap <silent> i_ :<c-u>exec "norm " . <sid>v_subword(v:false, v:false)<cr>
-onoremap <silent> a_ :<c-u>exec "norm " . <sid>v_subword(v:false, v:true)<cr>
-vnoremap <silent> a_ :<c-u>exec "norm " . <sid>v_subword(v:false, v:true)<cr>
+onoremap <silent> <Plug>(inner-sub-word-prefer-snake) :<c-u>exec "norm " . <sid>v_subword(v:false, v:false)<cr>
+vnoremap <silent> <Plug>(inner-sub-word-prefer-snake) :<c-u>exec "norm " . <sid>v_subword(v:false, v:false)<cr>
+onoremap <silent> <Plug>(around-sub-word-prefer-snake) :<c-u>exec "norm " . <sid>v_subword(v:false, v:true)<cr>
+vnoremap <silent> <Plug>(around-sub-word-prefer-snake) :<c-u>exec "norm " . <sid>v_subword(v:false, v:true)<cr>
+
+if g:subwords_include_bindings
+ onoremap <silent> i_ <Plug>(inner-sub-word-prefer-snake)
+ vnoremap <silent> i_ <Plug>(inner-sub-wor-prefer-snaked)
+ onoremap <silent> a_ <Plug>(around-sub-wor-prefer-snaked)
+ vnoremap <silent> a_ <Plug>(around-sub-wor-prefer-snaked)
+endif
" Movement keys for subwords. These all have prefer_camel set to true, the idea
" being it's pretty easy to navigate underscores with f_ and t_, but more
" difficult to navigate upper case letters.
-noremap <silent> <M--> :<c-u>silent! call <SID>next_subword(v:false, v:true)<cr>
-noremap <silent> <M-_> :<c-u>silent! call <SID>next_subword(v:false, v:false)<cr>
-vnoremap <silent> <M--> v:<c-u>silent! call <SID>next_subword(v:true, v:true)<cr>m'gv``
-vnoremap <silent> <M-_> v:<c-u>silent! call <SID>next_subword(v:true, v:false)<cr>m'gv``
+noremap <silent> <Plug>(next-subword) :<c-u>silent! call <SID>next_subword(v:false, v:true)<cr>
+noremap <silent> <Plug>(prev-subword) :<c-u>silent! call <SID>next_subword(v:false, v:false)<cr>
+vnoremap <expr> <silent> <Plug>(next-subword) visualmode() . ":\<c-u>silent! call \<SID>next_subword(visualmode(), v:true)\<cr>m'gv``"
+vnoremap <expr> <silent> <Plug>(prev-subword) visualmode() . ":\<c-u>silent! call \<SID>next_subword(visualmode(), v:false)<cr>m'gv``"
+
+let s:subword_motion = ""
+let s:subword_nosave = 0
+
+if g:subwords_include_bindings
+
+ function! s:clear_subword_mark()
+ let s:subword_motion = ""
+ return ''
+ endfunction
+
+ function! s:subword_repeat(char)
+ if s:subword_motion == ''
+ return a:char
+ endif
+
+ let mot = (s:subword_motion == 'next') != (a:char == ',')
+
+ let s:subword_nosave = 1
+ if mot
+ return "\<Plug>(next-subword)"
+ else
+ return "\<Plug>(prev-subword)"
+ endif
+ endfunction
+
+ noremap + <Plug>(next-subword)
+ vnoremap + <Plug>(next-subword)
+ noremap - <Plug>(prev-subword)
+ vnoremap - <Plug>(prev-subword)
+
+ " tetetetetetetete_tetete_tetesasa
+
+ noremap <expr> <silent> ; <SID>subword_repeat(';')
+ noremap <expr> <silent> , <SID>subword_repeat(',')
+ vnoremap <expr> <silent> ; <SID>subword_repeat(';')
+ vnoremap <expr> <silent> , <SID>subword_repeat(',')
+
+ noremap <expr> <silent> t <SID>clear_subword_mark() . "t"
+ noremap <expr> <silent> f <SID>clear_subword_mark() . "f"
+endif
" Return the type of meta-word (i.e. camelCase, snake_case). If
" a:prefer_camel is set, then a word like ThisIs_A_MixOfCamel_And_Snake will
-" some_snake_case SomeCamelCase SOME_CONSTANT_CASE
+" some_snake_cae SomeCamelCase SOME_CONSTANT_CASE
" return 'camel', otherwise it'll return 'snake'.
function! s:detect_word_type(prefer_camel, word) abort
let is_camel = 0
@@ -57,12 +116,22 @@ function! s:detect_word_type(prefer_camel, word) abort
endfunction
function! s:next_subword(vis, forward)
+ if ! s:subword_nosave
+ if a:forward
+ let s:subword_motion = 'next'
+ else
+ let s:subword_motion = 'prev'
+ endif
+ endif
+
let i = 0
while i < v:count1
call search(
\ '\([a-z]\zs[A-Z]\ze\)\|\(\W\|_\)\zs\w\ze', (a:forward ? '' : 'b'))
let i += 1
endwhile
+
+ let s:subword_nosave = 0
endfunction
" Highlight an inner subword.