""""""""""""""""""""""""""""""""""""""""" " Author : lucasysfeng " Email : [email protected] " Blog : http://cnblogs.com/lucasysfeng " ReadMe : README.md " Version : 1.0 - Jan. 16,2014 " Contents : -> 基础配置设置 " -> 自定义快捷键 " -> 主题颜色显示 " -> 其它杂项配置 " -> 插件管理配置 " -> 自定义的函数 """"""""""""""""""""""""""""""""""""""""" """"""""""""""""""""""""""""""""""""""""" " 基础配置设置 """"""""""""""""""""""""""""""""""""""""" filetype on "检测文件类型 filetype indent on "针对不同的文件类型采用不同的缩进格式 filetype plugin on "允许插件 filetype plugin indent on "启动自动补全 set nobackup "不自动保存 "set paste set relativenumber number "相对行号,可用Ctrl+n在相对/绝对行号间切换 set history=2000 "history存储长度 set nocompatible "非兼容vi模式,避免以前版本的一些bug和局限 set autoread "文件修改之后自动载入 set shortmess=atI "启动的时候不显示那个援助索马里儿童的提示 set t_ti= t_te= "退出vim后,内容显示在终端屏幕 set title "change the terminal's title set novisualbell "don't beep set noerrorbells "don't beep set t_vb= set tm=500 set mat=2 "Blink times every second when matching brackets set showmatch "括号配对情况 set hidden "A buffer becomes hidden when it is abandoned set wildmode=list:longest set ttyfast set wildignore=*.swp,*.,*.pyc,*.class set scrolloff=7 "至少有7行在光标所在行上下 set mouse=a "为所有模式启用鼠标 set selection=old set selectmode=mouse,key set viminfo^=% "Remember info about open buffers on close set magic "正则表达式匹配形式 set backspace=eol,start,indent "Configure backspace so it acts as it should act set whichwrap+=<,>,h,l " 搜索 """"""""""""""""""""""""""""""""""""""""" set hlsearch "高亮search命中的文本。 set ignorecase "搜索时忽略大小写 set incsearch "随着键入即时搜索 set smartcase "有一个或以上大写字母时仍大小写敏感 " 折叠 """"""""""""""""""""""""""""""""""""""""" set foldenable set foldmethod=indent set foldlevel=99 " 缩进 """"""""""""""""""""""""""""""""""""""""" set smartindent "智能缩进 set autoindent "总是自动缩进 set tabstop=4 "设置Tab键的宽度(等同的空格个数) set shiftwidth=4 "自动对齐的空格数 set softtabstop=4 "按退格键时可以一次删掉4个空格 set smarttab "insert tabs on the start of a line according to shiftwidth, not tabstop set expandtab "将Tab自动转化成空格(需要输入真正的Tab键时,使用Ctrl+V+Tab) set shiftround "Use multiple of shiftwidth when indenting with '<' and '>' " 编码 """"""""""""""""""""""""""""""""""""""""" set encoding=utf-8 set fileencodings=ucs-bom,utf-8,cp936,gb18030,chinese,big5,euc-jp,euc-kr,latin1 set fileencoding=utf-8 set helplang=cn set termencoding=utf-8 "这句只影响普通模式 (非图形界面) 下的Vim set ffs=unix,dos,mac "Use Unix as the standard file type set formatoptions+=m "如遇Unicode值大于255的文本,不必等到空格再折行。 set formatoptions+=B "合并两行中文时,不在中间加空格: " 语法 """"""""""""""""""""""""""""""""""""""""" syntax enable "打开语法高亮 syntax on " 撤销 """"""""""""""""""""""""""""""""""""""""" set undolevels=1000 "How many undos set undoreload=10000 "number of lines to save for undo if v:version >= 730 set undofile "keep a persistent backup file set undodir=~/bak/vimundo/ endif " 状态栏 """"""""""""""""""""""""""""""""""""""""" set ruler "显示当前的行号列号 set showcmd "在状态栏显示正在输入的命令 set showmode set statusline=%<%f\ %h%m%r%=%k[%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}]\ %-14.(%l,%c%V%)\ %P set laststatus=2 "命令行(在状态行下)的高度,默认为1,这里是2 " 相对绝对行号 """"""""""""""""""""""""""""""""""""""""" "autocmd FocusLost * :set norelativenumber number autocmd FocusGained * :set relativenumber autocmd InsertEnter * :set norelativenumber number autocmd InsertLeave * :set relativenumber "set cursorline "突出显示当前行,可用Ctrl+k切换是否显示 "set cursorcolumn "突出显示当前列,可用Ctrl+k切换是否显示 "set backup "备份 " 退出插入模式时自动保存 "autocmd InsertLeave * :w!<ESC> """"""""""""""""""""""""""""""""""""""""" " 自定义快捷键 """"""""""""""""""""""""""""""""""""""""" " 前导符号 """"""""""""""""""""""""""""""""""""""""" let mapleader = ',' let g:mapleader = ',' " 常用快捷键 """"""""""""""""""""""""""""""""""""""""" " 到行首行尾 noremap H ^ noremap L $ " 到光标所在行第一个非空字符 "map 0 ^ " 从光标处复制到行尾,不包括行尾结束符 map Y y$ " t/T增加空行 nmap t o<ESC> nmap T O<ESC> " 恢复撤销 nnoremap U <C-r> " 保存 map <leader>w :w!<cr> " 保存并退出当前窗口 map <leader>q :wq!<CR> " 保存并挂起 map <leader>z :w!<cr><C-z> " 全选 map <C-a> ggVG " 相对/绝对行号转换 noremap <C-n> :call NumberToggle()<cr> cnoremap <C-n> :call NumberToggle()<cr>: " 突出显示当前行/列开关 map <leader>k :call CusorCulLineToggle()<cr> " 打开/关闭全部折叠 map <leader>o zR map <leader>c zM " 连续按jf退出插入/命令行/可视模式 inoremap jk <ESC>l cnoremap jk <ESC>l vnoremap jf <ESC>l " 选中状态下 Ctrl+c 复制 vmap <C-c> "+y " 按;直接进入命令行模式 nnoremap ; : " 将光标所在行上移或下移一行,^[是按ctrl+v出来的,[k是按Alt+k出来的. "nmap <S-k> :m-2<cr> "nmap <S-j> :m+1<cr> "vmap <S-k> :m-2<cr> "vmap <S-j> :m+1<cr> "nmap k :m-2<cr> "nmap j :m+1<cr> "vmap k :m-2<cr> "vmap j :m+1<cr> nmap <S-j> yyp nmap <S-k> yyp " 搜索查找快捷键 """"""""""""""""""""""""""""""""""""""""" " 替换,匹配模式采用very magic map \ :%s/\v " 查找,匹配模式采用very magic nnoremap / /\v vnoremap / /\v " 去掉查找后的高亮显示 noremap <silent><leader>/ :nohls<CR> " 搜索的内容总是在屏幕中心显示 nnoremap <silent> n nzz nnoremap <silent> N Nzz nnoremap <silent> * *zz nnoremap <silent> # #zz nnoremap <silent> g* g*zz " 普通模式(Nomal Mode)下快捷键 """"""""""""""""""""""""""""""""""""""""" " 快速编辑重vimrc nmap <silent> <leader>ev :e $MYVIMRC<CR> nmap <silent> <leader>sv :so $MYVIMRC<CR> " 快速滚屏 nnoremap <C-e> 2<C-e> nnoremap <C-y> 2<C-y> " 命令行模式(Command Line Mode)下快捷键 """"""""""""""""""""""""""""""""""""""""" cnoremap <C-j> <t_kd> cnoremap <C-k> <t_ku> cnoremap <C-a> <Home> cnoremap <C-e> <End> " 功能键 """"""""""""""""""""""""""""""""""""""""" " F6语法高亮快捷键 nnoremap <F6> :exec exists('syntax_on') ? 'syn off' : 'syn on'<CR> " F7标签导航 "nnoremap <silent> <F7> :TlistToggle<CR> nnoremap <leader>m :TlistToggle<CR> " F8标签导航 "nmap <F8> :TagbarToggle<CR> " 多窗口标签快捷键 """"""""""""""""""""""""""""""""""""""""" " 在多个窗口间切换 map <C-j> <C-W>j map <C-k> <C-W>k map <C-h> <C-W>h map <C-l> <C-W>l " Disbale paste mode when leaving insert mode map <leader>tn :tabnew<cr> map <leader>to :tabonly<cr> map <leader>tc :tabclose<cr> map <leader>tm :tabmove<cr> " Opens a new tab with the current buffer's path " Super useful when editing files in the same directory map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/ " 杂项 """"""""""""""""""""""""""""""""""""""""" " Disbale paste mode when leaving insert mode autocmd InsertLeave * set nopaste " w!! to sudo & write a file cmap w!! w !sudo tee >/dev/null % " Swap implementations of ` and ' jump to markers " By default, ' jumps to the marked line, ` jumps to the marked line and " column, so swap them nnoremap ' ` nnoremap ` ' " Automatically reload vimrc when it's saved autocmd BufWritePost .vimrc so ~/.vimrc " ; can repeat fx/tx. so do not map it nnoremap <leader>v V`} """"""""""""""""""""""""""""""""""""""""" " 主题颜色显示 """"""""""""""""""""""""""""""""""""""""" " Set extra options when running in GUI mode if has("gui_running") set guifont=Monaco:h14 set guioptions-=T set guioptions+=e set guioptions-=r set guioptions-=L set guitablabel=%M\ %t set showtabline=1 set linespace=2 set noimd set t_Co=256 endif " 修改主题和颜色展示 " colorscheme solarized set background=dark set t_Co=256 " colorscheme molokai " colorscheme desert " 设置标记一列的背景颜色和数字一行颜色一致 hi! link SignColumn LineNr hi! link ShowMarksHLl DiffAdd hi! link ShowMarksHLu DiffChange " 防止错误整行标红导致看不清 highlight clear SpellBad highlight SpellBad term=standout ctermfg=1 term=underline cterm=underline highlight clear SpellCap highlight SpellCap term=underline cterm=underline highlight clear SpellRare highlight SpellRare term=underline cterm=underline highlight clear SpellLocal highlight SpellLocal term=underline cterm=underline " settings for kien/rainbow_parentheses.vim autocmd VimEnter * RainbowParenthesesToggle autocmd Syntax * RainbowParenthesesLoadRound autocmd Syntax * RainbowParenthesesLoadSquare autocmd Syntax * RainbowParenthesesLoadBraces """"""""""""""""""""""""""""""""""""""""" " 其它杂项配置 """"""""""""""""""""""""""""""""""""""""" autocmd! bufwritepost _vimrc source % "vimrc文件修改之后自动加载。 windows。 autocmd! bufwritepost .vimrc source % "vimrc文件修改之后自动加载。 linux。 set completeopt=longest,menu "自动补全配置,让Vim的补全菜单行为与一般IDE一致(参考VimTip1228) " 离开插入模式后自动关闭预览窗口 autocmd InsertLeave * if pumvisible() == 0|pclose|endif " 回车即选中当前项 inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>" " 增强模式中的命令行自动完成操作 set wildmenu " Ignore compiled files " set wildignore=*.o,*~,*.pyc,*.class " Python 文件的一般设置,比如不要tab等 autocmd FileType python set tabstop=4 shiftwidth=4 expandtab ai " 如果不起作用,确定.viminfo是否可写 if has("autocmd") au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif endif " 删除多余空格 func! DeleteTrailingWS() exe "normal mz" %s/\s\+$//ge exe "normal `z" endfunc autocmd BufWrite *.py :call DeleteTrailingWS() """"""""""""""""""""""""""""""""""""""""" " 插件管理配置开始 """"""""""""""""""""""""""""""""""""""""" " package dependent: ctags " python dependent: pep8, pyflake filetype off set rtp+=~/.vim/bundle/vundle/ call vundle#rc() Bundle 'gmarik/vundle' " vim plugin bundle control, command model " :BundleInstall install " :BundleInstall! update " :BundleClean remove plugin not in list " 插件:目录导航等 """"""""""""""""""""""""""""""""""""""""" Bundle 'scrooloose/nerdtree' map <leader>n :NERDTreeToggle<CR> let NERDTreeHighlightCursorline=1 let NERDTreeIgnore=[ '\.pyc$', '\.pyo$', '\.obj$', '\.o$', '\.so$', '\.egg$', '^\.git$', '^\.svn$', '^\.hg$' ] let g:netrw_home='~/' " close vim if the only window left open is a NERDTree autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | end " for minibufferexpl Bundle 'fholgado/minibufexpl.vim' let g:miniBufExplMapWindowNavVim = 1 let g:miniBufExplMapWindowNavArrows = 1 let g:miniBufExplMapCTabSwitchBufs = 1 let g:miniBufExplModSelTarget = 1 let g:miniBufExplForceSyntaxEnable = 1 let g:miniBufExplorerMoreThanOne=2 let g:miniBufExplCycleArround=1 " 默认方向键左右可以切换buffer nnoremap <TAB> :MBEbn<CR> noremap <leader>bn :MBEbn<CR> noremap <leader>bp :MBEbp<CR> noremap <leader>bd :MBEbd<CR> " 插件:标签导航等 """"""""""""""""""""""""""""""""""""""""" Bundle 'majutsushi/tagbar' let g:tagbar_autofocus = 1 Bundle 'vim-scripts/taglist.vim' set tags=tags;/ let Tlist_Ctags_Cmd="/usr/bin/ctags" let Tlist_Auto_Highlight_Tag = 1 let Tlist_Auto_Open = 0 let Tlist_Auto_Update = 1 let Tlist_Close_On_Select = 0 let Tlist_Compact_Format = 0 let Tlist_Display_Prototype = 0 let Tlist_Display_Tag_Scope = 1 let Tlist_Enable_Fold_Column = 0 let Tlist_Exit_OnlyWindow = 1 let Tlist_File_Fold_Auto_Close = 0 let Tlist_GainFocus_On_ToggleOpen = 1 let Tlist_Hightlight_Tag_On_BufEnter = 1 let Tlist_Inc_Winwidth = 0 let Tlist_Max_Submenu_Items = 1 let Tlist_Max_Tag_Length = 30 let Tlist_Process_File_Always = 0 let Tlist_Show_Menu = 0 let Tlist_Show_One_File = 1 let Tlist_Sort_Type = "order" let Tlist_Use_Horiz_Window = 0 let Tlist_Use_Right_Window = 0 let Tlist_WinWidth = 25 " 插件:文件搜索 """"""""""""""""""""""""""""""""""""""""" Bundle 'kien/ctrlp.vim' let g:ctrlp_map = '<leader>p' let g:ctrlp_cmd = 'CtrlP' map <leader>f :CtrlPMRU<CR> " set wildignore+=*/tmp/*,*.so,*.swp,*.zip " MacOSX/Linux" let g:ctrlp_custom_ignore = { \ 'dir': '\v[\/]\.(git|hg|svn|rvm)$', \ 'file': '\v\.(exe|so|dll|zip|tar|tar.gz)$', \ } " \ 'link': 'SOME_BAD_SYMBOLIC_LINKS', let g:ctrlp_working_path_mode=0 let g:ctrlp_match_window_bottom=1 let g:ctrlp_max_height=15 let g:ctrlp_match_window_reversed=0 let g:ctrlp_mruf_max=500 let g:ctrlp_follow_symlinks=1 " 插件:状态栏美观 """"""""""""""""""""""""""""""""""""""""" Bundle 'Lokaltog/vim-powerline' " if want to use fancy,need to add font patch -> git clone git://gist.github.com/1630581.git ~/.fonts/ttf-dejavu-powerline "let g:Powerline_symbols = 'fancy' "let g:Powerline_symbols = 'unicode' " 插件:括号显示增强 """"""""""""""""""""""""""""""""""""""""" Bundle 'kien/rainbow_parentheses.vim' let g:rbpt_colorpairs = [ \ ['brown', 'RoyalBlue3'], \ ['Darkblue', 'SeaGreen3'], \ ['darkgray', 'DarkOrchid3'], \ ['darkgreen', 'firebrick3'], \ ['darkcyan', 'RoyalBlue3'], \ ['darkred', 'SeaGreen3'], \ ['darkmagenta', 'DarkOrchid3'], \ ['brown', 'firebrick3'], \ ['gray', 'RoyalBlue3'], \ ['black', 'SeaGreen3'], \ ['darkmagenta', 'DarkOrchid3'], \ ['Darkblue', 'firebrick3'], \ ['darkgreen', 'RoyalBlue3'], \ ['darkcyan', 'SeaGreen3'], \ ['darkred', 'DarkOrchid3'], \ ['red', 'firebrick3'], \ ] let g:rbpt_max = 40 let g:rbpt_loadcmd_toggle = 0 " 插件:将每行无效的空格标红(,空格按键去掉末尾空格) """"""""""""""""""""""""""""""""""""""""" Bundle 'bronson/vim-trailing-whitespace' map <leader><space> :FixWhitespace<cr> " 插件:主题solarized Bundle 'altercation/vim-colors-solarized' " let g:solarized_termcolors=256 let g:solarized_termtrans=1 let g:solarized_contrast="normal" let g:solarized_visibility="normal" " 插件:主题molokai Bundle 'tomasr/molokai' " let g:molokai_original = 1 " 插件:快速移动 """"""""""""""""""""""""""""""""""""""""" " 更高效的移动 ,, + w/fx Bundle 'Lokaltog/vim-easymotion' Bundle 'vim-scripts/matchit.zip' " 插件:迄今为止用到的最好的自动VIM自动补全插件 """"""""""""""""""""""""""""""""""""""""" " Bundle 'Valloric/YouCompleteMe' " youcompleteme 默认tab s-tab 和自动补全冲突 " let g:ycm_key_list_select_completion=['<C-n>'] " let g:ycm_key_list_select_completion = ['<Down>'] " let g:ycm_key_list_previous_completion=['<C-p>'] " let g:ycm_key_list_previous_completion = ['<Up>'] " 在注释输入中也能补全 " let g:ycm_complete_in_comments = 1 " 在字符串输入中也能补全 " let g:ycm_complete_in_strings = 1 " 注释和字符串中的文字也会被收入补全 " let g:ycm_collect_identifiers_from_comments_and_strings = 0 " 插件:快速插入代码片段 """"""""""""""""""""""""""""""""""""""""" Bundle 'SirVer/ultisnips' let g:UltiSnipsExpandTrigger = "<tab>" let g:UltiSnipsJumpForwardTrigger = "<tab>" " 定义存放代码片段的文件夹 .vim/snippets下,使用自定义和默认的,将会的到全局,有冲突的会提示 let g:UltiSnipsSnippetDirectories=["snippets", "bundle/ultisnips/UltiSnips"] " 插件:快速加/减注释(选中后,按,cc加上注释,按,cu解开注释) """"""""""""""""""""""""""""""""""""""""" Bundle 'scrooloose/nerdcommenter' " 插件:用双引号/单引号包裹字符串 """"""""""""""""""""""""""""""""""""""""" " cs" ' " Hello world!" -> 'Hello world!' " ds" " " Hello world!" -> Hello world! " ysiw" " Hello -> " Hello" Bundle 'tpope/vim-surround' Bundle 'tpope/vim-repeat' " 插件:自动补全单引号,双引号等 """"""""""""""""""""""""""""""""""""""""" Bundle 'Raimondi/delimitMate' " for python docstring " ,优化输入 autocmd FileType python let b:delimitMate_nesting_quotes = ['"'] " 自动补全html/xml标签 Bundle 'docunext/closetag.vim' let g:closetag_html_style=1 " 插件:代码格式化 """"""""""""""""""""""""""""""""""""""""" Bundle 'godlygeek/tabular' nmap <Leader>a= :Tabularize /=<CR> vmap <Leader>a= :Tabularize /=<CR> nmap <Leader>a: :Tabularize /:\zs<CR> vmap <Leader>a: :Tabularize /:\zs<CR> " for visual selection Bundle 'terryma/vim-expand-region' map = <Plug>(expand_region_expand) map - <Plug>(expand_region_shrink) " 插件:多光标批量操作 """"""""""""""""""""""""""""""""""""""""" " Bundle 'terryma/vim-multiple-cursors' " let g:multi_cursor_use_default_mapping=0 " Default mapping " let g:multi_cursor_next_key='<C-m>' " let g:multi_cursor_prev_key='<C-p>' " let g:multi_cursor_skip_key='<C-x>' " let g:multi_cursor_quit_key='<ESC>' " 插件:语法检查 """"""""""""""""""""""""""""""""""""""""" " 编辑时自动语法检查标红, vim-flake8目前还不支持,所以多装一个 " 使用pyflakes,速度比pylint快 Bundle 'scrooloose/syntastic' let g:syntastic_error_symbol='>>' let g:syntastic_warning_symbol='>' let g:syntastic_check_on_open=1 let g:syntastic_enable_highlighting = 0 let g:syntastic_python_checkers=['pyflakes'] highlight SyntasticErrorSign guifg=white guibg=black " python fly check, 弥补syntastic只能打开和保存才检查语法的不足 Bundle 'kevinw/pyflakes-vim' let g:pyflakes_use_quickfix = 0 " 插件:具体语言语法高亮 """"""""""""""""""""""""""""""""""""""""" " for python.vim syntax highlight Bundle 'hdima/python-syntax' let python_highlight_all = 1 " for golang Bundle 'jnwhiteh/vim-golang' Bundle 'Blackrush/vim-gocode' " for markdown Bundle 'plasticboy/vim-markdown' let g:vim_markdown_folding_disabled=1 " for javascript Bundle "pangloss/vim-javascript" let g:html_indent_inctags = "html,body,head,tbody" let g:html_indent_script1 = "inc" let g:html_indent_style1 = "inc" " for jquery Bundle 'nono/jquery.vim' " for jinja2 highlight Bundle 'Glench/Vim-Jinja2-Syntax' " for nginx conf file highlight. need to confirm it works Bundle 'thiderman/nginx-vim-syntax' " 插件:杂项 """"""""""""""""""""""""""""""""""""""""" " task list Bundle 'vim-scripts/TaskList.vim' map <leader>td <Plug>TaskList " for git 尚未用起来 Bundle 'tpope/vim-fugitive' " 可以查看/回到某个历史状态 Bundle 'sjl/gundo.vim' nnoremap <leader>h :GundoToggle<CR> " end turn on filetype plugin indent on """"""""""""""""""""""""""""""""""""""""" " 插件管理配置结束 """"""""""""""""""""""""""""""""""""""""" """"""""""""""""""""""""""""""""""""""""" " 自定义的函数 """"""""""""""""""""""""""""""""""""""""" " 相对绝对行号转换 function! NumberToggle() if(&relativenumber == 1) set norelativenumber number else set relativenumber endif endfunc " 突出显示当前行列转换 function! CusorCulLineToggle() if(&cursorcolumn == 1) set nocursorcolumn set nocursorline else set cursorcolumn set cursorline endif endfunc function! GoToFileEnd() normal G endfunc ""定义函数SetTitle,自动插入文件头 autocmd BufNewFile *.py,*.cpp,*.c,*.sh,*.java exec ":call SetTitle()" function! SetTitle() "如果文件类型为.sh文件 if &filetype == 'sh' call setline(1,"\#!/bin/bash") call append(line("."), "\#############################################") call append(line(".")+1, "\# Copyright(c) Tencent, all rights reserved") call append(line(".")+2, "\# @file : ".expand("%")) call append(line(".")+3, "\# @author : lucasysfeng") call append(line(".")+4, "\# @revision : ".strftime("%Y-%m-%-d %H:%M:%S")) call append(line(".")+5, "\# @brief :") call append(line(".")+6, "\#############################################") elseif &filetype == 'cpp' || &filetype == 'c' call setline(1,"/****************************************************") call append(line("."), "\# Copyright(c) Tencent, all rights reserved") call append(line(".")+1, "\# @file : ".expand("%")) call append(line(".")+2, "\# @author : lucasysfeng") call append(line(".")+3, "\# @revision : ".strftime("%Y-%m-%-d %H:%M:%S")) call append(line(".")+4, "\# @brief :") call append(line(".")+5, "****************************************************/") call append(line(".")+6, "") call append(line(".")+7, "#include <iostream>") call append(line(".")+8, "#include <string>") call append(line(".")+9, "") call append(line(".")+10, "using namespace std;") call append(line(".")+11, "") call append(line(".")+12, "int main()") call append(line(".")+13, "{") call append(line(".")+14, "") call append(line(".")+15, " return 0;") call append(line(".")+16,"}") elseif &filetype == 'python' call setline(1,"\#!/usr/bin/env python") call append(line("."), "\# -*- coding: utf-8 -*-") call append(line(".")+1, "\#############################################") call append(line(".")+2, "\# Copyright(c) , all rights reserved") call append(line(".")+3, "\# @file : ".expand("%")) call append(line(".")+4, "\# @author : lucasysfeng") call append(line(".")+5, "\# @revision : ".strftime("%Y-%m-%-d %H:%M:%S")) call append(line(".")+6, "\# @brief :") call append(line(".")+7, "\#############################################") endif "新建文件后,自动定位到文件末尾 "autocmd BufNewFile * exec ":call GoToFileEnd()" call GoToFileEnd() endfunc " Doxygen注释快捷键 nnoremap <leader>g :Dox<CR> " DoxygenToolkit.vim " Brief: Usefull tools for Doxygen (comment, author, license). " Version: 0.2.13 " Date: 2010/10/16 " Author: Mathias Lorente " " TODO: add automatically (option controlled) in/in out flags to function " parameters " TODO: (Python) Check default paramareters defined as list/dictionnary/tuple " " Note: Correct insertion position and 'xxx_post' parameters. " - Insert position is correct when g:DoxygenToolkit_compactOneLineDoc = "yes" " and let g:DoxygenToolkit_commentType = "C++" are set. " - When you define: " g:DoxygenToolkit_briefTag_pre = "@brief " " g:DoxygenToolkit_briefTag_post = "<++>" " g:DoxygenToolkit_briefTag_funcName = "yes" " Documentation generated with these parameters is something like: " /// @brief foo <++> " You can configure similarly parameters to get something like: " /// @brief foo <++> " /// @param bar <++> " /// @param baz <++> " " Note: Position the cursor at the right position for one line documentation. " " Note: Remove trailing blank characters where they are not needed. " " Note: 'extern' keyword added in list of values to ignore for return type. " " Note: Correct bugs related to templates and add support for throw statement " (many thanks to Dennis Lubert): " - Template parameter of different type from class and typename are " recognized. " - Indentation mistake while detecting template. " - New option are available: g:DoxygenToolkit_throwTag_pre and " g:DoxygenToolkit_throwTag_post " " Note: Add support for documentation of template parameters. " Thanks to Dennis (plasmahh) and its suggestions. " - New option are available: g:DoxygenToolkit_templateParamTag_pre " and g:DoxygenToolkit_templateParamTag_post " " Note: Solve almost all compatibility problem with c/c++ IDE " " Note: Bug correction and improve compatibility with c/c++ IDE " - Documentation of function with struct parameters are now allowed. " - Comments are written in two steps to avoid conflicts with c/c++ IDE. " " Note: Bug correction (thanks to Jhon Do) " - DoxygenToolkit_briefTag_funcName and other xxx_xxName parameters " should work properly now. " " Note: Bug correction (thanks to Anders Bo Rasmussen) " - C++: now functions like void foo(type &bar); are correctly documented. " The parameter's name is bar (and no more &bar). " " Note: Added @version tag into the DocBlock generated by DoxygenAuthorFunc() " (thanks to Dave Walter). " The version string can be defines into your .vimrc file with " g:DoxygenToolkit_versionString or it will be asked the first time the " function is called (same behavior as @author tag). Example: " /// \file foo.cpp " /// \brief " /// \author Dave Walter " /// \version 1.0 " /// \date 2009-03-26 " " Note: Comments are now allowed in function declaration. Example: " - C/C++: void func( int foo, // first param " int bar /* second param */ ); " " - Python: def func( foo, # first param " bar ) # second param " " Note: Bug correction (many thanks to Alexey Radkov) " - C/C++: following function/method are now correctly documented: " - operator(), " - constructor with initialization parameter(s), " - pure virtual method, " - const method. " - Python: " - Single line function are now correctly documented. " " Note: The main function has been rewritten (I hope it is cleaner). " - There is now support for function pointer as parameter (C/C++). " - You can configure the script to get one line documentation (for " attribute instance for example, you need to set " g:DoxygenToolkit_compactOneLineDoc to "yes"). " " - NEW: Support Python scripts: " - Function/method are not scanned, so by default they are considered " as if they always return something (modify this behavior by defining " g:DoxygenToolkit_python_autoFunctionReturn to "no") " - self parameter is automatically ignored when scanning function " parameters (you can change this behavior by defining " g:DoxygenToolkit_python_autoRemoveSelfParam to "no") " " Note: Number of lines scanned is now configurable. Default value is still 10 " lines. (Thanks to Spencer Collyer for this improvement). " " Note: Bug correction : function that returns null pointer are correctly " documented (Thanks to Ronald WAHL for his report and patch). " " Note: Remove header and footer from doxygen documentation " - Generated documentation with block header/footer activated (see " parameters g:DoxygenToolkit_blockHeader and " g:DoxygenToolkit_blockFooter) do not integrate header and footer " anymore. " Thanks to Justin RANDALL for this. " Now comments are as following: " /* --- My Header --- */ // --- My Header --- " /** /// @brief ... " * @brief ... or // --- My Footer --- " */ " /* -- My Footer --- */ " " Note: Changes to customize cinoptions " - New option available for cinoptions : g:DoxygenToolkit_cinoptions " (default value is still c1C1) " Thanks to Arnaud GODET for this. Now comment can have the following " look: " /** /** " * and not only * " */ */ " Note: Changes for linux kernel comment style " - New option are available for brief tag and parameter tag ! Now there is " a pre and a post tag for each of these tag. " - You can define 'let g:DoxygenToolkit_briefTag_funcName = "yes"' to add " the name of commented function between pre-brief tag and post-brief tag. " - With these new features you can get something like: " /** " * @brief MyFunction - " * " * @param foo: " * @param bar: " */ " Note: Changes suggested by Soh Kok Hong: " - Fixed indentation in comments " ( no more /** /** " * but * " */ */ ) " Note: Changes made by Jason Mills: " - Fixed \n bug which resulted in comments being screwed up " - Added use of doxygen /// comments. " Note: Changes made by Mathias Lorente on 05/25/04 " - Fixed filename bug when including doxygen author comment whereas file " has not been open directly on commamd line. " - Now /// or /** doxygen comments are correctly integrated (except for " license). " Note: Changes made by Mathias Lorente on 08/02/04 " - Now include only filename in author comment (no more folder...) " - Fixed errors with function with no indentation. " " " Currently five purposes have been defined : " " Generates a doxygen license comment. The tag text is configurable. " " Generates a doxygen author skeleton. The tag text is configurable. " " Generates a doxygen comment skeleton for a C, C++ or Python function or class, " including @brief, @param (for each named argument), and @return. The tag " text as well as a comment block header and footer are configurable. " (Consequently, you can have \brief, etc. if you wish, with little effort.) " " Ignore code fragment placed in a block defined by #ifdef ... #endif (C/C++). The " block name must be given to the function. All of the corresponding blocks " in all the file will be treated and placed in a new block DOX_SKIP_BLOCK (or " any other name that you have configured). Then you have to update " PREDEFINED value in your doxygen configuration file with correct block name. " You also have to set ENABLE_PREPROCESSING to YES. " " Generate a doxygen group (begining and ending). The tag text is " configurable. " " Use: " - Type of comments (C/C++: /// or /** ... */, Python: ## and # ) : " In vim, default C++ comments are : /** ... */. But if you prefer to use /// " Doxygen comments just add 'let g:DoxygenToolkit_commentType = "C++"' " (without quotes) in your .vimrc file " " - License : " In vim, place the cursor on the line that will follow doxygen license " comment. Then, execute the command :DoxLic. This will generate license " comment and leave the cursor on the line just after. " " - Author : " In vim, place the cursor on the line that will follow doxygen author " comment. Then, execute the command :DoxAuthor. This will generate the " skeleton and leave the cursor just after @author tag if no variable " define it, or just after the skeleton. " " - Function / class comment : " In vim, place the cursor on the line of the function header (or returned " value of the function) or the class. Then execute the command :Dox. This " will generate the skeleton and leave the cursor after the @brief tag. " " - Ignore code fragment : " In vim, if you want to ignore all code fragment placed in a block such as : " #ifdef DEBUG " ... " #endif " You only have to execute the command :DoxUndoc(DEBUG) ! " " - Group : " In vim, execute the command :DoxBlock to insert a doxygen block on the " following line. " " Limitations: " - Assumes that the function name (and the following opening parenthesis) is " at least on the third line after current cursor position. " - Not able to update a comment block after it's been written. " - Blocks delimiters (header and footer) are only included for function " comment. " - Assumes that cindent is used. " - Comments in function parameters (such as void foo(int bar /* ... */, baz)) " are not yet supported. " " " Example: " Given: " int " foo(char mychar, " int myint, " double* myarray, " int mask = DEFAULT) " { //... " } " " Issuing the :Dox command with the cursor on the function declaration would " generate " " /** " * @brief " * " * @param mychar " * @param myint " * @param myarray " * @param mask " * " * @return " */ " " " To customize the output of the script, see the g:DoxygenToolkit_* " variables in the script's source. These variables can be set in your " .vimrc. " " For example, my .vimrc contains: " let g:DoxygenToolkit_briefTag_pre="@Synopsis " " let g:DoxygenToolkit_paramTag_pre="@Param " " let g:DoxygenToolkit_returnTag="@Returns " " let g:DoxygenToolkit_blockHeader="--------------------------------------------------------------------------" " let g:DoxygenToolkit_blockFooter="----------------------------------------------------------------------------" " let g:DoxygenToolkit_authorName="Mathias Lorente" " let g:DoxygenToolkit_licenseTag="My own license" <-- Does not end with " "\<enter>" " Verify if already loaded "if exists("loaded_DoxygenToolkit") " echo 'DoxygenToolkit Already Loaded.' " finish "endif let loaded_DoxygenToolkit = 1 "echo 'Loading DoxygenToolkit...' let s:licenseTag = "Copyright (C) \<enter>\<enter>" let s:licenseTag = s:licenseTag . "This program is free software; you can redistribute it and/or\<enter>" let s:licenseTag = s:licenseTag . "modify it under the terms of the GNU General Public License\<enter>" let s:licenseTag = s:licenseTag . "as published by the Free Software Foundation; either version 2\<enter>" let s:licenseTag = s:licenseTag . "of the License, or (at your option) any later version.\<enter>\<enter>" let s:licenseTag = s:licenseTag . "This program is distributed in the hope that it will be useful,\<enter>" let s:licenseTag = s:licenseTag . "but WITHOUT ANY WARRANTY; without even the implied warranty of\<enter>" let s:licenseTag = s:licenseTag . "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\<enter>" let s:licenseTag = s:licenseTag . "GNU General Public License for more details.\<enter>\<enter>" let s:licenseTag = s:licenseTag . "You should have received a copy of the GNU General Public License\<enter>" let s:licenseTag = s:licenseTag . "along with this program; if not, write to the Free Software\<enter>" let s:licenseTag = s:licenseTag . "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\<enter>" " Common standard constants if !exists("g:DoxygenToolkit_briefTag_pre") let g:DoxygenToolkit_briefTag_pre = "@brief " endif if !exists("g:DoxygenToolkit_briefTag_post") let g:DoxygenToolkit_briefTag_post = "" endif if !exists("g:DoxygenToolkit_templateParamTag_pre") let g:DoxygenToolkit_templateParamTag_pre = "@tparam " endif if !exists("g:DoxygenToolkit_templateParamTag_post") let g:DoxygenToolkit_templateParamTag_post = "" endif if !exists("g:DoxygenToolkit_paramTag_pre") let g:DoxygenToolkit_paramTag_pre = "@param " endif if !exists("g:DoxygenToolkit_paramTag_post") let g:DoxygenToolkit_paramTag_post = "" endif if !exists("g:DoxygenToolkit_returnTag") let g:DoxygenToolkit_returnTag = "@return" endif if !exists("g:DoxygenToolkit_throwTag_pre") let g:DoxygenToolkit_throwTag_pre = "@throw " " @exception is also valid endif if !exists("g:DoxygenToolkit_throwTag_post") let g:DoxygenToolkit_throwTag_post = "" endif if !exists("g:DoxygenToolkit_blockHeader") let g:DoxygenToolkit_blockHeader = "" endif if !exists("g:DoxygenToolkit_blockFooter") let g:DoxygenToolkit_blockFooter = "" endif if !exists("g:DoxygenToolkit_licenseTag") let g:DoxygenToolkit_licenseTag = s:licenseTag endif if !exists("g:DoxygenToolkit_fileTag") let g:DoxygenToolkit_fileTag = "@file " endif if !exists("g:DoxygenToolkit_authorTag") let g:DoxygenToolkit_authorTag = "@author " endif if !exists("g:DoxygenToolkit_dateTag") let g:DoxygenToolkit_dateTag = "@date " endif if !exists("g:DoxygenToolkit_versionTag") let g:DoxygenToolkit_versionTag = "@version " endif if !exists("g:DoxygenToolkit_undocTag") let g:DoxygenToolkit_undocTag = "DOX_SKIP_BLOCK" endif if !exists("g:DoxygenToolkit_blockTag") let g:DoxygenToolkit_blockTag = "@name " endif if !exists("g:DoxygenToolkit_classTag") let g:DoxygenToolkit_classTag = "@class " endif if !exists("g:DoxygenToolkit_cinoptions") let g:DoxygenToolkit_cinoptions = "c1C1" endif if !exists("g:DoxygenToolkit_startCommentTag ") let g:DoxygenToolkit_startCommentTag = "/** " let g:DoxygenToolkit_startCommentBlock = "/* " endif if !exists("g:DoxygenToolkit_interCommentTag ") let g:DoxygenToolkit_interCommentTag = "* " endif if !exists("g:DoxygenToolkit_interCommentBlock ") let g:DoxygenToolkit_interCommentBlock = "* " endif if !exists("g:DoxygenToolkit_endCommentTag ") let g:DoxygenToolkit_endCommentTag = "*/" let g:DoxygenToolkit_endCommentBlock = "*/" endif if exists("g:DoxygenToolkit_commentType") if ( g:DoxygenToolkit_commentType == "C++" ) let g:DoxygenToolkit_startCommentTag = "/// " let g:DoxygenToolkit_interCommentTag = "/// " let g:DoxygenToolkit_endCommentTag = "" let g:DoxygenToolkit_startCommentBlock = "// " let g:DoxygenToolkit_interCommentBlock = "// " let g:DoxygenToolkit_endCommentBlock = "" else let g:DoxygenToolkit_commentType = "C" endif else let g:DoxygenToolkit_commentType = "C" endif " Compact documentation " /** " * \brief foo ---> /** \brief foo */ " */ if !exists("g:DoxygenToolkit_compactOneLineDoc") let g:DoxygenToolkit_compactOneLineDoc = "no" endif " /** " * \brief foo /** " * * \brief foo " * \param bar ---> * \param bar " * * \return " * \return */ " */ if !exists("g:DoxygenToolkit_compactDoc") let g:DoxygenToolkit_compactDoc = "no" endif " Necessary '\<' and '\>' will be added to each item of the list. let s:ignoreForReturn = ['template', 'explicit', 'inline', 'static', 'virtual', 'void\([[:blank:]]*\*\)\@!', 'const', 'volatile', 'struct', 'extern'] if !exists("g:DoxygenToolkit_ignoreForReturn") let g:DoxygenToolkit_ignoreForReturn = s:ignoreForReturn[:] else let g:DoxygenToolkit_ignoreForReturn += s:ignoreForReturn endif unlet s:ignoreForReturn " Maximum number of lines to check for function parameters if !exists("g:DoxygenToolkit_maxFunctionProtoLines") let g:DoxygenToolkit_maxFunctionProtoLines = 10 endif " Add name of function/class/struct... after pre brief tag if you want if !exists("g:DoxygenToolkit_briefTag_className") let g:DoxygenToolkit_briefTag_className = "no" endif if !exists("g:DoxygenToolkit_briefTag_structName") let g:DoxygenToolkit_briefTag_structName = "no" endif if !exists("g:DoxygenToolkit_briefTag_enumName") let g:DoxygenToolkit_briefTag_enumName = "no" endif if !exists("g:DoxygenToolkit_briefTag_namespaceName") let g:DoxygenToolkit_briefTag_namespaceName = "no" endif if !exists("g:DoxygenToolkit_briefTag_funcName") let g:DoxygenToolkit_briefTag_funcName = "no" endif " Keep empty line (if any) between comment and function/class/... if !exists("g:DoxygenToolkit_keepEmptyLineAfterComment") let g:DoxygenToolkit_keepEmptyLineAfterComment = "no" endif " PYTHON specific """"""""""""""""" " Remove automatically self parameter from function to avoid its documantation if !exists("g:DoxygenToolkit_python_autoRemoveSelfParam") let g:DoxygenToolkit_python_autoRemoveSelfParam = "yes" endif " Consider functions as if they always return something (default: yes) if !exists("g:DoxygenToolkit_python_autoFunctionReturn") let g:DoxygenToolkit_python_autoFunctionReturn = "yes" endif """""""""""""""""""""""""" " Doxygen license comment """""""""""""""""""""""""" function! <SID>DoxygenLicenseFunc() call s:InitializeParameters() " Test authorName variable if !exists("g:DoxygenToolkit_authorName") let g:DoxygenToolkit_authorName = input("Enter name of the author (generally yours...) : ") endif mark d let l:date = strftime("%Y") exec "normal O".strpart( s:startCommentBlock, 0, 1 ) exec "normal A".strpart( s:startCommentBlock, 1 ).substitute( g:DoxygenToolkit_licenseTag, "\<enter>", "\<enter>".s:interCommentBlock, "g" ) if( s:endCommentBlock != "" ) exec "normal o".s:endCommentBlock endif if( g:DoxygenToolkit_licenseTag == s:licenseTag ) exec "normal %jA".l:date." - ".g:DoxygenToolkit_authorName endif exec "normal `d" call s:RestoreParameters() endfunction """""""""""""""""""""""""" " Doxygen author comment """""""""""""""""""""""""" function! <SID>DoxygenAuthorFunc() call s:InitializeParameters() " Test authorName variable if !exists("g:DoxygenToolkit_authorName") let g:DoxygenToolkit_authorName = input("Enter name of the author (generally yours...) : ") endif " Test versionString variable if !exists("g:DoxygenToolkit_versionString") let g:DoxygenToolkit_versionString = input("Enter version string : ") endif " Get file name let l:fileName = expand('%:t') " Begin to write skeleton let l:insertionMode = s:StartDocumentationBlock() exec "normal ".l:insertionMode.s:interCommentTag.g:DoxygenToolkit_fileTag.l:fileName exec "normal o".s:interCommentTag.g:DoxygenToolkit_briefTag_pre mark d exec "normal o".s:interCommentTag.g:DoxygenToolkit_authorTag.g:DoxygenToolkit_authorName exec "normal o".s:interCommentTag.g:DoxygenToolkit_versionTag.g:DoxygenToolkit_versionString let l:date = strftime("%Y-%m-%d") exec "normal o".s:interCommentTag.g:DoxygenToolkit_dateTag.l:date if ( g:DoxygenToolkit_endCommentTag != "" ) exec "normal o".s:endCommentTag endif " Move the cursor to the rigth position exec "normal `d" call s:RestoreParameters() startinsert! endfunction """""""""""""""""""""""""" " Doxygen undocument function " C/C++ only! """""""""""""""""""""""""" function! <SID>DoxygenUndocumentFunc(blockTag) call s:InitializeParameters() let l:search = "#ifdef " . a:blockTag " Save cursor position and go to the begining of the file mark d exec "normal gg" while ( search(l:search, 'W') != 0 ) exec "normal O#ifndef " . g:DoxygenToolkit_undocTag exec "normal j^%" if ( g:DoxygenToolkit_endCommentTag == "" ) exec "normal o#endif // " . g:DoxygenToolkit_undocTag else exec "normal o#endif /* " . g:DoxygenToolkit_undocTag . " */" endif endwhile exec "normal `d" call s:RestoreParameters() endfunction """""""""""""""""""""""""" " DoxygenBlockFunc """""""""""""""""""""""""" function! <SID>DoxygenBlockFunc() call s:InitializeParameters() let l:insertionMode = s:StartDocumentationBlock() exec "normal ".l:insertionMode.s:interCommentTag.g:DoxygenToolkit_blockTag mark d exec "normal o".s:interCommentTag."@{ ".s:endCommentTag exec "normal o".strpart( s:startCommentTag, 0, 1 ) exec "normal A".strpart( s:startCommentTag, 1 )." @} ".s:endCommentTag exec "normal `d" call s:RestoreParameters() startinsert! endfunction """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Main comment function for class, attribute, function... """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! <SID>DoxygenCommentFunc() " Initialize default templates. " Assure compatibility with Python for classes (cf. endDocPattern). let l:emptyLinePattern = '^[[:blank:]]*$' let l:someNamePattern = '[_[:alpha:]][_[:alnum:]]*' if( s:CheckFileType() == "cpp" ) let l:someNameWithNamespacePattern = l:someNamePattern.'\%(::'.l:someNamePattern.'\)*' let l:endDocPattern = ';\|{\|\%([^:]\zs:\ze\%([^:]\|$\)\)' let l:commentPattern = '\%(/*\)\|\%(//\)\' let l:templateParameterPattern = "<[^<>]*>" let l:throwPattern = '.*\<throw\>[[:blank:]]*(\([^()]*\)).*' "available only for 'cpp' type let l:classPattern = '\<class\>[[:blank:]]\+\zs'.l:someNameWithNamespacePattern.'\ze.*\%('.l:endDocPattern.'\)' let l:structPattern = '\<struct\>[[:blank:]]\+\zs'.l:someNameWithNamespacePattern.'\ze[^(),]*\%('.l:endDocPattern.'\)' let l:enumPattern = '\<enum\>\%(\%([[:blank:]]\+\zs'.l:someNamePattern.'\ze[[:blank:]]*\)\|\%(\zs\ze[[:blank:]]*\)\)\%('.l:endDocPattern.'\)' let l:namespacePattern = '\<namespace\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze[[:blank:]]*\%('.l:endDocPattern.'\)' let l:types = { "class": l:classPattern, "struct": l:structPattern, "enum": l:enumPattern, "namespace": l:namespacePattern } else let l:commentPattern = '#\|^[[:blank:]]*"""' let l:classPattern = '\<class\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze.*:' let l:functionPattern = '\<def\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze.*:' let l:endDocPattern = '\%(\<class\>\|\<def\>[^:]*\)\@<!$' let l:types = { "class": l:classPattern, "function": l:functionPattern } endif let l:lineBuffer = getline( line( "." ) ) let l:count = 1 let l:endDocFound = 0 let l:doc = { "type": "", "name": "None", "params": [], "returns": "" , "templates": [], "throws": [] } " Mark current line for future use mark d " Look for function/method/... to document " We look only on the first three lines! while( match( l:lineBuffer, l:emptyLinePattern ) != -1 && l:count < 4 ) exec "normal j" let l:lineBuffer = l:lineBuffer.' '.getline( line( "." ) ) let l:count = l:count + 1 endwhile " Error message when the buffer is still empty. if( match( l:lineBuffer, l:emptyLinePattern ) != -1 ) call s:WarnMsg( "Nothing to document here!" ) exec "normal `d" return endif " Remove unwanted lines (ie: jump to the first significant line) if( g:DoxygenToolkit_keepEmptyLineAfterComment == "no" ) " This erase previous mark mark d endif " Look for the end of the function/class/... to document " TODO does not work when function/class/... is commented out! let l:readError = "Cannot reach end of function/class/... declaration!" let l:count = 0 let l:throwCompleted = 0 let l:endReadPattern = l:endDocPattern while( l:endDocFound == 0 && l:count < g:DoxygenToolkit_maxFunctionProtoLines ) let l:lineBuffer = s:RemoveComments( l:lineBuffer ) " Valid only for cpp. For Python it must be 'class ...:' or 'def ...:' or " '... EOL'. if( match( l:lineBuffer, l:endReadPattern ) != -1 ) " Look for throw statement at the end if( s:CheckFileType() == "cpp" && l:throwCompleted == 0 ) " throw statement can have already been read or can be on next line if( match( l:lineBuffer.' '.getline( line ( "." ) + 1 ), '.*\<throw\>.*' ) != -1 ) let l:endReadPattern = l:throwPattern let l:throwCompleted = 1 let l:readError = "Cannot reach end of throw statement" else let l:endDocFound = 1 endif else let l:endDocFound = 1 endif continue endif exec "normal j" let l:lineBuffer = l:lineBuffer.' '.getline( line( "." )) let l:count = l:count + 1 endwhile " Error message when the end of the function(/...) has not been found if( l:endDocFound == 0 ) if( match( l:lineBuffer, l:emptyLinePattern ) != -1 ) " Fall here when only comments have been found. call s:WarnMsg( "Nothing to document here!" ) else call s:WarnMsg( l:readError ) endif exec "normal `d" return endif " Trim the buffer let l:lineBuffer = substitute( l:lineBuffer, "^[[:blank:]]*\|[[:blank:]]*$", "", "g" ) " Check whether it is a template definition call s:ParseFunctionTemplateParameters( l:lineBuffer, l:doc ) " Remove any template parameter. if( s:CheckFileType() == "cpp" ) while( match( l:lineBuffer, l:templateParameterPattern ) != -1 ) let l:lineBuffer = substitute( l:lineBuffer, l:templateParameterPattern, "", "g" ) endwhile endif " Look for the type for key in keys( l:types ) "call s:WarnMsg( "[DEBUG] buffer:_".l:lineBuffer."_, test:_".l:types[key] ) let l:name = matchstr( l:lineBuffer, l:types[key] ) if( l:name != "" ) let l:doc.type = key let l:doc.name = l:name " Python only. Functions are detected differently for C/C++. if( key == "function" ) "call s:WarnMsg( "HERE !!!".l:lineBuffer ) call s:ParseFunctionParameters( l:lineBuffer, l:doc ) endif break endif endfor if( l:doc.type == "" ) " Should be a function/method (cpp only) or an attribute. " (cpp only) Can also be an unnamed enum/namespace... (or something else ?) if( s:CheckFileType() == "cpp" ) if( match( l:lineBuffer, '(' ) == -1 ) if( match( l:lineBuffer, '\<enum\>' ) != -1 ) let l:doc.type = 'enum' elseif( match( l:lineBuffer, '\<namespace\>' ) != -1 ) let l:doc.type = 'namespace' else " TODO here we get a class attribute of something like that. " We probably just need a \brief statement... let l:doc.type = 'attribute' " TODO Retrieve the name of the attribute. " Do we really need it? I'm not sure for the moment. endif else let l:doc.type = 'function' call s:ParseFunctionParameters( l:lineBuffer, l:doc ) if( l:throwCompleted == 1 ) call s:ParseThrowParameters( l:lineBuffer, l:doc, l:throwPattern ) endif endif " This is an attribute for Python else let l:doc.type = 'attribute' endif endif " Remove the function/class/... name when it is not necessary if( ( l:doc.type == "class" && g:DoxygenToolkit_briefTag_className != "yes" ) || ( l:doc.type == "struct" && g:DoxygenToolkit_briefTag_structName != "yes" ) || ( l:doc.type == "enum" && g:DoxygenToolkit_briefTag_enumName != "yes" ) || ( l:doc.type == "namespace" && g:DoxygenToolkit_briefTag_namespaceName != "yes" ) || ( l:doc.type == "function" && g:DoxygenToolkit_briefTag_funcName != "yes" ) ) let l:doc.name = "None" " Remove namespace from the name of the class/function... elseif( s:CheckFileType() == "cpp" ) let l:doc.name = substitute( l:doc.name, '\%('.l:someNamePattern.'::\)', '', 'g' ) endif " Below, write what we have found """"""""""""""""""""""""""""""""" call s:InitializeParameters() if( s:CheckFileType() == "python" && l:doc.type == "function" && g:DoxygenToolkit_python_autoFunctionReturn == "yes" ) let l:doc.returns = "yes" endif " Header exec "normal `d" if( g:DoxygenToolkit_blockHeader != "" ) exec "normal O".strpart( s:startCommentBlock, 0, 1 ) exec "normal A".strpart( s:startCommentBlock, 1 ).g:DoxygenToolkit_blockHeader.s:endCommentBlock exec "normal `d" endif " Brief if( g:DoxygenToolkit_compactOneLineDoc =~ "yes" && l:doc.returns != "yes" && len( l:doc.params ) == 0 ) let s:compactOneLineDoc = "yes" exec "normal O".strpart( s:startCommentTag, 0, 1 ) exec "normal A".strpart( s:startCommentTag, 1 ).g:DoxygenToolkit_briefTag_pre else let s:compactOneLineDoc = "no" let l:insertionMode = s:StartDocumentationBlock() exec "normal ".l:insertionMode.s:interCommentTag.g:DoxygenToolkit_briefTag_pre endif if( l:doc.name != "None" ) exec "normal A".l:doc.name." " endif exec "normal A".g:DoxygenToolkit_briefTag_post " Mark the line where the cursor will be positionned. mark d " Arguments/parameters if( g:DoxygenToolkit_compactDoc =~ "yes" ) let s:insertEmptyLine = 0 else let s:insertEmptyLine = 1 endif for param in l:doc.templates if( s:insertEmptyLine == 1 ) exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" ) let s:insertEmptyLine = 0 endif exec "normal o".s:interCommentTag.g:DoxygenToolkit_templateParamTag_pre.param.g:DoxygenToolkit_templateParamTag_post endfor for param in l:doc.params if( s:insertEmptyLine == 1 ) exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" ) let s:insertEmptyLine = 0 endif exec "normal o".s:interCommentTag.g:DoxygenToolkit_paramTag_pre.param.g:DoxygenToolkit_paramTag_post endfor " Returned value if( l:doc.returns == "yes" ) if( g:DoxygenToolkit_compactDoc != "yes" ) exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" ) endif exec "normal o".s:interCommentTag.g:DoxygenToolkit_returnTag endif " Exception (throw) values (cpp only) if( len( l:doc.throws ) > 0 ) if( g:DoxygenToolkit_compactDoc =~ "yes" ) let s:insertEmptyLine = 0 else let s:insertEmptyLine = 1 endif for param in l:doc.throws if( s:insertEmptyLine == 1 ) exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" ) let s:insertEmptyLine = 0 endif exec "normal o".s:interCommentTag.g:DoxygenToolkit_throwTag_pre.param.g:DoxygenToolkit_throwTag_post endfor endif " End (if any) of documentation block. if( s:endCommentTag != "" ) if( s:compactOneLineDoc =~ "yes" ) let s:execCommand = "A" exec "normal A " exec "normal $md" else let s:execCommand = "o" endif exec "normal ".s:execCommand.s:endCommentTag endif " Footer if ( g:DoxygenToolkit_blockFooter != "" ) exec "normal o".strpart( s:startCommentBlock, 0, 1 ) exec "normal A".strpart( s:startCommentBlock, 1 ).g:DoxygenToolkit_blockFooter.s:endCommentBlock endif exec "normal `d" call s:RestoreParameters() if( s:compactOneLineDoc =~ "yes" && s:endCommentTag != "" ) startinsert else startinsert! endif " DEBUG purpose only "call s:WarnMsg( "Found a ".l:doc.type." named ".l:doc.name." (env: ".s:CheckFileType().")." ) "if( l:doc.type == "function" ) " let l:funcReturn = "returns something." " if( l:doc.returns == "" ) " let l:funcReturn = "doesn't return anything." " endif " call s:WarnMsg( " - which ".l:funcReturn ) " call s:WarnMsg( " - which has following parameter(s):" ) " for param in l:doc.params " call s:WarnMsg( " - ".param ) " endfor "endif endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Write the beginning of the documentation block: " - C and Python format: insert '/**' and '##' respectively then a linefeed, " - C++ insert '///' and continue on the same line " " This function return the insertion mode which should be used for the next " call to 'normal'. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:StartDocumentationBlock() " For C++ documentation format we do not need first empty line if( s:startCommentTag != s:interCommentTag ) "exec "normal O".s:startCommentTag exec "normal O".strpart( s:startCommentTag, 0, 1 ) exec "normal A".substitute( strpart( s:startCommentTag, 1 ), "[[:blank:]]*$", "", "" ) let l:insertionMode = "o" else let l:insertionMode = "O" endif return l:insertionMode endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Remove comments from the given buffer. " - Remove everything after '//' or '#'. " - Remove everything between '/*' and '*/' or keep '/*' if '*/' is not present. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:RemoveComments( lineBuffer ) if( s:CheckFileType() == "cpp" ) " Remove C++ (//) comment. let l:lineBuffer = substitute( a:lineBuffer, '[[:blank:]]*\/\/.*$', '', '') " Remove partial C (/* ...) comment: /* foo bar --> /* " '/*' is preserved until corresponding '*/' is found. Other part of the " comment is discarded to prevent the case where it contains characters " corresponding to the endDoc string. let l:lineBuffer = substitute( l:lineBuffer, '\%(\/\*\zs.*\ze\)\&\%(\%(\/\*.*\*\/\)\@!\)', '', '') " Remove C (/* ... */) comment. let l:lineBuffer = substitute( l:lineBuffer, '\/\*.\{-}\*\/', '', 'g') else let l:lineBuffer = substitute( a:lineBuffer, '[[:blank:]]*#.*$', '', '') endif return l:lineBuffer endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Retrieve file type. " - Default type is still 'cpp'. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:CheckFileType() if( &filetype == "python" ) let l:fileType = "python" else let l:fileType = "cpp" endif return l:fileType endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Parse the buffer and set the doc parameter. " - Functions which return pointer to function are not supported. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:ParseFunctionParameters( lineBuffer, doc ) "call s:WarnMsg( 'IN__'.a:lineBuffer ) let l:paramPosition = matchend( a:lineBuffer, 'operator[[:blank:]]*([[:blank:]]*)' ) if ( l:paramPosition == -1 ) let l:paramPosition = stridx( a:lineBuffer, '(' ) else let l:paramPosition = stridx( a:lineBuffer, '(', l:paramPosition ) endif " (cpp only) First deal with function name and returned value. " Function name has already been retrieved for Python and we need to parse " all the function definition to know whether a value is returned or not. if( s:CheckFileType() == "cpp" ) let l:functionBuffer = strpart( a:lineBuffer, 0, l:paramPosition ) " Remove unnecessary elements for ignored in g:DoxygenToolkit_ignoreForReturn let l:functionBuffer = substitute( l:functionBuffer, '\<'.ignored.'\>', '', 'g' ) endfor let l:functionReturnAndName = split( l:functionBuffer, '[[:blank:]*]' ) if( len( l:functionReturnAndName ) > 1 ) let a:doc.returns = 'yes' endif let a:doc.name = l:functionReturnAndName[-1] endif " Work on parameters. let l:parametersBuffer = strpart( a:lineBuffer, l:paramPosition + 1 ) " Remove trailing closing bracket and everything that follows and trim. if( s:CheckFileType() == "cpp" ) let l:parametersBuffer = substitute( l:parametersBuffer, ')[^)]*\%(;\|{\|\%([^:]:\%([^:]\|$\)\)\|\%(\<throw\>\)\).*', '', '' ) else let l:parametersBuffer = substitute( l:parametersBuffer, ')[^)]*:.*', '', '' ) endif let l:parametersBuffer = substitute( l:parametersBuffer, '^[[:blank:]]*\|[[:blank:]]*$', '', '' ) " Remove default parameter values (if any). let l:index = stridx( l:parametersBuffer, '=' ) let l:startIndex = l:index while( l:index != -1 ) " Look for the next colon... let l:colonIndex = stridx( l:parametersBuffer, ',', l:startIndex ) if( l:colonIndex == -1 ) let l:colonIndex = strlen( l:parametersBuffer ) endif let l:paramBuffer = strpart( l:parametersBuffer, l:index, l:colonIndex - l:index ) if( s:CountBrackets( l:paramBuffer ) == 0 ) " Everything in [l:index, l:colonIndex[ can be removed. let l:parametersBuffer = substitute( l:parametersBuffer, l:paramBuffer, '', '' ) let l:index = stridx( l:parametersBuffer, '=' ) let l:startIndex = l:index else " Parameter initialization contains brakets and colons... let l:startIndex = l:colonIndex + 1 endif endwhile "call s:WarnMsg( "[DEBUG]: ".l:parametersBuffer ) " Now, work on each parameter. let l:params = [] let l:index = stridx( l:parametersBuffer, ',' ) while( l:index != -1 ) let l:paramBuffer = strpart( l:parametersBuffer, 0, l:index ) if( s:CountBrackets( l:paramBuffer ) == 0 ) let l:params = add( l:params, s:ParseParameter( l:paramBuffer ) ) let l:parametersBuffer = strpart( l:parametersBuffer, l:index + 1 ) let l:index = stridx( l:parametersBuffer, ',' ) else let l:index = stridx( l:parametersBuffer, ',', l:index + 1 ) endif endwhile if( strlen( l:parametersBuffer ) != 0 ) let l:params = add( l:params, s:ParseParameter( l:parametersBuffer ) ) endif if( s:CheckFileType() == "cpp" ) call filter( l:params, 'v:val !~ "void"' ) else if( g:DoxygenToolkit_python_autoRemoveSelfParam == "yes" ) call filter( l:params, 'v:val !~ "self"' ) endif endif for param in l:params call add( a:doc.params, param ) "call s:WarnMsg( '[DEBUG]:OUT_'.param ) endfor endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Parse given parameter and return its name. " It is easy to do unless you use function's pointers... """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:ParseParameter( param ) let l:paramName = "Unknown" let l:firstIndex = stridx( a:param, '(' ) if( l:firstIndex == -1 ) let l:paramName = split( a:param, '[[:blank:]*&]' )[-1] else if( l:firstIndex != 0 ) let l:startIndex = 0 else let l:startIndex = stridx( a:param, ')' ) if( l:startIndex == -1 ) " Argggg... let l:paramName = a:param else let l:startIndex += 1 while( s:CountBrackets( strpart( a:param, 0, l:startIndex ) ) != 0 ) let l:startIndex = stridx( a:param, ')', l:startIndex + 1 ) + 1 if( l:startIndex == -1) " Argggg... let l:paramName = a:param endif endwhile endif endif if( l:startIndex != -1 ) let l:startIndex = stridx( a:param, '(', l:startIndex ) + 1 let l:endIndex = stridx( a:param, ')', l:startIndex + 1 ) let l:param = strpart( a:param, l:startIndex, l:endIndex - l:startIndex ) let l:paramName = substitute( l:param, '^[[:blank:]*]*\|[[:blank:]*]*$', '', '' ) else " Something really wrong has happened. let l:paramName = a:param endif endif return l:paramName endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Extract template parameter name for function/class/method """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:ParseFunctionTemplateParameters( lineBuffer, doc ) if( match( a:lineBuffer, '^[[:blank:]]*template' ) == 0 ) let l:firstIndex = stridx( a:lineBuffer, '<' ) if( l:firstIndex != -1 ) let l:lastIndex = stridx( a:lineBuffer, '>', l:firstIndex + 1 ) if( l:lastIndex != -1 ) " Keep only template parameters let l:parameters = strpart( a:lineBuffer, l:firstIndex + 1, l:lastIndex - l:firstIndex - 1) " Split on separator (,) let l:params = split( l:parameters, '\,' ) for param in l:params " Extract template parameter name let l:paramName = split( split( param, '=' )[0], '[[:blank:]]' )[-1] call add( a:doc.templates, l:paramName ) endfor endif endif endif endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Extract throw parameter name """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:ParseThrowParameters( lineBuffer, doc, throwPattern ) let l:throwParams = substitute( a:lineBuffer, a:throwPattern, '\1', "" ) for param in split( l:throwParams, "," ) call add( a:doc.throws, substitute( param, '[[:blank:]]', '', "" ) ) endfor endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Define start/end documentation format and backup generic parameters. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:InitializeParameters() if( s:CheckFileType() == "cpp" ) let s:startCommentTag = g:DoxygenToolkit_startCommentTag let s:interCommentTag = g:DoxygenToolkit_interCommentTag let s:endCommentTag = g:DoxygenToolkit_endCommentTag let s:startCommentBlock = g:DoxygenToolkit_startCommentBlock let s:interCommentBlock = g:DoxygenToolkit_interCommentBlock let s:endCommentBlock = g:DoxygenToolkit_endCommentBlock else let s:startCommentTag = "## " let s:interCommentTag = "# " let s:endCommentTag = "" let s:startCommentBlock = "# " let s:interCommentBlock = "# " let s:endCommentBlock = "" endif " Backup standard comment expension and indentation let s:commentsBackup = &comments let &comments = "" let s:cinoptionsBackup = &cinoptions let &cinoptions = g:DoxygenToolkit_cinoptions " Compatibility with c/c++ IDE plugin let s:timeoutlenBackup = &timeoutlen let &timeoutlen = 0 endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Restore previously backuped parameters. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:RestoreParameters() " Restore standard comment expension and indentation let &comments = s:commentsBackup let &cinoptions = s:cinoptionsBackup " Compatibility with c/c++ IDE plugin let &timeoutlen = s:timeoutlenBackup endfunction """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Count opened/closed brackets in the given buffer. " Each opened bracket increase the counter by 1. " Each closed bracket decrease the counter by 1. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" function! s:CountBrackets( buffer ) let l:count = len( split( a:buffer, '(', 1 ) ) let l:count -= len( split( a:buffer, ')', 1 ) ) return l:count endfunction """"""""""""""""""""""""""""""""""" " Simple warning message function """"""""""""""""""""""""""""""""""" function! s:WarnMsg( msg ) echohl WarningMsg echo a:msg echohl None return endfunction """""""""""""""""""""""""" " Shortcuts... """""""""""""""""""""""""" command! -nargs=0 Dox :call <SID>DoxygenCommentFunc() command! -nargs=0 DoxLic :call <SID>DoxygenLicenseFunc() command! -nargs=0 DoxAuthor :call <SID>DoxygenAuthorFunc() command! -nargs=1 DoxUndoc :call <SID>DoxygenUndocumentFunc(<q-args>) command! -nargs=0 DoxBlock :call <SID>DoxygenBlockFunc()