aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-08-23 12:31:13 -0600
committerJosh Rahm <rahm@google.com>2022-08-23 12:31:13 -0600
commit5e5cc5189d53443e82100d85926e5856e6506866 (patch)
tree6d8db9c84d3349787d9a050d05296896f8e0c1f5
parent17703b92b44e5afd12e4bca418f61cadb50ac91d (diff)
downloadfieldmarshal.vim-5e5cc5189d53443e82100d85926e5856e6506866.tar.gz
fieldmarshal.vim-5e5cc5189d53443e82100d85926e5856e6506866.tar.bz2
fieldmarshal.vim-5e5cc5189d53443e82100d85926e5856e6506866.zip
Add casefmt. This adds bindings to change the case format of text objects.
-rw-r--r--plugin/casefmt.vim113
1 files changed, 113 insertions, 0 deletions
diff --git a/plugin/casefmt.vim b/plugin/casefmt.vim
new file mode 100644
index 0000000..ed85fb3
--- /dev/null
+++ b/plugin/casefmt.vim
@@ -0,0 +1,113 @@
+" Mappings for changing the case type of a text object. These mappings are invoked with <C-c>.
+"
+" This way, to change the case format of a word to snake_case, one can run:
+"
+" <C-c>siw
+"
+" The format of this command is
+"
+" <C-c><target_casefmt><text_object>
+"
+" valid case formats are
+"
+" s - snake_case
+" S - Upper_Snake_Case
+" c - camelCase
+" C - UpperCamelCase
+" k - KONSTANT_CASE
+
+noremap <silent> <C-c>s :<C-u>let g:CaseFmtFunction=function("<SID>to_snake")<cr>:<C-u>set operatorfunc=<SID>casefmt_do<cr>g@
+vnoremap <silent> <C-c>s :<C-u>let g:CaseFmtFunction=function("<SID>to_snake")<cr>:<C-u>call <SID>casefmt_do(visualmode(), 1)<cr>
+nmap <C-c>ss ^<C-c>s$
+
+noremap <silent> <C-c>S :<C-u>let g:CaseFmtFunction=function("<SID>to_upper_snake")<cr>:<C-u>set operatorfunc=<SID>casefmt_do<cr>g@
+vnoremap <silent> <C-c>S :<C-u>let g:CaseFmtFunction=function("<SID>to_upper_snake")<cr>:<C-u>call <SID>casefmt_do(visualmode(), 1)<cr>
+nmap <C-c>SS ^<C-c>S$
+
+noremap <silent> <C-c>c :<C-u>let g:CaseFmtFunction=function("<SID>to_camel")<cr>:<C-u>set operatorfunc=<SID>casefmt_do<cr>g@
+vnoremap <silent> <C-c>c :<C-u>let g:CaseFmtFunction=function("<SID>to_camel")<cr>:<C-u>call <SID>casefmt_do(visualmode(), 1)<cr>
+nmap <C-c>cc ^<C-c>c$
+
+noremap <silent> <C-c>C :<C-u>let g:CaseFmtFunction=function("<SID>to_Camel")<cr>:<C-u>set operatorfunc=<SID>casefmt_do<cr>g@
+vnoremap <silent> <C-c>C :<C-u>let g:CaseFmtFunction=function("<SID>to_Camel")<cr>:<C-u>call <SID>casefmt_do(visualmode(), 1)<cr>
+nmap <C-c>CC ^<C-c>C$
+
+noremap <silent> <C-c>k :<C-u>let g:CaseFmtFunction=function("<SID>to_CONSTANT")<cr>:<C-u>set operatorfunc=<SID>casefmt_do<cr>g@
+vnoremap <silent> <C-c>k :<C-u>let g:CaseFmtFunction=function("<SID>to_CONSTANT")<cr>:<C-u>call <SID>casefmt_do(visualmode(), 1)<cr>
+nmap <C-c>kk ^<C-c>k$
+
+" CamelCaseStuff
+
+" what_about_this
+" test_camel_case
+
+function! s:casefmt_do(type, ...) abort
+ if a:0
+ silent exe "norm! gvy"
+ elseif a:type == 'line'
+ " yank the text described by the motion
+ silent exe "norm! '[V']y"
+ else
+ silent exe "norm! `[v`]y"
+ endif
+
+ let yanked = getreg('"', 1, v:true)
+ let yankedtype = getregtype('"')
+
+ let changed = []
+ for n in yanked
+ let split = split(n, '\<\|\>') " Split by word boundaries
+ let new_split = []
+
+ for s in split " Iterate by words.
+ if s =~ "[a-zA-Z_0-9]*" " Is s an identifier?
+ call add(new_split, call(g:CaseFmtFunction, [s]))
+ else
+ call add(new_split, s)
+ endif
+ endfor
+
+ call add(changed, join(new_split, ''))
+ endfor
+
+ call setreg('"', changed, yankedtype)
+
+ norm gvp
+
+ " Reset the yanked text to what it was originally.
+ call setreg('"', yanked, yankedtype)
+endfunction
+
+" snake_case is the platonic form that all other forms build from. This function
+" tries to be smart about detecting the current case format and converting it
+" properly.
+function! s:to_snake(s) abort
+ if a:s =~ '^[A-Z_]*$' || a:s =~ '_'
+ " This is in constant case or is already in some flavor of snake_case.
+ " return whatever it is, but to lower.
+ return tolower(a:s)
+ endif
+
+ if a:s =~ '[a-z][A-Z]'
+ " a:s has a camel case boundary in it.
+ return tolower(substitute(a:s, '\%([a-zA-Z]\)\zs\ze\([A-Z0-9]\)', '_', "g"))
+ endif
+
+ return a:s
+endfunction
+
+function s:to_upper_snake(s) abort
+ return substitute(s:to_snake(a:s), '\%(_\|\<\)\zs\w\ze', '\u\0', 'g')
+endfunction
+
+function! s:to_camel(s) abort
+ return substitute(s:to_snake(a:s), '_\([a-z]\)', '\u\1', "g")
+endfunction
+
+function! s:to_Camel(s) abort
+ return substitute(s:to_camel(a:s), '\<\w', '\u\0', 'g')
+endfunction
+
+function! s:to_CONSTANT(s) abort
+ return toupper(s:to_snake(a:s))
+endfunction