├── .gitignore ├── README.md └── plugin └── bx_vimim_dict.vim /.gitignore: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Author: XuanJun 3 | # Email: idxuanjun@qq.com 4 | # Blog: http://blog.csdn.net/idxuanjun 5 | # Version: 0.0.1 6 | # LastChange: 2013-11-16 7 | # Desc: Blog的git忽略文件配置 8 | #------------------------------------------------------------------------------ 9 | 10 | #----------------------------------------------------------------------------- 11 | # 忽略样例 12 | #----------------------------------------------------------------------------- 13 | ##忽略掉所有文件名是 foo.txt的文件 14 | #foo.txt 15 | ##忽略所有生成的 html文件, 16 | #*.html 17 | ##foo.html是手工维护的,所以例外 18 | #!foo.html 19 | ##忽略所有.o和 .a文件 20 | #*.[oa] 21 | ##忽略foo目录 22 | #foo/ 23 | ##忽略所有foo.txt以外文件. 24 | #!foo.txt 25 | 26 | 27 | #----------------------------------------------------------------------------- 28 | # 忽略文件配置 29 | #----------------------------------------------------------------------------- 30 | # 忽略所有Vim生成的临时交换文件, 31 | *.swp 32 | tags 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | >====================================================================== 2 | > FileName: README.md 3 | > Desc: Vim 字典输入 4 | > 插件编码参考源自[vimim-wubi](http://code.google.com/p/vimim-wubi) 5 | > Author: Xuan Jun (idxuanjun@gmail.com) 6 | > Link: http://idxuanjun.github.io 7 | > Version: 0.1.0 8 | > LastChange: 2014-05-01 21:04:28 9 | > History: 10 | >====================================================================== 11 | 12 | Vim 字典输入 13 | ============ 14 | 15 | 插件说明 16 | -------- 17 | 18 | 吐槽一下,Vim 对非字母输入的用户来说太糟心了,让行云流水的输入变得磕磕碰碰的异常难受。曾经停用了两次 Vim 的使用,又舍不得捡了回来,输入法是停用最大的原因,很有些鸡肋的感觉。就算你的英文好也麻烦的很,总不能你写的都是代码和英文文档吧。不管如何,在我的周围里需要使用中文的机会太多了…… 19 | 20 | 受到 VimIM 和 VimIM-wubi 的启发,最近在码能在 Vim 里使用的输入法,直接用 vim-script 编写。我是用“小鹤双拼输入法”的,VimIM 太麻烦,什么云输入之类的不适合我,作者又很长时间不更新了,有些小 BUG 因为功能太繁杂修改起来也较麻烦,想着干脆自己改造个适合自己的,哈哈,自己动手,丰衣足食嘛。以字词输入为重点,类似五笔输入,不考虑联想,用字典方式为主体架构。简单来说,就是输入字母,查找字典输出,输出什么都可以自己定义。 21 | 22 | 如果有同样需求的可以试用,欢迎多提宝贵意见哈:) 23 | 24 | #### 附注: 25 | 26 | * 默认使用小鹤双拼,如果需要使用五笔,请设置: 27 | 28 | let g:bx_im_wubi_used = 1 29 | 30 | * 程序自带的是小鹤双拼和五笔码表,你也可以改成自己习惯的码表,只要按照 [a~z] 的顺序排列好,同时设置 g:bx_im_charfirst=字母 [a~z] 在码表文件中的开始行号即可。例: 31 | 32 | let g:bx_im_charfirst=[1,234,...] 33 | 34 | 更新历史 35 | -------- 36 | 37 | 2014-04-24: 38 | 39 | * 程序已初步调试完成,进入试用阶段。 40 | 41 | 插件安装 42 | -------- 43 | 44 | * 使用插件管理器(Vundle):增加配置语句 Plugin 'idxuanjun/bx_vimim_dict' 45 | * 手工下载:[Github](https://github.com/idxuanjun/bx_vimim_dict) 。点击右下角“Download ZIP”,解压后把 bx_vimim_dict.vim 和字典文件 bx_vimim_*.txt 放到 vim 的 plugin 目录下即可。 46 | 47 | 使用说明 48 | -------- 49 | 50 | * 中英文输入切换:插入模式下使用 CTRL-L 51 | * 中英文标点切换:插入模式下使用 CTRL-\ 52 | * 空格输入中文,回车输入原英文字母 53 | * 最多四键输入,Ctrl+N、Ctrl+P 上下选择中文 54 | -------------------------------------------------------------------------------- /plugin/bx_vimim_dict.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " FileName: bx_vimim_dict.vim 3 | " Desc: 通过录入编码输出字典对应的信息 4 | " Author: Xuan Jun (idxuanjun@gmail.com) 5 | " License: GNU Lesser General Public License 6 | " Link: http://idxuanjun.github.io 7 | " Version: 0.1.0 8 | " LastChange: 2014-05-01 21:02:03 9 | " History: 10 | " 2014-04-24:程序已初步调试完成,进入试用阶段; 11 | "====================================================================== 12 | 13 | " 最多四键输入, 上下选择中文 14 | " 中英文输入切换:插入模式下使用 CTRL-L 15 | " 中英文标点切换:插入模式下使用 CTRL-\ 16 | " 空格输入中文,回车输入原英文字母 17 | " 18 | " 主要功能函数是补全函数 CVimIM_Dict() 19 | " 读取码表及匹配码表由 GetTable() 和 GetMatchFrom 完成 20 | " 然后还有设置 行为的 Smart 函数 21 | " 剩下的就是用来切换状态和设置 map 的函数 22 | " 23 | " 标点上字的功能, 涉及 map 及 unmap ,要动三个地方 24 | " 第一个是 MapChinesePunc() 设置中文标点上字. 25 | " 第二个是 UnMapChinesePunc() 设置英文标点上字. 26 | " 第三个是 Exit() unmap 所有的标点要映射. 27 | " 28 | if exists("b:loaded_bx_vimim_dict") || &cp || v:version < 700 29 | finish 30 | endif 31 | let b:loaded_bx_vimim_dict = 1 32 | scriptencoding utf-8 33 | 34 | " 是否使用五笔 35 | if exists('g:bx_im_wubi_used') && g:bx_im_wubi_used 36 | let g:bx_im_code_fn = 'bx_vimim_wubi.txt' 37 | let g:bm_im_charfirst = [1, 3477, 5016, 6371, 9569, 11098, 14620, 18428, 19911, 23828, 26116, 28500, 30475, 32402, 34864, 36276, 38711, 42226, 46442, 49453, 53687, 57072, 58912, 62805, 65013] 38 | else 39 | let g:bx_im_code_fn = 'bx_vimim_xiaohe.txt' 40 | let g:bm_im_charfirst = [12, 525, 3164, 4305, 7039, 7395, 8945, 11224, 13796, 15856, 18618, 20099, 22618, 24574, 25849, 25922, 27358, 29211, 30292, 31529, 33781, 36378, 38819, 40376, 42911, 46104] 41 | endif 42 | 43 | let s:path = expand(":p:h") . "/" 44 | inoremap Toggle() 45 | 46 | function CVimIM_Dict(findstart, keyboard) 47 | "补全函数 48 | "首先必须要返回一个起始点, 从超始点到当前光标处, 即是需要 49 | "匹配的字符. 50 | "返回的结果, 会替换从起始点到当前光标处的字符. 51 | if a:findstart 52 | "主要通过 s:typeLen 来控制 这些键的行为 53 | "s:typeLen 在 Init() 中定义. 54 | "因为最多只能输入4码, 所以在输入的过程中, 等这些键的 55 | "行为不是不变的. 56 | "let position = getpos('.') 57 | let columnNum = col('.') - 1 58 | let start = columnNum - s:typeLen 59 | return start 60 | else 61 | "读取码表的操作在 Init() 函数中, 62 | "匹配码表的操作在 AnyKey() 函数中. 63 | if s:matchFrom < 0 64 | return '' 65 | else 66 | "有匹配的情况下, 做扩展的预匹配 67 | "扩展匹配的一个标准是, 词条平均为9条, 即再扩展8条词条 68 | let res = [] 69 | let tableLen = len(g:bx_im_table) 70 | if s:typeLen < 2 71 | "1码的情况, 直接扩展到2码, 直接往后多匹配5条 72 | for i in range(5) 73 | if s:matchFrom + i < tableLen 74 | let res = extend(res, split(g:bx_im_table[s:matchFrom + i])[1:]) 75 | endif 76 | endfor 77 | elseif s:typeLen < 3 78 | "2码情况, 直接扩展到3码, 直接往后多匹配6条 79 | for i in range(6) 80 | if s:matchFrom + i < tableLen 81 | let res = extend(res, split(g:bx_im_table[s:matchFrom + i])[1:]) 82 | endif 83 | endfor 84 | elseif s:typeLen < 4 85 | "3码的情况复杂一点, 最多往后多匹配6条, 86 | "如果6条内同前3码的匹配不足, 则直接返回. 87 | for i in range(6) 88 | if s:matchFrom + i < tableLen 89 | let nowLine = g:bx_im_table[s:matchFrom + i] 90 | let res = extend(res, split(nowLine)[1:]) 91 | if s:matchFrom + i + 1 >= tableLen || g:bx_im_table[s:matchFrom + i + 1][:2] != nowLine[:2] 92 | break 93 | endif 94 | endif 95 | endfor 96 | elseif s:typeLen < 5 97 | "4码的情况不用扩展 98 | let res = extend(res, split(g:bx_im_table[s:matchFrom])[1:]) 99 | endif 100 | return res 101 | endif 102 | endif 103 | endfunction 104 | 105 | function s:GetTable() 106 | "读取码表 107 | let tableFile = s:path . g:bx_im_code_fn 108 | try 109 | let table = readfile(tableFile) 110 | catch /E484:/ 111 | echo 'Counld not open the table file `' . tableFile . '`' 112 | endtry 113 | return table 114 | endfunction 115 | 116 | function s:GetMatchFrom(keyboard) 117 | "把参数 keyboard 拿到 g:bx_im_table 去匹配,返回字典内的行 118 | let patterns = '^' . a:keyboard 119 | let bm_im_charfirstIndex = char2nr(a:keyboard[0]) - 97 120 | let keyboardLen = len(a:keyboard) 121 | 122 | if keyboardLen < 1 123 | return -1 124 | elseif keyboardLen < 2 125 | "1码直接取存好的各字母起始行 126 | return g:bm_im_charfirst[bm_im_charfirstIndex]-1 127 | elseif keyboardLen < 3 128 | "2码从头字母的起始行开始匹配 129 | return match(g:bx_im_table, patterns, g:bm_im_charfirst[bm_im_charfirstIndex]-1) 130 | elseif keyboardLen < 4 131 | "3码从上一个匹配行(2码或4码)开始匹配. 132 | if s:matchFrom > 0 133 | "从2码过来的话, 直接用2码的结果 134 | return match(g:bx_im_table, patterns, s:matchFrom) 135 | else 136 | "用从4码过来的话, 只能重新查了. 137 | return match(g:bx_im_table, patterns, g:bm_im_charfirst[bm_im_charfirstIndex] - 1) 138 | endif 139 | elseif keyboardLen < 5 140 | "4码从上一个匹配行(3码)开始匹配, 如果3码没有匹配直接返回-1 141 | if s:matchFrom < 0 142 | return -1 143 | else 144 | return match(g:bx_im_table, patterns, s:matchFrom) 145 | endif 146 | endfunction 147 | 148 | function s:MapAnyKeys() 149 | inoremap a a=AnyKey('a') 150 | inoremap b b=AnyKey('b') 151 | inoremap c c=AnyKey('c') 152 | inoremap d d=AnyKey('d') 153 | inoremap e e=AnyKey('e') 154 | inoremap f f=AnyKey('f') 155 | inoremap g g=AnyKey('g') 156 | inoremap h h=AnyKey('h') 157 | inoremap i i=AnyKey('i') 158 | inoremap j j=AnyKey('j') 159 | inoremap k k=AnyKey('k') 160 | inoremap l l=AnyKey('l') 161 | inoremap m m=AnyKey('m') 162 | inoremap n n=AnyKey('n') 163 | inoremap o o=AnyKey('o') 164 | inoremap p p=AnyKey('p') 165 | inoremap q q=AnyKey('q') 166 | inoremap r r=AnyKey('r') 167 | inoremap s s=AnyKey('s') 168 | inoremap t t=AnyKey('t') 169 | inoremap u u=AnyKey('u') 170 | inoremap v v=AnyKey('v') 171 | inoremap w w=AnyKey('w') 172 | inoremap x x=AnyKey('x') 173 | inoremap y y=AnyKey('y') 174 | if !exists('g:bx_im_wubi_used') || g:bx_im_wubi_used == 0 175 | inoremap z z=AnyKey('z') 176 | endif 177 | endfunction 178 | 179 | function s:UnMapAnyKeys() 180 | iunmap a 181 | iunmap b 182 | iunmap c 183 | iunmap d 184 | iunmap e 185 | iunmap f 186 | iunmap g 187 | iunmap h 188 | iunmap i 189 | iunmap j 190 | iunmap k 191 | iunmap l 192 | iunmap m 193 | iunmap n 194 | iunmap o 195 | iunmap p 196 | iunmap q 197 | iunmap r 198 | iunmap s 199 | iunmap t 200 | iunmap u 201 | iunmap v 202 | iunmap w 203 | iunmap x 204 | iunmap y 205 | if !exists('g:bx_im_wubi_used') || g:bx_im_wubi_used == 0 206 | iunmap z 207 | endif 208 | endfunction 209 | 210 | function Toggle() 211 | "切换中英文状态 212 | if !exists('b:chineseMode') 213 | let b:chineseMode = 0 214 | endif 215 | if b:chineseMode < 1 216 | call s:Init() 217 | elseif b:chineseMode > 0 218 | call s:Exit() 219 | endif 220 | "不加空格的话,会出现光标退到第一列的事件(第一次到一个新行,且前面有缩进) 221 | let WTF = "\\\:redraws\" 222 | silent!exe 'silent!return "' . WTF . '"' 223 | endfunction 224 | 225 | function s:Init() 226 | " 初始化函数, 要设置需要的一些变量 227 | " 在更改环境参数的时候, 先把之前的环境参数备份, 以便在切换到 228 | " 英文状态时还原. 229 | " 此函数还会设置相关的 map 230 | " 备份并重新指定 231 | " 插入模式补全 CTRL-X CTRL-U 使用的函数 232 | let b:save_completefunc = &completefunc 233 | let &l:completefunc = 'CVimIM_Dict' 234 | " 备份并重新指定 235 | " 插入模式补全使用的选项 236 | " menu 使用弹出菜单来显示可能的补全。只有匹配多于一个且有足够的颜 237 | " 色时才显示该菜单。|ins-completion-menu| 238 | " menuone 即使只有一个匹配,也使用弹出菜单。可用于匹配有附加信息的情 239 | " 况,例如,它来自的文件。 240 | " longest 只插入匹配的最长公共文本。如果显示菜单,用 CTRL-L 来插入更 241 | " 多的字符。是否忽略大小写取决于补全的类型。缓冲区文本使用 242 | " 'ignorecase' 选项。 243 | " preview 在预览窗口里显示当前选择的补全的额外信息。只能和 "menu" 或 244 | " "menuone" 搭配使用。 245 | let b:save_completeopt = &completeopt 246 | let &l:completeopt = 'menuone' 247 | " 备份并重新指定 248 | " 插入模式补全使用的选项 249 | " 插入模式里使用 :lmap 还是输入方法 (IM)。合法的值是: 250 | " 0 :lmap 关闭而 IM 关闭 251 | " 1 :lmap 打开而 IM 关闭 252 | " 2 :lmap 关闭而 IM 打开 253 | let b:save_iminsert = &iminsert 254 | let &l:iminsert = 1 255 | " 备份并重新指定 256 | " 决定用于插入模式补全的弹出菜单显示项目的最大数目。 257 | " 如果为零,有多少空间就用多少。 258 | let b:save_pumheight = &pumheight 259 | let &l:pumheight = 9 260 | highlight! lCursor guifg=bg guibg=green 261 | " === 下面的我不懂什么意思啊 262 | " 备份并重新指定 263 | " 单字符标志位的序列。每个字符的存在指示一种 vi 兼容的行为。 264 | " 可用于改变常见或被认为是更好的 vi 不兼容的行为。 265 | let b:save_cpo = &cpo 266 | set cpo&vim 267 | " 备份并重新指定 268 | " 执行宏、寄存器和其它不通过输入的命令时屏幕会不会重画。 269 | " 另外,窗口标题的刷新是否也被推迟。 270 | let b:save_lazyredraw = &lazyredraw 271 | set nolazyredraw 272 | " 备份并重新指定 273 | " 将 Vim 切换到粘贴模式。可用于从一个窗口剪切或复制文本并粘贴到 Vim。 274 | " 它的使用会避免一些意想不到的效果。 275 | let b:save_paste = &paste 276 | set nopaste 277 | " ========== 278 | if !exists('g:bx_im_table') 279 | let g:bx_im_table = s:GetTable() 280 | endif 281 | if !exists('b:chinesePunc') 282 | " 标点的状态要在中英文间保持 283 | let b:chinesePunc = 1 284 | "let b:chinesePunc = 0 285 | endif 286 | if b:chinesePunc > 0 287 | call s:MapChinesePunc() 288 | else 289 | call s:UnMapChinesePunc() 290 | endif 291 | let s:typeLen = 0 292 | let b:chineseMode = 1 293 | call s:MapAnyKeys() 294 | " map 一些特殊的键 295 | inoremap =SmartSpace() 296 | inoremap =SmartBack() 297 | inoremap =SmartEnter() 298 | inoremap =ToggleChinesePunc() 299 | inoremap =RZ() 300 | inoremap =RZ() 301 | " 设置弹出菜单的彩色 302 | highlight! link PmenuSel MatchParen 303 | highlight! link Pmenu StatusLine 304 | " highlight! PmenuSbar NONE 305 | highlight! link PmenuThumb DiffAdd 306 | return '' 307 | endfunction 308 | 309 | function s:Exit() 310 | " 退出中文输入状态调用此函数, 311 | " 它会还原以前的环境变量, 同时把一些变量设置成默认, 312 | " 它还会 unmap 一些映射. 313 | " 还原环境变量设置 314 | let &l:completeopt = b:save_completeopt 315 | let &l:completefunc = b:save_completefunc 316 | let &l:iminsert = b:save_iminsert 317 | let &l:pumheight = b:save_pumheight 318 | let &l:cpo = b:save_cpo 319 | let &l:lazyredraw = b:save_lazyredraw 320 | let &l:paste = b:save_paste 321 | " 还原光标彩色 322 | highlight! ICursor None 323 | " 还原弹出菜单彩色 324 | highlight! link PmenuSel PmenuSel 325 | highlight! link Pmenu Pmenu 326 | "highlight! PmenuSbar NONE 327 | highlight! link PmenuThumb PmenuThumb 328 | " 还原自身的一些变量 329 | let s:typeLen = 0 330 | "let b:chinesePunc = 0 331 | let b:chineseMode = 0 332 | " 还原 [a-z] 的 map 333 | call s:UnMapAnyKeys() 334 | " 还原特殊键的 map 335 | iunmap 336 | iunmap 337 | iunmap 338 | iunmap 339 | iunmap 340 | iunmap 341 | " 还原标点的 map 342 | iunmap , 343 | iunmap . 344 | iunmap ; 345 | iunmap : 346 | iunmap ? 347 | iunmap \ 348 | iunmap / 349 | iunmap ! 350 | iunmap @ 351 | iunmap ^ 352 | iunmap _ 353 | iunmap # 354 | iunmap % 355 | iunmap $ 356 | iunmap ` 357 | iunmap ~ 358 | iunmap { 359 | iunmap } 360 | iunmap < 361 | iunmap > 362 | iunmap ( 363 | iunmap ) 364 | iunmap ' 365 | iunmap " 366 | return '' 367 | endfunction 368 | 369 | function AnyKey(key) 370 | "[a-z]在输入过程中的行为 371 | let s:typeLen += 1 372 | if s:typeLen > 1 373 | "考虑在按了 后继续输入的情况 374 | "如果前一个字符是中文, 则无法再继续匹配, 处理这种情况. 375 | let columnNum = col('.') 376 | let charBefore = getline('.')[columnNum - 3] 377 | if charBefore !~# '\l' 378 | "虽然 \L 中有一个`z`, 但这不会有什么问题 379 | let s:typeLen = 1 380 | call s:RefreshMatch() 381 | let temp = "\\\\\" 382 | endif 383 | silent!exe 'silent!return "' . temp . '"' 384 | endif 385 | if s:typeLen == 5 386 | "限制4码输入在这里实现. 387 | "要考虑前4码是否有匹配两种情况. 388 | let p = getpos('.') 389 | call setpos('.', [p[0], p[1], p[2] - 1, p[3]]) 390 | let s:typeLen -= 1 391 | call s:RefreshMatch() 392 | "前4码肯定有匹配, 则先保存前4码的第一个匹配, 用这个匹配去 393 | "代替前4码, 再重新匹配第5码 394 | let word = split(g:bx_im_table[s:matchFrom])[1] 395 | "这里不能是四个, 不知道为什么! 396 | let temp = "\\\\\" . word . "\\\\\" 397 | let s:matchFrom = s:GetMatchFrom(a:key) 398 | let s:typeLen = 1 399 | silent!exe 'silent!return "' . temp . '"' 400 | endif 401 | call s:RefreshMatch() 402 | if s:matchFrom < 0 403 | "不能匹配的情况, 只可能出现在3码或4码 404 | "是否要实现如果3码无匹配则不能输入4码呢? 405 | "TODO: 3码无匹配则不能输入4码, 或无匹配自动删除. 406 | let temp = "\\\\\" 407 | let s:typeLen -= 1 408 | "要重新定位光标才正确取码 409 | let p = getpos('.') 410 | call setpos('.', [p[0], p[1], p[2] - 1, p[3]]) 411 | call s:RefreshMatch() 412 | else 413 | let temp = "\\\\" 414 | endif 415 | silent!exe 'silent!return "' . temp . '"' 416 | endfunction 417 | 418 | function s:RefreshMatch() 419 | "刷新匹配列表. 420 | "在更新计数器 s:typeLen 时注意考虑是否要调用. 421 | "考虑 这些行为时考虑是否要调用. 422 | "let position = getpos('.') 423 | let lineNum = line('.') 424 | let columnNum = col('.') - 1 425 | let temstr = getline(lineNum) 426 | let from = columnNum - s:typeLen 427 | let to = columnNum - 1 428 | let s:matchFrom = s:GetMatchFrom(temstr[from : to]) 429 | endfunction 430 | 431 | function SmartSpace() 432 | "在输入过程中的行为 433 | let space = ' ' 434 | if pumvisible() 435 | let space = "\" 436 | elseif s:typeLen == 1 437 | let space = "\" 438 | elseif s:typeLen == 2 439 | let space = "\\" 440 | elseif s:typeLen == 3 441 | let space = "\\\" 442 | elseif s:typeLen == 4 443 | let space = "\\\\" 444 | endif 445 | let s:typeLen = 0 446 | silent!exe 'silent!return "' . space . '"' 447 | endfunction 448 | 449 | function SmartEnter() 450 | "在输入过程中的行为 451 | if pumvisible() 452 | "如果有匹配列表, 则上屏第一个匹配 453 | let enter = "\" 454 | "如果没有匹配列表, 则删除已经输入的废码 455 | "现在不可能出现没有匹配的情况了 456 | else 457 | "完全没事干了, 再换行吧 458 | let enter = "\" 459 | endif 460 | let s:typeLen = 0 461 | silent!exe 'silent!return "' . enter . '"' 462 | endfunction 463 | 464 | function SmartBack() 465 | "在输入过程中的行为 466 | let bs = "\" 467 | if s:typeLen > 1 468 | "只有1码时, 不要 '自作聪明' 469 | let s:typeLen -= 1 470 | "s:typeLen 变了, 要重新定位光标并刷新匹配结果 471 | let p = getpos('.') 472 | "存在按了 后, 是删除一个中文字的情况, 473 | "这种情况如果执行 s:RefreshMatch() 会出现越界错误, 474 | "因为它前面的字符是一个中文字, 无法拿去匹配码表的. 475 | if getline('.')[p[2] - 3] !~# '\l' 476 | let s:typeLen = 0 477 | let s:matchFrom = -1 478 | let bs = bs . "\\" 479 | else 480 | call setpos('.', [p[0], p[1], p[2] - 1, p[3]]) 481 | call s:RefreshMatch() 482 | let bs = "\\\\\" 483 | endif 484 | else 485 | "只可能是 s:typeLen == 0 || s:typeLen == 1 486 | "不管是哪种, 按了 匹配列表都应该清空 487 | let s:typeLen = 0 488 | let s:matchFrom = -1 489 | endif 490 | silent!exe 'silent!return "' . bs . '"' 491 | endfunction 492 | 493 | function s:MapChinesePunc() 494 | "映射中文标点 495 | let b:chinesePunc = 1 496 | inoremap , =PuncIn(), 497 | inoremap . =PuncIn()。 498 | inoremap ; =PuncIn(); 499 | inoremap : =PuncIn(): 500 | inoremap ? =PuncIn()? 501 | inoremap \ =PuncIn()、 502 | inoremap / =PuncIn()/ 503 | inoremap ! =PuncIn()! 504 | inoremap @ =PuncIn()・ 505 | inoremap ^ =PuncIn()…… 506 | inoremap _ =PuncIn()—— 507 | inoremap # =PuncIn()# 508 | inoremap % =PuncIn()% 509 | inoremap $ =PuncIn()¥ 510 | inoremap ` =PuncIn()` 511 | inoremap ~ =PuncIn()~ 512 | inoremap < =PuncIn()《 513 | inoremap > =PuncIn()》 514 | inoremap ( =PuncIn()( 515 | inoremap ) =PuncIn()) 516 | inoremap { =PuncIn()『 517 | inoremap } =PuncIn()』 518 | inoremap ' =PuncIn()=ToggleChineseQuote("'") 519 | inoremap " =PuncIn()=ToggleChineseQuote('"') 520 | endfunction 521 | 522 | function s:UnMapChinesePunc() 523 | " 解除映射中文标点 524 | let b:chinesePunc = 0 525 | inoremap , =PuncIn(), 526 | inoremap . =PuncIn(). 527 | inoremap ; =PuncIn(); 528 | inoremap : =PuncIn(): 529 | inoremap ? =PuncIn()? 530 | inoremap \ =PuncIn()\ 531 | inoremap / =PuncIn()/ 532 | inoremap ! =PuncIn()! 533 | inoremap @ =PuncIn()@ 534 | inoremap ^ =PuncIn()^ 535 | inoremap _ =PuncIn()_ 536 | inoremap # =PuncIn()# 537 | inoremap % =PuncIn()% 538 | inoremap $ =PuncIn()$ 539 | inoremap ` =PuncIn()` 540 | inoremap ~ =PuncIn()~ 541 | inoremap < =PuncIn()< 542 | inoremap > =PuncIn()> 543 | inoremap ( =PuncIn()( 544 | inoremap ) =PuncIn()) 545 | inoremap { =PuncIn(){ 546 | inoremap } =PuncIn()} 547 | inoremap ' =PuncIn()' 548 | inoremap " =PuncIn()" 549 | endfunction 550 | 551 | function ToggleChinesePunc() 552 | "中英文标点状态的切换 553 | if b:chinesePunc > 0 554 | call s:UnMapChinesePunc() 555 | else 556 | call s:MapChinesePunc() 557 | endif 558 | return '' 559 | endfunction 560 | 561 | function ToggleChineseQuote(mark) 562 | " 中文引号成对切换 563 | if a:mark == "'" 564 | if !exists('b:singleMode') 565 | let b:singleMode = 0 566 | endif 567 | let b:singleMode = abs(b:singleMode - 1) 568 | return b:singleMode == 1 ? "‘" : "’" 569 | elseif a:mark == '"' 570 | if !exists('b:doubleMode') 571 | let b:doubleMode = 0 572 | endif 573 | let b:doubleMode = abs(b:doubleMode - 1) 574 | return b:doubleMode == 1 ? "“" : "”" 575 | endif 576 | endfunction 577 | 578 | function s:WTF() 579 | " ... 580 | let WTF = "\a" 581 | silent!exe 'silent!return "' . WTF . '"' 582 | endfunction 583 | 584 | function PuncIn() 585 | let s:typeLen = 0 586 | if pumvisible() 587 | let puncIn = "\" 588 | else 589 | let puncIn = '' 590 | endif 591 | silent!exe 'silent!return "' . puncIn . '"' 592 | endfunction 593 | 594 | function RZ() 595 | let s:typeLen = 0 596 | let s:matchFrom = -1 597 | return '' 598 | endfunction 599 | 600 | function s:Debug(var) 601 | let a = inputdialog(a:var) 602 | endfunction 603 | --------------------------------------------------------------------------------