vim 终极配置

vim--vim终极配置文件之最终极版

复制代码
"""""""""""""""""""""""""""""""""""""""""
" Author   : lucasysfeng
" Email    : lucasysfeng@gmail.com
" 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()
复制代码

 

分类:  软件使用vi
0
0
(请您对文章做出评价)
« 上一篇: 爬虫--用cookie访问任意网页
» 下一篇: python--中文比较

posted on 2014-06-13 22:58 lucasysfeng 阅读(246) 评论(0编辑 收藏

历史上的今天:
2013-06-13  Effective C++总结
<2015年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

  • 随笔 - 489
  • 文章 - 0
  • 评论 - 14
  • 引用 - 0
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值