目录:
1.命令..............调出插件.............|project-invoking|
2.继承...........项目层层关系.........|project-inheritance|
3.映射.............插件映射..............|project-mappings|
4.添加映射.......为插件添加映射...|project-adding-mappings|
5.设置..............项目设置.............|project-settings|
6.样例文件..........项目样例..............|project-example|
7.技巧..............使用技巧.................|project-tips|
使用这个插件的基本功能可以为你经常访问的文件提供方便的浏览. 文件会在 Vim 左侧
窗口列出来, 在文件名上按 <Return> 或者双击鼠标就可以打开相应的文件. 这比使用
|file-explorer| 去浏览多层目录要更为便捷.
也可在选择一个文件时候去让插件更改目录, 执行指定都 Vim 脚本. 这些脚本可以通过
修改 $PATH 来设定编译器等的环境. 这在进行多项目开发时可以让 quickfix 工作在不
同的环境中.
其他特性:
o 在项目中实时加载或卸载文件(/l, /L, /w, and /W)
o 在项目中所有文件进行全局搜索(/g and /G)
o 对某一个文件单独执行用户指定的脚本(可以利用这个特写来关联一个文件到
某一个外部程序) (使用/1 到 /9)
o 对所有文件执行某个用户指定的脚本(使用/f1-/f9 和 /F1-/F9)
o 用户高可定制性
o 可以配合 |netrw| 插件使用 XXXX://... 管理远程项目. XXXX 代表 ftp,
rcp, scp, or http.
可以在一个单独的纯本文件中或在 vimrc 中设置几个全局量变进行配置.
必须在 |vimrc| 文件中 set 'nocompatible' 才能使用这个插件. 也可以通过设置变量
"loaded_project" 来禁止插件被加载: >
:let loaded_project = 1
==============================================================================
COMMANDS *project-invoking*
要使用本插件, 只需将其放置到 Vim 的插件目录(~/.vim/plugin)即可. 参见
"|add-global-plugin|", 在下次打开 Vim 时, 输入如下命令 >
:Project
或者 >
:Project {file}
如果没有指定具体的项目文件, 那么会默认使用$HOME/.vimprojects文件.
命令: [g]vim +Project 可在 Vim 启动时同时自动载入project插件窗口.
调出项目窗口时每次只能使用某一个文件, 如果想更改项目, 在项目窗口中运行:bwipe
删除项目缓冲, 然后用 :Project {file} 重新载入新的项目.
可以在同一个文件中保留和显示多个项目, 通过 {} (c参见 |fold.txt|) 来分隔. 在项目
中可以有任意多个嵌套的折叠. {} 中的每一行被当作一个文件名. 空行和 # 号后面的内
容将被忽略.
插件使用 Vim 标准的折叠方式, 支持所有的 |fold-commands| . 例如双击折叠的首行可
以打开或关闭该折叠. 通过光标定位到一个文件名后按回车键或者双击即可打开该文件,
插件会为在右侧打开一个新窗口来显示(如果映射了 |CTRL-W_p|, 也是等价的).
*project-syntax*
*语法*
项目入口描述形式:
project_entry ::=
<Description>={projpath} [{options}] {
[ filename ]
[ project_entry ]
}
{options} 可以是下面的一项或者几项, 但必须放在同一行上.
CD={path}
in={filename}
out={filename}
filter="{pat}"
flags={flag}
注意: 一个项目入口可以包含在另一个项目入口里面, 这意味着可以在项目中设置层次关系.
<Description> 项目描述. 不能含有"="字符. 在 =. 的两边不能有空字符. 它会显示在折叠
行上.
{projpath} 项目路径. 它指向项目文件所在目录, 可以在里面使用环境变量. 如果是一个相
对路径, 插件会根据项目的父目录及其上层目录等层次建立路径, 但最外层的项目入口必须
是一个绝对路径. 参见下面 |project-inheritance|的例子.可以在该项中使用空格, 但是要
转义. 下面的两个例子是针对同一个目录的:
>
Example=/my/directory/with/ spaces {
}
Example="/my/directory/with spaces" {
}
推荐在 Windows 上这样使用: >
Example="c:/My Documents" {
}
而 Vim 很聪明, 这样做也是可以的: >
Example=c:/My/ Documents {
}
CD= 表示在项目中选定一个文件时 Vim 将要进入的目录(相当于使用|:cd|). 这对在需要
使用本地 Makefile 文件进行编译时, 如|:make| 非常有用. 使用 CD=. 表示 Vim 将
{projpath} 及其等价路径设为当前工作目录. 如果不设置 CD 的值将无法中在项目中进
行目录都切换, 注意 "=" 的两边没有空格. CD 参数也可以是来自其父目录下都一个相对
路径. 参考 |project-inheritance| 中的例子. 在使用 |netrw| 浏览项目时该指令将被
忽略. 在 {projpath} 中可以使用空格.
in= 和 out= 用来在进入或者退出文件缓冲时执行特定的 Vim 脚本. (参考 |BufEnter|
和 |BufLeave| 自动命令事件). 它可以使用 Vim 脚本来为项目设定或取消一定的环境.
例如:
in.vim: >
let $PROJECT_HOME='~/my_project'
" Put the compiler in $PATH
if $PATH !~ '/path/to/my/compiler'
let $PATH=$PATH.':/path/to/my/compiler'
endif
out.vim: >
" Remove compiler from $PATH
if $PATH =~ '/path/to/my/compiler'
let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g')
endif
在这种情况下, 在合适的环境下可以使用 :make 进行编译你正在编辑的文件. 如果脚本中
使用的是相对路径, If the path to the script is relative, then it is
relative from {projpath}.
如果子项目没有另行设定, 这些指令会被子项目继承. 当配合 |netrw| 插件使用时, in=
和 out= 中的路径必须是绝对路径.
filter= 过滤符. 它指定一个全局的 |glob()| 文件匹配模式. 用于在使用 /r 时更新项目
窗口中的文件列表. 由于可能含有多个文件匹配模式, 必须使用双引号将过滤符号串扩起
来. 如果不设置过滤符号, 插件默认使用通配符 * 来当做过滤符.注意"="前后不能含有空
格. 如果子项目没有指定具体的过滤符, 子项目将会继承父项目的过滤符.
flags= 标识位 为某个折叠设置(启用/取消)具体的特性. 为了记忆方便, 通常使用小写
的表示关闭某一特性, 大写则表示开启某一特性. {flag} 参数可以使用下面的字符标志位:
标志位 描述 ~
l 关闭由 /L 的递归. 对于子折叠的同样也被关闭.
r 关闭更新. 当对折叠使用了/r or /R 后不要进行更新.
它不影响子目录的递归.
S 为刷新和创建项目开启排序功能.
s 关闭刷新和创建项目的排序功能.
T 开启更新项目时折叠处于当前折叠的正下方. 跟在全局变量
g:proj_flags 中使用标志位等效, 但是不能针对多个折叠而言.
t 关闭更新项目时折叠至当前折叠区域的最顶部功能. 强制折叠到底部.
w 关闭 /W 的递归. 对于子折叠的同样也被关闭.
在子项目不能沿用父项目中设定的这些标志.
只对当前折叠生效, 折叠外的文字不受其影响.
==============================================================================
INHERITANCE *project-inheritance*
通过下面两个项目文件的对比来理解层次的含义:
>
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
Child1=c_code {
}
Child2=include CD=. filter="*.h" {
}
}
Child1 的路径是 "~/my_project/c_code", 因为 Child1 继承了 ~/my_project. 它还
继承了 CD. 因为父层的 CD=., 所以对于父层的当前工作路径是 "~/my_project". 那么
Child1 继承过来的 CD 也是"~/my_project". 最后, Child1 从父层继承过来过滤符.
而标志位则是不能继承的,除非单独设置.
Child2 只将 "~/my_project" 从父层继承过来.
所以上述例子跟下面的展开是等价的:
>
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" {
}
Child2=~/my_project/include CD=~/my_project/include filter="*.h" {
}
}
(在一个实际的项目中, Child1 一般不会希望从父层继承过滤符号, 该例子只是为了说明
这个概念而已), 使用 /i 可以显示当前光标下项目的层次关系.
==============================================================================
MAPPINGS *project-mappings*
映射 动作 ~
/r 根据过滤符更新光标处的项目. 更新项目, 每深入一层折叠缩进一个空格.
如果在一行最后使用了 "# pragma keep" (不含双引号), 那么该行将保留,
不会被在更新时被删除. 当使用 . 作为一个入口时, 进入当前目录进行浏览
相当方便, 通常对于这个有用的入口你肯定想在更新时被保留.
注意这个映射是 <LocalLeader>r, Vim 默认使用 / 作为|<LocalLeader>|.
对于使用 |netrw| 浏览的项目不适用.
/R 递归执行 /r.
对于使用 |netrw| 浏览的项目不适用.
/c 创建一个项目. 要求用户输入 项目描述, 文件路径, CD 参数, 文件名匹配表达
式 |glob()|. 插件会根据这些信息在光标下面建立一个项目的入口.
对于使用 |netrw| 浏览的项目不适用.
/C 为目录及其子目录下的文件递归创建一个项目.
<Return>
在前一窗口或者另外一个新窗口中打开光标处的文件. 如果光标位于折叠上,
按此键打开或关闭折叠.
<S-Return>
/s
跟 <Return> 一样, 但会水平分割目标窗口.
使用 <LocalLeader>s 主要是为那些不能识别 <S-Return> 的终端而提供的.
/S
加载所有文件到当前窗口, 当前窗口会被水平分割显示所有文件.
<C-Return>
/o
同 <Return> 在一个窗口中打开当前文件, 同时关闭其他所有打开的窗口.
该映射保证该文件是除项目窗口以外其他唯一的窗口.
<LocalLeader>o 主要是为那些不能识别 <C-Return> 的终端而提供的.
<M-Return>
/v
同 <Return> 仅仅显示文件内容, 而光标依然停留在项目窗口中.
<2-LeftMouse>
(Double-click) 双击鼠标左键, 如果当前光标下是一个已经展开的折叠则关闭
该折叠, 反之打开该折叠. 如果当前光标下为一个文件名, 则在|CTRL-W_p|(前
一窗口)或项目右侧新窗口中打开该文件.
<S-2-LeftMouse>
同 <S-Return>.
<C-2-LeftMouse>
同 <C-Return>.
<RightMouse>
根据变量的值 g:proj_window_increment 增加项目窗口的宽度, 反复点击则为
在原宽度
g:proj_window_width
和增加后的宽度
g:proj_window_width + g:proj_window_increment
之间切换.
是否能够切换原窗口和宽窗口, 或手动改变窗口宽度均取决于全局变量
g:proj_flags 中的标志位 't' 是否设置. (参见|project-flags|).
注意在其他窗口中单击鼠标时右键并不能自动将光标定位到项目窗口.
在离开项目窗口后, 项目窗口宽度会变回到原宽度 g:proj_window_width.
<space> 同 <RightMouse>
<CTRL-Up>
/<Up>
移动文本或者折叠到当前光标的上一行. 在有的终端中可能无法识别此绑定而失效.
<LocalLeader><Up> 主要是为那些不能识别 <C-Up> 的终端而提供的.
<CTRL-Down>
/<Down>
移动文本或者折叠到当前光标的下一行. 在有的终端中可能无法识别此绑定而失效.
<LocalLeader><Down> 主要是为那些不能识别 <C-Down>.
/i 在状态栏中显示光标所在折叠完全解析和继承的参数.
这是专门为手动进入项目时进行相对路径和继承参数的调试而映射的.
/I 在状态栏显示光标下文件名的全名(含路径). 此功能是插件调用
Project_GetFname(line('.'))函数来实现的.
/1 - /9
执行在 g:proj_run{x} 指定的命令, {x} 是执行命令入口的编号.
参考下文中的 g:proj_run1.
/f1-/f9
执行 g:proj_run_fold{x} 中指定的命令, {x} 执行命令入口的编号, 命令只针
对当前项目层的文件. 参考下文中的|project-settings|.
/F1-/F9
执行 g:proj_run_fold{x} 中指定的命令, {x} 是执行命令入口的编号. 对当前
项目层及其所有子项目的所有文件执行命令. 参考下文中的 |project-settings|
/0 显示由 /1 到 /9 定义的命令.
/f0 显示由 /f1 到 /f9 和 /F1 到 /F9 所定义的命令. /F0 作用与此相同.
/l 加载当前项目中的所有文件到 Vim 中, 在加载过程中按任何键可以停止加载.
/L 加载当前项目及其子项目中的所有文件到 Vim 中. 请谨慎使用这个映射, 作者并
不建议在项目中含有成千上万的文件时使用该映射. (顺便提一句, 我的项目中有
5,300 多个文件!) 在加载过程中按任何键可以停止加载.
/w 删除当前项目层次中的所有文件. (并非真正删除文件, 只针对该项目组织而言.
如果文件被修改, 会先保存文件.) 擦除过程中按任意键可以停止此操作.
/W 删除当前项目层及其子层次中的所有文件. (并非真正删除文件, 只针对该项目组
织而言. 如果文件被修改, 会先保存文件.) 擦除过程中按任意键可以停止此操作.
/g 搜索当前项目层所有文件.
/G 搜索项目所有层所有文件.
/e 为先通过 <Return> 选择的项目文件设置环境变量. 例如在 /e 设定环境变量后,
无需打开项目中的任何文件便可用 :make 来进行编译.
/E 使用 |file-explorer| 浏览光标处目录内的文件. 不支持 netrw 时的项目管理.
<F12> 当在变量 g:proj_flags (参考 |project-flags|)中使用了标志位 'g' 时, 该键
用来切换打开和关闭项目窗口. 可以在 vimrc 中进行重新绑定. 例如将其映射到
<Leader>P:
nmap <silent> <Leader>P <Plug>ToggleProject
注意由于使用 :help 时帮助窗口跟项目窗口有所冲突, 该插件通过重新映射 :help避免了
这个问题(在使用时你可能无法感觉出来).
==============================================================================
ADDING MAPPINGS *project-adding-mappings*
添加映射
也可单独在 $HOME/.vimproject_mappings 文件中设置自己需要的映射. 如果这个文件存
在, 插件每次启动时候会执行(source)它. 下例中定义了统计项目中入口数量功能的映射
当按下 /K (Kount, 这因为 C 与 K 谐音 :-):时候会显示统计结果 >
function! s:Wc()
let b:loadcount=0
function! SpawnExec(infoline, fname, lineno, data)
let b:loadcount = b:loadcount + 1
if getchar(0) != 0 | let b:stop_everything=1 | endif
endfunction
call Project_ForEach(1, line('.'), "*SpawnExec", 0, '')
delfunction SpawnExec
echon b:loadcount." Files/r"
unlet b:loadcount
if exists("b:stop_everything")
unlet b:stop_everything
echon "Aborted./r"
endif
endfunction
nnoremap <buffer> <silent> <LocalLeader>K :call <SID>Wc()<CR>
下例在 $HOME/.vimproject_mappings 中实现了插件对perforce的整合:
>
function! s:DoP4(cmd)
let name=Project_GetFname(line('.'))
let dir=substitute(name, '/(.*/)/.*', '/1', 'g')
exec 'cd '.dir
exec "!".a:cmd.' '.Project_GetFname(line('.'))
cd -
endfunction
nmap <buffer> <silent> /pa :call <SID>DoP4("p4add")<CR>
nmap <buffer> <silent> /pe :call <SID>DoP4("p4edit")<CR>
<
(注意我进入文件所在目录后才可以使用 $P4CONFIG 文件. 请参考关于 perforce 的文档.)
这就建立了使用映射 /pe 来检查用于编辑的文件, 用 /pa 来将文件存储.
下例中为 <Return> 在打开某种特定文件时映射到一个外部程序来. (该例中它调
用 ee 来浏览jpg文件). 尽管看起来有些刻意, 但它还是有点用的.
>
let s:sid = substitute(maparg('<Return>', 'n'), '.*/(<SNR>./{-}/)_.*', '/1', '')
function! s:LaunchOrWhat()
let fname=Project_GetFname(line('.'))
if fname =~ '/.jpg$'
exec 'silent! !ee "'.fname.'"&'
else
call {s:sid}_DoFoldOrOpenEntry('', 'e')
endif
endfunction
nnoremap <buffer> <silent> <Return> /|:call <SID>LaunchOrWhat()<CR>
<
该例中调用外部程序来查看后缀名为jpg的文件, 对其他文件则仍以原 <Return> 处理.
==============================================================================
SETTINGS *project-settings*
在 vimrc 文件中设定下述变量后, Vim 会在加载插件前先使用这些属性从而不按照插
件的默认属性进行加载.
g:proj_window_width
插件项目窗口宽度. 默认值: 24
尽管插件不能完全成功地按照我预想的方式设定窗口的大小,但是这个变量在
设定窗口大小时还是会起到很大的作用.
g:proj_window_increment
当按空格键 <space> 或者单击鼠标左键 <LeftMouse >时项目窗口宽度增加量
默认值: 100 (参见 |project-mappings|)
*project-flags*
g:proj_flags
默认值: "imst"
这些标志位可以用来控制插件的行为, 具体如下:
标志位 描述 ~
b 设置后将使用 |browse()| 通过浏览目录来为 /c 和 /C 设定目录.
默认关闭, 因为窗口浏览器本身不允许进行目录的选择.
c 设置后, 在项目窗口中打开文件后会自动关闭项目窗口.
F 显示浮动项目窗口. 关闭窗口的自动调整大小和窗口替换.
This allows placement between other windows that wish to share
similar placement at the side of the screen.
在使用外部窗口管理器的时候很有用.
g 设置后会将切换打开和关闭项目窗口映射到 <F12> 上.
i 设置后, 当选择打开一个文件时会在命令行显示文件名和当前工作路径.
l 设置后, 项目插件在选择一个要打开的文件时,使用命令 |:lcd| 替换默
认的 |:cd| 命令去改变目录. 在有了下面的 L 标志位后, 此标志已经
用处不大.
L 与标志位 l 很相似. 不管缓冲是否被使用, 它通过安装一个进入/离开
缓冲的自动命令|:autocommand| 来确保当前工作目录更改到 CD 参数
指定的目录.(|:lcd| 命令只能为窗口而不能为缓冲改变当前工作目录)
m 在常规模式下开启 |CTRL-W_o| 和 |CTRL-W_CTRL_O| 映射, 使得当前
缓冲区成为唯一可见的缓冲区, 但是项目窗口仍然可见.
n 设置后将在项目窗口中显示行号.
s 设置后将在项目窗口中使用语法高亮.
S 设置后将在更新和创建项目时启用排序.
t 设置后将在按空格 <space> 或鼠标右击 <RightMouse> 时候进行原窗口
和加宽窗口之间的切换. 参见 See the entry for in |project-mappings|.
T 设置后, 子项目的折叠在更新时会紧跟在当前折叠下方显示(而不是其底
部).
v 设置后将, 按 /G 搜索时用 :vimgrep 取代 :grep.
g:proj_run1 ... g:proj_run9
包含一个作用于文件的 Vim 命令, 参考前文中关于 /1 to /9 的映射.
%f 替换文件的全路径和文件名
%F 替换文件的全路径和文件名
is 替换文件的全路径和包含空格的文件
%n 只替换文件名
%N 只替换包含空格的文件名
%h 替换项目主目录
%H 替换包含空格的项目主目录
%r 替换与 CD 目录相关联的路径
%R 替换与包含空格的 CD 目录相关联的路径
%d 替换 CD 目录.
%D 替换包含空格的 CD 目录
%% 未使用
例如, 如果在 vimrc 中做了如下设置, 在当前光标下按下 /3 时将调
出 gvim : >
let g:proj_run3='silent !gvim %f'
< 其他的几个例子: >
let g:proj_run1='!p4 edit %f'
let g:proj_run2='!p4 add %f'
let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &"
<
在 Windows 系统中应用单引号括住 %f, %h, %d 以避免 / 引起的转义.
g:proj_run_fold1 ... g:proj_run_fold9
包含一个作用于折叠内文件的 Vim 命令. 参考前文中关于 /f1 to /f9
和 /F1 to /F9 的映射部分.$HOME/.vimproject_mappings
%f 替换文件名, %h 替换项目的主目录, %d 替换 CD 目录.
对应多个文件名有两种处理方式:
第一种(默认的)处理方式使用 %f 替换所有的绝对文件名, 让命令只执
行一次; 第二种是让命令针对每个非绝对文件名执行一次, %f 每次只
替换一个文件名. 使用第二种方式时, 须在变量 g:proj_run_fold{x}
的开头加上一个通配符 '*' (通配符 '*' 在运行时将被自动去掉.)
例如, 注意以下两种方式的差异: >
let g:proj_run_fold3="*echo '%h/%f'"
let g:proj_run_fold4="echo '%f'"
<
注意在Windows系统中, 需要用 '' 将 %f, %h, %c 括起来, 否则路径中
使用的 / 会出问题. 另一种办法是把它们放在 |escape()| 函数中.
==============================================================================
PROJECT EXAMPLE FILE *project-example*
例子: 项目文件(~/.vimprojects): >
1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r {
2 Makefile
3 in.vim
4 out.vim
5 GUI Files=. filter="gui*.c gui*.h" {
6 gui_window.c
7 gui_dialog.c
8 gui_list.c
9 gui.h # Header file
10 }
11 Database Files=. filter="data*.c data*.h" {
12 data_read.c
13 data_write.c
14 data.h
15 }
16 OS-Specific Files {
17 Win32=. filter="os_win32*.c os_win32*.h" {
18 os_win32_gui.c
19 os_win32_io.c
20 }
21 Unix=. filter="os_unix*.c os_unix*.h" {
22 os_unix_gui.c
23 os_unix_io.c
24 }
25 }
26 }
(注意左侧的行号不是文件内容.)
==============================================================================
插件技巧 *project-tips*
1. 先为项目创建一个入口: >
Label=~/wherever CD=. filter="*.c *.h" {
}
<
然后将光标定位在折叠上按 /r, 脚本会自动添加对应目录下所有 C 文件(本例中)
到项目之中. 这与 /c 是等效的, 只是没有对话框显示.
2. 可以在项目列表里随时添加,删除或排序项目文件.
3. 当项目窗口没有打开时, 输入 >
:Project
< 可以将其打开. (插件有自动记忆功能, 而无需输入具体的项目名称.) 如果在
g:proj_flags 变量中设定了 'm' 标志位, 通过组合键 |CTRL-W_o| 可以重新打开
项目窗口. 毫无疑问, 这会关闭除当前窗口之外的其他所有打开的窗口.
4. 往项目中添加新的文件. 例如添加 'more.c' 到项目中去, 只需在项目入口之中插
入文件名后按 <Return> 键即可.
5. 当使用 |quickfix| 时候, 在文件名上按回车键 <Return> 并不会有效, 这样的话,
将无法更改目录, 运行脚本. 解决办法是在使用 |quickfix| 前用 /L 将所有文件
载入到项目中去.
6. 当项目窗口因为或开或闭的折叠显得凌乱时, 使用 |zM| 可以关闭所有的展开折叠,
让项目窗口重新变得整洁如初.
7. 对于高级用户, 可以尝试插件提供如下几个函数:
Project_GetAllFnames()
返回一个折叠及其子项目(可选)下的所有文件名.
Project_ForEach()
在为项目中的每个文件提供一个调用函数的接口.如何使用请参考上面的例子以
及源代码.
Project_GetFname(line_number)
在编写自己的映射时用来获取文件名.
8. 将光标定位到项目插件窗口的键映射, 在 vimrc 文件中添加:
>
nmap <silent> <Leader>P :Project<CR>
<
9. 项目入口中使用符号"."会调出|file-explorer|插件. 为了防止在更新时候删除,
在项目入口中加入:
>
. # pragma keep
<