aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-08-30 12:12:16 -0600
committerJosh Rahm <rahm@google.com>2022-08-30 12:12:16 -0600
commit80c891e10223e560c641589fe81be6fa07f0cf1f (patch)
tree5aeb7a72bbce32f757f63ec292ee9bf8a7a5b827
parent52f035e111cfe766b030d603238b0552453d036c (diff)
downloadfieldmarshal.vim-80c891e10223e560c641589fe81be6fa07f0cf1f.tar.gz
fieldmarshal.vim-80c891e10223e560c641589fe81be6fa07f0cf1f.tar.bz2
fieldmarshal.vim-80c891e10223e560c641589fe81be6fa07f0cf1f.zip
subwords.vim: split functions into the autoload directory.
-rw-r--r--autoload/subwords.vim185
-rw-r--r--plugin/subwords.vim222
2 files changed, 207 insertions, 200 deletions
diff --git a/autoload/subwords.vim b/autoload/subwords.vim
new file mode 100644
index 0000000..eef8f8b
--- /dev/null
+++ b/autoload/subwords.vim
@@ -0,0 +1,185 @@
+let s:subword_motion = ""
+let s:subword_nosave = 0
+
+" 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_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
+ if a:word =~ '[a-z][A-Z]'
+ let is_camel = 1
+
+ if a:prefer_camel
+ " The word contains a camelCase boundary.
+ return 'camel'
+ endif
+ endif
+
+ if a:word =~ '_\|\W'
+ " The word contains a sake_case boundary.
+ return 'snake'
+ endif
+
+ if is_camel
+ return 'camel'
+ endif
+
+ " There is not discernible type, it's probably just a single word.
+ return 'word'
+endfunction
+
+" Move the cursor to the next subowrd.
+function! subwords#next(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
+
+" Visually highlights a subword.
+"
+" If a:prefer_camel is set, then WordsLike_This will be interpreted with
+" camelCase.
+"
+" if a:around is set, the highlight around the subword (otherwise highlight the
+" inner subword).
+function! subwords#visual(prefer_camel, around)
+
+ " Detect the type of the word.
+ let word = expand("<cword>")
+ let t = s:detect_word_type(a:prefer_camel, word)
+
+ let expr = ''
+
+ if t == 'camel'
+ let expr = 'v'
+
+ let line = getline('.')
+ let c = col('.') - 1
+ let i = 0
+
+ while line[c] =~ '[a-z]' && c >= 0
+ let c -= 1
+ let i += 1
+ endwhile
+
+ " camelCase
+
+ if c >= 0 && ! (line[c] =~ '[A-Z_]')
+ " If we are at the beginning of the meta word, the don't go back too far.
+ let i -= 1
+ endif
+
+ if i > 0
+ let expr .= printf("%dh", i)
+ endif
+
+ let expr .= 'o'
+
+ let c = col('.') - 1
+ let i = 0
+
+ if line[c] =~ '[A-Z_]'
+ " Actually on the starting capital letter, include it, but start counting
+ " from the next character.
+ let i += 1
+ let c += 1
+ endif
+
+ while c < len(line) && line[c] =~ '[a-z]'
+ let c += 1
+ let i += 1
+ endwhile
+
+ if i > 1
+ let expr .= printf("%dl", i - 1)
+ endif
+
+ elseif t == "snake"
+ let expr = 'v'
+
+ let line = getline('.')
+ let c = col('.') - 1
+ let i = 0
+
+ while c >= 0 && !( line[c] =~ '\W' ) && line[c] != '_'
+ let c -= 1
+ let i += 1
+ endwhile
+
+ let lhs_under = c >= 0 && line[c] == '_'
+
+ let i -= 1
+ let c += 1
+
+ if i > 0
+ let expr .= printf('%dho', i)
+ endif
+
+ let c = col('.') - 1
+ let i = 0
+
+ while c < len(line) && !(line[c] =~ '\W') && line[c] != '_'
+ let c += 1
+ let i += 1
+ endwhile
+
+ let rhs_under = c < len(line) && line[c] == '_'
+
+ let i -= 1
+ let c -= 1
+
+ if i > 0
+ let expr .= printf('%dl', i)
+ endif
+
+ if a:around
+ if rhs_under
+ let expr .= 'l'
+ elseif lhs_under
+ let expr .= 'oho'
+ endif
+ endif
+
+
+ elseif t == "word"
+ " Just a word? Easy peasy.
+ let expr = 'viw'
+ endif
+
+ return expr
+endfunction!
+
+" Clear the subword motion. (used for replacement TtfF)
+function! subwords#clear_mark()
+ let s:subword_motion = ""
+ return ''
+endfunction
+
+function! subwords#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
diff --git a/plugin/subwords.vim b/plugin/subwords.vim
index a8a38ee..067eb2c 100644
--- a/plugin/subwords.vim
+++ b/plugin/subwords.vim
@@ -8,10 +8,10 @@
" of snake_case identifier will include the underscores (_). The 'i_' references
" the ci_
-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>
+onoremap <silent> <Plug>(inner-sub-word) :<c-u>exec "norm " . subwords#visual(v:true, v:false)<cr>
+vnoremap <silent> <Plug>(inner-sub-word) :<c-u>exec "norm " . subwords#visual(v:true, v:false)<cr>
+onoremap <silent> <Plug>(around-sub-word) :<c-u>exec "norm " . subwords#visual(v:true, v:true)<cr>
+vnoremap <silent> <Plug>(around-sub-word) :<c-u>exec "norm " . subwords#visual(v:true, v:true)<cr>
if ! exists('g:subwords_include_bindings')
let g:subwords_include_bindings = 1
@@ -19,206 +19,28 @@ 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> <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>
+onoremap <silent> <Plug>(inner-sub-word-prefer-snake) :<c-u>exec "norm " . subwords#visual(v:false, v:false)<cr>
+vnoremap <silent> <Plug>(inner-sub-word-prefer-snake) :<c-u>exec "norm " . subwords#visual(v:false, v:false)<cr>
+onoremap <silent> <Plug>(around-sub-word-prefer-snake) :<c-u>exec "norm " . subwords#visual(v:false, v:true)<cr>
+vnoremap <silent> <Plug>(around-sub-word-prefer-snake) :<c-u>exec "norm " . subwords#visual(v:false, v:true)<cr>
" 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> <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``"
-
-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 <expr> <silent> <Plug>(subwords-replace-;) <SID>subword_repeat(';')
-noremap <expr> <silent> <Plug>(subwords-replace-,) <SID>subword_repeat(',')
-vnoremap <expr> <silent> <Plug>(subwords-replace-;) <SID>subword_repeat(';')
-vnoremap <expr> <silent> <Plug>(subwords-replace-,) <SID>subword_repeat(',')
-
-noremap <expr> <silent> <Plug>(subwords-replace-t) <SID>clear_subword_mark() . "t"
-noremap <expr> <silent> <Plug>(subwords-replace-f) <SID>clear_subword_mark() . "f"
-noremap <expr> <silent> <Plug>(subwords-replace-T) <SID>clear_subword_mark() . "T"
-noremap <expr> <silent> <Plug>(subwords-replace-F) <SID>clear_subword_mark() . "F"
-
-let s:subword_motion = ""
-let s:subword_nosave = 0
-
-" 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_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
- if a:word =~ '[a-z][A-Z]'
- let is_camel = 1
-
- if a:prefer_camel
- " The word contains a camelCase boundary.
- return 'camel'
- endif
- endif
-
- if a:word =~ '_'
- " The word contains a sake_case boundary.
- return 'snake'
- endif
-
- if is_camel
- return 'camel'
- endif
-
- " There is not discernible type, it's probably just a single word.
- return 'word'
-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.
-function! s:v_subword(prefer_camel, around)
-
- " Detect the type of the word.
- let word = expand("<cword>")
- let t = s:detect_word_type(a:prefer_camel, word)
-
- let expr = ''
-
- if t == 'camel'
- let expr = 'v'
-
- let line = getline('.')
- let c = col('.') - 1
- let i = 0
-
- while line[c] =~ '[a-z]' && c >= 0
- let c -= 1
- let i += 1
- endwhile
-
- " camelCase
-
- if c >= 0 && ! (line[c] =~ '[A-Z_]')
- " If we are at the beginning of the meta word, the don't go back too far.
- let i -= 1
- endif
-
- if i > 0
- let expr .= printf("%dh", i)
- endif
-
- let expr .= 'o'
-
- let c = col('.') - 1
- let i = 0
-
- if line[c] =~ '[A-Z_]'
- " Actually on the starting capital letter, include it, but start counting
- " from the next character.
- let i += 1
- let c += 1
- endif
-
- while c < len(line) && line[c] =~ '[a-z]'
- let c += 1
- let i += 1
- endwhile
-
- if i > 1
- let expr .= printf("%dl", i - 1)
- endif
-
- elseif t == "snake"
- let expr = 'v'
-
- let line = getline('.')
- let c = col('.') - 1
- let i = 0
-
- while c >= 0 && !( line[c] =~ '\W' ) && line[c] != '_'
- let c -= 1
- let i += 1
- endwhile
-
- let lhs_under = c >= 0 && line[c] == '_'
-
- let i -= 1
- let c += 1
-
- if i > 0
- let expr .= printf('%dho', i)
- endif
-
- let c = col('.') - 1
- let i = 0
-
- while c < len(line) && !(line[c] =~ '\W') && line[c] != '_'
- let c += 1
- let i += 1
- endwhile
-
- let rhs_under = c < len(line) && line[c] == '_'
-
- let i -= 1
- let c -= 1
-
- if i > 0
- let expr .= printf('%dl', i)
- endif
-
- if a:around
- if rhs_under
- let expr .= 'l'
- elseif lhs_under
- let expr .= 'oho'
- endif
- endif
-
-
- elseif t == "word"
- " Just a word? Easy peasy.
- let expr = 'viw'
- endif
-
- return expr
-endfunction!
+noremap <silent> <Plug>(next-subword) :<c-u>silent! call subwords#next(v:false, v:true)<cr>
+noremap <silent> <Plug>(prev-subword) :<c-u>silent! call subwords#next(v:false, v:false)<cr>
+vnoremap <expr> <silent> <Plug>(next-subword) visualmode() . ":\<c-u>silent! call subwords#next(visualmode(), v:true)\<cr>m'gv``"
+vnoremap <expr> <silent> <Plug>(prev-subword) visualmode() . ":\<c-u>silent! call subwords#next(visualmode(), v:false)<cr>m'gv``"
+
+noremap <expr> <silent> <Plug>(subwords-replace-;) subwords#repeat(';')
+noremap <expr> <silent> <Plug>(subwords-replace-,) subwords#repeat(',')
+vnoremap <expr> <silent> <Plug>(subwords-replace-;) subwords#repeat(';')
+vnoremap <expr> <silent> <Plug>(subwords-replace-,) subwords#repeat(',')
+
+noremap <expr> <silent> <Plug>(subwords-replace-t) subwords#clear_mark() . "t"
+noremap <expr> <silent> <Plug>(subwords-replace-f) subwords#clear_mark() . "f"
+noremap <expr> <silent> <Plug>(subwords-replace-T) subwords#clear_mark() . "T"
+noremap <expr> <silent> <Plug>(subwords-replace-F) subwords#clear_mark() . "F"
if g:subwords_include_bindings
onoremap <silent> i_ <Plug>(inner-sub-word-prefer-snake)