forked from ma6174/vim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tips.cnx
executable file
·492 lines (378 loc) · 20.5 KB
/
tips.cnx
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
*tips.txt* For Vim version 7.3. 最近更新: 2010年5月
Vim 参考手册 作者:Bram Moolenaar
译者: iCrazy <[email protected]>, tocer http://vimcdoc.sf.net
使用 Vim 的技巧 *tips*
这里只是一小部分我们认为会对很多用户有用的技巧。更多的技巧都在 wiki 上。URL 可
以从这里找到:
http://www.vim.org
别忘记浏览用户手册,里面也有很多实用的技巧 |usr_toc.txt|。
编辑 C 程序 |C-editing|
查找使用标识符的地方 |ident-search|
在 xterm 中切换屏幕 |xterm-screens|
在插入模式下滚屏 |scroll-insert|
平滑的滚屏 |scroll-smooth|
纠正普通的录入错误 |type-mistakes|
统计单词数、行数等 |count-items|
恢复光标位置 |restore-position|
文件更名 |rename-files|
更改多个文件中的一个名字 |change-name|
加速外部命令的执行 |speed-up|
一些有用的映射 |useful-mappings|
压缩帮助文件 |gzip-helpfile|
在一个窗口中执行 shell 命令 |shell-window|
十六进制编辑 |hex-editing|
在自动命令中使用 <> 记法 |autocmd-<>|
高亮匹配括号 |match-parens|
==============================================================================
编辑 C 程序 *C-editing*
Vim 里面有不少功能可以帮助你们编辑 C 程序。以下是一个概括,你们可以使用标签跳
转到具体的内容中去:
|usr_29.txt| 用户手册中关于在程序的不同部分间移动的内容。
|usr_30.txt| 用户手册中关于编辑程序的内容。
|C-indenting| 输入时自动设置每行的缩进。
|=| 重新缩进一些行。
|format-comments| 对注释进行排版。
|:checkpath| 显示所有被 (嵌套) 包含的文件。
|[i| 在当前和被包含的文件中查找光标所在的的标识符。
|[_CTRL-I| 跳到 "[i" 的匹配。
|[I| 列出在当前和被包含的文件中匹配光标所在的标识符的行。
|[d| 在当前和被包含的文件中查找光标所在的标识符的宏定义。
|CTRL-]| 跳到光标所在的标签处 (例如:函数的定义)。
|CTRL-T| 跳回执行 CTRL-] 命令前的地方。
|:tselect| 从一连串匹配的标签中选出一个。
|gd| 跳到光标所在的局部变量的声明处。
|gD| 跳到光标所在的全局变量的声明处。
|gf| 跳到光标所在的文件名表示的文件。
|%| 跳到匹配的 ()、{}、[]、/* */、#if、#else、#endif 处。
|[/| 跳到上一个注释开始的位置。
|]/| 跳到下一个注释结束的位置。
|[#| 反向到未闭合的 #if、#ifdef 或 #else 处。
|]#| 正向到未闭合的 #else 或 #endif 处。
|[(| 反向到未闭合的 '(' 处。
|])| 正向到未闭合的 ')' 处。
|[{| 反向到未闭合的 '{' 处。
|]}| 正向到未闭合的 '}' 处。
|v_ab| 选中 "一个块" ("a block"),从 "[(" 至 "])",含括号
|v_ib| 选中 "内含块" ("inner block"),从 "[(" 至 "])"
|v_aB| 选中 "一个大块" ("a Block"),从 "[{" 至 "]}",含括号
|v_iB| 选中 "内含大块" ("inner Block"),从 "[{" 至 "]}"
==============================================================================
查找使用标识符的地方 *ident-search*
你应该已经知道 |tags| 可以被用来跳转到定义函数和变量的地方。但是有时你希望跳转
到使用函数和变量的地方。可以用以下两种方法实现:
1. 使用 |:grep| 命令。这个应该可以在大多数 Unix 系统上工作,但是速度会比较慢
(因为它读取所有的文件),并且只能在一个目录中搜索。
2. 使用 ID 工具集。这个速度比较快而且可以搜索多个目录。它使用一个数据库来存放
定位信息。你需要一些额外的程序来使它得以工作,并且你必须使数据库不断保持更新。
使用 GNU id 工具集 (id-tools):
你所需要的:
- 安装 GNU id 工具集 (mkid 是用来创建 ID 的,lid 是用来运行宏的)
- 一个在当前目录下名为 "ID" 的标识符数据库。你可以用 shell 命令 "mkid file1
file2 .." 来创建它。
把这些添加写你的 .vimrc 文件中: >
map _u :call ID_search()<Bar>execute "/\\<" . g:word . "\\>"<CR>
map _n :n<Bar>execute "/\\<" . g:word . "\\>"<CR>
function! ID_search()
let g:word = expand("<cword>")
let x = system("lid --key=none ". g:word)
let x = substitute(x, "\n", " ", "g")
execute "next " . x
endfun
使用的时候,把光标放在一个单词上,敲入 "_u",然后 vim 会读入含有这个单词的文
件。使用 "n" 查找这个单词在相同文件中下一次的出现的地方。使用 "_n" 可以跳转到
下一个文件。
这些操作已经使用 id-utils-3.2 (这是位于距你最近的 gnu ftp 镜像服务器上的档案
名称) 测试通过了。
[这个的想法来自于 Andreas Kutschera]
==============================================================================
在 xterm 中切换屏幕 *xterm-screens* *xterm-save-screen*
(来源:comp.editors,作者:Juergen Weigert,回答一个问题的时候)
:> 另一个问题就是退出 vim 后,屏幕内容就被留在那儿了,也就是说:我刚刚正在查看
:> (或编辑) 的内容就被留在屏幕上了。而我此前执行的命令 (例如:"ls") 的输出却不
:> 见了,换而言之在滚屏缓冲区里不存在了。我知道有个办法可以在退出 vim 或其他仿
:> vi 的编辑器的时候恢复屏幕内容,但是我不知道该如何操作。请帮助我,谢谢!
:
: 我认为可能有人可以回答这个问题。我认为 vim 和 vi 在某个特定的 xterm 安装下和
: 别的程序一样工作。
他们并不一定完全相同,因为这牵扯到一个 termcap 对 terminfo 的问题。你们应该知
道针对一种特定的终端,有两种数据库可以用来描述它的属性:termcap 和 terminfo。
当它们中的条目不同,而且以上问题中的一个程序使用 terminfo,另一个使用 termcap
时,两个程序会出现差异 (请参见:|+terminfo|)。
在你的问题中,你可能需要以下的控制序列:^[[?47h 和 ^[[?47l。他们用来在 xterm
备用和主屏幕缓冲区中切换。一个快速的临时解决方案使用如下的命令序列 >
echo -n "^[[?47h"; vim ... ; echo -n "^[[?47l"
这可能就是你所需要的。(我用符号 ^[ 表示 ESC 字符,往后你还会看到数据库使用 \E
来表示它)。
在启动的时候,vim 把 termcap 中变量 ti (terminfo:smcup) 的值回显在终端上。退出
的时候,它回显 te (terminfo: rmcup) 的值。这样一来,这两个变量正好处于以上所述
的控制序列应该执行的位置。
把你的 xterm termcap 条目 (在 /etc/termcap 中) 和 xterm terminfo 条目 (用
"infocmp -C xterm" 得到) 比较一下。两者应该都会有与下面类似的条目: >
:te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:
附:如果你发现了任何差异,那么最好让某人 (或许是你的系统管理员) 彻底地检查一下
termcap 和 terminfo 的一致性。
备注 1: 如果你在 feature.h 中定义了 FEAT_XTERM_SAVE 之后又重新编译了 Vim,那么
内置的 xterm 会有上述的 "te" 和 "ti" 条目。
备注 2: 如果你希望禁止屏幕切换,并且不希望改变你的 termcap,你可以在 .vimrc 文
件中加入这一行: >
:set t_ti= t_te=
==============================================================================
在插入模式下滚屏 *scroll-insert*
如果你处于插入模式下并且希望看一些恰好在屏幕范围以外的东西,你可以使用 CTRL-X
CTRL-E 和 CTRL-X CTRL-Y 来滚屏。
|i_CTRL-X_CTRL-E|
为了使这个简单些,你可以用这些映射: >
:inoremap <C-E> <C-X><C-E>
:inoremap <C-Y> <C-X><C-Y>
(逐字敲入这些字符,并确认 '<' 标志位不在 'cpoptions' 选项中)。
不过这样你就不能使用从光标上一行/下一行拷贝文字的功能了 |i_CTRL-E|。
你还可以考虑把 'scrolloff' 设置得大一些,这样你就总能看到光标附近的上下文了。
如果 'scrolloff' 的值大于窗口高度的一半,在向上或向下移动光标时,文字会上下卷
动,但是光标会始终停留在屏幕中间的位置。
==============================================================================
平滑的滚屏 *scroll-smooth*
如果你希望你的滚屏更加平滑一些,你可以使用以下的映射: >
:map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y>
:map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E>
(逐字敲入这些字符,并确认 '<' 标志位不在 'cpoptions' 选项中)。
==============================================================================
纠正普通的录入错误 *type-mistakes*
如果有一些单词你总是敲错,你可以使用缩写来改正它们。例如: >
:ab teh the
:ab fro for
==============================================================================
统计单词数、行数等 *count-items*
如果需要统计缓冲区中一个模式 (pattern) 出现的频率,使用 substitute 命令并加入
'n' 标志位以避免实际的替代。Vim 报告的已替代的数目就是模式出现的次数。例: >
:%s/./&/gn 字符数
:%s/\i\+/&/gn 单词数
:%s/^//n 行数
:%s/the/&/gn 任何地方出现的 "the"
:%s/\<the\>/&/gn 作为单词出现的 "the"
你可能希望复位 'hlsearch' 或者使用 ":nohlsearch"。
如果你希望没有匹配的时候不显示错误,那么增加标志位 'e'。
另一种办法就是在可视模式下使用 |v_g_CTRL-G|。
如果你想在多个文件中查找匹配,用 |:vimgrep|。
*count-bytes*
如果你想数字节数,你可以这样做:
选中那些字符 (列块选择也可以)
使用 "y" 来拷贝这些字符
使用 strlen() 函数: >
:echo strlen(@")
一个换行符被当做一个字节。
==============================================================================
恢复光标位置 *restore-position*
有时你希望写一个映射,让它在文件中的其他地方做一些修改然后恢复光标的位置 (不滚
动文本)。例如,修改一个文件中的日期标记: >
:map <F2> msHmtgg/Last [cC]hange:\s*/e+1<CR>"_D"=strftime("%Y %b %d")<CR>p'tzt`s
分解出保存位置的命令:
ms 把光标位置存放在位置标记 's' 中
H 跳转到窗口的顶端
mt 把这个位置存放在位置标记 't' 中
分解出恢复位置的命令:
't 跳转到先前位于窗口顶端的那一行
zt 滚屏,使这一行位于窗口的顶端
`s 跳转到最初光标的位置
更高级的功能见 |winsaveview()| 和 |winrestview()|。
==============================================================================
文件更名 *rename-files*
假如我有一个目录,里面有如下的文件 (目录是随机选取的):
buffer.c
charset.c
digraph.c
...
现在我希望把 *.c 更名为 *.bla。我可以这样做: >
$ vim
:r !ls *.c
:%s/\(.*\).c/mv & \1.bla
:w !sh
:q!
==============================================================================
更改多个文件中的一个名字 *change-name*
使用脚本文件在若干文件中更改一个名字的示例:
创建文件 "subs.vim",包含替代命令和 :update 命令: >
:%s/Jones/Smith/g
:%s/Allen/Peter/g
:update
<
在所有你要改动的文件上执行 Vim,然后为每个参数执行脚本: >
vim *.let
argdo source subs.vim
参见 |:argdo|。
==============================================================================
加速外部命令的执行 *speed-up*
在一些情况下,外部命令执行起来非常地慢。而且还会减慢 Unix 上的通配符扩展。这儿
有一些建议可以加快速度:
如果你的 .cshrc 文件 (根据你使用的 shell,文件名可能不同) 非常地长,你应该把它
分割成两节:需要和用户交互的、无需和用户交互的 (经常被称作二级 shell)。当你在
Vim 中执行一个类似 ":!ls" 的命令时,你就不需要和用户交互的那一部分 (例如:设置
提示符)。把那些不必要的部分放到下面这些行后面去: >
if ($?prompt == 0) then
exit 0
endif
另一个办法是在 'shell' 选项中包含 "-f" 参数,例如: >
:set shell=csh\ -f
(这儿的反斜杠是必需的,这样才能在选项中表示一个空格)。
这样就会使 csh 完全跳过 .cshrc 文件。不过这样可能会造成一些程序不能正常运行。
==============================================================================
一些有用的映射 *useful-mappings*
这里有一些人们喜欢使用的映射。
*map-backtick* >
:map ' `
使得单引号和 ' 一样工作。把光标移动到一个位置标记所在的列,而不是那一行的第一
个非空白字符。
*emacs-keys*
要在命令行上实现 Emacs 风格的编辑操作: >
" 至行首
:cnoremap <C-A> <Home>
" 后退一个字符
:cnoremap <C-B> <Left>
" 删除光标所在的字符
:cnoremap <C-D> <Del>
" 至行尾
:cnoremap <C-E> <End>
" 前进一个字符
:cnoremap <C-F> <Right>
" 取回较新的命令行
:cnoremap <C-N> <Down>
" 取回以前 (较旧的) 命令行
:cnoremap <C-P> <Up>
" 后退一个单词
:cnoremap <Esc><C-B> <S-Left>
" 前进一个单词
:cnoremap <Esc><C-F> <S-Right>
备注: 前提条件是 '<' 标志位不在 'cpoptions' 选项中。|<>|
*format-bullet-list*
这个映射可以格式化任何带符号的 (bullet) 列表,不过它需要在每一个条目的上下都各
有一个空行。使用表达式命令,以便对映射的部分进行注释: >
:let m = ":map _f :set ai<CR>" " 需要置位 'autoindent'
:let m = m . "{O<Esc>" " 在项目上面加入空行
:let m = m . "}{)^W" " 跳转到 bullet 之后的文本
:let m = m . "i <CR> <Esc>" " 为缩进加空格
:let m = m . "gq}" " 排版 bullet 之后的文本
:let m = m . "{dd" " 删除空行
:let m = m . "5lDJ" " 把文本放到 bullet 之后
:execute m |" 定义这个 mapping
(<> 记法 |<>|。注意 必须按照字面逐个输入。^W 是 "^" 和 "W",而不是 CTRL-W。如
果 '<' 标志位不在 'cpoptions' 选项中,你可以把这些拷贝/粘贴代码给 Vim 执行。)
注意 最后一个注释以 |" 开始,因为 ":execute" 不能直接识别一个注释。
你还需要把 'textwidth' 设置成一个非 0 值,例如: >
:set tw=70
以下这个映射可以达到同样的效果,不过它从第一行获得列表的缩进 (备注: 这个映射其
实只有一行,其中有很多空格): >
:map _f :set ai<CR>}{a <Esc>WWmmkD`mi<CR><Esc>kkddpJgq}'mJO<Esc>j
<
*collapse*
这两个映射可以把一连串的空行 (;b) 或空白行 (;n) 压缩到一行 >
:map ;b GoZ<Esc>:g/^$/.,/./-j<CR>Gdd
:map ;n GoZ<Esc>:g/^[ <Tab>]*$/.,/[^ <Tab>]/-j<CR>Gdd
==============================================================================
压缩帮助文件 *gzip-helpfile*
对于那些磁盘空间极度紧张的人来说,你们可以压缩帮助文件。这样会使得查看帮助文
件时稍微慢一点,并且需要 "gzip" 这个程序的支持。
(1) 压缩所有帮助文件: "gzip doc/*.txt"。
(2) 编辑文件 "doc/tags",用 ".txt.gz" 替换 ".txt": >
:%s=\(\t.*\.txt\)\t=\1.gz\t=
(3) 把这一行加入到你的 vimrc 文件中: >
set helpfile={dirname}/help.txt.gz
这儿 {dirname} 是存放帮助文件的目录。|gzip| 这个插件会负责解压缩这些文件的。
如果其它 Vim 文件所在的位置和存放压缩帮助的 "doc" 目录不一致,你必须肯定已经把
$VIMRUNTIME 设置成存放 Vim 文件的目录。参见: |$VIMRUNTIME|。
==============================================================================
在一个窗口中执行 shell 命令 *shell-window*
很多人都询问能不能在 Vim 中的一个窗口内执行 shell 命令。答案是:不行!加入这个
功能会给 Vim 增加很多代码量,这也是为什么我们没有这样做的一个很好的理由。毕
竟,Vim 只是一个编辑器,它本身并不是用来做那些非编辑类工作的。然而,要达到这样
的目的,你可以用 "splitvt" 程序把你的终端屏幕或显示窗口进行分割。在一些 ftp 服
务器上你可以找到这个工具。Sam Lantinga <[email protected]> 对此了解颇多。
另一种办法是使用在 BSD Unix 系统上出现的 "window" 命令,它支持多个重叠的窗口。
或者使用最先出现在 www.uni-erlangen.de 上的 "screen" 程序,它支持窗口栈。
==============================================================================
十六进制编辑 *hex-editing* *using-xxd*
请看用户手册的第 |23.4| 节。
如果你用一些专门的扩展名来命名二进制文件 (诸如 exe,bin 等等),你会发现以下在
<.vimrc> 文件中使用的一些命令在自动处理这些文件时非常有用。你可以用你希望编辑
的文件扩展名 (用逗号分隔) 替换以下的 "*.bin": >
" vim -b : edit binary using xxd-format!
augroup Binary
au!
au BufReadPre *.bin let &bin=1
au BufReadPost *.bin if &bin | %!xxd
au BufReadPost *.bin set ft=xxd | endif
au BufWritePre *.bin if &bin | %!xxd -r
au BufWritePre *.bin endif
au BufWritePost *.bin if &bin | %!xxd
au BufWritePost *.bin set nomod | endif
augroup END
==============================================================================
在自动命令中使用 <> 记法 *autocmd-<>*
在自动命令的参数中,不能识别 <> 记法。为避免使用特殊的字符,你可以使用一个可以
自我毁灭的映射来得到 <> 记法,然后从自动命令中调用这个映射。举例如下:
*map-self-destroy* >
" 此命令自动把文件名加入到菜单列表中。
" 它使用了一个可以自我毁灭的映射!
" 1. 用缓冲区中的一行把文件名中的点 ('dots') 转换成 \.
" 2. 把该行存放在寄存器 '"' 中
" 3. 把该名字加入缓冲区菜单列表
" 警 告:这会有些副作用,比如:覆盖当前的寄存器内容和删除任何 "i" 命令的映射
"
autocmd BufNewFile,BufReadPre * nmap i :nunmap i<CR>O<C-R>%<Esc>:.g/\./s/\./\\./g<CR>0"9y$u:menu Buffers.<C-R>9 :buffer <C-R>%<C-V><CR><CR>
autocmd BufNewFile,BufReadPre * normal i
另一个或许更好一些的办法就是使用 ":execute" 命令。在字符串中,你可以通过在 <>
记法前面加一个反斜杠的方法来使用它。别忘了加倍已经存在的反斜杠的数目以及在 '"'
前面放一个反斜杠。 >
autocmd BufNewFile,BufReadPre * exe "normal O\<C-R>%\<Esc>:.g/\\./s/\\./\\\\./g\<CR>0\"9y$u:menu Buffers.\<C-R>9 :buffer \<C-R>%\<C-V>\<CR>\<CR>"
为了建立一个真正的缓冲区菜单,需要用到用户函数 (参见 |:function|),不过那里不
使用 <> 记法,所以失去了在这里举例的意义。
==============================================================================
高亮匹配括号 *match-parens*
本例演示一些高级技巧的用法:
- 使用 |CursorMoved| 自动命令事件
- 使用 |searchpairpos()| 查找匹配括号
- 使用 |synID()| 检测光标是否在字符串或注释上
- 使用 |:match| 高亮一些内容
- 使用 |pattern| 匹配文件的特定位置。
它应该被放在 Vim 脚本里,因为使用了局部于脚本的变量。它跳过字符串或注释里的匹
配,除非光标起始于字符串或者注释的内部。这需要语法高亮的支持。
|matchparen| 插件使用稍稍改进的版本。
>
let s:paren_hl_on = 0
function s:Highlight_Matching_Paren()
if s:paren_hl_on
match none
let s:paren_hl_on = 0
endif
let c_lnum = line('.')
let c_col = col('.')
let c = getline(c_lnum)[c_col - 1]
let plist = split(&matchpairs, ':\|,')
let i = index(plist, c)
if i < 0
return
endif
if i % 2 == 0
let s_flags = 'nW'
let c2 = plist[i + 1]
else
let s_flags = 'nbW'
let c2 = c
let c = plist[i - 1]
endif
if c == '['
let c = '\['
let c2 = '\]'
endif
let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
\ '=~? "string\\|comment"'
execute 'if' s_skip '| let s_skip = 0 | endif'
let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip)
if m_lnum > 0 && m_lnum >= line('w0') && m_lnum <= line('w$')
exe 'match Search /\(\%' . c_lnum . 'l\%' . c_col .
\ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
let s:paren_hl_on = 1
endif
endfunction
autocmd CursorMoved,CursorMovedI * call s:Highlight_Matching_Paren()
autocmd InsertEnter * match none
<
vim:tw=78:ts=8:ft=help:norl: