Vim一键修改光标所在单词为相反或关联的词
写代码或文字时,经常会需要修改当前词(或选中区域)为相反或 相关的词,比如
A | B |
---|---|
up |
down |
left |
right |
show |
hide |
from |
to |
encode |
decode |
get |
set |
yes |
no |
on |
off |
down |
up |
left |
right |
top |
bottom |
this |
base |
read |
write |
row |
column |
rows |
columns |
RowHeight |
ColumnWidth |
focus |
blur |
var |
const |
lower |
upper |
odd |
even |
before |
after |
max |
min |
prev |
next |
true |
false |
enable |
disable |
enabled |
disabled |
permit |
deny |
smtp |
imap |
width |
height |
horizontal |
vertical |
user |
pwd |
username |
password |
SendMessage |
PostMessage |
左 |
右 |
上 |
下 |
水平 |
垂直 |
成功 |
失败 |
显示 |
隐藏 |
github.com |
github.com.cnpmjs.org |
于是就有了以下 map 和相关函数
切换后仍会保留原大小写格式
核心见hy_string#modify#toggleWord
函数
NOTE:比如设置了
get
和set
的转化后,那么以下情况也会自动有效
getValue
setValue
get_value
set_value
原理是getValue
如果未匹配,则会分别判断get
和Value
是否被定义
补充:在函数一开始还额外定义了
.prop
和["prop"]
的转化(不需要删除即可)
nnoremap <silent> <M-t> ciw<C-r>=hy_string#modify#toggleWord(@")<cr><esc>
xnoremap <silent> <M-t> s<C-r>=hy_string#modify#toggleWord(@")<cr><esc>
"true/false, up/down切换
"NOTE lis大小写或首字母大写,全用小写,其他情况保留原大小写
function! hy_string#modify#toggleWord(word)
" .prop ⇄ ["prop"]
if (a:word =~ '^\v\.\w+$') | return '["' .strpart(a:word,1). '"]' | endif
if (a:word =~ '^\v\["\w+"\]$') | return '.' .strpart(a:word,2,len(a:word)-4) | endif
let lis = [
\ ['!', '!'],
\ [',', ','],
\ ['.', '。'],
\ ['<^', 'LCtrl & '],
\ ['>^', 'RCtrl & '],
\ ['<+', 'LShift & '],
\ ['>+', 'RShift & '],
\ ['<!', 'LAlt & '],
\ ['>!', 'RAlt & '],
\ ['FireShot', 'mcbpblocgmgfnpjjppndjkmgjaogfceg'],
\ ['Surfingkeys', 'gfbliohnnapiefjpjlpjnehglfpaknnc'],
\ ['SwitchyOmega', 'padekgcemlokbadohgkifijomclgjgif'],
\ ['Tampermonkey', 'dhdgffkkebhmkfjojejmpbldmpobfkfo'],
\ ['show', 'hide'],
\ ['from', 'to'],
\ ['encode', 'decode'],
\ ['get', 'set'],
\ ['yes', 'no'],
\ ['on', 'off'],
\ ['down', 'up'],
\ ['left', 'right'],
\ ['top', 'bottom'],
\ ['this', 'base'],
\ ['read', 'write'],
\ ['row', 'column'],
\ ['rows', 'columns'],
\ ['RowHeight', "ColumnWidth"],
\ ['focus', 'blur'],
\ ['lower', 'upper'],
\ ['odd', 'even'],
\ ['before', 'after'],
\ ['max', 'min'],
\ ['prev', 'next'],
\ ['true', 'false'],
\ ['enable', 'disable'],
\ ['enabled', 'disabled'],
\ ['permit', 'deny'],
\ ['user', 'pwd'],
\ ['username', 'password'],
\ ['smtp', 'imap'],
\ ['width', 'height'],
\ ['horizontal', 'vertical'],
\ ['var', 'const'],
\ ['absolute', 'relative'],
\ ['hkcr', 'HKEY_CLASSES_ROOT'],
\ ['hkcu', 'HKEY_CURRENT_USER'],
\ ['hklm', 'HKEY_LOCAL_MACHINE'],
\ ['hku', 'HKEY_USERS'],
\ ['hkcc', 'HKEY_CURRENT_CONFIG'],
\ ['ActiveCell', 'selection'],
\ ['WinActive', 'WinActivate'],
\ ['SendMessage', 'PostMessage'],
\ ['setTimeout', 'setInterval'],
\ ['screen', 'window'],
\ ['左', '右'],
\ ['上', '下'],
\ ['水平', '垂直'],
\ ['成功', '失败'],
\ ['显示', '隐藏'],
\ ['jshint', 'eslint'],
\ ['scanf', 'printf'],
\ ['WinGetClientPos', 'WinGetPos'],
\ ['cells', 'range'],
\ ['MergeArea', 'MergeCells'],
\ ['ComObjActive', 'ComObject'],
\ ['chr', 'ord'],
\ ['FindFirst', 'FindAll'],
\ ['FileMove', 'FileCopy'],
\ ['FileDelete', 'FileRecycle'],
\ ['font', 'interior'],
\ ['querySelector', 'querySelectorAll'],
\ ['innerHTML', 'innerText'],
\ ['LCtrl', 'RCtrl'],
\ ['LShift', 'RShift'],
\ ['LAlt', 'RAlt'],
\ ['run', 'RunWait'],
\ ['msgbox', 'tooltip'],
\ ['PgDn', 'PgUp'],
\ ['RegExReplace', 'RegExMatch'],
\ ['access', 'trunk'],
\ ['waitForPackage', 'waitForActivity'],
\ ['textStartsWith', 'textMatches'],
\ ['clickByWindow', 'clickStayByWindow'],
\ ['toastLog', 'toastInfo'],
\ ['0x111', 'WM_COMMAND:=0x111'],
\ ['WM_COMMAND', 'WM_COMMAND:=0x111'],
\ ['0x112', 'WM_SYSCOMMAND:=0x112'],
\ ['WM_SYSCOMMAND', 'WM_SYSCOMMAND:=0x112'],
\ ['currentPackage', 'currentActivity'],
\ ['github.com', 'github.com.cnpmjs.org'],
\ ]
let word = a:word
"获取 word 前后内容(用来 setline)
let sLine = getline('.')
let idx0 = stridx(sLine, word, col('.')-strlen(word))
let strBefore = strpart(sLine, 0, idx0)
let strAfter = strpart(sLine, idx0+strlen(word))
"echom strBefore .'--'. strAfter .'--'. word
"lPair 转成 dic(相互为key,方便判断)
let dic = {}
for lPair in lis
let dic[lPair[0]] = lPair[1]
let dic[lPair[1]] = lPair[0]
endfor
"NOTE dic 额外增加单向的内容
let dic['int'] = 'integer'
let dic['integer'] = '^\d+$'
"处理单词大小写
let upCase = hy_string#get#upperCase(word)
let wordFixed = upCase > 0 ? tolower(word) : word "wordFixed 用来调整大小写
"echom word .' '. wordFixed
if !has_key(dic,wordFixed) "不在定义列表内
"echom 'not in dic'
"aUp → aDown
if word =~# '[A-Z]'
let char = ''
let l = hy_string#split#byUpper(word)
else
let char = matchstr(word, '\c[^a-z]')
let l = split(word, '\c[^a-z]')
endif
for i in range(len(l))
let upCase = hy_string#get#upperCase(l[i])
let wordFixed = upCase > 0 ? tolower(l[i]) : word "wordFixed 用来调整大小写
if has_key(dic, wordFixed) "找到匹配
let res = dic[wordFixed]
"恢复大小写
if upCase == 1
let res = tolower(res)
elseif upCase == 2
let res = toupper(res)
elseif upCase == 3
let res = substitute(res, '.*', '\L\u&', '')
endif
"修改 l
let l[i] = res
return join(l, char)
endif
endfor
return word
else
let res = dic[wordFixed]
if upCase == 1
let res = tolower(res)
elseif upCase == 2
let res = toupper(res)
elseif upCase == 3
let res = substitute(res, '.*', '\L\u&', '')
endif
endif
return res
" execute "normal! ciw" . res
"call setline(line('.'), strBefore . res . strAfter)
endfunction
"获取字符串的大小写情况
"1为小写
"2为大写
"3为首字母大写
"0为其他情况(strUpper)
function! hy_string#get#upperCase(str) abort
if a:str !~ '\a' "没字母
return 0
elseif a:str ==# tolower(a:str)
return 1
elseif a:str ==# toupper(a:str)
return 2
elseif a:str =~# '\v^\u\l*$'
return 3
else
return 0
endif
endfunction
"abcUp转成 ['abc', 'Up']
function! hy_string#split#byUpper(str) abort
let char = '!'
let s = substitute(a:str, '\A', char.'&', 'g') "转换非字母
let s = substitute(s, '\v\C[A-Z\W]', char.'&', 'g') "大写字母前增加符号用来 split
if strcharpart(s, 0, 1) == char | let s = strcharpart(s, 1) | endif
return split(s, char)
endfunction