-
Notifications
You must be signed in to change notification settings - Fork 3
/
VimLite.vmb
20321 lines (17935 loc) · 669 KB
/
VimLite.vmb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
" Vimball Archiver by Charles E. Campbell, Jr., Ph.D.
UseVimball
finish
syntax/vlworkspace.vim [[[1
82
" Description: Vim syntax file for VimLite workspace buffer
" Maintainer: fanhe <fanhed@163.com>
" License: This file is placed in the public domain
" Create: 2011-07-19
" Last Change: 2011-07-19
" 允许装载自定义语法文件
if exists("b:current_syntax")
finish
endif
" 树结构标志
syn match VLWTreeLead '|'
syn match VLWTreeLead '`'
" 可展开和可折叠的标志
syn match VLWClosable '\V\[|`]~'hs=s+1 contains=VLWTreeLead
syn match VLWOpenable '\V\[|`]+'hs=s+1 contains=VLWTreeLead
" 文件前缀标志
syn match VLWFilePre '[|`]-'hs=s+1 contains=VLWTreeLead
" 忽略的文件
syn match VLWIgnoredFile '[|`]#.\+'hs=s+1 contains=VLWTreeLead
" 工作空间名字只能由 [a-zA-Z_ +-.] 组成
syn match VLWorkspace '^[a-zA-Z0-9_ +-.]\+$'
syn match VLWProject '^[|`][+~].\+'
\contains=VLWOpenable,VLWClosable,VLWTreeLead
syn match VLWVirtualDirectory '\s[|`][+~].\+$'hs=s+3
\contains=VLWOpenable,VLWClosable,VLWTreeLead
" 帮助信息
syn match VLWFlag '\~'
syn match VLWHelpKey '" \{1,2\}[^ ]*:'hs=s+2,he=e-1
syn match VLWHelpKey '" \{1,2\}[^ ]*,'hs=s+2,he=e-1
syn match VLWHelpTitle '" .*\~'hs=s+2,he=e-1 contains=VLWFlag
syn match VLWHelp '^".*' contains=VLWHelpKey,VLWHelpTitle,VLWFlag
if exists('g:VLWorkspaceHighlightSourceFile') && g:VLWorkspaceHighlightSourceFile
" c/c++ 源文件、头文件
syn match VLWCSource '\V\c\[|`]-\.\+.c\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCHeader '\V\c\[|`]-\.\+.h\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCppSource '\V\c\[|`]-\.\+.cpp\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCppSource '\V\c\[|`]-\.\+.c++\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCppSource '\V\c\[|`]-\.\+.cxx\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCppSource '\V\c\[|`]-\.\+.cc\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
syn match VLWCppHeader '\V\c\[|`]-\.\+.hpp\$'hs=s+2
\contains=VLWFilePre,VLWTreeLead
hi def link VLWCSource Function
hi def link VLWCHeader Constant
hi def link VLWCppSource VLWCSource
hi def link VLWCppHeader VLWCHeader
endif
hi def link VLWorkspace PreProc
hi def link VLWProject Type
hi def link VLWVirtualDirectory Statement
hi def link VLWTreeLead Special
hi def link VLWFilePre Linenr
hi def link VLWIgnoredFile Ignore
hi def link VLWClosable VLWFilePre
hi def link VLWOpenable Title
hi def link VLWFlag Ignore
hi def link VLWHelp Comment
hi def link VLWHelpKey Identifier
hi def link VLWHelpCommand Identifier
hi def link VLWHelpTitle Title
plugin/vpyclewn.vim [[[1
17
" pyclewn run time file
" Maintainer: <xdegaye at users dot sourceforge dot net>
"
" Configure VIM to be used with pyclewn and netbeans
"
" pyclewn version
let g:vpyclewn_version = "pyclewn-1.6.py2"
" enable balloon_eval
if has("balloon_eval")
set ballooneval
set balloondelay=100
endif
" The 'Pyclewn' command starts pyclewn and vim netbeans interface.
command -nargs=* -complete=file VPyclewn call vpyclewn#StartClewn(<f-args>)
plugin/VLCalltips.vim [[[1
335
" Description: vim script for display function calltips
" Maintainer: fanhe <fanhed@163.com>
" Create: 2011 Jun 18
" License: GPLv2
if exists('g:loaded_VLCalltips')
finish
endif
let g:loaded_VLCalltips = 1
" 这个插件的类
let s:VLCalltips = {}
let s:VLCalltips.keepCursor = 1 " 不自动结束没有参数的函数 calltips
function! s:InitVariable(varName, defaultVal) "{{{2
if !exists(a:varName)
let {a:varName} = a:defaultVal
return 1
endif
return 0
endfunction
"}}}
function! g:InitVLCalltips() "{{{1
call s:InitVariable('g:VLCalltips_IndicateArgument', 1)
call s:InitVariable('g:VLCalltips_EnableSyntaxTest', 0)
call s:InitVariable('g:VLCalltips_DispCalltipsKey', '<A-p>')
call s:InitVariable('g:VLCalltips_NextCalltipsKey', '<A-j>')
call s:InitVariable('g:VLCalltips_PrevCalltipsKey', '<A-k>')
"exec 'inoremap <silent> <buffer> ' . g:VLCalltips_DispCalltipsKey
"\. ' <C-r>=<SID>Test()<CR>'
exec 'inoremap <silent> <buffer> ' . g:VLCalltips_DispCalltipsKey
\. ' <C-r>=g:VLCalltips_Start()<CR>'
exec 'inoremap <silent> <buffer> ' . g:VLCalltips_NextCalltipsKey
\. ' <C-r>=<SID>HighlightNextCalltips()<CR>'
exec 'inoremap <silent> <buffer> ' . g:VLCalltips_PrevCalltipsKey
\. ' <C-r>=<SID>HighlightPrevCalltips()<CR>'
endfunction
"}}}
let s:lCalltips = [] "保存函数原型或者原型形参信息的列表(C++ 重载)
let s:nCurIndex = 0 "当前函数原型的索引
let s:nArgIndex = 0 "当前形参索引, 0 开始
function! s:Test()
let lLi = []
call add(lLi, 'int printf(const char *fmt, ...)')
call add(lLi, 'int printf(const char *fmt, int a, int b)')
call g:DisplayVLCalltips(lLi, 0)
return ''
endfunction
" 接口函数,注册回调函数
" 回调函数必须接受一个参数,并且必须返回一个列表,项目位函数的完整声明(如上)
function! g:VLCalltips_RegisterCallback(func, data) "{{{2
let Cbk = a:func
if type(a:func) == type("")
let Cbk = function(a:func)
endif
let s:VLCalltips.callback = Cbk
let s:VLCalltips.callbackData = a:data
endfunction
function! g:VLCalltips_Start() "{{{2
if !empty(get(s:VLCalltips, 'callback'))
let lCalltips = s:VLCalltips.callback(s:VLCalltips.callbackData)
call g:DisplayVLCalltips(lCalltips, 0)
endif
return ''
endfunction
function! g:VLCalltips_KeepCursor() "{{{2
let s:VLCalltips.keepCursor = 1
endfunction
function! g:VLCalltips_UnkeepCursor() "{{{2
let s:VLCalltips.keepCursor = 0
endfunction
" 接口函数, 用于外部调用
function! g:DisplayVLCalltips(lCalltips, nCurIndex) "{{{2
if empty(a:lCalltips)
return ''
endif
"let bKeepCursor = a:0 > 0 ? a:1 : 0
let bKeepCursor = s:VLCalltips.keepCursor
call s:StopCalltips()
if type(a:lCalltips) == type('')
let s:lCalltips = [a:lCalltips]
let s:nCurIndex = 0
else
let s:lCalltips = copy(a:lCalltips)
let s:nCurIndex = a:nCurIndex
endif
if !empty(s:lCalltips)
augroup DispCalltipsGroup
autocmd!
autocmd CursorMovedI <buffer> call <SID>AutoUpdateCalltips()
autocmd InsertLeave <buffer> call <SID>StopCalltips()
augroup END
"设置必要的选项
let s:bak_showmode = &showmode
let s:bak_ruler = &ruler
let s:bak_cmdheight = &cmdheight
set noshowmode
set noruler
let s:nArgIndex = s:GetArgIndex()
"如果函数无参数, 自动结束
if !bKeepCursor && len(s:lCalltips) == 1
\&& s:lCalltips[0] =~# '(\s*)\|(\s*void\s*)'
call s:StopCalltips()
call search(')', 'Wc')
normal! l
else
call s:DisplayCalltips()
endif
endif
return ''
endfunction
function! s:AutoUpdateCalltips() "{{{2
"函数无参数,自动结束
"if len(s:lCalltips) == 1 && s:lCalltips[0] =~# '()\|(\s*void\s*)'
"call s:StopCalltips()
"call search(')', 'Wc')
"normal! l
"endif
"精确模式
let nIdx = s:GetArgIndex()
if nIdx == -2
"不在括号内, 停止
call s:StopCalltips()
elseif nIdx == -1
"没有找到函数名称, 可能在括号内输入了括号
"TODO: 如果开始位置前于初始化时的开始位置, 必定停止
elseif nIdx >= 0
let s:nArgIndex = nIdx
call s:DisplayCalltips()
endif
return ''
endfunction
function! s:StopCalltips() "{{{2
call filter(s:lCalltips, 0)
let s:nCurIndex = 0
let s:nArgIndex = 0
silent! autocmd! DispCalltipsGroup
if exists('s:bak_showmode')
let &showmode = s:bak_showmode
let &ruler = s:bak_ruler
let &cmdheight = s:bak_cmdheight
unlet s:bak_showmode
unlet s:bak_ruler
unlet s:bak_cmdheight
"目的在于刷新
echo ""
endif
endfunction
function! s:HighlightNextCalltips() "{{{2
let nLen = len(s:lCalltips)
let s:nCurIndex = (s:nCurIndex + 1) % nLen
call s:DisplayCalltips()
return ''
endfunction
function! s:HighlightPrevCalltips() "{{{2
let nLen = len(s:lCalltips)
let s:nCurIndex = (s:nCurIndex - 1 + nLen) % nLen
call s:DisplayCalltips()
return ''
endfunction
function! s:DisplayCalltips() "{{{2
if empty(s:lCalltips)
return ''
endif
let nCalltipsCount = len(s:lCalltips)
let sCurCalltips = s:lCalltips[s:nCurIndex]
let nArgStartIdx = stridx(sCurCalltips, '(') + 1
let nArgEndIdx = strridx(sCurCalltips, ')') - 1
if !g:VLCalltips_IndicateArgument
let sContent = sCurCalltips
\. ' ('. (s:nCurIndex + 1) . '/' . nCalltipsCount . ')'
" 12 很诡异...
let nHeight = len(sContent) / (&columns - 12) + 1
let &cmdheight = nHeight
echohl Type
echo sContent[: nArgStartIdx-1]
echohl SpecialChar
echon sContent[nArgStartIdx : nArgEndIdx]
echohl Type
echon sContent[nArgEndIdx+1 :]
echohl None
return ''
endif
let nHlStartIdx = nArgStartIdx
let i = 0
while i < s:nArgIndex
let nHlStartIdx = stridx(sCurCalltips, ',', nHlStartIdx)
if nHlStartIdx != -1
let nHlStartIdx += 1
else
"指定的参数超过了该函数的参数数量
let nHlStartIdx = nArgEndIdx + 1
break
endif
let i += 1
endwhile
let nHlStopIdx = nArgEndIdx
let nHlStopIdx = stridx(sCurCalltips, ',', nHlStartIdx)
if nHlStopIdx != -1
"vim 的子串索引包括尾端,和 python 不一致!
let nHlStopIdx -= 1
else
"当前参数索引是最后的参数,所以 nHlStopIdx 为 -1
let nHlStopIdx = nArgEndIdx
endif
let sContent = sCurCalltips
\. ' ('. (s:nCurIndex + 1) . '/' . nCalltipsCount . ')'
" 12 很诡异...
let nHeight = len(sContent) / (&columns - 12) + 1
let &cmdheight = nHeight
"处理可变参数
let nVaArgIdx = match(sCurCalltips, '\V...)')
if nVaArgIdx != -1 && nHlStartIdx > nVaArgIdx
"存在可变参数,且参数索引到达最后了,锁定为最后的参数
let nHlStartIdx = nVaArgIdx
endif
echohl Type
echo sContent[: nHlStartIdx-1]
echohl SpecialChar
echon sContent[nHlStartIdx : nHlStopIdx]
echohl Type
echon sContent[nHlStopIdx + 1 :]
echohl None
endfunction
function! s:GetArgIndex() "{{{2
" 精确地确定光标所在位置所属的函数参数索引
" 不在括号内,返回 -2,函数名为空,返回 -1
" 确定函数括号开始的位置
if g:VLCalltips_EnableSyntaxTest
let sSkipExpr = 'synIDattr(synID(line("."), col("."), 0), "name") '
\. '=~? "string\\|character"'
else
let sSkipExpr = ''
endif
let lStartPos = searchpairpos('(', '', ')', 'nWb', sSkipExpr)
" 如果刚好在括号内,加 'c' 参数
let lEndPos = searchpairpos('(', '', ')', 'nWc', sSkipExpr)
let lCurPos = [line('.'), col('.')]
" 不在括号内
if lStartPos[0] == 0 && lStartPos[1] == 0
return -2
else
if !g:VLCalltips_IndicateArgument
return 0
endif
endif
"let lines = getline(lStartPos[0], lEndPos[0])
" 获取函数名称和名称开始的列,暂时只处理 '(' "与函数名称同行的情况,
" 允许之间有空格
" TODO: 处理更复杂的情况: 1.函数名称与 ( 不在同行 2.函数名称前有逗号
let sStartLine = getline(lStartPos[0])
let sFuncName = matchstr(sStartLine[: lStartPos[1]-1], '\w\+\ze\s*($')
let nFuncIdx = match(sStartLine[: lStartPos[1]-1], '\w\+\ze\s*($')
let nArgIdx = -1
if sFuncName != ''
" 计算光标所在的位置所属的函数参数索引(从 0 开始)
let nArgIdx = 0
for nLine in range(lStartPos[0], lCurPos[0])
let sLine = getline(nLine)
let nStart = 0
let nEnd = len(sLine)
if nLine == lCurPos[0]
" 光标所在行
let nEnd = lCurPos[1] - 1 "(a,b|,c)
endif
while nStart < nEnd
let nStart = stridx(sLine, ',', nStart)
if nStart != -1 && nStart < nEnd
" 确保不是字符串里的逗号
if !(g:VLCalltips_EnableSyntaxTest
\&& synIDattr(synID(nLine, nStart + 1, 0),
\ "name") =~? 'string\|character')
let nArgIdx += 1
endif
else
break
endif
let nStart += 1
endwhile
endfor
endif
return nArgIdx
endfunction
" vim:fdm=marker:fen:expandtab:smarttab:fdl=1:
plugin/videm.vim [[[1
17
" Vim Script
" Author: fanhe <fanhed@163.com>
" License: GPLv2
" Create: 2012-08-05
" Change: 2012-08-05
if exists('g:loaded_videm')
finish
endif
let g:loaded_videm = 1
" 命令导出
command! -nargs=? -complete=file VLWorkspaceOpen
\ call videm#wsp#InitWorkspace('<args>')
" vim: fdm=marker fen et sts=4 fdl=1
plugin/VLUtils.vim [[[1
240
" Vim script utilities for VimLite
" Last Change: 2011 Apr 11
" Maintainer: fanhe <fanhed@163.com>
" License: This file is placed in the public domain.
if exists('g:loaded_VLUtils')
finish
endif
let g:loaded_VLUtils = 1
"Function: g:InitVariable(varName, defaultVal) {{{2
"初始化变量
"仅在没有变量定义时才赋值
"Arg: varName: 变量名
"Arg: defaultVal: 默认值
"Return: 1 表示赋值为默认, 否则为 0
function g:InitVariable(varName, defaultVal)
if !exists(a:varName)
let {a:varName} = a:defaultVal
return 1
endif
return 0
endfunction
"Function: g:EchoHl(msg, ...) {{{2
"高亮显示 msg,默认高亮组为 WarningMsg
function g:EchoHl(msg, ...)
let l:hlGroup = 'WarningMsg'
if exists('a:1')
let l:hlGroup = a:1
endif
exec 'echohl ' . l:hlGroup
echo a:msg
echohl None
endfunction
"FUNCTION: g:Exec(cmd) {{{2
"与 exec 命令相同,但是运行时 set eventignore=all
"主要用于“安全”地运行某些命令,例如窗口跳转
function g:Exec(cmd)
let bak = &ei
set eventignore=all
try
exec a:cmd
catch
finally
let &ei = bak
endtry
endfunction
"Function: g:BufInWinCount(bufNumber) 打开指定缓冲区的窗口数目 {{{2
function g:BufInWinCount(bufNumber)
let cnt = 0
let winnum = 1
while 1
let bufnum = winbufnr(winnum)
if bufnum < 0
break
endif
if bufnum ==# a:bufNumber
let cnt = cnt + 1
endif
let winnum = winnum + 1
endwhile
return cnt
endfunction
"FUNCTION: g:IsWindowUsable(winNumber) 判断窗口是否可用 "{{{2
function g:IsWindowUsable(winNumber)
"如果仅有一个窗口打开,即自己是唯一窗口,怎样处理由外层决定
"if winnr("$") == 1
"return 0
"endif
"特殊窗口,如特殊缓冲类型的窗口、预览窗口
let specialWindow = getwinvar(a:winNumber, '&buftype') != ''
\|| getwinvar(a:winNumber, '&previewwindow')
if specialWindow
return 0
endif
"窗口缓冲是否已修改
let modified = getwinvar(a:winNumber, '&modified')
"如果可允许隐藏,则无论缓冲是否修改
if &hidden
return 1
endif
"如果缓冲区没有修改,或者,已修改,但是同时有其他窗口打开着,则表示可用
if !modified || g:BufInWinCount(winbufnr(a:winNumber)) >= 2
return 1
else
return 0
endif
endfunction
"FUNCTION: g:GetFirstUsableWindow() 获取第一个"常规"(非特殊)的窗口 {{{2
"特殊情况:特殊的缓冲区类型、预览缓冲区、已修改的缓冲并且不能隐藏
function g:GetFirstUsableWindow()
let i = 1
while i <= winnr("$")
if g:IsWindowUsable(i)
return i
endif
let i += 1
endwhile
return -1
endfunction
function g:GetMaxWidthWinNr() "{{{2
let i = 1
let nResult = 0
let nMaxWidth = 0
while i <= winnr("$")
let nCurWidth = winwidth(i)
if nCurWidth > nMaxWidth
let nMaxWidth = nCurWidth
let nResult = i
endif
let i += 1
endwhile
return nResult
endfunction
function g:GetMaxHeightWinNr() "{{{2
let i = 1
let nResult = 0
let nMaxHeight = 0
while i <= winnr("$")
let nCurHeight = winheight(i)
if nCurHeight > nMaxHeight
let nMaxHeight = nCurHeight
let nResult = i
endif
let i += 1
endwhile
return nResult
endfunction
function g:NormalizeCmdArg(arg) "{{{2
return substitute(a:arg, ' ', '\\ ', "g")
endfunction
function s:SID() "{{{2
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfunction
function s:GetSFuncref(sFuncName) "{{{2
return function('<SNR>'.s:SID().'_'.a:sFuncName[2:])
endfunction
let g:Timer = {'t1': 0, 't2': 0} "{{{1
function g:Timer.Start() "{{{2
let self.t1 = reltime()
endfunction
function g:Timer.End() "{{{2
let self.t2 = reltime()
endfunction
function g:Timer.EchoMes() "{{{2
echom join(reltime(self.t1, self.t2), '.')
endfunction
function g:Timer.EndEchoMes() "{{{2
call self.End()
call self.EchoMes()
endfunction
function g:EchoSyntaxStack() "{{{2
let names = []
let li = synstack(line("."), col("."))
let li = empty(li) ? [] : li
for id in li
"echo synIDattr(id, "name")
call add(names, synIDattr(id, 'name'))
endfor
echo join(names, ', ')
return ''
endfunction
function g:Progress(n, ...) "{{{2
let n = a:n
if a:0 > 0
let m = a:1
else
let m = 100
endif
let nRange = 10
let nRatio = n * nRange / m
echoh Pmenu
echon repeat(' ', nRatio)
echoh None
echon repeat(' ', nRange - nRatio)
echon printf("%4d%%", n * 100 / m)
redraw
endfunction
function g:GetCmdOutput(sCmd) "{{{2
let bak_lang = v:lang
" 把消息统一为英文
exec ":lan mes en_US.UTF-8"
try
redir => sOutput
silent! exec a:sCmd
catch
" 把错误消息设置为最后的 ':' 后的字符串?
"let v:errmsg = substitute(v:exception, '^[^:]\+:', '', '')
finally
redir END
endtry
exec ":lan mes " . bak_lang
return sOutput
endfunction
" vim:fdm=marker:fen:fdl=1:et:
plugin/VIMClangCC.vim [[[1
1398
" Vim clang code completion plugin
" Author: fanhe <fanhed@163.com>
" License: GPLv2
" Create: 2011-12-16
" Change: 2013-01-23
if !has('python')
echohl ErrorMsg
echom printf("[%s]: Required vim compiled with +python",
\ expand('<sfile>:p'))
echohl None
finish
endif
if exists("g:loaded_VIMClangCC")
finish
endif
let g:loaded_VIMClangCC = 1
" 在 console 跑的 vim 没法拥有这个特性...
let s:has_clientserver = 0
if has('clientserver')
let s:has_clientserver = 1
endif
autocmd FileType c,cpp call VIMClangCodeCompletionInit()
" 标识是否第一次初始化
let s:bFirstInit = 1
let s:dCalltipsData = {}
let s:dCalltipsData.usePrevTags = 0 " 是否使用最近一次的 tags 缓存
" 检查是否支持 noexpand 选项
let s:__temp = &completeopt
let s:has_noexpand = 1
try
set completeopt+=noexpand
catch /.*/
let s:has_noexpand = 0
endtry
let &completeopt = s:__temp
unlet s:__temp
"let g:has_noexpand = s:has_noexpand
let s:has_InsertCharPre = 0
if v:version >= 703 && has('patch196')
let s:has_InsertCharPre = 1
endif
" 关联的文件,一般用于头文件关联源文件
" 在头文件头部和尾部添加的额外的内容,用于修正在头文件时的头文件包含等等问题
" {头文件: {'line': 在关联文件中对应的行(#include), 'filename': 关联文件}, ...}
let g:dRelatedFile = {}
let s:sPluginPath = substitute(expand('<sfile>:p:h'), '\\', '/', 'g')
if has('win32') || has('win64')
let s:sDefaultPyModPath = fnamemodify($VIM . '\vimlite\VimLite', ":p")
else
let s:sDefaultPyModPath = fnamemodify("~/.vimlite/VimLite", ":p")
endif
function! s:InitVariable(varName, defaultVal) "{{{2
if !exists(a:varName)
let {a:varName} = a:defaultVal
return 1
else
return 0
endif
endfunction
"}}}
command! -nargs=0 -bar VIMCCCInitForcibly call <SID>VIMCCCInitForcibly()
" 临时启用选项函数 {{{2
function! s:SetOpts()
let s:bak_cot = &completeopt
if g:VIMCCC_ItemSelectionMode == 0 " 不选择
set completeopt-=menu,longest
set completeopt+=menuone
elseif g:VIMCCC_ItemSelectionMode == 1 " 选择并插入文本
set completeopt-=menuone,longest
set completeopt+=menu
elseif g:VIMCCC_ItemSelectionMode == 2 " 选择但不插入文本
if s:has_noexpand
" 支持 noexpand 就最好了
set completeopt+=noexpand
set completeopt-=longest
else
set completeopt-=menu,longest
set completeopt+=menuone
endif
else
set completeopt-=menu
set completeopt+=menuone,longest
endif
return ''
endfunction
function! s:RestoreOpts()
if exists('s:bak_cot')
let &completeopt = s:bak_cot
unlet s:bak_cot
else
return ""
endif
let sRet = ""
if pumvisible()
if g:VIMCCC_ItemSelectionMode == 0 " 不选择
let sRet = "\<C-p>"
elseif g:VIMCCC_ItemSelectionMode == 1 " 选择并插入文本
let sRet = ""
elseif g:VIMCCC_ItemSelectionMode == 2 " 选择但不插入文本
if !s:has_noexpand
let sRet = "\<C-p>\<Down>"
endif
else
let sRet = "\<Down>"
endif
endif
return sRet
endfunction
function! s:CheckIfSetOpts()
let sLine = getline('.')
let nCol = col('.') - 1
" 若是成员补全,添加 longest
if sLine[nCol-2:] =~ '->' || sLine[nCol-1:] =~ '\.'
\|| sLine[nCol-2:] =~ '::'
call s:SetOpts()
endif
return ''
endfunction
"}}}
function! s:SID() " 获取脚本 ID,这个函数名不能变 {{{2
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfunction
let s:sid = s:SID()
function! s:GetSFuncRef(sFuncName) "获取局部于脚本的函数的引用 {{{2
let sFuncName = a:sFuncName =~ '^s:' ? a:sFuncName[2:] : a:sFuncName
return function('<SNR>'.s:sid.'_'.sFuncName)
endfunction
"}}}
function! s:StartQucikCalltips() "{{{2
let s:dCalltipsData.usePrevTags = 1
call g:VLCalltips_Start()
return ''
endfunction
"}}}
function! s:ShouldComplete() "{{{2
if (getline('.') =~ '#\s*include')
" 写头文件,忽略
return 0
else
" 检测光标所在的位置,如果在注释、双引号、浮点数时,忽略
let nRow = line('.')
let nCol = col('.') - 1 " 是前一列 eg. ->|
if nCol < 1
" TODO: 支持续行的补全
return 0
endif
if g:VIMCCC_EnableSyntaxTest
let lStack = synstack(nRow, nCol)
let lStack = empty(lStack) ? [] : lStack
for nID in lStack
if synIDattr(nID, 'name')
\=~? 'comment\|string\|float\|character'
return 0
endif
endfor
else
" TODO
endif
return 1
endif
endfunction
"}}}
function! s:LaunchCodeCompletion() "{{{2
if s:ShouldComplete()
return "\<C-x>\<C-o>"
else
return ''
endif
endfunction
"}}}
" 触发条件
"
" 触发的情形:
" abcdefg
" ^ 并且离单词起始位置的长度大于或等于触发字符数
"
" 不触发的情形:
" abcdefg
" ^
" 插入模式光标自动命令的上一个状态
" ccrow: 代码完成的行号
" cccol: 代码完成的列号
" base: base
" pumvisible : 0|1
" init: 0|1 起始状态,暂时只有在进入插入模式时初始化
"
" FIXME: 这些状态,连我自己都分不清了...
" 等 7.3.196 使用 InsertCharPre 事件就好了
" InsertCharPre When a character is typed in Insert mode,
" before inserting the char.
" The |v:char| variable indicates the char typed
" and can be changed during the event to insert
" a different character. When |v:char| is set
" to more than one character this text is
" inserted literally.
" It is not allowed to change the text |textlock|.
" The event is not triggered when 'paste' is
" set.
let s:aucm_prev_stat = {}
function! VIMCCCAsyncComplete(charPre) "{{{2
if pumvisible() " 不重复触发
return ''
endif
" InsertCharPre 自动命令用
let sChar = ''
if a:charPre
let sChar = v:char
if sChar !~# '[A-Za-z_0-9]'
return ''
endif
endif
let nTriggerCharCount = g:VIMCCC_TriggerCharCount
let nCol = col('.')
let sLine = getline('.')
let sPrevChar = sLine[nCol-2]
let sCurrChar = sLine[nCol-1]
" 光标在单词之间,不需要启动 {for CursorMovedI}
if !a:charPre &&
\ (sPrevChar !~# '[A-Za-z_0-9]' || sCurrChar =~# '[A-Za-z_0-9]')
return ''
endif
" ==============================================================================
" 利用前状态和当前状态优化
" 前状态
let dPrevStat = s:aucm_prev_stat
" 刚进入插入模式
if !a:charPre && get(dPrevStat, 'init', 0)
call s:ResetAucmPrevStat()
return ''
endif
let sPrevWord = matchstr(sLine[: nCol-2], '[A-Za-z_]\w*$')
if a:charPre
let sPrevWord .= sChar
endif
if len(sPrevWord) < nTriggerCharCount
" 如果之前补全过就重置状态
if get(dPrevStat, 'cccol', 0) > 0
call s:ResetAucmPrevStat()
endif
return ''
endif
" 获取当前状态
let nRow = line('.')
let nCol = VIMCCCSearchStartColumn(0)
let sBase = getline('.')[nCol-1 : col('.')-2]
if a:charPre
let sBase .= sChar
endif
" 补全起始位置一样就不需要再次启动了
" 貌似是有条件的,要判断 sPrevWord 的长度
" case: 如果前面的单词的长度 < nTriggerCharCount,那么就需要启动了
" 例如一直删除字符
" 1. 起始行和上次相同
" 2. 起始列和上次相同
" 3. 光标前的字符串长度大于等于触发长度
" 4. 上次的 base 是光标前的字符串的前缀(InsertCharPre 专用)
" 1 && 2 && 3 && 4 则忽略请求
let save_ic = &ignorecase
let &ignorecase = g:VIMCCC_IgnoreCase
if get(dPrevStat, 'ccrow', 0) == nRow && get(dPrevStat, 'cccol', 0) == nCol
\ && len(sPrevWord) >= nTriggerCharCount
\ && (!a:charPre || sBase =~ '^'.get(dPrevStat, 'base', ''))
call s:UpdateAucmPrevStat(nRow, nCol, sBase, pumvisible())
let &ignorecase = save_ic
return ''
endif