├── .vimrc ├── README ├── TODO ├── hotkeys ├── ptags.cpp └── vimfiles ├── .netrwhist ├── after └── plugin │ └── TabularMaps.vim ├── autoload ├── checksyntax.vim └── tabular.vim ├── doc ├── NERD_tree.txt ├── Tabular.txt ├── checksyntax.txt └── taglist.txt ├── ftplugin ├── c.vim ├── cs.vim ├── java.vim ├── php.vim ├── python.vim └── txt.vim ├── funclist.txt ├── nerdtree_plugin ├── exec_menuitem.vim └── fs_menu.vim ├── phpm ├── HISTORY ├── README ├── generator.php ├── lib │ └── epc │ │ ├── object.php │ │ └── phpm │ │ ├── install.php │ │ ├── listall.php │ │ ├── listinstalled.php │ │ ├── parser.php │ │ └── reader.php ├── list.xml ├── php.xml ├── phpm ├── reader.php └── settings.xml ├── plugin ├── NERD_tree.vim ├── Tabular.vim ├── checksyntax.vim ├── filetype.vim ├── php-doc.vim ├── phpcs.vim ├── taglist.vim └── tasklist.vim └── template.spec /.vimrc: -------------------------------------------------------------------------------- 1 | " .vimrc 2 | " See: http://vimdoc.sourceforge.net/htmldoc/options.html for details 3 | 4 | " Source local settings 5 | if filereadable("~/.vimrc") 6 | source ~/.vimrc 7 | endif 8 | 9 | " disable VI's compatible mode(关闭vi兼容模式) 10 | set nocompatible 11 | " set encoding=utf-8(设置支持多语言) 12 | set fileencodings=utf-8,gbk,default,latin1 13 | "set gui options(设置字体,配色方案) 14 | if has("gui_running") 15 | set guifont=Courier\ New\ 14 16 | " on windows,use "set guifont=Courier:14 " 17 | " set color schema(设置配色方案) 18 | " colorscheme oceandeep 19 | endif 20 | 21 | " Basic editing options 22 | set number " Show line numbers.显示行号 23 | set expandtab " Use the appropriate number of spaces to insert a .用空格替换tab 24 | set shiftwidth=2 " Number of spaces to use for each step of (auto)indent.自动缩进的空格数 25 | set tabstop=2 " Number of spaces that a in the file counts for.一个tab用几个空格替换 26 | au FileType html,python,vim,javascript,css setl shiftwidth=2 27 | au FileType html,python,vim,javascript,css setl tabstop=2 28 | au FileType java,php setl shiftwidth=4 29 | au FileType java,php setl tabstop=4 30 | 31 | set textwidth=80 " Maximum width of text that is being inserted. A longer 32 | " line will be broken after white space to get this width.(每行的最大字符数,超过的话,将换行) 33 | set hlsearch " When there is a previous search pattern, highlight all 34 | " its matches.(搜索时高亮显示) 35 | 36 | set incsearch " While typing a search command, show immediately where the 37 | " so far typed pattern matches.(搜索时,立即高亮显示输入的字符) 38 | set fileformat=unix " 文本格式 39 | set nobackup " 不生成备份文件 40 | " Show a status bar " 显示状态栏 41 | set ruler 42 | set laststatus=2 43 | " Show Tab Bar 44 | set showtabline=2 " 生成多tab 45 | set tabline+=%f 46 | " Enable Code Folding 47 | set foldenable 48 | set foldmethod=syntax 49 | set mouse=a " Enable the use of the mouse.(可以使用鼠标) 50 | 51 | 52 | set cmdheight=1 "设定命令行的行数为 1 53 | "去掉烦死我的错误声音 54 | set vb t_vb= 55 | "工作目录随文件变 56 | autocmd BufEnter * cd %:p:h 57 | "设置状态栏 58 | set statusline=%F%m%r,%Y,%{&fileformat}\ \ \ ASCII=\%b,HEX=\%B\ \ \ %l,%c%V\ %p%%\ \ \ [\ %L\ lines\ in\ all\ ] 59 | "不显示工具条 60 | "set guioptions-=T 61 | set backspace=indent,eol,start "不设定的话在插入状态无法用退格键和 Delete 62 | filetype indent on "设置文件类型的检测,e.g. for PHP 63 | filetype plugin on "为特定的文件类型允许插件文件的载入 64 | 65 | " Allow file inline modelines to provide settings 66 | set modeline 67 | 68 | 69 | 70 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 71 | " => Plugin configuration 72 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 73 | " NERDTree 74 | map :NERDTreeToggle 75 | let NERDTreeIgnore=['\.svn$','\.bak$'] 76 | 77 | " taglist 78 | set tags=tags;/ 79 | let Tlist_Ctags_Cmd="/usr/bin/ctags" 80 | map :TlistToggle 81 | let Tlist_Auto_Highlight_Tag = 1 82 | let Tlist_Auto_Open = 0 83 | let Tlist_Auto_Update = 1 84 | let Tlist_Close_On_Select = 0 85 | let Tlist_Compact_Format = 0 86 | let Tlist_Display_Prototype = 0 87 | let Tlist_Display_Tag_Scope = 1 88 | let Tlist_Enable_Fold_Column = 0 89 | let Tlist_Exit_OnlyWindow = 0 90 | let Tlist_File_Fold_Auto_Close = 0 91 | let Tlist_GainFocus_On_ToggleOpen = 1 92 | let Tlist_Hightlight_Tag_On_BufEnter = 1 93 | let Tlist_Inc_Winwidth = 0 94 | let Tlist_Max_Submenu_Items = 1 95 | let Tlist_Max_Tag_Length = 30 96 | let Tlist_Process_File_Always = 0 97 | let Tlist_Show_Menu = 0 98 | let Tlist_Show_One_File = 0 99 | let Tlist_Sort_Type = "order" 100 | let Tlist_Use_Horiz_Window = 0 101 | let Tlist_Use_Right_Window = 0 102 | let Tlist_WinWidth = 40 103 | let tlist_php_settings = 'php;c:class;i:interfaces;d:constant;f:function' 104 | 105 | " Disable phpsyntax based indenting for .php files {{{ 106 | au BufRead,BufNewFile *.php set indentexpr= | set smartindent 107 | " }}} 108 | 109 | " {{{ .phps files handled like .php 110 | 111 | au BufRead,BufNewFile *.phps set filetype=php 112 | 113 | " }}} 114 | 115 | " {{{ Settings 116 | 117 | 118 | 119 | " MovingThroughCamelCaseWords 120 | nnoremap :cal search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%^','bW') 121 | nnoremap :cal search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%$','W') 122 | inoremap :cal search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%^','bW') 123 | inoremap :cal search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%$','W') 124 | 125 | " }}} 126 | 127 | " Map to turn spelling on (VIM 7.0+) 128 | map :setlocal spell! spelllang=en_us 129 | " Map to turn spelling (de) on (VIM 7.0+) 130 | "map :setlocal spell! spelllang=de 131 | 132 | " Highlight current line in insert mode. 133 | autocmd InsertLeave * se nocul 134 | autocmd InsertEnter * se cul 135 | 136 | if has("cscope") 137 | set csprg=/usr/bin/cscope 138 | set csto=0 139 | set cst 140 | set nocsverb 141 | " add any database in current directory 142 | if filereadable("cscope.out") 143 | cs add cscope.out 144 | " else add database pointed to by environment 145 | elseif $CSCOPE_DB != "" 146 | cs add $CSCOPE_DB 147 | endif 148 | set csverb 149 | endif 150 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 在fedora上用vim打造一个php集成开发环境(ide) 2 | 1 安装vim 3 | yum install vim-X11.x86_64 vim-common.x86_64 vim-enhanced.x86_64 4 | vim-minimal.x86_64 5 | 6 | 2 创建配置文件 7 | touch ~/.vimrc 8 | 9 | 3 我的配置文件 10 | " .vimrc 11 | " See: http://vimdoc.sourceforge.net/htmldoc/options.html for details 12 | 13 | "设定 gvim 运行在增强模式下,不使用vi的键盘模式 14 | set nocompatible 15 | "设置支持多语言,解决乱码 16 | set encoding=utf-8 17 | set fileencodings=utf-8,gbk,default,latin1 18 | "设置字体,配色方案 19 | if has("gui_running") 20 | set guifont=Courier\ New\ 14 21 | " on windows,use "set guifont=Courier:14 " 22 | "设置配色方案 23 | " colorscheme oceandeep 24 | endif 25 | 26 | "基本编辑器设置 27 | set number "显示行号 28 | set expandtab "编辑时将所有 Tab 替换为空格 29 | set shiftwidth=2 "自动缩进的时候,缩进尺寸为2个空格 30 | set tabstop=2 "设置 softtabstop 为 2. 输入 tab 后就跳了2格 31 | "对于不同类型的文件,进行自定义设置 32 | au FileType html,python,vim,javascript,css setl shiftwidth=2 33 | au FileType html,python,vim,javascript,css setl tabstop=2 34 | au FileType java,php setl shiftwidth=4 35 | au FileType java,php setl tabstop=4 36 | 37 | set textwidth=80 "设置每行的最大字符数,超过的话,将换行 38 | set hlsearch "搜索时高亮显示 39 | set incsearch "输入搜索内容时就显示搜索结果 40 | set fileformat=unix "文本格式 41 | set nobackup "覆盖文件时不备份 42 | 43 | set ruler "打开状态栏标尺 44 | set laststatus=2 "显示状态栏 (默认值为 1, 无法显示状态栏) 45 | set cmdheight=1 "设定命令行的行数为 1 46 | 47 | set showtabline=2 "显示tab标签 48 | set tabline+=%f "tab标签 49 | " Enable Code Folding 50 | set foldenable 51 | set foldmethod=syntax 52 | set mouse=a "任何情况都可以使用鼠标) 53 | 54 | "去掉错误声音 55 | set vb t_vb= 56 | "工作目录随文件变 57 | autocmd BufEnter * cd %:p:h 58 | "设置状态栏 59 | set statusline=%F%m%r,%Y,%{&fileformat}\ \ \ ASCII=\%b,HEX=\%B\ \ \ %l,%c%V\ 60 | %p%%\ \ \ [\ %L\ lines\ in\ all\ ] 61 | "不显示工具条 62 | set guioptions-=T 63 | set backspace=indent,eol,start "不设定的话在插入状态无法用退格键和 Delete 64 | filetype on "设置文件类型的检测 65 | filetype plugin on "为特定的文件类型允许插件文件的载入 66 | 67 | "按住ctrl键,移动方向键时,以峰驼的方式 68 | nnoremap :cal 69 | search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%^','bW') 70 | nnoremap :cal 71 | search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%$','W') 72 | inoremap :cal 73 | search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%^','bW') 74 | inoremap :cal 75 | search('\<\\U\@<=\u\\u\ze\%(\U\&\>\@!\)\\%$','W') 76 | 77 | "php语法检查 78 | setlocal makeprg=\/usr/bin/php\ -l\ -n\ -d\ html_errors=off\ % 79 | setlocal errorformat=%m\ in\ %f\ on\ line\ %l 80 | "autocmd BufWritePost *.php,*.phps :make 81 | map :w:noh:make 82 | 83 | "Disable phpsyntax based indenting for .php files 84 | au BufRead,BufNewFile *.php set indentexpr= | set smartindent 85 | au BufRead,BufNewFile *.phps set filetype=php 86 | 87 | 5 插件配置 88 | 89 | 1)集成NERDTree实现目录导航 90 | wget https://github.com/scrooloose/nerdtree/tarball/master 91 | tar zxvf scrooloose-nerdtree-4.1.0-35-g1cd5048.tar.gz 92 | cp doc/NERD_tree.txt /usr/share/vim/vimfiles/doc/ 93 | cp plugin/NERD_tree.vim /usr/share/vim/vimfiles/plugin/ 94 | cp -fr nerdtree_plugin/ /usr/share/vim/vimfiles/ 95 | 最后在 .vimrc 添加如下内容: 96 | 97 | "NERDTree 98 | map :NERDTreeToggle 99 | let NERDTreeIgnore=['\.svn$','\.bak$'] 100 | 101 | 通过F10即可调出目录导航,通过键盘ctrl+w+w可以在导航和编辑中的文件之前切换焦点。“u”可到上一级目录,回车则展开文件夹 102 | 103 | 2)集成task list url:http://www.vim.org/scripts/script.php?script_id=2607 104 | cp tasklist.vim /usr/share/vim/vimfiles/plugin/ 105 | 通过":TaskList"可以列出代码中的TODO和FIXME列表,将鼠标移动到相应的项目上时,会关闭列表窗口,并跳转到代码指定的位置 106 | 107 | 3)集成tag list url:http://www.vim.org/scripts/script.php?script_id=273 108 | taglist 可以列出已打开文件中定义的类、函数、常量,甚至变量。 109 | cp plugin/taglist.vim /usr/share/vim/vimfiles/plugin/ 110 | cp doc/taglist.txt /usr/share/vim/vimfiles/doc/ 111 | 最后在 .vimrc 添加如下内容: 112 | 113 | "taglist 114 | set tags=tags;/ 115 | let Tlist_Ctags_Cmd="/usr/bin/ctags" 116 | map :TlistToggle 117 | let Tlist_Auto_Highlight_Tag = 1 118 | let Tlist_Auto_Open = 0 119 | let Tlist_Auto_Update = 1 120 | let Tlist_Close_On_Select = 0 121 | let Tlist_Compact_Format = 0 122 | let Tlist_Display_Prototype = 0 123 | let Tlist_Display_Tag_Scope = 1 124 | let Tlist_Enable_Fold_Column = 0 125 | let Tlist_Exit_OnlyWindow = 0 126 | let Tlist_File_Fold_Auto_Close = 0 127 | let Tlist_GainFocus_On_ToggleOpen = 1 128 | let Tlist_Hightlight_Tag_On_BufEnter = 1 129 | let Tlist_Inc_Winwidth = 0 130 | let Tlist_Max_Submenu_Items = 1 131 | let Tlist_Max_Tag_Length = 30 132 | let Tlist_Process_File_Always = 0 133 | let Tlist_Show_Menu = 0 134 | let Tlist_Show_One_File = 0 135 | let Tlist_Sort_Type = "order" 136 | let Tlist_Use_Horiz_Window = 0 137 | let Tlist_Use_Right_Window = 0 138 | let Tlist_WinWidth = 40 139 | let tlist_php_settings = 'php;c:class;i:interfaces;d:constant;f:function' 140 | 141 | map :tab split:exec("tag ".expand("")) 142 | map :vsp :exec("tag ".expand("")) 143 | 144 | 需要安装ctags,本文采用yum安装,如需编译安装,请参见其他资料。 145 | 通过ctags -R生成tags后,可以使用如下快捷键: 146 | ctrl+] - 跳转到定义处 147 | ctrl+t - 从定义处跳转回来 148 | ctrl+w ctrl+] - 水平分割窗口,并在上部打开定义所在文件,跳转到定义处 149 | ctrl+\ - 打开新标签页。并跳转到定义处 150 | alt+] - 垂直分割窗口,并在右部打开定义所在文件,跳转到定义处 151 | 152 | ctrl+鼠标左键 - 跳转到定义处 153 | ctrl+鼠标右键 - 从定义处跳转回来 154 | 155 | 4)集成php-doc url http://www.vim.org/scripts/script.php?script_id=1355 156 | cp php-doc.vim /usr/share/vim/vimfiles/plugin/ 157 | 158 | 最后在 .vimrc 添加如下内容: 159 | "在通常模式(n)和插入模式(i),按ctrl+p插入注释 160 | inoremap ^[:call PhpDocSingle()i 161 | nnoremap :call PhpDocSingle() 162 | "选择多行,在可视模式(v)下,对选中的多行插入注释 163 | vnoremap :call PhpDocRange() 164 | 165 | 5)集成PHPM url http://eide.org/2009/01/02/phpm/ 166 | cp -fr phpm /usr/share/vim/vimfiles 167 | 最后在 .vimrc 添加如下内容: 168 | 169 | " Map -H to search phpm for the function name currently under the cursor 170 | (insert mode only) 171 | inoremap :!/usr/share/vim/vimfiles/phpm/phpm 172 | =expand("") 173 | 在插入模式下,按ctrl+h,即可调出光标在函数的说明,参数,返回值 174 | 175 | 6)集成funclist,实现自动完成 url 176 | http://svn.php.net/viewvc/phpdoc/doc-base/trunk/funclist.txt 177 | cp funclist.txt /usr/share/vim/vimfiles 178 | 最后在 .vimrc 添加如下内容: 179 | 180 | setlocal dictionary-=/usr/share/vim/vimfiles/funclist.txt 181 | dictionary+=/usr/share/vim/vimfiles/funclist.txt 182 | " Use the dictionary completion 183 | setlocal complete-=k complete+=k 184 | 185 | func! InsertTabWrapper() 186 | let col = col('.') - 1 187 | if !col || getline('.')[col - 1] !~ '\k' 188 | return "\" 189 | else 190 | return "\" 191 | endif 192 | endfunction 193 | 194 | " Remap the tab key to select action with InsertTabWrapper 195 | inoremap =InsertTabWrapper() 196 | 在插入模式下,按tab,即可调出函数列表 197 | 198 | 7)在任意模式下,按";"在行尾输入添加";",如果没有";"的话 199 | noremap ; :s/\([^;]\)$/\1;/ 200 | 201 | 8)配置 PhpAlign,手动格式代码的对齐 202 | 在 .vimrc 添加如下内容: 203 | 204 | " Map -a to alignment function 205 | vnoremap :call PhpAlign() 206 | 207 | func! PhpAlign() range 208 | let l:paste = &g:paste 209 | let &g:paste = 0 210 | 211 | let l:line = a:firstline 212 | let l:endline = a:lastline 213 | let l:maxlength = 0 214 | while l:line <= l:endline 215 | " Skip comment lines 216 | if getline (l:line) =~ '^\s*\/\/.*$' 217 | let l:line = l:line + 1 218 | continue 219 | endif 220 | " \{-\} matches ungreed * 221 | let l:index = substitute (getline (l:line), 222 | '^\s*\(.\{-\}\)\s*\S\{0,1}=\S\{0,1\}\s.*$', '\1', "") 223 | let l:indexlength = strlen (l:index) 224 | let l:maxlength = l:indexlength > l:maxlength ? l:indexlength : 225 | l:maxlength 226 | let l:line = l:line + 1 227 | endwhile 228 | 229 | let l:line = a:firstline 230 | let l:format = "%s%-" . l:maxlength . "s %s %s" 231 | 232 | while l:line <= l:endline 233 | if getline (l:line) =~ '^\s*\/\/.*$' 234 | let l:line = l:line + 1 235 | continue 236 | endif 237 | let l:linestart = substitute (getline (l:line), '^\(\s*\).*', '\1', "") 238 | let l:linekey = substitute (getline (l:line), 239 | '^\s*\(.\{-\}\)\s*\(\S\{0,1}=\S\{0,1\}\)\s\(.*\)$', '\1', "") 240 | let l:linesep = substitute (getline (l:line), 241 | '^\s*\(.\{-\}\)\s*\(\S\{0,1}=\S\{0,1\}\)\s\(.*\)$', '\2', "") 242 | let l:linevalue = substitute (getline (l:line), 243 | '^\s*\(.\{-\}\)\s*\(\S\{0,1}=\S\{0,1\}\)\s\(.*\)$', '\3', "") 244 | 245 | let l:newline = printf (l:format, l:linestart, l:linekey, l:linesep, 246 | l:linevalue) 247 | call setline (l:line, l:newline) 248 | let l:line = l:line + 1 249 | endwhile 250 | let &g:paste = l:paste 251 | endfunc 252 | 在可视模式下,选中代码,按ctrl+a,即可格式代码的对齐 253 | 254 | 9)配置 PhpUnComment,批量注释代码 255 | 在 .vimrc 添加如下内容: 256 | 257 | vnoremap :call PhpUnComment() 258 | 259 | func! PhpUnComment() range 260 | let l:paste = &g:paste 261 | let &g:paste = 0 262 | 263 | let l:line = a:firstline 264 | let l:endline = a:lastline 265 | 266 | while l:line <= l:endline 267 | if getline (l:line) =~ '^\s*\/\/.*$' 268 | let l:newline = substitute (getline (l:line), 269 | '^\(\s*\)\/\/ \(.*\).*$', '\1\2', '') 270 | else 271 | let l:newline = substitute (getline (l:line), 272 | '^\(\s*\)\(.*\)$', '\1// \2', '') 273 | endif 274 | call setline (l:line, l:newline) 275 | let l:line = l:line + 1 276 | endwhile 277 | 278 | let &g:paste = l:paste 279 | endfunc 280 | 在可视模式下,选中代码,按ctrl+c,即批量注释代码,再按就取消注释 281 | 282 | 10)设置自动补齐 283 | 在 .vimrc 添加如下内容: 284 | 285 | inoremap { {}O 286 | 287 | inoremap [ [] 288 | 289 | " Standard mapping after PEAR coding standard 290 | inoremap ( () 291 | " inoremap ( () 292 | 293 | " Maybe this way in other coding standards 294 | " inoremap ( ( ) 295 | 296 | inoremap " "" 297 | inoremap ' '' 298 | 11)在文件夹中查找 299 | :vimgrep /pattern/gj ./**/*.php 300 | 这哥命令告诉vim,在当前目前下的所有.php文件中全局查找符合pattern的结果。 301 | 运行 302 | :cw 303 | 会列出查找结果。 304 | 305 | 11)转换大小写 306 | ~ 转换当前光标所在字符的大小写 307 | u 将选中的字符全转成小写 308 | U 将选中的字符全转成大写 309 | UV 将当前行转成大写 310 | guw 将当前的单词转成小写 311 | 312 | 12)排序 313 | vim在linux上,可以通过在命令模式下输入相关命令,进行文本的排序 314 | %!sort -u 排序时,删除重复的行 315 | %!sort -f 排序时,忽略大小写 316 | %!sort -r 进行逆向排序 317 | 排序时,都是以行为单位。按照字典顺序,如:a-z, 0-100的顺序进行排序 318 | sort /pattern/ 可以在排序时,过滤掉正则匹配到的字符。 319 | sort /^./ 将不是按照第一个字符排序,而是过滤掉第一个字符,从第二个开始。正则表达式/^./匹配开头的第一个字符。 320 | 321 | 322 | 参考链接 323 | http://eide.org/category/php/ 324 | http://taggedzi.com/articles/display/vim-for-php-developers-part-3 325 | http://www.foolbirds.com/c/vi 326 | https://github.com/tobyS/vip 327 | http://lostechies.com/derickbailey/2010/05/11/vim-grep-find-all-occurrences-of-text-in-your-project/ 328 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 1 use cscope in vim with php 2 | 2 update phpm 3 | 3 other 4 | 4 check phpcs use,and uncomment later 5 | 5 search in floder 6 | 在当前目录下查找含有“getInfo”的php文档,但不跳到第一个匹配 7 | :vimgrep /getInfo/gj ./*/*.php 8 | 如果要包含子文件夹,则用 9 | :vimgrep /getInfo/gj ./**/*.php 10 | :cw 11 | 打开quickfix窗口查看匹配结果 12 | :vim[grep][!] /{pattern}/[g][j] {file} 13 | Search for {pattern} in the files {file} … and set 14 | the error list to the matches. 15 | Without the ‘g’ flag each line is added only once. 16 | With ‘g’ every match is added. 17 | 18 | {pattern} is a Vim search pattern. Instead of 19 | enclosing it in / any non-ID character (see 20 | |’isident’|) can be used, so long as it does not 21 | appear in {pattern}. 22 | ‘ignorecase’ applies. To overrule it put |/c| in the 23 | pattern to ignore case or |/C| to match case. 24 | ‘smartcase’ is not used. 25 | 26 | When a number is put before the command this is used 27 | as the maximum number of matches to find. Use 28 | “:1vimgrep pattern file” to find only the first. 29 | Useful if you only want to check if there is a match 30 | and quit quickly when it’s found. 31 | 32 | Without the ‘j’ flag Vim jumps to the first match. 33 | With ‘j’ only the quickfix list is updated. 34 | With the [!] any changes in the current buffer are 35 | abandoned. 36 | 37 | @@@@ test github 38 | -------------------------------------------------------------------------------- /hotkeys: -------------------------------------------------------------------------------- 1 | some shortcut keys in use php-vim 2 | 3 | f3 - show tag list,press agian to close 4 | f2 - show NERD_tree,press again to close 5 | [v,i]ctrl+p - 在可视和插入模式下,调用phpdoc会函数和类添加phpdocument 6 | [v]ctrl+a - 在可视模式下,调用phpAlign对代码格式进行对齐 7 | [i]ctrl+h - 在插入模式下,调用phpm打开php函数的定义 8 | [v]ctrl+c - 注释代码块或者行,再按一下则取消注释 9 | [v,i]ctrl+方向键 - 以峰驼的形式,跳转到上一处或者下一处 10 | 11 | ctrl+] - 跳转到定义处 12 | ctrl+t - 从定义处跳转回来 13 | ctrl+w ctrl+] - 水平分割窗口,并在上部打开定义所在文件,跳转到定义处 14 | ctrl+\ - 打开新标签页。并跳转到定义处 15 | alt+] - 垂直分割窗口,并在右部打开定义所在文件,跳转到定义处 16 | 17 | 18 | ctrl+鼠标左键 - 跳转到定义处 19 | ctrl+鼠标右键 - 从定义处跳转回来 20 | 21 | some command in use php-vim 22 | 23 | :tabnew[:tabe] - 打开新的标签页 24 | :tabclose[:tabc] - 关闭正在打开的标签页 25 | :vimgrep - 在文件夹中查找 26 | 在当前目录下查找含有“getInfo”的php文档,但不跳到第一个匹配 27 | :vimgrep /getInfo/gj ./*/*.php 28 | 如果要包含子文件夹,则用 29 | :vimgrep /getInfo/gj ./**/*.php 30 | :vim[grep][!] /{pattern}/[g][j] {file} 31 | :cw - 打开quickfix窗口查看匹配结果 32 | 33 | 34 | -------------------------------------------------------------------------------- /ptags.cpp: -------------------------------------------------------------------------------- 1 | // Save this file as ptags.cpp and compile by 2 | // g++ -o ptags ptags.cpp 3 | //***************************************************************** 4 | // Copyright policy is GNU/GPL but additional request is 5 | // that you include author's name and email on all copies 6 | // Author : Al Dev Email: alavoor@yahoo.com 7 | // Usage : ptags *.php3 *.inc 8 | // This will generate a file called tags 9 | //***************************************************************** 10 | #include 11 | #include 12 | #include // for sprintf 13 | #include // for system 14 | #include // for memset 15 | #include // for isspace 16 | 17 | #define BUFF_LEN 1024 18 | #define LOCATION 9 19 | using namespace std; 20 | 21 | char *ltrim(char *dd); 22 | char *rtrim(char *ee); 23 | 24 | main(int argc, char **argv) 25 | { 26 | if (argc < 2) 27 | { 28 | cerr << "\nUsage: " << argv[0] << " file .... " << endl; 29 | exit(0); 30 | } 31 | 32 | char fname[100] = "tag_file.out"; 33 | FILE *fpout; 34 | ofstream fout(fname); 35 | if (fout.fail()) 36 | { 37 | cerr << "\nError opening file : " << fname << endl; 38 | exit(-1); 39 | } 40 | //fpout = fopen(fname, "w"); 41 | 42 | for (int ii = 1; ii < argc; ii++) 43 | { 44 | /* 45 | char buff[2024]; 46 | 47 | sprintf(buff, "\\rm -f %s; ls %s > %s 2>/dev/null", outfile, argv[1], outfile); 48 | cout << "\nbuff = " << buff << endl; 49 | 50 | system(buff); 51 | fclose(fp); 52 | */ 53 | FILE *fpin = NULL; 54 | fpin = fopen(argv[ii], "r"); 55 | if (fpin == NULL) 56 | { 57 | cerr << "\nError opening file : " << argv[ii] << endl; 58 | exit(-1); 59 | } 60 | char buff[BUFF_LEN + 100]; 61 | memset(buff, 0, BUFF_LEN +10); 62 | for ( ; fgets(buff, BUFF_LEN, fpin) != NULL; ) 63 | { 64 | char aa[BUFF_LEN + 100]; 65 | char aapointer[BUFF_LEN + 100]; 66 | memset(aa, 0, BUFF_LEN +10); 67 | strcpy(aa, buff); 68 | strcpy(aapointer, ltrim(aa)); 69 | strcpy(aa, aapointer); 70 | 71 | // Remove the trailing new line.. 72 | { 73 | int tmpii = strlen(aa); 74 | if (aa[tmpii-1] == '\n') 75 | aa[tmpii-1] = 0; 76 | } 77 | //cout << "aa is : " << aa << endl; 78 | //cout << "aapointer is : " << aapointer << endl; 79 | if (strncmp(aa, "function ", LOCATION) != 0) 80 | continue; 81 | //cout << buff << endl; 82 | 83 | // Example tags file output is like - 84 | // al2 al.c /^al2()$/;" f 85 | { 86 | char bb[BUFF_LEN + 100]; 87 | memset(bb, 0, BUFF_LEN +10); 88 | strcpy(bb, & aa[LOCATION]); 89 | char *cc = bb; 90 | while (cc != NULL && *cc != '(') 91 | *cc++; 92 | *cc = 0; 93 | cc = rtrim(bb); 94 | //cout << "bb is : " << bb << endl; 95 | //cout << cc << "\t" << argv[ii] << "\t" << "/^" << aa << "$/;\"\tf" << endl; 96 | fout << cc << "\t" << argv[ii] << "\t" << "/^" << aa << "$/;\"\tf" << endl; 97 | //fprintf(fpout, "%s\t%s\t/^%s$/;\"f\n", cc, argv[ii], aa ); 98 | } 99 | 100 | memset(buff, 0, BUFF_LEN +10); 101 | } 102 | fclose(fpin); 103 | } 104 | fout.flush(); 105 | fout.close(); 106 | //fclose(fpout); 107 | 108 | // Sort and generate the tag file 109 | { 110 | char tmpaa[1024]; 111 | sprintf(tmpaa, "sort %s > tags; \\rm -f %s", fname, fname); 112 | system(tmpaa); 113 | } 114 | } 115 | 116 | char *ltrim(char *dd) 117 | { 118 | if (dd == NULL) 119 | return NULL; 120 | 121 | while (isspace(*dd)) 122 | dd++; 123 | 124 | return dd; 125 | } 126 | 127 | char *rtrim(char *ee) 128 | { 129 | if (ee == NULL) 130 | return NULL; 131 | 132 | int tmpii = strlen(ee) - 1; 133 | for (; tmpii >= 0 ; tmpii--) 134 | { 135 | if (isspace(ee[tmpii]) ) 136 | { 137 | //cout << "\nis a space!!" << endl; 138 | ee[tmpii] = 0; 139 | } 140 | } 141 | return ee; 142 | } -------------------------------------------------------------------------------- /vimfiles/.netrwhist: -------------------------------------------------------------------------------- 1 | let g:netrw_dirhistmax =10 2 | let g:netrw_dirhist_cnt =3 3 | let g:netrw_dirhist_1='/var/log/httpd' 4 | let g:netrw_dirhist_2='/var/www/html' 5 | let g:netrw_dirhist_3='/usr/share/vim/vimfiles/phpm/phpdoc/en/reference/zlib/functions' 6 | -------------------------------------------------------------------------------- /vimfiles/after/plugin/TabularMaps.vim: -------------------------------------------------------------------------------- 1 | if !exists(':Tabularize') 2 | finish " Tabular.vim wasn't loaded 3 | endif 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | AddTabularPattern! assignment /[|&+*/%<>=!~-]\@!=]=\|=\~\)\@![|&+*/%<>=!~-]*=/l1r1 9 | AddTabularPattern! two_spaces / /l0 10 | 11 | AddTabularPipeline! multiple_spaces / / map(a:lines, "substitute(v:val, ' *', ' ', 'g')") | tabular#TabularizeStrings(a:lines, ' ', 'l0') 12 | 13 | AddTabularPipeline! argument_list /(.*)/ map(a:lines, 'substitute(v:val, ''\s*\([(,)]\)\s*'', ''\1'', ''g'')') 14 | \ | tabular#TabularizeStrings(a:lines, '[(,)]', 'l0') 15 | \ | map(a:lines, 'substitute(v:val, ''\(\s*\),'', '',\1 '', "g")') 16 | \ | map(a:lines, 'substitute(v:val, ''\s*)'', ")", "g")') 17 | 18 | function! SplitCDeclarations(lines) 19 | let rv = [] 20 | for line in a:lines 21 | " split the line into declaractions 22 | let split = split(line, '\s*[,;]\s*') 23 | " separate the type from the first declaration 24 | let type = substitute(split[0], '\%(\%([&*]\s*\)*\)\=\k\+$', '', '') 25 | " add the ; back on every declaration 26 | call map(split, 'v:val . ";"') 27 | " add the first element to the return as-is, and remove it from the list 28 | let rv += [ remove(split, 0) ] 29 | " transform the other elements by adding the type on at the beginning 30 | call map(split, 'type . v:val') 31 | " and add them all to the return 32 | let rv += split 33 | endfor 34 | return rv 35 | endfunction 36 | 37 | AddTabularPipeline! split_declarations /,.*;/ SplitCDeclarations(a:lines) 38 | 39 | AddTabularPattern! ternary_operator /^.\{-}\zs?\|:/l1 40 | 41 | AddTabularPattern! cpp_io /<<\|>>/l1 42 | 43 | AddTabularPattern! pascal_assign /:=/l1 44 | 45 | AddTabularPattern! trailing_c_comments /\/\*\|\*\/\|\/\//l1 46 | 47 | let &cpo = s:save_cpo 48 | unlet s:save_cpo 49 | -------------------------------------------------------------------------------- /vimfiles/autoload/checksyntax.vim: -------------------------------------------------------------------------------- 1 | " checksyntax.vim 2 | " @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) 3 | " @Website: http://www.vim.org/account/profile.php?user_id=4037 4 | " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) 5 | " @Created: 2010-01-03. 6 | " @Last Change: 2011-07-04. 7 | " @Revision: 283 8 | 9 | 10 | if !exists('g:checksyntax#failrx') 11 | let g:checksyntax#failrx = '\ *\(\d \f\{-}:\)\?\d\{-}:' 12 | endif 13 | 14 | if !exists('g:checksyntax#okrx') 15 | let g:checksyntax#okrx = '' 16 | endif 17 | 18 | if !exists('g:checksyntax') 19 | " A dictionary {name/filetype => definition} of syntax checkers, where 20 | " definition is a dictionary with the following fields: 21 | " 22 | " Mandatory (either one of the following): 23 | " cmd ... A shell command used as 'makeprg' to check the file. 24 | " exec ... A vim command used to check the file. 25 | " compiler ... A vim compiler that is used to check the file. 26 | " 27 | " Optional: 28 | " auto ... Run automatically when saving a file. 29 | " efm ... An 'errorformat' string. 30 | " okrx ... A |regexp| matching the command output if no error were 31 | " found. 32 | " failrx ... A |regexp| matching the command output if an error 33 | " was found. 34 | " alt ... The name of an alternative syntax checker (see 35 | " |:CheckSyntax|). 36 | " prepare ... An ex command that is run before doing anything. 37 | " ignore_nr ... A list of error numbers that should be ignored. 38 | let g:checksyntax = {} "{{{2 39 | endif 40 | 41 | 42 | """ Php 43 | if !exists('g:checksyntax.php') 44 | let g:checksyntax['php'] = { 45 | \ 'auto': executable('php') == 1, 46 | \ 'cmd': 'php -l', 47 | \ 'efm': '%*[^:]: %m in %f on line %l', 48 | \ 'okrx': 'No syntax errors detected in ', 49 | \ 'alt': 'phpp' 50 | \ } 51 | endif 52 | 53 | 54 | """""" Parse php 55 | if !exists('g:checksyntax.phpp') 56 | let g:checksyntax['phpp'] = { 57 | \ 'cmd': 'php -f', 58 | \ 'efm': g:checksyntax.php.efm, 59 | \ 'okrx': g:checksyntax.php.okrx 60 | \ } 61 | endif 62 | 63 | autocmd CheckSyntax BufReadPost *.php if exists(':EclimValidate') && !empty(eclim#project#util#GetCurrentProjectName()) | let g:checksyntax.php.auto = 0 | endif 64 | 65 | 66 | """ JavaScript 67 | if !exists('g:checksyntax.javascript') 68 | if exists('g:checksyntax_javascript') ? (g:checksyntax_javascript == 'gjslint') : executable('gjslint') 69 | let g:checksyntax['javascript'] = { 70 | \ 'cmd': 'gjslint', 71 | \ 'ignore_nr': [1, 110], 72 | \ 'efm': '%P%*[^F]FILE%*[^:]: %f %*[-],Line %l%\, %t:%n: %m,%Q', 73 | \ } 74 | elseif exists('g:checksyntax_javascript') ? (g:checksyntax_javascript == 'jsl') : executable('jsl') 75 | let g:checksyntax['javascript'] = { 76 | \ 'cmd': 'jsl -nofilelisting -nocontext -nosummary -nologo -process', 77 | \ 'okrx': '0 error(s), 0 warning(s)', 78 | \ } 79 | endif 80 | endif 81 | 82 | 83 | """ Python 84 | if !exists('g:checksyntax.python') 85 | let g:checksyntax['python'] = { 86 | \ 'cmd': 'pyflakes', 87 | \ 'alt': 'pylint' 88 | \ } 89 | endif 90 | 91 | if !exists('g:checksyntax.pylint') 92 | let g:checksyntax['pylint'] = { 93 | \ 'compiler': 'pylint' 94 | \ } 95 | endif 96 | 97 | 98 | """ Ruby 99 | if !exists('g:checksyntax.ruby') 100 | let g:checksyntax['ruby'] = { 101 | \ 'prepare': 'compiler ruby', 102 | \ 'cmd': 'ruby -c', 103 | \ 'okrx': 'Syntax OK\|No Errors' 104 | \ } 105 | endif 106 | 107 | 108 | """ Viki 109 | if !exists('g:checksyntax.viki') 110 | let g:checksyntax['viki'] = { 111 | \ 'cmd': 'deplate -f null', 112 | \ } 113 | endif 114 | 115 | 116 | """ chktex (LaTeX) 117 | if !exists('g:checksyntax.tex') 118 | if executable('chktex') 119 | let g:checksyntax['tex'] = { 120 | \ 'cmd': 'chktex -q -v0', 121 | \ 'efm': '%f:%l:%m', 122 | \ } 123 | endif 124 | endif 125 | 126 | 127 | """ c, cpp 128 | if !exists('g:checksyntax.c') 129 | if executable('splint') 130 | let g:checksyntax['c'] = { 131 | \ 'compiler': 'splint', 132 | \ } 133 | endif 134 | endif 135 | 136 | if !exists('g:checksyntax.cpp') && exists('g:checksyntax.c') 137 | let g:checksyntax['cpp'] = copy(g:checksyntax.c) 138 | endif 139 | 140 | 141 | """ java 142 | if !exists('g:checksyntax.java') 143 | if executable('jlint') 144 | let g:checksyntax['java'] = { 145 | \ 'exec': 'call checksyntax#Jlint()', 146 | \ 'alt': 'javaCheckstyle' 147 | \ } 148 | 149 | " :nodoc: 150 | function! checksyntax#Jlint() "{{{3 151 | let filename = expand('%:r') .'.class' 152 | " TLogVAR filename 153 | " echom '! jlint -done '. shellescape(filename) 154 | exec '! jlint -done '. shellescape(filename) 155 | endf 156 | endif 157 | endif 158 | 159 | if !exists('g:checksyntax.javaCheckstyle') 160 | if executable('checkstyle') 161 | let g:checksyntax['javaCheckstyle'] = { 162 | \ 'compiler': 'checkstyle', 163 | \ } 164 | endif 165 | endif 166 | 167 | 168 | """ lua 169 | if !exists('g:checksyntax.lua') 170 | " efm: File:Line:Column:Warning number:Warning message 171 | let g:checksyntax['lua'] = { 172 | \ 'auto': executable('luac') == 1, 173 | \ 'cmd': 'luac -p', 174 | \ 'efm': 'luac\:\ %f:%l:\ %m' 175 | \ } 176 | endif 177 | 178 | 179 | """ tidy (HTML) 180 | if !exists('g:checksyntax.html') 181 | let g:checksyntax['html'] = { 182 | \ 'cmd': 'tidy -eq', 183 | \ 'efm': 'line %l column %c - %m' 184 | \ } 185 | endif 186 | if !exists('g:checksyntax.xhtml') 187 | let g:checksyntax['xhtml'] = copy(g:checksyntax.html) 188 | endif 189 | 190 | 191 | """ XML 192 | if !exists('g:checksyntax.xml') 193 | let g:checksyntax['xml'] = { 194 | \ 'compiler': 'xmllint' 195 | \ } 196 | endif 197 | if !exists('g:checksyntax.docbk') 198 | let g:checksyntax['docbk'] = copy(g:checksyntax.xml) 199 | endif 200 | 201 | 202 | if !exists('*CheckSyntaxSucceed') 203 | " :nodoc: 204 | function! CheckSyntaxSucceed(type, manually) 205 | call s:prototypes[a:type].Close() 206 | if a:manually 207 | echo 208 | echo 'Syntax ok.' 209 | endif 210 | endf 211 | endif 212 | 213 | 214 | if !exists('*CheckSyntaxFail') 215 | " :nodoc: 216 | function! CheckSyntaxFail(type, manually) 217 | call s:prototypes[a:type].Open() 218 | endf 219 | endif 220 | 221 | 222 | let s:prototypes = {'loc': {}, 'qfl': {}} 223 | 224 | function! s:prototypes.loc.Close() dict "{{{3 225 | lclose 226 | endf 227 | 228 | function! s:prototypes.loc.Open() dict "{{{3 229 | lopen 230 | endf 231 | 232 | function! s:prototypes.loc.Make(args) dict "{{{3 233 | exec 'silent lmake' a:args 234 | endf 235 | 236 | function! s:prototypes.loc.Get() dict "{{{3 237 | return copy(getloclist(0)) 238 | endf 239 | 240 | function! s:prototypes.loc.Set(list) dict "{{{3 241 | call setloclist(0, a:list) 242 | endf 243 | 244 | 245 | function! s:prototypes.qfl.Close() dict "{{{3 246 | cclose 247 | endf 248 | 249 | function! s:prototypes.qfl.Open() dict "{{{3 250 | copen 251 | endf 252 | 253 | function! s:prototypes.qfl.Make(args) dict "{{{3 254 | exec 'silent make' a:args 255 | endf 256 | 257 | function! s:prototypes.qfl.Get() dict "{{{3 258 | return copy(getqflist()) 259 | endf 260 | 261 | function! s:prototypes.qfl.Set(list) dict "{{{3 262 | call setqflist(a:list) 263 | endf 264 | 265 | 266 | function! s:Make(def) 267 | let bufnr = bufnr('%') 268 | let pos = getpos('.') 269 | let type = get(a:def, 'listtype', 'loc') 270 | try 271 | if has_key(a:def, 'compiler') 272 | 273 | if exists('g:current_compiler') 274 | let cc = g:current_compiler 275 | else 276 | let cc = '' 277 | endif 278 | try 279 | exec 'compiler '. a:def.compiler 280 | call s:prototypes[type].Make('') 281 | return 1 282 | finally 283 | if cc != '' 284 | let g:current_compiler = cc 285 | exec 'compiler '. cc 286 | endif 287 | endtry 288 | 289 | else 290 | 291 | let makeprg = &makeprg 292 | let shellpipe = &shellpipe 293 | let errorformat = &errorformat 294 | if has_key(a:def, 'shellpipe') 295 | let &l:shellpipe = get(a:def, 'shellpipe') 296 | endif 297 | if has_key(a:def, 'efm') 298 | let &l:errorformat = get(a:def, 'efm') 299 | endif 300 | try 301 | if has_key(a:def, 'cmd') 302 | let &l:makeprg = a:def.cmd 303 | " TLogVAR &l:makeprg, &l:errorformat 304 | call s:prototypes[type].Make('%') 305 | return 1 306 | elseif has_key(a:def, 'exec') 307 | exec a:def.exec 308 | return 1 309 | endif 310 | finally 311 | if &l:makeprg != makeprg 312 | let &l:makeprg = makeprg 313 | endif 314 | if &l:shellpipe != shellpipe 315 | let &l:shellpipe = shellpipe 316 | endif 317 | if &l:errorformat != errorformat 318 | let &l:errorformat = errorformat 319 | endif 320 | endtry 321 | 322 | endif 323 | catch 324 | echohl Error 325 | echom v:errmsg 326 | echohl NONE 327 | finally 328 | " TLogVAR pos, bufnr 329 | if bufnr != bufnr('%') 330 | exec bufnr 'buffer' 331 | endif 332 | call setpos('.', pos) 333 | endtry 334 | return 0 335 | endf 336 | 337 | 338 | function! s:GetDef(ft) "{{{3 339 | if exists('b:checksyntax') && has_key(b:checksyntax, a:ft) 340 | return b:checksyntax[a:ft] 341 | elseif has_key(g:checksyntax, a:ft) 342 | return g:checksyntax[a:ft] 343 | else 344 | return {} 345 | endif 346 | endf 347 | 348 | 349 | " :def: function! checksyntax#Check(manually, ?bang='', ?type=&ft) 350 | function! checksyntax#Check(manually, ...) 351 | let bang = a:0 >= 1 && a:1 != '' ? 1 : 0 352 | let ft = a:0 >= 2 && a:2 != '' ? a:2 : &filetype 353 | let def = a:manually ? {} : s:GetDef(ft .',auto') 354 | if empty(def) 355 | let def = s:GetDef(ft) 356 | endif 357 | if &modified 358 | if has_key(def, 'modified') 359 | let def = s:GetDef(def.modified) 360 | else 361 | echohl WarningMsg 362 | echom "Buffer was modified. Please save it before calling :CheckSyntax." 363 | echohl NONE 364 | return 365 | endif 366 | endif 367 | if bang && has_key(def, 'alt') 368 | let def = s:GetDef(def.alt) 369 | endif 370 | " TLogVAR def 371 | if empty(def) 372 | return 373 | endif 374 | let auto = get(def, 'auto', 0) 375 | " TLogVAR auto 376 | if !(a:manually || auto) 377 | return 378 | endif 379 | " TLogVAR &makeprg, &l:makeprg, &g:makeprg, &errorformat 380 | exec get(def, 'prepare', '') 381 | if s:Make(def) 382 | let failrx = get(def, 'failrx', g:checksyntax#failrx) 383 | let okrx = get(def, 'okrx', g:checksyntax#okrx) 384 | let type = get(def, 'listtype', 'loc') 385 | let list = s:prototypes[type].Get() 386 | let list = filter(list, 's:FilterItem(def, v:val)') 387 | let list = map(list, 's:CompleteItem(def, v:val)') 388 | call s:prototypes[type].Set(list) 389 | " echom "DBG 1" string(list) 390 | redraw! 391 | if len(list) == 0 392 | call CheckSyntaxSucceed(type, a:manually) 393 | else 394 | call CheckSyntaxFail(type, a:manually) 395 | endif 396 | endif 397 | endf 398 | 399 | 400 | function! s:CompleteItem(def, val) "{{{3 401 | if get(a:val, 'bufnr', 0) == 0 402 | let a:val.bufnr = bufnr('%') 403 | endif 404 | return a:val 405 | endf 406 | 407 | 408 | function! s:FilterItem(def, val) "{{{3 409 | if a:val.lnum == 0 && a:val.pattern == '' 410 | return 0 411 | elseif has_key(a:val, 'nr') && has_key(a:def, 'ignore_nr') && index(a:def.ignore_nr, a:val.nr) != -1 412 | return 0 413 | endif 414 | return 1 415 | endf 416 | 417 | -------------------------------------------------------------------------------- /vimfiles/autoload/tabular.vim: -------------------------------------------------------------------------------- 1 | " Tabular: Align columnar data using regex-designated column boundaries 2 | " Maintainer: Matthew Wozniski (mjw@drexel.edu) 3 | " Date: Thu, 11 Oct 2007 00:35:34 -0400 4 | " Version: 0.1 5 | 6 | " Stupid vimscript crap {{{1 7 | let s:savecpo = &cpo 8 | set cpo&vim 9 | 10 | " Private Functions {{{1 11 | 12 | " Return the number of bytes in a string after expanding tabs to spaces. {{{2 13 | " This expansion is done based on the current value of 'tabstop' 14 | function! s:Strlen(string) 15 | let rv = 0 16 | let i = 0 17 | 18 | for char in split(a:string, '\zs') 19 | if char == "\t" 20 | let rv += &ts - i 21 | let i = 0 22 | else 23 | let rv += 1 24 | let i = (i + 1) % &ts 25 | endif 26 | endfor 27 | 28 | return rv 29 | endfunction 30 | 31 | " Align a string within a field {{{2 32 | " These functions do not trim leading and trailing spaces. 33 | 34 | " Right align 'string' in a field of size 'fieldwidth' 35 | function! s:Right(string, fieldwidth) 36 | let spaces = a:fieldwidth - s:Strlen(a:string) 37 | return matchstr(a:string, '^\s*') . repeat(" ", spaces) . substitute(a:string, '^\s*', '', '') 38 | endfunction 39 | 40 | " Left align 'string' in a field of size 'fieldwidth' 41 | function! s:Left(string, fieldwidth) 42 | let spaces = a:fieldwidth - s:Strlen(a:string) 43 | return a:string . repeat(" ", spaces) 44 | endfunction 45 | 46 | " Center align 'string' in a field of size 'fieldwidth' 47 | function! s:Center(string, fieldwidth) 48 | let spaces = a:fieldwidth - s:Strlen(a:string) 49 | let right = spaces / 2 50 | let left = right + (right * 2 != spaces) 51 | return repeat(" ", left) . a:string . repeat(" ", right) 52 | endfunction 53 | 54 | " Remove spaces around a string {{{2 55 | 56 | " Remove all trailing spaces from a string. 57 | function! s:StripTrailingSpaces(string) 58 | return matchstr(a:string, '^.\{-}\ze\s*$') 59 | endfunction 60 | 61 | " Remove all leading spaces from a string. 62 | function! s:StripLeadingSpaces(string) 63 | return matchstr(a:string, '^\s*\zs.*$') 64 | endfunction 65 | 66 | " Split a string into fields and delimiters {{{2 67 | " Like split(), but include the delimiters as elements 68 | " All odd numbered elements are delimiters 69 | " All even numbered elements are non-delimiters (including zero) 70 | function! s:SplitDelim(string, delim) 71 | let rv = [] 72 | let beg = 0 73 | 74 | let len = len(a:string) 75 | let searchoff = 0 76 | 77 | while 1 78 | let mid = match(a:string, a:delim, beg + searchoff, 1) 79 | if mid == -1 || mid == len 80 | break 81 | endif 82 | 83 | let matchstr = matchstr(a:string, a:delim, beg + searchoff, 1) 84 | let length = strlen(matchstr) 85 | 86 | if length == 0 && beg == mid 87 | " Zero-length match for a zero-length delimiter - advance past it 88 | let searchoff += 1 89 | continue 90 | endif 91 | 92 | if beg == mid 93 | let rv += [ "" ] 94 | else 95 | let rv += [ a:string[beg : mid-1] ] 96 | endif 97 | 98 | let rv += [ matchstr ] 99 | 100 | let beg = mid + length 101 | let searchoff = 0 102 | endwhile 103 | 104 | let rv += [ strpart(a:string, beg) ] 105 | 106 | return rv 107 | endfunction 108 | 109 | " Replace lines from `start' to `start + len - 1' with the given strings. {{{2 110 | " If more lines are needed to show all strings, they will be added. 111 | " If there are too few strings to fill all lines, lines will be removed. 112 | function! s:SetLines(start, len, strings) 113 | if a:start > line('$') + 1 || a:start < 1 114 | throw "Invalid start line!" 115 | endif 116 | 117 | if len(a:strings) > a:len 118 | let fensave = &fen 119 | let view = winsaveview() 120 | call append(a:start + a:len - 1, repeat([''], len(a:strings) - a:len)) 121 | call winrestview(view) 122 | let &fen = fensave 123 | elseif len(a:strings) < a:len 124 | let fensave = &fen 125 | let view = winsaveview() 126 | sil exe (a:start + len(a:strings)) . ',' . (a:start + a:len - 1) . 'd_' 127 | call winrestview(view) 128 | let &fen = fensave 129 | endif 130 | 131 | call setline(a:start, a:strings) 132 | endfunction 133 | 134 | " Runs the given commandstring argument as an expression. {{{2 135 | " The commandstring expression is expected to reference the a:lines argument. 136 | " If the commandstring expression returns a list the items of that list will 137 | " replace the items in a:lines, otherwise the expression is assumed to have 138 | " modified a:lines itself. 139 | function! s:FilterString(lines, commandstring) 140 | exe 'let rv = ' . a:commandstring 141 | 142 | if type(rv) == type(a:lines) && rv isnot a:lines 143 | call filter(a:lines, 0) 144 | call extend(a:lines, rv) 145 | endif 146 | endfunction 147 | 148 | " Public API {{{1 149 | 150 | if !exists("g:tabular_default_format") 151 | let g:tabular_default_format = "l1" 152 | endif 153 | 154 | let s:formatelempat = '\%([lrc]\d\+\)' 155 | 156 | function! tabular#ElementFormatPattern() 157 | return s:formatelempat 158 | endfunction 159 | 160 | " Given a list of strings and a delimiter, split each string on every 161 | " occurrence of the delimiter pattern, format each element according to either 162 | " the provided format (optional) or the default format, and join them back 163 | " together with enough space padding to guarantee that the nth delimiter of 164 | " each string is aligned. 165 | function! tabular#TabularizeStrings(strings, delim, ...) 166 | if a:0 > 1 167 | echoerr "TabularizeStrings accepts only 2 or 3 arguments (got ".(a:0+2).")" 168 | return 1 169 | endif 170 | 171 | let formatstr = (a:0 ? a:1 : g:tabular_default_format) 172 | 173 | if formatstr !~? s:formatelempat . '\+' 174 | echoerr "Tabular: Invalid format \"" . formatstr . "\" specified!" 175 | return 1 176 | endif 177 | 178 | let format = split(formatstr, s:formatelempat . '\zs') 179 | 180 | let lines = map(a:strings, 's:SplitDelim(v:val, a:delim)') 181 | 182 | " Strip spaces 183 | " - Only from non-delimiters; spaces in delimiters must have been matched 184 | " intentionally 185 | " - Don't strip leading spaces from the first element; we like indenting. 186 | for line in lines 187 | if line[0] !~ '^\s*$' 188 | let line[0] = s:StripTrailingSpaces(line[0]) 189 | endif 190 | if len(line) >= 3 191 | for i in range(2, len(line)-1, 2) 192 | let line[i] = s:StripLeadingSpaces(s:StripTrailingSpaces(line[i])) 193 | endfor 194 | endif 195 | endfor 196 | 197 | " Find the max length of each field 198 | let maxes = [] 199 | for line in lines 200 | for i in range(len(line)) 201 | if i == len(maxes) 202 | let maxes += [ s:Strlen(line[i]) ] 203 | else 204 | let maxes[i] = max( [ maxes[i], s:Strlen(line[i]) ] ) 205 | endif 206 | endfor 207 | endfor 208 | 209 | let lead_blank = empty(filter(copy(lines), 'v:val[0] =~ "\\S"')) 210 | 211 | " Concatenate the fields, according to the format pattern. 212 | for idx in range(len(lines)) 213 | let line = lines[idx] 214 | for i in range(len(line)) 215 | let how = format[i % len(format)][0] 216 | let pad = format[i % len(format)][1:-1] 217 | 218 | if how =~? 'l' 219 | let field = s:Left(line[i], maxes[i]) 220 | elseif how =~? 'r' 221 | let field = s:Right(line[i], maxes[i]) 222 | elseif how =~? 'c' 223 | let field = s:Center(line[i], maxes[i]) 224 | endif 225 | 226 | let line[i] = field . (lead_blank && i == 0 ? '' : repeat(" ", pad)) 227 | endfor 228 | 229 | let lines[idx] = s:StripTrailingSpaces(join(line, '')) 230 | endfor 231 | endfunction 232 | 233 | " Apply 0 or more filters, in sequence, to selected text in the buffer {{{2 234 | " The lines to be filtered are determined as follows: 235 | " If the function is called with a range containing multiple lines, then 236 | " those lines will be used as the range. 237 | " If the function is called with no range or with a range of 1 line, then 238 | " if "includepat" is not specified, 239 | " that 1 line will be filtered, 240 | " if "includepat" is specified and that line does not match it, 241 | " no lines will be filtered 242 | " if "includepat" is specified and that line does match it, 243 | " all contiguous lines above and below the specified line matching the 244 | " pattern will be filtered. 245 | " 246 | " The remaining arguments must each be a filter to apply to the text. 247 | " Each filter must either be a String evaluating to a function to be called. 248 | function! tabular#PipeRange(includepat, ...) range 249 | let top = a:firstline 250 | let bot = a:lastline 251 | 252 | if a:includepat != '' && top == bot 253 | if top < 0 || top > line('$') || getline(top) !~ a:includepat 254 | return 255 | endif 256 | while top > 1 && getline(top-1) =~ a:includepat 257 | let top -= 1 258 | endwhile 259 | while bot < line('$') && getline(bot+1) =~ a:includepat 260 | let bot += 1 261 | endwhile 262 | endif 263 | 264 | let lines = map(range(top, bot), 'getline(v:val)') 265 | 266 | for filter in a:000 267 | if type(filter) != type("") 268 | echoerr "PipeRange: Bad filter: " . string(filter) 269 | endif 270 | 271 | call s:FilterString(lines, filter) 272 | 273 | unlet filter 274 | endfor 275 | 276 | call s:SetLines(top, bot - top + 1, lines) 277 | endfunction 278 | 279 | function! s:SplitDelimTest(string, delim, expected) 280 | let result = s:SplitDelim(a:string, a:delim) 281 | 282 | if result !=# a:expected 283 | echomsg 'Test failed!' 284 | echomsg ' string=' . string(a:string) . ' delim=' . string(a:delim) 285 | echomsg ' Returned=' . string(result) 286 | echomsg ' Expected=' . string(a:expected) 287 | endif 288 | endfunction 289 | 290 | function! tabular#SplitDelimUnitTest() 291 | let assignment = '[|&+*/%<>=!~-]\@!=]=\|=\~\)\@![|&+*/%<>=!~-]*=' 292 | let two_spaces = ' ' 293 | let ternary_operator = '^.\{-}\zs?\|:' 294 | let cpp_io = '<<\|>>' 295 | let pascal_assign = ':=' 296 | let trailing_c_comments = '\/\*\|\*\/\|\/\/' 297 | 298 | call s:SplitDelimTest('a+=b', assignment, ['a', '+=', 'b']) 299 | call s:SplitDelimTest('a-=b', assignment, ['a', '-=', 'b']) 300 | call s:SplitDelimTest('a!=b', assignment, ['a!=b']) 301 | call s:SplitDelimTest('a==b', assignment, ['a==b']) 302 | call s:SplitDelimTest('a&=b', assignment, ['a', '&=', 'b']) 303 | call s:SplitDelimTest('a|=b', assignment, ['a', '|=', 'b']) 304 | call s:SplitDelimTest('a=b=c', assignment, ['a', '=', 'b', '=', 'c']) 305 | 306 | call s:SplitDelimTest('a b c', two_spaces, ['a', ' ', 'b', ' ', 'c']) 307 | call s:SplitDelimTest('a b c', two_spaces, ['a b', ' ', ' c']) 308 | call s:SplitDelimTest('ab c', two_spaces, ['ab', ' ', '', ' ', 'c']) 309 | 310 | call s:SplitDelimTest('a?b:c', ternary_operator, ['a', '?', 'b', ':', 'c']) 311 | 312 | call s:SplitDelimTest('a<