diff --git a/.vimrc b/.vimrc index 10027c4..8c92811 100644 --- a/.vimrc +++ b/.vimrc @@ -1,370 +1,351 @@ -" gvim settings: -" -"set guifontset=-misc-fixed-medium-r-normal-*-*-120-*-*-c-*-iso8859-2 -"set guifont=-misc-fixed-medium-r-normal-*-*-120-*-*-c-*-iso8859-2 -"set mouse=a -"set guifontset="Monospace 13" -"set guifont="Monospace 13" -"colorscheme pablo +"Basic setup for all files {{{ +set nocompatible "VIM over VI +filetype plugin indent on "turn plugins/indent on +syntax on "Turn syntax highlighting on -" vim setting: -" -set bg=dark -" -" VIM configuration file -" Author: Piotr Debicki (pdebicki@poczta.onet.pl) -"""""""" -" -" Always set autoindenting on -" - set autoindent -" -" Automatically save modifications to files when -" using critical commands -" - set autowrite -" -" Allow backspacing over everything in insert mode -" - set backspace=2 -" -" Don't make a backup before overwriting -" - set nobackup -" -" Reset cinwords - this suxx with smartindent -" - set cinwords= -" -" Use Vim settings, rather then Vi settings -" - set nocompatible -" -" Ask for confirmation rather then refuse certain commands -" - set confirm -" -" Type of in written files -" - set fileformats=unix,dos -" -" Automatic formatting settings -" - set formatoptions=croq -" -" Keep hidden windows -" - set hidden -" -" Keep 50 lines of command line history -" - set history=50 -" -" Don't highlight search patterns -" - set nohlsearch -" -" Ignore case in search patterns -" - set ignorecase -" -" Always show statusbar -" - set laststatus=2 -" -" Don't update screen while executing macros -" - set lazyredraw -" -" Strings to use in 'list' mode -" - set listchars=tab:>-,trail:-,eol:$ -" -" Show the cursor position all the time -" - set ruler -" -" Content of the ruler string -" - set rulerformat=%l,%c%V%=#%n\ %3p%% -" -" Minimal number of lines to scroll when the cursor gets off the screen -" -" set scrolljump=1 -" -" Minimal number of screen lines to keep above and below the cursor -" - set scrolloff=3 -" -" Define the behavior of the selection -" - set selection=exclusive -" -" Name of the shell to use for ! and :! commands -" -" set shell=binbash -" -" Number of spaces to use for each step of (auto)indent -" - set shiftwidth=4 -" -" Abbreviate some messages -" - set shortmess=atToOI -" -" String to put at the start of lines that have been wrapped -" - set showbreak=> -" -" Show (partial) command in status line -" - set showcmd -" -" When a bracket is inserted, briefly jump to the matching one -" - set showmatch -" -" Do smart autoindenting when starting a new line -" - set smartindent -" -" Create new window below current one -" - set splitbelow -" -" Use swap file -" - set swapfile -" -" Turn beeping off -" - set t_vb= -" -" Set tab stop to 4 -" - set tabstop=4 -" -" Turn off scrolling -> faster -" -" set ttyscroll=0 -" -" After typing this many chars the swap file will be written to disk -" - set updatecount=50 -" -" Configure .viminfo -" - set viminfo='20,\"50 -" -" Cursor keys wrap to previous/next line -" - set whichwrap+=<,>,[,] -" -" Character to start wildcard expansion in the command-line -" - set wildchar= -" -" Put command-line completion in an enhanced mode -" - set wildmenu -" -" Turn line wrapping off (a ja chcê wrap) -" -" set nowrap -" -" Number of characters from the right window border where wrapping starts -" - set wrapmargin=1 -" -" Turn syntax highlighting on -" - syntax on +set backspace=indent,eol,start "Allow backspacing over everything in insert mode +set background=dark "Hint Vim that I use dark colorscheme -" -" wgrywaj równie¿ widoki dla plików php -" - - au BufWinLeave *.php mkview - au BufWinEnter *.php silent loadview - -" -" ============================ -" Abbreviations -" ============================ -" -" Some C abbreviations -" - iab Zmain int main(int argc, char *argv[]) - iab Zinc #include - iab Zdef #define -" -" Some other abbreviations -" - iab Zdate =strftime("%y%m%d") - iab Ztime =strftime("%H:%M:%S") - iab Zmymail pdebicki@poczta.onet.pl - iab Zmyphone 0 502 935 242 - iab Zfilename =expand("%:t:r") - iab Zfilepath =expand("%:p") -" -" ============================ -" Customization -" ============================ -" -" Function keys -" - nmap 3K - nmap :cnext - nmap :cprevious - nmap :clist - nmap :make - nmap :!! - nmap :call SwitchTabstop() - nmap :call SwitchSyntax() - nmap :call SwitchIndent() - imap 3Ki - imap :cnext - imap :cprevious - imap :clist - imap :make - imap :!! - imap :call SwitchTabstop()i - imap :call SwitchSyntax()i - imap :call SwitchIndent()i -" -" Show next buffer -" - nmap :bnext -" -" Execute shell commands easier -" - nmap ! :! -" -" Align line -" - nmap ,ac :center - nmap ,al :left - nmap ,ar :right -" -" Print the ASCII value of the character under the cursor -" - nmap ,as :ascii -" -" Change type of - unix/dos -" - nmap ,eol :call ChangeFileFormat() -" -" Insert C/C++ source footer -" - nmap ,fo :%r $HOME/src/TEMPLATE/FOOTER -" -" Insert C/C++ source header -" - nmap ,he :0r $HOME/src/TEMPLATE/HEADER -" -" Turn highlight search on/off -" - nmap ,hs :call ToggleOption('hlsearch') -" -" Turn line numbers on/off -" - nmap ,nu :call ToggleOption('number') -" -" Remove all empty lines -" - nmap ,re :g/^$/d -" -" Edit .vimrc -" - nmap ,rc :n $HOME/.vimrc -" -" Turn line wrapping on/off -" - nmap ,wr :call ToggleOption('wrap') -" -" Show white spaces on/off -" - nmap ,ws :call ToggleOption('list') -" -" Make selection lowercase -" - vmap ,l u -" -" Rot13 encode selection -" - vmap ,r g? -" -" Make selection switch case -" - vmap ,s ~ -" -" Make selection uppercase -" - vmap ,u U -" -" tym, oto, skrótem komentuj/unkomentuj ca³e linie, bloki, etc. -" niezbêdny plugin enhcommentify w ~/.vim/plugin -" -nmap :call EnhancedCommentify('', 'guess')j -vmap :call EnhancedCommentify('', 'guess')j +set confirm "Ask for confirmation rather then refuse certain commands +set cursorline "Turn on current line highlight +set expandtab "I want spaces instead of tabs +set fileencodings=ucs-bom,utf-8,latin2,default,latin1,default +set fileformats=unix,dos "Type of in written files +set formatoptions=croqw "Automatic formatting settings +set hidden "Keep hidden windows +set history=1000 "Keep 1000 lines of command line history +set ignorecase "Ignore case in search patterns +set laststatus=2 "Always show statusbar +set lazyredraw "Don't update screen while executing macros -" -" ============================ -" Functions -" ============================ +"set listchars=tab:▸⎯,eol:â—¦ "Strings to use in 'list' mode. list is off by default. +"set listchars=tab:▸⎯,eol:· "Strings to use in 'list' mode. list is off by default. +"set listchars=tab:⇄·,eol:↵ "Strings to use in 'list' mode. list is off by default. +"set listchars=tab:▸⎯,eol:↲,trail:· "Strings to use in 'list' mode. list is off by default. +set listchars=tab:▸⎯,trail:· "Strings to use in 'list' mode. list is off by default. +set number "show line numbers +"set ruler "Show the cursor position all the time +set rulerformat=%l,%c%V%=#%n\ %3p%% "Content of the ruler string +"set statusline=%<%F\ %h%m%r%=%-14.(%l,%c%V%=#%n\ %3p%%)\ %P +"set statusline=%<%F\ %h%m%r%=%-14.(%l,%c%V%)\ #%n\ %3p%% +set scrolloff=5 "Minimal number of screen lines to keep above and below the cursor +set selection=exclusive "Define the behavior of the selection -function ToggleOption (option) - execute 'set ' . a:option . '!' - execute 'echo "' . a:option . ':" strpart("OFFON",3*&' . a:option . ',3)' +set sessionoptions-=blank "Don't store empty windows +set sessionoptions-=globals "Don't store global vars +set sessionoptions-=localoptions "Don't store local options and mappings +set sessionoptions-=options "Don't store options and mappings +set shiftwidth=4 "Number of spaces to use for each step of (auto)indent +set shortmess=atToOI "Abbreviate some messages +set showbreak=> "String to put at the start of lines that have been wrapped +set showcmd "Show (partial) command in status line +set showmatch "When a bracket is inserted, briefly jump to the matching one +"set smartindent "Do smart autoindenting when starting a new line +filetype indent on "Indenting per filetype rather then smartindent. +set smarttab "Do the smart tab/backspace behaviour +set softtabstop=4 + +"spell options +set spelllang=pl,en +set spellfile=/home/gryf/.vim/pol.utf8.add + +set splitbelow "Create new window below current one +set swapfile "Use swap file +set t_vb= "Turn beeping off +set tabstop=4 "Set tab stop to 4 +set updatecount=50 "After typing this many chars the swap file will be written to disk +set viewoptions-=options "Don't store options in view stored in ~/.vim/view dir +set viminfo='20,\"50 "Configure .viminfo +set whichwrap+=<,>,[,] "Cursor keys wrap to previous/next line +set wildchar= "Character to start wildcard expansion in the command-line +set wildmenu "Put command-line completion in an enhanced mode +set wrapmargin=1 "Number of characters from the right window border where wrapping starts + +" TOhtml options +:let html_number_lines = 1 +:let html_use_css = 1 +:let html_ignore_folding = 1 +:let html_use_encoding = "utf-8" +"}}} +"PYTHON: specific vim behaviour for Python files {{{ +" +"remove all trailing withitespace for python before write +autocmd BufWritePre *.py :call StripTrailingWhitespaces() +"autocmd BufWritePre *.py :!message.py '%' +"Load views for py files +autocmd BufWinLeave *.py mkview +autocmd BufWinEnter *.py silent loadview + +"Set python custom editor behaviour. Note, smartindent is not recommended for +"python files! +autocmd FileType python set tabstop=4|set softtabstop=4|set shiftwidth=4 +autocmd FileType python set expandtab|set smarttab|set noautoindent +autocmd FileType python set smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class,with +autocmd FileType python set foldmethod=indent|set foldlevel=100|set list|set textwidth=78|set cinkeys-=0# +autocmd FileType python set indentkeys-=0#|inoremap # X# +autocmd FileType python set ofu=syntaxcomplete#Complete + +"autocmd FileType python setlocal omnifunc=pysmell#Complete +let python_highlight_all=1 +" }}} +" OTHER FILES: {{{ +"autocmd FileType python :!echo '%' +autocmd FileType sql set nolist|set nosmartindent|set autoindent|set foldmethod=manual +autocmd FileType vim set nolist|set nosmartindent|set autoindent|set foldmethod=manual +autocmd FileType snippet set nolist|set tabstop=4|set autoindent|set foldmethod=manual|set noexpandtab|set shiftwidth=4 +autocmd FileType snippets set noexpandtab, nolist +augroup mkd + autocmd BufRead *.mkd set ai formatoptions=tcroqn2 comments=n:> +augroup END +autocmd FileType rst set spf=/home/gryf/.vim/pol.utf8.add|set textwidth=80 + +"}}} +"LaTeX: option for LaTeX files {{{ +autocmd FileType tex compiler rubber|map :make +"}}} +"TERMINAL: options for terminal emulators {{{ +if $TERM == 'rxvt-unicode' || $TERM == 'xterm' + set t_Co=256 "Enable 256 colors support + set term=rxvt-unicode256 "Set terminal type + "repair urxvt ctrl+pgup/down behaviour + map [5^ + map [6^ +endif +if $TERM == 'linux' + "For term like linux terminal keep interface simple + set nolist + set nocursorline + set nonumber +endif +"}}} +"PLUGINS: {{{ +"getscriptPlugin +"let g:GetLatestVimScripts_allowautoinstall=1 "allow autoinstall scripts + +"TagList{{{2 +let Tlist_Use_Right_Window = 1 +"show menu in gvim. usefull to pop it up from kbd +let Tlist_Show_Menu = 1 +let Tlist_Auto_Open = 0 +let Tlist_Display_Prototype = 1 +"open fold for current buff, and close all others... +let Tlist_File_Fold_Auto_Close = 1 +".. or just display current file +"let Tlist_Show_One_File = 1 +let Tlist_Sort_Type = "name" +let Tlist_Exit_OnlyWindow = 1 +let Tlist_WinWidth = 40 +"}}} + +"NERDTree +let NERDTreeWinSize = 40 + +"VimWIKI +let g:vimwiki_list = [{'html_header': '~/vimwiki/vimwiki_head.tpl', + \ 'html_footer': '~/vimwiki/vimwiki_foot.tpl'}] + +"ShowMarks +let g:showmarks_ignore_type = "hqprm" +let g:showmarks_include = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +"jsbeautify +nnoremap ff :call g:Jsbeautify():retab! + +" pydiction +let g:pydiction_location = '/home/gryf/.vim/after/ftplugin/pytdiction/complete-dict' +"}}} +"KEYS: User definied keyboard shortcuts {{{ + +"set =^[[11^ +"set = ^[[23~ +"nmap :bnext +"nmap :split +"nmap :vsplit + +"Cycle through buffers. +map :bp +map :bn +"map :bp +"map :bn + +"Cycle through tabs. +if $TERM == 'rxvt-unicode' + map :tabn + map :tabp +endif + +map :PyLint +map :call PyLintBuf() + +"map ctags plugin to show popup menu in gvim +"map :popup Tags + +"QuickFix jumps +map :cp +map :cn +map :lprevious +map :lnext +map :QFix +map :LWin +map :call ToggleQFonValidate() + +"remove trailing whitespaces +map :%s/\s\+$// + +"redefine tab key for vimwiki +map wn VimwikiNextWord +map wp VimwikiPrevWord +map ]b :call OpenInFirefox() + +"make displaying tags easy +nmap t :Tlist +"aswell minibufexplorer +"map b :TMiniBufExplorer +"eclim Buffer shortcut +map b :Buffers + +" copy current buffer filename (full path) +nmap ,cn :silent call CopyFileName(1) +" copy current buffer filename (filename only) +nmap ,cs :silent call CopyFileName(0) + +"FuzzyFinder plugin. Keys for file fuf +map :FufFile **/ +" }}} +" FUNCTIONS: usefull functions for all of th files {{{ +"Sessions +"autocmd VimEnter * call LoadSession() +"autocmd VimLeave * call SaveSession() +" +"function! SaveSession() +" execute 'mksession!' +"endfunction +" +"function! LoadSession() +" if argc() == 0 +" execute 'source Session.vim' +" endif +"endfunction + +"function PyLint() +" :make +" let l:mbe = 0 +" if bufwinnr(bufnr('-MiniBufExplorer-')) != -1 +" let l:mbe = 1 +" :CMiniBufExplorer +" endif +" :cwindow +" if l:mbe == 1 +" :MiniBufExplorer +" endif +"endfunction + +function! StripTrailingWhitespaces() + " Preparation: save last search, and cursor position. + let _s=@/ + let l = line(".") + let c = col(".") + " Do the business: + %s/\s\+$//e + " Clean up: restore previous search history, and cursor position + let @/=_s + call cursor(l, c) endfunction -function ChangeFileFormat() - if &fileformat == "unix" - set fileformat=dos - echo " type: DOS" - else - set fileformat=unix - echo " type: UNIX" - endif +function CopyFileName(full) + if a:full + let l:full_fn = expand("%:p") + else + let l:full_fn = expand("%") + endif + + " Convert slashes to backslashes for Windows. + if has('win32') + let @*=substitute(l:full_fn, "/", "\\", "g") + else + let @*=l:full_fn + endif + echo l:full_fn + " copied to clipboard" endfunction -function SwitchTabstop() - if &tabstop == 4 - set tabstop=8 - echo "Tabstop = 8" - else - set tabstop=4 - echo "Tabstop = 4" - endif +command -bang -nargs=? QFix call QFixToggle(0) +function! QFixToggle(forced) + if exists("g:qfix_win") && a:forced == 0 + cclose + unlet g:qfix_win + else + copen 10 + let g:qfix_win = bufnr("$") + endif endfunction -function SwitchSyntax() - if has("syntax_items") - syntax off - echo "Syntax highlighting OFF" - else - syntax on - echo "Syntax highlighting ON" - endif +command -bang -nargs=? LWin call LocationWindowToggle(0) +function! LocationWindowToggle(forced) + if exists("g:loc_win") && a:forced == 0 + lclose + unlet g:loc_win + else + lopen 10 + let g:loc_win = bufnr("$") + endif endfunction -function SwitchIndent() - if &autoindent - set noautoindent - set nosmartindent - set formatoptions= - echo "Indent OFF" - else - set autoindent - set smartindent - set formatoptions=croq - echo "Indent ON" - endif +" OpenInFirefox +" try to open url in Firefox +function! OpenInFirefox() + let l:line = getline(".") + let l:cursor_position = getpos(".")[2] + let l:url = "" + let l:pattern = '\c\%(http[s]\?\|ftp\|file\)\:\/\/[^$ ]\+' + + for i in split(l:line) + if match(i, l:pattern) == 0 + "check position in line against cursor_position + for x in range(match(l:line, i), match(l:line, i) + len(i)) + if l:cursor_position == x + let l:url = i + break + endif + endfor + endif + endfor + + if len(l:url) > 0 + call system("firefox " . l:url) + echohl Statement + echo "Opened '" . l:url ."' in firefox." + else + echohl WarningMsg + echo "Not an URL under cursor." + endif + echohl None endfunction -" vim:ts=4:sw=4:wrap: -" - EOF - - - +"}}} +" GUI: here goes all the gvim customizations {{{ +if has('gui_running') + "set guifont=Consolas\ 12 "I like this font, but it looks like crap on linux + "set listchars=tab:▸⎼,eol:↲ "Strings to use in 'list' mode. this is different from console fixed-misc font. + set guifont=Fixed\ 14 "I like this font better. + set mouse=a "Enable mouse support + set guioptions-=T "No toolbar + "add menuitem OpenInFirefox + nmenu 666 PopUp.&Open\ in\ browser :call OpenInFirefox() + "Turn off annoying beep + au GUIEnter * set vb t_vb= +endif +"}}} +" HIGHLIGHT: colorscheme and highlight, which should be applyed on after {{{ +" some vim initialization +if $TERM == 'linux' + colorscheme pablo +else + colorscheme wombat256grf +endif +"highlight code beyond 79 column (must be after colorscheme) +highlight OverLength ctermbg=black +match OverLength /\%81v.*/ +"}}} +" vim:ts=4:sw=4:wrap:fdm=marker: diff --git a/GetLatest/GetLatestVimScripts.dat b/GetLatest/GetLatestVimScripts.dat new file mode 100644 index 0000000..655672b --- /dev/null +++ b/GetLatest/GetLatestVimScripts.dat @@ -0,0 +1,37 @@ +ScriptID SourceID Filename +-------------------------- +### plugins +102 9375 DirDiff.vim +1658 11834 NERD_tree.vim +2754 12764 :AutoInstall: delimitMate.vim +1984 11852 fuzzyfinder.vim +642 8136 :AutoInstall: getscript.vim +311 7645 grep.vim +2727 11120 jsbeautify.vim +2666 12423 Mark +2262 8944 occur.vim +2421 9423 pysmell.vim +152 3342 showmarks.vim +2540 11006 snipMate.vim +273 7701 taglist.vim +2607 10388 tasklist.vim +90 12743 vcscommand.vim +2226 12476 vimwiki.vim +1334 6377 vst.vim +### colors +1975 7471 lettuce.vim +2536 12154 lucius.vim +1165 3741 tolerable.vim +2465 11352 wombat256.vim +# ftplugin +2441 12763 pyflakes.vim +30 9196 python_fn.vim +1542 10872 pythoncomplete.vim +### indent +1936 7708 javascript.vim +# there is also python.vim, which is close to PEP8, but author of +# changes doesn't put it on vim.org scripts. it can be (still) found on +# http://monkey.org/~caz/python.vim +### syntax +790 12805 python.vim + diff --git a/GetLatest/GetLatestVimScripts.dist b/GetLatest/GetLatestVimScripts.dist new file mode 100644 index 0000000..4745fc8 --- /dev/null +++ b/GetLatest/GetLatestVimScripts.dist @@ -0,0 +1,18 @@ +ScriptID SourceID Filename +-------------------------- +294 1 Align.vim +302 2 AnsiEsc.vim +122 3 astronaut.vim +104 4 blockhl.vim +120 5 decho.vim + 40 6 DrawIt.tar.gz +451 7 EasyAccents.vim +195 8 engspchk.vim +642 9 GetLatestVimScripts.vim +489 10 Manpageview.vim +551 11 Mines.vim +514 12 mrswin.vim +670 13 visincr.vim +628 14 SeeTab.vim +508 15 ZoomWin.vim +877 16 gvcolor.vim diff --git a/after/plugin/snipMate.vim b/after/plugin/snipMate.vim new file mode 100644 index 0000000..03e79ae --- /dev/null +++ b/after/plugin/snipMate.vim @@ -0,0 +1,35 @@ +" These are the mappings for snipMate.vim. Putting it here ensures that it +" will be mapped after other plugins such as supertab.vim. +if !exists('loaded_snips') || exists('s:did_snips_mappings') + finish +endif +let s:did_snips_mappings = 1 + +ino =TriggerSnippet() +snor i=TriggerSnippet() +ino =BackwardsSnippet() +snor i=BackwardsSnippet() +ino =ShowAvailableSnips() + +" The default mappings for these are annoying & sometimes break snipMate. +" You can change them back if you want, I've put them here for convenience. +snor b +snor a +snor bi +snor ' b' +snor ` b` +snor % b% +snor U bU +snor ^ b^ +snor \ b\ +snor b + +" By default load snippets in snippets_dir +if empty(snippets_dir) + finish +endif + +call GetSnippets(snippets_dir, '_') " Get global snippets + +au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif +" vim:noet:sw=4:ts=4:ft=vim diff --git a/autoload/fuf.vim b/autoload/fuf.vim new file mode 100644 index 0000000..0a91d3a --- /dev/null +++ b/autoload/fuf.vim @@ -0,0 +1,1155 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + + + +function fuf#getPathSeparator() + return (!&shellslash && (has('win32') || has('win64')) ? '\' : '/') +endfunction + +" Removes duplicates +" this function doesn't change list of argument. +function fuf#unique(items) + let sorted = sort(a:items) + if len(sorted) < 2 + return sorted + endif + let last = remove(sorted, 0) + let result = [last] + for item in sorted + if item != last + call add(result, item) + let last = item + endif + endfor + return result +endfunction + +" [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ] +" this function doesn't change list of argument. +function fuf#concat(items) + let result = [] + for l in a:items + let result += l + endfor + return result +endfunction + +" filter() with the maximum number of items +" this function doesn't change list of argument. +function fuf#filterWithLimit(items, expr, limit) + if a:limit <= 0 + return filter(copy(a:items), a:expr) + endif + let result = [] + let stride = a:limit * 3 / 2 " x1.5 + for i in range(0, len(a:items) - 1, stride) + let result += filter(a:items[i : i + stride - 1], a:expr) + if len(result) >= a:limit + return remove(result, 0, a:limit - 1) + endif + endfor + return result +endfunction + +" +function fuf#countModifiedFiles(files, time) + return len(filter(copy(a:files), 'getftime(v:val) > a:time')) +endfunction + +" +function fuf#getCurrentTagFiles() + return sort(filter(map(tagfiles(), 'fnamemodify(v:val, '':p'')'), 'filereadable(v:val)')) +endfunction + +" +function fuf#mapToSetSerialIndex(in, offset) + for i in range(len(a:in)) + let a:in[i].index = i + a:offset + endfor + return a:in +endfunction + +" +function fuf#updateMruList(mrulist, newItem, maxItem, exclude) + let result = copy(a:mrulist) + let result = filter(result,'v:val.word != a:newItem.word') + let result = insert(result, a:newItem) + let result = filter(result, 'v:val.word !~ a:exclude') + return result[0 : a:maxItem - 1] +endfunction + +" takes suffix number. if no digits, returns -1 +function fuf#suffixNumber(str) + let s = matchstr(a:str, '\d\+$') + return (len(s) ? str2nr(s) : -1) +endfunction + +" "foo/bar/buz/hoge" -> { head: "foo/bar/buz/", tail: "hoge" } +function fuf#splitPath(path) + let head = matchstr(a:path, '^.*[/\\]') + return { + \ 'head' : head, + \ 'tail' : a:path[strlen(head):] + \ } +endfunction + +" "foo/.../bar/...hoge" -> "foo/.../bar/../../hoge" +function fuf#expandTailDotSequenceToParentDir(pattern) + return substitute(a:pattern, '^\(.*[/\\]\)\?\zs\.\(\.\+\)\ze[^/\\]*$', + \ '\=repeat(".." . fuf#getPathSeparator(), len(submatch(2)))', '') +endfunction + +" +function fuf#hash224(str) + let a = 0x00000800 " shift 11 bit + let b = 0x001fffff " extract 11 bit + let nHash = 7 + let hashes = repeat([0], nHash) + for i in range(len(a:str)) + let iHash = i % nHash + let hashes[iHash] = hashes[iHash] * a + hashes[iHash] / b + let hashes[iHash] += char2nr(a:str[i]) + endfor + return join(map(hashes, 'printf("%08x", v:val)'), '') +endfunction + +" +function fuf#formatPrompt(prompt, partialMatching) + let indicator = (a:partialMatching ? '!' : '') + return substitute(a:prompt, '[]', indicator, 'g') +endfunction + +" +function fuf#getFileLines(file) + let bufnr = (type(a:file) ==# type(0) ? a:file : bufnr('^' . a:file . '$')) + let lines = getbufline(bufnr, 1, '$') + if !empty(lines) + return lines + endif + try + return readfile(expand(a:file)) + catch /.*/ + endtry + return [] +endfunction + +" +function fuf#makePreviewLinesAround(lines, indices, page, maxHeight) + let index = ((empty(a:indices) ? 0 : a:indices[0]) + \ + a:page * a:maxHeight) % len(a:lines) + if empty(a:lines) || a:maxHeight <= 0 + return [] + endif + let beg = max([0, index - a:maxHeight / 2]) + let end = min([beg + a:maxHeight, len(a:lines)]) + let beg = max([0, end - a:maxHeight]) + let lines = [] + for i in range(beg, end - 1) + let mark = (count(a:indices, i) ? '>' : ' ') + call add(lines, printf('%s%4d ', mark, i + 1) . a:lines[i]) + endfor + return lines +endfunction + +" a:file: a path string or a buffer number +function fuf#makePreviewLinesForFile(file, count, maxHeight) + let lines = fuf#getFileLines(a:file) + if empty(lines) + return [] + endif + let bufnr = (type(a:file) ==# type(0) ? a:file : bufnr('^' . a:file . '$')) + if exists('s:bufferCursorPosMap[bufnr]') + let indices = [s:bufferCursorPosMap[bufnr][1] - 1] + else + let indices = [] + endif + return fuf#makePreviewLinesAround( + \ lines, indices, a:count, a:maxHeight) +endfunction + +" +function fuf#echoWithHl(msg, hl) + execute "echohl " . a:hl + echo a:msg + echohl None +endfunction + +" +function fuf#inputHl(prompt, text, hl) + execute "echohl " . a:hl + let s = input(a:prompt, a:text) + echohl None + return s +endfunction + +" +function fuf#openBuffer(bufNr, mode, reuse) + if a:reuse && ((a:mode == s:OPEN_TYPE_SPLIT && + \ s:moveToWindowOfBufferInCurrentTabPage(a:bufNr)) || + \ (a:mode == s:OPEN_TYPE_VSPLIT && + \ s:moveToWindowOfBufferInCurrentTabPage(a:bufNr)) || + \ (a:mode == s:OPEN_TYPE_TAB && + \ s:moveToWindowOfBufferInOtherTabPage(a:bufNr))) + return + endif + execute printf({ + \ s:OPEN_TYPE_CURRENT : '%sbuffer' , + \ s:OPEN_TYPE_SPLIT : '%ssbuffer' , + \ s:OPEN_TYPE_VSPLIT : 'vertical %ssbuffer', + \ s:OPEN_TYPE_TAB : 'tab %ssbuffer' , + \ }[a:mode], a:bufNr) +endfunction + +" +function fuf#openFile(path, mode, reuse) + let bufNr = bufnr('^' . a:path . '$') + if bufNr > -1 + call fuf#openBuffer(bufNr, a:mode, a:reuse) + else + execute { + \ s:OPEN_TYPE_CURRENT : 'edit ' , + \ s:OPEN_TYPE_SPLIT : 'split ' , + \ s:OPEN_TYPE_VSPLIT : 'vsplit ' , + \ s:OPEN_TYPE_TAB : 'tabedit ', + \ }[a:mode] . fnameescape(fnamemodify(a:path, ':~:.')) + endif +endfunction + +" +function fuf#openTag(tag, mode) + execute { + \ s:OPEN_TYPE_CURRENT : 'tjump ' , + \ s:OPEN_TYPE_SPLIT : 'stjump ' , + \ s:OPEN_TYPE_VSPLIT : 'vertical stjump ', + \ s:OPEN_TYPE_TAB : 'tab stjump ' , + \ }[a:mode] . a:tag +endfunction + +" +function fuf#openHelp(tag, mode) + execute { + \ s:OPEN_TYPE_CURRENT : 'help ' , + \ s:OPEN_TYPE_SPLIT : 'help ' , + \ s:OPEN_TYPE_VSPLIT : 'vertical help ', + \ s:OPEN_TYPE_TAB : 'tab help ' , + \ }[a:mode] . a:tag +endfunction + +" +function fuf#prejump(mode) + execute { + \ s:OPEN_TYPE_CURRENT : '' , + \ s:OPEN_TYPE_SPLIT : 'split' , + \ s:OPEN_TYPE_VSPLIT : 'vsplit' , + \ s:OPEN_TYPE_TAB : 'tab split', + \ }[a:mode] +endfunction + +" +function fuf#compareRanks(i1, i2) + if exists('a:i1.ranks') && exists('a:i2.ranks') + for i in range(min([len(a:i1.ranks), len(a:i2.ranks)])) + if a:i1.ranks[i] > a:i2.ranks[i] + return +1 + elseif a:i1.ranks[i] < a:i2.ranks[i] + return -1 + endif + endfor + endif + return 0 +endfunction + +" +function fuf#makePathItem(fname, menu, appendsDirSuffix) + let pathPair = fuf#splitPath(a:fname) + let dirSuffix = (a:appendsDirSuffix && isdirectory(a:fname) + \ ? fuf#getPathSeparator() + \ : '') + return { + \ 'word' : a:fname . dirSuffix, + \ 'wordForPrimaryHead': s:toLowerForIgnoringCase(pathPair.head), + \ 'wordForPrimaryTail': s:toLowerForIgnoringCase(pathPair.tail), + \ 'wordForBoundary' : s:toLowerForIgnoringCase(s:getWordBoundaries(pathPair.tail)), + \ 'wordForRefining' : s:toLowerForIgnoringCase(a:fname . dirSuffix), + \ 'wordForRank' : s:toLowerForIgnoringCase(pathPair.tail), + \ 'menu' : a:menu, + \ } +endfunction + +" +function fuf#makeNonPathItem(word, menu) + let wordL = s:toLowerForIgnoringCase(a:word) + return { + \ 'word' : a:word, + \ 'wordForPrimary' : wordL, + \ 'wordForBoundary': s:toLowerForIgnoringCase(s:getWordBoundaries(a:word)), + \ 'wordForRefining': wordL, + \ 'wordForRank' : wordL, + \ 'menu' : a:menu, + \ } +endfunction + +" +function s:interpretPrimaryPatternForPathTail(pattern) + let pattern = fuf#expandTailDotSequenceToParentDir(a:pattern) + let pairL = fuf#splitPath(s:toLowerForIgnoringCase(pattern)) + return { + \ 'primary' : pattern, + \ 'primaryForRank': pairL.tail, + \ 'matchingPairs' : [['v:val.wordForPrimaryTail', pairL.tail],], + \ } +endfunction + +" +function s:interpretPrimaryPatternForPath(pattern) + let pattern = fuf#expandTailDotSequenceToParentDir(a:pattern) + let patternL = s:toLowerForIgnoringCase(pattern) + let pairL = fuf#splitPath(patternL) + if g:fuf_splitPathMatching + let matches = [ + \ ['v:val.wordForPrimaryHead', pairL.head], + \ ['v:val.wordForPrimaryTail', pairL.tail], + \ ] + else + let matches = [ + \ ['v:val.wordForPrimaryHead . v:val.wordForPrimaryTail', patternL], + \ ] + endif + return { + \ 'primary' : pattern, + \ 'primaryForRank': pairL.tail, + \ 'matchingPairs' : matches, + \ } +endfunction + +" +function s:interpretPrimaryPatternForNonPath(pattern) + let patternL = s:toLowerForIgnoringCase(a:pattern) + return { + \ 'primary' : a:pattern, + \ 'primaryForRank': patternL, + \ 'matchingPairs' : [['v:val.wordForPrimary', patternL],], + \ } +endfunction + +" +function fuf#makePatternSet(patternBase, interpreter, partialMatching) + let MakeMatchingExpr = function(a:partialMatching + \ ? 's:makePartialMatchingExpr' + \ : 's:makeFuzzyMatchingExpr') + let [primary; refinings] = split(a:patternBase, g:fuf_patternSeparator, 1) + let elements = call(a:interpreter, [primary]) + let primaryExprs = map(elements.matchingPairs, 'MakeMatchingExpr(v:val[0], v:val[1])') + let refiningExprs = map(refinings, 's:makeRefiningExpr(v:val)') + return { + \ 'primary' : elements.primary, + \ 'primaryForRank': elements.primaryForRank, + \ 'filteringExpr' : join(primaryExprs + refiningExprs, ' && '), + \ } +endfunction + +" +function fuf#enumExpandedDirsEntries(dir, exclude) + " Substitutes "\" because on Windows, "**\" doesn't include ".\", + " but "**/" include "./". I don't know why. + let dirNormalized = substitute(a:dir, '\', '/', 'g') + let entries = split(glob(dirNormalized . "*" ), "\n") + + \ split(glob(dirNormalized . ".*"), "\n") + " removes "*/." and "*/.." + call filter(entries, 'v:val !~ ''\v(^|[/\\])\.\.?$''') + call map(entries, 'fuf#makePathItem(v:val, "", 1)') + if len(a:exclude) + call filter(entries, 'v:val.word !~ a:exclude') + endif + return entries +endfunction + +" +function fuf#mapToSetAbbrWithSnippedWordAsPath(items) + let maxLenStats = {} + call map(a:items, 's:makeFileAbbrInfo(v:val, maxLenStats)') + let snippedHeads = + \ map(maxLenStats, 's:getSnippedHead(v:key[: -2], v:val)') + return map(a:items, 's:setAbbrWithFileAbbrData(v:val, snippedHeads)') +endfunction + +" +function fuf#setAbbrWithFormattedWord(item, abbrIndex) + let lenMenu = (exists('a:item.menu') ? len(a:item.menu) + 2 : 0) + let abbrPrefix = (exists('a:item.abbrPrefix') ? a:item.abbrPrefix : '') + let a:item.abbr = abbrPrefix . a:item.word + if a:abbrIndex + let a:item.abbr = printf('%4d: ', a:item.index) . a:item.abbr + endif + let a:item.abbr = s:snipTail(a:item.abbr, g:fuf_maxMenuWidth - lenMenu, s:ABBR_SNIP_MASK) + return a:item +endfunction + +" +function fuf#defineLaunchCommand(CmdName, modeName, prefixInitialPattern) + execute printf('command! -bang -narg=? %s call fuf#launch(%s, %s . , len())', + \ a:CmdName, string(a:modeName), a:prefixInitialPattern) +endfunction + +" +function fuf#defineKeyMappingInHandler(key, func) + " hacks to be able to use feedkeys(). + execute printf( + \ 'inoremap %s =fuf#getRunningHandler().%s ? "" : ""', + \ a:key, a:func) +endfunction + +" +function fuf#launch(modeName, initialPattern, partialMatching) + if exists('s:runningHandler') + call fuf#echoWithHl('FuzzyFinder is running.', 'WarningMsg') + endif + if count(g:fuf_modes, a:modeName) == 0 + echoerr 'This mode is not available: ' . a:modeName + return + endif + let s:runningHandler = fuf#{a:modeName}#createHandler(copy(s:handlerBase)) + let s:runningHandler.info = fuf#loadInfoFile(s:runningHandler.getModeName()) + let s:runningHandler.partialMatching = a:partialMatching + let s:runningHandler.bufNrPrev = bufnr('%') + let s:runningHandler.lastCol = -1 + call s:runningHandler.onModeEnterPre() + call s:setTemporaryGlobalOption('completeopt', 'menuone') + call s:setTemporaryGlobalOption('ignorecase', 0) + if s:runningHandler.getPreviewHeight() > 0 + call s:setTemporaryGlobalOption( + \ 'cmdheight', s:runningHandler.getPreviewHeight() + 1) + endif + call s:activateFufBuffer() + augroup FufLocal + autocmd! + autocmd CursorMovedI call s:runningHandler.onCursorMovedI() + autocmd InsertLeave nested call s:runningHandler.onInsertLeave() + augroup END + for [key, func] in [ + \ [ g:fuf_keyOpen , 'onCr(' . s:OPEN_TYPE_CURRENT . ', 0)' ], + \ [ g:fuf_keyOpenSplit , 'onCr(' . s:OPEN_TYPE_SPLIT . ', 0)' ], + \ [ g:fuf_keyOpenVsplit , 'onCr(' . s:OPEN_TYPE_VSPLIT . ', 0)' ], + \ [ g:fuf_keyOpenTabpage , 'onCr(' . s:OPEN_TYPE_TAB . ', 0)' ], + \ [ '' , 'onBs()' ], + \ [ '' , 'onBs()' ], + \ [ g:fuf_keyPreview , 'onPreviewBase()' ], + \ [ g:fuf_keyNextMode , 'onSwitchMode(+1)' ], + \ [ g:fuf_keyPrevMode , 'onSwitchMode(-1)' ], + \ [ g:fuf_keySwitchMatching, 'onSwitchMatching()' ], + \ [ g:fuf_keyPrevPattern , 'onRecallPattern(+1)' ], + \ [ g:fuf_keyNextPattern , 'onRecallPattern(-1)' ], + \ ] + call fuf#defineKeyMappingInHandler(key, func) + endfor + " Starts Insert mode and makes CursorMovedI event now. Command prompt is + " needed to forces a completion menu to update every typing. + call setline(1, s:runningHandler.getPrompt() . a:initialPattern) + call s:runningHandler.onModeEnterPost() + call feedkeys("A", 'n') " startinsert! does not work in InsertLeave event handler + redraw +endfunction + +" +function fuf#loadInfoFile(modeName) + try + let lines = readfile(expand(g:fuf_infoFile)) + " compatibility check + if count(lines, s:INFO_FILE_VERSION_LINE) == 0 + call s:warnOldInfoFile() + let g:fuf_infoFile = '' + throw 1 + endif + catch /.*/ + let lines = [] + endtry + let s:lastInfoMap = s:deserializeInfoMap(lines) + if !exists('s:lastInfoMap[a:modeName]') + let s:lastInfoMap[a:modeName] = {} + endif + return extend(s:lastInfoMap[a:modeName], { 'data': [], 'stats': [] }, 'keep') +endfunction + +" if a:modeName is empty, a:info is treated as a map of information +function fuf#saveInfoFile(modeName, info) + if empty(a:modeName) + let s:lastInfoMap = a:info + else + let s:lastInfoMap[a:modeName] = a:info + endif + let lines = [ s:INFO_FILE_VERSION_LINE ] + s:serializeInfoMap(s:lastInfoMap) + try + call writefile(lines, expand(g:fuf_infoFile)) + catch /.*/ + endtry +endfunction + +" +function fuf#editInfoFile() + new + silent file `='[fuf-info]'` + let s:bufNrInfo = bufnr('%') + setlocal filetype=vim + setlocal bufhidden=delete + setlocal buftype=acwrite + setlocal noswapfile + augroup FufInfo + autocmd! + autocmd BufWriteCmd call s:onBufWriteCmdInfoFile() + augroup END + execute '0read ' . expand(g:fuf_infoFile) + setlocal nomodified +endfunction + +" +function fuf#getRunningHandler() + return s:runningHandler +endfunction + +" +function fuf#onComplete(findstart, base) + return s:runningHandler.onComplete(a:findstart, a:base) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:INFO_FILE_VERSION_LINE = "VERSION\t300" +let s:ABBR_SNIP_MASK = '...' +let s:OPEN_TYPE_CURRENT = 1 +let s:OPEN_TYPE_SPLIT = 2 +let s:OPEN_TYPE_VSPLIT = 3 +let s:OPEN_TYPE_TAB = 4 + +" wildcard -> regexp +function s:convertWildcardToRegexp(expr) + let re = escape(a:expr, '\') + for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ] + let re = substitute(re, pat, sub, 'g') + endfor + return '\V' . re +endfunction + +" a:pattern: 'str' -> '\V\.\*s\.\*t\.\*r\.\*' +function s:makeFuzzyMatchingExpr(target, pattern) + let wi = '' + for c in split(a:pattern, '\zs') + if wi =~# '[^*?]$' && c !~ '[*?]' + let wi .= '*' + endif + let wi .= c + endfor + return s:makePartialMatchingExpr(a:target, wi) +endfunction + +" a:pattern: 'str' -> '\Vstr' +" 'st*r' -> '\Vst\.\*r' +function s:makePartialMatchingExpr(target, pattern) + let patternMigemo = s:makeAdditionalMigemoPattern(a:pattern) + if a:pattern !~ '[*?]' && empty(patternMigemo) + " NOTE: stridx is faster than regexp matching + return 'stridx(' . a:target . ', ' . string(a:pattern) . ') >= 0' + endif + return a:target . ' =~# ' . + \ string(s:convertWildcardToRegexp(a:pattern)) . patternMigemo +endfunction + +" +function s:makeRefiningExpr(pattern) + let expr = s:makePartialMatchingExpr('v:val.wordForRefining', a:pattern) + if a:pattern =~# '\D' + return expr + else + return '(' . expr . ' || v:val.index == ' . string(a:pattern) . ')' + endif +endfunction + +" +function s:makeAdditionalMigemoPattern(pattern) + if !g:fuf_useMigemo || a:pattern =~# '[^\x01-\x7e]' + return '' + endif + return '\|\m' . substitute(migemo(a:pattern), '\\_s\*', '.*', 'g') +endfunction + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function s:snipHead(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + return a:mask . a:str[-a:len + len(a:mask):] +endfunction + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function s:snipTail(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + return a:str[:a:len - 1 - len(a:mask)] . a:mask +endfunction + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function s:snipMid(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + let len_head = (a:len - len(a:mask)) / 2 + let len_tail = a:len - len(a:mask) - len_head + return (len_head > 0 ? a:str[: len_head - 1] : '') . a:mask . + \ (len_tail > 0 ? a:str[-len_tail :] : '') +endfunction + +" +function s:getWordBoundaries(word) + return substitute(a:word, '\a\zs\l\+\|\zs\A', '', 'g') +endfunction + +" +function s:toLowerForIgnoringCase(str) + return (g:fuf_ignoreCase ? tolower(a:str) : a:str) +endfunction + +" +function s:setRanks(item, pattern, exprBoundary, stats) + "let word2 = substitute(a:eval_word, '\a\zs\l\+\|\zs\A', '', 'g') + let a:item.ranks = [ + \ s:evaluateLearningRank(a:item.word, a:stats), + \ -s:scoreSequentialMatching(a:item.wordForRank, a:pattern), + \ -s:scoreBoundaryMatching(a:item.wordForBoundary, + \ a:pattern, a:exprBoundary), + \ a:item.index, + \ ] + return a:item +endfunction + +" +function s:evaluateLearningRank(word, stats) + for i in range(len(a:stats)) + if a:stats[i].word ==# a:word + return i + endif + endfor + return len(a:stats) +endfunction + +let g:s = "" +" range of return value is [0.0, 1.0] +function s:scoreSequentialMatching(word, pattern) + if empty(a:pattern) + return 0.0 + endif + let pos = stridx(a:word, a:pattern) + if pos < 0 + return 0.0 + endif + let lenRest = len(a:word) - len(a:pattern) - pos + return (pos == 0 ? 0.5 : 0.0) + 0.5 / (lenRest + 1) +endfunction + +" range of return value is [0.0, 1.0] +function s:scoreBoundaryMatching(wordForBoundary, pattern, exprBoundary) + if empty(a:pattern) + return 0.0 + endif + if !eval(a:exprBoundary) + return 0 + endif + return 0.5 + 0.5 * s:scoreSequentialMatching(a:wordForBoundary, a:pattern) +endfunction + +" +function s:highlightPrompt(prompt) + syntax clear + execute printf('syntax match %s /^\V%s/', g:fuf_promptHighlight, escape(a:prompt, '\')) +endfunction + +" +function s:highlightError() + syntax clear + syntax match Error /^.*$/ +endfunction + +" returns 0 if the buffer is not found. +function s:moveToWindowOfBufferInCurrentTabPage(bufNr) + if count(tabpagebuflist(), a:bufNr) == 0 + return 0 + endif + execute bufwinnr(a:bufNr) . 'wincmd w' + return 1 +endfunction + +" returns 0 if the buffer is not found. +function s:moveToOtherTabPageOpeningBuffer(bufNr) + for tabNr in range(1, tabpagenr('$')) + if tabNr != tabpagenr() && count(tabpagebuflist(tabNr), a:bufNr) > 0 + execute 'tabnext ' . tabNr + return 1 + endif + endfor + return 0 +endfunction + +" returns 0 if the buffer is not found. +function s:moveToWindowOfBufferInOtherTabPage(bufNr) + if !s:moveToOtherTabPageOpeningBuffer(a:bufNr) + return 0 + endif + return s:moveToWindowOfBufferInCurrentTabPage(a:bufNr) +endfunction + +" +function s:expandAbbrevMap(pattern, abbrevMap) + let result = [a:pattern] + for [pattern, subs] in items(a:abbrevMap) + let exprs = result + let result = [] + for expr in exprs + let result += map(copy(subs), 'substitute(expr, pattern, escape(v:val, ''\''), "g")') + endfor + endfor + return fuf#unique(result) +endfunction + +" +function s:makeFileAbbrInfo(item, maxLenStats) + let head = matchstr(a:item.word, '^.*[/\\]\ze.') + let a:item.abbr = { 'head' : head, + \ 'tail' : a:item.word[strlen(head):], + \ 'key' : head . '.', + \ 'prefix' : printf('%4d: ', a:item.index), } + if exists('a:item.abbrPrefix') + let a:item.abbr.prefix .= a:item.abbrPrefix + endif + let len = len(a:item.abbr.prefix) + len(a:item.word) + + \ (exists('a:item.menu') ? len(a:item.menu) + 2 : 0) + if !exists('a:maxLenStats[a:item.abbr.key]') || len > a:maxLenStats[a:item.abbr.key] + let a:maxLenStats[a:item.abbr.key] = len + endif + return a:item +endfunction + +" +function s:getSnippedHead(head, baseLen) + return s:snipMid(a:head, len(a:head) + g:fuf_maxMenuWidth - a:baseLen, s:ABBR_SNIP_MASK) +endfunction + +" +function s:setAbbrWithFileAbbrData(item, snippedHeads) + let lenMenu = (exists('a:item.menu') ? len(a:item.menu) + 2 : 0) + let abbr = a:item.abbr.prefix . a:snippedHeads[a:item.abbr.key] . a:item.abbr.tail + let a:item.abbr = s:snipTail(abbr, g:fuf_maxMenuWidth - lenMenu, s:ABBR_SNIP_MASK) + return a:item +endfunction + +let s:bufNrFuf = -1 + +" +function s:openFufBuffer() + if !bufexists(s:bufNrFuf) + topleft 1new + silent file `='[fuf]'` + let s:bufNrFuf = bufnr('%') + elseif bufwinnr(s:bufNrFuf) == -1 + topleft 1split + execute 'silent ' . s:bufNrFuf . 'buffer' + delete _ + elseif bufwinnr(s:bufNrFuf) != bufwinnr('%') + execute bufwinnr(s:bufNrFuf) . 'wincmd w' + endif +endfunction + +function s:setLocalOptionsForFufBuffer() + setlocal filetype=fuf + setlocal bufhidden=delete + setlocal buftype=nofile + setlocal noswapfile + setlocal nobuflisted + setlocal modifiable + setlocal nocursorline " for highlighting + setlocal nocursorcolumn " for highlighting + setlocal omnifunc=fuf#onComplete +endfunction + +" +function s:activateFufBuffer() + " lcd . : To avoid the strange behavior that unnamed buffer changes its cwd + " if 'autochdir' was set on. + lcd . + let cwd = getcwd() + call s:openFufBuffer() + " lcd ... : countermeasure against auto-cd script + lcd `=cwd` + call s:setLocalOptionsForFufBuffer() + redraw " for 'lazyredraw' + if exists(':AcpLock') + AcpLock + elseif exists(':AutoComplPopLock') + AutoComplPopLock + endif +endfunction + +" +function s:deactivateFufBuffer() + if exists(':AcpUnlock') + AcpUnlock + elseif exists(':AutoComplPopUnlock') + AutoComplPopUnlock + endif + " must close after returning to previous window + wincmd p + execute s:bufNrFuf . 'bdelete' +endfunction + +let s:originalGlobalOptions = {} + +" +function s:setTemporaryGlobalOption(name, value) + call extend(s:originalGlobalOptions, { a:name : eval('&' . a:name) }, 'keep') + execute printf('let &%s = a:value', a:name) +endfunction + +" +function s:restoreTemporaryGlobalOptions() + for [name, value] in items(s:originalGlobalOptions) + execute printf('let &%s = value', name) + endfor + let s:originalGlobalOptions = {} +endfunction + +" +function s:warnOldInfoFile() + call fuf#echoWithHl(printf("=================================================================\n" . + \ " Sorry, but your information file for FuzzyFinder is no longer \n" . + \ " compatible with this version of FuzzyFinder. Please remove \n" . + \ " %-63s\n" . + \ "=================================================================\n" , + \ '"' . expand(g:fuf_infoFile) . '".'), + \ 'WarningMsg') + echohl Question + call input('Press Enter') + echohl None +endfunction + +" +function s:serializeInfoMap(infoMap) + let lines = [] + for [m, info] in items(a:infoMap) + for [key, value] in items(info) + let lines += map(copy(value), 'm . "\t" . key . "\t" . string(v:val)') + endfor + endfor + return lines +endfunction + +" +function s:deserializeInfoMap(lines) + let infoMap = {} + for e in filter(map(a:lines, 'matchlist(v:val, ''^\v(\S+)\s+(\S+)\s+(.+)$'')'), '!empty(v:val)') + if !exists('infoMap[e[1]]') + let infoMap[e[1]] = {} + endif + if !exists('infoMap[e[1]][e[2]]') + let infoMap[e[1]][e[2]] = [] + endif + call add(infoMap[e[1]][e[2]], eval(e[3])) + endfor + return infoMap +endfunction + +" +function s:onBufWriteCmdInfoFile() + call fuf#saveInfoFile('', s:deserializeInfoMap(getline(1, '$'))) + setlocal nomodified + execute printf('%dbdelete! ', s:bufNrInfo) + echo "Information file updated" +endfunction + +" }}}1 +"============================================================================= +" s:handlerBase {{{1 + +let s:handlerBase = {} + +"----------------------------------------------------------------------------- +" PURE VIRTUAL FUNCTIONS {{{2 +" +" " +" s:handler.getModeName() +" +" " +" s:handler.getPrompt() +" +" " returns true if the mode deals with file paths. +" s:handler.targetsPath() +" +" " +" s:handler.getCompleteItems(patternSet) +" +" " +" s:handler.onOpen(word, mode) +" +" " Before entering FuzzyFinder buffer. This function should return in a short time. +" s:handler.onModeEnterPre() +" +" " After entering FuzzyFinder buffer. +" s:handler.onModeEnterPost() +" +" " After leaving FuzzyFinder buffer. +" s:handler.onModeLeavePost(opened) +" +" }}}2 +"----------------------------------------------------------------------------- + +" +function s:handlerBase.concretize(deriv) + call extend(self, a:deriv, 'error') + return self +endfunction + +" +function s:handlerBase.addStat(pattern, word) + let stat = { 'pattern' : a:pattern, 'word' : a:word } + call filter(self.info.stats, 'v:val !=# stat') + call insert(self.info.stats, stat) + let self.info.stats = self.info.stats[0 : g:fuf_learningLimit - 1] +endfunction + +" +function s:handlerBase.getMatchingCompleteItems(patternBase) + let MakeMatchingExpr = function(self.partialMatching + \ ? 's:makePartialMatchingExpr' + \ : 's:makeFuzzyMatchingExpr') + let patternSet = self.makePatternSet(a:patternBase) + let exprBoundary = s:makeFuzzyMatchingExpr('a:wordForBoundary', patternSet.primaryForRank) + let stats = filter( + \ copy(self.info.stats), 'v:val.pattern ==# patternSet.primaryForRank') + let items = self.getCompleteItems(patternSet.primary) + " NOTE: In order to know an excess, plus 1 to limit number + let items = fuf#filterWithLimit( + \ items, patternSet.filteringExpr, g:fuf_enumeratingLimit + 1) + return map(items, + \ 's:setRanks(v:val, patternSet.primaryForRank, exprBoundary, stats)') +endfunction + +" +function s:handlerBase.onComplete(findstart, base) + if a:findstart + return 0 + elseif !self.existsPrompt(a:base) + return [] + endif + call s:highlightPrompt(self.getPrompt()) + let items = [] + for patternBase in s:expandAbbrevMap(self.removePrompt(a:base), g:fuf_abbrevMap) + let items += self.getMatchingCompleteItems(patternBase) + if len(items) > g:fuf_enumeratingLimit + let items = items[ : g:fuf_enumeratingLimit - 1] + call s:highlightError() + break + endif + endfor + if empty(items) + call s:highlightError() + else + call sort(items, 'fuf#compareRanks') + call feedkeys("\\", 'n') + let self.lastFirstWord = items[0].word + endif + return items +endfunction + +" +function s:handlerBase.existsPrompt(line) + return strlen(a:line) >= strlen(self.getPrompt()) && + \ a:line[:strlen(self.getPrompt()) -1] ==# self.getPrompt() +endfunction + +" +function s:handlerBase.removePrompt(line) + return a:line[(self.existsPrompt(a:line) ? strlen(self.getPrompt()) : 0):] +endfunction + +" +function s:handlerBase.restorePrompt(line) + let i = 0 + while i < len(self.getPrompt()) && i < len(a:line) && self.getPrompt()[i] ==# a:line[i] + let i += 1 + endwhile + return self.getPrompt() . a:line[i : ] +endfunction + +" +function s:handlerBase.onCursorMovedI() + if !self.existsPrompt(getline('.')) + call setline('.', self.restorePrompt(getline('.'))) + call feedkeys("\", 'n') + elseif col('.') <= len(self.getPrompt()) + " if the cursor is moved before command prompt + call feedkeys(repeat("\", len(self.getPrompt()) - col('.') + 1), 'n') + elseif col('.') > strlen(getline('.')) && col('.') != self.lastCol + " if the cursor is placed on the end of the line and has been actually moved. + let self.lastCol = col('.') + let self.lastPattern = self.removePrompt(getline('.')) + call feedkeys("\\", 'n') + endif +endfunction + +" +function s:handlerBase.onInsertLeave() + unlet s:runningHandler + let lastPattern = self.removePrompt(getline('.')) + call s:restoreTemporaryGlobalOptions() + call s:deactivateFufBuffer() + call fuf#saveInfoFile(self.getModeName(), self.info) + let fOpen = exists('s:reservedCommand') + if fOpen + call self.onOpen(s:reservedCommand[0], s:reservedCommand[1]) + unlet s:reservedCommand + endif + call self.onModeLeavePost(fOpen) + if exists('s:reservedMode') + call fuf#launch(s:reservedMode, lastPattern, self.partialMatching) + unlet s:reservedMode + endif +endfunction + +" +function s:handlerBase.onCr(openType, fCheckDir) + if pumvisible() + call feedkeys(printf("\\=fuf#getRunningHandler().onCr(%d, %d) ? '' : ''\", + \ a:openType, self.targetsPath()), 'n') + return + endif + if !empty(self.lastPattern) + call self.addStat(self.lastPattern, self.removePrompt(getline('.'))) + endif + if a:fCheckDir && getline('.') =~# '[/\\]$' + " To clear i_ expression (fuf#getRunningHandler().onCr...) + echo '' + return + endif + let s:reservedCommand = [self.removePrompt(getline('.')), a:openType] + call feedkeys("\", 'n') " stopinsert behavior is strange... +endfunction + +" +function s:handlerBase.onBs() + let pattern = self.removePrompt(getline('.')[ : col('.') - 2]) + if empty(pattern) + let numBs = 0 + elseif !g:fuf_smartBs + let numBs = 1 + elseif pattern[-len(g:fuf_patternSeparator) : ] ==# g:fuf_patternSeparator + let numBs = len(split(pattern, g:fuf_patternSeparator, 1)[-2]) + \ + len(g:fuf_patternSeparator) + elseif self.targetsPath() && pattern[-1 : ] =~# '[/\\]' + let numBs = len(matchstr(pattern, '[^/\\]*.$')) + else + let numBs = 1 + endif + call feedkeys((pumvisible() ? "\" : "") . repeat("\", numBs), 'n') +endfunction + +" +function s:handlerBase.onPreviewBase() + if self.getPreviewHeight() <= 0 + return + elseif !pumvisible() + return + elseif !self.existsPrompt(getline('.')) + let word = self.removePrompt(getline('.')) + elseif !exists('self.lastFirstWord') + return + else + let word = self.lastFirstWord + endif + redraw + if exists('self.lastPreviewInfo') && self.lastPreviewInfo.word ==# word + let self.lastPreviewInfo.count += 1 + else + let self.lastPreviewInfo = {'word': word, 'count': 0} + endif + let lines = self.makePreviewLines(word, self.lastPreviewInfo.count) + let lines = lines[: self.getPreviewHeight() - 1] + call map(lines, 'substitute(v:val, "\t", repeat(" ", &tabstop), "g")') + call map(lines, 's:snipTail(v:val, &columns - 1, s:ABBR_SNIP_MASK)') + echo join(lines, "\n") +endfunction + +" +function s:handlerBase.onSwitchMode(shift) + let modes = copy(g:fuf_modes) + call map(modes, '{ "ranks": [ fuf#{v:val}#getSwitchOrder(), v:val ] }') + call filter(modes, 'v:val.ranks[0] >= 0') + call sort(modes, 'fuf#compareRanks') + let s:reservedMode = self.getModeName() + for i in range(len(modes)) + if modes[i].ranks[1] ==# self.getModeName() + let s:reservedMode = modes[(i + a:shift) % len(modes)].ranks[1] + break + endif + endfor + call feedkeys("\", 'n') " stopinsert doesn't work. +endfunction + +" +function s:handlerBase.onSwitchMatching() + let self.partialMatching = !self.partialMatching + let self.lastCol = -1 + call setline('.', self.restorePrompt(self.lastPattern)) + call feedkeys("\", 'n') + "call self.onCursorMovedI() +endfunction + +" +function s:handlerBase.onRecallPattern(shift) + let patterns = map(copy(self.info.stats), 'v:val.pattern') + if !exists('self.indexRecall') + let self.indexRecall = -1 + endif + let self.indexRecall += a:shift + if self.indexRecall < 0 + let self.indexRecall = -1 + elseif self.indexRecall >= len(patterns) + let self.indexRecall = len(patterns) - 1 + else + call setline('.', self.getPrompt() . patterns[self.indexRecall]) + call feedkeys("\", 'n') + endif +endfunction + +" }}}1 +"============================================================================= +" INITIALIZATION {{{1 + +augroup FufGlobal + autocmd! + autocmd BufLeave * let s:bufferCursorPosMap[bufnr('')] = getpos('.') +augroup END + +let s:bufferCursorPosMap = {} + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/autoload/fuf/bookmark.vim b/autoload/fuf/bookmark.vim new file mode 100644 index 0000000..59cc13b --- /dev/null +++ b/autoload/fuf/bookmark.vim @@ -0,0 +1,211 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_bookmark') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_bookmark = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#bookmark#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#bookmark#getSwitchOrder() + return g:fuf_bookmark_switchOrder +endfunction + +" +function fuf#bookmark#renewCache() +endfunction + +" +function fuf#bookmark#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#bookmark#onInit() + call fuf#defineLaunchCommand('FufBookmark', s:MODE_NAME, '""') + command! -bang -narg=? FufAddBookmark call s:bookmarkHere() + command! -bang -narg=0 -range FufAddBookmarkAsSelectedText call s:bookmarkHere(s:getSelectedText()) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') +let s:OPEN_TYPE_DELETE = -1 + +" +function s:getSelectedText() + let reg_ = [@", getregtype('"')] + let regA = [@a, getregtype('a')] + if mode() =~# "[vV\]" + silent normal! "aygv + else + let pos = getpos('.') + silent normal! gv"ay + call setpos('.', pos) + endif + let text = @a + call setreg('"', reg_[0], reg_[1]) + call setreg('a', regA[0], regA[1]) + return text +endfunction + +" opens a:path and jumps to the line matching to a:pattern from a:lnum within +" a:range. if not found, jumps to a:lnum. +function s:jumpToBookmark(path, mode, pattern, lnum) + call fuf#openFile(a:path, a:mode, g:fuf_reuseWindow) + call cursor(s:getMatchingLineNumber(getline(1, '$'), a:pattern, a:lnum), 0) + normal! zvzz +endfunction + +" +function s:getMatchingLineNumber(lines, pattern, lnumBegin) + let l = min([a:lnumBegin, len(a:lines)]) + for [l0, l1] in map(range(0, g:fuf_bookmark_searchRange), + \ '[l + v:val, l - v:val]') + if l0 <= len(a:lines) && a:lines[l0 - 1] =~# a:pattern + return l0 + elseif l1 >= 0 && a:lines[l1 - 1] =~# a:pattern + return l1 + endif + endfor + return l +endfunction + +" +function s:getLinePattern(lnum) + return '\C\V\^' . escape(getline(a:lnum), '\') . '\$' +endfunction + +" +function s:bookmarkHere(word) + if !empty(&buftype) || expand('%') !~ '\S' + call fuf#echoWithHl('Can''t bookmark this buffer.', 'WarningMsg') + return + endif + let item = { + \ 'word' : (a:word =~# '\S' ? substitute(a:word, '\n', ' ', 'g') + \ : pathshorten(expand('%:p:~')) . '|' . line('.') . '| ' . getline('.')), + \ 'path' : expand('%:p'), + \ 'lnum' : line('.'), + \ 'pattern' : s:getLinePattern(line('.')), + \ 'time' : localtime(), + \ } + let item.word = fuf#inputHl('Bookmark as:', item.word, 'Question') + if item.word !~ '\S' + call fuf#echoWithHl('Canceled', 'WarningMsg') + return + endif + let info = fuf#loadInfoFile(s:MODE_NAME) + call insert(info.data, item) + call fuf#saveInfoFile(s:MODE_NAME, info) +endfunction + +" +function s:findItem(items, word) + for item in a:items + if item.word ==# a:word + return item + endif + endfor + return {} +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_bookmark_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let item = s:findItem(self.info.data, a:word) + let lines = fuf#getFileLines(item.path) + if empty(lines) + return [] + endif + let index = s:getMatchingLineNumber(lines, item.pattern, item.lnum) - 1 + return fuf#makePreviewLinesAround( + \ lines, [index], a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + if a:mode == s:OPEN_TYPE_DELETE + call filter(self.info.data, 'v:val.word !=# a:word') + call fuf#saveInfoFile(s:MODE_NAME, self.info) + call fuf#launch(s:MODE_NAME, self.lastPattern, self.partialMatching) + return + else + let item = s:findItem(self.info.data, a:word) + if !empty(item) + call s:jumpToBookmark(item.path, a:mode, item.pattern, item.lnum) + endif + endif +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + call fuf#defineKeyMappingInHandler(g:fuf_bookmark_keyDelete, + \ 'onCr(' . s:OPEN_TYPE_DELETE . ', 0)') + let self.items = copy(self.info.data) + call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))') + call fuf#mapToSetSerialIndex(self.items, 1) + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/buffer.vim b/autoload/fuf/buffer.vim new file mode 100644 index 0000000..b8e5ee1 --- /dev/null +++ b/autoload/fuf/buffer.vim @@ -0,0 +1,176 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_buffer') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_buffer = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#buffer#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#buffer#getSwitchOrder() + return g:fuf_buffer_switchOrder +endfunction + +" +function fuf#buffer#renewCache() +endfunction + +" +function fuf#buffer#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#buffer#onInit() + call fuf#defineLaunchCommand('FufBuffer', s:MODE_NAME, '""') + augroup fuf#buffer + autocmd! + autocmd BufEnter * call s:updateBufTimes() + autocmd BufWritePost * call s:updateBufTimes() + augroup END +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +let s:bufTimes = {} + +" +function s:updateBufTimes() + let s:bufTimes[bufnr('%')] = localtime() +endfunction + +" +function s:makeItem(nr) + let fname = (empty(bufname(a:nr)) + \ ? '[No Name]' + \ : fnamemodify(bufname(a:nr), ':~:.')) + let time = (exists('s:bufTimes[a:nr]') ? s:bufTimes[a:nr] : 0) + let item = fuf#makePathItem(fname, strftime(g:fuf_timeFormat, time), 0) + let item.index = a:nr + let item.bufNr = a:nr + let item.time = time + let item.abbrPrefix = s:getBufIndicator(a:nr) . ' ' + return item +endfunction + +" +function s:getBufIndicator(bufNr) + if !getbufvar(a:bufNr, '&modifiable') + return '[-]' + elseif getbufvar(a:bufNr, '&modified') + return '[+]' + elseif getbufvar(a:bufNr, '&readonly') + return '[R]' + else + return ' ' + endif +endfunction + +" +function s:compareTimeDescending(i1, i2) + return a:i1.time == a:i2.time ? 0 : a:i1.time > a:i2.time ? -1 : +1 +endfunction + +" +function s:findItem(items, word) + for item in a:items + if item.word ==# a:word + return item + endif + endfor + return {} +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_buffer_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let item = s:findItem(self.items, a:word) + if empty(item) + return [] + endif + return fuf#makePreviewLinesForFile(item.bufNr, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + " not use bufnr(a:word) in order to handle unnamed buffer + let item = s:findItem(self.items, a:word) + if !empty(item) + call fuf#openBuffer(item.bufNr, a:mode, g:fuf_reuseWindow) + endif +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let self.items = map(filter(range(1, bufnr('$')), + \ 'buflisted(v:val) && v:val != self.bufNrPrev'), + \ 's:makeItem(v:val)') + if g:fuf_buffer_mruOrder + call fuf#mapToSetSerialIndex(sort(self.items, 's:compareTimeDescending'), 1) + endif + let self.items = fuf#mapToSetAbbrWithSnippedWordAsPath(self.items) +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/callbackfile.vim b/autoload/fuf/callbackfile.vim new file mode 100644 index 0000000..8c69638 --- /dev/null +++ b/autoload/fuf/callbackfile.vim @@ -0,0 +1,133 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_callbackfile') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_callbackfile = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#callbackfile#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#callbackfile#getSwitchOrder() + return -1 +endfunction + +" +function fuf#callbackfile#renewCache() + let s:cache = {} +endfunction + +" +function fuf#callbackfile#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#callbackfile#onInit() +endfunction + +" +function fuf#callbackfile#launch(initialPattern, partialMatching, prompt, exclude, listener) + let s:prompt = (empty(a:prompt) ? '>' : a:prompt) + let s:exclude = a:exclude + let s:listener = a:listener + call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:enumItems(dir) + let key = getcwd() . s:exclude . "\n" . a:dir + if !exists('s:cache[key]') + let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, s:exclude) + if isdirectory(a:dir) + call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0)) + endif + call fuf#mapToSetSerialIndex(s:cache[key], 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key]) + endif + return s:cache[key] +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(s:prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + let items = copy(s:enumItems(fuf#splitPath(a:patternPrimary).head)) + return filter(items, 'bufnr("^" . v:val.word . "$") != self.bufNrPrev') +endfunction + +" +function s:handler.onOpen(word, mode) + call s:listener.onComplete(a:word, a:mode) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) + if !a:opened + call s:listener.onAbort() + endif +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/callbackitem.vim b/autoload/fuf/callbackitem.vim new file mode 100644 index 0000000..3ee072c --- /dev/null +++ b/autoload/fuf/callbackitem.vim @@ -0,0 +1,135 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_callbackitem') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_callbackitem = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#callbackitem#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#callbackitem#getSwitchOrder() + return -1 +endfunction + +" +function fuf#callbackitem#renewCache() +endfunction + +" +function fuf#callbackitem#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#callbackitem#onInit() +endfunction + +" +function fuf#callbackitem#launch(initialPattern, partialMatching, prompt, listener, items, forPath) + let s:prompt = (empty(a:prompt) ? '>' : a:prompt) + let s:listener = a:listener + let s:forPath = a:forPath + let s:items = copy(a:items) + if s:forPath + call map(s:items, 'fuf#makePathItem(v:val, "", 1)') + call fuf#mapToSetSerialIndex(s:items, 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items) + else + call map(s:items, 'fuf#makeNonPathItem(v:val, "")') + call fuf#mapToSetSerialIndex(s:items, 1) + call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') + endif + call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(s:prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + if s:forPath + return g:fuf_previewHeight + endif + return 0 +endfunction + +" +function s:handler.targetsPath() + return s:forPath +endfunction + +" +function s:handler.makePatternSet(patternBase) + let parser = (s:forPath + \ ? 's:interpretPrimaryPatternForPath' + \ : 's:interpretPrimaryPatternForNonPath') + return fuf#makePatternSet(a:patternBase, parser, self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + if s:forPath + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) + endif + return [] +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:items +endfunction + +" +function s:handler.onOpen(word, mode) + call s:listener.onComplete(a:word, a:mode) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) + if !a:opened + call s:listener.onAbort() + endif +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/changelist.vim b/autoload/fuf/changelist.vim new file mode 100644 index 0000000..40f2d2c --- /dev/null +++ b/autoload/fuf/changelist.vim @@ -0,0 +1,168 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_changelist') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_changelist = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#changelist#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#changelist#getSwitchOrder() + return g:fuf_changelist_switchOrder +endfunction + +" +function fuf#changelist#renewCache() +endfunction + +" +function fuf#changelist#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#changelist#onInit() + call fuf#defineLaunchCommand('FufChangeList', s:MODE_NAME, '""') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getChangesLines() + redir => result + :silent changes + redir END + return split(result, "\n") +endfunction + +" +function s:parseChangesLine(line) + " return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$') + let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$') + if empty(elements) + return {} + endif + return { + \ 'prefix': elements[1], + \ 'count' : elements[2], + \ 'lnum' : elements[3], + \ 'text' : printf('|%d:%d|%s', elements[3], elements[4], elements[5]), + \ } +endfunction + +" +function s:makeItem(line) + let parsed = s:parseChangesLine(a:line) + if empty(parsed) + return {} + endif + let item = fuf#makeNonPathItem(parsed.text, '') + let item.abbrPrefix = parsed.prefix + let item.lnum = parsed.lnum + return item +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_changelist_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let items = filter(copy(self.items), 'v:val.word ==# a:word') + if empty(items) + return [] + endif + let lines = fuf#getFileLines(self.bufNrPrev) + return fuf#makePreviewLinesAround( + \ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#prejump(a:mode) + let older = 0 + for line in reverse(s:getChangesLines()) + if stridx(line, '>') == 0 + let older = 1 + endif + let parsed = s:parseChangesLine(line) + if !empty(parsed) && parsed.text ==# a:word + if parsed.count != 0 + execute 'normal! ' . parsed.count . (older ? 'g;' : 'g,') . 'zvzz' + endif + break + endif + endfor +endfunction + +" +function s:handler.onModeEnterPre() + let self.items = s:getChangesLines() +endfunction + +" +function s:handler.onModeEnterPost() + call map(self.items, 's:makeItem(v:val)') + call filter(self.items, '!empty(v:val)') + call reverse(self.items) + call fuf#mapToSetSerialIndex(self.items, 1) + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/autoload/fuf/dir.vim b/autoload/fuf/dir.vim new file mode 100644 index 0000000..689ba0f --- /dev/null +++ b/autoload/fuf/dir.vim @@ -0,0 +1,128 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_dir') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_dir = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#dir#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#dir#getSwitchOrder() + return g:fuf_dir_switchOrder +endfunction + +" +function fuf#dir#renewCache() + let s:cache = {} +endfunction + +" +function fuf#dir#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#dir#onInit() + call fuf#defineLaunchCommand('FufDir' , s:MODE_NAME, '""') + call fuf#defineLaunchCommand('FufDirWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')') + call fuf#defineLaunchCommand('FufDirWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:enumItems(dir) + let key = getcwd() . g:fuf_dir_exclude . "\n" . a:dir + if !exists('s:cache[key]') + let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_dir_exclude) + call filter(s:cache[key], 'v:val.word =~# ''[/\\]$''') + if isdirectory(a:dir) + call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0)) + endif + call fuf#mapToSetSerialIndex(s:cache[key], 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key]) + endif + return s:cache[key] +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_dir_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesAround( + \ split(glob(fnamemodify(a:word, ':p') . '*'), "\n"), + \ [], a:count, self.getPreviewHeight()) + return +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:enumItems(fuf#splitPath(a:patternPrimary).head) +endfunction + +" +function s:handler.onOpen(word, mode) + execute ':cd ' . fnameescape(a:word) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/file.vim b/autoload/fuf/file.vim new file mode 100644 index 0000000..348b4af --- /dev/null +++ b/autoload/fuf/file.vim @@ -0,0 +1,137 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_file') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_file = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#file#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#file#getSwitchOrder() + return g:fuf_file_switchOrder +endfunction + +" +function fuf#file#renewCache() + let s:cache = {} +endfunction + +" +function fuf#file#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#file#onInit() + call fuf#defineLaunchCommand('FufFile' , s:MODE_NAME, '""') + call fuf#defineLaunchCommand('FufFileWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')') + call fuf#defineLaunchCommand('FufFileWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:enumItems(dir) + let key = getcwd() . g:fuf_file_exclude . "\n" . a:dir + if !exists('s:cache[key]') + let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_file_exclude) + call fuf#mapToSetSerialIndex(s:cache[key], 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key]) + endif + return s:cache[key] +endfunction + +" +function s:enumNonCurrentItems(dir, bufNr, cache) + let key = a:dir . 'AVOIDING EMPTY KEY' + if !exists('a:cache[key]') + " NOTE: filtering should be done with + " 'bufnr("^" . v:val.word . "$") != a:bufNr'. + " But it takes a lot of time! + let bufName = bufname(a:bufNr) + let a:cache[key] = + \ filter(copy(s:enumItems(a:dir)), 'v:val.word != bufName') + endif + return a:cache[key] +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_file_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:enumNonCurrentItems( + \ fuf#splitPath(a:patternPrimary).head, self.bufNrPrev, self.cache) +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let self.cache = {} +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/givencmd.vim b/autoload/fuf/givencmd.vim new file mode 100644 index 0000000..7572829 --- /dev/null +++ b/autoload/fuf/givencmd.vim @@ -0,0 +1,119 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_givencmd') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_givencmd = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#givencmd#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#givencmd#getSwitchOrder() + return -1 +endfunction + +" +function fuf#givencmd#renewCache() +endfunction + +" +function fuf#givencmd#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#givencmd#onInit() +endfunction + +" +function fuf#givencmd#launch(initialPattern, partialMatching, prompt, items) + let s:prompt = (empty(a:prompt) ? '>' : a:prompt) + let s:items = copy(a:items) + call map(s:items, 'fuf#makeNonPathItem(v:val, "")') + call fuf#mapToSetSerialIndex(s:items, 1) + call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') + call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(s:prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return 0 +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return [] +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:items +endfunction + +" +function s:handler.onOpen(word, mode) + if a:word[0] =~# '[:/?]' + call histadd(a:word[0], a:word[1:]) + endif + call feedkeys(a:word . "\", 'n') +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/givendir.vim b/autoload/fuf/givendir.vim new file mode 100644 index 0000000..10b89ef --- /dev/null +++ b/autoload/fuf/givendir.vim @@ -0,0 +1,119 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_givendir') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_givendir = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#givendir#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#givendir#getSwitchOrder() + return -1 +endfunction + +" +function fuf#givendir#renewCache() +endfunction + +" +function fuf#givendir#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#givendir#onInit() +endfunction + +" +function fuf#givendir#launch(initialPattern, partialMatching, prompt, items) + let s:prompt = (empty(a:prompt) ? '>' : a:prompt) + let s:items = map(copy(a:items), 'substitute(v:val, ''[/\\]\?$'', "", "")') + let s:items = map(s:items, 'fuf#makePathItem(v:val, "", 0)') + call fuf#mapToSetSerialIndex(s:items, 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items) + call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching) +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(s:prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesAround( + \ split(glob(fnamemodify(a:word, ':p') . '*'), "\n"), + \ [], a:count, self.getPreviewHeight()) + return +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:items +endfunction + +" +function s:handler.onOpen(word, mode) + execute ':cd ' . fnameescape(a:word) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/givenfile.vim b/autoload/fuf/givenfile.vim new file mode 100644 index 0000000..3b726bc --- /dev/null +++ b/autoload/fuf/givenfile.vim @@ -0,0 +1,117 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_givenfile') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_givenfile = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#givenfile#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#givenfile#getSwitchOrder() + return -1 +endfunction + +" +function fuf#givenfile#renewCache() +endfunction + +" +function fuf#givenfile#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#givenfile#onInit() +endfunction + +" +function fuf#givenfile#launch(initialPattern, partialMatching, prompt, items) + let s:prompt = (empty(a:prompt) ? '>' : a:prompt) + let s:items = map(copy(a:items), 'fuf#makePathItem(v:val, "", 0)') + call fuf#mapToSetSerialIndex(s:items, 1) + call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') + call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching) +endfunction + + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(s:prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow) +endfunction + + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/help.vim b/autoload/fuf/help.vim new file mode 100644 index 0000000..b0693d0 --- /dev/null +++ b/autoload/fuf/help.vim @@ -0,0 +1,202 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_help') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_help = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#help#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#help#getSwitchOrder() + return g:fuf_help_switchOrder +endfunction + +" +function fuf#help#renewCache() + let s:cache = {} +endfunction + +" +function fuf#help#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#help#onInit() + call fuf#defineLaunchCommand('FufHelp' , s:MODE_NAME, '""') + call fuf#defineLaunchCommand('FufHelpWithCursorWord', s:MODE_NAME, 'expand('''')') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getCurrentHelpTagFiles() + let prefix = 'doc' . fuf#getPathSeparator() + let tagFiles = split(globpath(&runtimepath, prefix . 'tags' ), "\n") + \ + split(globpath(&runtimepath, prefix . 'tags-??'), "\n") + return sort(map(tagFiles, 'fnamemodify(v:val, ":p")')) +endfunction + +" +function s:parseHelpTagEntry(line, tagFile) + let elements = split(a:line, "\t") + if len(elements) != 3 || elements[0][0] ==# '!' + return {} + endif + let suffix = matchstr(a:tagFile, '-\zs..$') + if empty(suffix) + let suffix = '@en' + else + let suffix = '@' . suffix + endif + let dir = fnamemodify(a:tagFile, ':h') . fuf#getPathSeparator() + return { + \ 'word' : elements[0] . suffix, + \ 'path' : dir . elements[1], + \ 'pattern': elements[2][1:], + \ } +endfunction + +" +function s:getHelpTagEntries(tagFile) + let names = map(readfile(a:tagFile), 's:parseHelpTagEntry(v:val, a:tagFile)') + return filter(names, '!empty(v:val)') +endfunction + +" +function s:parseHelpTagFiles(tagFiles) + if !empty(g:fuf_help_cache_dir) + if !isdirectory(expand(g:fuf_help_cache_dir)) + call mkdir(expand(g:fuf_help_cache_dir), 'p') + endif + " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists. + let cacheFile = fnamemodify(g:fuf_help_cache_dir, ':p') + \ . fuf#hash224(join(a:tagFiles, "\n")) + if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0 + return map(readfile(cacheFile), 'eval(v:val)') + endif + endif + let items = fuf#unique(fuf#concat(map(copy(a:tagFiles), 's:getHelpTagEntries(v:val)'))) + let items = map(items, 'extend(v:val, fuf#makeNonPathItem(v:val.word, ""))') + call fuf#mapToSetSerialIndex(items, 1) + let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') + if !empty(g:fuf_help_cache_dir) + call writefile(map(copy(items), 'string(v:val)'), cacheFile) + endif + return items +endfunction + +" +function s:enumHelpTags(tagFiles) + if !len(a:tagFiles) + return [] + endif + let key = join(a:tagFiles, "\n") + if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time) + let s:cache[key] = { + \ 'time' : localtime(), + \ 'items' : s:parseHelpTagFiles(a:tagFiles) + \ } + endif + return s:cache[key].items +endfunction + +" +function s:getMatchingIndex(lines, pattern) + if empty(a:pattern) + return -1 + endif + for i in range(len(a:lines)) + if stridx(a:lines[i], a:pattern) >= 0 + return i + endif + endfor + return -1 +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_help_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let items = filter(copy(s:enumHelpTags(self.tagFiles)), 'v:val.word ==# a:word') + if empty(items) + return [] + endif + let lines = fuf#getFileLines(items[0].path) + let index = s:getMatchingIndex(lines, items[0].pattern) + return [items[0].path . ':'] + fuf#makePreviewLinesAround( + \ lines, (index < 0 ? [] : [index]), a:count, self.getPreviewHeight() - 1) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:enumHelpTags(self.tagFiles) +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openHelp(a:word, a:mode) +endfunction + +" +function s:handler.onModeEnterPre() + let self.tagFiles = s:getCurrentHelpTagFiles() +endfunction + +" +function s:handler.onModeEnterPost() +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/jumplist.vim b/autoload/fuf/jumplist.vim new file mode 100644 index 0000000..72876d9 --- /dev/null +++ b/autoload/fuf/jumplist.vim @@ -0,0 +1,178 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_jumplist') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_jumplist = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#jumplist#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#jumplist#getSwitchOrder() + return g:fuf_jumplist_switchOrder +endfunction + +" +function fuf#jumplist#renewCache() +endfunction + +" +function fuf#jumplist#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#jumplist#onInit() + call fuf#defineLaunchCommand('FufJumpList', s:MODE_NAME, '""') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getJumpsLines() + redir => result + :silent jumps + redir END + return split(result, "\n") +endfunction + +" +function s:parseJumpsLine(line, bufnrPrev) + "return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$') + let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$') + if empty(elements) + return {} + endif + let linePrevBuffer = join(getbufline(a:bufnrPrev, elements[3])) + if stridx(linePrevBuffer, elements[5]) >= 0 + let fname = bufname(a:bufnrPrev) + let text = elements[5] + else + let fname = elements[5] + let text = join(getbufline('^' . elements[5] . '$', elements[3])) + endif + return { + \ 'prefix': elements[1], + \ 'count' : elements[2], + \ 'lnum' : elements[3], + \ 'fname' : fname, + \ 'text' : printf('%s|%d:%d|%s', fname, elements[3], elements[4], text), + \ } +endfunction + +" +function s:makeItem(line, bufnrPrev) + let parsed = s:parseJumpsLine(a:line, a:bufnrPrev) + if empty(parsed) + return {} + endif + let item = fuf#makeNonPathItem(parsed.text, '') + let item.abbrPrefix = parsed.prefix + let item.lnum = parsed.lnum + let item.fname = parsed.fname + return item +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_jumplist_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let items = filter(copy(self.items), 'v:val.word ==# a:word') + if empty(items) + return [] + endif + let lines = fuf#getFileLines(items[0].fname) + return fuf#makePreviewLinesAround( + \ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#prejump(a:mode) + let older = 0 + for line in reverse(s:getJumpsLines()) + if stridx(line, '>') == 0 + let older = 1 + endif + let parsed = s:parseJumpsLine(line, self.bufNrPrev) + if !empty(parsed) && parsed.text ==# a:word + if parsed.count != 0 + execute 'normal! ' . parsed.count . (older ? "\" : "\") . 'zvzz' + endif + break + endif + endfor +endfunction + +" +function s:handler.onModeEnterPre() + let self.items = s:getJumpsLines() +endfunction + +" +function s:handler.onModeEnterPost() + call map(self.items, 's:makeItem(v:val, self.bufNrPrev)') + call filter(self.items, '!empty(v:val)') + call reverse(self.items) + call fuf#mapToSetSerialIndex(self.items, 1) + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/autoload/fuf/line.vim b/autoload/fuf/line.vim new file mode 100644 index 0000000..166c629 --- /dev/null +++ b/autoload/fuf/line.vim @@ -0,0 +1,131 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_line') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_line = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#line#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#line#getSwitchOrder() + return g:fuf_line_switchOrder +endfunction + +" +function fuf#line#renewCache() +endfunction + +" +function fuf#line#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#line#onInit() + call fuf#defineLaunchCommand('FufLine', s:MODE_NAME, '""') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') +let s:OPEN_TYPE_DELETE = -1 + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_line_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let items = filter(copy(self.items), 'v:val.word ==# a:word') + if empty(items) + return [] + endif + let lines = fuf#getFileLines(self.bufNrPrev) + return fuf#makePreviewLinesAround( + \ lines, [items[0].index - 1], a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#prejump(a:mode) + call filter(self.items, 'v:val.word ==# a:word') + if empty(self.items) + return + execute 'cc ' . self.items[0].index + endif + call cursor(self.items[0].index, 0) + normal! zvzz +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let tab = repeat(' ', getbufvar(self.bufNrPrev, '&tabstop')) + let self.items = getbufline(self.bufNrPrev, 1, '$') + let lnumFormat = '%' . len(string(len(self.items) + 1)) . 'd|' + for i in range(len(self.items)) + let self.items[i] = printf(lnumFormat, i + 1) + \ . substitute(self.items[i], "\t", tab, 'g') + endfor + call map(self.items, 'fuf#makeNonPathItem(v:val, "")') + call fuf#mapToSetSerialIndex(self.items, 1) + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 0)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/mrucmd.vim b/autoload/fuf/mrucmd.vim new file mode 100644 index 0000000..cb3ada3 --- /dev/null +++ b/autoload/fuf/mrucmd.vim @@ -0,0 +1,130 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_mrucmd') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_mrucmd = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#mrucmd#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#mrucmd#getSwitchOrder() + return g:fuf_mrucmd_switchOrder +endfunction + +" +function fuf#mrucmd#renewCache() +endfunction + +" +function fuf#mrucmd#requiresOnCommandPre() + return 1 +endfunction + +" +function fuf#mrucmd#onInit() + call fuf#defineLaunchCommand('FufMruCmd', s:MODE_NAME, '""') +endfunction + +" +function fuf#mrucmd#onCommandPre(cmd) + if getcmdtype() =~# '^[:/?]' + call s:updateInfo(a:cmd) + endif +endfunction + + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:updateInfo(cmd) + let info = fuf#loadInfoFile(s:MODE_NAME) + let info.data = fuf#updateMruList( + \ info.data, { 'word' : a:cmd, 'time' : localtime() }, + \ g:fuf_mrucmd_maxItem, g:fuf_mrucmd_exclude) + call fuf#saveInfoFile(s:MODE_NAME, info) +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_mrucmd_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return 0 +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return [] +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call s:updateInfo(a:word) + call histadd(a:word[0], a:word[1:]) + call feedkeys(a:word . "\", 'n') +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let self.items = copy(self.info.data) + call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))') + call fuf#mapToSetSerialIndex(self.items, 1) + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/mrufile.vim b/autoload/fuf/mrufile.vim new file mode 100644 index 0000000..9235f03 --- /dev/null +++ b/autoload/fuf/mrufile.vim @@ -0,0 +1,156 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_mrufile') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_mrufile = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#mrufile#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#mrufile#getSwitchOrder() + return g:fuf_mrufile_switchOrder +endfunction + +" +function fuf#mrufile#renewCache() + let s:cache = {} +endfunction + +" +function fuf#mrufile#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#mrufile#onInit() + call fuf#defineLaunchCommand('FufMruFile', s:MODE_NAME, '""') + augroup fuf#mrufile + autocmd! + autocmd BufEnter * call s:updateInfo() + autocmd BufWritePost * call s:updateInfo() + augroup END +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:updateInfo() + if !empty(&buftype) || !filereadable(expand('%')) + return + endif + let info = fuf#loadInfoFile(s:MODE_NAME) + let info.data = fuf#updateMruList( + \ info.data, { 'word' : expand('%:p'), 'time' : localtime() }, + \ g:fuf_mrufile_maxItem, g:fuf_mrufile_exclude) + call fuf#saveInfoFile(s:MODE_NAME, info) + call s:removeItemFromCache(expand('%:p')) +endfunction + +" +function s:removeItemFromCache(word) + for items in values(s:cache) + if exists('items[a:word]') + unlet items[a:word] + endif + endfor +endfunction + +" returns empty value if invalid item +function s:formatItemUsingCache(item) + if a:item.word !~ '\S' + return {} + endif + if !exists('s:cache[a:item.word]') + if filereadable(a:item.word) + let s:cache[a:item.word] = fuf#makePathItem( + \ fnamemodify(a:item.word, ':~'), strftime(g:fuf_timeFormat, a:item.time), 0) + else + let s:cache[a:item.word] = {} + endif + endif + return s:cache[a:item.word] +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_mrufile_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow) +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let self.items = copy(self.info.data) + let self.items = map(self.items, 's:formatItemUsingCache(v:val)') + let self.items = filter(self.items, '!empty(v:val) && bufnr("^" . v:val.word . "$") != self.bufNrPrev') + let self.items = fuf#mapToSetSerialIndex(self.items, 1) + let self.items = fuf#mapToSetAbbrWithSnippedWordAsPath(self.items) +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/quickfix.vim b/autoload/fuf/quickfix.vim new file mode 100644 index 0000000..1bb4b64 --- /dev/null +++ b/autoload/fuf/quickfix.vim @@ -0,0 +1,150 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_quickfix') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_quickfix = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#quickfix#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#quickfix#getSwitchOrder() + return g:fuf_quickfix_switchOrder +endfunction + +" +function fuf#quickfix#renewCache() +endfunction + +" +function fuf#quickfix#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#quickfix#onInit() + call fuf#defineLaunchCommand('FufQuickfix', s:MODE_NAME, '""') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getJumpsLines() + redir => result + :silent jumps + redir END + return split(result, "\n") +endfunction + +" +function s:parseJumpsLine(line) + return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$') +endfunction + +" +function s:makeItem(qfItem) + if !a:qfItem.valid + return {} + endif + let item = fuf#makeNonPathItem( + \ printf('%s|%d:%d|%s', bufname(a:qfItem.bufnr), a:qfItem.lnum, + \ a:qfItem.col, matchstr(a:qfItem.text, '\s*\zs.*\S')) + \ , '') + let item.bufnr = a:qfItem.bufnr + let item.lnum = a:qfItem.lnum + return item +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_quickfix_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + let items = filter(copy(self.items), 'v:val.word ==# a:word') + if empty(items) + return [] + endif + let lines = fuf#getFileLines(items[0].bufnr) + return fuf#makePreviewLinesAround( + \ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#prejump(a:mode) + call filter(self.items, 'v:val.word ==# a:word') + if !empty(self.items) + execute 'cc ' . self.items[0].index + endif +endfunction + +" +function s:handler.onModeEnterPre() +endfunction + +" +function s:handler.onModeEnterPost() + let self.items = getqflist() + call map(self.items, 's:makeItem(v:val)') + call fuf#mapToSetSerialIndex(self.items, 1) + call filter(self.items, 'exists("v:val.word")') + call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/autoload/fuf/tag.vim b/autoload/fuf/tag.vim new file mode 100644 index 0000000..bf566f0 --- /dev/null +++ b/autoload/fuf/tag.vim @@ -0,0 +1,182 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_tag') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_tag = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#tag#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#tag#getSwitchOrder() + return g:fuf_tag_switchOrder +endfunction + +" +function fuf#tag#renewCache() + let s:cache = {} +endfunction + +" +function fuf#tag#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#tag#onInit() + call fuf#defineLaunchCommand('FufTag' , s:MODE_NAME, '""') + call fuf#defineLaunchCommand('FufTagWithCursorWord', s:MODE_NAME, 'expand('''')') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getTagNames(tagFile) + let names = map(readfile(a:tagFile), 'matchstr(v:val, ''^[^!\t][^\t]*'')') + return filter(names, 'v:val =~# ''\S''') +endfunction + +" +function s:parseTagFiles(tagFiles) + if !empty(g:fuf_tag_cache_dir) + if !isdirectory(expand(g:fuf_tag_cache_dir)) + call mkdir(expand(g:fuf_tag_cache_dir), 'p') + endif + " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists. + let cacheFile = fnamemodify(g:fuf_tag_cache_dir, ':p') + \ . fuf#hash224(join(a:tagFiles, "\n")) + if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0 + return map(readfile(cacheFile), 'eval(v:val)') + endif + endif + let items = fuf#unique(fuf#concat(map(copy(a:tagFiles), 's:getTagNames(v:val)'))) + let items = map(items, 'fuf#makeNonPathItem(v:val, "")') + call fuf#mapToSetSerialIndex(items, 1) + let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)') + if !empty(g:fuf_tag_cache_dir) + call writefile(map(copy(items), 'string(v:val)'), cacheFile) + endif + return items +endfunction + +" +function s:enumTags(tagFiles) + if !len(a:tagFiles) + return [] + endif + let key = join(a:tagFiles, "\n") + if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time) + let s:cache[key] = { + \ 'time' : localtime(), + \ 'items' : s:parseTagFiles(a:tagFiles) + \ } + endif + return s:cache[key].items +endfunction + +" +function s:getMatchingIndex(lines, cmd) + if a:cmd !~# '\D' + return str2nr(a:cmd) + endif + let pattern = matchstr(a:cmd, '^\/\^\zs.*\ze\$\/$') + if empty(pattern) + return -1 + endif + for i in range(len(a:lines)) + if a:lines[i] ==# pattern + return i + endif + endfor + return -1 +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_tag_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 0 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath', + \ self.partialMatching) +endfunction + +" 'cmd' is '/^hoge hoge$/' or line number +function s:handler.makePreviewLines(word, count) + let tags = taglist('^' . a:word . '$') + if empty(tags) + return [] + endif + let i = a:count % len(tags) + let title = printf('(%d/%d) %s', i + 1, len(tags), tags[i].filename) + let lines = fuf#getFileLines(tags[i].filename) + let index = s:getMatchingIndex(lines, tags[i].cmd) + return [title] + fuf#makePreviewLinesAround( + \ lines, (index < 0 ? [] : [index]), 0, self.getPreviewHeight() - 1) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return s:enumTags(self.tagFiles) +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openTag(a:word, a:mode) +endfunction + +" +function s:handler.onModeEnterPre() + let self.tagFiles = fuf#getCurrentTagFiles() +endfunction + +" +function s:handler.onModeEnterPost() + let &l:tags = join(self.tagFiles, ',') +endfunction + +" +function s:handler.onModeLeavePost(opened) + let &l:tags = '' +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/fuf/taggedfile.vim b/autoload/fuf/taggedfile.vim new file mode 100644 index 0000000..30a79b1 --- /dev/null +++ b/autoload/fuf/taggedfile.vim @@ -0,0 +1,162 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_fuf_taggedfile') || v:version < 702 + finish +endif +let g:loaded_autoload_fuf_taggedfile = 1 + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS {{{1 + +" +function fuf#taggedfile#createHandler(base) + return a:base.concretize(copy(s:handler)) +endfunction + +" +function fuf#taggedfile#getSwitchOrder() + return g:fuf_taggedfile_switchOrder +endfunction + +" +function fuf#taggedfile#renewCache() + let s:cache = {} +endfunction + +" +function fuf#taggedfile#requiresOnCommandPre() + return 0 +endfunction + +" +function fuf#taggedfile#onInit() + call fuf#defineLaunchCommand('FufTaggedFile', s:MODE_NAME, '""') +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS/VARIABLES {{{1 + +let s:MODE_NAME = expand(':t:r') + +" +function s:getTaggedFileList(tagfile) + execute 'cd ' . fnamemodify(a:tagfile, ':h') + let result = map(readfile(a:tagfile), 'matchstr(v:val, ''^[^!\t][^\t]*\t\zs[^\t]\+'')') + call map(readfile(a:tagfile), 'fnamemodify(v:val, ":p")') + cd - + call map(readfile(a:tagfile), 'fnamemodify(v:val, ":~:.")') + return filter(result, 'v:val =~# ''[^/\\ ]$''') +endfunction + +" +function s:parseTagFiles(tagFiles) + if !empty(g:fuf_taggedfile_cache_dir) + if !isdirectory(expand(g:fuf_taggedfile_cache_dir)) + call mkdir(expand(g:fuf_taggedfile_cache_dir), 'p') + endif + " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists. + let cacheFile = fnamemodify(g:fuf_taggedfile_cache_dir, ':p') + \ . fuf#hash224(join(a:tagFiles, "\n")) + if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0 + return map(readfile(cacheFile), 'eval(v:val)') + endif + endif + let items = fuf#unique(fuf#concat(map(copy(a:tagFiles), 's:getTaggedFileList(v:val)'))) + call map(items, 'fuf#makePathItem(v:val, "", 0)') + call fuf#mapToSetSerialIndex(items, 1) + call fuf#mapToSetAbbrWithSnippedWordAsPath(items) + if !empty(g:fuf_taggedfile_cache_dir) + call writefile(map(copy(items), 'string(v:val)'), cacheFile) + endif + return items +endfunction + +" +function s:enumTaggedFiles(tagFiles) + if !len(a:tagFiles) + return [] + endif + let key = join([getcwd()] + a:tagFiles, "\n") + if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time) + let s:cache[key] = { + \ 'time' : localtime(), + \ 'items' : s:parseTagFiles(a:tagFiles) + \ } + endif + return s:cache[key].items +endfunction + +" }}}1 +"============================================================================= +" s:handler {{{1 + +let s:handler = {} + +" +function s:handler.getModeName() + return s:MODE_NAME +endfunction + +" +function s:handler.getPrompt() + return fuf#formatPrompt(g:fuf_taggedfile_prompt, self.partialMatching) +endfunction + +" +function s:handler.getPreviewHeight() + return g:fuf_previewHeight +endfunction + +" +function s:handler.targetsPath() + return 1 +endfunction + +" +function s:handler.makePatternSet(patternBase) + return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath', + \ self.partialMatching) +endfunction + +" +function s:handler.makePreviewLines(word, count) + return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight()) +endfunction + +" +function s:handler.getCompleteItems(patternPrimary) + return self.items +endfunction + +" +function s:handler.onOpen(word, mode) + call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow) +endfunction + +" +function s:handler.onModeEnterPre() + let self.tagFiles = fuf#getCurrentTagFiles() +endfunction + +" +function s:handler.onModeEnterPost() + " NOTE: Don't do this in onModeEnterPre() + " because that should return in a short time. + let self.items = + \ filter(copy(s:enumTaggedFiles(self.tagFiles)), + \ 'bufnr("^" . v:val.word . "$") != self.bufNrPrev') +endfunction + +" +function s:handler.onModeLeavePost(opened) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/autoload/getscript.vim b/autoload/getscript.vim new file mode 100644 index 0000000..44d5668 --- /dev/null +++ b/autoload/getscript.vim @@ -0,0 +1,591 @@ +" --------------------------------------------------------------------- +" getscript.vim +" Author: Charles E. Campbell, Jr. +" Date: Jan 08, 2008 +" Version: 29 +" Installing: :help glvs-install +" Usage: :help glvs +" +" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim +"redraw!|call inputsave()|call input("Press to continue")|call inputrestore() +" --------------------------------------------------------------------- +" Initialization: {{{1 +" if you're sourcing this file, surely you can't be +" expecting vim to be in its vi-compatible mode! +if &cp + echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)" + finish +endif +let s:keepcpo = &cpo +set cpo&vim +"DechoTabOn + +if exists("g:loaded_getscript") + finish +endif +let g:loaded_getscript= "v29" + +" --------------------------- +" Global Variables: {{{1 +" --------------------------- +" Cygwin Detection ------- {{{2 +if !exists("g:getscript_cygwin") + if has("win32") || has("win95") || has("win64") || has("win16") + if &shell =~ '\%(\\|\\)\%(\.exe\)\=$' + let g:getscript_cygwin= 1 + else + let g:getscript_cygwin= 0 + endif + else + let g:getscript_cygwin= 0 + endif +endif +" shell quoting character {{{2 +if exists("g:netrw_shq") && !exists("g:getscript_shq") + let g:getscript_shq= g:netrw_shq +elseif !exists("g:getscript_shq") + if exists("&shq") && &shq != "" + let g:getscript_shq= &shq + elseif exists("&sxq") && &sxq != "" + let g:getscript_shq= &sxq + elseif has("win32") || has("win95") || has("win64") || has("win16") + if g:getscript_cygwin + let g:getscript_shq= "'" + else + let g:getscript_shq= '"' + endif + else + let g:getscript_shq= "'" + endif +" call Decho("g:getscript_shq<".g:getscript_shq.">") +endif + +" wget vs curl {{{2 +if !exists("g:GetLatestVimScripts_wget") + if executable("wget") + let g:GetLatestVimScripts_wget= "wget" + elseif executable("curl") + let g:GetLatestVimScripts_wget= "curl" + else + let g:GetLatestVimScripts_wget = 'echo "GetLatestVimScripts needs wget or curl"' + let g:GetLatestVimScripts_options = "" + endif +endif + +" options that wget and curl require: +if !exists("g:GetLatestVimScripts_options") + if g:GetLatestVimScripts_wget == "wget" + let g:GetLatestVimScripts_options= "-q -O" + elseif g:GetLatestVimScripts_wget == "curl" + let g:GetLatestVimScripts_options= "-s -O" + else + let g:GetLatestVimScripts_options= "" + endif +endif + +" by default, allow autoinstall lines to work +if !exists("g:GetLatestVimScripts_allowautoinstall") + let g:GetLatestVimScripts_allowautoinstall= 1 +endif + +"" For debugging: +"let g:GetLatestVimScripts_wget = "echo" +"let g:GetLatestVimScripts_options = "options" + +" --------------------------------------------------------------------- +" Check If AutoInstall Capable: {{{1 +let s:autoinstall= "" +if g:GetLatestVimScripts_allowautoinstall + + if (has("win32") || has("gui_win32") || has("gui_win32s") || has("win16") || has("win64") || has("win32unix") || has("win95")) && &shell != "bash" + " windows (but not cygwin/bash) + let s:dotvim= "vimfiles" + if !exists("g:GetLatestVimScripts_mv") + let g:GetLatestVimScripts_mv= "ren" + endif + + else + " unix + let s:dotvim= ".vim" + if !exists("g:GetLatestVimScripts_mv") + let g:GetLatestVimScripts_mv= "mv" + endif + endif + + if exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim) + let s:autoinstall= $HOME."/".s:dotvim + endif +" call Decho("s:autoinstall<".s:autoinstall.">") +"else "Decho +" call Decho("g:GetLatestVimScripts_allowautoinstall=".g:GetLatestVimScripts_allowautoinstall.": :AutoInstall: disabled") +endif + +" --------------------------------------------------------------------- +" Public Interface: {{{1 +com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts() +com! -nargs=0 GetScript call getscript#GetLatestVimScripts() +silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts() + +" --------------------------------------------------------------------- +" GetOneScript: (Get Latest Vim Script) this function operates {{{1 +" on the current line, interpreting two numbers and text as +" ScriptID, SourceID, and Filename. +" It downloads any scripts that have newer versions from vim.sf.net. +fun! s:GetOneScript(...) +" call Dfunc("GetOneScript()") + + " set options to allow progress to be shown on screen + let rega= @a + let t_ti= &t_ti + let t_te= &t_te + let rs = &rs + set t_ti= t_te= nors + + " put current line on top-of-screen and interpret it into + " a script identifer : used to obtain webpage + " source identifier : used to identify current version + " and an associated comment: used to report on what's being considered + if a:0 >= 3 + let scriptid = a:1 + let srcid = a:2 + let fname = a:3 + let cmmnt = "" +" call Decho("scriptid<".scriptid.">") +" call Decho("srcid <".srcid.">") +" call Decho("fname <".fname.">") + else + let curline = getline(".") + if curline =~ '^\s*#' + let @a= rega +" call Dret("GetOneScript : skipping a pure comment line") + return + endif + let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(.\{-}\)\(\s*#.*\)\=$' + try + let scriptid = substitute(curline,parsepat,'\1','e') + catch /^Vim\%((\a\+)\)\=:E486/ + let scriptid= 0 + endtry + try + let srcid = substitute(curline,parsepat,'\2','e') + catch /^Vim\%((\a\+)\)\=:E486/ + let srcid= 0 + endtry + try + let fname= substitute(curline,parsepat,'\3','e') + catch /^Vim\%((\a\+)\)\=:E486/ + let fname= "" + endtry + try + let cmmnt= substitute(curline,parsepat,'\4','e') + catch /^Vim\%((\a\+)\)\=:E486/ + let cmmnt= "" + endtry +" call Decho("curline <".curline.">") +" call Decho("parsepat<".parsepat.">") +" call Decho("scriptid<".scriptid.">") +" call Decho("srcid <".srcid.">") +" call Decho("fname <".fname.">") + endif + + if scriptid == 0 || srcid == 0 + " When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname + let @a= rega +" call Dret("GetOneScript : skipping a scriptid==srcid==0 line") + return + endif + + let doautoinstall= 0 + if fname =~ ":AutoInstall:" +" call Decho("case AutoInstall: fname<".fname.">") + let aicmmnt= substitute(fname,'\s\+:AutoInstall:\s\+',' ','') +" call Decho("aicmmnt<".aicmmnt."> s:autoinstall=".s:autoinstall) + if s:autoinstall != "" + let doautoinstall = g:GetLatestVimScripts_allowautoinstall + endif + else + let aicmmnt= fname + endif +" call Decho("aicmmnt<".aicmmnt.">: doautoinstall=".doautoinstall) + + exe "norm z\" + redraw! +" call Decho('considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid) + echomsg 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid + + " grab a copy of the plugin's vim.sf.net webpage + let scriptaddr = 'http://vim.sf.net/script.php?script_id='.scriptid + let tmpfile = tempname() + let v:errmsg = "" + + " make up to three tries at downloading the description + let itry= 1 + while itry <= 3 +" call Decho("try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr) + if has("win32") || has("win16") || has("win95") +" call Decho("new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq.' '.g:getscript_shq.scriptaddr.g:getscript_shq."|q!") + new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq.' '.g:getscript_shq.scriptaddr.g:getscript_shq|q! + else +" call Decho("exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq." ".g:getscript_shq.scriptaddr.g:getscript_shq) + exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq." ".g:getscript_shq.scriptaddr.g:getscript_shq + endif + if itry == 1 + exe "silent vsplit ".tmpfile + else + silent! e % + endif + + " find the latest source-id in the plugin's webpage + silent! 1 + let findpkg= search('Click on the package to download','W') + if findpkg > 0 + break + endif + let itry= itry + 1 + endwhile +" call Decho(" --- end downloading tries while loop --- itry=".itry) + + " testing: did finding "Click on the package..." fail? + if findpkg == 0 || itry >= 4 + silent q! + call delete(tmpfile) + " restore options + let &t_ti = t_ti + let &t_te = t_te + let &rs = rs + let s:downerrors = s:downerrors + 1 +" call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">") + echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">" +" call Dret("GetOneScript : srch for /Click on the package/ failed") + let @a= rega + return + endif +" call Decho('found "Click on the package to download"') + + let findsrcid= search('src_id=','W') + if findsrcid == 0 + silent q! + call delete(tmpfile) + " restore options + let &t_ti = t_ti + let &t_te = t_te + let &rs = rs + let s:downerrors = s:downerrors + 1 +" call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">") + echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">" + let @a= rega +" call Dret("GetOneScript : srch for /src_id/ failed") + return + endif +" call Decho('found "src_id=" in description page') + + let srcidpat = '^\s*\([^<]\+\)<.*$' + let latestsrcid= substitute(getline("."),srcidpat,'\1','') + let sname = substitute(getline("."),srcidpat,'\2','') " script name actually downloaded +" call Decho("srcidpat<".srcidpat."> latestsrcid<".latestsrcid."> sname<".sname.">") + silent q! + call delete(tmpfile) + + " convert the strings-of-numbers into numbers + let srcid = srcid + 0 + let latestsrcid = latestsrcid + 0 +" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">") + + " has the plugin's most-recent srcid increased, which indicates + " that it has been updated + if latestsrcid > srcid +" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">") + + let s:downloads= s:downloads + 1 + if sname == bufname("%") + " GetLatestVimScript has to be careful about downloading itself + let sname= "NEW_".sname + endif + + " the plugin has been updated since we last obtained it, so download a new copy +" call Decho("...downloading new <".sname.">") + echomsg "...downloading new <".sname.">" + if has("win32") || has("win16") || has("win95") +" call Decho("new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq."|q") + new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq|q + else +" call Decho("silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq) + exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq + endif + + " AutoInstall: only if doautoinstall has been requested by the plugin itself + if doautoinstall +" call Decho("attempting to do autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname)) + if filereadable(sname) +" call Decho("silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.s:autoinstall.g:getscript_shq) + exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.s:autoinstall.g:getscript_shq + let curdir = escape(substitute(getcwd(),'\','/','ge'),"|[]*'\" #") + let installdir= curdir."/Installed" + if !isdirectory(installdir) + call mkdir(installdir) + endif +" call Decho("exe cd ".s:autoinstall) + exe "cd ".escape(s:autoinstall,' ') + + " decompress + if sname =~ '\.bz2$' +" call Decho("decompress: attempt to bunzip2 ".sname) + exe "silent !bunzip2 ".g:getscript_shq.sname.g:getscript_shq + let sname= substitute(sname,'\.bz2$','','') +" call Decho("decompress: new sname<".sname."> after bunzip2") + elseif sname =~ '\.gz$' +" call Decho("decompress: attempt to gunzip ".sname) + exe "silent !gunzip ".g:getscript_shq.sname.g:getscript_shq + let sname= substitute(sname,'\.gz$','','') +" call Decho("decompress: new sname<".sname."> after gunzip") + endif + + " distribute archive(.zip, .tar, .vba) contents + if sname =~ '\.zip$' +" call Decho("dearchive: attempt to unzip ".sname) + exe "silent !unzip -o ".g:getscript_shq.sname.g:getscript_shq + elseif sname =~ '\.tar$' +" call Decho("dearchive: attempt to untar ".sname) + exe "silent !tar -xvf ".g:getscript_shq.sname.g:getscript_shq + elseif sname =~ '\.vba$' +" call Decho("dearchive: attempt to handle a vimball: ".sname) + silent 1split + exe "silent e ".escape(sname,' ') + silent so % + silent q + endif + + if sname =~ '.vim$' +" call Decho("dearchive: attempt to simply move ".sname." to plugin") + exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." plugin" + else +" call Decho("dearchive: move <".sname."> to installdir<".installdir.">") + exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".installdir + endif + + " helptags step + let docdir= substitute(&rtp,',.*','','e')."/doc" +" call Decho("helptags: docdir<".docdir.">") + exe "helptags ".docdir + exe "cd ".curdir + endif + if fname !~ ':AutoInstall:' + let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt + else + let modline=scriptid." ".latestsrcid." ".fname.cmmnt + endif + else + let modline=scriptid." ".latestsrcid." ".fname.cmmnt + endif + + " update the data in the file + call setline(line("."),modline) +" call Decho("update data in ".expand("%")."#".line(".").": modline<".modline.">") +" else " Decho +" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."], no need to update") + endif + + " restore options + let &t_ti = t_ti + let &t_te = t_te + let &rs = rs + let @a = rega + +" call Dret("GetOneScript") +endfun + +" --------------------------------------------------------------------- +" GetLatestVimScripts: this function gets the latest versions of {{{1 +" scripts based on the list in +" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat +fun! getscript#GetLatestVimScripts() +" call Dfunc("GetLatestVimScripts() autoinstall<".s:autoinstall.">") + +" insure that wget is executable + if executable(g:GetLatestVimScripts_wget) != 1 + echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system" +" call Dret("GetLatestVimScripts : wget not executable/availble") + return + endif + + " Find the .../GetLatest subdirectory under the runtimepath + for datadir in split(&rtp,',') + [''] + if isdirectory(datadir."/GetLatest") +" call Decho("found directory<".datadir.">") + let datadir= datadir . "/GetLatest" + break + endif + if filereadable(datadir."GetLatestVimScripts.dat") +" call Decho("found ".datadir."/GetLatestVimScripts.dat") + break + endif + endfor + + " Sanity checks: readability and writability + if datadir == "" + echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install' +" call Dret("GetLatestVimScripts : unable to find a GetLatest subdirectory") + return + endif + + if filewritable(datadir) != 2 + echoerr "(getLatestVimScripts) Your ".datadir." isn't writable" +" call Dret("GetLatestVimScripts : non-writable directory<".datadir.">") + return + endif + let datafile= datadir."/GetLatestVimScripts.dat" + if !filereadable(datafile) + echoerr "Your data file<".datafile."> isn't readable" +" call Dret("GetLatestVimScripts : non-readable datafile<".datafile.">") + return + endif + if !filewritable(datafile) + echoerr "Your data file<".datafile."> isn't writable" +" call Dret("GetLatestVimScripts : non-writable datafile<".datafile.">") + return + endif +" call Decho("datadir <".datadir.">") +" call Decho("datafile <".datafile.">") + + " don't let any events interfere (like winmanager's, taglist's, etc) + let eikeep= &ei + set ei=all + + " record current directory, change to datadir, open split window with + " datafile + let origdir= getcwd() + exe "cd ".escape(substitute(datadir,'\','/','ge'),"|[]*'\" #") + split + exe "e ".escape(substitute(datafile,'\','/','ge'),"|[]*'\" #") + res 1000 + let s:downloads = 0 + let s:downerrors= 0 + + " Check on dependencies mentioned in plugins +" call Decho(" ") +" call Decho("searching plugins for GetLatestVimScripts dependencies") + let lastline = line("$") +" call Decho("lastline#".lastline) + let plugins = split(globpath(&rtp,"plugin/*.vim"),'\n') + let foundscript = 0 + let firstdir= "" + + for plugin in plugins + + " don't process plugins in system directories + if firstdir == "" + let firstdir= substitute(plugin,'[/\\][^/\\]\+$','','') +" call Decho("setting firstdir<".firstdir.">") + else + let curdir= substitute(plugin,'[/\\][^/\\]\+$','','') +" call Decho("curdir<".curdir.">") + if curdir != firstdir +" call Decho("skipping subsequent plugins: curdir<".curdir."> != firstdir<".firstdir.">") + break + endif + endif + + " read plugin in + $ +" call Decho(" ") +" call Decho(".dependency checking<".plugin."> line$=".line("$")) + exe "silent r ".escape(plugin,"[]#*$%'\" ?`!&();<>\\") + + while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0 + let newscript= substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e') + let llp1 = lastline+1 +" call Decho("..newscript<".newscript.">") + + " don't process ""GetLatestVimScripts lines -- those that have been doubly-commented out + if newscript !~ '^"' + " found a "GetLatestVimScripts: # #" line in the script; check if its already in the datafile + let curline = line(".") + let noai_script = substitute(newscript,'\s*:AutoInstall:\s*','','e') + exe llp1 + let srchline = search('\<'.noai_script.'\>','bW') +" call Decho("..noai_script<".noai_script."> srch=".srchline."curline#".line(".")." lastline#".lastline) + + if srchline == 0 + " found a new script to permanently include in the datafile + let keep_rega = @a + let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','') + exe lastline."put a" + echomsg "Appending <".@a."> to ".datafile." for ".newscript +" call Decho("..APPEND (".noai_script.")<".@a."> to GetLatestVimScripts.dat") + let @a = keep_rega + let lastline = llp1 + let curline = curline + 1 + let foundscript = foundscript + 1 +" else " Decho +" call Decho("..found <".noai_script."> (already in datafile at line#".srchline.")") + endif + + let curline = curline + 1 + exe curline + endif + endwhile + + let llp1= lastline + 1 +" call Decho(".deleting lines: ".llp1.",$d") + exe "silent! ".llp1.",$d" + endfor +" call Decho("--- end dependency checking loop --- foundscript=".foundscript) +" call Decho(" ") + + if foundscript == 0 + setlocal nomod + endif + + " Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat +" call Decho("begin: checking out-of-date scripts using datafile<".datafile.">") + setlocal lz + 1 +" /^-----/,$g/^\s*\d/call Decho(getline(".")) + 1 + /^-----/,$g/^\s*\d/call s:GetOneScript() +" call Decho("--- end out-of-date checking --- ") + + " Final report (an echomsg) + try + silent! ?^-------? + catch /^Vim\%((\a\+)\)\=:E114/ +" call Dret("GetLatestVimScripts : nothing done!") + return + endtry + exe "norm! kz\" + redraw! + let s:msg = "" + if s:downloads == 1 + let s:msg = "Downloaded one updated script to <".datadir.">" + elseif s:downloads == 2 + let s:msg= "Downloaded two updated scripts to <".datadir.">" + elseif s:downloads > 1 + let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">" + else + let s:msg= "Everything was already current" + endif + if s:downerrors > 0 + let s:msg= s:msg." (".s:downerrors." downloading errors)" + endif + echomsg s:msg + " save the file + if &mod + silent! w! + endif + q + + " restore events and current directory + exe "cd ".escape(substitute(origdir,'\','/','ge'),"|[]*'\" #") + let &ei= eikeep + setlocal nolz +" call Dret("GetLatestVimScripts : did ".s:downloads." downloads") +endfun + +" --------------------------------------------------------------------- +" Restore Options: {{{1 +let &cpo= s:keepcpo +unlet s:keepcpo + +" --------------------------------------------------------------------- +" Modelines: {{{1 +" vim: ts=8 sts=2 fdm=marker nowrap diff --git a/autoload/mark.vim b/autoload/mark.vim new file mode 100644 index 0000000..1c7ffe7 --- /dev/null +++ b/autoload/mark.vim @@ -0,0 +1,471 @@ +" Script Name: mark.vim +" Description: Highlight several words in different colors simultaneously. +" +" Copyright: (C) 2005-2008 by Yuheng Xie +" (C) 2008-2010 by Ingo Karkat +" The VIM LICENSE applies to this script; see ':help copyright'. +" +" Maintainer: Ingo Karkat +" +" Dependencies: +" - SearchSpecial.vim autoload script (optional, for improved search messages). +" +" Version: 2.3.3 +" Changes: +" 19-Feb-2010, Andy Wokula +" - BUG: Clearing of an accidental zero-width match (e.g. via :Mark \zs) results +" in endless loop. Thanks to Andy Wokula for the patch. +" +" 17-Nov-2009, Ingo Karkat + Andy Wokula +" - BUG: Creation of literal pattern via '\V' in {Visual}m mapping +" collided with individual escaping done in m mapping so that an +" escaped '\*' would be interpreted as a multi item when both modes are used +" for marking. Replaced \V with s:EscapeText() to be consistent. Replaced the +" (overly) generic mark#GetVisualSelectionEscaped() with +" mark#GetVisualSelectionAsRegexp() and +" mark#GetVisualSelectionAsLiteralPattern(). Thanks to Andy Wokula for the +" patch. +" +" 06-Jul-2009, Ingo Karkat +" - Re-wrote s:AnyMark() in functional programming style. +" - Now resetting 'smartcase' before the search, this setting should not be +" considered for *-command-alike searches and cannot be supported because all +" mark patterns are concatenated into one large regexp, anyway. +" +" 04-Jul-2009, Ingo Karkat +" - Re-wrote s:Search() to handle v:count: +" - Obsoleted s:current_mark_position; mark#CurrentMark() now returns both the +" mark text and start position. +" - s:Search() now checks for a jump to the current mark during a backward +" search; this eliminates a lot of logic at its calling sites. +" - Reverted negative logic at calling sites; using empty() instead of != "". +" - Now passing a:isBackward instead of optional flags into s:Search() and +" around its callers. +" - ':normal! zv' moved from callers into s:Search(). +" - Removed delegation to SearchSpecial#ErrorMessage(), because the fallback +" implementation is perfectly fine and the SearchSpecial routine changed its +" output format into something unsuitable anyway. +" - Using descriptive text instead of "@" (and appropriate highlighting) when +" querying for the pattern to mark. +" +" 02-Jul-2009, Ingo Karkat +" - Split off functions into autoload script. + +"- functions ------------------------------------------------------------------ +function! s:EscapeText( text ) + return substitute( escape(a:text, '\' . '^$.*[~'), "\n", '\\n', 'ge' ) +endfunction +" Mark the current word, like the built-in star command. +" If the cursor is on an existing mark, remove it. +function! mark#MarkCurrentWord() + let l:regexp = mark#CurrentMark()[0] + if empty(l:regexp) + let l:cword = expand("") + + " The star command only creates a \ search pattern if the + " actually only consists of keyword characters. + if l:cword =~# '^\k\+$' + let l:regexp = '\<' . s:EscapeText(l:cword) . '\>' + elseif l:cword != '' + let l:regexp = s:EscapeText(l:cword) + endif + endif + + if ! empty(l:regexp) + call mark#DoMark(l:regexp) + endif +endfunction + +function! s:GetVisualSelection() + let save_a = @a + silent normal! gv"ay + let res = @a + let @a = save_a + return res +endfunction +function! mark#GetVisualSelectionAsLiteralPattern() + return s:EscapeText(s:GetVisualSelection()) +endfunction +function! mark#GetVisualSelectionAsRegexp() + return substitute(s:GetVisualSelection(), '\n', '', 'g') +endfunction + +" Manually input a regular expression. +function! mark#MarkRegex( regexpPreset ) + call inputsave() + echohl Question + let l:regexp = input('Input pattern to mark: ', a:regexpPreset) + echohl None + call inputrestore() + if ! empty(l:regexp) + call mark#DoMark(l:regexp) + endif +endfunction + +function! s:Cycle( ... ) + let l:currentCycle = g:mwCycle + let l:newCycle = (a:0 ? a:1 : g:mwCycle) + 1 + let g:mwCycle = (l:newCycle < g:mwCycleMax ? l:newCycle : 0) + return l:currentCycle +endfunction + +" Set / clear matches in the current window. +function! s:MarkMatch( indices, expr ) + for l:index in a:indices + if w:mwMatch[l:index] > 0 + silent! call matchdelete(w:mwMatch[l:index]) + let w:mwMatch[l:index] = 0 + endif + endfor + + if ! empty(a:expr) + " Make the match according to the 'ignorecase' setting, like the star command. + " (But honor an explicit case-sensitive regexp via the /\C/ atom.) + let l:expr = ((&ignorecase && a:expr !~# '\\\@= 0 + call histadd("/", regexp) + endif + if stridx(g:mwHistAdd, "@") >= 0 + call histadd("@", regexp) + endif + + " choose an unused mark group + let i = 0 + while i < g:mwCycleMax + if empty(g:mwWord[i]) + let g:mwWord[i] = regexp + call s:Cycle(i) + call s:MarkScope([i], regexp) + return + endif + let i += 1 + endwhile + + " choose a mark group by cycle + let i = s:Cycle() + if g:mwLastSearched == g:mwWord[i] + let g:mwLastSearched = '' + endif + let g:mwWord[i] = regexp + call s:MarkScope([i], regexp) +endfunction +" Initialize mark colors in a (new) window. +function! mark#UpdateMark() + if ! exists('w:mwMatch') + let w:mwMatch = repeat([0], g:mwCycleMax) + endif + + let i = 0 + while i < g:mwCycleMax + if empty(g:mwWord[i]) + call s:MarkMatch([i], '') + else + call s:MarkMatch([i], g:mwWord[i]) + endif + let i += 1 + endwhile +endfunction + +" Return [mark text, mark start position] of the mark under the cursor (or +" ['', []] if there is no mark); multi-lines marks not supported. +function! mark#CurrentMark() + let line = getline(".") + let i = 0 + while i < g:mwCycleMax + if !empty(g:mwWord[i]) + " Note: col() is 1-based, all other indexes zero-based! + let start = 0 + while start >= 0 && start < strlen(line) && start < col(".") + let b = match(line, g:mwWord[i], start) + let e = matchend(line, g:mwWord[i], start) + if b < col(".") && col(".") <= e + return [g:mwWord[i], [line("."), (b + 1)]] + endif + if b == e + break + endif + let start = e + endwhile + endif + let i += 1 + endwhile + return ['', []] +endfunction + +" Search current mark. +function! mark#SearchCurrentMark( isBackward ) + let [l:markText, l:markPosition] = mark#CurrentMark() + if empty(l:markText) + if empty(g:mwLastSearched) + call mark#SearchAnyMark(a:isBackward) + let g:mwLastSearched = mark#CurrentMark()[0] + else + call s:Search(g:mwLastSearched, a:isBackward, [], 'same-mark') + endif + else + call s:Search(l:markText, a:isBackward, l:markPosition, (l:markText ==# g:mwLastSearched ? 'same-mark' : 'new-mark')) + let g:mwLastSearched = l:markText + endif +endfunction + +silent! call SearchSpecial#DoesNotExist() " Execute a function to force autoload. +if exists('*SearchSpecial#WrapMessage') + function! s:WrapMessage( searchType, searchPattern, isBackward ) + redraw + call SearchSpecial#WrapMessage(a:searchType, a:searchPattern, a:isBackward) + endfunction + function! s:EchoSearchPattern( searchType, searchPattern, isBackward ) + call SearchSpecial#EchoSearchPattern(a:searchType, a:searchPattern, a:isBackward) + endfunction +else + function! s:Trim( message ) + " Limit length to avoid "Hit ENTER" prompt. + return strpart(a:message, 0, (&columns / 2)) . (len(a:message) > (&columns / 2) ? "..." : "") + endfunction + function! s:WrapMessage( searchType, searchPattern, isBackward ) + redraw + let v:warningmsg = printf('%s search hit %s, continuing at %s', a:searchType, (a:isBackward ? 'TOP' : 'BOTTOM'), (a:isBackward ? 'BOTTOM' : 'TOP')) + echohl WarningMsg + echo s:Trim(v:warningmsg) + echohl None + endfunction + function! s:EchoSearchPattern( searchType, searchPattern, isBackward ) + let l:message = (a:isBackward ? '?' : '/') . a:searchPattern + echohl SearchSpecialSearchType + echo a:searchType + echohl None + echon s:Trim(l:message) + endfunction +endif +function! s:ErrorMessage( searchType, searchPattern, isBackward ) + if &wrapscan + let v:errmsg = a:searchType . ' not found: ' . a:searchPattern + else + let v:errmsg = printf('%s search hit %s without match for: %s', a:searchType, (a:isBackward ? 'TOP' : 'BOTTOM'), a:searchPattern) + endif + echohl ErrorMsg + echomsg v:errmsg + echohl None +endfunction + +" Wrapper around search() with additonal search and error messages and "wrapscan" warning. +function! s:Search( pattern, isBackward, currentMarkPosition, searchType ) + let l:save_view = winsaveview() + + " searchpos() obeys the 'smartcase' setting; however, this setting doesn't + " make sense for the mark search, because all patterns for the marks are + " concatenated as branches in one large regexp, and because patterns that + " result from the *-command-alike mappings should not obey 'smartcase' (like + " the * command itself), anyway. If the :Mark command wants to support + " 'smartcase', it'd have to emulate that into the regular expression. + let l:save_smartcase = &smartcase + set nosmartcase + + let l:count = v:count1 + let [l:startLine, l:startCol] = [line('.'), col('.')] + let l:isWrapped = 0 + let l:isMatch = 0 + let l:line = 0 + while l:count > 0 + " Search for next match, 'wrapscan' applies. + let [l:line, l:col] = searchpos( a:pattern, (a:isBackward ? 'b' : '') ) + +"****D echomsg '****' a:isBackward string([l:line, l:col]) string(a:currentMarkPosition) l:count + if a:isBackward && l:line > 0 && [l:line, l:col] == a:currentMarkPosition && l:count == v:count1 + " On a search in backward direction, the first match is the start of the + " current mark (if the cursor was positioned on the current mark text, and + " not at the start of the mark text). + " In contrast to the normal search, this is not considered the first + " match. The mark text is one entity; if the cursor is positioned anywhere + " inside the mark text, the mark text is considered the current mark. The + " built-in '*' and '#' commands behave in the same way; the entire + " text is considered the current match, and jumps move outside that text. + " In normal search, the cursor can be positioned anywhere (via offsets) + " around the search, and only that single cursor position is considered + " the current match. + " Thus, the search is retried without a decrease of l:count, but only if + " this was the first match; repeat visits during wrapping around count as + " a regular match. The search also must not be retried when this is the + " first match, but we've been here before (i.e. l:isMatch is set): This + " means that there is only the current mark in the buffer, and we must + " break out of the loop and indicate that no other mark was found. + if l:isMatch + let l:line = 0 + break + endif + + " The l:isMatch flag is set so if the final mark cannot be reached, the + " original cursor position is restored. This flag also allows us to detect + " whether we've been here before, which is checked above. + let l:isMatch = 1 + elseif l:line > 0 + let l:isMatch = 1 + let l:count -= 1 + + " Note: No need to check 'wrapscan'; the wrapping can only occur if + " 'wrapscan' is actually on. + if ! a:isBackward && (l:startLine > l:line || l:startLine == l:line && l:startCol >= l:col) + let l:isWrapped = 1 + elseif a:isBackward && (l:startLine < l:line || l:startLine == l:line && l:startCol <= l:col) + let l:isWrapped = 1 + endif + else + break + endif + endwhile + let &smartcase = l:save_smartcase + + " We're not stuck when the search wrapped around and landed on the current + " mark; that's why we exclude a possible wrap-around via v:count1 == 1. + let l:isStuckAtCurrentMark = ([l:line, l:col] == a:currentMarkPosition && v:count1 == 1) + if l:line > 0 && ! l:isStuckAtCurrentMark + normal! zv + + if l:isWrapped + call s:WrapMessage(a:searchType, a:pattern, a:isBackward) + else + call s:EchoSearchPattern(a:searchType, a:pattern, a:isBackward) + endif + return 1 + else + if l:isMatch + " The view has been changed by moving through matches until the end / + " start of file, when 'nowrapscan' forced a stop of searching before the + " l:count'th match was found. + " Restore the view to the state before the search. + call winrestview(l:save_view) + endif + call s:ErrorMessage(a:searchType, a:pattern, a:isBackward) + return 0 + endif +endfunction + +" Combine all marks into one regexp. +function! s:AnyMark() + return join(filter(copy(g:mwWord), '! empty(v:val)'), '\|') +endfunction + +" Search any mark. +function! mark#SearchAnyMark( isBackward ) + let l:markPosition = mark#CurrentMark()[1] + let l:markText = s:AnyMark() + call s:Search(l:markText, a:isBackward, l:markPosition, 'any-mark') + let g:mwLastSearched = "" +endfunction + +" Search last searched mark. +function! mark#SearchNext( isBackward ) + let l:markText = mark#CurrentMark()[0] + if empty(l:markText) + return 0 + else + if empty(g:mwLastSearched) + call mark#SearchAnyMark(a:isBackward) + else + call mark#SearchCurrentMark(a:isBackward) + endif + return 1 + endif +endfunction + +"- initializations ------------------------------------------------------------ +augroup Mark + autocmd! + autocmd VimEnter * if ! exists('w:mwMatch') | call mark#UpdateMark() | endif + autocmd WinEnter * if ! exists('w:mwMatch') | call mark#UpdateMark() | endif + autocmd TabEnter * call mark#UpdateScope() +augroup END + +" Define global variables and initialize current scope. +function! s:InitMarkVariables() + if !exists("g:mwHistAdd") + let g:mwHistAdd = "/@" + endif + if !exists("g:mwCycleMax") + let i = 1 + while hlexists("MarkWord" . i) + let i = i + 1 + endwhile + let g:mwCycleMax = i - 1 + endif + if !exists("g:mwCycle") + let g:mwCycle = 0 + endif + if !exists("g:mwWord") + let g:mwWord = repeat([''], g:mwCycleMax) + endif + if !exists("g:mwLastSearched") + let g:mwLastSearched = "" + endif +endfunction +call s:InitMarkVariables() +call mark#UpdateScope() + +" vim: ts=2 sw=2 diff --git a/autoload/snipMate.vim b/autoload/snipMate.vim new file mode 100644 index 0000000..dcd28f6 --- /dev/null +++ b/autoload/snipMate.vim @@ -0,0 +1,433 @@ +fun! Filename(...) + let filename = expand('%:t:r') + if filename == '' | return a:0 == 2 ? a:2 : '' | endif + return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') +endf + +fun s:RemoveSnippet() + unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen + \ s:lastBuf s:oldWord + if exists('s:update') + unl s:startCol s:origWordLen s:update + if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif + endif + aug! snipMateAutocmds +endf + +fun snipMate#expandSnip(snip, col) + let lnum = line('.') | let col = a:col + + let snippet = s:ProcessSnippet(a:snip) + " Avoid error if eval evaluates to nothing + if snippet == '' | return '' | endif + + " Expand snippet onto current position with the tab stops removed + let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1) + + let line = getline(lnum) + let afterCursor = strpart(line, col - 1) + " Keep text after the cursor + if afterCursor != "\t" && afterCursor != ' ' + let line = strpart(line, 0, col - 1) + let snipLines[-1] .= afterCursor + else + let afterCursor = '' + " For some reason the cursor needs to move one right after this + if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' + let col += 1 + endif + endif + + call setline(lnum, line.snipLines[0]) + + " Autoindent snippet according to previous indentation + let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1 + call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val")) + + " Open any folds snippet expands into + if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif + + let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent) + + if s:snipLen + aug snipMateAutocmds + au CursorMovedI * call s:UpdateChangedSnip(0) + au InsertEnter * call s:UpdateChangedSnip(1) + aug END + let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer + let s:curPos = 0 + let s:endCol = g:snipPos[s:curPos][1] + let s:endLine = g:snipPos[s:curPos][0] + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + let s:prevLen = [line('$'), col('$')] + if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif + else + unl g:snipPos s:snipLen + " Place cursor at end of snippet if no tab stop is given + let newlines = len(snipLines) - 1 + call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor) + \ + (newlines ? 0: col - 1)) + endif + return '' +endf + +" Prepare snippet to be processed by s:BuildTabStops +fun s:ProcessSnippet(snip) + let snippet = a:snip + " Evaluate eval (`...`) expressions. + " Using a loop here instead of a regex fixes a bug with nested "\=". + if stridx(snippet, '`') != -1 + while match(snippet, '`.\{-}`') != -1 + let snippet = substitute(snippet, '`.\{-}`', + \ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')), + \ "\n\\%$", '', ''), '') + endw + let snippet = substitute(snippet, "\r", "\n", 'g') + endif + + " Place all text after a colon in a tab stop after the tab stop + " (e.g. "${#:foo}" becomes "${:foo}foo"). + " This helps tell the position of the tab stops later. + let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g') + + " Update the a:snip so that all the $# become the text after + " the colon in their associated ${#}. + " (e.g. "${1:foo}" turns all "$1"'s into "foo") + let i = 1 + while stridx(snippet, '${'.i) != -1 + let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}') + if s != '' + let snippet = substitute(snippet, '$'.i, s.'&', 'g') + endif + let i += 1 + endw + + if &et " Expand tabs to spaces if 'expandtab' is set. + return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g') + endif + return snippet +endf + +" Counts occurences of haystack in needle +fun s:Count(haystack, needle) + let counter = 0 + let index = stridx(a:haystack, a:needle) + while index != -1 + let index = stridx(a:haystack, a:needle, index+1) + let counter += 1 + endw + return counter +endf + +" Builds a list of a list of each tab stop in the snippet containing: +" 1.) The tab stop's line number. +" 2.) The tab stop's column number +" (by getting the length of the string between the last "\n" and the +" tab stop). +" 3.) The length of the text after the colon for the current tab stop +" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned. +" 4.) If the "${#:}" construct is given, another list containing all +" the matches of "$#", to be replaced with the placeholder. This list is +" composed the same way as the parent; the first item is the line number, +" and the second is the column. +fun s:BuildTabStops(snip, lnum, col, indent) + let snipPos = [] + let i = 1 + let withoutVars = substitute(a:snip, '$\d\+', '', 'g') + while stridx(a:snip, '${'.i) != -1 + let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D') + let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g') + + let j = i - 1 + call add(snipPos, [0, 0, -1]) + let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n") + let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D')) + if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif + + " Get all $# matches in another list, if ${#:name} is given + if stridx(withoutVars, '${'.i.':') != -1 + let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}')) + let dots = repeat('.', snipPos[j][2]) + call add(snipPos[j], []) + let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g') + while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1 + let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)') + call add(snipPos[j][3], [0, 0]) + let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n") + let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum + \ ? len(matchstr(beforeMark, '.*\n\zs.*')) + \ : a:col + len(beforeMark)) + let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '') + endw + endif + let i += 1 + endw + return [snipPos, i - 1] +endf + +fun snipMate#jumpTabStop(backwards) + let leftPlaceholder = exists('s:origWordLen') + \ && s:origWordLen != g:snipPos[s:curPos][2] + if leftPlaceholder && exists('s:oldEndCol') + let startPlaceholder = s:oldEndCol + 1 + endif + + if exists('s:update') + call s:UpdatePlaceholderTabStops() + else + call s:UpdateTabStops() + endif + + " Don't reselect placeholder if it has been modified + if leftPlaceholder && g:snipPos[s:curPos][2] != -1 + if exists('startPlaceholder') + let g:snipPos[s:curPos][1] = startPlaceholder + else + let g:snipPos[s:curPos][1] = col('.') + let g:snipPos[s:curPos][2] = 0 + endif + endif + + let s:curPos += a:backwards ? -1 : 1 + " Loop over the snippet when going backwards from the beginning + if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif + + if s:curPos == s:snipLen + let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2] + call s:RemoveSnippet() + return sMode ? "\" : TriggerSnippet() + endif + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + + let s:endLine = g:snipPos[s:curPos][0] + let s:endCol = g:snipPos[s:curPos][1] + let s:prevLen = [line('$'), col('$')] + + return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord() +endf + +fun s:UpdatePlaceholderTabStops() + let changeLen = s:origWordLen - g:snipPos[s:curPos][2] + unl s:startCol s:origWordLen s:update + if !exists('s:oldVars') | return | endif + " Update tab stops in snippet if text has been added via "$#" + " (e.g., in "${1:foo}bar$1${2}"). + if changeLen != 0 + let curLine = line('.') + + for pos in g:snipPos + if pos == g:snipPos[s:curPos] | continue | endif + let changed = pos[0] == curLine && pos[1] > s:oldEndCol + let changedVars = 0 + let endPlaceholder = pos[2] - 1 + pos[1] + " Subtract changeLen from each tab stop that was after any of + " the current tab stop's placeholders. + for [lnum, col] in s:oldVars + if lnum > pos[0] | break | endif + if pos[0] == lnum + if pos[1] > col || (pos[2] == -1 && pos[1] == col) + let changed += 1 + elseif col < endPlaceholder + let changedVars += 1 + endif + endif + endfor + let pos[1] -= changeLen * changed + let pos[2] -= changeLen * changedVars " Parse variables within placeholders + " e.g., "${1:foo} ${2:$1bar}" + + if pos[2] == -1 | continue | endif + " Do the same to any placeholders in the other tab stops. + for nPos in pos[3] + let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol + for [lnum, col] in s:oldVars + if lnum > nPos[0] | break | endif + if nPos[0] == lnum && nPos[1] > col + let changed += 1 + endif + endfor + let nPos[1] -= changeLen * changed + endfor + endfor + endif + unl s:endCol s:oldVars s:oldEndCol +endf + +fun s:UpdateTabStops() + let changeLine = s:endLine - g:snipPos[s:curPos][0] + let changeCol = s:endCol - g:snipPos[s:curPos][1] + if exists('s:origWordLen') + let changeCol -= s:origWordLen + unl s:origWordLen + endif + let lnum = g:snipPos[s:curPos][0] + let col = g:snipPos[s:curPos][1] + " Update the line number of all proceeding tab stops if has + " been inserted. + if changeLine != 0 + let changeLine -= 1 + for pos in g:snipPos + if pos[0] >= lnum + if pos[0] == lnum | let pos[1] += changeCol | endif + let pos[0] += changeLine + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] >= lnum + if nPos[0] == lnum | let nPos[1] += changeCol | endif + let nPos[0] += changeLine + endif + endfor + endfor + elseif changeCol != 0 + " Update the column of all proceeding tab stops if text has + " been inserted/deleted in the current line. + for pos in g:snipPos + if pos[1] >= col && pos[0] == lnum + let pos[1] += changeCol + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] >= col + let nPos[1] += changeCol + endif + endfor + endfor + endif +endf + +fun s:SelectWord() + let s:origWordLen = g:snipPos[s:curPos][2] + let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1, + \ s:origWordLen) + let s:prevLen[1] -= s:origWordLen + if !empty(g:snipPos[s:curPos][3]) + let s:update = 1 + let s:endCol = -1 + let s:startCol = g:snipPos[s:curPos][1] - 1 + endif + if !s:origWordLen | return '' | endif + let l = col('.') != 1 ? 'l' : '' + if &sel == 'exclusive' + return "\".l.'v'.s:origWordLen."l\" + endif + return s:origWordLen == 1 ? "\".l.'gh' + \ : "\".l.'v'.(s:origWordLen - 1)."l\" +endf + +" This updates the snippet as you type when text needs to be inserted +" into multiple places (e.g. in "${1:default text}foo$1bar$1", +" "default text" would be highlighted, and if the user types something, +" UpdateChangedSnip() would be called so that the text after "foo" & "bar" +" are updated accordingly) +" +" It also automatically quits the snippet if the cursor is moved out of it +" while in insert mode. +fun s:UpdateChangedSnip(entering) + if exists('g:snipPos') && bufnr(0) != s:lastBuf + call s:RemoveSnippet() + elseif exists('s:update') " If modifying a placeholder + if !exists('s:oldVars') && s:curPos + 1 < s:snipLen + " Save the old snippet & word length before it's updated + " s:startCol must be saved too, in case text is added + " before the snippet (e.g. in "foo$1${2}bar${1:foo}"). + let s:oldEndCol = s:startCol + let s:oldVars = deepcopy(g:snipPos[s:curPos][3]) + endif + let col = col('.') - 1 + + if s:endCol != -1 + let changeLen = col('$') - s:prevLen[1] + let s:endCol += changeLen + else " When being updated the first time, after leaving select mode + if a:entering | return | endif + let s:endCol = col - 1 + endif + + " If the cursor moves outside the snippet, quit it + if line('.') != g:snipPos[s:curPos][0] || col < s:startCol || + \ col - 1 > s:endCol + unl! s:startCol s:origWordLen s:oldVars s:update + return s:RemoveSnippet() + endif + + call s:UpdateVars() + let s:prevLen[1] = col('$') + elseif exists('g:snipPos') + if !a:entering && g:snipPos[s:curPos][2] != -1 + let g:snipPos[s:curPos][2] = -2 + endif + + let col = col('.') + let lnum = line('.') + let changeLine = line('$') - s:prevLen[0] + + if lnum == s:endLine + let s:endCol += col('$') - s:prevLen[1] + let s:prevLen = [line('$'), col('$')] + endif + if changeLine != 0 + let s:endLine += changeLine + let s:endCol = col + endif + + " Delete snippet if cursor moves out of it in insert mode + if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1])) + \ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0] + call s:RemoveSnippet() + endif + endif +endf + +" This updates the variables in a snippet when a placeholder has been edited. +" (e.g., each "$1" in "${1:foo} $1bar $1bar") +fun s:UpdateVars() + let newWordLen = s:endCol - s:startCol + 1 + let newWord = strpart(getline('.'), s:startCol, newWordLen) + if newWord == s:oldWord || empty(g:snipPos[s:curPos][3]) + return + endif + + let changeLen = g:snipPos[s:curPos][2] - newWordLen + let curLine = line('.') + let startCol = col('.') + let oldStartSnip = s:startCol + let updateTabStops = changeLen != 0 + let i = 0 + + for [lnum, col] in g:snipPos[s:curPos][3] + if updateTabStops + let start = s:startCol + if lnum == curLine && col <= start + let s:startCol -= changeLen + let s:endCol -= changeLen + endif + for nPos in g:snipPos[s:curPos][3][(i):] + " This list is in ascending order, so quit if we've gone too far. + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] > col + let nPos[1] -= changeLen + endif + endfor + if lnum == curLine && col > start + let col -= changeLen + let g:snipPos[s:curPos][3][i][1] = col + endif + let i += 1 + endif + + " "Very nomagic" is used here to allow special characters. + call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'. + \ escape(s:oldWord, '\'), escape(newWord, '\&'), '')) + endfor + if oldStartSnip != s:startCol + call cursor(0, startCol + s:startCol - oldStartSnip) + endif + + let s:oldWord = newWord + let g:snipPos[s:curPos][2] = newWordLen +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/autoload/vimwiki.vim b/autoload/vimwiki.vim new file mode 100644 index 0000000..80e6b0f --- /dev/null +++ b/autoload/vimwiki.vim @@ -0,0 +1,699 @@ +" Vimwiki autoload plugin file +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ + +if exists("g:loaded_vimwiki_auto") || &cp + finish +endif +let g:loaded_vimwiki_auto = 1 + +if has("win32") + let s:os_sep = '\' +else + let s:os_sep = '/' +endif + +let s:badsymbols = '['.g:vimwiki_badsyms.g:vimwiki_stripsym.'<>|?*:"]' + +" MISC helper functions {{{ + +" This function is double defined. +" TODO: refactor common functions into new module. +function! s:chomp_slash(str) "{{{ + return substitute(a:str, '[/\\]\+$', '', '') +endfunction "}}} + +function! s:is_windows() + return has("win32") || has("win64") || has("win95") || has("win16") +endfunction + +function! vimwiki#mkdir(path) "{{{ + let path = expand(a:path) + if !isdirectory(path) && exists("*mkdir") + let path = s:chomp_slash(path) + if s:is_windows() && !empty(g:vimwiki_w32_dir_enc) + let path = iconv(path, &enc, g:vimwiki_w32_dir_enc) + endif + call mkdir(path, "p") + endif +endfunction +" }}} + +function! vimwiki#safe_link(string) "{{{ + return substitute(a:string, s:badsymbols, g:vimwiki_stripsym, 'g') +endfunction +"}}} + +function! vimwiki#unsafe_link(string) "{{{ + return substitute(a:string, g:vimwiki_stripsym, s:badsymbols, 'g') +endfunction +"}}} + +function! vimwiki#subdir(path, filename)"{{{ + let path = expand(a:path) + let filename = expand(a:filename) + let idx = 0 + while path[idx] == filename[idx] + let idx = idx + 1 + endwhile + + let p = split(strpart(filename, idx), '[/\\]') + let res = join(p[:-2], s:os_sep) + if len(res) > 0 + let res = res.s:os_sep + endif + return res +endfunction"}}} + +function! vimwiki#current_subdir()"{{{ + return vimwiki#subdir(VimwikiGet('path'), expand('%:p')) +endfunction"}}} + +function! vimwiki#open_link(cmd, link, ...) "{{{ + if s:is_link_to_non_wiki_file(a:link) + call s:edit_file(a:cmd, a:link) + else + if a:0 + let vimwiki_prev_link = [a:1, []] + elseif &ft == 'vimwiki' + let vimwiki_prev_link = [expand('%:p'), getpos('.')] + endif + + call s:edit_file(a:cmd, VimwikiGet('path').a:link.VimwikiGet('ext')) + + if exists('vimwiki_prev_link') + let b:vimwiki_prev_link = vimwiki_prev_link + endif + endif +endfunction +" }}} + +function! s:filename(link) "{{{ + let result = vimwiki#safe_link(a:link) + if a:link =~ '|' + let result = vimwiki#safe_link(split(a:link, '|')[0]) + elseif a:link =~ '][' + let result = vimwiki#safe_link(split(a:link, '][')[0]) + endif + return result +endfunction +" }}} + +function! s:is_wiki_word(str) "{{{ + if a:str =~ g:vimwiki_word1 && a:str !~ '[[:space:]\\/]' + return 1 + endif + return 0 +endfunction +" }}} + +function! s:edit_file(command, filename) "{{{ + let fname = escape(a:filename, '% ') + call vimwiki#mkdir(fnamemodify(a:filename, ":p:h")) + execute a:command.' '.fname +endfunction +" }}} + +function! s:search_word(wikiRx, cmd) "{{{ + let match_line = search(a:wikiRx, 's'.a:cmd) + if match_line == 0 + echomsg "vimwiki: Wiki link not found." + endif +endfunction +" }}} + +function! s:get_word_at_cursor(wikiRX) "{{{ + let col = col('.') - 1 + let line = getline('.') + let ebeg = -1 + let cont = match(line, a:wikiRX, 0) + while (ebeg >= 0 || (0 <= cont) && (cont <= col)) + let contn = matchend(line, a:wikiRX, cont) + if (cont <= col) && (col < contn) + let ebeg = match(line, a:wikiRX, cont) + let elen = contn - ebeg + break + else + let cont = match(line, a:wikiRX, contn) + endif + endwh + if ebeg >= 0 + return strpart(line, ebeg, elen) + else + return "" + endif +endf "}}} + +function! s:strip_word(word) "{{{ + let result = a:word + if strpart(a:word, 0, 2) == "[[" + " get rid of [[ and ]] + let w = strpart(a:word, 2, strlen(a:word)-4) + + if w =~ '|' + " we want "link" from [[link|link desc]] + let w = split(w, "|")[0] + elseif w =~ '][' + " we want "link" from [[link][link desc]] + let w = split(w, "][")[0] + endif + + let result = vimwiki#safe_link(w) + endif + return result +endfunction +" }}} + +function! s:is_link_to_non_wiki_file(word) "{{{ + " Check if word is link to a non-wiki file. + " The easiest way is to check if it has extension like .txt or .html + if a:word =~ '\.\w\{1,4}$' + return 1 + endif + return 0 +endfunction +" }}} + +function! s:print_wiki_list() "{{{ + let idx = 0 + while idx < len(g:vimwiki_list) + if idx == g:vimwiki_current_idx + let sep = ' * ' + echohl PmenuSel + else + let sep = ' ' + echohl None + endif + echo (idx + 1).sep.VimwikiGet('path', idx) + let idx += 1 + endwhile + echohl None +endfunction +" }}} + +function! vimwiki#select(wnum)"{{{ + if a:wnum < 1 || a:wnum > len(g:vimwiki_list) + return + endif + if &ft == 'vimwiki' + let b:vimwiki_idx = g:vimwiki_current_idx + endif + let g:vimwiki_current_idx = a:wnum - 1 +endfunction +" }}} + +function! s:update_wiki_link(fname, old, new) " {{{ + echo "Updating links in ".a:fname + let has_updates = 0 + let dest = [] + for line in readfile(a:fname) + if !has_updates && match(line, a:old) != -1 + let has_updates = 1 + endif + call add(dest, substitute(line, a:old, escape(a:new, "&"), "g")) + endfor + " add exception handling... + if has_updates + call rename(a:fname, a:fname.'#vimwiki_upd#') + call writefile(dest, a:fname) + call delete(a:fname.'#vimwiki_upd#') + endif +endfunction +" }}} + +function! s:update_wiki_links_dir(dir, old_fname, new_fname) " {{{ + let old_fname = substitute(a:old_fname, '[/\\]', '[/\\\\]', 'g') + let new_fname = a:new_fname + + if !s:is_wiki_word(new_fname) + let new_fname = '[['.new_fname.']]' + endif + if !s:is_wiki_word(old_fname) + let old_fname = '\[\['.vimwiki#unsafe_link(old_fname). + \ '\%(|.*\)\?\%(\]\[.*\)\?\]\]' + else + let old_fname = '\<'.old_fname.'\>' + endif + let files = split(glob(VimwikiGet('path').a:dir.'*'.VimwikiGet('ext')), '\n') + for fname in files + call s:update_wiki_link(fname, old_fname, new_fname) + endfor +endfunction +" }}} + +function! s:tail_name(fname) "{{{ + let result = substitute(a:fname, ":", "__colon__", "g") + let result = fnamemodify(result, ":t:r") + let result = substitute(result, "__colon__", ":", "g") + return result +endfunction "}}} + +function! s:update_wiki_links(old_fname, new_fname) " {{{ + let old_fname = s:tail_name(a:old_fname) + let new_fname = s:tail_name(a:new_fname) + + let subdirs = split(a:old_fname, '[/\\]')[: -2] + + " TODO: Use Dictionary here... + let dirs_keys = [''] + let dirs_vals = [''] + if len(subdirs) > 0 + let dirs_keys = [''] + let dirs_vals = [join(subdirs, '/').'/'] + let idx = 0 + while idx < len(subdirs) - 1 + call add(dirs_keys, join(subdirs[: idx], '/').'/') + call add(dirs_vals, join(subdirs[idx+1 :], '/').'/') + let idx = idx + 1 + endwhile + call add(dirs_keys,join(subdirs, '/').'/') + call add(dirs_vals, '') + endif + + let idx = 0 + while idx < len(dirs_keys) + let dir = dirs_keys[idx] + let new_dir = dirs_vals[idx] + call s:update_wiki_links_dir(dir, + \ new_dir.old_fname, new_dir.new_fname) + let idx = idx + 1 + endwhile +endfunction +" }}} + +function! s:get_wiki_buffers() "{{{ + let blist = [] + let bcount = 1 + while bcount<=bufnr("$") + if bufexists(bcount) + let bname = fnamemodify(bufname(bcount), ":p") + if bname =~ VimwikiGet('ext')."$" + let bitem = [bname, getbufvar(bname, "vimwiki_prev_link")] + call add(blist, bitem) + endif + endif + let bcount = bcount + 1 + endwhile + return blist +endfunction +" }}} + +function! s:open_wiki_buffer(item) "{{{ + call s:edit_file('e', a:item[0]) + if !empty(a:item[1]) + call setbufvar(a:item[0], "vimwiki_prev_link", a:item[1]) + endif +endfunction +" }}} + +" }}} + +" SYNTAX highlight {{{ +function! vimwiki#WikiHighlightWords() "{{{ + " search all wiki files in 'path' and its subdirs. + let subdir = vimwiki#current_subdir() + let wikies = glob(VimwikiGet('path').subdir.'**/*'.VimwikiGet('ext')) + + " remove .wiki extensions + let wikies = substitute(wikies, '\'.VimwikiGet('ext'), "", "g") + let g:vimwiki_wikiwords = split(wikies, '\n') + + " remove backup files (.wiki~) + call filter(g:vimwiki_wikiwords, 'v:val !~ ''.*\~$''') + + " remove paths + let rem_path = escape(expand(VimwikiGet('path')).subdir, '\') + call map(g:vimwiki_wikiwords, 'substitute(v:val, rem_path, "", "g")') + + " Links with subdirs should be highlighted for linux and windows separators + " Change \ or / to [/\\] + let os_p = '[/\\]' + let os_p2 = escape(os_p, '\') + call map(g:vimwiki_wikiwords, 'substitute(v:val, os_p, os_p2, "g")') + + for word in g:vimwiki_wikiwords + if g:vimwiki_camel_case && + \ word =~ g:vimwiki_word1 && !s:is_link_to_non_wiki_file(word) + execute 'syntax match VimwikiWord /\%(^\|[^!]\)\@<=\<'.word.'\>/' + endif + execute 'syntax match VimwikiWord /\[\[\<'. + \ vimwiki#unsafe_link(word). + \ '\>\%(|\+.*\)*\]\]/' + execute 'syntax match VimwikiWord /\[\[\<'. + \ vimwiki#unsafe_link(word). + \ '\>\]\[.\+\]\]/' + endfor + execute 'syntax match VimwikiWord /\[\[.\+\.\%(jpg\|png\|gif\)\%(|\+.*\)*\]\]/' + execute 'syntax match VimwikiWord /\[\[.\+\.\%(jpg\|png\|gif\)\]\[.\+\]\]/' +endfunction +" }}} + +function! vimwiki#hl_exists(hl)"{{{ + if !hlexists(a:hl) + return 0 + endif + redir => hlstatus + exe "silent hi" a:hl + redir END + return (hlstatus !~ "cleared") +endfunction +"}}} + +function! vimwiki#nested_syntax(filetype, start, end, textSnipHl) abort "{{{ +" From http://vim.wikia.com/wiki/VimTip857 + let ft=toupper(a:filetype) + let group='textGroup'.ft + if exists('b:current_syntax') + let s:current_syntax=b:current_syntax + " Remove current syntax definition, as some syntax files (e.g. cpp.vim) + " do nothing if b:current_syntax is defined. + unlet b:current_syntax + endif + + " Some syntax files set up iskeyword which might scratch vimwiki a bit. + " Let us save and restore it later. + " let b:skip_set_iskeyword = 1 + let is_keyword = &iskeyword + + execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim' + try + execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim' + catch + endtry + + let &iskeyword = is_keyword + + if exists('s:current_syntax') + let b:current_syntax=s:current_syntax + else + unlet b:current_syntax + endif + execute 'syntax region textSnip'.ft.' + \ matchgroup='.a:textSnipHl.' + \ start="'.a:start.'" end="'.a:end.'" + \ contains=@'.group +endfunction "}}} + +"}}} + +" WIKI functions {{{ +function! vimwiki#WikiNextWord() "{{{ + call s:search_word(g:vimwiki_rxWikiWord.'\|'.g:vimwiki_rxWeblink, '') +endfunction +" }}} + +function! vimwiki#WikiPrevWord() "{{{ + call s:search_word(g:vimwiki_rxWikiWord.'\|'.g:vimwiki_rxWeblink, 'b') +endfunction +" }}} + +function! vimwiki#WikiFollowWord(split) "{{{ + if a:split == "split" + let cmd = ":split " + elseif a:split == "vsplit" + let cmd = ":vsplit " + else + let cmd = ":e " + endif + + let link = s:strip_word(s:get_word_at_cursor(g:vimwiki_rxWikiWord)) + if link == "" + let weblink = s:strip_word(s:get_word_at_cursor(g:vimwiki_rxWeblink)) + if weblink != "" + call VimwikiWeblinkHandler(weblink) + else + execute "normal! \n" + endif + return + endif + + let subdir = vimwiki#current_subdir() + call vimwiki#open_link(cmd, subdir.link) + +endfunction +" }}} + +function! vimwiki#WikiGoBackWord() "{{{ + if exists("b:vimwiki_prev_link") + " go back to saved WikiWord + let prev_word = b:vimwiki_prev_link + execute ":e ".substitute(prev_word[0], '\s', '\\\0', 'g') + call setpos('.', prev_word[1]) + endif +endfunction +" }}} + +function! vimwiki#WikiGoHome(index) "{{{ + call vimwiki#select(a:index) + call vimwiki#mkdir(VimwikiGet('path')) + + try + execute ':e '.fnameescape( + \ VimwikiGet('path').VimwikiGet('index').VimwikiGet('ext')) + catch /E37/ " catch 'No write since last change' error + " this is really unsecure!!! + execute ':'.VimwikiGet('gohome').' '. + \ VimwikiGet('path'). + \ VimwikiGet('index'). + \ VimwikiGet('ext') + catch /E325/ " catch 'ATTENTION' error (:h E325) + endtry +endfunction +"}}} + +function! vimwiki#WikiDeleteWord() "{{{ + "" file system funcs + "" Delete WikiWord you are in from filesystem + let val = input('Delete ['.expand('%').'] (y/n)? ', "") + if val != 'y' + return + endif + let fname = expand('%:p') + try + call delete(fname) + catch /.*/ + echomsg 'vimwiki: Cannot delete "'.expand('%:t:r').'"!' + return + endtry + execute "bdelete! ".escape(fname, " ") + + " reread buffer => deleted WikiWord should appear as non-existent + if expand('%:p') != "" + execute "e" + endif +endfunction +"}}} + +function! vimwiki#WikiRenameWord() "{{{ + "" Rename WikiWord, update all links to renamed WikiWord + let subdir = vimwiki#current_subdir() + let old_fname = subdir.expand('%:t') + + " there is no file (new one maybe) + if glob(expand('%:p')) == '' + echomsg 'vimwiki: Cannot rename "'.expand('%:p'). + \'". It does not exist! (New file? Save it before renaming.)' + return + endif + + let val = input('Rename "'.expand('%:t:r').'" (y/n)? ', "") + if val!='y' + return + endif + + let new_link = input('Enter new name: ', "") + + if new_link =~ '[/\\]' + " It is actually doable but I do not have free time to do it. + echomsg 'vimwiki: Cannot rename to a filename with path!' + return + endif + + let new_link = subdir.new_link + + " check new_fname - it should be 'good', not empty + if substitute(new_link, '\s', '', 'g') == '' + echomsg 'vimwiki: Cannot rename to an empty filename!' + return + endif + if s:is_link_to_non_wiki_file(new_link) + echomsg 'vimwiki: Cannot rename to a filename with extension (ie .txt .html)!' + return + endif + + let new_link = s:strip_word(new_link) + let new_fname = VimwikiGet('path').s:filename(new_link).VimwikiGet('ext') + + " do not rename if word with such name exists + let fname = glob(new_fname) + if fname != '' + echomsg 'vimwiki: Cannot rename to "'.new_fname. + \ '". File with that name exist!' + return + endif + " rename WikiWord file + try + echomsg "Renaming ".VimwikiGet('path').old_fname." to ".new_fname + let res = rename(expand('%:p'), expand(new_fname)) + if res != 0 + throw "Cannot rename!" + end + catch /.*/ + echomsg 'vimwiki: Cannot rename "'.expand('%:t:r').'" to "'.new_fname.'"' + return + endtry + + let &buftype="nofile" + + let cur_buffer = [expand('%:p'), + \getbufvar(expand('%:p'), "vimwiki_prev_link")] + + let blist = s:get_wiki_buffers() + + " save wiki buffers + for bitem in blist + execute ':b '.escape(bitem[0], ' ') + execute ':update' + endfor + + execute ':b '.escape(cur_buffer[0], ' ') + + " remove wiki buffers + for bitem in blist + execute 'bwipeout '.escape(bitem[0], ' ') + endfor + + let setting_more = &more + setlocal nomore + + " update links + call s:update_wiki_links(old_fname, new_link) + + " restore wiki buffers + for bitem in blist + if bitem[0] != cur_buffer[0] + call s:open_wiki_buffer(bitem) + endif + endfor + + call s:open_wiki_buffer([new_fname, + \ cur_buffer[1]]) + " execute 'bwipeout '.escape(cur_buffer[0], ' ') + + echomsg old_fname." is renamed to ".new_fname + + let &more = setting_more +endfunction +" }}} + +function! vimwiki#WikiUISelect()"{{{ + call s:print_wiki_list() + let idx = input("Select Wiki (specify number): ") + if idx == "" + return + endif + call vimwiki#WikiGoHome(idx) +endfunction +"}}} + +" }}} + +" TEXT OBJECTS functions {{{ + +function! vimwiki#TO_header(inner, visual) "{{{ + if !search('^\(=\+\)[^=]\+\1\s*$', 'bcW') + return + endif + + let sel_start = line("'<") + let sel_end = line("'>") + let block_start = line(".") + let advance = 0 + + let level = vimwiki#count_first_sym(getline('.')) + + let is_header_selected = sel_start == block_start + \ && sel_start != sel_end + + if a:visual && is_header_selected + if level > 1 + let level -= 1 + call search('^\(=\{'.level.'\}\)[^=]\+\1\s*$', 'bcW') + else + let advance = 1 + endif + endif + + normal! V + + if a:visual && is_header_selected + call cursor(sel_end + advance, 0) + endif + + if search('^\(=\{1,'.level.'}\)[^=]\+\1\s*$', 'W') + call cursor(line('.') - 1, 0) + else + call cursor(line('$'), 0) + endif + + if a:inner && getline(line('.')) =~ '^\s*$' + let lnum = prevnonblank(line('.') - 1) + call cursor(lnum, 0) + endif +endfunction +"}}} + +function! vimwiki#count_first_sym(line) "{{{ + let first_sym = matchstr(a:line, '\S') + return len(matchstr(a:line, first_sym.'\+')) +endfunction "}}} + +function! vimwiki#AddHeaderLevel() "{{{ + let lnum = line('.') + let line = getline(lnum) + + if line =~ '^\s*$' + return + endif + + if line =~ '^\s*\(=\+\).\+\1\s*$' + let level = vimwiki#count_first_sym(line) + if level < 6 + let line = substitute(line, '\(=\+\).\+\1', '=&=', '') + call setline(lnum, line) + endif + else + let line = substitute(line, '^\s*', '&= ', '') + let line = substitute(line, '\s*$', ' =&', '') + call setline(lnum, line) + endif +endfunction +"}}} + +function! vimwiki#RemoveHeaderLevel() "{{{ + let lnum = line('.') + let line = getline(lnum) + + if line =~ '^\s*$' + return + endif + + if line =~ '^\s*\(=\+\).\+\1\s*$' + let level = vimwiki#count_first_sym(line) + let old = repeat('=', level) + let new = repeat('=', level - 1) + + let chomp = line =~ '=\s' + + let line = substitute(line, old, new, 'g') + + if level == 1 && chomp + let line = substitute(line, '^\s', '', 'g') + let line = substitute(line, '\s$', '', 'g') + endif + call setline(lnum, line) + endif +endfunction +" }}} + +" }}} diff --git a/autoload/vimwiki_diary.vim b/autoload/vimwiki_diary.vim new file mode 100644 index 0000000..25d8d33 --- /dev/null +++ b/autoload/vimwiki_diary.vim @@ -0,0 +1,216 @@ +" Vimwiki autoload plugin file +" Desc: Handle diary notes +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ + +" Load only once {{{ +if exists("g:loaded_vimwiki_diary_auto") || &cp + finish +endif +let g:loaded_vimwiki_diary_auto = 1 +"}}} + +function! s:prefix_zero(num) "{{{ + if a:num < 10 + return '0'.a:num + endif + return a:num +endfunction "}}} + +function! s:desc(d1, d2) "{{{ + return a:d1 == a:d2 ? 0 : a:d1 < a:d2 ? 1 : -1 +endfunction "}}} + +function! s:get_date_link(fmt) "{{{ + return strftime(a:fmt) +endfunction "}}} + +function! s:link_exists(lines, link) "{{{ + let link_exists = 0 + for line in a:lines + if line =~ escape(a:link, '[]\') + let link_exists = 1 + break + endif + endfor + return link_exists +endfunction "}}} + +function! s:diary_path() "{{{ + return VimwikiGet('path').VimwikiGet('diary_rel_path') +endfunction "}}} + +function! s:diary_index() "{{{ + return s:diary_path().VimwikiGet('diary_index').VimwikiGet('ext') +endfunction "}}} + +function! s:get_diary_range(lines, header) "{{{ + let rx = '\[\[\d\{4}-\d\d-\d\d\]\]' + let idx = 0 + let ln_start = -1 + let ln_end = -1 + for line in a:lines + if ln_start != -1 + if line =~ '^\s*\(=\)\+.*\1\s*$' || (line !~ rx && line !~ '^\s*$') + break + endif + endif + if line =~ '^\s*\(=\)\+\s*'.a:header.'\s*\1\s*$' + let ln_start = idx + 1 + endif + let idx += 1 + endfor + + let ln_end = idx - 1 + return [ln_start, ln_end] +endfunction "}}} + +function! s:diary_date_link() "{{{ + return s:get_date_link(VimwikiGet('diary_link_fmt')) +endfunction "}}} + +function! s:get_file_contents(file_name) "{{{ + let lines = [] + let bufnr = bufnr(expand(a:file_name)) + if bufnr != -1 + let lines = getbufline(bufnr, 1, '$') + else + try + let lines = readfile(expand(a:file_name)) + catch + endtry + endif + return [lines, bufnr] +endfunction "}}} + +function! s:get_links() "{{{ + let rx = '\d\{4}-\d\d-\d\d' + let s_links = glob(VimwikiGet('path').VimwikiGet('diary_rel_path').'*.wiki') + + "let s_links = substitute(s_links, '\'.VimwikiGet('ext'), "", "g") + let s_links = substitute(s_links, '\.wiki', "", "g") + let links = split(s_links, '\n') + + " remove backup files (.wiki~) + call filter(links, 'v:val !~ ''.*\~$''') + + " remove paths + call map(links, 'fnamemodify(v:val, ":t")') + + call filter(links, 'v:val =~ "'.escape(rx, '\').'"') + call map(links, '"[[".v:val."]]"') + return links +endfunction "}}} + +function! s:format_links(links) "{{{ + let lines = [] + let line = '| ' + let idx = 0 + let trigger = 0 + while idx < len(a:links) + if idx/VimwikiGet('diary_link_count') > trigger + let trigger = idx/VimwikiGet('diary_link_count') + call add(lines, substitute(line, '\s\+$', '', '')) + let line = '| ' + endif + let line .= a:links[idx].' | ' + let idx += 1 + endwhile + call add(lines, substitute(line, '\s\+$', '', '')) + call extend(lines, ['']) + + return lines +endfunction "}}} + +function! s:add_link(page, header, link) "{{{ + let [lines, bufnr] = s:get_file_contents(a:page) + + let [ln_start, ln_end] = s:get_diary_range(lines, a:header) + + let link = '[['.a:link.']]' + + let link_exists = s:link_exists(lines[ln_start : ln_end], link) + + if !link_exists + + if ln_start == -1 + call insert(lines, '= '.a:header.' =') + let ln_start = 1 + endif + + " removing 'old' links + let idx = ln_end - ln_start + while idx > 0 + call remove(lines, ln_start) + let idx -= 1 + endwhile + + " get all diary links from filesystem + let links = s:get_links() + + " add current link + if index(links, link) == -1 + call add(links, link) + endif + + let links = sort(links, 's:desc') + call extend(lines, s:format_links(links), ln_start) + + if bufnr != -1 + exe 'buffer '.bufnr + if !&readonly + 1,$delete _ + call append(1, lines) + 1,1delete _ + endif + else + call writefile(lines, expand(a:page)) + endif + endif +endfunction "}}} + +function! s:make_date_link(...) "{{{ + if a:0 + let link = a:1 + else + let link = s:diary_date_link() + endif + let header = VimwikiGet('diary_header') + call s:add_link(s:diary_index(), header, link) + return VimwikiGet('diary_rel_path').link +endfunction "}}} + +function! vimwiki_diary#make_note(index, ...) "{{{ + call vimwiki#select(a:index) + call vimwiki#mkdir(VimwikiGet('path').VimwikiGet('diary_rel_path')) + if a:0 + let link = s:make_date_link(a:1) + else + let link = s:make_date_link() + endif + call vimwiki#open_link(':e ', link, s:diary_index()) +endfunction "}}} + +" Calendar.vim callback. +function! vimwiki_diary#calendar_action(day, month, year, week, dir) "{{{ + let day = s:prefix_zero(a:day) + let month = s:prefix_zero(a:month) + + let link = a:year.'-'.month.'-'.day + if winnr('#') == 0 + if a:dir == 'V' + vsplit + else + split + endif + else + wincmd p + if !&hidden && &modified + new + endif + endif + + " Create diary note for a selected date in default wiki. + call vimwiki_diary#make_note(1, link) +endfunction + diff --git a/autoload/vimwiki_html.vim b/autoload/vimwiki_html.vim new file mode 100644 index 0000000..e7c7722 --- /dev/null +++ b/autoload/vimwiki_html.vim @@ -0,0 +1,1123 @@ +" Vimwiki autoload plugin file +" Export to HTML +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ + +" XXX: This file should be refactored! + +" Load only once {{{ +if exists("g:loaded_vimwiki_html_auto") || &cp + finish +endif +let g:loaded_vimwiki_html_auto = 1 +"}}} + +" SCRIPT VARS "{{{ +" Warn if html header or html footer do not exist only once. +let s:warn_html_header = 0 +let s:warn_html_footer = 0 +"}}} + +" UTILITY "{{{ +function! s:root_path(subdir) "{{{ + return repeat('../', len(split(a:subdir, '[/\\]'))) +endfunction "}}} + +function! s:syntax_supported() " {{{ + return VimwikiGet('syntax') == "default" +endfunction " }}} + +function! s:remove_blank_lines(lines) " {{{ + while a:lines[-1] =~ '^\s*$' + call remove(a:lines, -1) + endwhile +endfunction "}}} + +function! s:is_web_link(lnk) "{{{ + if a:lnk =~ '^\%(https://\|http://\|www.\|ftp://\|file://\)' + return 1 + endif + return 0 +endfunction "}}} + +function! s:is_img_link(lnk) "{{{ + if a:lnk =~ '\.\%(png\|jpg\|gif\|jpeg\)$' + return 1 + endif + return 0 +endfunction "}}} + +function! s:is_non_wiki_link(lnk) "{{{ + " TODO: Add more file extensions here + if a:lnk =~ '.\+\.\%(pdf\|txt\|doc\|rtf\|xls\)$' + return 1 + endif + return 0 +endfunction "}}} + +function! s:has_abs_path(fname) "{{{ + if a:fname =~ '\(^.:\)\|\(^/\)' + return 1 + endif + return 0 +endfunction "}}} + +function! s:create_default_CSS(path) " {{{ + let path = expand(a:path) + let css_full_name = path.VimwikiGet('css_name') + if glob(css_full_name) == "" + call vimwiki#mkdir(fnamemodify(css_full_name, ':p:h')) + let lines = [] + + call add(lines, 'body {font-family: Arial, sans-serif; margin: 1em 2em 1em 2em; font-size: 100%; line-height: 130%;}') + call add(lines, 'h1, h2, h3, h4, h5, h6 {font-family: Trebuchet MS, serif; margin-top: 1.5em; margin-bottom: 0.5em;}') + call add(lines, 'h1 {font-size: 2.0em; color: #a77070;}') + call add(lines, 'h2 {font-size: 1.6em; color: #779977;}') + call add(lines, 'h3 {font-size: 1.3em; color: #555577;}') + call add(lines, 'h4 {font-size: 1.2em; color: #222244;}') + call add(lines, 'h5 {font-size: 1.1em; color: #222244;}') + call add(lines, 'h6 {font-size: 1.0em; color: #222244;}') + call add(lines, 'p, pre, blockquote, table, ul, ol, dl {margin-top: 1em; margin-bottom: 1em;}') + call add(lines, 'ul ul, ul ol, ol ol, ol ul {margin-top: 0.5em; margin-bottom: 0.5em;}') + call add(lines, 'li {margin: 0.3em auto;}') + call add(lines, 'ul {margin-left: 2em; padding-left: 0.5em;}') + call add(lines, 'dt {font-weight: bold;}') + call add(lines, 'img {border: none;}') + call add(lines, 'pre {border-left: 1px solid #ccc; margin-left: 2em; padding-left: 0.5em;}') + call add(lines, 'blockquote {padding: 0.4em; background-color: #f6f5eb;}') + call add(lines, 'th, td {border: 1px solid #ccc; padding: 0.3em;}') + call add(lines, 'th {background-color: #f0f0f0;}') + call add(lines, 'hr {border: none; border-top: 1px solid #ccc; width: 100%;}') + call add(lines, 'del {text-decoration: line-through; color: #777777;}') + call add(lines, '.toc li {list-style-type: none;}') + call add(lines, '.todo {font-weight: bold; background-color: #f0ece8; color: #a03020;}') + call add(lines, '.justleft {text-align: left;}') + call add(lines, '.justright {text-align: right;}') + call add(lines, '.justcenter {text-align: center;}') + + call writefile(lines, css_full_name) + echomsg "Default style.css is created." + endif +endfunction "}}} + +function! s:get_html_header(wikifile, subdir, charset) "{{{ + let lines=[] + + let title = fnamemodify(a:wikifile, ":t:r") + + if VimwikiGet('html_header') != "" && !s:warn_html_header + try + let lines = readfile(expand(VimwikiGet('html_header'))) + call map(lines, 'substitute(v:val, "%title%", "'. title .'", "g")') + call map(lines, 'substitute(v:val, "%root_path%", "'. + \ s:root_path(a:subdir) .'", "g")') + return lines + catch /E484/ + let s:warn_html_header = 1 + echomsg 'vimwiki: Header template '.VimwikiGet('html_header'). + \ ' does not exist!' + endtry + endif + + let css_name = expand(VimwikiGet('css_name')) + let css_name = substitute(css_name, '\', '/', 'g') + if !s:has_abs_path(css_name) + " Relative css file for deep links: [[dir1/dir2/dir3/filename]] + let css_name = s:root_path(a:subdir).css_name + endif + + " if no VimwikiGet('html_header') set up or error while reading template + " file -- use default header. + call add(lines, '') + call add(lines, '') + call add(lines, '') + call add(lines, ''.title.'') + call add(lines, '') + call add(lines, '') + call add(lines, '') + + return lines +endfunction "}}} + +function! s:get_html_footer() "{{{ + let lines=[] + + if VimwikiGet('html_footer') != "" && !s:warn_html_footer + try + let lines = readfile(expand(VimwikiGet('html_footer'))) + return lines + catch /E484/ + let s:warn_html_footer = 1 + echomsg 'vimwiki: Footer template '.VimwikiGet('html_footer'). + \ ' does not exist!' + endtry + endif + + " if no VimwikiGet('html_footer') set up or error while reading template + " file -- use default footer. + call add(lines, "") + call add(lines, '') + call add(lines, '') + + return lines +endfunction "}}} + +function! s:safe_html(line) "{{{ + "" change dangerous html symbols: < > & + + let line = substitute(a:line, '&', '\&', 'g') + let line = substitute(line, '<', '\<', 'g') + let line = substitute(line, '>', '\>', 'g') + return line +endfunction "}}} + +function! s:delete_html_files(path) "{{{ + let htmlfiles = split(glob(a:path.'**/*.html'), '\n') + for fname in htmlfiles + try + call delete(fname) + catch + echomsg 'vimwiki: Cannot delete '.fname + endtry + endfor +endfunction "}}} + +function! s:remove_comments(lines) "{{{ + let res = [] + let multiline_comment = 0 + + let idx = 0 + while idx < len(a:lines) + let line = a:lines[idx] + let idx += 1 + + if multiline_comment + let col = matchend(line, '-->',) + if col != -1 + let multiline_comment = 0 + let line = strpart(line, col) + else + continue + endif + endif + + if !multiline_comment && line =~ '' + let line = substitute(line, '', '', 'g') + if line =~ '^\s*$' + continue + endif + endif + + if !multiline_comment + let col = match(line, '" + let g:paras[i] = toc + endif + let i += 1 + endwhile +endif +" }}} +" Create h[1-6] paragraphs {{{ +let i = 0 +while i < len(g:paras) + if g:ptype[i] =~ '^h\d' + if g:ptype[i] == 'h1' && !exists("g:vst_doc_title") + let g:vst_doc_title = substitute(g:paras[i], '^.*\zs\n.*$', '', '') + endif + let g:paras[i] = VST_SpecCharacter(g:paras[i]) + let stitle = tolower(matchstr(g:paras[i], '^\s*\zs.*\ze\n')) + let stitle = VST_IdMaker(stitle) + let g:paras[i] = substitute(g:paras[i], '^.*\zs\n.*$', '', '') + let g:paras[i] = substitute(g:paras[i], '^\s*', '\0', '') + endif + let i += 1 +endwhile +" }}} +" Create document title (.. title::) {{{ +if string(g:ptype) =~ "'title'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'title' + let g:vst_doc_title = substitute(g:paras[i], '^\s*\.\. title::\s*', '', '') + let g:paras[i] = '' + endif + let i += 1 + endwhile +endif +" }}} +" Create verse paragraphs ("| ") {{{ +if string(g:ptype) =~ "'verse'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'verse' + let g:paras[i] = VST_SpecCharacter(g:paras[i]) + let g:paras[i] = VST_CreateVerse(g:paras[i]) + + let g:paras[i] = substitute(g:paras[i], '\n".VST_ProtectLiteral(g:paras[i])."\n" + endif + let i += 1 + endwhile +endif +" }}} +" Create raw HTML paragraph (next after .. raw:: html) {{{ +if string(g:ptype) =~ "'rawhtmlcontent'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'rawhtmlcontent' + let g:paras[i] = "\n".VST_ProtectLiteral(g:paras[i])."\n" + endif + let i += 1 + endwhile +endif +" }}} +" Create raw both paragraph (next after .. raw:: ) {{{ +if string(g:ptype) =~ "'rawbothcontent'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'rawbothcontent' + let g:paras[i] = "\n".g:paras[i]."\n" + endif + let i += 1 + endwhile +endif +" }}} +" Create LaTeX only paragraph - latexonly (.. raw:: latex) {{{ +if string(g:ptype) =~ "'latexonly'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'latexonly' + let g:paras[i] = substitute(g:paras[i], '\(\s*\)$', '\n\1', '') + let g:paras[i] = substitute(g:paras[i], '^\(\s*\)\.\. latexonly::\s*\n', '\n\1\n', '') + let g:paras[i] = substitute(g:paras[i], '^\(\s*\)\.\. latexonly::', '\n\1\n', '') + endif + let i += 1 + endwhile +endif +" }}} +" Create HTML only paragraph - htmlonly (.. raw:: html) {{{ +if string(g:ptype) =~ "'htmlonly'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'htmlonly' + let g:paras[i] = substitute(g:paras[i], '\(\s*\)$', '\n\1', '') + let g:paras[i] = substitute(g:paras[i], '^\(\s*\)\.\. htmlonly::\s*\n', '\n\1\n', '') + let g:paras[i] = substitute(g:paras[i], '^\(\s*\)\.\. htmlonly::', '\n\1\n', '') + endif + let i += 1 + endwhile +endif +" }}} +" Check and embrace paragraphs in blockquote tags {{{ +if string(g:ptype) =~ "'blockquote'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'blockquote' + let j = i + 1 + while j < len(g:paras) + let noteindent = g:pindent[j] - g:pindent[i] + if g:pindent[i] > g:pindent[j] || g:ptype[j] == 'blank' || g:ptype[j] == 'notend' + call insert(g:paras, repeat(' ' , g:pindent[i]).'', j) + call insert(g:pindent, g:pindent[i], j) + call insert(g:ptype, 'blockend', j) + call insert(g:plinen, 0, j) + + call insert(g:paras, repeat(' ' , g:pindent[i]).'', i) + call insert(g:pindent, g:pindent[i], i) + call insert(g:ptype, 'blockbegin', i) + call insert(g:plinen, 0, i) + + " Recompensate inserted paragraph before current position. + let i += 1 + + " Region embraced , now I have to take care about paragraph + let g:ptype[i] = 'p' + + break + + endif + let j += 1 + endwhile + endif + let i += 1 + endwhile +endif +" }}} +" Create table {{{ +if string(g:ptype) =~ "'table'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] =~ 'table' + let g:tclen = [] + let g:thash = {} + let g:tabb = [] + let g:taba = [] + + let lines = split(g:paras[i], '\n') + let newrow = 0 + unlet! trow + + let line_count = 0 + let headfoot_counter = 0 + unlet! usedthead + unlet! usedtfoot + + for line in lines + let row = substitute(line, '^\s*\|\s*$', '', 'g') + if row =~ '^+' + if exists('trow') + + let g:tabb += [deepcopy(trow)] + + let rl = 0 + while rl < len(trow) + let trow[rl] = VST_SpecCharacter(trow[rl]) + let cell = split(trow[rl], "\n") + let trow[rl] = VST_Structure(cell) + let rl += 1 + endwhile + + let g:taba += [trow] + + endif + if row =~ '^+=' && line_count > 0 + let headfoot_counter += 1 + endif + " Add head/foot structure elements to the end of last cell in + " row. Later switch order of elements by regexps. + if headfoot_counter > 0 && !exists('usedthead') && !exists('usedtfoot') + let g:taba[-1][-1] .= '' + let usedthead = 1 + endif + if headfoot_counter > 1 && !exists('usedtfoot') + let g:taba[-1][-1] .= '' + let usedtfoot = 1 + endif + let g:hf = headfoot_counter + let newrow = 1 + let g:thash[len(split(row, '+'))] = split(row, '+') + continue + else + if newrow == 1 + let trow = split(row, '\(^\| \)|\( \|$\)') + let newrow = 0 + else + let tmprow = split(row, '\(^\| \)|\( \|$\)') + let rl = 0 + while rl < len(tmprow) + let trow[rl] .= "\n".tmprow[rl] + let rl += 1 + endwhile + endif + endif + let line_count += 1 + endfor + + + " Get lengths of most standard cells in table, need this for testing + " of cells for length if they are longer + let g:tstandard = g:thash[max(keys(g:thash))] + let tl = 0 + while tl < len(g:tstandard) + let g:tclen += [len(g:tstandard[tl])] + let tl += 1 + endwhile + + " Check relative sizes of table columns + " I need this to declare widths of columns in LaTeX export + exe 'let g:sum = '.join(g:tclen, '+') + let g:sizes = [] + for col in g:tclen + let colwidth = col*90/g:sum + if len(colwidth) == 1 + let colwidth = '0'.colwidth + endif + let g:sizes += [colwidth] + endfor + + " insertion of columns size for proper breaking of text in table cells + let colnumber = join(g:sizes, '+').'+' + + let tl = 0 + let g:ctable = '' + while tl < len(g:tabb) + let trow = g:tabb[tl] + let g:ctable .= '' + let cn = 0 + let tcc = cn + while cn < len(trow) + let cll = trow[cn] + if stridx(cll, "\n") != -1 + let g:celllength = strlen(matchstr(cll, '^.\{-}\ze\n')) + 2 + else + let g:celllength = strlen(cll) + 2 + endif + let k = 0 + let tempst = 0 + while 1 + if k < 2 + let tempst += g:tclen[tcc+k] + k + else + let tempst += g:tclen[tcc+k] + 1 + endif + if g:celllength == tempst + if k > 0 + let tccplus = tcc + k + exe 'let g:summa = '.join(g:sizes[tcc : tccplus], '+') + if exists("g:vst_center_multicol") && g:vst_center_multicol != 1 + let g:ctable .= "".g:taba[tl][cn]."" + else + let g:ctable .= "".g:taba[tl][cn]."" + endif + else + let g:ctable .= "".g:taba[tl][cn]."" + endif + let tcc += k + break + else + let k += 1 + continue + endif + endwhile + let tcc += 1 + let cn += 1 + endwhile + let g:ctable .= "\n" + let tl += 1 + endwhile + + + " Check if table is borderless + if g:ptype[i] == 'bltable' + let class = 'vstbless' + else + let class = 'vstborder' + endif + " Info about borders is awful abuse of summary... + let ttable = "\n".g:ctable."" + + if headfoot_counter > 0 + let ttable = substitute(ttable, ']*>', '\0\n', '') + let ttable = substitute(ttable, '\(\)\(\n\)', '\2\n\1\n', '') + endif + if headfoot_counter == 2 + let ttable = substitute(ttable, '<.vim:table>', '\n\0', '') + let ttable = substitute(ttable, '\(\)\(\n\)', '\2\n\1\n', '') + endif + + let g:paras[i] = ttable + + endif + let i += 1 + endwhile + unlet! trow + unlet! row +endif +" }}} +" Create subtitle paragraphs {{{ +let i = 0 +while i < len(g:paras) + if g:ptype[i] =~ 'subh\d' + let g:paras[i] = VST_SpecCharacter(g:paras[i]) + let g:paras[i] = "\n".repeat(' ', g:pindent[i]).''."\n".g:paras[i] + " Remove last line of subtitle if this is ornament. + " Treatment of headers in reST is weird. + let g:paras[i] = substitute(g:paras[i], '\n\s*'.s:vst_headdef.'\s*$', '', '') + let g:paras[i] .= "\n".repeat(' ', g:pindent[i])."\n" + endif + let i += 1 +endwhile +" }}} +" Doctest paragraphs {{{ +if string(g:ptype) =~ "'doctest'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] == 'doctest' + let class = VST_AddClass(i,1, ' ', '') + let g:paras[i] = VST_SpecCharacter(g:paras[i]) + let g:paras[i] = "\n".repeat(' ', g:pindent[i])."\n".g:paras[i] + let g:paras[i] .= "\n".repeat(' ', g:pindent[i])."\n" + endif + let i += 1 + endwhile +endif +" }}} +" Simple table paragraphs {{{ +if string(g:ptype) =~ "'simpletbl'" + let i = 0 + while i < len(g:paras) + + if g:ptype[i] == 'simpletbl' + + unlet! usedthead + unlet! usedtfoot + unlet! usethead + + let plines = split(g:paras[i], '\n') + let header = substitute(plines[0], '^\s\+', '', '') + " Remove framing === === lines + let plines = plines[1:-2] + let usethead = 0 + for j in range(len(plines)) + let plines[j] = substitute(plines[j], '^\s\{'.g:pindent[i].'}', '', '') + if plines[j] =~ '^\(=\{2,}\s*\)\+$' + let usethead += 1 + endif + endfor + " Get width of cols {{{ + let cols = [] + for k in split(header, '[^=]=') + let cols += [len(matchstr(header, '^=*\s*'))] + let header = substitute(header, '^=*\s*', '', '') + endfor + " Due to nature of formatting last column may seem narrower than rest. + " Add 1 to slightly recompense that. + let cols[-1] += 1 + " Calculate percentage widths of columns. + exe 'let total_width = '.join(cols, '+') + let sizes = [] + for col in cols + let colwidth = col*90/total_width + if len(colwidth) == 1 + let colwidth = '0'.colwidth + endif + let sizes += [colwidth] + endfor + let col_desc = join(sizes, '+').'+' + " }}} + " Split plines into separate cells {{{ + let table = [] + for line in plines + + let trow = [] + + for k in range(len(cols)) + if k == len(cols)-1 + let trow += [line] + else + let trow += [line[0:(cols[k]-1)]] + let line = line[(cols[k]):] + endif + endfor + + let table += [trow] + + endfor + " }}} + " Now create real, multiline if necessary, cells {{{ + let rtable = [] + for k in range(len(table)) + + let row = table[k] + + if k == 0 + let prevrow = ['-----'] + else + let prevrow = table[k-1] + endif + + if row[0] =~ '^\s*$' + if prevrow[0] =~ '[-=]\{2,}' + let addrow = 0 + else + let addrow = 1 + endif + else + let addrow = 0 + endif + + if addrow == 0 + let temprow = [] + for j in range(len(cols)) + if row[j] !~ '^[=-]\{2,}' + let temprow += [row[j]] + elseif row[j] =~ '^=\{2,}' + let temprow += ['-vst-thfelem-'] + endif + endfor + let rtable += [temprow] + elseif addrow == 1 + for j in range(len(cols)) + if row[j] !~ '^[=-]\{2,}' + let temprow[j] .= "\n".row[j] + elseif row[j] =~ '^=\{2,}' + let temprow += ['-vst-thfelem-'] + endif + endfor + endif + + endfor + " }}} + + " Translate data structure into Vim reStructured Text markup + " Go through cells, call Structure function, join(). + let class = VST_AddClass(i,0, ' ', '') + let g:paras[i] = '\n" + + " insert thead at the beginning + if usethead > 0 + let g:paras[i] .= "\n" + endif + + for k in range(len(rtable)) + let row = rtable[k] + + if row == [] + let k += 1 + continue + endif + + " Interpret text inside of cells looking for structures {{{ + for j in range(len(row)) + if row[j] =~ '^-vst-thfelem-$' + let j += 1 + continue + else + let row[j] = VST_SpecCharacter(row[j]) + let cellt = split(row[j], "\n") + " Remove in-frontal space from one-line cells to avoid + " interpretation of text as blockquote + "if len(cellt) == 1 + " let cellt[0] = substitute(cellt[0], '^\s\+', '', '') + "endif + let row[j] = VST_Structure(cellt) + endif + endfor + " }}} + + " Create marked text and add thead and tfoot when appropriate + if usethead > 0 && !exists("usedthead") && join(row, '') =~ '^\(-vst-thfelem-\)\+$' + let g:paras[i] .= "\n\n" + let usedthead = 1 + continue + endif + if usethead > 1 && exists("usedthead") && join(row, '') =~ '^\(-vst-thfelem-\)\+$' + let g:paras[i] .= "\n\n" + unlet usedthead + let usedtfoot = 1 + continue + endif + + let g:paras[i] .= ''.join(row, '').''."\n" + + + endfor + + if exists("usedtfoot") + unlet usedtfoot + let g:paras[i] .= "\n\n" + endif + + unlet! usedthead + unlet! usedtfoot + unlet! usethead + + let g:paras[i] .= '' + + endif + let i += 1 + endwhile +endif +" }}} +" Create p paragraph {{{ +let i = 0 +while i < len(g:paras) + if g:ptype[i] == 'p' + let g:paras[i] = VST_SpecCharacter(g:paras[i]) + if g:paras[i] =~ '^\s\+---\?\s.*\S' && g:ptype[i+1] == 'blockend' + let class = VST_AddClass(i,0, '', '') + let g:paras[i] = "\n".repeat(' ', g:pindent[i])."\n".g:paras[i] + else + let class = VST_AddClass(i,1, ' ', '') + let g:paras[i] = "\n".repeat(' ', g:pindent[i])."\n".g:paras[i] + endif + let g:paras[i] .= "\n".repeat(' ', g:pindent[i])."\n" + endif + let i += 1 +endwhile +" }}} +" Insert raw files placeholders {{{ +if string(g:ptype) =~ "'raw\(latex\|html\|both\)'" + let i = 0 + while i < len(g:paras) + if g:ptype[i] =~ '^raw\(latex\|html\|both\)$' + if g:paras[i] =~ ':file:' + let file = matchstr(g:paras[i], ':file:\s*\zs.*') + let g:paras[i] = '-vst-raw-file-placeholder:'.VST_ProtectLiteral(file) + else + let g:paras[i] = '' + endif + endif + let i += 1 + endwhile +endif +" }}} +" Insert MED-classes {{{ +if string(g:ptype) =~ "'MED-class'" + let i = 0 + while i < len(g:paras) + if i == len(doc) - 1 + let nextline = i - 1 + else + let nextline = i + 1 + endif + if g:ptype[i] == 'MED-class' && g:ptype[nextline] != 'notend' + let name = g:paras[i] + let j = i + 1 + while j < len(g:paras) + if g:ptype[j] == 'notend' && g:pindent[j] == g:pindent[i] && g:paras[j] =~ '^\s*]*>') + if initial !~ 'class\s*=\s*[''"]' + let final = substitute(initial, '\(/\)\?>', ' class="'.name.'" \1>', '') + elseif initial =~ 'class\s*=\s*[''"]' + let final = substitute(initial, '\(class\s*=\s*\)\([''"]\)\(.\{-}\)\2', '\1\2\3 '.name.'\2', '') + endif + let g:paras[j] = substitute(g:paras[j], initial, final, '') + endif + let j += 1 + endif + endwhile + endif + let i += 1 + endwhile +endif +" }}} +" Nuke auxiliary elements {{{ +let i = 0 +while i < len(g:paras) + if g:ptype[i] == 'link' + let g:paras[i] = '' + elseif g:ptype[i] == 'anonlink' + let g:paras[i] = '' + elseif g:ptype[i] == 'replacement' + let g:paras[i] = '' + elseif g:ptype[i] == 'rawhtml' + let g:paras[i] = '' + elseif g:ptype[i] == 'rawlatex' + let g:paras[i] = '' + elseif g:ptype[i] == 'rawboth' + let g:paras[i] = '' + elseif g:ptype[i] == 'emptypre' + let g:paras[i] = '' + elseif g:ptype[i] == 'role' + let g:paras[i] = '' + elseif g:ptype[i] == 'MED-class' + let g:paras[i] = '' + endif + let i += 1 +endwhile +" }}} +" Create markup {{{ +let i = 0 +while i < len(g:paras) + " Careful checking if given construct exists in paragraph. + " BIG speed gains. + if g:ptype[i] !~ '^pre\|^hr\|^blank' + if g:paras[i] =~ '|' + let g:paras[i] = VST_Replacement(g:paras[i]) + endif + if g:paras[i] =~ '[*`=]' + let g:paras[i] = VST_Markup(g:paras[i]) + endif + if g:paras[i] =~ ':`' || g:paras[i] =~ '`:' + let g:paras[i] = VST_Roles(g:paras[i]) + endif + if g:paras[i] =~ '\[\d\+\]_' + let g:paras[i] = VST_Footnotes(g:paras[i]) + endif + if g:paras[i] =~ 'http' || g:paras[i] =~ 'mailto' || g:paras[i] =~ 'ftp' + let g:paras[i] = VST_SA_Hyperlink(g:paras[i]) + endif + if g:paras[i] =~ '\[#\k\+\]_' + let g:paras[i] = VST_LabelFootnote(g:paras[i]) + endif + if g:paras[i] =~ '\[\k\+\]_' + let g:paras[i] = VST_Citations(g:paras[i]) + endif + endif + let i += 1 +endwhile +" }}} +" Fixing! {{{ +" +let file = join(g:paras, "\n") +" Remove commented content +" let file = substitute(file, '.\{-}', '', 'g') +" Remove replacement placeholders +let file = substitute(file, '{-vst-replace-{', '', 'g') +let file = substitute(file, '}-vst-replace-}', '', 'g') +" Glueing together dl +let file = substitute(file, '\_s\{-}', '', 'g') +" Remove li to embed lists +let file = substitute(file, '\(\_s\{-}\_.\{-}\_s*\_s*\_s*\_s*', '', 'g') +let file = substitute(file, '\_s*\_s*', '', 'g') +let file = substitute(file, '', '', 'g') +" Removing redundant \n +let file = substitute(file, '\_s*', '\n\n', 'g') +let file = substitute(file, '\n\n\n\(\s*\)', '', 'g') +" Remove double :: at the end of paragraphs indicating code in next. +let file = substitute(file, '::\(\_s*\)', ':\1', 'g') +" Remove double :: when it was the only element after list indicator +let file = substitute(file, '\s*:', '', 'g') +" Remove empty pre paragraphs +let file = substitute(file, ']\{-}>\n', '', 'g') +" Remove links created inside of image src +let file = substitute(file, '<\(vim:\)\?img\([^>]\{-}\)src="\([^<]*\)"', + \ '<\1img\2src="\3"', 'g') +" let file = substitute(file, ' \n', '', 'g') +" Remove too much of empty space at the end of footnotes +let file = substitute(file, '\n\(\)', '\1', 'g') + + +" }}} +" Restore structure from temporary variables {{{ +if len(g:paras_rez) > 0 + let g:paras = g:paras_rez[-1] + call remove(g:paras_rez, -1) +endif +if len(g:ptype_rez) > 0 + let g:ptype = g:ptype_rez[-1] + call remove(g:ptype_rez, -1) +endif +if len(g:pindent_rez) > 0 + let g:pindent = g:pindent_rez[-1] + call remove(g:pindent_rez, -1) +endif +if len(g:plinen_rez) > 0 + let g:plinen = g:plinen_rez[-1] + call remove(g:plinen_rez, -1) +endif +" }}} + +return file + +" End of VST_Structure +endfunction + +function! vst#vst#VST_Export(line1, line2, format) range " {{{ + +" VST_DictTable: creation of nice looking table from dictionary {{{ +" Description: Go through all key value pairs and create nicely looking table +" db: dictionary itself +" key: header of key column +" value: header of value column +" sort: 0/1 sort table or not +function! VST_DictTable(db, key, value, sort) + + let valmargin = 20 + let dict = a:db + let table = a:key.repeat(' ', valmargin-strlen(a:key)).a:value."\n" + if a:sort == 0 + for key in keys(dict) + if dict[key] !~ '^\s*$' + if valmargin - strlen(key) < 1 + let table .= key."\n".repeat(' ', valmargin).substitute(dict[key], '\n', ' ', 'g')."\n" + else + let table .= key.repeat(' ', valmargin - strlen(key)).substitute(dict[key], '\n', ' ', 'g')."\n" + endif + endif + endfor + else + for key in sort(keys(dict)) + if dict[key] !~ '^\s*$' + if valmargin - strlen(key) < 1 + let table .= key."\n".repeat(' ', valmargin).substitute(dict[key], '\n', ' ', 'g')."\n" + else + let table .= key.repeat(' ', valmargin - strlen(key)).substitute(dict[key], '\n', ' ', 'g')."\n" + endif + endif + endfor + endif + + "return table + call input(table) + "echo table + +endfunction +" }}} +" VST_TocTable: creation of nice looking table of contents {{{ +" Description: Go through all 3 element items in list and render them in +" nicely looking table +" list: list itself +" fcol: header of first column +" scol: header of second column +" tcol: header of third column +" sinfo: special info +function! VST_TocTable(list, fcol, scol, tcol, sinfo) + + let secmargin = 15 + let thdmargin = 40 + let table = a:fcol.repeat(' ', secmargin-len(a:fcol)) + \ .a:scol.repeat(' ',thdmargin-len(a:scol)).a:tcol."\n" + + let i = 0 + while i < len(a:list) + let [level, title, line] = a:list[i] + let title = substitute(title, '\n.\{-}$', '', '') + " Add a markers around name of section were cursor is + if !exists("a:list[i+1]") + let nextsection = line('$') + else + let nextsection = a:list[i+1][2] + endif + let title = b:vst_toc_numbers[title].' '.substitute(title, '^\s\+', '', '') + if a:sinfo >= line && a:sinfo < nextsection + let title = '[[[ '.title.' ]]]' + endif + let table .= level.' '.g:vst_headers[level].' ' + \ .repeat(' ', secmargin-len(level.g:vst_headers[level].' ')) + \ .title.repeat(' ', thdmargin-len(title)).' '.line."\n" + let i += 1 + endwhile + + return table + +endfunction +" }}} +" VST_CreateDBs: creation of databases {{{ +function! VST_CreateDBs(table) + " Preprocess table to get class of role into the same line + " Preprocessing here is nice idea for links, they don't have to be changed + " physically in document, no messing with adding/removing lines. It slow + " things down but more precise processing is Good Thing(tm) + " table: text to analyze in List form + let preproc = a:table + let i = 0 + while i < len(preproc) + if i == len(preproc) - 1 + let nextline = i - 1 + else + let nextline = i + 1 + endif + if preproc[i] =~ '^\s*\.\. role:' + if preproc[nextline] =~ '^\s*:class:' + let preproc[i] = preproc[i].' -vst-role-'.preproc[nextline] + else + let preproc[i] = preproc[i].' -vst-role-' + endif + endif + " Connect multiline link definitions + if preproc[i] =~ '^\s*\(\.\. _\|__ \)' + if preproc[nextline] !~ '^\s*\(\.\. _\|__ \)' && preproc[nextline] !~ '^\s*$' + let findent = strlen(matchstr(preproc[i], '^\s*')) + let sindent = strlen(matchstr(preproc[nextline], '^\s*')) + if (findent + 3) <= sindent + let preproc[i] = substitute(preproc[i], '\s\+$', '', '') + \.substitute(preproc[nextline], '^\s\+', '', '') + call remove(preproc, nextline) + " Turn counter down to process more than 2 lines + let i -= 1 + endif + endif + endif + let i += 1 + endwhile + + for i in range(len(preproc)) + if preproc[i] =~ '^\s*\.\. _' + " Hyperlink database + let title = tolower(matchstr(preproc[i], '_\zs.\{-}\ze:')) + let url = matchstr(preproc[i], '_.\{-}:\s*\zs.*') + let k = 1 + while url == '' && len(preproc) > (i+k) && stridx(preproc[i+k], '_') > -1 + let url = matchstr(preproc[i+k], '_.\{-}:\s*\zs.*') + let k += 1 + endwhile + unlet! k + if url =~ '@' && url !~ '^http\|^s\?ftp' + let url = 'mailto:'.url + endif + if title != '' && title != '_' + let g:vst_hlinkdb[title] = url + endif + elseif preproc[i] =~ '^\s*\.\. role' + let rolekey = matchstr(preproc[i], 'role::\s*\zs.\{-}\ze\s*-vst-role-') + let rolevalue = matchstr(preproc[i], '-vst-role-\s*:class:\s*\zs.*\ze\s*$') + if rolevalue == '' + let rolevalue = rolekey + endif + let g:vst_roledb[rolekey] = rolevalue + endif + endfor + " Add embedded reusable URIs + " I have to join and split file again to avoid problems with: links + " splitted across lines and more than one link in line + let dbfile = join(a:table) + " This is done only for links, compress white space + let dbfile = substitute(dbfile, '\s\+', ' ', 'g') + let dbtable = split(dbfile, '>`_[^_]') + let i = 0 + while i < len(dbtable)-1 + " Hyperlink database + let expr= matchstr(dbtable[i], '.*`\zs.\{-}$') + if expr =~ '^<' + let title = tolower(matchstr(expr, '<\zs.*')) + else + let title = tolower(matchstr(expr, '\zs.\{-}\ze <.*$')) + endif + let url = matchstr(expr, ' <\zs.\{-}$') + if url =~ '@' && url !~ '^http\|^ftp' + let url = 'mailto:'.url + endif + if title != '' + let g:vst_hlinkdb[title] = url + endif + let i += 1 + endwhile + +endfunction +" }}} +" VST_FoldText: Create text for folds {{{ +function! VST_FoldText() + let text = getline(v:foldstart) + let length = v:foldend - v:foldstart + let indent = '+'.v:folddashes.repeat(' ', 5-len(length)).length + \ .' lines: ' + let line = b:vst_fold_numbers[text].' '.substitute(text, '^\s\+', '', '') + let symbol = repeat(' ', 50-len(line)).'(' + \ .matchstr(getline(v:foldstart+1), '^\s*\zs...\ze').')' + return indent.repeat(' ', 15-len(indent)).line.symbol.' ' +endfunction +" }}} +" VST_ColNumbers: Create tags for HTML {{{ +" numbers - values for width of columns, String with + to separate numbers +function! VST_ColNumbers(numbers) + let widths = split(a:numbers, '+') + let col_string = '' + for width in widths + let col_string .= '' + endfor + return col_string +endfunction +" }}} + +" Auxiliary functions: {{{ +" Unicode2Char: Return char according to hex code {{{ +" nr - decimal value of Unicode character +function! Unicode2Char(nr) + let n = join(reverse(split(tolower(a:nr), '.\zs')), '') + + let r = 0 + let i = 0 + while i <= len(n) + if n[i] == 'a' + let p = 10 + elseif n[i] == 'b' + let p = 11 + elseif n[i] == 'c' + let p = 12 + elseif n[i] == 'd' + let p = 13 + elseif n[i] == 'e' + let p = 14 + elseif n[i] == 'f' + let p = 15 + else + let p = n[i] + endif + + if p == 0 + let fp = 0 + else + exe 'let fp = '.repeat('16*', i).p + endif + + let r += fp + + let i += 1 + endwhile + return nr2char(r) +endfunction +" }}} +" VST_2html: Parse 2html directive {{{ +" Description: Go through document looking for 2html directives, copy text of +" directive to new buffer and process it there with 2html.vim, at the end +" replace original text with colored text and additional ', '\n
', '')
+		else
+			let @z = substitute(@z, '.*', '\n
', '')
+		endif
+		silent exe 'buffer! '.bufnumber
+		silent exe line
+		silent! put z
+		let line3 = line('.') - 1
+		silent exe line
+		silent delete
+		silent exe line3
+		unlet! cscheme
+	endwhile
+
+	" Restore settings
+	let @z = z_rez
+	let @y = y_rez
+	if splitb == 0
+		set nosplitbelow
+	endif
+	silent exe 'buffer! '.bufnumber
+	silent exe 'colorscheme '.col_scheme
+	" Restoring 2html.vim options {{{
+	if h_number_lines == 2
+		unlet g:html_number_lines
+	else
+		let g:html_number_lines = h_number_lines
+	endif
+	if h_use_css == 2
+		unlet g:html_use_css
+	else
+		let g:html_use_css = h_use_css
+	endif
+	if h_no_pre == 2
+		unlet g:html_no_pre
+	else
+		let g:html_no_pre = h_no_pre
+	endif
+	" }}} 
+
+endfunction
+" }}}
+" VST_AddClass:	  Return class string if prev par is class (.. class::) {{{
+" Description: Check previous paragraph and in case it is class return string
+"	  class="classname", classname or ''.
+"	  parnumber - number of described paragraph
+"	  full - check if return full declaration or name only
+"	  	1 - full declaration class="classname"
+"	  	0 - name only
+"	  pre - prefix
+"	  post - suffix
+function! VST_AddClass(parnumber, full, pre, post)
+	" Escaping of special characters
+	if g:ptype[a:parnumber-1] == 'notend' && g:ptype[a:parnumber-2] == 'MED-class'
+
+		"let name = matchstr(g:paras[a:parnumber-2], '^\s*\.\. class::\s*\zs.\{-1,}\ze\s*$')
+		let name = VST_IdMaker(g:paras[a:parnumber-2])
+		if a:full == 1
+			let class = 'class="'.name.'"'
+		else
+			let class = name
+		endif
+		let class = a:pre.class.a:post
+	else
+		let class = ''
+	endif
+
+	return class
+
+endfunction
+" }}}
+" VST_AnonHyperlink: Create anonymous hyperlinks {{{
+function! VST_AnonHyperlink(text)
+	let parlines = split(a:text, '-vst-anon-hyperlink-')
+	let i = 0
+	let g:a0 = []
+	while i < len(g:vst_anonhlinkdb) 
+		if g:vst_anonhlinkdb[i] =~ '_\s*$'
+			let href = g:vst_anonhlinkdb[i]
+			let title = tolower(matchstr(href, '\(\.\. __ :\|__\)\s*\(`\?\)\zs.*\ze\2_\s*$'))
+			while href =~ '_\s*$'
+				" If ends in _ it is probably indirect link, process it.
+				if has_key(g:vst_hlinkdb, title) && g:vst_hlinkdb[title] != ''
+					let href = escape(g:vst_hlinkdb[title], '&\~')
+				else
+					let href = '#l'.VST_IdMaker(title)
+				endif
+			endwhile
+		else
+			let href = matchstr(g:vst_anonhlinkdb[i], '^\s*\(\.\. __:\|__\)\s*\zs.*')
+		endif
+		let g:a0 += [href]
+		if i < len(parlines) - 1
+			let parlines[i] .= href
+		endif
+		let i += 1
+	endwhile
+	let par = join(parlines, '')
+	
+	return par
+
+endfunction
+" }}}
+" VST_AutoFootnote:  Create auto-numbered footnotes [#]_ {{{
+function! VST_AutoFootnote(text)
+	let parlines = split(a:text, '\[#]_')
+	let i = 0
+	let k = s:maxfnumber + s:maxlnumber + 1
+	while i < len(parlines)-1
+		let parlines[i] .= '['.k.']'
+		let i += 1
+		let k += 1
+	endwhile
+	let par = join(parlines, '')
+	
+	return par
+
+endfunction
+" }}}
+" VST_Citations:	 Create citations [first]_ {{{
+function! VST_Citations(text)
+	let par = substitute(a:text, '\[\(\k\{-}\)]_', '[\1]', 'g')
+	
+	return par
+endfunction
+" }}}
+" VST_CreateVerse:   Create verse paragraph ("| ") {{{
+" Description: 
+function! VST_CreateVerse(text)
+	" Escaping of special characters
+	let par = substitute(a:text, '\n\s*|\( *\)', '\="-vst-new-line-".repeat(" ", len(submatch(1)))', 'g')
+	let par = substitute(par, '^\s*|\( *\)', '\="-vst-new-line-".repeat(" ", len(submatch(1)))', 'g')
+	let par .= "\n"
+	let par = substitute(par, '-vst-new-line-', '\n', 'g')
+
+	return par
+endfunction
+" }}}
+" VST_EscapingSlash: Remove escaping backslashes {{{
+function! VST_EscapingSlash(text)
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+
+	" Special constructs for escaping:
+	" \*	   -> *
+	" \`	   -> `
+	" \=	   -> = (commented)
+	" \ -> 
+	" \-	   ->  
+	"
+	" To escape backslash, use backslash:
+	" \\*, \\, \\-
+	
+	" Remove single escaping backslash before letters and digits which can form
+	" lists enumerators:
+	let par = substitute(par, '\\\@
+	let par = substitute(par, '\\\@ 0
+		let par = ''.a:text.''
+	else
+		let par = a:text
+	endif
+
+	return par
+endfunction
+" }}}
+" VST_FirstLine:	 Returns first and only first line " {{{
+" without trailing spaces of given text
+function! VST_FirstLine(text)
+	return matchstr(a:text, '^\s*\ze.\{-}\ze\s*\(\n\|$\)')
+
+endfunction
+" }}}
+" VST_Footnotes:	 Create footnotes [\d\+]_ {{{
+function! VST_Footnotes(text)
+	let parlines = split(a:text, '\(\[\d\+\]\)\@<=_')
+	let j = 0
+	for parline in parlines
+		let parlines[j] = substitute(parlines[j], '\[\(\d\+\)]$', '\0', '')
+		let j += 1
+	endfor
+	let par = join(parlines, '')
+	
+	return par
+
+endfunction
+" }}}
+" VST_Hyperlink:	 Create inline `markup of hyperlinks`_ " {{{
+function! VST_Hyperlink(text)
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+	" Technical spaces
+	" Adding spaces at the end and start of paragraph isn't elegant but
+	" catching of ^ and $ in regexps by \| is very expensive.
+	let par = ' '.par.' '
+	" `Inline external anchors`_
+	if par =~ '__'
+		" Embedded anonymous hyperlinks, Note: second space is nonbreaking
+		" space \x160
+		let par = substitute(par, "[-  '\"([{]\\@<=`\<\\(.\\{-1,}\\)\>`__[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".VST_ProtectLiteral(submatch(1)).""', 'g')
+		let par = substitute(par, "[-  '\"([{]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\) \<\\(.\\{-1,}\\)\>`__[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".submatch(1).submatch(2).""', 'g')
+		" Multi word anon hyperlink (enclosed in backticks)
+		let par = substitute(par, "[-  '\"([{]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`__[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".submatch(1).submatch(2).""', 'g')
+		" One word anon hyperlink
+		let par = substitute(par, "[-  '\"([{]\\@<=\\([[:alnum:]._-]\\{-2,}\\)__[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+		let par = substitute(par, "[-  '\"([{]\\@<=\\(\\k\\{-1,}\\)__[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+	endif
+	" Embedded hyperlinks
+	let par = substitute(par, "[-  '\"([{]\\@<=`\<\\([^`]\\{-1,}\\)\>`_[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".VST_ProtectLiteral(submatch(1)).""', 'g')
+	let par = substitute(par, "[-  '\"([{]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\) \<\\(.\\{-1,}\\)\>`_[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".submatch(1).submatch(2).""', 'g')
+	" Multi word hyperlink (enclosed in backticks)
+	let par = substitute(par, "[-  '\"([{]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`_[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\="".submatch(1).submatch(2).""', 'g')
+	" One word hyperlink
+	let par = substitute(par, "[-  '\"([{]\\@<=\\([[:alnum:]._-]\\{-2,}\\)_[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  '\"([{]\\@<=\\(\\k\\{-1,}\\)_[\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+
+	" Strange splitting is necessary to be sure it will be unique and only one
+	" hyperlink per element.
+	let parlines = split(par, 'vim:a h')
+	let j = 0
+	for parline in parlines
+		if parline =~ '^refext='
+			let title = tolower(matchstr(parlines[j], '^refext="\zs.\{-}\ze"'))
+			let title = substitute(title, '\s\+-vst-new-line-\s\+', ' ', 'g')
+			" There was already some processing in text, while data in hlinkdb
+			" is in its crude form. I need to reverse some changes to match
+			" them:
+			let title = substitute(title, '&', '\&', 'g')
+			let title = substitute(title, '<', '<', 'g')
+			let title = substitute(title, '>', '>', 'g')
+			let title = substitute(title, '©', '(c)', 'g')
+			let title = substitute(title, '@', '@', 'g')
+
+			if has_key(g:vst_hlinkdb, title) && g:vst_hlinkdb[title] != ''
+				let href = escape(g:vst_hlinkdb[title], '&\~')
+				if href =~ '_\s*$'
+					while href =~ '_\s*$'
+						" If ends in _ it is probably indirect link, process it
+						" We need to remove _ from the end to get proper key name.
+						let shref = tolower(matchstr(href, '^\s*\(`\?\)\zs.*\ze\1_\s*$'))
+						if has_key(g:vst_hlinkdb, shref) && g:vst_hlinkdb[shref] != ''
+							let href = escape(g:vst_hlinkdb[shref], '&\~')
+						else
+							let href = '#l'.tolower(VST_IdMaker(shref))
+						endif
+					endwhile
+				else
+					let href = escape(g:vst_hlinkdb[title], '&\~')
+				endif
+			else
+				let href = '#l'.VST_IdMaker(title)
+			endif
+			let parlines[j] = substitute(parlines[j], '^refext=".\{-}"', 'ref="'.href.'"', 'g') 
+			let parlines[j] = substitute(parlines[j], 'title="\(.\{-}\)"', '\="title=\"".substitute(submatch(1), " -vst-new-line-\s*", " ", "g")."\""', 'g') 
+		endif
+		let j += 1
+	endfor
+	let par = join(parlines, 'vim:a h')
+
+	let par = substitute(par, '^ ', '', '')
+	let par = substitute(par, ' $', '', '')
+	let par = substitute(par, ' -vst-new-line- ', '\n', 'g')
+	" Without this regexp new line placeholders wouldn't be removed from
+	" broken embedded URIs
+	let par = substitute(par, ' -vst-new-line-\(\S\)', '\1', 'g')
+
+	return par
+endfunction
+" }}}
+" VST_IdentifyImage: Return dimensions of image {{{
+function! VST_IdentifyImage(imagename, line)
+	let iscale = matchstr(a:line, ':identify:\s*\zs.\{-}\ze\s*$')
+	let istring = system('identify -format %wx%h "'.a:imagename.'"')
+	if istring =~ '^identify'
+		let width = ''
+		let height = ''
+	endif
+	" identify may return new line char at the end breaking some regexps in
+	" final stage.
+	let istring = substitute(istring, '\n', '', 'g')
+	let dimensions = split(istring, 'x')
+	if iscale != '' && iscale !~ '\D'
+		let width = dimensions[0]*iscale/100
+		let height = dimensions[1]*iscale/100
+	else
+		let [width, height] = dimensions
+	endif
+
+	return [width, height]
+
+endfunction
+" }}}
+" VST_IdMaker:	   Create strings used in name and href {{{
+" arguments of links
+" Description: Split string to list (necessary to escape unholy mess with
+" utf-8 && multibyte characters) and iterate through elements:
+" 	When char is \w or - leave unchanged, 
+" 	when \s change to -, 
+" 	when other use built-in char2nr() function.
+function! VST_IdMaker(str)
+  " Changing to list is necessary to escape mess with utf-8 characters
+  let link = split(a:str, '.\zs')
+  let out = ''
+  let ix = 0
+  while ix < len(link)
+	if link[ix] =~ '[a-zA-Z0-9_-]'
+		let out .= link[ix]
+	elseif link[ix] =~ '\s'
+		let out .= '-'
+	else
+		let out .= char2nr(link[ix])
+	endif
+	let ix += 1
+  endwhile
+  return out
+endfunction
+" }}}
+" VST_ImagePar:	  Process image par and return image {{{
+" Description: Process image paragraph checking options and composing vim:img
+" tag
+"	  par - image paragraph
+"	  full - is this standalone image or replacement
+"		 1 - standalone image, put tag in new line
+"		 0 - tag inline, add inline class
+function! VST_ImagePar(par, full)
+	if a:full == 1
+		let nl = "\n"
+		let inline = ''
+	else
+		" This will be inline image. No need for new line at the end of tag
+		" and we have to declare inlininess of it
+		let nl = ''
+		let inline = ' inline'
+	endif
+	let src = ''
+	let width = ''
+	let height = ''
+	let alt =  ''
+	let title = ''
+	let identify = ''
+	let align = ''
+	let scale = ''
+	let target = ''
+	let class = ''
+	let parlines = split(a:par, '\n')
+	for parline in parlines
+		let parline = substitute(parline, '^\s*', '', '')
+		if src == ''
+			let src = matchstr(parline, '\(\.\. \)\?image::\s*\zs.\{-}\ze\s*$')
+			if !filereadable(escape(src, ' \#%'))
+				let noimage = 1
+				let g:vst_error .= "No image: ".src."\n"
+			else
+				let noimage = 0
+			endif
+		endif
+		if width == ''
+			let width = matchstr(parline, ':width:\s*\zs.\{-}\ze\s*$')
+		endif
+		if height == ''
+			let height = matchstr(parline, ':height:\s*\zs.\{-}\ze\s*$')
+		endif
+		if alt == ''
+			let alt = matchstr(parline, ':alt:\s*\zs.\{-}\ze\s*$')
+		endif
+		if title == ''
+			let title = matchstr(parline, ':title:\s*\zs.\{-}\ze\s*$')
+		endif
+		if align == ''
+			let align = matchstr(parline, ':align:\s*\zs.\{-}\ze\s*$')
+		endif
+		if scale == ''
+			let scale = matchstr(parline, ':scale:\s*\zs.\{-}\ze\s*$')
+			if scale =~ '\D'
+				let scale = ''
+			endif
+		endif
+		if target == ''
+			let target = matchstr(parline, ':target:\s*\zs.\{-}\ze\s*$')
+			if target == 'self' && src != ''
+				let target = src
+			endif
+			while target =~ '_\s*$'
+				" If ends in _ it is probably indirect link, process it
+				let title = matchstr(target, '^\s*\(`\?\)\zs.*\ze\1_\s*$')
+				if has_key(g:vst_hlinkdb, title) && g:vst_hlinkdb[title] != ''
+					let href = escape(g:vst_hlinkdb[title], '&\~')
+				else
+					let href = '#l'.tolower(VST_IdMaker(title))
+				endif
+			endwhile
+		endif
+		if class == ''
+			let class = matchstr(parline, ':class:\s*\zs.\{-}\ze\s*$')
+		endif
+		if identify == ''
+			let identify = matchstr(parline, ':identify:')
+			if identify != '' 
+				if executable('identify') && noimage == 0
+					let [width, height] = VST_IdentifyImage(src, parline)
+				else
+					let [width, height] = ['', '']
+				endif
+			endif
+		endif
+	endfor
+	if src != ''
+		let tempsrc = VST_ProtectLiteral(src)
+		let src = 'src="'.tempsrc.'"'
+	endif
+	if scale != ''
+		if width != ''
+			let width = width*scale/100
+		endif
+		if height != ''
+			let height = height*scale/100
+		endif
+	endif
+	if width != ''
+		let width = ' width="'.width.'"'
+	endif
+	if height != ''
+		let height = ' height="'.height.'"'
+	endif
+	if alt != ''
+		let alt = ' alt="'.alt.'"'
+	else
+		let alt = ' alt="'.tempsrc.'"'
+	endif
+	if title != ''
+		let title = ' title="'.title.'"'
+	endif
+	if class != ''
+		if align == ''
+			let class = ' class="'.class.inline.'"'
+		else
+			let class = ' class="'.class.inline.' vst'.align.'"'
+		endif
+	else
+		if align == ''
+			if inline != ''
+				let class = ' class="inline"'
+			else
+				let class = ' '
+			endif
+		else
+			let class = ' class="vst'.align.'"'
+		endif
+	endif
+
+	if src != ''
+		if target != ''
+			if target =~ '_\s*$'
+				let address = matchstr(VST_Hyperlink(target), '^.\{-}>\ze')
+			else
+				let address = ''
+			endif
+			let para = address.nl."".nl.""
+		else
+			let para = "\n".nl
+		endif
+	else
+		let para = ''
+	endif
+	if a:full == 1
+		return "\n".para."\n"
+	else
+		return para
+	endif
+endfunction
+" }}}
+" VST_LabelFootnote: Create auto-numbered footnotes [#first]_ {{{
+function! VST_LabelFootnote(text)
+	let par = a:text
+	for label in keys(g:lfnotes)
+		let k = g:lfnotes[label] 
+		let par = substitute(par, '\[#'.label.']_', '['.k.']', 'g')
+	endfor
+	
+	unlet! k
+
+	return par
+
+endfunction
+" }}}
+" VST_Markup:		Create inline markup of text styles " {{{
+function! VST_Markup(text)
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+	" Technical spaces
+	let par = ' '.par.' '
+	" Take care about escaping of asterisk
+	let par = substitute(par, '\\\@ ]\\)", '\1\*\2', 'g')
+	let par = substitute(par, "\\(['\"]\\)\\*\\([\"']\\)", '\1\*\2', 'g')
+	" Take care about double asterisk inside of (), {}, [], '', ""
+	let par = substitute(par, "\\([[({<]\\)\\*\\*\\([])}> ]\\)", '\1\*\*\2', 'g')
+	let par = substitute(par, "\\(['\"]\\)\\*\\*\\([\"']\\)", '\1\*\*\2', 'g')
+	" Take care about backticks inside of (), {}, [], '', ""
+	let par = substitute(par, "\\([[({<]\\)`\\([])}> ]\\)", '\1\`\2', 'g')
+	let par = substitute(par, "\\(['\"]\\)`\\([\"']\\)", '\1\`\2', 'g')
+	" Take care about double backticks inside of (), {}, [], '', ""
+	let par = substitute(par, "\\([[({<]\\)``\\([])}> ]\\)", '\1\`\`\2', 'g')
+	let par = substitute(par, "\\(['\"]\\)``\\([\"']\\)", '\1\`\`\2', 'g')
+	"" **strong**, Note: second space in next 3 LOC is nonbreaking space - \x160
+	let par = substitute(par, "[-  '\"([{~]\\@<=\\*\\* \\@/\\:\\.,;!?]\\@=", '\1', 'g')
+	"" *emph*
+	let par = substitute(par, "[-  '\"([{~]\\@<=\\* \\@/\\\:.,;!?]\\@=", '\1', 'g')
+	"" ``literal`` ( like), ``code``, Note: space after :space: is
+	" nonbreaking space, not included into :space:
+	let par = substitute(par, "[-  '\"([{~]\\@<=``\\([^[:space:] ]\\)\\(.\\{-}\\)``[\\]<\\-  '\")}>/\\\:.,;!?]\\@=", '\="".VST_ProtectLiteral(submatch(1).submatch(2)).""', 'g')
+
+	let par = substitute(par, ' -vst-new-line- ', '\n', 'g')
+
+	" Restore escaped asterisk
+	let par = substitute(par, '-vst-escape-asterisk-', '\\*', 'g')
+	" Restore asterisks
+	let par = substitute(par, '*', '*', 'g')
+	" Restore backticks
+	let par = substitute(par, '`', '`', 'g')
+	" Remove technical spaces
+	let par = substitute(par, ' $', '', '')
+	let par = substitute(par, '^ ', '', '')
+
+
+	return par
+endfunction
+" }}}
+" VST_ProtectLiteral: Change special chars inside of literals into entities {{{
+" Description: take text from submatch and change meaningful characters into
+" entities.
+function! VST_ProtectLiteral(text)
+	" Escaping of special characters
+	"let par = substitute(a:text, "[[`\_|:]", '\="\&#".char2nr(submatch(0)).";"', 'g')
+	let par = substitute(a:text, '`', '\`', 'g')
+	let par = substitute(par, '[', '\[', 'g')
+	let par = substitute(par, '\', '\\', 'g')
+	let par = substitute(par, '_', '\_', 'g')
+	let par = substitute(par, '|', '\|', 'g')
+	" : is required part of raw links, if we don't want to convert them,
+	" "remove" colon
+	let par = substitute(par, ':', '\:', 'g')
+
+	return par
+endfunction
+" }}}
+" VST_RemoveTags:	 Returns given string without vim tags {{{
+function! VST_RemoveTags(text)
+	return substitute(a:text, '<.\?vim:[^>]\{-}>', '', 'g')
+
+endfunction
+" }}}
+" VST_Replacement:   Resolve |replacements| into full text {{{
+function! VST_Replacement(text)
+
+	let par = a:text
+	" Loop through entries in replacedb 
+	" keys and values have to be proper Vim regexp constructs
+	for key in keys(g:vst_replacedb)
+		let replace = g:vst_replacedb[key]
+		"let replace = escape(g:vst_replacedb[key], '\&~')
+		" [^:] blocks processing of reST style image replacement
+		if replace =~ '^image:[^:]'
+			" Old style image, deprecated {{{
+			" Create image. We have here one line of pairs term:definition,
+			" but definition can be a string with spaces embraced in quotes.
+			" image:src with:420 alt:"this image"
+			let img = substitute(replace, '\(\w\+\):', ',"\1":', 'g') 
+			let img = substitute(img, ':\([^"].\{-}\)\( \|$\)', ':"\1"', 'g') 
+			let img = '{'.substitute(img, '^\s*,', '', 'g').'}'
+			unlet! g:image
+			let g:image = eval(img)
+			let replace = ''.replace.''
+			endif
+			let par = substitute(par, '|'.key.'|', replace, 'g')
+			" }}}
+		elseif replace =~ '^replace::'
+			" Plain replace {{{
+			if replace =~ ':ltrim:'
+				let ltrim = '\s*'
+				let rtrim = ''
+			elseif replace =~ ':trim:'
+				let ltrim = '\s*'
+				let rtrim = '\s*'
+			elseif replace =~ ':rtrim:'
+				let ltrim = ''
+				let rtrim = '\s*'
+			else
+				let ltrim = ''
+				let rtrim = ''
+			endif
+			" Process special characters in key: lt, gt, amp
+			" They were already processed in text
+			let key = substitute(key, '&', '\&', 'g')
+			let key = substitute(key, '<', '\<', 'g')
+			let key = substitute(key, '>', '\>', 'g')
+			let replace = matchstr(replace, '^replace::\s*\zs.\{-}\ze\_s*\(\.\. \|:trim:\|:ltrim:\|:rtrim:\|$\)')
+			"let replace = matchstr(replace, '^replace::\s*\zs.\{-}\ze\s*$')
+			let replace = escape(VST_SpecCharacter(replace), '&~\')
+			if par =~ '|_'
+				" Placeholder necessary to later trigger markup commands
+				let par = substitute(par, ltrim.'|'.key.'|__'.rtrim, '`{-vst-replace-{'.replace.'}-vst-replace-}`__', 'g')
+				let par = substitute(par, ltrim.'|'.key.'|_'.rtrim, '`{-vst-replace-{'.replace.'}-vst-replace-}`_', 'g')
+				if has_key(g:vst_hlinkdb, key)
+					" replace can contain markup - in text it will be proceed,
+					" in db no. Force 
+					let proceed = VST_Markup(replace)
+					let proceed = VST_Roles(proceed)
+					let proceed = VST_EscapingSlash(proceed)
+					" And remove tags!
+					let proceed = substitute(proceed, '<.\?vim:[^>]\{-}>', '', 'g')
+					let g:vst_hlinkdb[tolower(proceed)] = g:vst_hlinkdb[key]
+				endif
+			endif
+			let par = substitute(par, ltrim.'|'.key.'|'.rtrim, replace, 'g')
+			" }}}
+		elseif replace =~ '^unicode::'
+			" Unicode {{{
+			if replace =~ ':ltrim:'
+				let ltrim = '\s*'
+				let rtrim = ''
+			elseif replace =~ ':trim:'
+				let ltrim = '\s*'
+				let rtrim = '\s*'
+			elseif replace =~ ':rtrim:'
+				let ltrim = ''
+				let rtrim = '\s*'
+			else
+				let ltrim = ''
+				let rtrim = ''
+			endif
+			let g:vst_encoding = "utf-8"
+			" We need this interference - without that character would be
+			" inserted improperly
+			let origenc = &encoding
+			set encoding=utf-8
+			let key = substitute(key, '&', '\&', 'g')
+			let key = substitute(key, '<', '\<', 'g')
+			let key = substitute(key, '>', '\>', 'g')
+			let replace = matchstr(replace, '^unicode::\s*\zs.\{-}\ze\s*\(\.\. \|:trim:\|:ltrim:\|:rtrim:\|$\)')
+			let replace = substitute(replace, '\(0x\|x\|\\x\|U+\|u\|\\u\|&#x\)\([0-9a-fA-F]\+\)', '\=Unicode2Char(submatch(2))', 'g')
+			let replace = substitute(replace, '\_s' , '', 'g')
+			let replace = escape(VST_SpecCharacter(replace), '&~\')
+			if par =~ '|_'
+				let par = substitute(par, '|'.key.'|__', '`'.replace.'`__', 'g')
+				let par = substitute(par, '|'.key.'|_', '`'.replace.'`_', 'g')
+				if has_key(g:vst_hlinkdb, key)
+					" replace can contain markup - in text it will be proceed,
+					" in db no. Force 
+					let proceed = VST_Markup(replace)
+					let proceed = VST_Roles(proceed)
+					let proceed = VST_EscapingSlash(proceed)
+					" And remove tags!
+					let proceed = substitute(proceed, '<.\?vim:[^>]\{-}>', '', 'g')
+					let g:vst_hlinkdb[tolower(proceed)] = g:vst_hlinkdb[key]
+				endif
+			endif
+			"let par = substitute(par, ltrim.'|'.key.'|__'.rtrim, '`'.replace.'`__', 'g')
+			"let par = substitute(par, ltrim.'|'.key.'|_'.rtrim, '`'.replace.'`_', 'g')
+			let par = substitute(par, ltrim.'|'.key.'|'.rtrim, replace, 'g')
+			let &encoding = origenc
+			" }}}
+		elseif replace =~ '^image::'
+			" Image replacement {{{
+			let replace = VST_ImagePar(replace, 0)
+			let replace = escape(replace, '&~\')
+			let par = substitute(par, '|'.key.'|', replace, 'g')
+			" }}}
+		elseif replace =~ '^date::'
+			" Date replacement {{{
+			let replace = matchstr(replace, 'date::\s*\zs.*$')
+			let replace = substitute(replace, '\s*$', '', '')
+			if exists("*strftime")
+				if replace == ''
+					let replace = strftime("%Y-%m-%d")
+				else
+					let replace = strftime(replace)
+				endif
+			else
+				let replace = localtime()
+			endif
+
+			let replace = escape(replace, '&~\')
+			let par = substitute(par, '|'.key.'|', replace, 'g')
+			" }}}
+		elseif replace =~ '^\w\+::'
+			" Don't perform replacement of reST style replacement directives.
+			" This can cause big mess.
+			continue
+		endif
+	endfor
+
+
+	return par
+endfunction
+" }}}
+" VST_Roles:		 Change text :roles: into proper tags " {{{
+function! VST_Roles(text)
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+	" Technical spaces
+	let par = ' '.par.' '
+	" :sub:`text` and `text`:sub:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:sub:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:sub:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=:subscript:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:subscript:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :sup:`text` and `text`:sup:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:sup:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:sup:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=:superscript:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:superscript:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :strong:`text` and `text`:strong:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:strong:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:strong:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :emphasis:`text` and `text`:emphasis:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:emphasis:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:emphasis:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :literal:`text` and `text`:literal:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:literal:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:literal:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :big:`text` and `text`:big:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:big:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:big:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :small:`text` and `text`:small:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:small:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:small:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" :title-reference:, :title:, :t:
+	let par = substitute(par, "[-  `'\"([{]\\@<=:title-reference:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=:title:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=:t:`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:title-reference:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:title:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:t:[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\1', 'g')
+	" any other role
+	let par = substitute(par, "[-  `'\"([{]\\@<=:\\(\\S\\+\\):`\\([^`]\\{-1,}\\)`[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\=VST_ExtraRoles(submatch(1), submatch(2))', 'g')
+	let par = substitute(par, "[-  `'\"([{]\\@<=`\\([^`]\\{-1,}\\)`:\\(\\S\\+\\):[\\]\\-  '\")}<>/\\\:.,;!?]\\@=", '\=VST_ExtraRoles(submatch(1), submatch(2))', 'g')
+
+	let par = substitute(par, ' -vst-new-line- ', '\n', 'g')
+	" Remove technical spaces
+	let par = substitute(par, ' $', '', '')
+	let par = substitute(par, '^ ', '', '')
+
+	return par
+endfunction
+" }}}
+" VST_DefaultRole:		 Change `default roles` into proper tags " {{{
+function! VST_DefaultRole(text)
+
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+	" Technical spaces
+	let par = ' '.par.' '
+
+	" Take care about backticks inside of (), {}, [], '', ""
+	let par = substitute(par, "\\([['\"({<]\\)`\\([])}>\"']\\)", '\1\`\2', 'g')
+
+	let split_file = split(par, '\(^\|-vst-new-line-\)\s*\.\. default-role::\s*')
+
+	if len(split_file) == 1
+		let roled = substitute(split_file[0], "[-  '\"([{;]\\@<=`\\([^[:space:] `]\\)\\(.\\{-}\\)`[`\\]<\\-  '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+	else
+		for i in range(len(split_file))
+
+			if i == 0
+				let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:]`]\\)\\(.\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+			else
+				let role = matchstr(split_file[i], '^.\{-}\ze\s\+-vst-new-line- ')
+				let split_file[i] = substitute(split_file[i], '^.\{-}-vst-new-line- ', '', '')
+				if role =~ '^\(t\|title\|title-reference\)$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^sup\(erscript\)\?$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^sub\(script\)\?$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^strong$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^emphasis$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^literal$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^big$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				elseif role =~ '^small$'
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				else
+					let role = VST_IdMaker(role)
+					let split_file[i] = substitute(split_file[i], "[- '\"([{;]\\@<=`\\([^[:space:] `]\\)\\([^`]\\{-}\\)`[`\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+				endif
+			endif
+		endfor
+		let roled = join(split_file, "\n")
+	endif
+
+	let par = substitute(roled, ' -vst-new-line- ', '\n', 'g')
+	" Restore backticks
+	let par = substitute(par, '`', '`', 'g')
+	" Remove technical spaces
+	let par = substitute(par, ' $', '', '')
+	let par = substitute(par, '^ ', '', '')
+
+	return par
+endfunction
+" }}}
+" VST_SA_Hyperlink:  Process explicit hyperlinks {{{
+" Description: Find text following rules of certain protocol and change it
+" into .
+" Supported: http, https, ftp, sftp, mailto
+function! VST_SA_Hyperlink(text)
+
+	function! VST_PunctTrap(link)
+		let punctless = a:link
+		if punctless =~ '[.?!;,]$'
+			let punctless = matchstr(punctless, '.*\ze.$')
+		endif
+		return VST_ProtectLiteral(punctless)
+	endfunction
+
+	let par = a:text
+	" Handle standalone links in <> brackets.
+	let par = substitute(par, '<\(https\?://[a-zA-Z0-9./%&@#:;?=_-]\+\)>\(`_\)\@!', '\="\<".VST_ProtectLiteral(submatch(1))."\>"', 'g')
+	let par = substitute(par, '<\(s\?ftp://[a-zA-Z0-9./%&#@:;?=_-]\+\)>\(`_\)\@!', '\="\<".VST_ProtectLiteral(submatch(1))."\>"', 'g')
+	let par = substitute(par, '<mailto:\([a-zA-Z0-9@&#.;?=_-]\+\)>\(`_\)\@!', '\="\<".VST_ProtectLiteral(submatch(1))."\>"', 'g')
+
+	let par = substitute(par, '\(href="\|<\)\@".VST_ProtectLiteral(submatch(0)).""', 'g')
+	let par = substitute(par, '\(href="\|<\)\@".VST_ProtectLiteral(submatch(0)).""', 'g')
+	let par = substitute(par, '\(href="\|<\)\@".VST_ProtectLiteral(submatch(2)).""', 'g')
+
+	" Remove doubled links caused by http regexps.
+	let par = substitute(par, '\(\)\1', '\1', 'g')
+	let par = substitute(par, '', '', 'g')
+	" In 99% of causes some punct chars at the end of link (.?!;,) shouldn't be
+	" there and was already catched by VST_PunctTrap
+	let par = substitute(par, '\([.?!;,]\+\)', '\1', 'g')
+
+	return par
+endfunction
+" }}}
+" VST_SpecCharacter: Change special chars into entities {{{
+" Supported: &, <, >, (c) 
+function! VST_SpecCharacter(text)
+	" Escaping of special characters
+	let par = substitute(a:text, '&\([#a-z0-9]\+;\)\@!', '\&', 'g')
+	let par = substitute(par, '\\&[#a-z0-9]', '\&#', 'g')
+	let par = substitute(par, '(c)', '\©', 'g')
+	let par = substitute(par, '@', '\@', 'g')
+	let par = substitute(par, '<', '\<', 'g')
+	let par = substitute(par, '>', '\>', 'g')
+	return par
+endfunction
+" }}}
+" VST_Target:		Create  tags for _`inline targets` {{{
+function! VST_Target(text)
+	let par = substitute(a:text, '\n', ' -vst-new-line- ', 'g')
+	" Technical spaces
+	let par = ' '.par.' '
+	" _`Inline internal targets`
+	let par = substitute(par, "[- '\"([{]\\@<=_`\\([^[:space:] `]\\)\\(.\\{-}\\)`[\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1\2', 'g')
+	let par = substitute(par, "[- '\"([{]\\@<=_\\([[:alnum:]._-]\\{-2,}\\)[\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+	let par = substitute(par, "[- '\"([{]\\@<=_\\(\\k\\{-1,}\\)[\\]<\\- '\")}>/\\:\\.,;!?]\\@=", '\1', 'g')
+	" Strange splitting is necessary to be sure it will be unique and only one
+	" hyperlink per element.
+	let parlines = split(par, 'vim:span targeti')
+	let j = 0
+	for parline in parlines
+		if parline =~ '^d='
+			let title = tolower(matchstr(parlines[j], '^d="\zs.\{-}\ze"'))
+			let href = VST_IdMaker(substitute(title, '\s\+-vst-new-line-\s\+', ' ', 'g'))
+			let parlines[j] = substitute(parlines[j], '^d=".\{-}"', 'd="l'.href.'"', 'g') 
+		endif
+		let j += 1
+	endfor
+	let par = join(parlines, 'vim:span i')
+
+	let par = substitute(par, '^ ', '', '')
+	let par = substitute(par, ' $', '', '')
+
+	let par = substitute(par, ' -vst-new-line- ', '\n', 'g')
+
+	return par
+endfunction
+" }}}
+" VST_FoldExpr: Folding expression {{{
+" lnum - current line to evaluate fold level
+function! VST_FoldExpr(lnum)
+	if getline(a:lnum) =~ "'"
+		let line = substitute(getline(a:lnum), "'", "''", 'g')
+	else
+		let line = getline(a:lnum)
+	endif
+	if b:vst_fold_lvl =~ 'r'
+		if string(b:vst_flvl_1) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>1'
+		elseif string(b:vst_flvl_2) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>2'
+		elseif string(b:vst_flvl_3) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>3'
+		elseif string(b:vst_flvl_4) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>4'
+		elseif string(b:vst_flvl_5) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>5'
+		elseif string(b:vst_flvl_6) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+			return '>6'
+		else
+			return '='
+		endif
+	endif
+	"let list = keys(b:vst_fold)
+	let list = keys(b:vst_fold_list)
+	if string(list) =~? "[[ ]'".escape(line, '.*\[~&^$')."'[],]"
+		return '>1'
+	else
+		return '1'
+	endif
+endfunction
+" }}}
+" VST_D: simple debug {{{
+" Description: echo structure of document in form of list:
+"   )  
+function! VD()
+	for i in range(len(g:paras))
+		"echo i.') '.g:pindent[i].'  '.g:ptype[i].'  '.split(g:paras[i], "\n")[0]."\n"
+		echo i.') '.g:pindent[i].'  '.g:ptype[i].'  '."\n"
+	endfor
+endfunction
+" }}}
+" VST_End: remove unnecessary global variables and other garbage {{{
+" Description: function unlet! g:vars which may clash in next calls of VST
+" functions
+function! VST_End()
+	unlet! g:paras g:paras_rez
+	unlet! g:pindent g:pindent_rez
+	"unlet! g:ptype g:ptype_rez
+	unlet! g:plinen g:plinen_rez
+	unlet! g:vst_recursion
+	unlet! g:vst_doc_title
+endfunction
+" }}}
+" }}}
+
+	" Initialize error message
+	let g:vst_error = ''
+
+	" Source project file
+	if filereadable("vstrc.vim")
+		source vstrc.vim
+	endif
+
+	" We don't need freaking tabs!
+	setlocal expandtab
+	retab
+
+	" For proper working of script nocompatible has to be set but setting it
+	" explicitly may break other settings which usually don't disturb
+	if &compatible == 1
+		set nocompatible
+	endif
+
+	let format = tolower(a:format)
+
+	if format == ''
+		let format = 'html'
+	endif
+
+	let text = getline(a:line1, a:line2)
+
+	" Include external files before anything else will be done {{{
+	" But only for "real" export
+	if ',pdf,xml,html,s5,latex,tex,preproc,' =~ ','.format.','
+	let rec_counter = 0
+	while rec_counter < &maxfuncdepth/2
+		" if len(filter(copy(text), 'v:val =~ "^\\s*\\.\\. \\(header\\|include\\|footer\\)::"')) > 0
+		" Tried to do in one regexp, but its alternative was sometimes working, sometimes not
+		" Note: it always works... even inside of preformatted text
+		let isinclude = len(filter(copy(text), 'v:val =~ "^\\s*\\.\\. include::"'))
+		let isheader = len(filter(copy(text), 'v:val =~ "^\\s*\\.\\. header::"'))
+		let isfooter = len(filter(copy(text), 'v:val =~ "^\\s*\\.\\. footer::"'))
+		" End loop when there are no including commands, save up to 100
+		" filtering
+		if isinclude == 0 && isheader == 0 && isfooter == 0
+			break
+		endif
+		if isinclude > 0 || isheader > 0 || isfooter > 0
+			let i = 0
+			while i < len(text)
+				if text[i] =~ '^\s*\.\. \(header\|include\|footer\)::'
+					let include = matchlist(text[i], '^\(\s*\)\.\. \(header\|include\|footer\)::\s*\(.*\)\s*$')
+					" Do nothing if file isn't readable, general VST policy:
+					" silently ignore all author errors.
+					
+					if include[3] =~ '^<' && include[3] =~ '>$'
+						let include[3] = matchstr(include[3], '^.\zs.*\ze.$')
+						let include[3] = g:vst_included.'/'.include[3]
+					endif
+					" let inc_indent = len(include[1])
+					" EXPERIMENTAL: change \ into / - windows separator into
+					" unix separator and vice versa depending on running
+					" system
+					if has("win16") || has("win32") || has("win64") || has("win95") || has("dos16") || has("dos32")
+						let include[3] = substitute(include[3], '/', '\\', 'g')
+					else
+						let include[3] = substitute(include[3], '\\', '/', 'g')
+					endif
+					if filereadable(include[3])
+						let included = readfile(include[3])
+						call map(included, 'include[1].v:val')
+						if include[2] == 'header'
+							let text[i] = ''
+							let included += ['']
+							call extend(text, included, 0)
+						elseif include[2] == 'footer'
+							let text[i] = ''
+							let included = [''] + included
+							call extend(text, included)
+						else
+							let text[i] = ''
+							call extend(text, included, i+1)
+						endif
+					elseif include[3] == 'vstfooter' || include[3] == ''
+						if exists("*strftime")
+							let date = strftime("%c")
+						else
+							let date = "Unknown"
+						endif
+						let included = ['.. block:: vstfooter', '', '   -----------------------',
+							\ '', '   Vim reStructured Text document. Generated: '.date
+							\.'. `View VST source`_', '', 
+							\ '   .. _view VST source: '.expand("%"),'']
+						call extend(text, included)
+						let text[i] = ''
+					elseif include[2] =~ 'header\|footer' && text[i-2] !~ '::\s*$'
+						" Second part of above condition is hack to allow for
+						" proper compilation of f/h examples. Simple test should
+						" cover most of them.
+						if include[2] == 'footer'
+							let text[i] = ''
+							if format !~ 's5'
+								let included = ['.. block:: vstfooter','', '   ------------------------',
+									\ '', '   '.VST_ProtectLiteral(include[3]), '']
+								call extend(text, included)
+							else
+								let s5footer = VST_ProtectLiteral(include[3])
+							endif
+						elseif include[2] == 'header'
+							let text[i] = ''
+							let included = ['.. block:: vstfooter','', '   '.VST_ProtectLiteral(include[3]),
+								\ '', '   ------------------------', '']
+							call extend(text, included, 0)
+						endif
+					else
+						if include[3] !~ '^{.*}$'
+							let text[i] = ''
+							let included = [include[1].'.. Unknown file: '.VST_ProtectLiteral(include[3]), 
+								\ '', include[1].'..']
+							call extend(text, included, i+1)
+						endif
+					endif
+					if exists('included')
+						let i += len(included)
+					endif
+				endif
+				let i += 1
+			endwhile
+		endif
+		let rec_counter += 1
+	endwhile
+	unlet! rec_counter
+	endif
+	" }}}
+	" Preprocess text to ... 	{{{
+	" But not for preproc export:
+	if format !~ '^pre'
+	" Separate preprocessing for modeline correction
+	" Not elegant but prevents from messing with last element in main loop
+	" This take care about modeline in last line
+	" Remove filetype setting from modeline to not confuse Vim in exported
+	" files
+	for i in range(&modelines+1) + range(len(text)-&modelines, len(text)-1) 
+		if get(text, i) != ''
+			if text[i] =~ '^\s*\.\. vim:.*re\?st'
+				let text[i] = substitute(text[i], '\s\?\%(filetype\|ft\)=re\?st', '', 'g')
+				if text[i] =~ 'vim:\s*\(set\)\?\s*:\?\s*$'
+					let text[i] = ''
+				endif
+			endif
+		endif
+	endfor
+	" We need to keep track of real lines. Create hash with keys of virtual
+	" lines created by preprocessing and real lines
+	let i = 0
+	let g:vst_reallines = {}
+	let rl_correction = 0
+	while i < len(text)-1
+		" Remove control characters, some Emacs deviation
+		if text[i] =~ '[[:cntrl:]]'
+			let text[i] = substitute(text[i], '[[:cntrl:]]', '', 'g')
+		endif
+		" If comment directive is empty and following line is blank change
+		" it to .. comment:: directive. In this way indentation still will be
+		" taken into account
+		if text[i] =~ '^\s*\.\.\s*$' && text[i+1] =~ '^\s*$'
+			let text[i] = substitute(text[i], '^\(\s*\.\.\)', '\1 comment::', '')
+		endif
+		" Insert blank line between one line directives
+		if text[i] =~ '^\s*\(\.\.\|__\) ' && text[i+1] =~ '^\s*\(\.\.\|__\) '
+			let findent = strlen(matchstr(text[i], '^\s*'))
+			let sindent = strlen(matchstr(text[i+1], '^\s*'))
+			" But only if those .. are on the same level of indentation
+			if findent == sindent
+				call insert(text, '', i+1)
+				let rl_correction -= 1
+			endif
+		endif
+		" Insert blank line between option of directive and directive in next
+		" line
+		if text[i] =~ '^\s\+:\w\+:' && text[i+1] =~ '^\s*\.\. '
+			let findent = strlen(matchstr(text[i], '^\s*'))
+			let sindent = strlen(matchstr(text[i+1], '^\s*'))
+			" But only if option has bigger indentation than directive
+			if (sindent + 3) <= findent
+				call insert(text, '', i+1)
+				let rl_correction -= 1
+			endif
+		endif
+		" Insert blank line between named admonition and unordered|ordered
+		" list in next line Have to be splitted in two if's because || is
+		" horrible ineffective.  
+		" LISTDEF: here is list definition which may require adjustment
+		if text[i] =~? '^\s*\.\. \(note\|tip\|warning\|attention\|caution\|danger\|error\|hint\|important\|admonition\)::\s*$' && text[i+1] =~ '^\s*'.s:vst_bulletdef.'\s'
+			let findent = strlen(matchstr(text[i], '^\s*'))
+			let sindent = strlen(matchstr(text[i+1], '^\s*'))
+			" But only if list has bigger indentation than directive
+			if (findent + 3) <= sindent
+				call insert(text, '', i+1)
+				let rl_correction -= 1
+			endif
+		endif
+		if text[i] =~? '^\s*\.\. \(note\|tip\|warning\|attention\|caution\|danger\|error\|hint\|important\|admonition\)::\s*$' && text[i+1] =~ '^\s*\(\d\+\|[a-zA-Z]\|[icdvlmxICDVLMX]\+\|#\)[\]:.)}]\s'
+			let findent = strlen(matchstr(text[i], '^\s*'))
+			let sindent = strlen(matchstr(text[i+1], '^\s*'))
+			" But only if list has bigger indentation than directive
+			if (findent + 3) <= sindent
+				call insert(text, '', i+1)
+				let rl_correction -= 1
+			endif
+		endif
+		let i += 1
+		let g:vst_reallines[i] = i + rl_correction
+	endwhile
+	" In main loop we are not interested in last item, here add correction for
+	" this
+	let g:vst_reallines[i+1] = i + 1 + rl_correction
+	endif
+	" }}}
+	" Initiate variables for non export specific databases: {{{
+	let g:vst_headers = {}
+	let g:vst_hlinkdb = {}
+	let g:vst_replacedb = {}
+	let g:vst_roledb = {}
+
+	" }}}
+
+	let g:vst_anonhlinkdb = filter(copy(text), 'v:val =~ "^\\s*\\(\\.\\. __:\\|__ \\)"')
+	if ',pdf,xml,html,s5,latex,tex,' =~ ','.format.','
+		let g:vst_footnotedb = {}
+		let g:vst_citationdb = {}
+		let g:vst_fielddb = {}
+		let g:vst_metadb = {}
+
+		unlet! g:vst_encoding
+
+		" Necessary for working of labels
+		if '-' !~ '\k'
+			let b:vst_hyphenisk = 1
+			set isk+=-
+		else
+			let b:vst_hyphenisk = 0
+		endif
+
+		" Main function
+		let file = VST_Structure(text)
+
+		unlet! b:vst_afs
+		unlet! b:vst_first_parsing
+
+		if file =~ '\[#\]_'
+			let file = VST_AutoFootnote(file)
+		endif
+
+		" Process hyperlinks {{{
+		let lines = split(file, '\"' ]\\)", '\1\`\2', 'g')
+				let lines[i] = substitute(lines[i], "\\([['\"({<]\\)_`\\([])}>\"' ]\\)", '\1_\`\2', 'g')
+				" Take care about "``"
+				let lines[i] = substitute(lines[i], '"``"', '-vst-quot-dbacktick-', 'g')
+				" Take care about alone _ and __
+				let lines[i] = substitute(lines[i], ' _ ', ' \_ ', 'g')
+				let lines[i] = substitute(lines[i], ' __ ', ' \_\_ ', 'g')
+				" Take care about __ in programmer expressions __init__ like (shaky)
+				let lines[i] = substitute(lines[i], '\([[:punct:][:space:] ]\)__\(\k*\)__\([[:punct:][:space:] ]\?\)', '\1\_\_\2\_\_\3', 'g')
+				" Ugly, ugly, prevent from linkination of ".. __:" in text
+				let lines[i] = substitute(lines[i], ' __\(\S\)', ' \_\_\1', 'g')
+				" Take care about anonymous references
+				let lines[i] = substitute(lines[i], "\\([['\"({<]\\)__\\([])}>\"' ]\\)", '\1\_\_\2', 'g')
+				" Take care about "``"
+
+				" Main hyperlink processing
+				let lines[i] = VST_Hyperlink(lines[i])
+				let lines[i] = VST_Target(lines[i])
+
+				" Restore \`
+				let lines[i] = substitute(lines[i], '-vst-escape-backtick-ddash-', '\\`__', 'g')
+				let lines[i] = substitute(lines[i], '-vst-escape-backtick-dash-', '\\`_', 'g')
+				let lines[i] = substitute(lines[i], '-vst-escape-backtick-', '\\`', 'g')
+				" Take care about "``"
+				let lines[i] = substitute(lines[i], '-vst-quot-dbacktick-', '"``"', 'g')
+				" Restore ` and _
+				let lines[i] = substitute(lines[i], '`', '`', 'g')
+				let lines[i] = substitute(lines[i], '_', '_', 'g')
+
+			endif
+			"if lines[i] =~ '\\'
+			"	let lines[i] = VST_EscapingSlash(lines[i])
+			"endif
+			let i += 1
+		endwhile
+		let file = join(lines, '_', '_', 'g')
+		" Sometimes regexps are catching \` as link. Remove such glitches
+		let file = substitute(file, '\\`', '\\`', 'g')
+		" }}}
+		" Create footnote and citation dbs: {{{
+		" Go with stridx and strpart cutting file and retrieve information.
+		" Necessary for LaTeX export.
+		let fn = file
+		while stridx(fn, '\[\zs\d\+\ze\]')
+			let content = matchstr(fn, '\zs.\{-}\ze\_s*')
+			let g:vst_footnotedb[number] = content
+			let fn = strpart(fn, 2)
+		endwhile
+		let fn = file
+		while stridx(fn, '\[\zs\k\+\ze\]')
+			let content = matchstr(fn, '\zs.\{-}\ze\_s*')
+			let g:vst_citationdb[label] = '['.label.'] '.content
+			let fn = strpart(fn, 2)
+		endwhile
+		" }}}
+
+		if len(g:vst_anonhlinkdb) > 0
+			let file = VST_AnonHyperlink(file)
+		endif
+
+		" Process default roles
+		let file = VST_DefaultRole(file)
+		" Remove escaping slashes.
+		let file = VST_EscapingSlash(file)
+
+		" Removing - from 'isk'
+		if b:vst_hyphenisk == 1
+			set isk-=-
+		endif
+		unlet! b:vst_hyphenisk
+
+		" Replace ` with `
+		let file = substitute(file, '`', '`', 'g')
+		" Replace [ with [
+		let file = substitute(file, '[', '[', 'g')
+		" Replace \ with \
+		let file = substitute(file, '\', '\\', 'g')
+		" Replace _ with _
+		let file = substitute(file, '_', '_', 'g')
+		" Replace . with .
+		let file = substitute(file, '.', '.', 'g')
+		" Replace | with |
+		let file = substitute(file, '|', '|', 'g')
+		" Replace : with :
+		let file = substitute(file, ':', ':', 'g')
+
+		" VST_URIMaker: Create real, properly encrypted URIs. {{{
+		function! VST_URIMaker(uri)
+			" Auxiliary functions lifted from eval.txt {{{
+			" The function Nr2Hex() returns the Hex string of a number.
+			func! Nr2Hex(nr)
+			  let n = a:nr
+			  let r = ""
+			  while n
+				let r = '0123456789ABCDEF'[n % 16] . r
+				let n = n / 16
+			  endwhile
+			  return r
+			endfunc
+			" The function String2Hex() converts each character in a string to a two
+			" character Hex string.
+			func! String2Hex(str)
+			  let out = ''
+			  let ix = 0
+			  while ix < strlen(a:str)
+				let out = out . Nr2Hex(char2nr(a:str[ix]))
+				let ix = ix + 1
+			  endwhile
+			  return out
+			endfunc " }}}
+			let uri = a:uri
+			if uri =~ '^#'
+				return uri
+			endif
+			" URI:
+			if uri =~ '^[-_!~*():?;@&=+$.,/a-zA-Z0-9#]*$'
+				return uri
+			else
+				let elements = split(uri, '#')
+				let first = elements[0]
+				if len(elements) > 1
+					let rest = '#'.join(elements[1:-1], '#')
+				else
+					let rest = ''
+				endif
+				let link = split(first, '.\zs')
+				let out = ''
+				let ix = 0
+				while ix < len(link)
+					if link[ix] =~ '[-_!~*():?;@&=+$.,/a-zA-Z0-9#]'
+						let out .= link[ix]
+					elseif link[ix] =~ '%'
+						" Bold assumption: all escape sequences I saw on the net
+						" were uppercased
+						if link[ix+1] =~ '[A-F0-9]' && link[ix+2] =~ '[A-F0-9]'
+							let out .= link[ix] . link[ix+1] . link[ix+2]
+							let ix = ix + 2
+						else
+							let out .= '%'.String2Hex('%')
+						endif
+					else
+						let out .= '%'.String2Hex(link[ix])
+					endif
+					let ix += 1
+				endwhile
+			endif
+			return out.rest
+		endfunction
+		" }}}
+		let file = substitute(file, 'vim:\(img src="\|a href="\)\(.\{-}\)"', '\="vim:".submatch(1).VST_URIMaker(submatch(2))."\""', 'g')
+
+		" Figure out proper MIME charset from the 'encoding' option. {{{
+		if exists("g:vst_encoding")
+			let encoding = g:vst_encoding
+		else
+			if &fileencoding != ''
+				let encoding = &fileencoding
+			else
+				let encoding = &encoding
+			endif
+		endif
+		if encoding =~ '^8bit\|^2byte'
+			let encoding = substitute(s:vim_encoding, '^8bit-\|^2byte-', '', '')
+		endif
+		if encoding == 'latin1'
+			let encoding = 'iso-8859-1'
+		elseif encoding =~ "^cp12"
+			let encoding = substitute(encoding, 'cp', 'windows-', '')
+		elseif encoding == 'sjis'
+			let encoding = 'Shift_JIS'
+		elseif encoding == 'euc-cn'
+			let encoding = 'GB_2312-80'
+		elseif encoding == 'euc-tw'
+			let encoding = ""
+		elseif encoding == 'big5'
+			let encoding = "Big5"
+		elseif encoding =~ '^euc\|^iso\|^koi'
+			let encoding = substitute(encoding, '.*', '\U\0', '')
+		elseif encoding == 'cp949'
+			let encoding = 'KS_C_5601-1987'
+		elseif encoding == 'cp936'
+			let encoding = 'GBK'
+		elseif encoding =~ '^ucs\|^utf'
+			let encoding = 'UTF-8'
+		else
+			let encoding = ""
+		endif
+		" }}}
+		let filename = expand("%:r")
+	endif
+
+	if format =~ '^\(html\|s5\)$'
+		" HTML export {{{
+
+		let language = matchstr(v:lang, '.*\ze_')
+
+		" CSS: {{{
+		let rtp = split(&rtp, ',')
+		for i in range(len(rtp))
+			if filereadable(rtp[i].'/autoload/vst/default.css')
+				let defcssfile = rtp[i].'/autoload/vst/default.css'
+				break
+			endif
+		endfor
+
+		let default_css = join(readfile(defcssfile), "\n")
+
+		" g:vst_css_default g:vst_css_user
+		if g:vst_css_default == '' && g:vst_css_user == ''
+			let css = ''
+		endif
+
+		if g:vst_css_default == '' && g:vst_css_user != ''
+			let css = ''
+			let css .= ''."\n"
+		endif
+
+		if g:vst_css_default != '' && g:vst_user_css == ''
+			if g:vst_css_default !~ 'NONE'
+				let completecss = ['/* Vim reStructured Text CSS */', ''] + split(default_css, '\n')
+				call writefile(completecss, g:vst_css_default)
+				let css = ''."\n"
+			else
+				let css = "\n"
+			endif
+		endif
+
+		if g:vst_css_default != '' && g:vst_css_user != ''
+			if g:vst_css_default !~ 'NONE'
+				let completecss = ['/* Vim reStructured Text CSS */', ''] + split(default_css, '\n')
+				call writefile(completecss, g:vst_css_default)
+				let css = ''."\n"
+			else
+				let css = "\n"
+			endif
+			let css .= ''."\n"
+		endif
+		" }}}
+
+		" META Info {{{
+		let metainfo = ''
+		let metaauthor = ''
+		let metatitle = ''
+		let metasubject = ''
+		let metakeywords = ''
+		let metadate = ''
+		if has_key(g:vst_fielddb, 'author')
+			let metaauthor = '\n"
+		endif
+		if has_key(g:vst_fielddb, 'title')
+			let metatitle = '\n"
+		endif
+		if has_key(g:vst_fielddb, 'keywords')
+			let metakeywords = '\n"
+		endif
+		if has_key(g:vst_fielddb, 'subject')
+			let metasubject = '\n"
+		endif
+		if has_key(g:vst_fielddb, 'date')
+			if g:vst_fielddb['date'] != 'NONE'
+				let metadate = '\n"
+			endif
+		endif
+		let metainfo = metaauthor.metatitle.metakeywords.metasubject.metadate
+
+		let metadata = ''
+		for key in keys(g:vst_metadb)
+			if key =~ '^http-equiv='
+				let item = substitute(key, 'http-equiv=\(.*\)', 'http-equiv="\1"', '')
+				let element = ''."\n"
+			elseif key =~ '^description \(lang\|scheme\|dir\)'
+				let item = substitute(key, 'description \(lang\|scheme\|dir\)=\(.*\)', 'name="description" \1="\2", '')
+				let element = ''."\n"
+			else
+				let element = ''."\n"
+			endif
+			let metadata .= element
+		endfor
+
+		if exists("g:vst_doc_title")
+			let htmltitle = substitute(g:vst_doc_title, '^\s*', '', '')
+            let htmltitle = VST_SpecCharacter(htmltitle)
+		elseif metasubject != ''
+			let htmltitle = g:vst_fielddb['subject']
+		else
+			let htmltitle = expand("%")
+		endif
+		" }}}
+
+		" S5 special content {{{
+		if format == 's5'
+			if exists('s5footer')
+				let s5foot = VST_Structure(split(s5footer, '0000000000000000000'))
+				let s5foot = substitute(s5foot, '^\_s*\_s*', '', '')
+				let s5foot = substitute(s5foot, '\_s*\_s*$', '', '')
+				unlet! s5footer
+			else
+				if has_key(g:vst_fielddb, 'author')
+					let s5author = g:vst_fielddb['author']
+				else
+					let s5author = 'Author'
+				endif
+				if has_key(g:vst_fielddb, 'date') && g:vst_fielddb['date'] != 'NONE'
+					let s5date = g:vst_fielddb['date']
+				else
+					let s5date = 'Date'
+				endif
+				let s5foot = s5author.' • '.s5date
+			endif
+			let s5head = ''
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+					\.''."\n"
+			let s5body = ''
+					\.'
'."\n" + \.'
'."\n" + \.'
'."\n" + \.''."\n" + \.''."\n" + \.'
'."\n" + \.'
' + let s5body2 = "
\n" + else + let s5body = '' + let s5head = '' + let s5body2 = '' + endif + " }}} + + let metainfo .= metadata + + if file =~ ']*start="' + let g:zzz = 1 + let doctype = + \ ''."\n" + "\ ' '."\n" + else + let doctype = + \ ''."\n" + "\ ''."\n" + endif + + let header = + \ doctype + \.''."\n" + \.''."\n" + \.''."\n" + \.''.htmltitle.''."\n" + \.''."\n" + \.metainfo."\n" + \.css."\n" + \.s5head."\n" + \.''."\n" + \.''."\n" + + let closing = ''."\n".'' + + let file = header."\n".s5body."\n".file."\n".s5body2."\n".closing + let file = substitute(file, '\)_', '\1', 'g') + " let file = substitute(file, '\(\[#\]
\)_', '\1', 'g') + + " Create comment tags + let file = substitute(file, '', ' -->', 'g') + let file = substitute(file, '', '', '\n\\tableofcontents', '') + + " Replace new line tags + let file = substitute(file, '\n\s*\s*\n', '\n\n', "g") + let file = substitute(file, '', '\\\\', "g") + + " Title + let file = substitute(file, '\_s*\(.\{-}\)', '\\title{\1}\n\\maketitle', "g") + " Sections + let file = substitute(file, '', '\\hypertarget{\1}{}\n\\section{', "g") + let file = substitute(file, '', '\\hypertarget{\1}{}\n\\subsection{', "g") + let file = substitute(file, '', '\\hypertarget{\1}{}\n\\subsubsection{', "g") + let file = substitute(file, '', '\\hypertarget{\1}{}\n\\paragraph{', "g") + let file = substitute(file, '', '\\hypertarget{\1}{}\n\\subparagraph{', "g") + let file = substitute(file, '<.vim:h[1-6]>', '}', 'g') + + " Rawlatex directive + " Ha. I didn't anticipate this - special chars inside of rawlatex will be + " escaped. Operating on string is faster than going through file line + " by line so unescaping of chars in while loop similar to pre handling still + " should be faster. + let file = substitute(file, '', '% Begin rawlatex', "g") + let file = substitute(file, '<.vim:rawlatex>', '% End rawlatex', "g") + " And the same for latexonly + let file = substitute(file, '', '% Begin rawlatex', "g") + let file = substitute(file, '<.vim:latexonly>', '% End rawlatex', "g") + " And the same for rawboth + let file = substitute(file, '', '% Begin rawlatex', "g") + let file = substitute(file, '<.vim:rawboth>', '% End rawlatex', "g") + + " Lists + let file = substitute(file, '', '\\item ', 'g') + let file = substitute(file, '<.vim:li>', "", "g") + let file = substitute(file, '', '\\begin{itemize}', "g") + let file = substitute(file, '<.vim:ul.\{-}>', '\\end{itemize}', "g") + " Enumitem and enumerate are in conflict. It has to be one or the + " other + if file =~ 'vim:ol class="[^>]\{-}start="' + let file = substitute(file, '', '\\begin{enumerate}[label=\\alph*.,start=\1]', "g") + let file = substitute(file, '', '\\begin{enumerate}[label=\\Alph*.,start=\1]', "g") + let file = substitute(file, '', '\\begin{enumerate}[label=\\roman*.,start=\1]', "g") + let file = substitute(file, '', '\\begin{enumerate}[label=\\Roman*.,start=\1]', "g") + let file = substitute(file, '', '\\begin{enumerate}[label=\\arabic*.,start=\1]', "g") + let file = substitute(file, '', '\\begin{enumerate}[label=\\arabic*.]', "g") + let listings = 'enumitem' + else + let file = substitute(file, '', '\\begin{enumerate}[1.]', "g") + let listings = 'enumerate' + endif + let file = substitute(file, '<.vim:ol>', '\\end{enumerate}', "g") + + " Field lists + let file = substitute(file, '\(.\{-}\)', '\\item[\1]', 'g') + let file = substitute(file, '", '\\end{deflist}', 'g') + + " Option lists + let file = substitute(file, '', '\\begin{optlist}{longoptionslist}\n', 'g') + let file = substitute(file, '\(.\{-}\)', '\\item[\1]', 'g') + let file = substitute(file, '\(.\{-}\)', '\\item[\1]', 'g') + let file = substitute(file, '', '', 'g') + let file = substitute(file, '', '', 'g') + let file = substitute(file, "", '\\end{optlist}', 'g') + + " Definition lists + let file = substitute(file, '', '\\begin{deflist}{iii}', 'g') + let file = substitute(file, '\(.\{-}\)', '\\item[\1]', 'g') + let file = substitute(file, '', '', 'g') + let file = substitute(file, '', '', 'g') + "let file = substitute(file, "", '\\end{deflist}', 'g') + " + " Rubric + let file = substitute(file, '', '\\rubric{ ', "g") + let file = substitute(file, "", ' }', "g") + + " Pull-quote + let file = substitute(file, '', '\\begin{pullquote}', "g") + let file = substitute(file, "", '\\end{pullquote}', "g") + + " Blockquote + let file = substitute(file, "", '\\begin{quotation}', "g") + let file = substitute(file, "", '\\end{quotation}', "g") + + " Text styles + let file = substitute(file, '', '\\emph{', "g") + let file = substitute(file, "", "}", "g") + let file = substitute(file, '', '\\textbf{', "g") + let file = substitute(file, "", "}", "g") + let file = substitute(file, '', '\\texttt{', "g") + let file = substitute(file, "", "}", "g") + + " Tables + let file = substitute(file, '', '\\setlongtables\n\\begin{center}\n\\begin{longtable}[c]{\1coln\2}\\hline\n', "g") + let file = substitute(file, "", '', "g") + let file = substitute(file, "", '\\endhead', "g") + let file = substitute(file, "", '', "g") + let file = substitute(file, "", '', "g") + let file = substitute(file, "", '\\end{longtable}\n\\end{center}', "g") + let file = substitute(file, '\n\?', '', "g") + let file = substitute(file, '', ' \& ', "g") + let file = substitute(file, "", ' \\\\ \\hline', "g") + let file = substitute(file, '\n\?\(.\{-}\)\_s*', '\n\\multicolumn{\1}{|p{0.\2\\textwidth}|}{\3}', "g") + let file = substitute(file, '\(.\{-}\)\_s*', ' \& \\multicolumn{\1}{p{0.\2\\textwidth}|}{\3}', "g") + let file = substitute(file, "", '', "g") + + " Line + " \transition allows for easy change of transition display, eg. for + " fancy graphics + let file = substitute(file, "", '\\transition', "g") + + " Comment + let file = substitute(file, "\(.\{-}\)', '\\href{\2}{\3}', 'g') + let file = substitute(file, '\(.\{-}\)', '\\hypertarget{\1}{\2}', 'g') + + " Subscript, superscript + let file = substitute(file, '\(.\{-}\)', '\\subs{\1}', 'g') + let file = substitute(file, '\(.\{-}\)', '\\sups{\1}', 'g') + + " Fix address special field + let file = substitute(file, '\(.\{-}\)', '\1', 'g') + + " Replace unknown with pre elements in frame + let file = substitute(file, '', 'Unknown element\n', 'g') + let file = substitute(file, '', '', 'g') + + " Title-reference role () + let file = substitute(file, '', '\\emph{', 'g') + let file = substitute(file, '', '}', 'g') + + " Class big, small + let file = substitute(file, '', '{\\small ', 'g') + let file = substitute(file, '', '}', 'g') + + " Figure + let file = substitute(file, '', '\\begin{center}\n\\begin{minipage}{0.6\\textwidth}', 'g') + let file = substitute(file, '', '\\end{minipage}\n\\end{center}', 'g') + + " Create ghost commands for custom block directives + let file = substitute(file, '', '\\vst\1{', 'g') + let file = substitute(file, '', '}', 'g') + + " Create ghost commands for custom container directives + let file = substitute(file, '', '\\vst\1{', 'g') + let file = substitute(file, '', '}', 'g') + + " Topic + let file = substitute(file, '', '\\hfill\\begin{minipage}{0.9\\textwidth}', 'g') + let file = substitute(file, '', '\\end{minipage}', 'g') + + " Sidebar + let file = substitute(file, '', '\\hfill\\begin{minipage}{0.9\\textwidth}', 'g') + let file = substitute(file, '', '\\end{minipage}', 'g') + + " Divs + let file = substitute(file, '', '\\begin{center}\n\\fbox{\\begin{minipage}{0.8\\textwidth}', 'g') + let file = substitute(file, '', '\\end{minipage}}\n\\end{center}', 'g') + " Div titles ( was already replaced) + let file = substitute(file, '\(.\{-}\)}', '\\textbf{\\sffamily\\large \1}\n\\vspace{2mm}', 'g') + + " Remove rest of vim:span + " let file = substitute(file, '', '\\emph{', 'g') + let file = substitute(file, '', '\\vst\1{', 'g') + + " Replace empty vim:p tags when hypertargets + let file = substitute(file, '', '\\hypertarget{\1}{}', "g") + " Ignore all other tags + let file = substitute(file, '<.\?vim:p\>.\{-}>', "", "g") + + " Make sure no (La)TeX entity is in URL address of hyperlinks + let file = substitute(file, '\\href{\([^}]\{-}\)\\\(La\)\?TeX{}', '\\href{\1\2TeX', 'g') + let file = substitute(file, '\\hypertarget{\([^}]\{-}\)\\\(La\)\?TeX{}', '\\hypertarget{\1\2TeX', 'g') + " Unescape _ from hyperlinks + let file = substitute(file, '\\href{\([^}]\{-}\)\\_', '\\href{\1_', 'g') + let file = substitute(file, '\\hypertarget{\([^}]\{-}\)\\_', '\\hypertarget{\1_', 'g') + " Prepare newcommands from roles + if exists("g:vst_roledb") + let rolenewcommands = '%% Commands for content of roles directives'."\n" + let rolekeys = keys(g:vst_roledb) + for i in range(len(rolekeys)) + let name = g:vst_roledb[rolekeys[i]] + let rolenewcommands .= '\newcommand{\vst'.name.'}[1]{\textnormal{#1}}'."\n" + endfor + unlet! rolekeys + unlet! name + else + let rolenewcommands = "\n" + endif + " Prepare newcommands from containers + if len("g:vst_containers") > 0 + let containernewcommands = '%% Commands for content of container directives'."\n" + let usednames = '' + for name in g:vst_containers + if usednames !~ ','.name.',' + let usednames .= ','.name.',' + let containernewcommands .= '\newcommand{\vst'.name.'}[1]{#1}'."\n" + endif + endfor + else + let containernewcommands = "\n" + endif + + " Preamble {{{ + " This one is better for deflist but has some not nice side effects + " which have to be worked out + "\.'{\renewcommand{\makelabel}[1]{\parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{##1}}\mbox{}\\}}'."\n" + let preamble = + \ '\documentclass[12pt]{article}'."\n" + \.'%% Generated by Vim reStructured Text '.s:vst_ver.' - Vim '.v:version/100.".".v:version % 100."\n" + \.'\usepackage[a4paper,margin=2.5cm,nohead]{geometry}'."\n" + \.'\usepackage{'.listings."}\n" + \.'\usepackage{graphicx}'."\n" + \.'\usepackage{longtable}'."\n" + \.'\usepackage{tabularx}'."\n" + \.'\usepackage{amsmath}'."\n" + \.'\usepackage['.encoding."]{inputenc}\n" + \.countrysettings."\n" + \.'\newenvironment{deflist}[1]{%'."\n" + \.'\begin{list}{}'."\n" + \.'{\renewcommand{\makelabel}[1]{\textbf{##1}\hfill}'."\n" + \.'\settowidth{\labelwidth}{\textbf{#1}}'."\n" + \.'\leftmargin=\labelwidth'."\n" + \.'\advance \leftmargin\labelsep}}'."\n" + \.'{\end{list}}'."\n" + \.'\newenvironment{optlist}[1]{%'."\n" + \.'\begin{list}{}'."\n" + \.'{\renewcommand{\makelabel}[1]{\texttt{##1}\hfill}'."\n" + \.'\settowidth{\labelwidth}{\texttt{#1}}'."\n" + \.'\leftmargin=\labelwidth'."\n" + \.'\advance \leftmargin\labelsep}}'."\n" + \.'{\end{list}}'."\n" + \.'\newenvironment{pullquote}{\begin{quotation}\Large}{\end{quotation}}'."\n" + \.'\setlength{\extrarowheight}{2pt}'."\n" + \.tocdepth."\n" + \.'\newcommand{\transition}{\begin{center}\rule{.8\textwidth}{0.2pt}\end{center}}'."\n" + \.'\newcommand{\subtitle}[1]{{\large\textsc{#1}}\vskip15pt}'."\n" + \.'\newcommand{\subs}[1]{\raisebox{-0.7ex}{\footnotesize #1}}'."\n" + \.'\newcommand{\sups}[1]{\raisebox{0.7ex}{\footnotesize #1}}'."\n" + \.'\newcommand{\attribution}[1]{\raggedleft\textit{#1}}'."\n" + \.'\newcommand{\rubric}[1]{\vskip15pt{\large #1}}'."\n" + \.rolenewcommands."\n" + \.containernewcommands."\n" + \.userpreamble."\n" + \.'\usepackage[pdftex]{hyperref}'."\n" + " Additional data {{{ + let author = '' + let data = '' + if has_key(g:vst_fielddb, 'author') + let author = '\author{'.g:vst_fielddb['author'].'}'."\n" + endif + if has_key(g:vst_fielddb, 'date') + if g:vst_fielddb['date'] == 'NONE' + let g:vst_fielddb['date'] = '' + endif + let data = '\date{'.g:vst_fielddb['date'].'}'."\n" + else + let data = '' + endif + " }}} + " PDF Info {{{ + let pdfinfo = '' + let pdfauthor = '' + let pdftitle = '' + let pdfsubject = '' + let pdfkeywords = '' + if has_key(g:vst_fielddb, 'author') + let pdfauthor = 'pdfauthor={'.g:vst_fielddb['author']."},\n" + endif + if has_key(g:vst_fielddb, 'title') + let pdftitle = 'pdftitle={'.g:vst_fielddb['title']."},\n" + endif + if has_key(g:vst_fielddb, 'keywords') + let pdfkeywords = 'pdfkeywords={'.g:vst_fielddb['keywords']."},\n" + endif + if has_key(g:vst_fielddb, 'subject') + let pdfsubject = 'pdfsubject={'.g:vst_fielddb['subject']."}" + endif + for key in keys(g:vst_metadb) + if key =~ 'author' && pdfauthor == '' + let pdfauthor = 'pdfauthor={'.g:vst_metadb[key]."},\n" + elseif key =~ 'title' && pdftitle == '' + let pdftitle = 'pdftitle={'.g:vst_metadb[key]."},\n" + elseif key =~ 'keywords' && pdfkeywords == '' + let pdfkeywords = 'pdfkeywords={'.g:vst_metadb[key]."},\n" + elseif key =~ 'subject' && pdfsubject == '' + let pdfsubject = 'pdfsubject={'.g:vst_metadb[key]."}" + endif + endfor + + if exists("g:vst_doc_title") + let pdftitle = 'pdftitle={'.substitute(g:vst_doc_title, '^\s*', '', '')."},\n" + endif + + let pdfinfo = "\\hypersetup{\npdfcreator={VST, LaTeX, hyperref},\n" + \."bookmarksopen=true,\nbookmarksopenlevel=2,\n" + \."colorlinks=true,urlcolor=blue,\n" + \.pdfauthor.pdftitle.pdfkeywords.pdfsubject."}\n" + + let file = preamble."\n".pdfinfo."\n".author.data."\n".file."\n".footer + " }}} + " }}} + + " Create comments + let file = substitute(file, '\(.\{-}\)<.vim:comment>', '\=VST_CreateTexComment(submatch(1))', 'g') + + new + if &compatible == 1 + set nocompatible + endif + 0put =file + + " Go through tables to tune them {{{ + " 1. Create preamble of table + " 2. Remove \hline for borderless tables + silent call cursor(1,1) + while search('begin{longtable', 'W') + unlet! line1 line2 + let line1 = line('.') + if getline('.') =~ 'vstbordercoln' + "silent exe line1.','.line2.'s/\(multicolumn{\d\+}{\)\(.\{-}\)}/\=submatch(1).substitute(submatch(2), "\\(\\d\\+\\)+", "|p{0.\\1\\\\\\\\textwidth}", "g")."}"/ge' + silent s/vstbordercoln\(.\{-}\)}/\='|'.substitute(submatch(1), '\(\d\+\)+', 'p{0.\1\\\\textwidth}|', 'g').'}'/e + call search('end{longtable', 'W') + let line2 = line('.') + "silent exe line1.','.line2.'s/\(multicolumn{\d\+}{\)\(.\{-}\)}/\=submatch(1).substitute(submatch(2), "\\(\\d\\+\\)+", "|p{0.\\1\\\\\\textwidth}", "g")."}"/ge' + "silent exe line1.','.line2.'s/\(\& \\multicolumn{\d\+}{\)|/\1/ge' + elseif getline('.') =~ 'vstblesscoln' + silent s/vstblesscoln\(.\{-}\)}/\=substitute(submatch(1), '\(\d\+\)+', 'p{0.\1\\\\textwidth} ', 'g').'}'/e + call search('end{longtable', 'W') + let line2 = line('.') + silent exe line1.','.line2.'s/\\hline\($\|\\end{longtable\)/\1/e' + silent exe line1.','.line2.'g/\\multicolumn/s/\(\\textwidth}\)|/\1/ge' + silent exe line1.','.line2.'g/\\multicolumn/s/\(\\multicolumn{\d\+}{\)|/\1/ge' + endif + " NOTE: this changes range so line1, line2 are useless after that + silent exe line1.','.line2.'s/\_s*&\_s*/\r\&\r/ge' + endwhile + " }}} + " Process {{{ + silent call cursor(1,1) + while search('+'.imagestring.'+e' + silent normal! j + endwhile + " }}} + " Processing preformatted text. {{{ + " Not using verbatim because it is + " in conflict with minipages + silent call cursor(1,1) + while search('^\s* in $$ to show them. {{{ + " \langle, \rangle would be more proper solution but they + " look too differently for my taste. + silent v/^\\mbox/s//$>$/ge + silent v/^\\mbox\|begin{longtable\|multicolumn{/s/|/$|$/ge + " }}} + " Beautyfication of LaTeX output {{{ + silent %s/^\s*$// + silent %s/\n\{3,}/\r\r/ + silent %s/\n\+\(\n\s*\\end\)/\1/ + silent %s/\(\\begin{.\{-}}\n\)\n\+/\1/ + " Compressing of titles + silent %s/title{\n/title{/e + silent %s/section{\n/section{/e + silent %s/paragraph{\n/paragraph{/e + " Shorten lists + silent %s/\\item\s*\n\n/\\item\r/e + " Because multiple spaces are meaningless: + silent %s/\s\+/ /ge + " Test it + silent %s/{\_s*/{/ge + silent %s/\n\n\s*&\s*\n\n/\r\&\r/ge + silent %s/\n\n \(\\\\ \\hline\)\s*\n\n/\r\1\r/ge + " Fix vertical space in admonitions + silent %s/\(\\vspace{2mm}\n\)\(\S\)/\1\r\2/ge + " Replace lines for .. figure:: - image first, minipage later. + silent %s/\(\\begin{minipage}{0\.6\\textwidth}\)\n\(\\begin{figure.*\)/\2\r\1/ge + " Remove special chars catchers + silent %s/@/@/ge + silent %s/[/[/ge + silent %s/\/\\/ge + silent %s/:/:/ge + silent %s/&\\#64;/@/ge + silent %s/&\\#91;/[/ge + silent %s/&\\#92;/\\/ge + silent %s/&\\#58;/:/ge + " Insert new line before \item[], it causes problems in complex + " environments + silent %s/\\item\[/\r\0/ge + " But we don't like if there is more than one blank line + silent %s/\n\n\n\\item\[/\r\r\\item\[/ge + " Remove empty deflist environment + " may be a problem when :Date: NONE is the only element of field list + silent %s/\\begin{deflist}{.\{-}}\n\\end{deflist}//ge + " Replace non-breaking space characters with ~ + silent %s/ /\~/ge + " }}} + " Insert raw files {{{ + silent call cursor(1,1) + while search('-vst-raw-file-placeholder:', 'W') + let file = matchstr(getline('.'), '-vst-raw-file-placeholder:\zs.*') + " Remove \ before _ - in most cases it was placed there by + " escaping mechanism, not user + let file = substitute(file, '\\_', '_', 'g') + silent s/.*//ge + exe 'silent read '.escape(file, ' \#%') + endwhile + " }}} + + redraw! + + " This is place for special CJK postprocessing + " What if &encoding=='utf-8'? + if &encoding =~? 'big5\|cp950\|euc-tw' || ( &encoding =~? '^utf' && v:ctype =~ 'big5' ) + + silent! g/^\\usepackage.*geometry}/s/.*/\0\r\\usepackage{CJK}/ + silent! g/^\\usepackage.*inputenc}/d + silent! g/^\\usepackage.*hyperref}/s/.*/\\usepackage[CJKbookmarks,bookmarks=false,pdftex]{hyperref} + silent! g/^bookmarksopen=true,$/d + silent! g/^bookmarksopenlevel=2,$/d + if encoding == 'Big5' + silent! g/\\begin{document}/s/.*/\0\\begin{CJK}{Bg5}{}/ + elseif encoding == 'UTF-8' + silent! g/\\begin{document}/s/.*/\0\\begin{CJK}{UTF8}{}/ + else + silent! g/\\begin{document}/s/.*/\0\\begin{CJK}{}{}/ + endif + silent! g/\\end{document}/s/.*/\\end{CJK}\0/ + + let cjkpreamble = '\renewcommand\CJKglue{\hskip -0.3pt plus 0.08\baselineskip}'."-cjk-newline-placeholder-" + \.'\linespread{1.382}'."-cjk-newline-placeholder-" + \.'\renewcommand{\arraystretch}{1.2}'."-cjk-newline-placeholder-" + \.'\parindent=0pt'."-cjk-newline-placeholder-" + \.'\parskip=1.382ex'."-cjk-newline-placeholder-" + \.'\renewenvironment{quote}'."-cjk-newline-placeholder-" + \.' {\list{}{\topsep 1ex\parsep 0ex\setlength\leftmargin{1.5em}%'."-cjk-newline-placeholder-" + \.' \rightmargin\leftmargin}\item\relax\linespread{1.0}\small}%'."-cjk-newline-placeholder-" + \.' {\endlist}'."-cjk-newline-placeholder-" + \.'\let\oldfootnote\footnote'."-cjk-newline-placeholder-" + \.'\renewcommand\footnote[1]{\oldfootnote{\renewcommand\baselinestretch{1.0}%'."-cjk-newline-placeholder-" + \.'\large\footnotesize\ignorespaces#1}}'."-cjk-newline-placeholder-" + \.'\addtolength{\footnotesep}{3pt}' + + silent call cursor(1,1) + silent call search('^\\usepackage{amsmath}') + silent call append(line('.'), cjkpreamble) + " Placeholder stuff is necessary because no Vim function for + " inserting text like newline character. + silent! %s/-cjk-newline-placeholder-/\r/g + silent call cursor(1,1) + + endif + + " User postprocessing + if g:vst_tex_post != '' && filereadable(g:vst_tex_post) + exe "silent! source ".g:vst_tex_post + endif + + " Handling of pdf export {{{ + if format =~ 'pdf' + silent call cursor(1,1) + let file_tex = filename.'.tex' + if !exists('g:vst_pdf_command') + let g:vst_pdf_command = 'pdflatex -interaction=nonstopmode' + endif + silent exe 'write! '.escape(file_tex, ' \#%') + silent exe "call system(\"".g:vst_pdf_command." '".file_tex."'\")" + if search('\\tableofcontents', 'W') + silent exe "call system(\"".g:vst_pdf_command." '".file_tex."'\")" + endif + if v:shell_error == 0 + bw! % + echomsg "Document compiled OK. You can view it in PDF viewer." + if exists("g:vst_pdf_clean") && g:vst_pdf_clean == 1 + call delete(file_tex) + call delete(filename.'.log') + call delete(filename.'.out') + call delete(filename.'.aux') + endif + if exists("g:vst_pdf_view") && g:vst_pdf_view == 1 + if !exists("g:vst_pdf_viewer") + if has("win32") + let g:vst_pdf_viewer = "" + elseif has("unix") + if executable("kpdf") + let g:vst_pdf_viewer = "kpdf" + elseif executable("xpdf") + let g:vst_pdf_viewer = "xpdf" + else + let g:vst_pdf_viewer = "no_pdf_viewer" + endif + endif + endif + silent exe "call system(\"".g:vst_pdf_viewer." '".filename.".pdf'\")" + silent redraw! + endif + else + echomsg "Something went wrong, check TeX code or command settings." + endif + silent call cursor(1,1) + call VST_End() + return + endif + " }}} + + " Latex-Suite (or any other tex ftype settings) brokes *many* + " things. Load it at the end + setlocal ft=tex + if exists("g:vst_write_export") && g:vst_write_export != 0 + silent exe 'write! '.escape(filename, ' \#%').'.tex' + endif + + silent call cursor(1,1) + " }}} + " Auxiliary commands {{{ + elseif format =~ '^head' + " Symbols for section titles {{{ + call VST_Headers(text) + unlet! b:vst_first_parsing + call VST_DictTable(g:vst_headers, 'Level', 'Symbol', 0) + " }}} + elseif format =~ '^toc' + " Table of contents for file {{{ + let line = line('.') + call VST_Headers(text) + unlet! b:vst_first_parsing + let i = 1 + let tocc = [] + let b:vst_toc_numbers = {} + let i1 = -1 + let i2 = -1 + let i3 = -1 + let i4 = -1 + let i5 = -1 + let i6 = -1 + + while i < len(g:paras) + if g:ptype[i] =~ '^h\d' + " Real table + call add(tocc, [g:ptype[i], g:paras[i], g:plinen[i]]) + " Header numbers + let header_text = matchstr(g:paras[i], '^.\{-}\ze\n') + let lvl = strpart(g:ptype[i], 1) + if lvl == 1 + let b:vst_toc_numbers[header_text] = '' + let i2 = 0 + let i3 = 0 + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 2 + let i2 += 1 + let b:vst_toc_numbers[header_text] = i2.' ' + let i3 = 0 + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 3 + let i3 += 1 + let b:vst_toc_numbers[header_text] = i2.'.'.i3.' ' + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 4 + let i4 += 1 + let b:vst_toc_numbers[header_text] = i2.'.'.i3.'.'.i4.' ' + let i5 = 0 + let i6 = 0 + elseif lvl == 5 + let i5 += 1 + let b:vst_toc_numbers[header_text] = i2.'.'.i3.'.'.i4.'.'.i5.' ' + let i6 = 0 + elseif lvl == 6 + let i6 += 1 + let b:vst_toc_numbers[header_text] = i2.'.'.i3.'.'.i4.'.'.i5.'.'.i6.' ' + endif + endif + let i += 1 + endwhile + + echo VST_TocTable(tocc, 'Nr', 'Title', ' Line', line) + " }}} + elseif format =~ '^fold' + " Folding {{{ + let b:vst_fold = {} + call VST_Headers(text) + unlet! b:vst_first_parsing + " Prepare numbers of head lines {{{ + let b:vst_fold_numbers = {} + let i = 0 + let i1 = -1 + let i2 = -1 + let i3 = -1 + let i4 = -1 + let i5 = -1 + let i6 = -1 + while i < len(g:paras) + if g:ptype[i] =~ '^h\d' + let header_text = matchstr(g:paras[i], '^.\{-}\ze\n') + let lvl = strpart(g:ptype[i], 1) + if lvl == 1 + let b:vst_fold_numbers[header_text] = '' + let i2 = 0 + let i3 = 0 + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 2 + let i2 += 1 + let b:vst_fold_numbers[header_text] = i2.' ' + let i3 = 0 + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 3 + let i3 += 1 + let b:vst_fold_numbers[header_text] = i2.'.'.i3.' ' + let i4 = 0 + let i5 = 0 + let i6 = 0 + elseif lvl == 4 + let i4 += 1 + let b:vst_fold_numbers[header_text] = i2.'.'.i3.'.'.i4.' ' + let i5 = 0 + let i6 = 0 + elseif lvl == 5 + let i5 += 1 + let b:vst_fold_numbers[header_text] = i2.'.'.i3.'.'.i4.'.'.i5.' ' + let i6 = 0 + elseif lvl == 6 + let i6 += 1 + let b:vst_fold_numbers[header_text] = i2.'.'.i3.'.'.i4.'.'.i5.'.'.i6.' ' + endif + + let b:vst_fold[header_text] = lvl-1 + endif + let i += 1 + endwhile + " }}} + " Prepare fold levels {{{ + let b:vst_fold_lvl = matchstr(format, '\zs.\ze\s*$') + if b:vst_fold_lvl =~ 'r' + for i in [1, 2, 3, 4, 5, 6] + let b:vst_fold_list_{i} = filter(deepcopy(b:vst_fold), 'v:val == i') + let b:vst_flvl_{i} = keys(b:vst_fold_list_{i}) + endfor + else + if b:vst_fold_lvl !~ '\d' + let b:vst_fold_lvl = 0 + elseif b:vst_fold_lvl =~ '\d' && b:vst_fold_lvl > 6 + let b:vst_fold_lvl = 6 + endif + if b:vst_fold_lvl != 0 + let b:vst_fold_list = filter(deepcopy(b:vst_fold), 'v:val <= b:vst_fold_lvl') + else + let b:vst_fold_list = b:vst_fold + endif + endif + " }}} + setlocal foldmethod=expr + setlocal foldexpr=VST_FoldExpr(v:lnum) + setlocal foldtext=VST_FoldText() + " }}} + elseif format =~ '^fblank' + " Folding by blank lines {{{ + let directive = matchstr(format, '^f\zs.*') + setlocal foldmethod=expr + set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1 + function! VST_FoldText() + let text = getline(v:foldstart) + let indent = '+'.v:folddashes + return indent.repeat(' ', 2).text.' ' + endfunction + setlocal foldtext=VST_FoldText() + " }}} + elseif format =~ '^f' + " Folding by directive {{{ + "elseif format =~ '^f\(block\|container\|image\|figure\|sidebar\|compound\|topic\|rubric\|table\|tip\|note\|warning\|admonition\|include\|pull-quote\|class\|meta\|raw\|2html\)' + let directive = matchstr(format, '^f\zs.*') + setlocal foldmethod=expr + "exe "setlocal foldexpr=getline(v:lnum)=~?'^\\\\s*\\\.\\\.\\\ ".directive."::'?'>1':1" + exe "setlocal foldexpr=getline(v:lnum)=~?'^\\\\s*\\\.\\\.\\\ ".directive."'?'>1':1" + function! VST_FoldDirective() + let text = getline(v:foldstart) + let indent = '+'.v:folddashes + let fill = 65 - (len(indent) + len(text) + 3) + if fill < 1 + let fill = 1 + endif + return indent.' '.text.repeat(' ', fill).v:foldstart.' ('.v:foldstart*100/line('$').'%)' + endfunction + setlocal foldtext=VST_FoldDirective() + " }}} + elseif format =~ '^link' + " Link table {{{ + call VST_Headers(text) + unlet! b:vst_first_parsing + call VST_DictTable(g:vst_hlinkdb, 'Text', 'Link', 0) + " }}} + elseif format =~ '^slink' + " Sorted link table {{{ + call VST_Headers(text) + unlet! b:vst_first_parsing + call VST_DictTable(g:vst_hlinkdb, 'Text', 'Link', 1) + " }}} + elseif format =~ '^rep' + " Replacement table {{{ + call VST_Headers(text) + unlet! b:vst_first_parsing + call VST_DictTable(g:vst_replacedb, 'Symbol', 'Replacement', 0) + " }}} + elseif format =~ '^srep' + " Sorted replacement table {{{ + call VST_Headers(text) + unlet! b:vst_first_parsing + call VST_DictTable(g:vst_replacedb, 'Symbol', 'Replacement', 1) + " }}} + elseif format =~ '^help' + " Help for commands {{{ + echo + \ "Help for :Vst arguments:\n" + \."html - [default] export to HTML format\n" + \."tex - export to LaTeX format\n" + \."pdf - export to LaTeX format and compile PDF\n" + \."rest - export to reST format\n" + \."s5 - export to S5 HTML presentation\n" + \." ---------------\n" + \."toc - file table of contents\n" + \."head - show used symbols for headers\n" + \."link - show table of link declarations\n" + \."slink - show sorted table of link declarations\n" + \."rep - show table of replacements\n" + \."srep - show sorted table of replacements\n" + \."preproc - process inclusion commands (non-recursively)\n" + \."help - this message\n" + \." ---------------\n" + \."fold - (re)create folds in file\n" + \."foldr - (re)create folds recursively in file\n" + \."fold1 - (re)create folds of 1st level headers in file\n" + \."fold2 - (re)create folds up to 2nd level header in file\n" + \."fold3 - (re)create folds up to 3rd level header in file\n" + \."fold4 - (re)create folds up to 4th level header in file\n" + \."fold5 - (re)create folds up to 5th level header in file\n" + \."fold6 - (re)create folds up to 6th level header in file\n" + \." ---------------\n" + \."Additional commands:\n" + \.":Vsti - immediately write file\n" + \.":Vstm - display menus (no arguments)" + return '' + " }}} + elseif format =~ '^pre' + " Interpret all including commands and put them in file {{{ + silent normal! ggdG + let jtext = join(text, "\n") + silent 0put =jtext + silent call cursor(1,1) + " }}} + " }}} + endif + + call VST_End() + + return '' + +endfunction +" }}} + +" Functions for auxiliary mappings {{{ +function! vst#vst#VST_AuxiliaryMappings() +" VST_Ornaments: insert ornaments depending on position {{{ +" Description: Depending on position and inserted character inserted before +" cursor fill ornaments: single section ornaments, double section ornaments, +" transition element +function! VST_Ornaments() + " Get ornament character + " HEADDEF: + let s:vst_headdef = '\(=\{3,}\|+\{3,}\|\*\{3,}\|\^\{3,}\|%\{3,}\|\$\{3,}\|#\{3,}\|@\{3,}\|;\{3,}\|"\{3,}\|\.\{3,}\|,\{3,}\|`\{3,}\|\~\{3,}\|-\{3,}\|!\{3,}\|(\{3,}\|)\{3,}\|:\{3,}\|_\{3,}\|&\{3,}\|}\{3,}\|{\{3,}\||\{3,}\|?\{3,}\|<\{3,}\|>\{3,}\|\\\{3,}\|\[\{3,}\|\]\{3,}\|\/\{3,}\|''\{3,}\)' + let s:vst_headchars2 = '\(=\|+\|\*\|\^\|%\|\$\|#\|@\|;\|"\|\.\|,\|`\|\~\|-\|!\|(\|)\|:\|_\|&\|}\|{\||\|?\|<\|>\|\\\|\[\|\]\|\/\|''\)' + let curline = getline(line('.')) + let character = curline[len(curline)-1] + if curline =~ '^\s*$' + " Temporary thing, to by-pass headchars test + let character = '-' + elseif curline !~ '^\s*'.s:vst_headchars2.'\+$' + return '' + endif + + let prevline = getline(line('.')-1) + let nextline = getline(line('.')+1) + + if prevline =~ '^\s*$' + let prevline_is_empty = 1 + else + let prevline_is_empty = 0 + endif + + if nextline =~ '^\s*$' + let nextline_is_empty = 1 + else + let nextline_is_empty = 0 + endif + + if prevline_is_empty == 1 && nextline_is_empty == 1 + " We are to insert transition element + if &tw > 50 + let trans_len = &tw/3 + else + let trans_len = 20 + endif + if curline =~ '^\s*$' + " Current line consists of only white characters. Try to find last + " used transition + let last_trans_line = search('\n\s*\n\s*'.s:vst_headdef.'\s*\n\s*\n' , 'bWn') + 2 + if last_trans_line == 2 + let character = '-' + else + let character = matchstr(getline(last_trans_line), '^\s*\zs.\ze') + endif + endif + return repeat(character, trans_len) + elseif prevline_is_empty == 0 && nextline_is_empty == 1 + " Insert single ornament + let prevline_len = len(prevline) + if curline =~ '^\s*$' + " Current line consists of only white characters. Try to find last + " single ornament section + let last_single_ornament = search('\(\%^\|\n\s*\n\|\%^\s*\n\).\{-}\n\s*'.s:vst_headdef.'\s*\n\s*\n' , 'bWn') + 3 + if last_single_ornament == 4 && getline(1) =~ '^\s*$' && getline(2) =~ '^\s*$' + let last_single_ornament = 4 + elseif last_single_ornament == 4 && getline(1) =~ '^\s*$' + let last_single_ornament = 3 + let real3 = 1 + elseif last_single_ornament == 4 + let last_single_ornament = 2 + endif + if last_single_ornament == 3 + if !exists('real3') + let character = '-' + else + let character = matchstr(getline(last_single_ornament), '^\s*\zs.\ze') + unlet! real3 + endif + else + let character = matchstr(getline(last_single_ornament), '^\s*\zs.\ze') + endif + endif + if prevline_len < 3 + let ornament_len = 3 - len(curline) + else + let ornament_len = prevline_len - len(curline) + endif + return repeat(character, ornament_len)."\n" + elseif prevline_is_empty == 1 && nextline_is_empty == 0 + " Insert double ornament + let nextline_len = len(nextline) + " Unfortunately this line borks undo history + normal! 2"_dd + if curline =~ '^\s*$' + " Current line consists of only white characters. Try to find last + " used ornament + let last_double_ornament = search('\(\%^\|\n\s*\n\|\%^\s*\n\)\s*'.s:vst_headdef.'\s*\n.\{-}\n\s*\2\s*\n' , 'bWn') + 2 + if last_double_ornament == 3 && getline(1) =~ '^\s*$' && getline(2) !~ '^\s*$' + let last_double_ornament = 4 + endif + if last_double_ornament == 2 + let character = '=' + else + let character = matchstr(getline(last_double_ornament), '^\s*\zs.\ze') + endif + endif + if len(curline) == 0 + let correction = 0 + else + let correction = 1 + endif + if nextline_len < 3 + let ornament_len = 3 + else + let ornament_len = nextline_len + endif + let ornament = repeat(character, ornament_len) + return ornament."\n".nextline."\n".ornament."\n" + else + return '' + endif + + return '' + +endfunction +" }}} +" VST_RotateOrnaments: rotate characters in ornaments {{{ +" headers +function! VST_RotateOrnaments() + " HEADDEF: + let s:vst_headdef = '\(=\{3,}\|+\{3,}\|\*\{3,}\|\^\{3,}\|%\{3,}\|\$\{3,}\|#\{3,}\|@\{3,}\|;\{3,}\|"\{3,}\|\.\{3,}\|,\{3,}\|`\{3,}\|\~\{3,}\|-\{3,}\|!\{3,}\|(\{3,}\|)\{3,}\|:\{3,}\|_\{3,}\|&\{3,}\|}\{3,}\|{\{3,}\||\{3,}\|?\{3,}\|<\{3,}\|>\{3,}\|\\\{3,}\|\[\{3,}\|\]\{3,}\|\/\{3,}\|''\{3,}\)' + let s:vst_headchars2 = '\(=\|+\|\*\|\^\|%\|\$\|#\|@\|;\|"\|\.\|,\|`\|\~\|-\|!\|(\|)\|:\|_\|&\|}\|{\||\|?\|<\|>\|\\\|\[\|\]\|\/\|''\)' + " Make sure we are in position to perform any actions + " This is more general regexp, could match several + if getline('.') !~ '^\s*'.s:vst_headdef.'\s*$' + return 0 + endif + + " Get situation: double/single ornament, transition + let prevline = getline(line('.')-1) + let nextline = getline(line('.')+1) + + if prevline =~ '^\s*$' + let prevline_is_empty = 1 + else + let prevline_is_empty = 0 + endif + + if nextline =~ '^\s*$' + let nextline_is_empty = 1 + else + let nextline_is_empty = 0 + endif + + if !exists("g:vst_headers") + call input('No knowledge about headers, run :Vst head') + return 0 + endif + + if nextline_is_empty == 1 && prevline_is_empty == 0 + " Single ornament + let a = 0 + endif + " Make sure we have data about headers. Note: updating of data will be + " done manually or updated at the end +endfunction +" }}} +" Auxiliary mappings +inoremap o =VST_Ornaments() +"noremap o =VST_RotateOrnaments() +endfunction +" vim:fdm=marker:ff=unix:noet:ts=4:sw=4:nowrap diff --git a/colors/lettuce.vim b/colors/lettuce.vim new file mode 100644 index 0000000..223dc36 --- /dev/null +++ b/colors/lettuce.vim @@ -0,0 +1,215 @@ +" Vim color file +" Version: 1.2 2007.08.08 +" Author: Valyaeff Valentin +" License: GPL +" +" Copyright 2007 Valyaeff Valentin +" +" This program is free software: you can redistribute it and/or modify +" it under the terms of the GNU General Public License as published by +" the Free Software Foundation, either version 3 of the License, or +" (at your option) any later version. +" +" This program is distributed in the hope that it will be useful, +" but WITHOUT ANY WARRANTY; without even the implied warranty of +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +" GNU General Public License for more details. +" +" You should have received a copy of the GNU General Public License +" along with this program. If not, see . + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name="lettuce" + + +augroup Syntax_extensions + au! + au Syntax c,cpp,ruby,javascript syn match Operator "[*/%&|!=><^~,.;:?+-]\+" display contains=TOP + au Syntax c,cpp syn region cParen matchgroup=Operator transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell + au Syntax c,cpp syn region cCppParen matchgroup=Operator transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString,@Spell + au Syntax c,cpp syn region cBracket matchgroup=Operator transparent start='\[\|<::\@!' end=']\|:>' contains=ALLBUT,@cParenGroup,cErrInParen,cCppParen,cCppBracket,cCppString,@Spell + au Syntax c,cpp syn region cCppBracket matchgroup=Operator transparent start='\[\|<::\@!' skip='\\$' excludenl end=']\|:>' end='$' contained contains=ALLBUT,@cParenGroup,cErrInParen,cParen,cBracket,cString,@Spell + au Syntax c,cpp syn region cBlock matchgroup=OperatorCurlyBrackets start="{" end="}" transparent fold + au Syntax ruby syn match rubyBlockParameter "\%(\%(\\|{\)\s*\)\@<=|\s*[( ,a-zA-Z0-9_*)]\+\ze\s*|"hs=s+1 display + au Syntax ruby syn region rubyCurlyBlock matchgroup=Operator start="{" end="}" contains=ALLBUT,@rubyExtendedStringSpecial,rubyTodo fold + au Syntax ruby syn region rubyParentheses matchgroup=Operator start="(" end=")" contains=ALLBUT,@rubyExtendedStringSpecial,rubyTodo + au Syntax ruby syn region rubySquareBrackets matchgroup=Operator start="\[" end="\]" contains=ALLBUT,@rubyExtendedStringSpecial,rubyTodo + au Syntax javascript syn region javascriptCurlyBrackets matchgroup=Operator start="{" end="}" transparent fold + au Syntax javascript syn region javascriptParentheses matchgroup=Operator start="(" end=")" transparent + au Syntax javascript syn region javascriptSquareBrackets matchgroup=Operator start="\[" end="\]" transparent +augroup END + + +if !has("gui_running") + +hi rubyGlobalVariable cterm=none ctermfg=64 +hi rubyPredefinedIdentifier cterm=bold ctermfg=64 +hi def link rubyStringDelimiter String + +hi Normal cterm=none ctermbg=232 ctermfg=189 +hi StatusLine cterm=none ctermbg=236 ctermfg=231 +hi StatusLineNC cterm=none ctermbg=236 ctermfg=103 +hi User1 cterm=bold ctermbg=236 ctermfg=223 +hi User2 cterm=none ctermbg=236 ctermfg=240 +hi VertSplit cterm=none ctermbg=236 ctermfg=103 +hi TabLine cterm=none ctermbg=236 ctermfg=145 +hi TabLineFill cterm=none ctermbg=236 +hi TabLineSel cterm=none ctermbg=240 ctermfg=253 +hi LineNr cterm=none ctermfg=238 +hi NonText cterm=bold ctermbg=233 ctermfg=241 +hi Folded cterm=none ctermbg=234 ctermfg=136 +hi FoldColumn cterm=none ctermbg=236 ctermfg=103 +hi SignColumn cterm=none ctermbg=236 ctermfg=103 +hi CursorColumn cterm=none ctermbg=234 +hi CursorLine cterm=none ctermbg=234 +hi IncSearch cterm=bold ctermbg=63 ctermfg=232 +hi Search cterm=none ctermbg=36 ctermfg=232 +hi Visual cterm=none ctermbg=24 +hi WildMenu cterm=bold ctermbg=35 ctermfg=232 +hi ModeMsg cterm=bold ctermfg=110 +hi MoreMsg cterm=bold ctermfg=121 +hi Question cterm=bold ctermfg=121 +hi ErrorMsg cterm=none ctermbg=88 ctermfg=255 +hi WarningMsg cterm=none ctermbg=58 ctermfg=255 +hi SpecialKey cterm=none ctermfg=77 +hi Title cterm=bold ctermfg=147 +hi Directory ctermfg=105 +hi DiffAdd cterm=none ctermbg=18 +hi DiffChange cterm=none ctermbg=58 +hi DiffDelete cterm=none ctermbg=52 ctermfg=58 +hi DiffText cterm=none ctermbg=53 +hi Pmenu cterm=none ctermbg=17 ctermfg=121 +hi PmenuSel cterm=none ctermbg=24 ctermfg=121 +hi PmenuSbar cterm=none ctermbg=19 +hi PmenuThumb cterm=none ctermbg=37 +hi MatchParen cterm=bold ctermbg=24 +hi SpellBad cterm=none ctermbg=88 +hi SpellCap cterm=none ctermbg=18 +hi SpellLocal cterm=none ctermbg=30 +hi SpellRare cterm=none ctermbg=90 + +hi Comment cterm=none ctermfg=138 +hi Constant cterm=none ctermfg=215 + hi String cterm=none ctermbg=235 ctermfg=215 + hi Character cterm=none ctermbg=235 ctermfg=215 + hi Number cterm=none ctermfg=34 + hi Float cterm=none ctermfg=41 +hi Identifier cterm=none ctermfg=186 + hi Function cterm=none ctermfg=210 +hi Statement cterm=bold ctermfg=63 + hi Exception cterm=bold ctermfg=99 + hi Operator cterm=none ctermfg=75 + hi Label cterm=none ctermfg=63 +hi PreProc cterm=bold ctermfg=36 +hi Type cterm=bold ctermfg=71 +hi Special cterm=none ctermbg=235 ctermfg=87 +hi Underlined cterm=underline ctermfg=227 +hi Ignore cterm=bold ctermfg=235 +hi Error cterm=bold ctermbg=52 ctermfg=231 +hi Todo cterm=bold ctermbg=143 ctermfg=16 + +hi OperatorCurlyBrackets cterm=bold ctermfg=75 + +" highlight modes +autocmd InsertEnter * hi StatusLine ctermbg=52 +autocmd InsertEnter * hi User1 ctermbg=52 +autocmd InsertEnter * hi User2 ctermbg=52 +autocmd InsertLeave * hi User2 ctermbg=236 +autocmd InsertLeave * hi User1 ctermbg=236 +autocmd InsertLeave * hi StatusLine ctermbg=236 +autocmd CmdwinEnter * hi StatusLine ctermbg=22 +autocmd CmdwinEnter * hi User1 ctermbg=22 +autocmd CmdwinEnter * hi User2 ctermbg=22 +autocmd CmdwinLeave * hi User2 ctermbg=236 +autocmd CmdwinLeave * hi User1 ctermbg=236 +autocmd CmdwinLeave * hi StatusLine ctermbg=236 + +else + +hi rubyGlobalVariable gui=none guifg=#5f8700 +hi rubyPredefinedIdentifier gui=bold guifg=#5f8700 +hi def link rubyStringDelimiter String + +hi Normal gui=none guibg=#080808 guifg=#dfdfff +hi StatusLine gui=none guibg=#303030 guifg=#ffffff +hi StatusLineNC gui=none guibg=#303030 guifg=#8787af +hi User1 gui=bold guibg=#303030 guifg=#ffdfaf +hi User2 gui=none guibg=#303030 guifg=#585858 +hi VertSplit gui=none guibg=#303030 guifg=#8787af +hi TabLine gui=none guibg=#303030 guifg=#afafaf +hi TabLineFill gui=none guibg=#303030 +hi TabLineSel gui=none guibg=#585858 guifg=#dadada +hi LineNr gui=none guifg=#444444 +hi NonText gui=bold guibg=#121212 guifg=#606060 +hi Folded gui=none guibg=#1c1c1c guifg=#af8700 +hi FoldColumn gui=none guibg=#303030 guifg=#8787af +hi SignColumn gui=none guibg=#303030 guifg=#8787af +hi CursorColumn gui=none guibg=#1c1c1c +hi CursorLine gui=none guibg=#1c1c1c +hi IncSearch gui=bold guibg=#5f5fff guifg=#080808 +hi Search gui=none guibg=#00af87 guifg=#080808 +hi Visual gui=none guibg=#005f87 +hi WildMenu gui=bold guibg=#00af5f guifg=#080808 +hi ModeMsg gui=bold guifg=#87afdf +hi MoreMsg gui=bold guifg=#87ffaf +hi Question gui=bold guifg=#87ffaf +hi ErrorMsg gui=none guibg=#870000 guifg=#eeeeee +hi WarningMsg gui=none guibg=#5f5f00 guifg=#eeeeee +hi SpecialKey gui=none guifg=#5fdf5f +hi Title gui=bold guifg=#afafff +hi Directory guifg=#8787ff +hi DiffAdd gui=none guibg=#000087 +hi DiffChange gui=none guibg=#5f5f00 +hi DiffDelete gui=none guibg=#5f0000 guifg=#5f5f00 +hi DiffText gui=none guibg=#5f005f +hi Pmenu gui=none guibg=#00005f guifg=#87ffaf +hi PmenuSel gui=none guibg=#005f87 guifg=#87ffaf +hi PmenuSbar gui=none guibg=#0000af +hi PmenuThumb gui=none guibg=#00afaf +hi MatchParen gui=bold guibg=#005f87 +hi SpellBad gui=none guibg=#870000 +hi SpellCap gui=none guibg=#000087 +hi SpellLocal gui=none guibg=#008787 +hi SpellRare gui=none guibg=#870087 + +hi Comment gui=none guifg=#af8787 +hi Constant gui=none guifg=#ffaf5f + hi String gui=none guibg=#262626 guifg=#ffaf5f + hi Character gui=none guibg=#262626 guifg=#ffaf5f + hi Number gui=none guifg=#00af00 + hi Float gui=none guifg=#00df5f +hi Identifier gui=none guifg=#dfdf87 + hi Function gui=none guifg=#ff8787 +hi Statement gui=bold guifg=#5f5fff + hi Exception gui=bold guifg=#875fff + hi Operator gui=none guifg=#5fafff + hi Label gui=none guifg=#5f5fff +hi PreProc gui=bold guifg=#00af87 +hi Type gui=bold guifg=#5faf5f +hi Special gui=none guibg=#262626 guifg=#5fffff +hi Underlined gui=underline guifg=#ffff5f +hi Ignore gui=bold guifg=#262626 +hi Error gui=bold guibg=#5f0000 guifg=#ffffff +hi Todo gui=bold guibg=#afaf5f guifg=#000000 + +hi OperatorCurlyBrackets gui=bold guifg=#5fafff + +" highlight modes +autocmd InsertEnter * hi StatusLine guibg=#5f0000 +autocmd InsertEnter * hi User1 guibg=#5f0000 +autocmd InsertEnter * hi User2 guibg=#5f0000 +autocmd InsertLeave * hi User2 guibg=#303030 +autocmd InsertLeave * hi User1 guibg=#303030 +autocmd InsertLeave * hi StatusLine guibg=#303030 +autocmd CmdwinEnter * hi StatusLine guibg=#005f00 +autocmd CmdwinEnter * hi User1 guibg=#005f00 +autocmd CmdwinEnter * hi User2 guibg=#005f00 +autocmd CmdwinLeave * hi User2 guibg=#303030 +autocmd CmdwinLeave * hi User1 guibg=#303030 +autocmd CmdwinLeave * hi StatusLine guibg=#303030 + +end diff --git a/colors/lucius.vim b/colors/lucius.vim new file mode 100644 index 0000000..f83c92a --- /dev/null +++ b/colors/lucius.vim @@ -0,0 +1,346 @@ +" Vim color file +" Maintainer: Jonathan Filip +" Last Modified: Wed Oct 21, 2009 11:39AM +" Version: 3.1 +" +" GUI / 256 color terminal +" +" I started out trying to combine my favorite parts of other schemes and ended +" up with this (oceandeep, moria, peaksea, wombat, zenburn). +" +" This file also tries to have descriptive comments for each higlighting group +" so it is easy to understand what each part does. + + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let colors_name="lucius" + +" Some other colors to save +" blue: 3eb8e5 +" green: 92d400 +" c green: d5f876, cae682 +" new blue: 002D62 +" new gray: CCCCCC + + +" Base color +" ---------- +hi Normal guifg=#e0e0e0 guibg=#202020 +hi Normal ctermfg=253 ctermbg=235 + + +" Comment Group +" ------------- +" any comment +hi Comment guifg=#606060 gui=none +hi Comment ctermfg=240 cterm=none + + +" Constant Group +" -------------- +" any constant +hi Constant guifg=#8cd0d3 gui=none +hi Constant ctermfg=116 cterm=none +" strings +hi String guifg=#80c0d9 gui=none +hi String ctermfg=110 cterm=none +" character constant +hi Character guifg=#80c0d9 gui=none +hi Character ctermfg=110 cterm=none +" numbers decimal/hex +hi Number guifg=#8cd0d3 gui=none +hi Number ctermfg=116 cterm=none +" true, false +hi Boolean guifg=#8cd0d3 gui=none +hi Boolean ctermfg=116 cterm=none +" float +hi Float guifg=#8cd0d3 gui=none +hi Float ctermfg=116 cterm=none + + +" Identifier Group +" ---------------- +" any variable name +hi Identifier guifg=#efaf7f gui=none +hi Identifier ctermfg=216 cterm=none +" function, method, class +hi Function guifg=#efaf7f gui=none +hi Function ctermfg=216 cterm=none + + +" Statement Group +" --------------- +" any statement +hi Statement guifg=#b3d38c gui=none +hi Statement ctermfg=150 cterm=none +" if, then, else +hi Conditional guifg=#b3d38c gui=none +hi Conditional ctermfg=150 cterm=none +" try, catch, throw, raise +hi Exception guifg=#b3d38c gui=none +hi Exception ctermfg=150 cterm=none +" for, while, do +hi Repeat guifg=#b3d38c gui=none +hi Repeat ctermfg=150 cterm=none +" case, default +hi Label guifg=#b3d38c gui=none +hi Label ctermfg=150 cterm=none +" sizeof, +, * +hi Operator guifg=#b3d38c gui=none +hi Operator ctermfg=150 cterm=none +" any other keyword +hi Keyword guifg=#b3d38c gui=none +hi Keyword ctermfg=150 cterm=none + + +" Preprocessor Group +" ------------------ +" generic preprocessor +hi PreProc guifg=#f0dfaf gui=none +hi PreProc ctermfg=223 cterm=none +" #include +hi Include guifg=#f0dfaf gui=none +hi Include ctermfg=223 cterm=none +" #define +hi Define guifg=#f0dfaf gui=none +hi Define ctermfg=223 cterm=none +" same as define +hi Macro guifg=#f0dfaf gui=none +hi Macro ctermfg=223 cterm=none +" #if, #else, #endif +hi PreCondit guifg=#f0dfaf gui=none +hi PreCondit ctermfg=223 cterm=none + + +" Type Group +" ---------- +" int, long, char +hi Type guifg=#93d6a9 gui=none +hi Type ctermfg=115 cterm=none +" static, register, volative +hi StorageClass guifg=#93d6a9 gui=none +hi StorageClass ctermfg=115 cterm=none +" struct, union, enum +hi Structure guifg=#93d6a9 gui=none +hi Structure ctermfg=115 cterm=none +" typedef +hi Typedef guifg=#93d6a9 gui=none +hi Typedef ctermfg=115 cterm=none + + +" Special Group +" ------------- +" any special symbol +hi Special guifg=#cca3b3 gui=none +hi Special ctermfg=181 cterm=none +" special character in a constant +hi SpecialChar guifg=#cca3b3 gui=none +hi SpecialChar ctermfg=181 cterm=none +" things you can CTRL-] +hi Tag guifg=#cca3b3 gui=none +hi Tag ctermfg=181 cterm=none +" character that needs attention +hi Delimiter guifg=#cca3b3 gui=none +hi Delimiter ctermfg=181 cterm=none +" special things inside a comment +hi SpecialComment guifg=#cca3b3 gui=none +hi SpecialComment ctermfg=181 cterm=none +" debugging statements +hi Debug guifg=#cca3b3 guibg=NONE gui=none +hi Debug ctermfg=181 ctermbg=NONE cterm=none + + +" Underlined Group +" ---------------- +" text that stands out, html links +hi Underlined guifg=fg gui=underline +hi Underlined ctermfg=fg cterm=underline + + +" Ignore Group +" ------------ +" left blank, hidden +hi Ignore guifg=bg +hi Ignore ctermfg=bg + + +" Error Group +" ----------- +" any erroneous construct +hi Error guifg=#e37170 guibg=#432323 gui=none +hi Error ctermfg=167 ctermbg=52 cterm=none + + +" Todo Group +" ---------- +" todo, fixme, note, xxx +hi Todo guifg=#efef8f guibg=NONE gui=underline +hi Todo ctermfg=228 ctermbg=NONE cterm=underline + + +" Spelling +" -------- +" word not recognized +hi SpellBad guisp=#ee0000 gui=undercurl +hi SpellBad ctermbg=9 cterm=undercurl +" word not capitalized +hi SpellCap guisp=#eeee00 gui=undercurl +hi SpellCap ctermbg=12 cterm=undercurl +" rare word +hi SpellRare guisp=#ffa500 gui=undercurl +hi SpellRare ctermbg=13 cterm=undercurl +" wrong spelling for selected region +hi SpellLocal guisp=#ffa500 gui=undercurl +hi SpellLocal ctermbg=14 cterm=undercurl + + +" Cursor +" ------ +" character under the cursor +hi Cursor guifg=bg guibg=#a3e3ed +hi Cursor ctermfg=bg ctermbg=153 +" like cursor, but used when in IME mode +hi CursorIM guifg=bg guibg=#96cdcd +hi CursorIM ctermfg=bg ctermbg=116 +" cursor column +hi CursorColumn guifg=NONE guibg=#202438 gui=none +hi CursorColumn ctermfg=NONE ctermbg=236 cterm=none +" cursor line/row +hi CursorLine gui=NONE guibg=#202438 gui=none +hi CursorLine cterm=NONE ctermbg=236 cterm=none + + +" Misc +" ---- +" directory names and other special names in listings +hi Directory guifg=#c0e0b0 gui=none +hi Directory ctermfg=151 cterm=none +" error messages on the command line +hi ErrorMsg guifg=#ee0000 guibg=NONE gui=none +hi ErrorMsg ctermfg=196 ctermbg=NONE cterm=none +" column separating vertically split windows +hi VertSplit guifg=#777777 guibg=#363946 gui=none +hi VertSplit ctermfg=242 ctermbg=237 cterm=none +" columns where signs are displayed (used in IDEs) +hi SignColumn guifg=#9fafaf guibg=#181818 gui=none +hi SignColumn ctermfg=145 ctermbg=233 cterm=none +" line numbers +hi LineNr guifg=#818698 guibg=#363946 +hi LineNr ctermfg=102 ctermbg=237 +" match parenthesis, brackets +hi MatchParen guifg=#00ff00 guibg=NONE gui=bold +hi MatchParen ctermfg=46 ctermbg=NONE cterm=bold +" the 'more' prompt when output takes more than one line +hi MoreMsg guifg=#2e8b57 gui=none +hi MoreMsg ctermfg=29 cterm=none +" text showing what mode you are in +hi ModeMsg guifg=#76d5f8 guibg=NONE gui=none +hi ModeMsg ctermfg=117 ctermbg=NONE cterm=none +" the '~' and '@' and showbreak, '>' double wide char doesn't fit on line +hi NonText guifg=#404040 gui=none +hi NonText ctermfg=235 cterm=none +" the hit-enter prompt (show more output) and yes/no questions +hi Question guifg=fg gui=none +hi Question ctermfg=fg cterm=none +" meta and special keys used with map, unprintable characters +hi SpecialKey guifg=#404040 +hi SpecialKey ctermfg=237 +" titles for output from :set all, :autocmd, etc +hi Title guifg=#62bdde gui=none +hi Title ctermfg=74 cterm=none +"hi Title guifg=#5ec8e5 gui=none +" warning messages +hi WarningMsg guifg=#e5786d gui=none +hi WarningMsg ctermfg=173 cterm=none +" current match in the wildmenu completion +hi WildMenu guifg=#cae682 guibg=#363946 gui=bold,underline +hi WildMenu ctermfg=16 ctermbg=186 cterm=bold + + +" Diff +" ---- +" added line +hi DiffAdd guifg=#80a090 guibg=#313c36 gui=none +hi DiffAdd ctermfg=108 ctermbg=22 cterm=none +" changed line +hi DiffChange guifg=NONE guibg=#4a343a gui=none +hi DiffChange ctermfg=fg ctermbg=52 cterm=none +" deleted line +hi DiffDelete guifg=#6c6661 guibg=#3c3631 gui=none +hi DiffDelete ctermfg=59 ctermbg=58 cterm=none +" changed text within line +hi DiffText guifg=#f05060 guibg=#4a343a gui=bold +hi DiffText ctermfg=203 ctermbg=52 cterm=bold + + +" Folds +" ----- +" line used for closed folds +hi Folded guifg=#91d6f8 guibg=#363946 gui=none +hi Folded ctermfg=117 ctermbg=238 cterm=none +" column on side used to indicated open and closed folds +hi FoldColumn guifg=#91d6f8 guibg=#363946 gui=none +hi FoldColumn ctermfg=117 ctermbg=238 cterm=none + + +" Search +" ------ +" highlight incremental search text; also highlight text replaced with :s///c +hi IncSearch guifg=#66ffff gui=reverse +hi IncSearch ctermfg=87 cterm=reverse +" hlsearch (last search pattern), also used for quickfix +hi Search guibg=#ffaa33 gui=none +hi Search ctermbg=214 cterm=none + + +" Popup Menu +" ---------- +" normal item in popup +hi Pmenu guifg=#e0e0e0 guibg=#303840 gui=none +hi Pmenu ctermfg=253 ctermbg=233 cterm=none +" selected item in popup +hi PmenuSel guifg=#cae682 guibg=#505860 gui=none +hi PmenuSel ctermfg=186 ctermbg=237 cterm=none +" scrollbar in popup +hi PMenuSbar guibg=#505860 gui=none +hi PMenuSbar ctermbg=59 cterm=none +" thumb of the scrollbar in the popup +hi PMenuThumb guibg=#808890 gui=none +hi PMenuThumb ctermbg=102 cterm=none + + +" Status Line +" ----------- +" status line for current window +hi StatusLine guifg=#e0e0e0 guibg=#363946 gui=bold +hi StatusLine ctermfg=254 ctermbg=237 cterm=bold +" status line for non-current windows +hi StatusLineNC guifg=#767986 guibg=#363946 gui=none +hi StatusLineNC ctermfg=244 ctermbg=237 cterm=none + + +" Tab Lines +" --------- +" tab pages line, not active tab page label +hi TabLine guifg=#b6bf98 guibg=#363946 gui=none +hi TabLine ctermfg=244 ctermbg=236 cterm=none +" tab pages line, where there are no labels +hi TabLineFill guifg=#cfcfaf guibg=#363946 gui=none +hi TabLineFill ctermfg=187 ctermbg=236 cterm=none +" tab pages line, active tab page label +hi TabLineSel guifg=#efefef guibg=#414658 gui=bold +hi TabLineSel ctermfg=254 ctermbg=236 cterm=bold + + +" Visual +" ------ +" visual mode selection +hi Visual guifg=NONE guibg=#364458 +hi Visual ctermfg=NONE ctermbg=24 +" visual mode selection when vim is not owning the selection (x11 only) +hi VisualNOS guifg=fg gui=underline +hi VisualNOS ctermfg=fg cterm=underline diff --git a/colors/tolerable256.vim b/colors/tolerable256.vim new file mode 100644 index 0000000..e6afb8f --- /dev/null +++ b/colors/tolerable256.vim @@ -0,0 +1,267 @@ +" Vim color file +" Maintainer: Ian Langworth +" Last Change: 2004 Dec 24 +" Email: + +" Color settings inspired by BBEdit for Mac OS, plus I liked +" the low-contrast comments from the 'oceandeep' colorscheme +" +" gryf: Nice colorscheme for printing in white, or to generate html in dark on +" bright. Added functions for converting it into terminal 256xterm codes. + +set background=light + +hi clear +if exists("syntax_on") + syntax reset +endif + +if !has("gui_running") && &t_Co != 88 && &t_Co != 256 + finish +endif + +let g:colors_name="tolerable" + +" functions {{{ +" returns an approximate grey index for the given grey level +fun! grey_number(x) + if &t_Co == 88 + if a:x < 23 + return 0 + elseif a:x < 69 + return 1 + elseif a:x < 103 + return 2 + elseif a:x < 127 + return 3 + elseif a:x < 150 + return 4 + elseif a:x < 173 + return 5 + elseif a:x < 196 + return 6 + elseif a:x < 219 + return 7 + elseif a:x < 243 + return 8 + else + return 9 + endif + else + if a:x < 14 + return 0 + else + let l:n = (a:x - 8) / 10 + let l:m = (a:x - 8) % 10 + if l:m < 5 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual grey level represented by the grey index +fun! grey_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 46 + elseif a:n == 2 + return 92 + elseif a:n == 3 + return 115 + elseif a:n == 4 + return 139 + elseif a:n == 5 + return 162 + elseif a:n == 6 + return 185 + elseif a:n == 7 + return 208 + elseif a:n == 8 + return 231 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 8 + (a:n * 10) + endif + endif +endfun + +" returns the palette index for the given grey index +fun! grey_color(n) + if &t_Co == 88 + if a:n == 0 + return 16 + elseif a:n == 9 + return 79 + else + return 79 + a:n + endif + else + if a:n == 0 + return 16 + elseif a:n == 25 + return 231 + else + return 231 + a:n + endif + endif +endfun + +" returns an approximate color index for the given color level +fun! rgb_number(x) + if &t_Co == 88 + if a:x < 69 + return 0 + elseif a:x < 172 + return 1 + elseif a:x < 230 + return 2 + else + return 3 + endif + else + if a:x < 75 + return 0 + else + let l:n = (a:x - 55) / 40 + let l:m = (a:x - 55) % 40 + if l:m < 20 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual color level for the given color index +fun! rgb_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 139 + elseif a:n == 2 + return 205 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 55 + (a:n * 40) + endif + endif +endfun + +" returns the palette index for the given R/G/B color indices +fun! rgb_color(x, y, z) + if &t_Co == 88 + return 16 + (a:x * 16) + (a:y * 4) + a:z + else + return 16 + (a:x * 36) + (a:y * 6) + a:z + endif +endfun + +" returns the palette index to approximate the given R/G/B color levels +fun! color(r, g, b) + " get the closest grey + let l:gx = grey_number(a:r) + let l:gy = grey_number(a:g) + let l:gz = grey_number(a:b) + + " get the closest color + let l:x = rgb_number(a:r) + let l:y = rgb_number(a:g) + let l:z = rgb_number(a:b) + + if l:gx == l:gy && l:gy == l:gz + " there are two possibilities + let l:dgr = grey_level(l:gx) - a:r + let l:dgg = grey_level(l:gy) - a:g + let l:dgb = grey_level(l:gz) - a:b + let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb) + let l:dr = rgb_level(l:gx) - a:r + let l:dg = rgb_level(l:gy) - a:g + let l:db = rgb_level(l:gz) - a:b + let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db) + if l:dgrey < l:drgb + " use the grey + return grey_color(l:gx) + else + " use the color + return rgb_color(l:x, l:y, l:z) + endif + else + " only one possibility + return rgb_color(l:x, l:y, l:z) + endif +endfun + +" returns the palette index to approximate the 'rrggbb' hex string +fun! rgb(rgb) + let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0 + let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0 + let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0 + return color(l:r, l:g, l:b) +endfun + +" sets the highlighting for the given group +fun! X(group, fg, bg, attr) + if a:fg != "" + exec "hi ".a:group." guifg=#".a:fg." ctermfg=".rgb(a:fg) + endif + if a:bg != "" + exec "hi ".a:group." guibg=#".a:bg." ctermbg=".rgb(a:bg) + endif + if a:attr != "" + if a:attr == 'italic' + exec "hi ".a:group." gui=".a:attr." cterm=none" + else + exec "hi ".a:group." gui=".a:attr." cterm=".a:attr + endif + endif +endfun +" }}} + +call X("Cursor", "006400", "", "none") +call X("CursorLine", "", "eeeeee", "none") +call X("CursorColumn", "", "eeeeee", "none") + +call X("Normal", "000000", "ffffff", "none") +call X("NonText", "ffae1b", "", "none") + +call X("Statement", "0000ff", "", "none") +call X("Special", "ff0000", "", "none") +call X("Constant", "8b0000", "", "none") +call X("Comment", "555555", "", "none") +call X("Preproc", "008b8b", "", "none") +call X("Type", "8b008b", "", "none") +call X("Identifier", "006400", "", "none") +call X("Title", "000000", "", "none") + +call X("StatusLine", "ffffff", "333333", "none") +call X("StatusLineNC", "ffffff", "333333", "none") +call X("VertSplit", "ffffff", "333333", "none") + +call X("Visual", "000000", "00ff00", "none") +call X("Search", "", "ffff00", "none") +call X("Directory", "00008b", "", "none") +call X("WarningMsg", "ff0000", "", "none") +call X("Error", "ffffff", "ff0000", "none") +call X("Todo", "000000", "ffff00", "none") + +call X("MoreMsg", "", "", "none") +call X("ModeMsg", "", "", "none") + +" vim:set ts=4 sw=4 noet fdm=marker: diff --git a/colors/wombat.vim b/colors/wombat.vim new file mode 100644 index 0000000..9ad1e56 --- /dev/null +++ b/colors/wombat.vim @@ -0,0 +1,51 @@ +" Maintainer: Lars H. Nielsen (dengmao@gmail.com) +" Last Change: January 22 2007 + +set background=dark + +hi clear + +if exists("syntax_on") + syntax reset +endif + +let colors_name = "wombat" + + +" Vim >= 7.0 specific colors +if version >= 700 + hi CursorLine guibg=#2d2d2d + hi CursorColumn guibg=#2d2d2d + hi MatchParen guifg=#f6f3e8 guibg=#857b6f gui=bold + hi Pmenu guifg=#f6f3e8 guibg=#444444 + hi PmenuSel guifg=#000000 guibg=#cae682 +endif + +" General colors +hi Cursor guifg=NONE guibg=#656565 gui=none +hi Normal guifg=#f6f3e8 guibg=#242424 gui=none +hi NonText guifg=#808080 guibg=#303030 gui=none +hi LineNr guifg=#857b6f guibg=#000000 gui=none +hi StatusLine guifg=#f6f3e8 guibg=#444444 gui=italic +hi StatusLineNC guifg=#857b6f guibg=#444444 gui=none +hi VertSplit guifg=#444444 guibg=#444444 gui=none +hi Folded guibg=#384048 guifg=#a0a8b0 gui=none +hi Title guifg=#f6f3e8 guibg=NONE gui=bold +hi Visual guifg=#f6f3e8 guibg=#444444 gui=none +hi SpecialKey guifg=#808080 guibg=#343434 gui=none + +" Syntax highlighting +hi Comment guifg=#99968b gui=italic +hi Todo guifg=#8f8f8f gui=italic +hi Constant guifg=#e5786d gui=none +hi String guifg=#95e454 gui=italic +hi Identifier guifg=#cae682 gui=none +hi Function guifg=#cae682 gui=none +hi Type guifg=#cae682 gui=none +hi Statement guifg=#8ac6f2 gui=none +hi Keyword guifg=#8ac6f2 gui=none +hi PreProc guifg=#e5786d gui=none +hi Number guifg=#e5786d gui=none +hi Special guifg=#e7f6da gui=none + + diff --git a/colors/wombat256.vim b/colors/wombat256.vim new file mode 100644 index 0000000..ecda096 --- /dev/null +++ b/colors/wombat256.vim @@ -0,0 +1,359 @@ +" Vim color file +" Maintainer: David Liang (bmdavll at gmail dot com) +" Last Change: November 28 2008 +" +" wombat256.vim - a modified version of Wombat by Lars Nielsen that also +" works on xterms with 88 or 256 colors. The algorithm for approximating the +" GUI colors with the xterm palette is from desert256.vim by Henry So Jr. + +set background=dark + +if version > 580 + hi clear + if exists("syntax_on") + syntax reset + endif +endif + +let g:colors_name = "wombat256" + +if !has("gui_running") && &t_Co != 88 && &t_Co != 256 + finish +endif + +" functions {{{ +" returns an approximate grey index for the given grey level +fun grey_number(x) + if &t_Co == 88 + if a:x < 23 + return 0 + elseif a:x < 69 + return 1 + elseif a:x < 103 + return 2 + elseif a:x < 127 + return 3 + elseif a:x < 150 + return 4 + elseif a:x < 173 + return 5 + elseif a:x < 196 + return 6 + elseif a:x < 219 + return 7 + elseif a:x < 243 + return 8 + else + return 9 + endif + else + if a:x < 14 + return 0 + else + let l:n = (a:x - 8) / 10 + let l:m = (a:x - 8) % 10 + if l:m < 5 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual grey level represented by the grey index +fun grey_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 46 + elseif a:n == 2 + return 92 + elseif a:n == 3 + return 115 + elseif a:n == 4 + return 139 + elseif a:n == 5 + return 162 + elseif a:n == 6 + return 185 + elseif a:n == 7 + return 208 + elseif a:n == 8 + return 231 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 8 + (a:n * 10) + endif + endif +endfun + +" returns the palette index for the given grey index +fun grey_color(n) + if &t_Co == 88 + if a:n == 0 + return 16 + elseif a:n == 9 + return 79 + else + return 79 + a:n + endif + else + if a:n == 0 + return 16 + elseif a:n == 25 + return 231 + else + return 231 + a:n + endif + endif +endfun + +" returns an approximate color index for the given color level +fun rgb_number(x) + if &t_Co == 88 + if a:x < 69 + return 0 + elseif a:x < 172 + return 1 + elseif a:x < 230 + return 2 + else + return 3 + endif + else + if a:x < 75 + return 0 + else + let l:n = (a:x - 55) / 40 + let l:m = (a:x - 55) % 40 + if l:m < 20 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual color level for the given color index +fun rgb_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 139 + elseif a:n == 2 + return 205 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 55 + (a:n * 40) + endif + endif +endfun + +" returns the palette index for the given R/G/B color indices +fun rgb_color(x, y, z) + if &t_Co == 88 + return 16 + (a:x * 16) + (a:y * 4) + a:z + else + return 16 + (a:x * 36) + (a:y * 6) + a:z + endif +endfun + +" returns the palette index to approximate the given R/G/B color levels +fun color(r, g, b) + " get the closest grey + let l:gx = grey_number(a:r) + let l:gy = grey_number(a:g) + let l:gz = grey_number(a:b) + + " get the closest color + let l:x = rgb_number(a:r) + let l:y = rgb_number(a:g) + let l:z = rgb_number(a:b) + + if l:gx == l:gy && l:gy == l:gz + " there are two possibilities + let l:dgr = grey_level(l:gx) - a:r + let l:dgg = grey_level(l:gy) - a:g + let l:dgb = grey_level(l:gz) - a:b + let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb) + let l:dr = rgb_level(l:gx) - a:r + let l:dg = rgb_level(l:gy) - a:g + let l:db = rgb_level(l:gz) - a:b + let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db) + if l:dgrey < l:drgb + " use the grey + return grey_color(l:gx) + else + " use the color + return rgb_color(l:x, l:y, l:z) + endif + else + " only one possibility + return rgb_color(l:x, l:y, l:z) + endif +endfun + +" returns the palette index to approximate the 'rrggbb' hex string +fun rgb(rgb) + let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0 + let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0 + let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0 + return color(l:r, l:g, l:b) +endfun + +" sets the highlighting for the given group +fun X(group, fg, bg, attr) + if a:fg != "" + exec "hi ".a:group." guifg=#".a:fg." ctermfg=".rgb(a:fg) + endif + if a:bg != "" + exec "hi ".a:group." guibg=#".a:bg." ctermbg=".rgb(a:bg) + endif + if a:attr != "" + if a:attr == 'italic' + exec "hi ".a:group." gui=".a:attr." cterm=none" + else + exec "hi ".a:group." gui=".a:attr." cterm=".a:attr + endif + endif +endfun +" }}} + +" italic only in gui and only where font is not fixed-misc! + +if has("gui_running") && &guifont !~ "Fixed" + let s:italic = "italic" +else + let s:italic = "none" +endif + + +" X(fg, bg, attr) +call X("Normal", "dddddd", "242424", "none") +call X("NonText", "4c4c36", "", "none") +call X("Cursor", "222222", "ecee90", "none") +call X("CursorLine", "", "32322e", "none") +call X("CursorColumn", "", "2d2d2d", "") + "CursorIM + "Question + "IncSearch +call X("Search", "444444", "af87d7", "") +call X("MatchParen", "ecee90", "857b6f", "bold") +call X("SpecialKey", "6c6c6c", "2d2d2d", "none") +call X("Visual", "ecee90", "597418", "none") +call X("LineNr", "857b6f", "121212", "none") +call X("SignColumn", "", "121212", "none") +call X("Folded", "a0a8b0", "404048", "none") +call X("Title", "f6f3e8", "", "bold") +call X("VertSplit", "444444", "444444", "none") +call X("StatusLine", "f6f3e8", "444444", s:italic) +call X("StatusLineNC", "857b6f", "444444", "none") + "Scrollbar + "Tooltip + "Menu + "WildMenu +call X("Pmenu", "f6f3e8", "444444", "") +call X("PmenuSel", "121212", "caeb82", "") +call X("WarningMsg", "ff0000", "", "") + "ErrorMsg + "ModeMsg + "MoreMsg + "Directory + "DiffAdd + "DiffChange + "DiffDelete + "DiffText + +" syntax highlighting +call X("Number", "e5786d", "", "none") +call X("Constant", "e5786d", "", "none") +call X("String", "95e454", "", s:italic) +call X("Comment", "c0bc6c", "", s:italic) +call X("Identifier", "caeb82", "", "none") +call X("Keyword", "87afff", "", "none") +call X("Statement", "87afff", "", "none") +call X("Function", "caeb82", "", "none") +call X("PreProc", "e5786d", "", "none") +call X("Type", "caeb82", "", "none") +call X("Special", "ffdead", "", "none") +call X("Todo", "857b6f", "", s:italic) + "Underlined + "Error + "Ignore +hi! link VisualNOS Visual +hi! link FoldColumn Folded +hi! link TabLineSel StatusLine +hi! link TabLineFill StatusLineNC +hi! link TabLine StatusLineNC +call X("TabLineSel", "f6f3e8", "", "none") + +" Python Highlighting for python.vim +"call X("pythonCoding", "ff0086", "", "none") +"call X("pythonRun", "ff0086", "", "none") +"call X("pythonBuiltinObji", "2b6ba2", "", "bold") +"call X("pythonBuiltinFunc", "2b6ba2", "", "bold") +"call X("pythonException", "ee0000", "", "bold") +"call X("pythonExClass", "66cd66", "", "bold") +"call X("pythonSpaceError", "270000", "", "none") +"call X("pythonDocTest", "2f5f49", "", "none") +"call X("pythonDocTest2", "3b916a", "", "none") +"call X("pythonFunction", "ee0000", "", "bold") +"call X("pythonClass", "ff0086", "", "bold") + +call X("ShowMarksHLl", "ab8042", "121212", "bold") +"call X("ShowMarksHLu", "ab4242", "121212", "bold") +call X("ShowMarksHLu", "aaab42", "121212", "bold") +call X("ShowMarksHLo", "42ab47", "121212", "bold") +call X("ShowMarksHLm", "aaab42", "121212", "bold") + +" Diff colors +"call X("DiffAdd", "", "1d1d50", "bold") +"call X("DiffText", "", "9f1e1e", "bold") +"call X("DiffDelete", "", "1d5050", "bold") +"call X("DiffChange", "", "4c1c4c", "bold") + +call X("DiffAdd", "", "646464", "bold") +call X("DiffText", "", "bf5f00", "bold") +call X("DiffDelete", "343434", "101010", "bold") +call X("DiffChange", "", "424242", "bold") + +" DiffAdd xxx term=bold ctermbg=4 +" DiffChange xxx term=bold ctermbg=5 +" DiffDelete xxx term=bold ctermfg=12 ctermbg=6 +" DiffText xxx term=reverse cterm=bold ctermbg=9 + +if ! has('gui_running') + " spell, make it underline, and less bright colors. only for terminal + call X("SpellBad", "", "880000", "underline") + call X("SpellCap", "", "000088", "underline") + call X("SpellRare", "", "880088", "underline") + call X("SpellLocal", "", "008888", "underline") +endif + +" delete functions {{{ +delf X +delf rgb +delf color +delf rgb_color +delf rgb_level +delf rgb_number +delf grey_color +delf grey_level +delf grey_number +" }}} + +" vim:set ts=4 sw=4 noet fdm=marker: diff --git a/colors/wombat256_.vim b/colors/wombat256_.vim new file mode 100644 index 0000000..c7ae0f8 --- /dev/null +++ b/colors/wombat256_.vim @@ -0,0 +1,348 @@ +" Vim color file +" Maintainer: David Liang (bmdavll at gmail dot com) +" Last Change: November 28 2008 +" +" wombat256.vim - a modified version of Wombat by Lars Nielsen that also +" works on xterms with 88 or 256 colors. The algorithm for approximating the +" GUI colors with the xterm palette is from desert256.vim by Henry So Jr. + +set background=dark + +if version > 580 + hi clear + if exists("syntax_on") + syntax reset + endif +endif + +let g:colors_name = "wombat256" + +if !has("gui_running") && &t_Co != 88 && &t_Co != 256 + finish +endif + +" functions {{{ +" returns an approximate grey index for the given grey level +fun grey_number(x) + if &t_Co == 88 + if a:x < 23 + return 0 + elseif a:x < 69 + return 1 + elseif a:x < 103 + return 2 + elseif a:x < 127 + return 3 + elseif a:x < 150 + return 4 + elseif a:x < 173 + return 5 + elseif a:x < 196 + return 6 + elseif a:x < 219 + return 7 + elseif a:x < 243 + return 8 + else + return 9 + endif + else + if a:x < 14 + return 0 + else + let l:n = (a:x - 8) / 10 + let l:m = (a:x - 8) % 10 + if l:m < 5 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual grey level represented by the grey index +fun grey_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 46 + elseif a:n == 2 + return 92 + elseif a:n == 3 + return 115 + elseif a:n == 4 + return 139 + elseif a:n == 5 + return 162 + elseif a:n == 6 + return 185 + elseif a:n == 7 + return 208 + elseif a:n == 8 + return 231 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 8 + (a:n * 10) + endif + endif +endfun + +" returns the palette index for the given grey index +fun grey_color(n) + if &t_Co == 88 + if a:n == 0 + return 16 + elseif a:n == 9 + return 79 + else + return 79 + a:n + endif + else + if a:n == 0 + return 16 + elseif a:n == 25 + return 231 + else + return 231 + a:n + endif + endif +endfun + +" returns an approximate color index for the given color level +fun rgb_number(x) + if &t_Co == 88 + if a:x < 69 + return 0 + elseif a:x < 172 + return 1 + elseif a:x < 230 + return 2 + else + return 3 + endif + else + if a:x < 75 + return 0 + else + let l:n = (a:x - 55) / 40 + let l:m = (a:x - 55) % 40 + if l:m < 20 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual color level for the given color index +fun rgb_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 139 + elseif a:n == 2 + return 205 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 55 + (a:n * 40) + endif + endif +endfun + +" returns the palette index for the given R/G/B color indices +fun rgb_color(x, y, z) + if &t_Co == 88 + return 16 + (a:x * 16) + (a:y * 4) + a:z + else + return 16 + (a:x * 36) + (a:y * 6) + a:z + endif +endfun + +" returns the palette index to approximate the given R/G/B color levels +fun color(r, g, b) + " get the closest grey + let l:gx = grey_number(a:r) + let l:gy = grey_number(a:g) + let l:gz = grey_number(a:b) + + " get the closest color + let l:x = rgb_number(a:r) + let l:y = rgb_number(a:g) + let l:z = rgb_number(a:b) + + if l:gx == l:gy && l:gy == l:gz + " there are two possibilities + let l:dgr = grey_level(l:gx) - a:r + let l:dgg = grey_level(l:gy) - a:g + let l:dgb = grey_level(l:gz) - a:b + let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb) + let l:dr = rgb_level(l:gx) - a:r + let l:dg = rgb_level(l:gy) - a:g + let l:db = rgb_level(l:gz) - a:b + let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db) + if l:dgrey < l:drgb + " use the grey + return grey_color(l:gx) + else + " use the color + return rgb_color(l:x, l:y, l:z) + endif + else + " only one possibility + return rgb_color(l:x, l:y, l:z) + endif +endfun + +" returns the palette index to approximate the 'rrggbb' hex string +fun rgb(rgb) + let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0 + let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0 + let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0 + return color(l:r, l:g, l:b) +endfun + +" sets the highlighting for the given group +fun X(group, fg, bg, attr) + if a:fg != "" + exec "hi ".a:group." guifg=#".a:fg." ctermfg=".rgb(a:fg) + endif + if a:bg != "" + exec "hi ".a:group." guibg=#".a:bg." ctermbg=".rgb(a:bg) + endif + if a:attr != "" + if a:attr == 'italic' + exec "hi ".a:group." gui=".a:attr." cterm=none" + else + exec "hi ".a:group." gui=".a:attr." cterm=".a:attr + endif + endif +endfun +" }}} + +" X(fg, bg, attr) +call X("Normal", "dddddd", "242424", "none") +call X("NonText", "4c4c36", "", "none") +call X("Cursor", "222222", "ecee90", "none") +call X("CursorLine", "", "32322e", "none") +call X("CursorColumn", "", "2d2d2d", "") + "CursorIM + "Question + "IncSearch +call X("Search", "444444", "af87d7", "") +call X("MatchParen", "ecee90", "857b6f", "bold") +call X("SpecialKey", "6c6c6c", "2d2d2d", "none") +call X("Visual", "ecee90", "597418", "none") +call X("LineNr", "857b6f", "121212", "none") +call X("SignColumn", "", "121212", "none") +call X("Folded", "a0a8b0", "404048", "none") +call X("Title", "f6f3e8", "", "bold") +call X("VertSplit", "444444", "444444", "none") +call X("StatusLine", "f6f3e8", "444444", "italic") +call X("StatusLineNC", "857b6f", "444444", "none") + "Scrollbar + "Tooltip + "Menu + "WildMenu +call X("Pmenu", "f6f3e8", "444444", "") +call X("PmenuSel", "121212", "caeb82", "") +call X("WarningMsg", "ff0000", "", "") + "ErrorMsg + "ModeMsg + "MoreMsg + "Directory + "DiffAdd + "DiffChange + "DiffDelete + "DiffText + +" syntax highlighting +call X("Number", "e5786d", "", "none") +call X("Constant", "e5786d", "", "none") +call X("String", "95e454", "", "italic") +call X("Comment", "c0bc6c", "", "italic") +call X("Identifier", "caeb82", "", "none") +call X("Keyword", "87afff", "", "none") +call X("Statement", "87afff", "", "none") +call X("Function", "caeb82", "", "none") +call X("PreProc", "e5786d", "", "none") +call X("Type", "caeb82", "", "none") +call X("Special", "ffdead", "", "none") +call X("Todo", "857b6f", "", "italic") + "Underlined + "Error + "Ignore +hi! link VisualNOS Visual +hi! link FoldColumn Folded +hi! link TabLineSel StatusLine +hi! link TabLineFill StatusLineNC +hi! link TabLine StatusLineNC +call X("TabLineSel", "f6f3e8", "", "none") + +" Python Highlighting for python.vim +"call X("pythonCoding", "ff0086", "", "none") +"call X("pythonRun", "ff0086", "", "none") +"call X("pythonBuiltinObji", "2b6ba2", "", "bold") +"call X("pythonBuiltinFunc", "2b6ba2", "", "bold") +"call X("pythonException", "ee0000", "", "bold") +"call X("pythonExClass", "66cd66", "", "bold") +"call X("pythonSpaceError", "270000", "", "none") +"call X("pythonDocTest", "2f5f49", "", "none") +"call X("pythonDocTest2", "3b916a", "", "none") +"call X("pythonFunction", "ee0000", "", "bold") +"call X("pythonClass", "ff0086", "", "bold") + +call X("ShowMarksHLl", "ab8042", "121212", "bold") +"call X("ShowMarksHLu", "ab4242", "121212", "bold") +call X("ShowMarksHLu", "aaab42", "121212", "bold") +call X("ShowMarksHLo", "42ab47", "121212", "bold") +call X("ShowMarksHLm", "aaab42", "121212", "bold") + +" Diff colors +"call X("DiffAdd", "", "1d1d50", "bold") +"call X("DiffText", "", "9f1e1e", "bold") +"call X("DiffDelete", "", "1d5050", "bold") +"call X("DiffChange", "", "4c1c4c", "bold") + +call X("DiffAdd", "", "646464", "bold") +call X("DiffText", "", "bf5f00", "bold") +call X("DiffDelete", "343434", "101010", "bold") +call X("DiffChange", "", "424242", "bold") + +" DiffAdd xxx term=bold ctermbg=4 +" DiffChange xxx term=bold ctermbg=5 +" DiffDelete xxx term=bold ctermfg=12 ctermbg=6 +" DiffText xxx term=reverse cterm=bold ctermbg=9 + +" spell, make it underline, and less bright colors +call X("SpellBad", "", "880000", "underline") +call X("SpellCap", "", "000088", "underline") +call X("SpellRare", "", "880088", "underline") +call X("SpellLocal", "", "008888", "underline") + +" delete functions {{{ +delf X +delf rgb +delf color +delf rgb_color +delf rgb_level +delf rgb_number +delf grey_color +delf grey_level +delf grey_number +" }}} + +" vim:set ts=4 sw=4 noet fdm=marker: diff --git a/colors/wombat256grf.vim b/colors/wombat256grf.vim new file mode 100644 index 0000000..ecda096 --- /dev/null +++ b/colors/wombat256grf.vim @@ -0,0 +1,359 @@ +" Vim color file +" Maintainer: David Liang (bmdavll at gmail dot com) +" Last Change: November 28 2008 +" +" wombat256.vim - a modified version of Wombat by Lars Nielsen that also +" works on xterms with 88 or 256 colors. The algorithm for approximating the +" GUI colors with the xterm palette is from desert256.vim by Henry So Jr. + +set background=dark + +if version > 580 + hi clear + if exists("syntax_on") + syntax reset + endif +endif + +let g:colors_name = "wombat256" + +if !has("gui_running") && &t_Co != 88 && &t_Co != 256 + finish +endif + +" functions {{{ +" returns an approximate grey index for the given grey level +fun grey_number(x) + if &t_Co == 88 + if a:x < 23 + return 0 + elseif a:x < 69 + return 1 + elseif a:x < 103 + return 2 + elseif a:x < 127 + return 3 + elseif a:x < 150 + return 4 + elseif a:x < 173 + return 5 + elseif a:x < 196 + return 6 + elseif a:x < 219 + return 7 + elseif a:x < 243 + return 8 + else + return 9 + endif + else + if a:x < 14 + return 0 + else + let l:n = (a:x - 8) / 10 + let l:m = (a:x - 8) % 10 + if l:m < 5 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual grey level represented by the grey index +fun grey_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 46 + elseif a:n == 2 + return 92 + elseif a:n == 3 + return 115 + elseif a:n == 4 + return 139 + elseif a:n == 5 + return 162 + elseif a:n == 6 + return 185 + elseif a:n == 7 + return 208 + elseif a:n == 8 + return 231 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 8 + (a:n * 10) + endif + endif +endfun + +" returns the palette index for the given grey index +fun grey_color(n) + if &t_Co == 88 + if a:n == 0 + return 16 + elseif a:n == 9 + return 79 + else + return 79 + a:n + endif + else + if a:n == 0 + return 16 + elseif a:n == 25 + return 231 + else + return 231 + a:n + endif + endif +endfun + +" returns an approximate color index for the given color level +fun rgb_number(x) + if &t_Co == 88 + if a:x < 69 + return 0 + elseif a:x < 172 + return 1 + elseif a:x < 230 + return 2 + else + return 3 + endif + else + if a:x < 75 + return 0 + else + let l:n = (a:x - 55) / 40 + let l:m = (a:x - 55) % 40 + if l:m < 20 + return l:n + else + return l:n + 1 + endif + endif + endif +endfun + +" returns the actual color level for the given color index +fun rgb_level(n) + if &t_Co == 88 + if a:n == 0 + return 0 + elseif a:n == 1 + return 139 + elseif a:n == 2 + return 205 + else + return 255 + endif + else + if a:n == 0 + return 0 + else + return 55 + (a:n * 40) + endif + endif +endfun + +" returns the palette index for the given R/G/B color indices +fun rgb_color(x, y, z) + if &t_Co == 88 + return 16 + (a:x * 16) + (a:y * 4) + a:z + else + return 16 + (a:x * 36) + (a:y * 6) + a:z + endif +endfun + +" returns the palette index to approximate the given R/G/B color levels +fun color(r, g, b) + " get the closest grey + let l:gx = grey_number(a:r) + let l:gy = grey_number(a:g) + let l:gz = grey_number(a:b) + + " get the closest color + let l:x = rgb_number(a:r) + let l:y = rgb_number(a:g) + let l:z = rgb_number(a:b) + + if l:gx == l:gy && l:gy == l:gz + " there are two possibilities + let l:dgr = grey_level(l:gx) - a:r + let l:dgg = grey_level(l:gy) - a:g + let l:dgb = grey_level(l:gz) - a:b + let l:dgrey = (l:dgr * l:dgr) + (l:dgg * l:dgg) + (l:dgb * l:dgb) + let l:dr = rgb_level(l:gx) - a:r + let l:dg = rgb_level(l:gy) - a:g + let l:db = rgb_level(l:gz) - a:b + let l:drgb = (l:dr * l:dr) + (l:dg * l:dg) + (l:db * l:db) + if l:dgrey < l:drgb + " use the grey + return grey_color(l:gx) + else + " use the color + return rgb_color(l:x, l:y, l:z) + endif + else + " only one possibility + return rgb_color(l:x, l:y, l:z) + endif +endfun + +" returns the palette index to approximate the 'rrggbb' hex string +fun rgb(rgb) + let l:r = ("0x" . strpart(a:rgb, 0, 2)) + 0 + let l:g = ("0x" . strpart(a:rgb, 2, 2)) + 0 + let l:b = ("0x" . strpart(a:rgb, 4, 2)) + 0 + return color(l:r, l:g, l:b) +endfun + +" sets the highlighting for the given group +fun X(group, fg, bg, attr) + if a:fg != "" + exec "hi ".a:group." guifg=#".a:fg." ctermfg=".rgb(a:fg) + endif + if a:bg != "" + exec "hi ".a:group." guibg=#".a:bg." ctermbg=".rgb(a:bg) + endif + if a:attr != "" + if a:attr == 'italic' + exec "hi ".a:group." gui=".a:attr." cterm=none" + else + exec "hi ".a:group." gui=".a:attr." cterm=".a:attr + endif + endif +endfun +" }}} + +" italic only in gui and only where font is not fixed-misc! + +if has("gui_running") && &guifont !~ "Fixed" + let s:italic = "italic" +else + let s:italic = "none" +endif + + +" X(fg, bg, attr) +call X("Normal", "dddddd", "242424", "none") +call X("NonText", "4c4c36", "", "none") +call X("Cursor", "222222", "ecee90", "none") +call X("CursorLine", "", "32322e", "none") +call X("CursorColumn", "", "2d2d2d", "") + "CursorIM + "Question + "IncSearch +call X("Search", "444444", "af87d7", "") +call X("MatchParen", "ecee90", "857b6f", "bold") +call X("SpecialKey", "6c6c6c", "2d2d2d", "none") +call X("Visual", "ecee90", "597418", "none") +call X("LineNr", "857b6f", "121212", "none") +call X("SignColumn", "", "121212", "none") +call X("Folded", "a0a8b0", "404048", "none") +call X("Title", "f6f3e8", "", "bold") +call X("VertSplit", "444444", "444444", "none") +call X("StatusLine", "f6f3e8", "444444", s:italic) +call X("StatusLineNC", "857b6f", "444444", "none") + "Scrollbar + "Tooltip + "Menu + "WildMenu +call X("Pmenu", "f6f3e8", "444444", "") +call X("PmenuSel", "121212", "caeb82", "") +call X("WarningMsg", "ff0000", "", "") + "ErrorMsg + "ModeMsg + "MoreMsg + "Directory + "DiffAdd + "DiffChange + "DiffDelete + "DiffText + +" syntax highlighting +call X("Number", "e5786d", "", "none") +call X("Constant", "e5786d", "", "none") +call X("String", "95e454", "", s:italic) +call X("Comment", "c0bc6c", "", s:italic) +call X("Identifier", "caeb82", "", "none") +call X("Keyword", "87afff", "", "none") +call X("Statement", "87afff", "", "none") +call X("Function", "caeb82", "", "none") +call X("PreProc", "e5786d", "", "none") +call X("Type", "caeb82", "", "none") +call X("Special", "ffdead", "", "none") +call X("Todo", "857b6f", "", s:italic) + "Underlined + "Error + "Ignore +hi! link VisualNOS Visual +hi! link FoldColumn Folded +hi! link TabLineSel StatusLine +hi! link TabLineFill StatusLineNC +hi! link TabLine StatusLineNC +call X("TabLineSel", "f6f3e8", "", "none") + +" Python Highlighting for python.vim +"call X("pythonCoding", "ff0086", "", "none") +"call X("pythonRun", "ff0086", "", "none") +"call X("pythonBuiltinObji", "2b6ba2", "", "bold") +"call X("pythonBuiltinFunc", "2b6ba2", "", "bold") +"call X("pythonException", "ee0000", "", "bold") +"call X("pythonExClass", "66cd66", "", "bold") +"call X("pythonSpaceError", "270000", "", "none") +"call X("pythonDocTest", "2f5f49", "", "none") +"call X("pythonDocTest2", "3b916a", "", "none") +"call X("pythonFunction", "ee0000", "", "bold") +"call X("pythonClass", "ff0086", "", "bold") + +call X("ShowMarksHLl", "ab8042", "121212", "bold") +"call X("ShowMarksHLu", "ab4242", "121212", "bold") +call X("ShowMarksHLu", "aaab42", "121212", "bold") +call X("ShowMarksHLo", "42ab47", "121212", "bold") +call X("ShowMarksHLm", "aaab42", "121212", "bold") + +" Diff colors +"call X("DiffAdd", "", "1d1d50", "bold") +"call X("DiffText", "", "9f1e1e", "bold") +"call X("DiffDelete", "", "1d5050", "bold") +"call X("DiffChange", "", "4c1c4c", "bold") + +call X("DiffAdd", "", "646464", "bold") +call X("DiffText", "", "bf5f00", "bold") +call X("DiffDelete", "343434", "101010", "bold") +call X("DiffChange", "", "424242", "bold") + +" DiffAdd xxx term=bold ctermbg=4 +" DiffChange xxx term=bold ctermbg=5 +" DiffDelete xxx term=bold ctermfg=12 ctermbg=6 +" DiffText xxx term=reverse cterm=bold ctermbg=9 + +if ! has('gui_running') + " spell, make it underline, and less bright colors. only for terminal + call X("SpellBad", "", "880000", "underline") + call X("SpellCap", "", "000088", "underline") + call X("SpellRare", "", "880088", "underline") + call X("SpellLocal", "", "008888", "underline") +endif + +" delete functions {{{ +delf X +delf rgb +delf color +delf rgb_color +delf rgb_level +delf rgb_number +delf grey_color +delf grey_level +delf grey_number +" }}} + +" vim:set ts=4 sw=4 noet fdm=marker: diff --git a/compiler/rubber.vim b/compiler/rubber.vim new file mode 100644 index 0000000..fd17759 --- /dev/null +++ b/compiler/rubber.vim @@ -0,0 +1,14 @@ +" Vim compiler file +" Compiler: pdf creator out of LaTeX files using rubber +if exists("current_compiler") + finish +endif + +let current_compiler = "rubber" +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal +endif + +CompilerSet makeprg=rubber\ -d\ % +"CompilerSet efm=%f:%l:\ [%t]%m,%f:%l:%m + diff --git a/doc/NERD_tree.txt b/doc/NERD_tree.txt new file mode 100644 index 0000000..2e2278c --- /dev/null +++ b/doc/NERD_tree.txt @@ -0,0 +1,1222 @@ +*NERD_tree.txt* A tree explorer plugin that owns your momma! + + + + omg its ... ~ + + ________ ________ _ ____________ ____ __________ ____________~ + /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~ + / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~ + / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~ + /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~ + + + Reference Manual~ + + + + +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERD tree mappings................|NERDTreeMappings| + 2.4.The NERD tree menu................|NERDTreeMenu| + 3.Options.................................|NERDTreeOptions| + 3.1.Option summary....................|NERDTreeOptionSummary| + 3.2.Option details....................|NERDTreeOptionDetails| + 4.The NERD tree API.......................|NERDTreeAPI| + 4.1.Key map API.......................|NERDTreeKeymapAPI| + 4.2.Menu API..........................|NERDTreeMenuAPI| + 5.About...................................|NERDTreeAbout| + 6.Changelog...............................|NERDTreeChangelog| + 7.Credits.................................|NERDTreeCredits| + 8.License.................................|NERDTreeLicense| + +============================================================================== +1. Intro *NERDTree* + +What is this "NERD tree"?? + +The NERD tree allows you to explore your filesystem and to open files and +directories. It presents the filesystem to you in the form of a tree which you +manipulate with the keyboard and/or mouse. It also allows you to perform +simple filesystem operations. + +The following features and functionality are provided by the NERD tree: + * Files and directories are displayed in a hierarchical tree structure + * Different highlighting is provided for the following types of nodes: + * files + * directories + * sym-links + * windows .lnk files + * read-only files + * executable files + * Many (customisable) mappings are provided to manipulate the tree: + * Mappings to open/close/explore directory nodes + * Mappings to open files in new/existing windows/tabs + * Mappings to change the current root of the tree + * Mappings to navigate around the tree + * ... + * Directories and files can be bookmarked. + * Most NERD tree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * custom file filters to prevent e.g. vim backup files being displayed + * optional displaying of hidden files (. files) + * files can be "turned off" so that only directories are displayed + * The position and size of the NERD tree window can be customised + * The order in which the nodes in the tree are listed can be customised. + * A model of your filesystem is created/maintained as you explore it. This + has several advantages: + * All filesystem information is cached and is only re-read on demand + * If you revisit a part of the tree that you left earlier in your + session, the directory nodes will be opened/closed as you left them + * The script remembers the cursor position and window position in the NERD + tree so you can toggle it off (or just close the tree window) and then + reopen it (with NERDTreeToggle) the NERD tree window will appear exactly + as you left it + * You can have a separate NERD tree for each tab, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netw), so if + you :edit a directory a (slighly modified) NERD tree will appear in the + current window + * A programmable menu system is provided (simulates right clicking on a + node) + * one default menu plugin is provided to perform basic filesytem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [ | ] *:NERDTree* + Opens a fresh NERD tree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeFromBookmark *:NERDTreeFromBookmark* + Opens a fresh NERD tree with the root initialized to the dir for + . This only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [ | ] *:NERDTreeToggle* + If a NERD tree already exists for this tab, it is reopened and rendered + again. If no NERD tree exists for this tab then this command acts the + same as the |:NERDTree| command. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERD tree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERD tree exists, that tree is automatically mirrored. If + more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERD tree in this tab. + +:NERDTreeFind *:NERDTreeFind* + Find the current file in the tree. If no tree exists for the current tab, + or the file is not under the current root, then initialize a new tree where + the root is the directory of the current file. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note that the following commands are only available in the NERD tree buffer. + +:Bookmark + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + must point to a file. The file is opened as though |NERDTree-o| + was applied. If the node is cached under the current root then it will be + revealed and the cursor will be placed on it. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default Description~ help-tag~ +Key~ + +o.......Open files, directories and bookmarks....................|NERDTree-o| +go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| +t.......Open selected node/bookmark in a new tab.................|NERDTree-t| +T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| +i.......Open selected file in a split window.....................|NERDTree-i| +gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| +s.......Open selected file in a new vsplit.......................|NERDTree-s| +gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| +O.......Recursively open the selected directory..................|NERDTree-O| +x.......Close the current nodes parent...........................|NERDTree-x| +X.......Recursively close all children of the current node.......|NERDTree-X| +e.......Edit the current dif.....................................|NERDTree-e| + +...............same as |NERDTree-o|. +double-click.......same as the |NERDTree-o| map. +middle-click.......same as |NERDTree-i| for files, same as + |NERDTree-e| for dirs. + +D.......Delete the current bookmark .............................|NERDTree-D| + +P.......Jump to the root node....................................|NERDTree-P| +p.......Jump to current nodes parent.............................|NERDTree-p| +K.......Jump up inside directories at the current tree depth.....|NERDTree-K| +J.......Jump down inside directories at the current tree depth...|NERDTree-J| +...Jump down to the next sibling of the current directory...|NERDTree-C-J| +...Jump up to the previous sibling of the current directory.|NERDTree-C-K| + +C.......Change the tree root to the selected dir.................|NERDTree-C| +u.......Move the tree root up one directory......................|NERDTree-u| +U.......Same as 'u' except the old root node is left open........|NERDTree-U| +r.......Recursively refresh the current directory................|NERDTree-r| +R.......Recursively refresh the current root.....................|NERDTree-R| +m.......Display the NERD tree menu...............................|NERDTree-m| +cd......Change the CWD to the dir of the selected node...........|NERDTree-cd| + +I.......Toggle whether hidden files displayed....................|NERDTree-I| +f.......Toggle whether the file filters are used.................|NERDTree-f| +F.......Toggle whether files are displayed.......................|NERDTree-F| +B.......Toggle whether the bookmark table is displayed...........|NERDTree-B| + +q.......Close the NERDTree window................................|NERDTree-q| +A.......Zoom (maximize/minimize) the NERDTree window.............|NERDTree-A| +?.......Toggle the display of the quick help.....................|NERDTree-?| + +------------------------------------------------------------------------------ + *NERDTree-o* +Default key: o +Map option: NERDTreeMapActivateNode +Applies to: files and directories. + +If a file node is selected, it is opened in the previous window. + +If a directory is selected it is opened or closed depending on its current +state. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *NERDTree-go* +Default key: go +Map option: None +Applies to: files. + +If a file node is selected, it is opened in the previous window, but the +cursor does not move. + +The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see +|NERDTree-o|). + +------------------------------------------------------------------------------ + *NERDTree-t* +Default key: t +Map option: NERDTreeMapOpenInTab +Applies to: files and directories. + +Opens the selected file in a new tab. If a directory is selected, a fresh +NERD Tree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERD tree for +that directory in a new tab. If the bookmark points to a file, open that file +in a new tab. + +------------------------------------------------------------------------------ + *NERDTree-T* +Default key: T +Map option: NERDTreeMapOpenInTabSilent +Applies to: files and directories. + +The same as |NERDTree-t| except that the focus is kept in the current tab. + +------------------------------------------------------------------------------ + *NERDTree-i* +Default key: i +Map option: NERDTreeMapOpenSplit +Applies to: files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map option: None +Applies to: files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map option: NERDTreeMapOpenVSplit +Applies to: files. + +Opens the selected file in a new vertically split window and puts the cursor in +the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map option: None +Applies to: files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *NERDTree-O* +Default key: O +Map option: NERDTreeMapOpenRecursively +Applies to: directories. + +Recursively opens the selelected directory. + +All files and directories are cached, but if a directory would not be +displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the +hidden file filter (see |'NERDTreeShowHidden'|) then its contents are not +cached. This is handy, especially if you have .svn directories. + +------------------------------------------------------------------------------ + *NERDTree-x* +Default key: x +Map option: NERDTreeMapCloseDir +Applies to: files and directories. + +Closes the parent of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-X* +Default key: X +Map option: NERDTreeMapCloseChildren +Applies to: directories. + +Recursively closes all children of the selected directory. + +Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. + +------------------------------------------------------------------------------ + *NERDTree-e* +Default key: e +Map option: NERDTreeMapOpenExpl +Applies to: files and directories. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERD tree or a netrw being opened, depending on +|'NERDTreeHijackNetrw'|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map option: NERDTreeMapDeleteBookmark +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *NERDTree-P* +Default key: P +Map option: NERDTreeMapJumpRoot +Applies to: no restrictions. + +Jump to the tree root. + +------------------------------------------------------------------------------ + *NERDTree-p* +Default key: p +Map option: NERDTreeMapJumpParent +Applies to: files and directories. + +Jump to the parent node of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-K* +Default key: K +Map option: NERDTreeMapJumpFirstChild +Applies to: files and directories. + +Jump to the first child of the current nodes parent. + +If the cursor is already on the first node then do the following: + * loop back thru the siblings of the current nodes parent until we find an + open dir with children + * go to the first child of that node + +------------------------------------------------------------------------------ + *NERDTree-J* +Default key: J +Map option: NERDTreeMapJumpLastChild +Applies to: files and directories. + +Jump to the last child of the current nodes parent. + +If the cursor is already on the last node then do the following: + * loop forward thru the siblings of the current nodes parent until we find + an open dir with children + * go to the last child of that node + +------------------------------------------------------------------------------ + *NERDTree-C-J* +Default key: +Map option: NERDTreeMapJumpNextSibling +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: +Map option: NERDTreeMapJumpPrevSibling +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map option: NERDTreeMapChdir +Applies to: directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *NERDTree-u* +Default key: u +Map option: NERDTreeMapUpdir +Applies to: no restrictions. + +Move the tree root up a dir (like doing a "cd .."). + +------------------------------------------------------------------------------ + *NERDTree-U* +Default key: U +Map option: NERDTreeMapUpdirKeepOpen +Applies to: no restrictions. + +Like |NERDTree-u| except that the old tree root is kept open. + +------------------------------------------------------------------------------ + *NERDTree-r* +Default key: r +Map option: NERDTreeMapRefresh +Applies to: files and directories. + +If a dir is selected, recursively refresh that dir, i.e. scan the filesystem +for changes and represent them in the tree. + +If a file node is selected then the above is done on it's parent. + +------------------------------------------------------------------------------ + *NERDTree-R* +Default key: R +Map option: NERDTreeMapRefreshRoot +Applies to: no restrictions. + +Recursively refresh the tree root. + +------------------------------------------------------------------------------ + *NERDTree-m* +Default key: m +Map option: NERDTreeMapMenu +Applies to: files and directories. + +Display the NERD tree menu. See |NERDTreeMenu| for details. + +------------------------------------------------------------------------------ + *NERDTree-cd* +Default key: cd +Map option: NERDTreeMapChdir +Applies to: files and directories. + +Change vims current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map option: NERDTreeMapToggleHidden +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *NERDTree-f* +Default key: f +Map option: NERDTreeMapToggleFilters +Applies to: no restrictions. + +Toggles whether file filters are used. See |'NERDTreeIgnore'| for details. + +------------------------------------------------------------------------------ + *NERDTree-F* +Default key: F +Map option: NERDTreeMapToggleFiles +Applies to: no restrictions. + +Toggles whether file nodes are displayed. + +------------------------------------------------------------------------------ + *NERDTree-B* +Default key: B +Map option: NERDTreeMapToggleBookmarks +Applies to: no restrictions. + +Toggles whether the bookmarks table is displayed. + +------------------------------------------------------------------------------ + *NERDTree-q* +Default key: q +Map option: NERDTreeMapQuit +Applies to: no restrictions. + +Closes the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-A* +Default key: A +Map option: NERDTreeMapToggleZoom +Applies to: no restrictions. + +Maximize (zoom) and minimize the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-?* +Default key: ? +Map option: NERDTreeMapHelp +Applies to: no restrictions. + +Toggles whether the quickhelp is displayed. + +------------------------------------------------------------------------------ +2.3. The NERD tree menu *NERDTreeMenu* + +The NERD tree has a menu that can be programmed via the an API (see +|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most +file explorers have. + +The script comes with two default menu plugins: exec_menuitem.vim and +fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for +creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a +menu item to execute executable files. + +Related tags: |NERDTree-m| |NERDTreeApi| + +============================================================================== +3. Customisation *NERDTreeOptions* + + +------------------------------------------------------------------------------ +3.1. Customisation summary *NERDTreeOptionSummary* + +The script provides the following options that can customise the behaviour the +NERD tree. These options should be set in your vimrc. + +|'loaded_nerd_tree'| Turns off the script. + +|'NERDChristmasTree'| Tells the NERD tree to make itself colourful + and pretty. + +|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers + when the cursor moves within a specified + distance to the top/bottom of the window. +|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering. + +|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case + sensitive or not when sorting nodes. + +|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change + vim's current working directory. + +|'NERDTreeHighlightCursorline'| Tell the NERD tree whether to highlight the + current cursor line. + +|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw + autocommands for exploring local directories. + +|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. + +|'NERDTreeBookmarksFile'| Where the bookmarks are stored. + +|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse + clicks. + +|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. + +|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the + bookmarks table on startup. + +|'NERDTreeShowFiles'| Tells the NERD tree whether to display files + in the tree on startup. + +|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden + files on startup. + +|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line + numbers in the tree window. + +|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in + the tree. + +|'NERDTreeStatusline'| Set a statusline for NERD tree windows. + +|'NERDTreeWinPos'| Tells the script where to put the NERD tree + window. + +|'NERDTreeWinSize'| Sets the window size when the NERD tree is + opened. + +------------------------------------------------------------------------------ +3.2. Customisation details *NERDTreeOptionDetails* + +To enable any of the below options you should put the given line in your +~/.vimrc + + *'loaded_nerd_tree'* +If this plugin is making you feel homicidal, it may be a good idea to turn it +off with this line in your vimrc: > + let loaded_nerd_tree=1 +< +------------------------------------------------------------------------------ + *'NERDChristmasTree'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then some extra syntax highlighting elements are +added to the nerd tree to make it more colourful. + +Set it to 0 for a more vanilla looking tree. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenter'* +Values: 0 or 1. +Default: 1 + +If set to 1, the NERD tree window will center around the cursor if it moves to +within |'NERDTreeAutoCenterThreshold'| lines of the top/bottom of the window. + +This is ONLY done in response to tree navigation mappings, +i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| +|NERDTree-P| + +The centering is done with a |zz| operation. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenterThreshold'* +Values: Any natural number. +Default: 3 + +This option controls the "sensitivity" of the NERD tree auto centering. See +|'NERDTreeAutoCenter'| for details. + +------------------------------------------------------------------------------ + *'NERDTreeCaseSensitiveSort'* +Values: 0 or 1. +Default: 0. + +By default the NERD tree does not sort nodes case sensitively, i.e. nodes +could appear like this: > + bar.c + Baz.c + blarg.c + boner.c + Foo.c +< +But, if you set this option to 1 then the case of the nodes will be taken into +account. The above nodes would then be sorted like this: > + Baz.c + Foo.c + bar.c + blarg.c + boner.c +< +------------------------------------------------------------------------------ + *'NERDTreeChDirMode'* + +Values: 0, 1 or 2. +Default: 0. + +Use this option to tell the script when (if at all) to change the current +working directory (CWD) for vim. + +If it is set to 0 then the CWD is never changed by the NERD tree. + +If set to 1 then the CWD is changed when the NERD tree is first loaded to the +directory it is initialized in. For example, if you start the NERD tree with > + :NERDTree /home/marty/foobar +< +then the CWD will be changed to /home/marty/foobar and will not be changed +again unless you init another NERD tree with a similar command. + +If the option is set to 2 then it behaves the same as if set to 1 except that +the CWD is changed whenever the tree root is changed. For example, if the CWD +is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new +root then the CWD will become /home/marty/foobar/baz. + +------------------------------------------------------------------------------ + *'NERDTreeHighlightCursorline'* +Values: 0 or 1. +Default: 1. + +If set to 1, the current cursor line in the NERD tree buffer will be +highlighted. This is done using the |'cursorline'| option. + +------------------------------------------------------------------------------ + *'NERDTreeHijackNetrw'* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit +< +will open up a "secondary" NERD tree instead of a netrw in the target window. + +Secondary NERD trees behaves slighly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have as many secondary tree as you want in the same tab. + +------------------------------------------------------------------------------ + *'NERDTreeIgnore'* +Values: a list of regular expressions. +Default: ['\~$']. + +This option is used to specify which files the NERD tree should ignore. It +must be a list of regular expressions. When the NERD tree is rendered, any +files/dirs that match any of the regex's in 'NERDTreeIgnore' wont be +displayed. + +For example if you put the following line in your vimrc: > + let NERDTreeIgnore=['\.vim$', '\~$'] +< +then all files ending in .vim or ~ will be ignored. + +Note: to tell the NERD tree not to ignore any files you must use the following +line: > + let NERDTreeIgnore=[] +< + +The file filters can be turned on and off dynamically with the |NERDTree-f| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksFile'* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *'NERDTreeMouseMode'* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *'NERDTreeQuitOnOpen'* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. + +------------------------------------------------------------------------------ + *'NERDTreeShowBookmarks'* +Values: 0 or 1. +Default: 0. + +If this option is set to 1 then the bookmarks table will be displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeShowFiles'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then files are displayed in the NERD tree. If it is +set to 0 then only directories are displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *'NERDTreeShowHidden'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display hidden files by default. This option +can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one +of the follow lines to set this option: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeShowLineNumbers'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines to set this option: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeSortOrder'* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This option is set to a list of regular expressions which are used to +specify the order of nodes under their parent. + +For example, if the option is set to: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be placed at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesnt match any of the other regexps should be placed here. + +If no star is present in 'NERDTreeSortOrder' then one is automatically +appended to the array. + +The regex '\/$' should be used to match directory nodes. + +After this sorting is done, the files in each group are sorted alphabetically. + +Other examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Dirs will appear first, then ruby and php. Swap files, bak files and vim + backup files will appear last with everything else preceding them. + +------------------------------------------------------------------------------ + *'NERDTreeStatusline'* +Values: Any valid statusline setting. +Default: %{b:NERDTreeRoot.path.strForOS(0)} + +Tells the script what to use as the |'statusline'| setting for NERD tree +windows. + +Note that the statusline is set using |:let-&| not |:set| so escaping spaces +isn't necessary. + +Setting this option to -1 will will deactivate it so that your global +statusline setting is used instead. + +------------------------------------------------------------------------------ + *'NERDTreeWinPos'* +Values: "left" or "right" +Default: "left". + +This option is used to determine where NERD tree window is placed on the +screen. + +This option makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERD tree on the right. + +------------------------------------------------------------------------------ + *'NERDTreeWinSize'* +Values: a positive integer. +Default: 31. + +This option is used to change the size of the NERD tree when it is loaded. + +============================================================================== +4. The NERD tree API *NERDTreeAPI* + +The NERD tree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERD tree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'b', + \ 'callback': 'NERDTreeEchoCurrentNode', + \ 'quickhelpText': 'echo full path of current node' }) + + function! NERDTreeEchoCurrentNode() + let n = g:NERDTreeFileNode.GetSelected() + if n != {} + echomsg 'Current node: ' . n.path.str() + endif + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (rather useless) mapping on 'b' which echos the full path to the + current node. + +------------------------------------------------------------------------------ +4.2. Menu API *NERDTreeMenuAPI* + +NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* + Creates and returns a new submenu. + + {options} must be a dictionary and must contain the following keys: + "text" - the text of the submenu that the user will see + "shortcut" - a shortcut key for the submenu (need not be unique) + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this submenu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - the parent submenu of the new submenu (returned from a previous + invocation of NERDTreeAddSubmenu()). If this key is left out then the new + submenu will sit under the top level menu. + + See below for an example. + +NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* + Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|). + + {options} must be a dictionary and must contain the + following keys: + "text" - the text of the menu item which the user will see + "shortcut" - a shortcut key for the menu item (need not be unique) + "callback" - the function that will be called when the user activates the + menu item. + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this menu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - if the menu item belongs under a submenu then this key must be + specified. This value for this key will be the object that + was returned when the submenu was created with |NERDTreeAddSubmenu()|. + + See below for an example. + +NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* + Adds a menu separator (a row of dashes). + + {options} is an optional dictionary that may contain the following keys: + "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. + +Below is an example of the menu API in action. > + call NERDTreeAddMenuSeparator() + + call NERDTreeAddMenuItem({ + \ 'text': 'a (t)op level menu item', + \ 'shortcut': 't', + \ 'callback': 'SomeFunction' }) + + let submenu = NERDTreeAddSubmenu({ + \ 'text': 'a (s)ub menu', + \ 'shortcut': 's' }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 1', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 2', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) +< +This will create the following menu: > + -------------------- + a (t)op level menu item + a (s)ub menu +< +Where selecting "a (s)ub menu" will lead to a second menu: > + (n)ested item 1 + (n)ested item 2 +< +When any of the 3 concrete menu items are selected the function "SomeFunction" +will be called. + +------------------------------------------------------------------------------ +NERDTreeRender() *NERDTreeRender()* + Re-renders the NERD tree buffer. Useful if you change the state of the + tree and you want to it to be reflected in the UI. + +============================================================================== +5. About *NERDTreeAbout* + +The author of the NERD tree is a terrible terrible monster called Martyzilla +who gobbles up small children with milk and sugar for breakfast. + +He can be reached at martin.grenfell at gmail dot com. He would love to hear +from you, so feel free to send him suggestions and/or comments about this +plugin. Don't be shy --- the worst he can do is slaughter you and stuff you in +the fridge for later ;) + +The latest stable versions can be found at + http://www.vim.org/scripts/script.php?script_id=1658 + +The latest dev versions are on github + http://github.com/scrooloose/nerdtree + + +============================================================================== +6. Changelog *NERDTreeChangelog* + +4.1.0 + features: + - NERDTreeFind to reveal the node for the current buffer in the tree, + see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by + Doug McInnes) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan + Ritter and Rémi Prévost. + - truncate the root node if wider than the tree window. Thanks to Victor + Gonzalez. + + bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, + jfilip1024, and Chris Chambers + +4.0.0 + - add a new programmable menu system (see :help NERDTreeMenu). + - add new APIs to add menus/menu-items to the menu system as well as + custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). + - removed the old API functions + - added a mapping to maximize/restore the size of nerd tree window, thanks + to Guillaume Duranceau for the patch. See :help NERDTree-A for details. + + - fix a bug where secondary nerd trees (netrw hijacked trees) and + NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. + - fix a bug where the script ignored directories whose name ended in a dot, + thanks to Aggelos Orfanakos for the patch. + - fix a bug when using the x mapping on the tree root, thanks to Bryan + Venteicher for the patch. + - fix a bug where the cursor position/window size of the nerd tree buffer + wasnt being stored on closing the window, thanks to Richard Hart. + - fix a bug where NERDTreeMirror would mirror the wrong tree + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + " (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree would fail if was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring + +============================================================================== +7. Credits *NERDTreeCredits* + +Thanks to the following people for testing, bug reports, ideas etc. Without +you I probably would have got bored of the hacking the NERD tree and +just downloaded pr0n instead. + + Tim Carey-Smith (halorgium) + Vigil + Nick Brettell + Thomas Scott Urban + Terrance Cohen + Yegappan Lakshmanan + Jason Mills + Michael Geddes (frogonwheels) + Yu Jun + Michael Madsen + AOYAMA Shotaro + Zhang Weiwu + Niels Aan de Brugh + Olivier Yiptong + Zhang Shuhan + Cory Echols + Piotr Czachur + Yuan Jiang + Matan Nassau + Maxim Kim + Charlton Wang + Matt Wozniski (godlygeek) + knekk + Sean Chou + Ryan Penn + Simon Peter Nicholls + Michael Foobar + Tomasz Chomiuk + Denis Pokataev + Tim Pope (tpope) + James Kanze + James Vega (jamessan) + Frederic Chanal (nach) + Alf Mikula + Lucas S. Buchala + Curtis Harvey + Guillaume Duranceau + Richard Hart (hates) + Doug McInnes + Stefan Ritter + Rémi Prévost + Victor Gonzalez + Stephan Baumeister + Ricky + jfilip1024 + Chris Chambers + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. diff --git a/doc/delimitMate.txt b/doc/delimitMate.txt new file mode 100644 index 0000000..6de8b50 --- /dev/null +++ b/doc/delimitMate.txt @@ -0,0 +1,561 @@ +*delimitMate* Trying to keep those beasts at bay! v.2.0 *delimitMate.txt* + + ========================================================================= ~ + ==== ========= ========================== ===== ===================== ~ + ==== ========= ========================== === ===================== ~ + ==== ========= ===================== === = = ========== ========= ~ + ==== === === == == = = === == == == == === === === == ~ + == == = == ====== ======= === ===== == = === === = = ~ + = = == == == == = = == === === ===== ===== === === = ~ + = = == ===== == == = = == === === ===== === === === ==== ~ + = = == = == == == = = == === === ===== == = === === = = ~ + == === === == == = = == === == ===== === === === == ~ + ========================================================================= ~ + + REFERENCE MANUAL * + +============================================================================== + 0.- CONTENTS *delimitMate-contents* + + 1. Introduction____________________________|delimitMateIntro| + 2. Functionality___________________________|delimitMateFunctionality| + 2.1 Automatic closing & exiting________|delimitMateAutoClose| + 2.2 Expansion of space and CR__________|delimitMateExpansion| + 2.3 Backspace__________________________|delimitMateBackspace| + 2.4 Visual wrapping____________________|delimitMateVisualWrapping| + 2.5 Smart Quotes_______________________|delimitMateSmartQuotes| + 3. Customization___________________________|delimitMateOptions| + 3.1 Option summary_____________________|delimitMateOptionSummary| + 3.2 Options details____________________|delimitMateOptionDetails| + 4. Commands________________________________|delimitMateCommands| + 5. Functions_______________________________|delimitMateFunctions| + 6. TODO list_______________________________|delimitMateTodo| + 7. Maintainer______________________________|delimitMateMaintainer| + 8. Credits_________________________________|delimitMateCredits| + 9. History_________________________________|delimitMateHistory| + +============================================================================== + 1.- INTRODUCTION *delimitMateIntro* + +The delimitMate plugin tries to provide some not so dumb help in the work with +delimiters (brackets, quotes, etc.), with some optional auto-completions and +expansions. + +When automatic closing is enabled, if an opening delimiter is inserted +delimitMate inserts the closing pair and places the cursor between them. When +automatic closing is disabled, no closing delimiters is inserted by +delimitMate, but if a pair of delimiters is typed, the cursor is placed in the +middle. Also, to get out of a pair of delimiters just type shift+tab or the +right delimiter and the cursor will jump to the right. + +If the cursor is inside an empty pair of delimiters, typing will +insert two spaces and the cursor will be placed in the middle; typing +will insert to car retunrs and place the cursor in the middle line, between +the delimiters. + +All of the operations are undo/redo-wise safe. + +============================================================================== + 2. FUNCTIONALITY *delimitMateFunctionality* + +------------------------------------------------------------------------------ + 2.1 AUTOMATIC CLOSING AND EXITING *delimitMateAutoClose* + +With automatic closing enabled, if an opening delimiter is inserted the plugin +inserts the closing delimiter and places the cursor between the pair. With +automatic closing disabled, no closing delimiters is inserted by delimitMate, +but when a pair of delimiters is typed, the cursor is placed in the middle. + +When the cursor is inside an empty pair or located next to the left of a +closing delimiter, the cursor is placed outside the pair to the right of the +closing delimiter. + +Unless |'delimitMate_matchpairs'| or |'delimitMate_quotes'|are set, this +script uses the values in '&matchpairs' to identify the pairs, and ", ' and ` +for quotes respectively. + +The following table shows the behaviour, this applies to quotes too (the final +position of the cursor is represented by a "|"): + +With auto-close: > + Type | You get + ==================== + ( | (|) + –––––––––|–––––––––– + () | ()| + –––––––––|–––––––––– + ( | ()| +< +Without auto-close: > + + Type | You get + ===================== + () | (|) + –––––––––-|–––––––––– + ()) | ()| + –––––––––-|–––––––––– + () | ()| +< +------------------------------------------------------------------------------ + 2.2 EXPANSION OF SPACE AND CAR RETURN *delimitMateExpansion* + +When the cursor is inside an empty pair of delimiters, and can be +expanded, see |'delimitMate_expand_space'| and +|'delimitMate_expand_cr'|: + +Expand to: > + + | You get + ==================================== + (|) | ( | ) +< +Expand to: > + + | You get + ============================ + (|) | ( + | | + | ) +< + +Since and are used everywhere, I have made the functions involved +in expansions global, so they can be used to make custom mappings. Read +|delimitMateFunctions| for more details. + +------------------------------------------------------------------------------ + 2.3 BACKSPACE *delimitMateBackspace* + +If you press backspace inside an empty pair, both delimiters are deleted. If +you type shift + backspace instead, only the closing delimiter will be +deleted. + +e.g. typing at the "|": > + + What | Before | After + ============================================== + | call expand(|) | call expand| + ---------|------------------|----------------- + | call expand(|) | call expand(| +< + +------------------------------------------------------------------------------ + 2.4 WRAPPING OF VISUAL SELECTION *delimitMateVisualWrapping* + +When visual mode is active this script allows for the selection to be enclosed +with delimiters. But, since brackets have special meaning in visual mode, a +leader (the value of 'mapleader' by default) should precede the delimiter. +This feature doesn't currently work on blockwise visual mode, any suggestions +will be welcome. + +e.g. (selection represented between square brackets): > + + Selected text | After \" + ============================================= + An [absurd] example! | An "absurd" example! +< + +------------------------------------------------------------------------------ + 2.5 SMART QUOTES *delimitMateSmartQuotes* + +Only one quote will be inserted following a quote, a "\" or an alphanumeric +character. This should cover closing quotes, escaped quotes and apostrophes. +Except for apostrophes, this feature can be disabled setting the option +|'delimitMate_smart_quotes'| to 0. + +e.g. typing at the "|": > + + What | Before | After + ======================================= + " | "String| | "String"| + " | let i = "| | let i = "|" + ' | I| | I'| +< +============================================================================== + 3. CUSTOMIZATION *delimitMateOptions* + +You can create your own mappings for some features using the global functions. +Read |DelimitMateFunctions| for more info. + +------------------------------------------------------------------------------ + 3.1 OPTIONS SUMMARY *delimitMateOptionSummary* + +The behaviour of this script can be customized setting the following options +in your vimrc file. You can use local options to set the configuration for +specific file types, see |delimitMateOptionDetails| for examples. + +|'loaded_delimitMate'| Turns off the script. + +|'delimitMate_autoclose'| Tells delimitMate whether to automagically + insert the closing delimiter. + +|'delimitMate_matchpairs'| Tells delimitMate which characters are + matching pairs. + +|'delimitMate_quotes'| Tells delimitMate which quotes should be + used. + +|'delimitMate_visual_leader'| Sets the leader to be used in visual mode. + +|'delimitMate_expand_cr'| Turns on/off the expansion of . + +|'delimitMate_expand_space'| Turns on/off the expansion of . + +|'delimitMate_excluded_ft'| Turns off the script for the given file types. + +|'delimitMate_apostrophes'| Tells delimitMate how it should "fix" + balancing of single quotes when used as + apostrophes. NOTE: Not needed any more, kept + for compatibility with older versions. + +|'delimitMate_smart_quotes'| Turns on/off the "smart quotes" feature. + +------------------------------------------------------------------------------ + 3.2 OPTIONS DETAILS *delimitMateOptionDetails* + +Add the shown lines to your vimrc file in order to set the below options. +Local options take precedence over global ones and can be used along with +autocmd to modify delimitMate's behavior for specific file types. + +------------------------------------------------------------------------------ + *'loaded_delimitMate'* + *'b:loaded_delimitMate'* +This option prevents delimitMate from loading. +e.g.: > + let loaded_delimitMate = 1 + au FileType mail let b:loaded_delimitMate = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_autoclose'* + *'b:delimitMate_autoclose'* +Values: 0 or 1. ~ +Default: 1 ~ + +If this option is set to 0, delimitMate will not add a closing delimiter +automagically. See |delimitMateAutoClose| for details. +e.g.: > + let delimitMate_autoclose = 0 + au FileType mail let b:delimitMate_autoclose = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_matchpairs'* + *'b:delimitMate_matchpairs'* +Values: A string with |matchpairs| syntax. ~ +Default: &matchpairs ~ + +Use this option to tell delimitMate which characters should be considered +matching pairs. Read |delimitMateAutoClose| for details. +e.g: > + let delimitMate = "(:),[:],{:},<:>" + au FileType vim,html let b:delimitMate_matchpairs = "(:),[:],{:},<:>" +< +------------------------------------------------------------------------------ + *'delimitMate_quotes'* + *'b:delimitMate_quotes'* +Values: A string of characters separated by spaces. ~ +Default: "\" ' `" ~ + +Use this option to tell delimitMate which characters should be considered as +quotes. Read |delimitMateAutoClose| for details. +e.g.: > + let b:delimitMate_quotes = "\" ' ` *" + au FileType html let b:delimitMate_quotes = "\" '" +< +------------------------------------------------------------------------------ + *'delimitMate_visual_leader'* + *'b:delimitMate_visual_leader'* +Values: Any character. ~ +Default: q ~ + +The value of this option will be used to wrap the selection in visual mode +when followed by a delimiter. Read |delimitMateVisualWrap| for details. +e.g: > + let delimitMate_visual_leader = "f" + au FileType html let b:delimitMate_visual_leader = "f" +< +------------------------------------------------------------------------------ + *'delimitMate_expand_cr'* + *'b:delimitMate_expand_cr'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. +e.g.: > + let b:delimitMate_expand_cr = "\\\" + au FileType mail let b:delimitMate_expand_cr = "\" +< +------------------------------------------------------------------------------ + *'delimitMate_expand_space'* + *'b:delimitMate_expand_space'* +Values: A key mapping. ~ +Default: "\" ~ + +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. +e.g.: > + let delimitMate_expand_space = "\\\" + au FileType tcl let b:delimitMate_expand_space = "\" +< +------------------------------------------------------------------------------ + *'delimitMate_excluded_ft'* +Values: A string of file type names separated by single commas. ~ +Default: Empty. ~ + +This options turns delimitMate off for the listed file types, use this option +only if you don't want any of the features it provides on those file types. +e.g.: > + let delimitMate_excluded_ft = "mail,txt" +< +------------------------------------------------------------------------------ + *'delimitMate_apostrophes'* +Values: Strings separated by ":". ~ +Default: No longer used. ~ + +NOTE: This feature is turned off by default, it's been kept for compatibility +with older version, read |delimitMateSmartQuotes| for details. +If auto-close is enabled, this option tells delimitMate how to try to fix the +balancing of single quotes when used as apostrophes. The values of this option +are strings of text where a single quote would be used as an apostrophe (e.g.: +the "n't" of wouldn't or can't) separated by ":". Set it to an empty string to +disable this feature. +e.g.: > + let delimitMate_apostrophes = "" + au FileType tcl let delimitMate_apostrophes = "" +< +============================================================================== + 4. COMMANDS *delimitMateCommands* + +------------------------------------------------------------------------------ +:DelimitMateReload *:DelimitMateReload* + +Re-sets all the mappings used for this script, use it if any option has been +changed or if the filetype option hasn't been set yet. + +------------------------------------------------------------------------------ +:DelimitMateTest *:DelimitMateTest* + +This command tests every mapping set-up for this script, useful for testing +custom configurations. + +The following output corresponds to the default values, it will be different +depending on your configuration. "Open & close:" represents the final result +when the closing delimiter has been inserted, either manually or +automatically, see |delimitMateExpansion|. "Delete:" typing backspace in an +empty pair, see |delimitMateBackspace|. "Exit:" typing a closing delimiter +inside a pair of delimiters, see |delimitMateAutoclose|. "Space:" the +expansion, if any, of space, see |delimitMateExpansion|. "Visual-L", +"Visual-R" and "Visual" shows visual wrapping, see +|delimitMateVisualWrapping|. "Car return:" the expansion of car return, see +|delimitMateExpansion|. The cursor's position at the end of every test is +represented by an "|": > + + * AUTOCLOSE: + Open & close: (|) + Delete: | + Exit: ()| + Space: ( |) + Visual-L: (v) + Visual-R: (v) + Car return: ( + |) + + Open & close: {|} + Delete: | + Exit: {}| + Space: { |} + Visual-L: {v} + Visual-R: {v} + Car return: { + |} + + Open & close: [|] + Delete: | + Exit: []| + Space: [ |] + Visual-L: [v] + Visual-R: [v] + Car return: [ + |] + + Open & close: "|" + Delete: | + Exit: ""| + Space: " |" + Visual: "v" + Car return: " + |" + + Open & close: '|' + Delete: | + Exit: ''| + Space: ' |' + Visual: 'v' + Car return: ' + |' + + Open & close: `|` + Delete: | + Exit: ``| + Space: ` |` + Visual: `v` + Car return: ` + |` +< + +============================================================================== + 5. FUNCTIONS *delimitMateFunctions* + +------------------------------------------------------------------------------ +delimitMate_WithinEmptyPair() *delimitMate_WithinEmptyPair* + +Returns 1 if the cursor is inside an empty pair, 0 otherwise. + +------------------------------------------------------------------------------ +DelimitMate_ExpandReturn() *DelimitMate_ExpandReturn()* + +Returns the expansion for . + +e.g.: This mapping could be used to select an item on a pop-up menu or expand + inside an empty pair: > + + inoremap pumvisible() ? "\" : + \ DelimitMate_WithinEmptyPair ? + \ DelimitMate_ExpandReturn() : "\" +< +------------------------------------------------------------------------------ +DelimitMate_ExpandSpace() *DelimitMate_ExpandSpace()* + +Returns the expansion for . +e.g.: > + + inoremap DelimitMate_WithinEmptyPair() ? + \ DelimitMate_ExpandSpace() : "\" +< +------------------------------------------------------------------------------ +DelimitMate_ShouldJump() *DelimitMate_ShouldJump()* + +Returns 1 if there is a closing delimiter or a quote to the right of the +cursor, 0 otherwise. + +------------------------------------------------------------------------------ +DelimitMate_JumpAny() *DelimitMate_JumpAny()* + +This function returns a mapping that will make the cursor jump to the right. +e.g.: You can use this to create your own mapping to jump over any delimiter. +> + inoremap DelimitMate_ShouldJump() ? + \ DelimitMate_JumpAny() : "\" +< + +============================================================================== + 6. TODO LIST *delimitMateTodo* + +- Automatic set-up by file type. +- Make visual wrapping work on blockwise visual mode. +- Limit behaviour by region. + +============================================================================== + 7. MAINTAINER *delimitMateMaintainer* + +Hi there! My name is Israel Chauca F. and I can be reached at: + mailto:israelchauca@gmail.com + +Feel free to send me any suggestions and/or comments about this plugin, I'll +be very pleased to read them. + +============================================================================== + 8. CREDITS *delimitMateCredits* + +Some of the code that make this script is modified or just shamelessly copied +from the following sources: + + - Ian McCracken + Post titled: Vim, Part II: Matching Pairs: + http://concisionandconcinnity.blogspot.com/ + + - Aristotle Pagaltzis + From the comments on the previous blog post and from: + http://gist.github.com/144619 + + - Vim Scripts: + http://www.vim.org/scripts + +This script was inspired by the auto-completion of delimiters of TextMate. + +============================================================================== + 9. HISTORY *delimitMateHistory* + + Version Date Release notes ~ +|---------|------------|-----------------------------------------------------| + 2.0 2010-04-01 * New features: + - All features are redo/undo-wise safe. + - A single quote typed after an alphanumeric + character is considered an apostrophe and one + single quote is inserted. + - A quote typed after another quote inserts a single + quote and the cursor jumps to the middle. + - jumps out of any empty pair. + - and expansions are fixed, but the + functions used for it are global and can be used in + custom mappings. The previous system is still + active if you have any of the expansion options + set. + - deletes the closing delimiter. + + * Fixed bug: + - s:vars were being used to store buffer options. + +|---------|------------|-----------------------------------------------------| + 1.6 2009-10-10 Now delimitMate tries to fix the balancing of single + quotes when used as apostrophes. You can read + |delimitMate_apostrophes| for details. + Fixed an error when |b:delimitMate_expand_space| + wasn't set but |delimitMate_expand_space| wasn't. + +|---------|------------|-----------------------------------------------------| + 1.5 2009-10-05 Fix: delimitMate should work correctly for files + passed as arguments to Vim. Thanks to Ben Beuchler + for helping to nail this bug. + +|---------|------------|-----------------------------------------------------| + 1.4 2009-09-27 Fix: delimitMate is now enabled on new buffers even + if they don't have set the file type option or were + opened directly from the terminal. + +|---------|------------|-----------------------------------------------------| + 1.3 2009-09-24 Now local options can be used along with autocmd + for specific file type configurations. + Fixes: + - Unnamed register content is not lost on visual + mode. + - Use noremap where appropiate. + - Wrapping a single empty line works as expected. + +|---------|------------|-----------------------------------------------------| + 1.2 2009-09-07 Fixes: + - When inside nested empty pairs, deleting the + innermost left delimiter would delete all right + contiguous delimiters. + - When inside an empty pair, inserting a left + delimiter wouldn't insert the right one, instead + the cursor would jump to the right. + - New buffer inside the current window wouldn't + have the mappings set. + +|---------|------------|-----------------------------------------------------| + 1.1 2009-08-25 Fixed an error that ocurred when mapleader wasn't + set and added support for GetLatestScripts + auto-detection. + +|---------|------------|-----------------------------------------------------| + 1.0 2009-08-23 Initial upload. + +|---------|------------|-----------------------------------------------------| + + + ... |"| _ _ . . ___ ~ + o,*,(o o) _|_|_ o' \,=./ `o . .:::. /_\ `* ~ + 8(o o)(_)Ooo (o o) (o o) :(o o): . (o o) ~ +---ooO-(_)---Ooo----ooO--(_)--Ooo-ooO--(_)--Ooo-ooO--(_)--Ooo-ooO--(_)--Ooo- ~ + +vim:tw=78:ts=8:ft=help:norl:formatoptions+=tcroqn:autoindent: diff --git a/doc/fuf.jax b/doc/fuf.jax new file mode 100644 index 0000000..072afcc --- /dev/null +++ b/doc/fuf.jax @@ -0,0 +1,1149 @@ +*fuf.jax* ãƒãƒƒãƒ•ã‚¡/ファイル/ãã®ä»–ã‚’ã€ã‚ã„ã¾ã„検索 + + Copyright (c) 2007-2009 Takeshi NISHIDA + +FuzzyFinder *fuzzyfinder* *fuf* + +æ¦‚è¦ |fuf-introduction| +インストール |fuf-installation| +ä½¿ã„æ–¹ |fuf-usage| +モード |fuf-modes| +詳細ãªãƒˆãƒ”ック |fuf-detailed-topics| +コマンド |fuf-commands| +オプション |fuf-options| +VIMRC ã®ä¾‹ |fuf-vimrc-example| +SPECIAL THANKS |fuf-thanks| +CHANGELOG |fuf-changelog| +ã‚ã°ã†ã¨ |fuf-about| + +============================================================================== +æ¦‚è¦ *fuf-introduction* + +FuzzyFinder ã¯ãƒãƒƒãƒ•ã‚¡/ファイル/コマンド/ブックマーク/ã‚¿ã‚°ã«ç´ æ—©ãアクセスã™ã‚‹ +ãŸã‚ã®æ‰‹æ®µã‚’æä¾›ã—ã¾ã™ã€‚入力ã•れãŸãƒ‘ターンã‹ã‚‰å¤‰æ›ã•れãŸã‚ã„ã¾ã„パターンã¾ãŸã¯ +éƒ¨åˆ†ä¸€è‡´ãƒ‘ã‚¿ãƒ¼ãƒ³ã§æ¤œç´¢ã‚’行ã„ã¾ã™ã€‚ + + 入力パターン ã‚ã„ã¾ã„パターン 部分一致パターン ~ +> + abc *a*b*c* *abc* + dir/file dir/*f*i*l*e* dir/*file* + d*r/file d*r/*f*i*l*e* d*r/*file* + ../**/s ../**/*s* ../**/*s* + (** : å†å¸°æ¤œç´¢) +< +次ã®ã‚ˆã†ãªå ´é¢ã§æœ‰ç”¨ã§ã™: + + "./AhLongLongLongLongLongFile.txt" + "./AhLongLongLongLongLongName.txt" + "./OhLongLongLongLongLongFile.txt" + "./OhLongLongLongLongLongName.txt" <- 欲ã—ã„ファイル :-O + +"ON" ã¨å…¥åŠ›ã™ã‚Œã° "OhLongLongLongLongLongName.txt" ãŒé¸æŠžã§ãã¾ã™. :-D + +FuzzyFinder ãŒæ¤œç´¢ã§ãã‚‹å¯¾è±¡ã¯æ¬¡ã®é€šã‚Šã§ã™: + - ãƒãƒƒãƒ•ã‚¡ + - ファイル + - ディレクトリ + - 最近使ã£ãŸãƒ•ァイル + - 最近使ã£ãŸã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ + - ブックマーク + - ã‚¿ã‚° + - タグファイルã«å«ã¾ã‚Œã‚‹ãƒ•ァイル + - ジャンプリスト + - ãƒã‚§ãƒ³ã‚¸ãƒªã‚¹ãƒˆ + - ãƒãƒƒãƒ•ã‚¡ã®è¡Œ + - quickfix + - ヘルプ + +FuzzyFinder 㯠ファイルを検索ã—ãŸã‚Šã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã™ã‚‹ã‚·ã‚¹ãƒ†ãƒ ã‚’利用ã™ã‚‹ãŸã‚ã® +API ã‚‚æä¾›ã—ã¾ã™ã€‚ + +FuzzyFinder ã¯ãƒžãƒ«ãƒãƒã‚¤ãƒˆæ–‡å­—をサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚ + + +============================================================================== +インストール *fuf-installation* + +ZIPファイルをランタイムディレクトリã«å±•é–‹ã—ã¾ã™ã€‚ + +以下ã®ã‚ˆã†ã«ãƒ•ァイルãŒé…ç½®ã•れるã¯ãšã§ã™ã€‚ +> + <ランタイムディレクトリ>/plugin/fuf.vim + <ランタイムディレクトリ>/autoload/fuf.vim + <ランタイムディレクトリ>/autoload/fuf/buffer.vim + ... +< +ã‚‚ã—ランタイムディレクトリãŒä»–ã®ãƒ—ラグインã¨ã”ãŸæ··ãœã«ãªã‚‹ã®ãŒå«Œãªã‚‰ã€ãƒ•ァイル +ã‚’æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«é…ç½®ã—ã€ãã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ãƒ‘スを 'runtimepath' ã«è¿½åŠ ã—㦠+ãã ã•ã„。アンインストールも楽ã«ãªã‚Šã¾ã™ã€‚ + +ãã®å¾Œ FuzzyFinder ã®ãƒ˜ãƒ«ãƒ—を有効ã«ã™ã‚‹ãŸã‚ã«ã‚¿ã‚°ãƒ•ァイルを更新ã—ã¦ãã ã•ã„。 +詳ã—ãã¯|add-local-help|ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + +============================================================================== +ä½¿ã„æ–¹ *fuf-usage* + +次ã®ã‚³ãƒžãƒ³ãƒ‰ã§ FuzzyFinder ã‚’èµ·å‹•ã—ã¾ã™: + + コマンド モード ~ + |:FufBuffer| - Buffer モード (|fuf-buffer-mode|) + |:FufFile| - File モード (|fuf-file-mode|) + |:FufDir| - Directory モード (|fuf-dir-mode|) + |:FufMruFile| - MRU-File モード (|fuf-mrufile-mode|) + |:FufMruCmd| - MRU-Command モード (|fuf-mrucmd-mode|) + |:FufBookmark| - Bookmark モード (|fuf-bookmark-mode|) + |:FufTag| - Tag モード (|fuf-tag-mode|) + |:FufTaggedFile| - Tagged-File モード (|fuf-taggedfile-mode|) + |:FufJumpList| - Jump-List モード (|fuf-jumplist-mode|) + |:FufChangeList| - Change-List モード (|fuf-changelist-mode|) + |:FufQuickfix| - Quickfix モード (|fuf-quickfix-mode|) + |:FufLine| - Line モード (|fuf-line-mode|) + |:FufHelp| - Help モード (|fuf-help-mode|) + +ã“れらã®ã‚³ãƒžãƒ³ãƒ‰ã‚’押ã—ã‚„ã™ã„キーã«ãƒžãƒƒãƒ”ングã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚ + +ã“れらã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã¨ãƒ‘ターンを入力ã™ã‚‹ãŸã‚ã®1行ã®ãƒãƒƒãƒ•ã‚¡ã‚’é–‹ãã€ã‚¤ãƒ³ +サートモードを開始ã—ã¾ã™ã€‚ + +FuzzyFinder ã¯å…¥åŠ›ã•れãŸãƒ‘ターンã«ãƒžãƒƒãƒã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã‚’検索ã—ã€ãれを補完メニュ +ーã«è¡¨ç¤ºã—ã¾ã™ã€‚パターンマッãƒãƒ³ã‚°ã®è©³ç´°ã¯|fuf-search-patterns|ã‚’å‚ç…§ã—ã¦ãã  +ã•ã„。 + +多ãã®ã‚¢ã‚¤ãƒ†ãƒ ãŒãƒžãƒƒãƒãƒ³ã‚°ã™ã‚‹å ´åˆã€FuzzyFinder ã¯ãƒ¬ã‚¹ãƒãƒ³ã‚¹ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã« +列挙ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã®æ•°(|g:fuf_enumeratingLimit|)を制é™ã—ã€ãã®éš›ã€å…¥åŠ›ã•れãŸãƒ‘ã‚¿ +ーンを"Error" グループã§ãƒã‚¤ãƒ©ã‚¤ãƒˆã—ã¾ã™ã€‚ + +è£œå®Œãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®æœ€åˆã®ã‚¢ã‚¤ãƒ†ãƒ ã¯è‡ªå‹•çš„ã«é¸æŠžçŠ¶æ…‹ã«ãªã‚Šã¾ã™ã€‚ + + (|g:fuf_keyPrevPattern|) 㨠(|g:fuf_keyNextPattern|) ã§ã€å±¥æ­´ã‹ã‚‰ +éŽåŽ»ã«å…¥åŠ›ã—ãŸãƒ‘ターンを呼ã³å‡ºã™ã“ã¨ãŒã§ãã¾ã™ã€‚ + +ã„ã‚ã„ã‚ãªæ–¹æ³•ã§ã€é¸æŠžã•れãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã™: + + (|g:fuf_keyOpen|) - ç›´å‰ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ãã¾ã™ã€‚ + (|g:fuf_keyOpenSplit|) - ウィンドウを分割ã—ã¦é–‹ãã¾ã™ã€‚ + (|g:fuf_keyOpenVsplit|) - ウィンドウを垂直分割ã—ã¦é–‹ãã¾ã™ã€‚ + (|g:fuf_keyOpenTabpage|) - 別ã®ã‚¿ãƒ–ページã§é–‹ãã¾ã™ã€‚ + +キャンセルã—ã¦ç›´å‰ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«æˆ»ã‚‹ã«ã¯ã€ã‚¤ãƒ³ã‚µãƒ¼ãƒˆãƒ¢ãƒ¼ãƒ‰ã‚’抜ã‘ã¦ãã ã•ã„。 + + (|g:fuf_keySwitchMatching|) ã§ã€æ¤œç´¢æ–¹æ³•ã‚’ã‚ã„ã¾ã„マッãƒãƒ³ã‚°ã¾ãŸã¯ +部分一致マッãƒãƒ³ã‚°ã«äº¤äº’ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + (|g:fuf_keyNextMode|) 㨠(|g:fuf_keyPrevMode|) ã§ã€ã‚¤ãƒ³ã‚µãƒ¼ãƒˆãƒ¢ãƒ¼ +ドを抜ã‘ã‚‹ã“ã¨ãªãカレントモードを切り替ãˆã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã™ã€‚ + +ã„ãã¤ã‹ã®ãƒ¢ãƒ¼ãƒ‰ã§ã¯ã€é¸æŠžã•れãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’ (|g:fuf_keyPreview|) ã§ãƒ—レビ +ューã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚åŒã˜ã‚¢ã‚¤ãƒ†ãƒ ã§ã‚­ãƒ¼ã‚’繰り返ã™ã“ã¨ã§åˆ¥ã®æƒ…報を表示ã•ã›ã‚‹ +ã“ã¨ãŒã§ãã¾ã™ã€‚プレビューをサãƒãƒ¼ãƒˆã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã‚’èµ·å‹•ã™ã‚‹ã¨ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã®é«˜ +ã•ãŒ|g:fuf_previewHeight|ã«ãªã‚Šã¾ã™ã€‚ + + +============================================================================== +モード *fuf-modes* + + *fuf-buffer-mode* +Buffer モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ãƒãƒƒãƒ•ã‚¡ã‚’é¸æŠžã—ã¦é–‹ãインターフェースをæä¾›ã—ã¾ã™ã€‚ + + *fuf-file-mode* +File モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ãƒ•ァイルを検索ã—ã¦é–‹ãインターフェースをæä¾›ã—ã¾ã™ã€‚ + + *fuf-dir-mode* +Directory モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’検索ã—ã¦ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’変更ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェー +スをæä¾›ã—ã¾ã™ã€‚ + + *fuf-mrufile-mode* +MRU-File モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯æœ€è¿‘使ã£ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦é–‹ãインターフェースをæä¾›ã—ã¾ã™ã€‚ + +|BufEnter| 㨠|BufWritePost| ã§è¡Œã†å‡¦ç†ãŒãƒ‘フォーマンス上ã®å•題を起ã“ã—ã†ã‚‹ã® +ã§ã€ãƒ‡ãƒ•ォルトã§ã¯|g:fuf_modesDisable|ã§ç„¡åŠ¹åŒ–ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã«æŒ‡å®šã•れã¦ã„ã¾ã™ã€‚ + + *fuf-mrucmd-mode* +MRU-Command モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯æœ€è¿‘使ã£ãŸã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’é¸æŠžã—ã¦é–‹ãインターフェースをæä¾›ã—ã¾ã™ +。 +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã«å¿…è¦ãªã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ãƒ¢ãƒ¼ãƒ‰ã® ã®ãƒžãƒƒãƒ”ングã«å‰¯ä½œç”¨ãŒã‚ã‚‹ã®ã§ã€ +ã€ãƒ‡ãƒ•ォルトã§ã¯|g:fuf_modesDisable|ã§ç„¡åŠ¹åŒ–ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã«æŒ‡å®šã•れã¦ã„ã¾ã™ã€‚ + + *fuf-bookmark-mode* +Bookmark モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯äº‹å‰ã«è¿½åŠ ã—ãŸãƒ–ãƒƒã‚¯ãƒžãƒ¼ã‚¯ã‚’é¸æŠžã—ã¦ãã®è¡Œã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ• +ェースをæä¾›ã—ã¾ã™ã€‚ + +|:FufAddBookmark|コマンドã§ã‚«ãƒ¼ã‚½ãƒ«ã®ã‚る行をブックマークã«è¿½åŠ ã§ãã¾ã™ã€‚ã“ã® +コマンドを実行ã™ã‚‹ã¨ã€ãƒ–ックマークåã®å…¥åŠ›ã‚’æ±‚ã‚られã¾ã™ã€‚ + +FuzzyFinder ã¯ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹è¡Œç•ªå·ã‚’調整ã—ã¾ã™ã€‚ブックマークã•れãŸè¡ŒãŒãƒ–ックマー +クã•れãŸã¨ãã®ãƒ‘ターンã¨ãƒžãƒƒãƒã—ãªã„å ´åˆã€FuzzyFinder ã¯ãƒ–ックマークã•れãŸä½ç½® +ã®å‘¨è¾ºã§ãƒžãƒƒãƒã™ã‚‹è¡Œã‚’探ã—ã¾ã™ã€‚ãªã®ã§ãƒ–ックマークã—ãŸè¡ŒãŒå¤šå°‘移動ã—ã¦ã„ãŸã¨ã— +ã¦ã‚‚ã€ãã“ã§ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ブックマークã—ãŸè¡Œç•ªå·ã¸èª¿æ•´ã›ãšã«ã‚¸ãƒ£ +ンプã—ãŸã„å ´åˆã€|g:fuf_bookmark_searchRange|ã‚’ 0 ã«è¨­å®šã—ã¦ãã ã•ã„。 + +Bookmark モード中㫠(|g:fuf_bookmark_keyDelete|) を押ã™ã¨é¸æŠžã—ãŸãƒ–ックマ +ークを削除ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + *fuf-tag-mode* +Tag モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‚¿ã‚°ã‚’é¸æŠžã—ã¦ãã®å®šç¾©ã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースをæä¾›ã—ã¾ã™ã€‚ + +ä»¥ä¸‹ã¯ ã‚’ç½®ãæ›ãˆã‚‹ãƒžãƒƒãƒ”ングã§ã™ã€‚ +> + noremap :FufTagWithCursorWord! +< + + *fuf-taggedfile-mode* +Tagged-File モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‚¿ã‚°ãƒ•ァイルã«å«ã¾ã‚Œã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦é–‹ãインターフェースをæä¾› +ã—ã¾ã™ã€‚ + + *fuf-jumplist-mode* +Jump-List モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‚«ãƒ¬ãƒ³ãƒˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®|jumplist|ã‹ã‚‰é¸æŠžã—ãŸä½ç½®ã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ +ーフェースをæä¾›ã—ã¾ã™ã€‚ + + *fuf-changelist-mode* +Change-List モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‚«ãƒ¬ãƒ³ãƒˆãƒãƒƒãƒ•ã‚¡ã®|changelist|ã‹ã‚‰é¸æŠžã—ãŸä½ç½®ã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ +ーフェースをæä¾›ã—ã¾ã™ã€‚ + + *fuf-quickfix-mode* +Quickfix モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯|quickfix|リストã‹ã‚‰é¸æŠžã—ãŸä½ç½®ã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースをæ +ä¾›ã—ã¾ã™ã€‚ + + *fuf-line-mode* +Line モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‚«ãƒ¬ãƒ³ãƒˆãƒãƒƒãƒ•ã‚¡ã®è¡Œã‚’é¸æŠžã—ã¦ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースをæä¾›ã— +ã¾ã™ã€‚ + + *fuf-help-mode* +Help モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ãƒ˜ãƒ«ãƒ—ã‚¿ã‚°ã‚’é¸æŠžã—ã¦ãã®ãƒ˜ãƒ«ãƒ—ページã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェース +ã‚’æä¾›ã—ã¾ã™ã€‚ + + *fuf-givenfile-mode* +Given-File モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ä¸Žãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã•れãŸãƒ•ァイルを開ã API ã‚’æä¾›ã—ã¾ã™ã€‚ + +API 関数: +> + function fuf#givenfile#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - FuzzyFinder èµ·å‹•ç›´å¾Œã«æŒ¿å…¥ã•れる文字列 + partialMatching - ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‹ + prompt - プロンプト文字列 + items - アイテムã®ãƒªã‚¹ãƒˆ + +利用例: +> + " ドットファイルを開ã + call fuf#givenfile#launch('', 0, '>', split(glob('~/.*'), "\n")) +< + + *fuf-givendir-mode* +Given-Directory モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ä¸Žãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã•れãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ +変更ã™ã‚‹ API ã‚’æä¾›ã—ã¾ã™ã€‚ + +API 関数: +> + function fuf#givendir#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - FuzzyFinder èµ·å‹•ç›´å¾Œã«æŒ¿å…¥ã•れる文字列 + partialMatching - ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‹ + prompt - プロンプト文字列 + items - アイテムã®ãƒªã‚¹ãƒˆ + + +利用例: +> + " ランタイムディレクトリã®ã©ã‚Œã‹ã‚’カレントディレクトリã«ã™ã‚‹ + call fuf#givendir#launch('', 0, '>', split(&runtimepath, ',')) +< + + *fuf-givencmd-mode* +Given-Command モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ä¸Žãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã•れãŸã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ API ã‚’æä¾›ã—ã¾ã™ã€‚ + +é¸æŠžã•れãŸã‚³ãƒžãƒ³ãƒ‰ã¯ feedkeys() ã«ã‚ˆã£ã¦å®Ÿè¡Œã•れるã®ã§ã€ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã§ã®ä¸€é€£ +ã®ã‚­ãƒ¼å…¥åŠ›ã‚’ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆã•ã›ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã™ã€‚ + +API 関数: +> + function fuf#givencmd#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - FuzzyFinder èµ·å‹•ç›´å¾Œã«æŒ¿å…¥ã•れる文字列 + partialMatching - ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‹ + prompt - プロンプト文字列 + items - アイテムã®ãƒªã‚¹ãƒˆ + + +利用例: +> + function GetAllCommands() + redir => commands + silent command + redir END + return map((split(commands, "\n")[3:]), + \ '":" . matchstr(v:val, ''^....\zs\S*'')') + endfunction + + " ãƒ¦ãƒ¼ã‚¶ãƒ¼å®šç¾©ã‚³ãƒžãƒ³ãƒ‰ã‚’é¸æŠžã—ã¦å®Ÿè¡Œ + call fuf#givencmd#launch('', 0, '>', GetAllCommands()) + +< + + *fuf-callbackfile-mode* +Callback-File モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ãƒ•ァイルを検索ã—ã¦é¸æŠžã•れãŸãƒ•ァイルパスを得る API ã‚’æä¾›ã—ã¾ã™ã€‚ + +API 関数: +> + function fuf#callbackfile#launch( + \ initialPattern, partialMatching, prompt, exclude, listener) +< + initialPattern - FuzzyFinder èµ·å‹•ç›´å¾Œã«æŒ¿å…¥ã•れる文字列 + partialMatching - ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‹ + prompt - プロンプト文字列 + exclude - 補完リストã‹ã‚‰é™¤å¤–ã—ãŸã„ã‚¢ã‚¤ãƒ†ãƒ ã®æ­£è¦è¡¨ç¾ãƒ‘ターン + listener - 'onComplete' 㨠'onAbort' ã‚’æŒã¤|Dictionary|。ã“れ + ら㯠FuzzyFinder 終了時ã«å‘¼ã°ã‚Œã¾ã™ã€‚ + listener.onComplete(item, method) ã¯é¸æŠžãŒå®Œäº†ã—ãŸã¨ + ãã€é¸æŠžã•れãŸã‚¢ã‚¤ãƒ†ãƒ åã¨ã‚ªãƒ¼ãƒ—ン方å¼ç•ªå·ã®2引数㨠+ å…±ã«å‘¼ã°ã‚Œã¾ã™ã€‚listener.onAbort() ã¯é¸æŠžã‚’中止ã—㟠+ ã¨ãã«å‘¼ã°ã‚Œã¾ã™ã€‚ + +利用例: +> + let listener = {} + + function listener.onComplete(item, method) + echo "Item: " . a:item . "\nMethod: " . a:method + endfunction + + function listener.onAbort() + echo "Abort" + endfunction + + " カレントディレクトリã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + call fuf#callbackfile#launch('', 0, '>', '', listener) + + " ホームディレクトリã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + call fuf#callbackfile#launch('~/', 0, '>', '', listener) +< + + *fuf-callbackitem-mode* +Callback-Item モード ~ + +ã“ã®ãƒ¢ãƒ¼ãƒ‰ã¯ä¸Žãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã•れãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å¾—ã‚‹ãŸã‚ã® API ã‚’æä¾›ã—ã¾ +ã™ã€‚ + +API 関数: +> + function fuf#callbackitem#launch( + \ initialPattern, partialMatching, prompt, listener, items, forPath) +< + initialPattern - FuzzyFinder èµ·å‹•ç›´å¾Œã«æŒ¿å…¥ã•れる文字列 + partialMatching - ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‹ + prompt - プロンプト文字列 + listener - 'onComplete' 㨠'onAbort' ã‚’æŒã¤|Dictionary|。ã“れ + ら㯠FuzzyFinder 終了時ã«å‘¼ã°ã‚Œã¾ã™ã€‚ + listener.onComplete(item, method) ã¯é¸æŠžãŒå®Œäº†ã—ãŸã¨ + ãã€é¸æŠžã•れãŸã‚¢ã‚¤ãƒ†ãƒ åã¨ã‚ªãƒ¼ãƒ—ン方å¼ç•ªå·ã®2引数㨠+ å…±ã«å‘¼ã°ã‚Œã¾ã™ã€‚listener.onAbort() ã¯é¸æŠžã‚’中止ã—㟠+ ã¨ãã«å‘¼ã°ã‚Œã¾ã™ã€‚ + items - アイテムã®ãƒªã‚¹ãƒˆ + forPath - ãƒ•ã‚¡ã‚¤ãƒ«é¸æŠžã«ç‰¹åŒ–ã—ãŸãƒžãƒƒãƒãƒ³ã‚°ã‚’利用ã™ã‚‹ã‹ + +利用例: +> + let listener = {} + + function listener.onComplete(item, method) + echo "Item: " . a:item . "\nMethod: " . a:method + endfunction + + function listener.onAbort() + echo "Abort" + endfunction + + " 与ãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠž + call fuf#callbackitem#launch('', 0, '>', listener, ['ed', 'vi', 'vim'], 0) + + " 与ãˆã‚‰ã‚ŒãŸãƒªã‚¹ãƒˆã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + call fuf#callbackitem#launch('', 0, '>', listener, ['../foo/bar', 'baz'], 1) +< + +============================================================================== +詳細ãªãƒˆãƒ”ック *fuf-detailed-topics* + + *fuf-search-patterns* +検索パターン ~ + +検索パターンã¨ã—ã¦ã€ä¸€ã¤ã®ãƒ—ライマリパターンã¨0個以上ã®çµžã‚Šè¾¼ã¿ãƒ‘ターンを入力 +ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚入力パターン㯠";" (|g:fuf_patternSeparator|) ã§åŒºåˆ‡ã‚‰ã‚Œã€ +最åˆã®ãƒ‘ターンãŒãƒ—ライマリパターンã«ãªã‚Šã€æ®‹ã‚Šã®ãƒ‘ターンãŒçµžã‚Šè¾¼ã¿ãƒ‘ターンã«ãª +りã¾ã™ã€‚ +> + プライマリ 絞り込㿠絞り込㿠+ |----------| |-------| |----| + >MruFile>bookmark.vim;autoload/;/home/ +< +プライマリパターンã«ãƒžãƒƒãƒã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã®ãƒªã‚¹ãƒˆã‚’別ã®ãƒ‘ターンã§çµžã‚Šè¾¼ã‚€ãŸã‚ã«ã€ +絞り込ã¿ãƒ‘ターンを利用ã—ã¾ã™ã€‚ + +プライマリパターンã§ã¯ã€ã‚ã„ã¾ã„マッãƒãƒ³ã‚°ã¨éƒ¨åˆ†ä¸€è‡´ãƒžãƒƒãƒãƒ³ã‚°ã®ã†ã¡ã€é¸æŠžã•れ +ãŸæ–¹ã‚’行ã„ã¾ã™ã€‚絞り込ã¿ãƒ‘ターンã§ã¯ã€å¸¸ã«éƒ¨åˆ†ä¸€è‡´ãƒžãƒƒãƒãƒ³ã‚°ã‚’行ã„ã¾ã™ã€‚ + +絞り込ã¿ãƒ‘ターンã¨ã—ã¦æ•°å€¤ã‚’入力ã—ãŸå ´åˆã€ã‚¢ã‚¤ãƒ†ãƒ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã«å¯¾ã—ã¦ã‚‚ +マッãƒãƒ³ã‚°ã—ã¾ã™ã€‚ + +ファイルパスã®é™çš„ãªé›†åˆã‚’対象ã¨ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ (Buffer, MRU-File モードãªã©ã€‚File, +Directory モードãªã©ã§ã¯ãªã„) ã§|g:fuf_splitPathMatching|ãŒçœŸã®å ´åˆã€ãƒ—ライマ +リパターンã®ãƒžãƒƒãƒãƒ³ã‚°ã¯ head 部ã¨tail 部ã«åˆ†ã‘ã¦è¡Œã‚れã¾ã™ã€‚ +> + head tail + |------||-----| + foo/bar/baz.vim + + ã‚ã„ã¾ã„マッãƒãƒ³ã‚°ä¾‹: + +----------------+---------+---------+---------+ + | item \ pattern | foo/bar | foo/ | bar | + +----------------+---------+---------+---------+ + | foo/bar | match | match | match | + | foo/abc | unmatch | match | unmatch | + | abc/bar | unmatch | unmatch | match | + | foobar | unmatch | unmatch | match | + | foooo/barrrr | match | match | match | + | foooo/fooooo | unmatch | match | unmatch | + +----------------+---------+---------+---------+ +< +上記ã®ã‚±ãƒ¼ã‚¹ã§ã€çµžã‚Šè¾¼ã¿ãƒ‘ターンã¯ãƒ‘ス全体ã«å¯¾ã—ã¦ãƒžãƒƒãƒãƒ³ã‚°ã§ãã¾ã™ã€‚ + + *fuf-sorting-of-completion-items* +補完アイテムã®ã‚½ãƒ¼ãƒˆ ~ + +FuzzyFinder ã¯å¹¾ã¤ã‹ã®ãƒ«ãƒ¼ãƒ«ã«å¾“ã£ã¦è£œå®Œã‚¢ã‚¤ãƒ†ãƒ ã‚’ソートã—ã¾ã™ã€‚ + +パターン全体ãŒä¸€éƒ¨åˆ†ã«ã´ã£ãŸã‚Šãƒžãƒƒãƒã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã¯å„ªå…ˆã•れã¾ã™ã€‚例ãˆã°ã€ãƒ‘ター +ン "bc" ã§ã¯ã‚¢ã‚¤ãƒ†ãƒ  "abc" 㯠"bac" より優先ã•れã¾ã™ã€‚ + +ã“ã®ã‚±ãƒ¼ã‚¹ã§ã€ãƒžãƒƒãƒã™ã‚‹éƒ¨åˆ†ãŒå…ˆé ­ã§ã‚るアイテムã¯ãã†ã§ãªã„アイテムより優先㕠+れã¾ã™ã€‚例ãˆã°ãƒ‘ターン "foo" ã§ã¯ã‚¢ã‚¤ãƒ†ãƒ  "foobar" ã¯"barfoo" より優先ã•れã¾ã™ +。 + +マッãƒãƒ³ã‚°ä½ç½®ã‚ˆã‚Šå¾Œã®æ–‡å­—æ•°ãŒå°‘ãªã„ã»ã©å„ªå…ˆã•れã¾ã™ã€‚例ãˆã°ãƒ‘ターン "bar" ã§ +ã¯ã‚¢ã‚¤ãƒ†ãƒ "foobar" ã¯"foobarbaz"より優先ã•れã¾ã™ã€‚ + +å˜èªžã®å¢ƒç•Œæ–‡å­—ã«ã ã‘マッãƒãƒ³ã‚°ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã¯å„ªå…ˆã•れã¾ã™ã€‚ 例ãˆã°ã€ãƒ‘ターン +"fb" ã§ã¯ã‚¢ã‚¤ãƒ†ãƒ "fooBarBaz" ã‚„ "foo_bar_baz" ãªã©ãŒå„ªå…ˆã•れã¾ã™ã€‚ + +加ãˆã¦ã€FuzzyFinder ã«ã¯å­¦ç¿’システムãŒã‚りã¾ã™ã€‚ç¾åœ¨ã®ãƒ‘ターンã§ã€éŽåŽ»ã«è£œå®Œã• +れãŸã“ã¨ã®ã‚るアイテムを優先ã—ã¾ã™ã€‚ + + *fuf-reusing-window* +目的ã®ãƒãƒƒãƒ•ã‚¡/ファイルãŒé–‹ã‹ã‚Œã¦ã„るウィンドウã®å†åˆ©ç”¨ ~ + +ウィンドウを分割ã—ã¦ãƒãƒƒãƒ•ã‚¡/ファイルを開ãã¨ãã«ã€ç¾åœ¨ã®ã‚¿ãƒ–ページã§ãれãŒé–‹ +ã‹ã‚Œã¦ã„るウィンドウãŒè¦‹ã¤ã‹ã£ãŸå ´åˆã€ãã“ã¸ç§»å‹•ã—ã¾ã™ã€‚別ã®ã‚¿ãƒ–ページã§ãƒãƒƒãƒ• +ã‚¡/ファイルを開ãã¨ãã«ã€ä»–ã®ã‚¿ãƒ–ページã§ãれãŒé–‹ã‹ã‚Œã¦ã„るウィンドウãŒè¦‹ã¤ã‹ +ã£ãŸå ´åˆã€ãã“ã¸ç§»å‹•ã—ã¾ã™ã€‚ + +常ã«ãƒãƒƒãƒ•ã‚¡/ファイルを新ウィンドウã§é–‹ããŸã„å ´åˆã€'reuse_window'オプション㧠+ã“ã®æ©Ÿèƒ½ã‚’無効ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + *fuf-hiding-menu* +補完メニューã®ä¸€æ™‚éžè¡¨ç¤º ~ + + ã§è£œå®Œãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’é–‰ã˜ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ã§å†åº¦é–‹ãã“ã¨ãŒã§ +ãã¾ã™ã€‚ + + *fuf-abbreviation* *fuf-multiple-search* +短縮入力åŠã³è¤‡åˆæ¤œç´¢ ~ + +|g:fuf_abbrevMap|を設定ã™ã‚‹ã“ã¨ã§ã€å…¨ãƒ¢ãƒ¼ãƒ‰ã§çŸ­ç¸®å…¥åŠ›ã¨è¤‡åˆæ¤œç´¢ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚ + +例ãˆã°æ¬¡ã®ã‚ˆã†ã«è¨­å®šã—ãŸã¨ã—ã¾ã™: +> + let g:fuf_abbrevMap = { + \ "^doc:" : [ + \ "~/project/**/doc/", + \ ".vim/doc/", + \ ], + \ } +< +ãã—㦠File モード㧠"doc:txt" ã¨å…¥åŠ›ã™ã‚‹ã¨ã€æ¬¡ã®2ã¤ã®ãƒ‘ã‚¿ãƒ¼ãƒ³ã®æ¤œç´¢çµæžœã‚’è¤‡åˆ +ã—ã¾ã™: + + "~/project/**/doc/*t*x*t*" + ".vim/doc/*t*x*t*" + + *fuf-information-file* +情報ファイル ~ + +FuzzyFinder ã¯è£œå®Œçµ±è¨ˆã€MRUデータã€ãƒ–ックマークãªã©ã‚’ +|g:fuf_infoFile|ã«æ›¸ãè¾¼ã¿ã¾ã™ã€‚ + +:FufEditInfo ã‚³ãƒžãƒ³ãƒ‰ã¯æƒ…報ファイルã®ç·¨é›†ã‚’補助ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’ +実行ã™ã‚‹ã¨ã€æƒ…報ファイルを無åãƒãƒƒãƒ•ã‚¡ã«èª­ã¿è¾¼ã¿ã¾ã™ã€‚:write ãªã©ã§æ›¸ãè¾¼ã¿ã‚’ +行ã†ã¨ã€æƒ…報ファイルを更新ã—ã¾ã™ã€‚ + + *fuf-cache* +キャッシュ ~ + +一旦キャッシュãŒç”Ÿæˆã•れるã¨ã€ãƒ¬ã‚¹ãƒãƒ³ã‚¹ã‚’å‘上ã•ã›ã‚‹ãŸã‚自動的ã«ã¯æ›´æ–°ã•れã¾ã› +ん。ã“れを更新ã™ã‚‹ã«ã¯|:FufRenewCache|コマンドを実行ã—ã¦ãã ã•ã„。 + + *fuf-dot-sequence* +ドット列ã§è¦ªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¸ç§»å‹• ~ + +ドット列を入力ã™ã‚‹ã“ã¨ã§è¦ªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’上ãŒã£ã¦ã„ãã“ã¨ãŒã§ãã¾ã™ã€‚パス区切り +文字直後ã®ãƒ‰ãƒƒãƒˆåˆ—㯠"../" ã®åˆ—ã«å±•é–‹ã•れã¾ã™ã€‚ + + ドット列 展開パターン ~ + /.. /../ + /... /../../ + /.... /../../../ + + *fuf-migemo* +Migemo ã¨ã¯ ~ + +以下ã®ãƒšãƒ¼ã‚¸ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + - http://0xcc.net/migemo/ + - http://www.kaoriya.net/#CMIGEMO + + +============================================================================== +コマンド *fuf-commands* + +See also: |fuf-vimrc-example| + + *:FufBuffer* +:FufBuffer [{pattern}] + Buffer モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufFile* +:FufFile [{pattern}] + File モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufFileWithFullCwd* +:FufFileWithFullCwd [{pattern}] + カレントディレクトリã®ãƒ•ãƒ«ãƒ‘ã‚¹ã‚’åˆæœŸãƒ‘ターンã¨ã™ã‚‹ä»¥å¤–ã¯|:FufFile|ã¨åŒ + ã˜ã§ã™ã€‚ + + *:FufFileWithCurrentBufferDir* +:FufFileWithCurrentBufferDir [{pattern}] + カレントãƒãƒƒãƒ•ã‚¡ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’åˆæœŸãƒ‘ターンã¨ã™ã‚‹ä»¥å¤–ã¯|:FufFile|ã¨åŒ + ã˜ã§ã™ã€‚ + + *:FufDir* +:FufDir [{pattern}] + Directory モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufDirWithFullCwd* +:FufDirWithFullCwd [{pattern}] + カレントディレクトリã®ãƒ•ãƒ«ãƒ‘ã‚¹ã‚’åˆæœŸãƒ‘ターンã¨ã™ã‚‹ä»¥å¤–ã¯|:FufDir|ã¨åŒ + ã˜ã§ã™ã€‚ + + *:FufDirWithCurrentBufferDir* +:FufDirWithCurrentBufferDir [{pattern}] + カレントãƒãƒƒãƒ•ã‚¡ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’åˆæœŸãƒ‘ターンã¨ã™ã‚‹ä»¥å¤–ã¯|:FufDir|ã¨åŒ + ã˜ã§ã™ã€‚ + + *:FufMruFile* +:FufMruFile [{pattern}] + MRU-File モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufMruCmd* +:FufMruCmd [{pattern}] + MRU-Command モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufBookmark* +:FufBookmark [{pattern}] + Bookmark モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufTag* +:FufTag [{pattern}] + Tag モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufTagWithCursorWord* +:FufTagWithCursorWord [{pattern}] + カーソル下ã®å˜èªžã‚’åˆæœŸãƒ‘ターンã¨ã™ã‚‹ä»¥å¤–ã¯|:FufTag|ã¨åŒã˜ã§ã™ã€‚ + + *:FufTaggedFile* +:FufTaggedFile [{pattern}] + Tagged-File モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufJumpList* +:FufJumpList [{pattern}] + Jump-List モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufChangeList* +:FufChangeList [{pattern}] + Change-List モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufQuickfix* +:FufQuickfix [{pattern}] + Quickfix モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufLine* +:FufLine [{pattern}] + Line モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufHelp* +:FufHelp[!] [{pattern}] + Help モードを起動ã—ã¾ã™ã€‚ + + ! 修飾å­ã‚’付ã‘ã¦å®Ÿè¡Œã—ãŸå ´åˆã€ã‚ã„ã¾ã„検索ã§ã¯ãªã部分一致検索を行ã†ã‚ˆ + ã†ã«ãªã‚Šã¾ã™ã€‚ + + FuzzyFinder 起動後㫠{pattern} ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + *:FufEditInfo* +:FufEditInfo + 情報ファイルを編集ã™ã‚‹ãŸã‚ã®ãƒãƒƒãƒ•ã‚¡ã‚’é–‹ãã¾ã™ã€‚詳ã—ã㯠+ |fuf-information-file|ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + + *:FufAddBookmark* +:FufAddBookmark [{name}] + カーソル行をブックマークã«è¿½åŠ ã—ã¾ã™ã€‚詳ã—ãã¯|fuf-adding-bookmark|ã‚’ + å‚ç…§ã—ã¦ãã ã•ã„。 + + *:FufAddBookmarkAsSelectedText* +:FufAddBookmarkAsSelectedText + 最後ã«é¸æŠžã•れãŸãƒ†ã‚­ã‚¹ãƒˆã‚’ブックマークåã¨ã™ã‚‹ä»¥å¤–ã¯|:FufAddBookmark| + ã¨åŒã˜ã§ã™ã€‚ + + *:FufRenewCache* +:FufRenewCache + 補完アイテムを作り直ã™ãŸã‚ã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’削除ã—ã¾ã™ã€‚詳ã—ã㯠+ |fuf-cache|ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + + +============================================================================== +オプション *fuf-options* + + *fuf-options-for-all-modes* +全モード用 ~ + + *g:fuf_modesDisable* > + let g:fuf_modesDisable = [ 'mrufile', 'mrucmd', ] +< + 無効ã«ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰åã®ãƒªã‚¹ãƒˆã€‚ã“れã«å«ã¾ã‚Œã‚‹ãƒ¢ãƒ¼ãƒ‰ã¯åˆæœŸåŒ–ã•れãšã€ã‚¤ãƒ™ãƒ³ + トã®å‡¦ç†ã‚‚行ã‚れã¾ã›ã‚“。 + + *g:fuf_keyOpen* > + let g:fuf_keyOpen = '' +< + 補完を確定ã—ã€ãƒãƒƒãƒ•ã‚¡/ファイルを直å‰ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ãキー。 + + *g:fuf_keyOpenSplit* > + let g:fuf_keyOpenSplit = '' +< + 補完を確定ã—ã€ãƒãƒƒãƒ•ã‚¡/ファイルを直å‰ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’分割ã—ã¦é–‹ãキー。 + + *g:fuf_keyOpenVsplit* > + let g:fuf_keyOpenVsplit = '' +< + 補完を確定ã—ã€ãƒãƒƒãƒ•ã‚¡/ファイルを直å‰ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’垂直分割ã—ã¦é–‹ãã‚­ + ー。 + + *g:fuf_keyOpenTabpage* > + let g:fuf_keyOpenTabpage = '' +< + 補完を確定ã—ã€ãƒãƒƒãƒ•ã‚¡/ファイルを別タブページ開ãキー。 + + *g:fuf_keyPreview* > + let g:fuf_keyPreview = '' +< + é¸æŠžã•れã¦ã„ã‚‹è£œå®Œã‚¢ã‚¤ãƒ†ãƒ ã®æƒ…報をコマンドライン領域ã«è¡¨ç¤ºã™ã‚‹ã‚­ãƒ¼ã€‚プ + レビューをサãƒãƒ¼ãƒˆã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã®ã¿ä½œç”¨ã—ã¾ã™ã€‚ + + *g:fuf_keyNextMode* > + let g:fuf_keyNextMode = '' +< + 次ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã‚­ãƒ¼ã€‚ + + *g:fuf_keyPrevMode* > + let g:fuf_keyPrevMode = '' +< + å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã‚­ãƒ¼ã€‚ + + *g:fuf_keyPrevPattern* > + let g:fuf_keyPrevPattern = '' +< + 履歴ã‹ã‚‰å‰ã®å…¥åŠ›ãƒ‘ã‚¿ãƒ¼ãƒ³ã‚’å‘¼ã³å‡ºã™ã‚­ãƒ¼ã€‚ + + *g:fuf_keyNextPattern* > + let g:fuf_keyNextPattern = '' +< + 履歴ã‹ã‚‰æ¬¡ã®å…¥åŠ›ãƒ‘ã‚¿ãƒ¼ãƒ³ã‚’å‘¼ã³å‡ºã™ã‚­ãƒ¼ã€‚ + + *g:fuf_keySwitchMatching* > + let g:fuf_keySwitchMatching = '' +< + ã‚ã„ã¾ã„マッãƒãƒ³ã‚°ã¨éƒ¨åˆ†ä¸€è‡´ãƒžãƒƒãƒãƒ³ã‚°ã‚’切り替ãˆã‚‹ã‚­ãƒ¼ã€‚ + + *g:fuf_infoFile* > + let g:fuf_infoFile = '~/.vim-fuf' +< + 補完統計ã€MRUデータã€ãƒ–ックマークãªã©ã‚’書ã込むファイル。空文字列を設 + 定ã™ã‚‹ã¨ãƒ•ァイルã¸ã®æ›¸ãè¾¼ã¿ã¯è¡Œã‚れãªããªã‚Šã¾ã™ã€‚ + + *g:fuf_abbrevMap* > + let g:fuf_abbrevMap = {} +< + |Dictionary|åž‹ã§ãれãžã‚Œã®å€¤ã¯|List|åž‹ã§ã™ã€‚入力ã•れãŸãƒ†ã‚­ã‚¹ãƒˆã®ã€ã‚­ãƒ¼ + ã«ãƒžãƒƒãƒã™ã‚‹éƒ¨åˆ†ãŒå¯¾å¿œã™ã‚‹å€¤ã«å±•é–‹ã•れã¾ã™ã€‚ + + *g:fuf_patternSeparator* > + let g:fuf_patternSeparator = ';' +< + 入力パターンをプライマリパターンã¨çµžã‚Šè¾¼ã¿ãƒ‘ターン列ã«åŒºåˆ‡ã‚‹æ–‡å­—列。 + + *g:fuf_promptHighlight* > + let g:fuf_promptHighlight = 'Question' +< + プロンプトをãƒã‚¤ãƒ©ã‚¤ãƒˆã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—å。 + + *g:fuf_ignoreCase* > + let g:fuf_ignoreCase = 1 +< + 真ãªã‚‰ã€å¤§æ–‡å­—å°æ–‡å­—を無視ã—ã¾ã™ã€‚ + + *g:fuf_splitPathMatching* > + let g:fuf_splitPathMatching = 1 +< + 真ãªã‚‰ã€ãƒ—ライマリパターンã®ãƒžãƒƒãƒãƒ³ã‚°ã¯ head 部ã¨tail 部ã«åˆ†ã‘ã¦è¡Œã‚ + れã¾ã™ã€‚ + + See also: |fuf-search-patterns| + + *g:fuf_smartBs* > + let g:fuf_smartBs = 1 +< + 真ãªã‚‰ã€ãƒ‘ス区切り文字ã®ç›´å¾Œã§ を入力ã™ã‚‹ã¨ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå1ã¤åˆ†ã‚’ + 削除ã—ã€|g:fuf_patternSeparator|ã®ç›´å¾Œã§ を入力ã™ã‚‹ã¨ãƒ‘ターン1ã¤åˆ† + を削除ã—ã¾ã™ã€‚ + + *g:fuf_reuseWindow* > + let g:fuf_reuseWindow = 1 +< + 真ãªã‚‰ã€ã™ã§ã«é–‹ã‹ã‚Œã¦ã„ã‚‹ãƒãƒƒãƒ•ã‚¡ã‚’é–‹ãã¨ãã€ç›®çš„ã®ãƒãƒƒãƒ•ã‚¡ã‚’å«ã‚€ã‚¦ã‚£ + ンドウをå†åˆ©ç”¨ã—ã¾ã™ã€‚ + + *g:fuf_timeFormat* > + let g:fuf_timeFormat = '(%Y-%m-%d %H:%M:%S)' +< + アイテムãŒç™»éŒ²ã•ã‚ŒãŸæ—¥æ™‚ã®æ›¸å¼ã‚’設定ã—ã¾ã™ã€‚書å¼ã®è©³ç´°ã¯|strftime()|ã‚’ + å‚ç…§ã—ã¦ãã ã•ã„。 + + *g:fuf_learningLimit* > + let g:fuf_learningLimit = 100 +< + ä¿æŒã™ã‚‹è£œå®Œçµ±è¨ˆãƒ‡ãƒ¼ã‚¿ã®ãƒ¢ãƒ¼ãƒ‰æ¯Žã®ä¸Šé™å€¤ã§ã™ã€‚ + + *g:fuf_enumeratingLimit* > + let g:fuf_enumeratingLimit = 50 +< + レスãƒãƒ³ã‚¹ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã€è£œå®Œã‚¢ã‚¤ãƒ†ãƒ ã®åˆ—挙をã“ã®æ•°ã«é”ã—ãŸæ™‚ç‚¹ã§æ‰“ + ã¡åˆ‡ã‚Šã¾ã™ã€‚ + + *g:fuf_maxMenuWidth* > + let g:fuf_maxMenuWidth = 78 +< + é•·ã„補完アイテムã¯ã€ã“ã®é•·ã•ã«åŽã¾ã‚‹ã‚ˆã†çœç•¥ã—ã¦è¡¨ç¤ºã—ã¾ã™ã€‚ + + *g:fuf_previewHeight* > + let g:fuf_previewHeight = 5 +< + プレビューをサãƒãƒ¼ãƒˆã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã‚’èµ·å‹•ã—ãŸã¨ãã€'cmdheight'ãŒã“ã®å€¤ã«è¨­ + 定ã•れã¾ã™ã€‚é¸æŠžã•れã¦ã„ã‚‹è£œå®Œã‚¢ã‚¤ãƒ†ãƒ ã®æƒ…å ±ãŒã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³é ˜åŸŸã«è¡¨ç¤º + ã•れã¾ã™ã€‚0 ãªã‚‰ãƒ—レビュー機能ã¯ç„¡åйã«ãªã‚Šã¾ã™ã€‚ + + *g:fuf_useMigemo* > + let g:fuf_useMigemo = 0 +< + 真ãªã‚‰ migemo を利用ã—ã¾ã™ã€‚ + + *fuf-options-for-buffer-mode* +Buffer モード用 ~ + + *g:fuf_buffer_prompt* > + let g:fuf_buffer_prompt = '>Buffer[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_buffer_switchOrder* > + let g:fuf_buffer_switchOrder = 10 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_buffer_mruOrder* > + let g:fuf_buffer_mruOrder = 1 +< + 真ãªã‚‰ã€æœ€å¾Œã«ä½¿ã£ãŸæ™‚é–“é †ã«è£œå®Œã‚¢ã‚¤ãƒ†ãƒ ã‚’ソートã—ã¾ã™ã€‚ + + *fuf-options-for-file-mode* +File モード用 ~ + + *g:fuf_file_prompt* > + let g:fuf_file_prompt = '>File[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_file_switchOrder* > + let g:fuf_file_switchOrder = 20 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_file_exclude* > + let g:fuf_file_exclude = '\v\~$|\.(o|exe|bak|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])' +< + 補完リストã‹ã‚‰é™¤å¤–ã—ãŸã„ã‚¢ã‚¤ãƒ†ãƒ ã®æ­£è¦è¡¨ç¾ãƒ‘ターン。 + + *fuf-options-for-dir-mode* +Directory モード用 ~ + + *g:fuf_dir_prompt* > + let g:fuf_dir_prompt = '>Dir[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_dir_switchOrder* > + let g:fuf_dir_switchOrder = 30 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_dir_exclude* > + let g:fuf_dir_exclude = '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])' +< + 補完リストã‹ã‚‰é™¤å¤–ã—ãŸã„ã‚¢ã‚¤ãƒ†ãƒ ã®æ­£è¦è¡¨ç¾ãƒ‘ターン。 + + *fuf-options-for-mrufile-mode* +Mru-File モード用 ~ + + *g:fuf_mrufile_prompt* > + let g:fuf_mrufile_prompt = '>Mru-File[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_mrufile_switchOrder* > + let g:fuf_mrufile_switchOrder = 40 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_mrufile_exclude* > + let g:fuf_mrufile_exclude = '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)' +< + 補完リストã‹ã‚‰é™¤å¤–ã—ãŸã„ã‚¢ã‚¤ãƒ†ãƒ ã®æ­£è¦è¡¨ç¾ãƒ‘ターン。 + + *g:fuf_mrufile_maxItem* > + let g:fuf_mrufile_maxItem = 200 +< + ä¿æŒã™ã‚‹MRUアイテムã®ä¸Šé™å€¤ã€‚ + + *fuf-options-for-mrucmd-mode* +Mru-Cmd モード用 ~ + + *g:fuf_mrucmd_prompt* > + let g:fuf_mrucmd_prompt = '>Mru-Cmd[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_mrucmd_switchOrder* > + let g:fuf_mrucmd_switchOrder = 50 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_mrucmd_exclude* > + let g:fuf_mrucmd_exclude = '^$' +< + 補完リストã‹ã‚‰é™¤å¤–ã—ãŸã„ã‚¢ã‚¤ãƒ†ãƒ ã®æ­£è¦è¡¨ç¾ãƒ‘ターン。 + + *g:fuf_mrucmd_maxItem* > + let g:fuf_mrucmd_maxItem = 200 +< + ä¿æŒã™ã‚‹MRUアイテムã®ä¸Šé™å€¤ã€‚ + + *fuf-options-for-Bookmark-mode* +Bookmark モード用 ~ + + *g:fuf_bookmark_prompt* > + let g:fuf_bookmark_prompt = '>Bookmark[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_bookmark_switchOrder* > + let g:fuf_bookmark_switchOrder = 60 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_bookmark_searchRange* > + let g:fuf_bookmark_searchRange = 400 +< + ジャンプã™ã‚‹ã¨ãã€ãƒ–ックマークã—ãŸä½ç½®ã‹ã‚‰ã“ã®è¡Œæ•°ã®ç¯„囲内ã§ãƒ–ックマー + クã—ãŸã¨ãã®ãƒ‘ターンã¨ãƒžãƒƒãƒã™ã‚‹è¡Œã‚’探ã—ã¾ã™ã€‚ + + *g:fuf_bookmark_keyDelete* > + let g:fuf_bookmark_keyDelete = '' +< + é¸æŠžã—ãŸãƒ–ックマークを削除ã™ã‚‹ã‚­ãƒ¼ã€‚ + + *fuf-options-for-tag-mode* +Tag モード用 ~ + + *g:fuf_tag_prompt* > + let g:fuf_tag_prompt = '>Tag[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_tag_switchOrder* > + let g:fuf_tag_switchOrder = 70 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_tag_cache_dir* > + let g:fuf_tag_cache_dir = '~/.vim-fuf-cache/tag' +< + ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå†…ã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãƒ•ァイルãŒä½œæˆã•れã¾ã™ã€‚空文字列ãªã‚‰ä½œæˆ + ã•れã¾ã›ã‚“。 + + *fuf-options-for-taggedfile-mode* +Tagged-File モード用 ~ + + *g:fuf_taggedfile_prompt* > + let g:fuf_taggedfile_prompt = '>Tagged-File[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_taggedfile_switchOrder* > + let g:fuf_taggedfile_switchOrder = 80 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_taggedfile_cache_dir* > + let g:fuf_taggedfile_cache_dir = '~/.vim-fuf-cache/taggedfile' +< + ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå†…ã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãƒ•ァイルãŒä½œæˆã•れã¾ã™ã€‚空文字列ãªã‚‰ä½œæˆ + ã•れã¾ã›ã‚“。 + + *fuf-options-for-jumplist-mode* +Jump-List モード用 ~ + + *g:fuf_jumplist_prompt* > + let g:fuf_jumplist_prompt = '>Jump-List[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_jumplist_switchOrder* > + let g:fuf_jumplist_switchOrder = 90 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *fuf-options-for-changelist-mode* +Change-List モード用 ~ + + *g:fuf_changelist_prompt* > + let g:fuf_changelist_prompt = '>Change-List[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_changelist_switchOrder* > + let g:fuf_changelist_switchOrder = 100 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *fuf-options-for-quickfix-mode* +Quickfix モード用 ~ + + *g:fuf_quickfix_prompt* > + let g:fuf_quickfix_prompt = '>Quickfix[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_quickfix_switchOrder* > + let g:fuf_quickfix_switchOrder = 110 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *fuf-options-for-line-mode* +Line モード用 ~ + + *g:fuf_line_prompt* > + let g:fuf_line_prompt = '>Line[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_line_switchOrder* > + let g:fuf_line_switchOrder = 120 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *fuf-options-for-help-mode* +Help モード用 ~ + + *g:fuf_help_prompt* > + let g:fuf_help_prompt = '>Help[]>' +< + プロンプト文字列。"[]" ã¯ã‚¤ãƒ³ã‚¸ã‚±ãƒ¼ã‚¿ã«ç½®æ›ã•れã¾ã™ã€‚ + + *g:fuf_help_switchOrder* > + let g:fuf_help_switchOrder = 130 +< + 次/å‰ã®ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã‚‹ã¨ãã®ã€ãƒ¢ãƒ¼ãƒ‰ã®é †ä½ã§ã™ã€‚è² æ•°ãªã‚‰ã“ã®ãƒ¢ãƒ¼ãƒ‰ + ã«ã¯åˆ‡ã‚Šæ›¿ãˆã¾ã›ã‚“。 + + *g:fuf_help_cache_dir* > + let g:fuf_help_cache_dir = '~/.vim-fuf-cache/help' +< + ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªå†…ã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãƒ•ァイルãŒä½œæˆã•れã¾ã™ã€‚空文字列ãªã‚‰ä½œæˆ + ã•れã¾ã›ã‚“。 + + +============================================================================== +vimrc ã®ä¾‹ *fuf-vimrc-example* + +> + let g:fuf_modesDisable = [] + let g:fuf_abbrevMap = { + \ '^vr:' : map(filter(split(&runtimepath, ','), 'v:val !~ "after$"'), 'v:val . ''/**/'''), + \ '^m0:' : [ '/mnt/d/0/', '/mnt/j/0/' ], + \ } + let g:fuf_mrufile_maxItem = 300 + let g:fuf_mrucmd_maxItem = 400 + nnoremap :FufBuffer + nnoremap :FufFileWithCurrentBufferDir + nnoremap :FufFileWithFullCwd + nnoremap p :FufFile + nnoremap :FufDirWithCurrentBufferDir + nnoremap d :FufDirWithFullCwd + nnoremap D :FufDir + nnoremap :FufMruFile + nnoremap :FufMruCmd + nnoremap :FufBookmark + nnoremap :FufTag + nnoremap t :FufTag! + noremap g] :FufTagWithCursorWord! + nnoremap :FufTaggedFile + nnoremap :FufJumpList + nnoremap :FufChangeList + nnoremap :FufQuickfix + nnoremap :FufLine + nnoremap :FufHelp + nnoremap :FufAddBookmark + vnoremap :FufAddBookmarkAsSelectedText + nnoremap :FufEditInfo + nnoremap :FufRenewCache +< + +============================================================================== +ã‚ã°ã†ã¨ *fuf-about* *fuf-contact* *fuf-author* + +作者: Takeshi NISHIDA +ライセンス: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=1984 + http://bitbucket.org/ns9tks/vim-fuzzyfinder/ + +ãƒã‚°ã‚„è¦æœ›ãªã© ~ + +ã“ã¡ã‚‰ã¸ã©ã†ãž: http://bitbucket.org/ns9tks/vim-fuzzyfinder/issues/ + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/fuf.txt b/doc/fuf.txt new file mode 100644 index 0000000..d6d64c0 --- /dev/null +++ b/doc/fuf.txt @@ -0,0 +1,1562 @@ +*fuf.txt* buffer/file/command/tag/etc explorer with fuzzy matching. + + Copyright (c) 2007-2009 Takeshi NISHIDA + +FuzzyFinder *fuzzyfinder* *fuf* + +INTRODUCTION |fuf-introduction| +INSTALLATION |fuf-installation| +USAGE |fuf-usage| +MODES |fuf-modes| +DETAILED TOPICS |fuf-detailed-topics| +COMMANDS |fuf-commands| +OPTIONS |fuf-options| +VIMRC EXAMPLE |fuf-vimrc-example| +SPECIAL THANKS |fuf-thanks| +CHANGELOG |fuf-changelog| +ABOUT |fuf-about| + +============================================================================== +INTRODUCTION *fuf-introduction* + +FuzzyFinder provides convenient ways to quickly reach the +buffer/file/command/bookmark/tag you want. FuzzyFinder searches with the +fuzzy/partial pattern to which it converted an entered pattern. + + Entered pattern Fuzzy pattern Partial pattern ~ +> + abc *a*b*c* *abc* + dir/file dir/*f*i*l*e* dir/*file* + d*r/file d*r/*f*i*l*e* d*r/*file* + ../**/s ../**/*s* ../**/*s* + (** allows searching a directory tree.) +< +You will be happy when: + + "./AhLongLongLongLongLongFile.txt" + "./AhLongLongLongLongLongName.txt" + "./OhLongLongLongLongLongFile.txt" + "./OhLongLongLongLongLongName.txt" <- you want :O + +Type "ON" and "OhLongLongLongLongLongName.txt" will be select. :D + +FuzzyFinder can search: + + - buffers + - files + - directories + - most recently used files + - most recently used command-lines + - bookmarks + - tags + - files which are included in current tagfiles + - jump list + - change list + - buffer lines + - quickfix + - help + +FuzzyFinder also provides APIs to use its system of searching files or +selecting items. + +FuzzyFinder supports multibyte characters. + + +============================================================================== +INSTALLATION *fuf-installation* + +Put all files into your runtime directory. If you have the zip file, extract +it to your runtime directory. + +You should place the files as follows: +> + /plugin/fuf.vim + /autoload/fuf.vim + /autoload/fuf/buffer.vim + ... +< +If you disgust to jumble up this plugin and other plugins in your runtime +directory, put the files into new directory and just add the directory path to +'runtimepath'. It's easy to uninstall the plugin. + +And then update your help tags files to enable fuzzyfinder help. See +|add-local-help| for details. + +============================================================================== +USAGE *fuf-usage* + +You can launch FuzzyFinder by following commands: + + Command Mode ~ + |:FufBuffer| - Buffer mode (|fuf-buffer-mode|) + |:FufFile| - File mode (|fuf-file-mode|) + |:FufDir| - Directory mode (|fuf-dir-mode|) + |:FufMruFile| - MRU-File mode (|fuf-mrufile-mode|) + |:FufMruCmd| - MRU-Command mode (|fuf-mrucmd-mode|) + |:FufBookmark| - Bookmark mode (|fuf-bookmark-mode|) + |:FufTag| - Tag mode (|fuf-tag-mode|) + |:FufTaggedFile| - Tagged-File mode (|fuf-taggedfile-mode|) + |:FufJumpList| - Jump-List mode (|fuf-jumplist-mode|) + |:FufChangeList| - Change-List mode (|fuf-changelist-mode|) + |:FufQuickfix| - Quickfix mode (|fuf-quickfix-mode|) + |:FufLine| - Line mode (|fuf-line-mode|) + |:FufHelp| - Help mode (|fuf-help-mode|) + +It is recommended to map these commands. + +These commands open 1-line buffer to enter search pattern and start insert +mode. + +FuzzyFinder searchs for matching items with an entered pattern and shows them +in a completion menu. For more details on pattern matching, see +|fuf-search-patterns|. + +If there are a lot of matching items, FuzzyFinder limits the number of +enumerating items (|g:fuf_enumeratingLimit|) to speed up a response time, and +highlights the pattern with "Error" group. + +The first item in the completion menu will be selected automatically. + +with (|g:fuf_keyPrevPattern|) and (|g:fuf_keyNextPattern|), You +can recall patterns which have been entered before from history. + +You can open a selected item in various ways: + + (|g:fuf_keyOpen|) - opens in a previous window. + (|g:fuf_keyOpenSplit|) - opens in a split window. + (|g:fuf_keyOpenVsplit|) - opens in a vertical-split window. + (|g:fuf_keyOpenTabpage|) - opens in a new tab page. + +To cancel and return to previous window, just leave Insert mode. + +With (|g:fuf_keySwitchMatching|), You can switch search method +between fuzzy matching and partial matching. + +With (|g:fuf_keyNextMode|) and (|g:fuf_keyPrevMode|), You can +switch current mode without leaving Insert mode . + +You can preview selected item with (|g:fuf_keyPreview|) in some modes. +Repeating the key on the same item might show another information. The height +of command-line area is changed to |g:fuf_previewHeight| when you launch a +mode supporting preview. + + +============================================================================== +MODES *fuf-modes* + + *fuf-buffer-mode* +Buffer mode ~ + +This mode provides an interface to select a buffer from a list of existing +buffers and open it. + + *fuf-file-mode* +File mode ~ + +This mode provides an interface to search a file and open it. + + *fuf-dir-mode* +Directory mode ~ + +This mode provides an interface to search a directory and change the current +directory. + + *fuf-mrufile-mode* +MRU-File mode ~ + +This mode provides an interface to select a file from most recently used files +and open it. + +This mode is set to disable in |g:fuf_modesDisable| by default because +processes for this mode in |BufEnter| and |BufWritePost| could cause +Performance issue. + + *fuf-mrucmd-mode* +MRU-Command mode ~ + +This mode provides an interface to select a command from most recently used +commands and execute it. + +This mode is set to disable in |g:fuf_modesDisable| by default because mapping + of Command-line mode required by this mode has side effects. + + *fuf-bookmark-mode* +Bookmark mode ~ + +This mode provides an interface to select one of the bookmarks you have added +beforehand and jump there. + +You can add a cursor line to bookmarks by |:FufAddBookmark| command. +Execute that command and you will be prompted to enter a bookmark name. + +FuzzyFinder adjusts a line number for jump. If a line of bookmarked position +does not match to a pattern when the bookmark was added, FuzzyFinder searches +a matching line around bookmarked position. So you can jump to a bookmarked +line even if the line is out of bookmarked position. If you want to jump to +bookmarked line number without the adjustment, set +|g:fuf_bookmark_searchRange| option to 0. + +Press (|g:fuf_bookmark_keyDelete|) in Bookmark mode and selected +bookmark will be deleted. + + *fuf-tag-mode* +Tag mode ~ + +This mode provides an interface to select a tag and jump to the definition of +it. + +Following mapping is the replacement for : +> + noremap :FufTagWithCursorWord! +< + + *fuf-taggedfile-mode* +Tagged-File mode ~ + +This mode provides an interface to select one of the files which are included +in current tagfiles and open it. + + *fuf-jumplist-mode* +Jump-List mode ~ + +This mode provides an interface to select one from the |jumplist| of the +current window and jump there. + + *fuf-changelist-mode* +Change-List mode ~ + +This mode provides an interface to select one from the |changelist| of the +current buffer and jump there. + + *fuf-quickfix-mode* +Quickfix mode ~ + +This mode provides an interface to select one from the |quickfix| list and +jump there. + + *fuf-line-mode* +Line mode ~ + +This mode provides an interface to select a line from current buffer and jump +there. + + *fuf-help-mode* +Help mode ~ + +This mode provides an interface to select a help tag and jump to the help +page. + + *fuf-givenfile-mode* +Given-File mode ~ + +This mode provides an API to open a selected file from a given list. + +API function: +> + function fuf#givenfile#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - String which is inserted after launching + FuzzyFinder. + partialMatching - If non-zero, enable partial matching instead of + fuzzy matching. + prompt - Prompt string + items - List of items. + +Example of use: +> + " Open one of your dotfiles. + call fuf#givenfile#launch('', 0, '>', split(glob('~/.*'), "\n")) +< + + *fuf-givendir-mode* +Given-Directory mode ~ + +This mode provides an API to change current working directory to a selected +one from a given list. + +API function: +> + function fuf#givendir#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - String which is inserted after launching + FuzzyFinder. + partialMatching - If non-zero, enable partial matching instead of + fuzzy matching. + prompt - Prompt string + items - List of items. + + +Example of use: +> + " Change current working directory to one of your runtime directory. + call fuf#givendir#launch('', 0, '>', split(&runtimepath, ',')) +< + + *fuf-givencmd-mode* +Given-Command mode ~ + +This mode provides an API to execute a selected command from a given list. + +A selected command is executed by |feedkeys()|, so it is able to emulate a +series of key input in Normal mode. + +API function: +> + function fuf#givencmd#launch( + \ initialPattern, partialMatching, prompt, items) +< + initialPattern - String which is inserted after launching + FuzzyFinder. + partialMatching - If non-zero, enable partial matching instead of + fuzzy matching. + prompt - Prompt string + items - List of items. + + +Example of use: +> + function GetAllCommands() + redir => commands + silent command + redir END + return map((split(commands, "\n")[3:]), + \ '":" . matchstr(v:val, ''^....\zs\S*'')') + endfunction + + " execute one of the user-defined commands + call fuf#givencmd#launch('', 0, '>', GetAllCommands()) + +< + + *fuf-callbackfile-mode* +Callback-File mode ~ + +This mode provides an API to find and get a file path which is selected by an +user. + +API function: +> + function fuf#callbackfile#launch( + \ initialPattern, partialMatching, prompt, exclude, listener) +< + initialPattern - String which is inserted after launching + FuzzyFinder. + partialMatching - If non-zero, enable partial matching instead of + fuzzy matching. + prompt - Prompt string. + exclude - Regexp pattern for items which you want to exclude + from completion list. + listener - |Dictionary| which has 'onComplete' and 'onAbort'. + They are called at the end of FuzzyFinder. + listener.onComplete(item, method) is called with 2 + arguments which are a name of selected item and a + number of open method when completed. + listener.onAbort() is called when aborted. + +Example of use: +> + let listener = {} + + function listener.onComplete(item, method) + echo "Item: " . a:item . "\nMethod: " . a:method + endfunction + + function listener.onAbort() + echo "Abort" + endfunction + + " Find a file from current working directory. + call fuf#callbackfile#launch('', 0, '>', '', listener) + + " Find a file from home directory. + call fuf#callbackfile#launch('~/', 0, '>', '', listener) +< + + *fuf-callbackitem-mode* +Callback-Item mode ~ + +This mode provides an API to get an item which is selected from a given list +by an user. + +API function: +> + function fuf#callbackitem#launch( + \ initialPattern, partialMatching, prompt, listener, items, forPath) +< + initialPattern - String which is inserted after launching + FuzzyFinder. + partialMatching - If non-zero, enable partial matching instead of + fuzzy matching. + prompt - Prompt string + listener - |Dictionary| which has 'onComplete' and 'onAbort'. + They are called at the end of FuzzyFinder. + listener.onComplete(item, method) is called with 2 + arguments which are a name of selected item and a + number of open method when completed. + listener.onAbort() is called when aborted. + items - List of items. + forPath - If non-zero, use a matching method for files. + +Example of use: +> + let listener = {} + + function listener.onComplete(item, method) + echo "Item: " . a:item . "\nMethod: " . a:method + endfunction + + function listener.onAbort() + echo "Abort" + endfunction + + " Select an item from a given list. + call fuf#callbackitem#launch('', 0, '>', listener, ['ed', 'vi', 'vim'], 0) + + " Select a file from a given list. + call fuf#callbackitem#launch('', 0, '>', listener, ['../foo/bar', 'baz'], 1) +< + +============================================================================== +DETAILED TOPICS *fuf-detailed-topics* + + *fuf-search-patterns* +Search Patterns ~ + +You can enter one primary pattern and zero or more refining patterns as search +patterns. An entered pattern is separated by ";" (|g:fuf_patternSeparator|), +and the first pattern is a primary pattern and the rest of patterns is a +refining pattern. +> + primary refining refining + |----------| |-------| |----| + >MruFile>bookmark.vim;autoload/;/home/ +< +A refining pattern is used to narrow down the list of matching items by +another pattern. + +With a primary pattern, FuzzyFinder does fuzzy matching or partial matching, +which you specified. With a refining pattern, FuzzyFinder always does partial +matching. + +When you enter a number as refining pattern, it also can match the index of +each item. + +In a mode which targets a static set of file paths (such as Buffer or MRU-File +mode, not File or Directory) and |g:fuf_splitPathMatching| is non-zero, +matching with a primary pattern is divided into head part and tail part and +done individually. +> + head tail + |------||-----| + foo/bar/baz.vim + + fuzzy matching example: + +----------------+---------+---------+---------+ + | item \ pattern | foo/bar | foo/ | bar | + +----------------+---------+---------+---------+ + | foo/bar | match | match | match | + | foo/abc | unmatch | match | unmatch | + | abc/bar | unmatch | unmatch | match | + | foobar | unmatch | unmatch | match | + | foooo/barrrr | match | match | match | + | foooo/fooooo | unmatch | match | unmatch | + +----------------+---------+---------+---------+ +< +refining pattern can match anywhere on each path in the above case. + + *fuf-sorting-of-completion-items* +Sorting Of Completion Items ~ + +FuzzyFinder sorts completion items with some rules. + +An item, one part of which is matched with a whole pattern, is placed upper. +E.g., with the pattern "bc", the item "abc" is placed upper than "bac". + +In the above case, items, each having matching part at the head of itself, are +placed upper than others. E.g., with the pattern "foo", the item "foobar" is +placed upper than "foobarbaz". + +And the shorter the length of the item after matching position puts it higher. +E.g., with the pattern "bar", the item "foobar" is placed upper than +"foobarbaz". + +If a pattern matches an item at only word boundaries of it, the item is placed +upper. E.g., with a pattern "fb", items such as "fooBarBaz" and "foo_bar_baz" +is placed upper. + +Plus, FuzzyFinder has a learning system. An item which has been completed in +the past with current pattern is placed upper. + + *fuf-reusing-window* +Reusing Of A Window Containing Target Buffer/File ~ + +If a window containing target buffer is found in current tab page when +FuzzyFinder is going to open the buffer in a split new window, move to it. If +a window containing target buffer is found in other tab page when FuzzyFinder +is going to open the buffer in a new tab page, move to it. + +You can disable that feature via 'reuse_window' options if always want to open +a buffer in a new window. + + *fuf-hiding-menu* +To Hide The Completion Menu Temporarily In FuzzyFinder ~ + +You can close it by and reopen it by . + + *fuf-abbreviation* *fuf-multiple-search* +Abbreviations And Multiple Search ~ + +You can use abbreviations and multiple search in all modes by setting +|g:fuf_abbrevMap| option. + +For example, set as below: +> + let g:fuf_abbrevMap = { + \ "^doc:" : [ + \ "~/project/**/doc/", + \ ".vim/doc/", + \ ], + \ } +< +and enter "doc:txt" in File mode, then FuzzyFinder searches by following +patterns: + + "~/project/**/doc/*t*x*t*" + ".vim/doc/*t*x*t*" + +and show concatenated search results. + + *fuf-information-file* +Information File ~ + +FuzzyFinder writes completion statistics, MRU data, bookmark, etc to +|g:fuf_infoFile|. + +|:FufEditInfo| command is helpful in editing your information file. +This command reads the information file in new unnamed buffer. Write the +buffer and the information file will be updated. + + *fuf-cache* +Cache ~ + +Once a cache was created, It is not automatically updated to speed up the +response time by default. To update it, use |:FufRenewCache| command. + + *fuf-dot-sequence* +Going Up Parent Directories With Dot Sequence ~ + +You can go up parent directories with entering dot sequence. Dot sequence +after a path separator is expanded to "../" sequence. + + Dot sequence Expanded pattern ~ + /.. /../ + /... /../../ + /.... /../../../ + + *fuf-migemo* +What Is Migemo ~ + +Migemo is a search method for Japanese language. + + +============================================================================== +COMMANDS *fuf-commands* + +See also: |fuf-vimrc-example| + + *:FufBuffer* +:FufBuffer[!] [{pattern}] + Launchs Buffer mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufFile* +:FufFile[!] [{pattern}] + Launchs File mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufFileWithFullCwd* +:FufFileWithFullCwd[!] [{pattern}] + Is mostly the same as |:FufFile|, except that initial pattern is a + full path of current working directory. + + *:FufFileWithCurrentBufferDir* +:FufFileWithCurrentBufferDir[!] [{pattern}] + Is mostly the same as |:FufFile|, except that initial pattern is a + path of directory current buffer is in. + + *:FufDir* +:FufDir[!] [{pattern}] + Launchs Directory mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufDirWithFullCwd* +:FufDirWithFullCwd[!] [{pattern}] + Is mostly the same as |:FufDir|, except that initial pattern is a full + path of current working directory. + + *:FufDirWithCurrentBufferDir* +:FufDirWithCurrentBufferDir[!] [{pattern}] + Is mostly the same as |:FufDir|, except that initial pattern is a path + of directory current buffer is in. + + *:FufMruFile* +:FufMruFile[!] [{pattern}] + Launchs MRU-File mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufMruCmd* +:FufMruCmd[!] [{pattern}] + Launchs MRU-Command mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufBookmark* +:FufBookmark[!] [{pattern}] + Launchs Bookmark mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufTag* +:FufTag[!] [{pattern}] + Launchs Tag mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufTagWithCursorWord* +:FufTagWithCursorWord[!] [{pattern}] + Is mostly the same as |:FufTag|, except that + + *:FufTaggedFile* +:FufTaggedFile[!] [{pattern}] + Launchs Tagged-File mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufJumpList* +:FufJumpList[!] [{pattern}] + Launchs Jump-List mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufChangeList* +:FufChangeList[!] [{pattern}] + Launchs Change-List mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufQuickfix* +:FufQuickfix[!] [{pattern}] + Launchs Quickfix mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufLine* +:FufLine[!] [{pattern}] + Launchs Line mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufHelp* +:FufHelp[!] [{pattern}] + Launchs Help mode. + + If a command was executed with a ! modifier, it does partial matching + instead of fuzzy matching. + + {pattern} will be inserted after launching FuzzyFinder. + + *:FufEditInfo* +:FufEditInfo + Opens a buffer for editing your information file. See + |fuf-information-file| for details. + + *:FufAddBookmark* +:FufAddBookmark [{name}] + Adds a cursor line to bookmarks. See |fuf-adding-bookmark| for + details. + + *:FufAddBookmarkAsSelectedText* +:FufAddBookmarkAsSelectedText + Is mostly the same as |:FufAddBookmark|, except that initial pattern + is last selected one. + + *:FufRenewCache* +:FufRenewCache + Removes caches to renew completion items. See |fuf-cache| for details. + + +============================================================================== +OPTIONS *fuf-options* + + *fuf-options-for-all-modes* +For All Modes ~ + + *g:fuf_modesDisable* > + let g:fuf_modesDisable = [ 'mrufile', 'mrucmd', ] +< + List of mode names to disable. + + Modes which are listed will never be initialized and never handle any + event. + + *g:fuf_keyOpen* > + let g:fuf_keyOpen = '' +< + Key mapped to select completion item or finish input and open a + buffer/file in previous window. + + *g:fuf_keyOpenSplit* > + let g:fuf_keyOpenSplit = '' +< + Key mapped to select completion item or finish input and open a + buffer/file in split new window + + *g:fuf_keyOpenVsplit* > + let g:fuf_keyOpenVsplit = '' +< + Key mapped to select completion item or finish input and open a + buffer/file in vertical-split new window. + + *g:fuf_keyOpenTabpage* > + let g:fuf_keyOpenTabpage = '' +< + + Key mapped to select completion item or finish input and open a + buffer/file in a new tab page. + + *g:fuf_keyPreview* > + let g:fuf_keyPreview = '' +< + + Key mapped to show information of selected completion item on + command-line area. This key makes sense only in modes supporting + preview. + + *g:fuf_keyNextMode* > + let g:fuf_keyNextMode = '' +< + Key mapped to switch to next mode. + + *g:fuf_keyPrevMode* > + let g:fuf_keyPrevMode = '' +< + Key mapped to switch to previous mode. + + *g:fuf_keyPrevPattern* > + let g:fuf_keyPrevPattern = '' +< + Key mapped to recall previous entered patten from history. + + *g:fuf_keyNextPattern* > + let g:fuf_keyNextPattern = '' +< + Key mapped to recall next entered patten from history. + + *g:fuf_keySwitchMatching* > + let g:fuf_keySwitchMatching = '' +< + Key mapped to switch between fuzzy matching and partial matching. + + *g:fuf_infoFile* > + let g:fuf_infoFile = '~/.vim-fuf' +< + Filename to write completion statistics, MRU data, bookmark, etc. If + empty string, FuzzyFinder does not write to a file. + + *g:fuf_abbrevMap* > + let g:fuf_abbrevMap = {} +< + |Dictionary|. Each value must be a |List|. All matchs of a + key in entered text is expanded with the value. + + *g:fuf_patternSeparator* > + let g:fuf_patternSeparator = ';' +< + String which sparates a input pattern into a primary pattern and + refining patterns. + + *g:fuf_promptHighlight* > + let g:fuf_promptHighlight = 'Question' +< + a highlight group name for a prompt string. + + *g:fuf_ignoreCase* > + let g:fuf_ignoreCase = 1 +< + If non-zero, FuzzyFinder ignores case in search patterns. + + *g:fuf_splitPathMatching* > + let g:fuf_splitPathMatching = 1 +< + If non-zero, matching with a primary pattern is divided into head part + and tail part and done individually. + + See also: |fuf-search-patterns| + + *g:fuf_smartBs* > + let g:fuf_smartBs = 1 +< + If non-zero, pressing after a path separator deletes one + directory name and pressing after |g:fuf_patternSeparator| + deletes one pattern. + + *g:fuf_reuseWindow* > + let g:fuf_reuseWindow = 1 +< + If non-zero and when FuzzyFinder opens a buffer which has already been + opened, it reuses a window containing the target buffer. + + *g:fuf_timeFormat* > + let g:fuf_timeFormat = '(%Y-%m-%d %H:%M:%S)' +< + String to format time string. See |strftime()| for details. + + *g:fuf_learningLimit* > + let g:fuf_learningLimit = 100 +< + Ceiling for the number of completion statistics to be stored. + + *g:fuf_enumeratingLimit* > + let g:fuf_enumeratingLimit = 50 +< + To speed up the response time, FuzzyFinder ends enumerating completion + items when found over this. + + *g:fuf_maxMenuWidth* > + let g:fuf_maxMenuWidth = 78 +< + If a length of a completion item is more than this, it is snipped in + completion menu. + + *g:fuf_previewHeight* > + let g:fuf_previewHeight = 5 +< + 'cmdheight' is set to this when a mode supporting preview is launched. + Information of selected completion item will be shown on command-line + area. If zero, preview feature is disabled. + + *g:fuf_useMigemo* > + let g:fuf_useMigemo = 0 +< + If non-zero, FuzzyFinder uses Migemo. + + *fuf-options-for-buffer-mode* +For Buffer Mode ~ + + *g:fuf_buffer_prompt* > + let g:fuf_buffer_prompt = '>Buffer[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_buffer_switchOrder* > + let g:fuf_buffer_switchOrder = 10 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_buffer_mruOrder* > + let g:fuf_buffer_mruOrder = 1 +< + If non-zero, completion items is sorted in order of recently used. + + *fuf-options-for-file-mode* +For File Mode ~ + + *g:fuf_file_prompt* > + let g:fuf_file_prompt = '>File[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_file_switchOrder* > + let g:fuf_file_switchOrder = 20 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_file_exclude* > + let g:fuf_file_exclude = '\v\~$|\.(o|exe|dll|bak|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])' +< + Regexp pattern for items which you want to exclude from completion + list. + + *fuf-options-for-dir-mode* +For Directory Mode ~ + + *g:fuf_dir_prompt* > + let g:fuf_dir_prompt = '>Dir[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_dir_switchOrder* > + let g:fuf_dir_switchOrder = 30 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_dir_exclude* > + let g:fuf_dir_exclude = '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])' +< + Regexp pattern for items which you want to exclude from completion + list. + + *fuf-options-for-mrufile-mode* +For Mru-File Mode ~ + + *g:fuf_mrufile_prompt* > + let g:fuf_mrufile_prompt = '>Mru-File[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_mrufile_switchOrder* > + let g:fuf_mrufile_switchOrder = 40 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_mrufile_exclude* > + let g:fuf_mrufile_exclude = '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)' +< + Regexp pattern for items which you want to exclude from completion + list. + + *g:fuf_mrufile_maxItem* > + let g:fuf_mrufile_maxItem = 200 +< + Ceiling for the number of MRU items to be stored. + + *fuf-options-for-mrucmd-mode* +For Mru-Cmd Mode ~ + + *g:fuf_mrucmd_prompt* > + let g:fuf_mrucmd_prompt = '>Mru-Cmd[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_mrucmd_switchOrder* > + let g:fuf_mrucmd_switchOrder = 50 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_mrucmd_exclude* > + let g:fuf_mrucmd_exclude = '^$' +< + Regexp pattern for items which you want to exclude from completion + list. + + *g:fuf_mrucmd_maxItem* > + let g:fuf_mrucmd_maxItem = 200 +< + This is the ceiling for the number of MRU items to be stored. + + *fuf-options-for-Bookmark-mode* +For Bookmark Mode ~ + + *g:fuf_bookmark_prompt* > + let g:fuf_bookmark_prompt = '>Bookmark[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_bookmark_switchOrder* > + let g:fuf_bookmark_switchOrder = 60 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_bookmark_searchRange* > + let g:fuf_bookmark_searchRange = 400 +< + Number of lines which FuzzyFinder searches a matching line from + bookmarked position within. + + *g:fuf_bookmark_keyDelete* > + let g:fuf_bookmark_keyDelete = '' +< + Key mapped to delete selected bookmark. + + *fuf-options-for-tag-mode* +For Tag Mode ~ + + *g:fuf_tag_prompt* > + let g:fuf_tag_prompt = '>Tag[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_tag_switchOrder* > + let g:fuf_tag_switchOrder = 70 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_tag_cache_dir* > + let g:fuf_tag_cache_dir = '~/.vim-fuf-cache/tag' +< + Cache files are created in this directory. If empty, they are not + created. + + *fuf-options-for-taggedfile-mode* +For Tagged-File Mode ~ + + *g:fuf_taggedfile_prompt* > + let g:fuf_taggedfile_prompt = '>Tagged-File[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_taggedfile_switchOrder* > + let g:fuf_taggedfile_switchOrder = 80 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_taggedfile_cache_dir* > + let g:fuf_taggedfile_cache_dir = '~/.vim-fuf-cache/taggedfile' +< + Cache files are created in this directory. If empty, they are not + created. + + *fuf-options-for-jumplist-mode* +For Jump-List Mode ~ + + *g:fuf_jumplist_prompt* > + let g:fuf_jumplist_prompt = '>Jump-List[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_jumplist_switchOrder* > + let g:fuf_jumplist_switchOrder = 90 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *fuf-options-for-changelist-mode* +For Change-List Mode ~ + + *g:fuf_changelist_prompt* > + let g:fuf_changelist_prompt = '>Change-List[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_changelist_switchOrder* > + let g:fuf_changelist_switchOrder = 100 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *fuf-options-for-quickfix-mode* +For Quickfix Mode ~ + + *g:fuf_quickfix_prompt* > + let g:fuf_quickfix_prompt = '>Quickfix[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_quickfix_switchOrder* > + let g:fuf_quickfix_switchOrder = 110 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *fuf-options-for-line-mode* +For Line Mode ~ + + *g:fuf_line_prompt* > + let g:fuf_line_prompt = '>Line[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_line_switchOrder* > + let g:fuf_line_switchOrder = 120 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *fuf-options-for-help-mode* +For Help Mode ~ + + *g:fuf_help_prompt* > + let g:fuf_help_prompt = '>Help[]>' +< + Prompt string. "[]" will be substituted with indicators. + + *g:fuf_help_switchOrder* > + let g:fuf_help_switchOrder = 130 +< + Number of order for switching to the next/previous mode. If negative + number, Fuzzyfinder never switches to this mode. + + *g:fuf_help_cache_dir* > + let g:fuf_help_cache_dir = '~/.vim-fuf-cache/help' +< + Cache files are created in this directory. If empty, they are not + created. + + +============================================================================== +VIMRC EXAMPLE *fuf-vimrc-example* + +> + let g:fuf_modesDisable = [] + let g:fuf_abbrevMap = { + \ '^vr:' : map(filter(split(&runtimepath, ','), 'v:val !~ "after$"'), 'v:val . ''/**/'''), + \ '^m0:' : [ '/mnt/d/0/', '/mnt/j/0/' ], + \ } + let g:fuf_mrufile_maxItem = 300 + let g:fuf_mrucmd_maxItem = 400 + nnoremap :FufBuffer + nnoremap :FufFileWithCurrentBufferDir + nnoremap :FufFileWithFullCwd + nnoremap p :FufFile + nnoremap :FufDirWithCurrentBufferDir + nnoremap d :FufDirWithFullCwd + nnoremap D :FufDir + nnoremap :FufMruFile + nnoremap :FufMruCmd + nnoremap :FufBookmark + nnoremap :FufTag + nnoremap t :FufTag! + noremap g] :FufTagWithCursorWord! + nnoremap :FufTaggedFile + nnoremap :FufJumpList + nnoremap :FufChangeList + nnoremap :FufQuickfix + nnoremap :FufLine + nnoremap :FufHelp + nnoremap :FufAddBookmark + vnoremap :FufAddBookmarkAsSelectedText + nnoremap :FufEditInfo + nnoremap :FufRenewCache +< + +============================================================================== +SPECIAL THANKS *fuf-thanks* + +- Vincent Wang +- Ingo Karkat +- Nikolay Golubev +- Brian Doyle +- id:secondlife +- Nathan Neff + + +============================================================================== +CHANGELOG *fuf-changelog* + +3.5: + - Added Line mode. + - Added Help mode. + - Added key mapping to switch between fuzzy matching and partial matching. + - Changed the default values of g:fuf_file_exclude for ignoring "*.dll". + - Changed Tag mode and Tagged-File mode to cache parsed data to files in + "~/.vim-fuf-cache/". + - Fixed a bug that repeating preview key produced no effect. + - Fixed a bug that File mode and Directory mode didn't list items in a + directory whose name includes uppercase characters. (Thanks, ryo7000) + +3.4: + - Added new feature which makes it possible to preview selected completion + item. + - Changed matching rules and added g:fuf_splitPathMatching. + - Changed sorting rules. + - Changed the default values of g:fuf_file_exclude and g:fuf_dir_exclude in + order to ignore ".hg", ".git", and ".bzr" directories. + - Changed the default value of g:fuf_mrufile_exclude in order to ignore + network files (\\*) on Windows and ignore /mnt/* and /media/* on Unix like + systems. + - Fixed a bug that an exclude pattern of File, Dir, and Callback-File mode + can't be changed. + +3.3: + - Added Jump-List mode, Change-List mode, and Quickfix mode which enable + jumps with jump list, change list, and quickfix list. + - Added new feature which deletes selected bookmark with FuzzyFinder and + g:fuf_bookmark_keyDelete option. + - Changed default values of g:fuf_keyPrevPattern. + - Changed to show error message when incompatible with a installed vim. + +3.2: + - Added g:fuf_promptHighlight option to integrate such options for each + mode. + - Changed APIs of Given-File, Given-Directory, Given-Command, Callback-File, + and Callback-Item modes to be able to set a prompt string. + - Changed default values of g:fuf_keyPrevPattern and g:fuf_keyNextPattern. + - Fixed a bug that MRU-File data was not updated When a file was opened with + FuzzyFinder. + - Fixed a bug with scoring matchings for sorting. Thanks to Vincent. + - Brought back the removed feature which is switching to an other mode in + FuzzyFinder. + +3.1: + - Added new feature to recall patterns which have been entered before from + history. + +3.0: + - Redesigned the whole plugin for improvements of maintainability and + performance. "fuzzyfinder" is abbreviated to "fuf" in the sorce code and + filenames. All commands and options are renamed. + - Added new feature which is refining pattern. + - Improved the rules for sorting completion items. Thanks to the suggestion + by Nathan, the rule for boundary matching was implemented. + - Changed to open one line buffer of FuzzyFinder with :topleft command + instead of :leftabove. The window will alway appear at the top and occupy + the full with of the vim window. Thanks to Jan Christoph. + - Changed default filename of information file. + - Changed MRU-File mode and MRU-Command mode to be disabled by default + due to performance and side effect issues. + - Removed the feature which is switching to an other mode in FuzzyFinder. + - Removed the feature which is temporarily switching 'ignorecase' in + FuzzyFinder. + +2.22.3: + - Fixed a bug that Fuzzyfinder could not open files with '$' in the name on + Windows. + +2.22.2: + - Changed to consider a length of a date/time string when abbreviates long + completion items. + - Fixed a bug that '**/' pattern did not search for files directly under the + current working directory in File mode. Thanks to Martin for reporting. + +2.22.1: + - Fixed a bug that Fuzzyfinder could not expand abbreviations to patterns + including '\' correctly. + - Fixed to show item number in Given-File, Given-Directory, and + Given-Command mode. + +2.22.0: + - More improved the abbreviation method for long completion items. + - Added Given-File mode for third-party script to select a file from a given + list and open. + - Added Given-Directory mode for third-party script to select a directory + from a given list and change current working directory to it. + - Added Given-Command mode for third-party script to select a command from a + given list and execute. + - Changed ways to launch Callback-File mode and Callback-item mode. + +2.21.0: + - Improved a method of trimming long completion items. Thanks to Andy, + pyrhockz, and Nathan. + - Changed not to map command-line for MRU-Command mode if + g:FuzzyFinderOptions.MruCmd.mode_available is set 0 before loading + fuzzyfinder.vim. + - Added Callback-File mode and Callback-Item mode for third-party script to + find a file/directory or an item from a given list using Fuzzyfinder. + - Changed not to append ".." to a completion menu in File/Directory mode. + Use dot sequence feature. + - Changed default value of g:FuzzyFinderOptions.File.excluded_path option. + - Changed default value of g:FuzzyFinderOptions.Dir.excluded_path option. + - Fixed a bug that couldn't jump to a tag. Thanks to Thinca. + +2.20: + - Added help files which are doc/fuzzyfinder.txt and doc/fuzzyfinder.jax. + - Fixed a bug that an error occurs if current directory included spaces. + Thanks id:cho45 and id:secondlife. + - Implemented a feature to reuse a window containing target buffer. + - Added g:FuzzyFinderOptions.Buffer.reuse_window option. + - Added g:FuzzyFinderOptions.File.reuse_window option. + - Added g:FuzzyFinderOptions.MruFile.reuse_window option. + - Added g:FuzzyFinderOptions.Bookmark.reuse_window option. + - Added g:FuzzyFinderOptions.TaggedFile.reuse_window option. + - Changed to use 'omnifunc' instead of 'completefunc'. Now you can use + to delete all entered characters. + - Changed default value of g:FuzzyFinderOptions.Base.key_open_tab option. + - Changed default value of g:FuzzyFinderOptions.Base.key_next_mode option. + - Changed default value of g:FuzzyFinderOptions.Base.key_prev_mode option. + - Changed default value of g:FuzzyFinderOptions.Base.key_ignore_case option. + - Changed to truncate long completion items from the head instead of tail. + - Added g:FuzzyFinderOptions.Base.max_menu_width option instead of + g:FuzzyFinderOptions.Base.trim_length option. + - Added :FuzzyFinderFileWithFullCwd command. + - Added :FuzzyFinderFileWithCurrentBufferDir command. + - Added :FuzzyFinderDirWithFullCwd command. + - Added :FuzzyFinderDirWithCurrentBufferDir command. + - Added :FuzzyFinderTagWithCursorWord command. + - Renamed :FuzzyFinderRemoveCache command to :FuzzyFinderRenewCache. + +2.19: + - Changed MRU-File mode that always formats completion items to be relative + to the home directory. + - Fixed a bug that a file was opened in an unintended window with Tag List + plugin. Thanks Alexey. + - Fixed a bug that garbage characters were entered when switched current + mode. Thanks id:lugecy. + +2.18: + - Improved rules for the sorting of completion items. + - Changed not to learn a completion if an entered pattern is empty. + - Fixed a bug that Buffer mode did not work. Thanks ryo7000. + +2.17: + - Introduced a learning system for the sorting of completion items. + - Added g:FuzzyFinderOptions.Base.learning_limit option. + - Changed the specification of the information file. Please remove your + information file for Fuzzyfinder. + +2.16: + - Improved response time by caching in MRU-File mode. + - Fixed a bug in Bookmark mode that Fuzzyfinder did not jump to the + Bookmarked line number when Bookmarked pattern was not found. + +2.15: + - Added Bookmark mode. + - Removed Favorite-file mode. Use Bookmark mode instead. + - Fixed not to record a entry of input() in MRU-Command mode. + +2.14: + - Changed to show buffer status in Buffer mode. + - Fixed a bug that an error occurs when nonexistent buffer-name was entered + in Buffer mode. Thanks Maxim Kim. + - Added 'enumerating_limit' option. Thanks id:secondlife. + - Removed 'matching_limit' option. Use 'enumerating_limit' instead. + +2.13: + - Fixed a bug that a directory disappeared when a file in that directory was + being opened in File/Mru-File mode. + +2.12: + - Changed to be able to show completion items in the order of recently used + in Buffer mode. + - Added g:FuzzyFinderOptions.Buffer.mru_order option. + +2.11: + - Changed that a dot sequence of entered pattern is expanded to parent + directories in File/Dir mode. + E.g.: "foo/...bar" -> "foo/../../bar" + - Fixed a bug that a prompt string was excessively inserted. + +2.10: + - Changed not to show a current buffer in a completion menu. + - Fixed a bug that a filename to open was not been escaped. + - Added 'prompt' option. + - Added 'prompt_highlight' option. + - Removed g:FuzzyFinderOptions.MruFile.no_special_buffer option. + +2.9: + - Enhanced behavior in Fuzzyfinder and added 'smart_bs' option. + - Fixed a bug that entered pattern was not been escaped. + - Fixed not to insert "zv" with "c/pattern" command in Normal mode. + - Avoid the slow down problem caused by filereadable() check for the MRU + information in BufEnter/BufWritePost. + +2.8.1: + - Fixed a bug caused by the non-escaped buffer name "[Fuzzyfinder]". + - Fixed a command to open in a new tab page in Buffer mode. +2.8: + - Added 'trim_length' option. + - Added 'switch_order' option. + - Fixed a bug that entered command did not become the newest in the history. + - Fixed a bug that folds could not open with in a command-line when + searching. + - Removed 'excluded_indicator' option. Now a completion list in Buffer mode + is the same as a result of :buffers. + +2.7: + - Changed to find an item whose index is matched with the number suffixed + with entered pattern. + - Fixed the cache bug after changing current directory in File mode. + +2.6.2: + - Fixed not to miss changes in options when updates the MRU information. + +2.6.1: + - Fixed a bug related to floating-point support. + - Added support for GetLatestVimScripts. + +2.6: + - Revived MRU-command mode. The problem with a command-line abbreviation was + solved. + - Changed the specification of the information file. + - Added :FuzzyFinderEditInfo command. + +2.5.1: + - Fixed to be able to match "foo/./bar" by "foo/**/bar" in File mode. + - Fixed to be able to open a space-containing file in File mode. + - Fixed to honor the current working directory properly in File mode. + +2.5: + - Fixed the bug that a wrong initial text is entered after switching to a + next mode. + - Fixed the bug that it does not return to previous window after leaving + Fuzzyfinder one. + +2.4: + - Fixed the bug that Fuzzyfinder fails to open a file caused by auto-cd + plugin/script. + +2.3: + - Added a key mapping to open items in a new tab page and + g:FuzzyFinderOptions.Base.key_open_tab opton. + - Changed to show Fuzzyfinder window above last window even if 'splitbelow' + was set. + - Changed to set nocursorline and nocursorcolumn in Fuzzyfinder. + - Fixed not to push up a buffer number unlimitedly. + +2.2: + - Added new feature, which is the partial matching. + - Fixed the bug that an error occurs when "'" was entered. + +2.1: + - Restructured the option system AGAIN. Sorry :p + - Changed to inherit a typed text when switching a mode without leaving + Insert mode. + - Changed commands which launch explorers to be able to take a argument for + initial text. + - Changed to complete file names by relative path and not full path in the + buffer/mru-file/tagged-file mode. + - Changed to highlight a typed text when the completion item was not found + or the completion process was aborted. + - Changed to create caches for each tag file and not working directory in + the tag/tagged-file mode. + - Fixed the bug that the buffer mode couldn't open a unnamed buffer. + - Added 'matching_limit' option. + - Removed 'max_match' option. Use 'matching_limit' option instead. + - Removed 'initial_text' option. Use command argument instead. + - Removed the MRU-command mode. + +2.0: + - Added the tag mode. + - Added the tagged-file mode. + - Added :FuzzyFinderRemoveCache command. + - Restructured the option system. many options are changed names or default + values of some options. + - Changed to hold and reuse caches of completion lists by default. + - Changed to set filetype 'fuzzyfinder'. + - Disabled the MRU-command mode by default because there are problems. + - Removed FuzzyFinderAddMode command. + +1.5: + - Added the directory mode. + - Fixed the bug that it caused an error when switch a mode in Insert mode. + - Changed g:FuzzyFinder_KeySwitchMode type to a list. + +1.4: + - Changed the specification of the information file. + - Added the MRU-commands mode. + - Renamed :FuzzyFinderAddFavorite command to :FuzzyFinderAddFavFile. + - Renamed g:FuzzyFinder_MruModeVars option to g:FuzzyFinder_MruFileModeVars. + - Renamed g:FuzzyFinder_FavoriteModeVars option to + g:FuzzyFinder_FavFileModeVars. + - Changed to show registered time of each item in MRU/favorite mode. + - Added 'timeFormat' option for MRU/favorite modes. + +1.3: + - Fixed a handling of multi-byte characters. + +1.2: + - Added support for Migemo. (Migemo is Japanese search method.) + +1.1: + - Added the favorite mode. + - Added new features, which are abbreviations and multiple search. + - Added 'abbrevMap' option for each mode. + - Added g:FuzzyFinder_MruModeVars['ignoreSpecialBuffers'] option. + - Fixed the bug that it did not work correctly when a user have mapped + or . + +1.0: + - Added the MRU mode. + - Added commands to add and use original mode. + - Improved the sorting algorithm for completion items. + - Added 'initialInput' option to automatically insert a text at the + beginning of a mode. + - Changed that 'excludedPath' option works for the entire path. + - Renamed some options. + - Changed default values of some options. + - Packed the mode-specific options to dictionaries. + - Removed some options. + +0.6: + - Fixed some bugs. + +0.5: + - Improved response by aborting processing too many items. + - Changed to be able to open a buffer/file not only in previous window but + also in new window. + - Fixed a bug that recursive searching with '**' does not work. + - Added g:FuzzyFinder_CompletionItemLimit option. + - Added g:FuzzyFinder_KeyOpen option. + +0.4: + - Improved response of the input. + - Improved the sorting algorithm for completion items. It is based on the + matching level. 1st is perfect matching, 2nd is prefix matching, and 3rd + is fuzzy matching. + - Added g:FuzzyFinder_ExcludePattern option. + - Removed g:FuzzyFinder_WildIgnore option. + - Removed g:FuzzyFinder_EchoPattern option. + - Removed g:FuzzyFinder_PathSeparator option. + - Changed the default value of g:FuzzyFinder_MinLengthFile from 1 to 0. + +0.3: + - Added g:FuzzyFinder_IgnoreCase option. + - Added g:FuzzyFinder_KeyToggleIgnoreCase option. + - Added g:FuzzyFinder_EchoPattern option. + - Changed the open command in a buffer mode from ":edit" to ":buffer" to + avoid being reset cursor position. + - Changed the default value of g:FuzzyFinder_KeyToggleMode from to + because does not work on some CUI environments. + - Changed to avoid being loaded by Vim before 7.0. + - Fixed a bug with making a fuzzy pattern which has '\'. + +0.2: + - A bug it does not work on Linux is fixed. + +0.1: + - First release. + + +============================================================================== +ABOUT *fuf-about* *fuf-contact* *fuf-author* + +Author: Takeshi NISHIDA +Licence: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=1984 + http://bitbucket.org/ns9tks/vim-fuzzyfinder/ + +Bugs/Issues/Suggestions/Improvements ~ + +Please submit to http://bitbucket.org/ns9tks/vim-fuzzyfinder/issues/ . + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/mark.txt b/doc/mark.txt new file mode 100644 index 0000000..33656bd --- /dev/null +++ b/doc/mark.txt @@ -0,0 +1,251 @@ +*mark.txt* Highlight several words in different colors simultaneously. + + MARK by Ingo Karkat + (original version by Yuheng Xie) + *mark.vim* +description |mark-description| +usage |mark-usage| +installation |mark-installation| +configuration |mark-configuration| +integration |mark-integration| +limitations |mark-limitations| +known problems |mark-known-problems| +todo |mark-todo| +history |mark-history| + +============================================================================== +DESCRIPTION *mark-description* + +This script adds mappings and a :Mark command to highlight several words in +different colors simultaneously, similar to the built-in 'hlsearch' +highlighting of search results and the * |star| command. For example, when you +are browsing a big program file, you could highlight multiple identifiers in +parallel. This will make it easier to trace the source code. + +This is a continuation of vimscript #1238 by Yuheng Xie, who apparently +doesn't maintain his original version anymore and cannot be reached via the +email address in his profile. This script offers the following advantages over +the original: +- Much faster, all colored words can now be highlighted, no more clashes with + syntax highlighting (due to use of matchadd()). +- Many bug fixes. +- Jumps behave like the built-in search, including wrap and error messages. +- Like the built-in commands, jumps take an optional [count] to quickly skip + over some marks. + +RELATED WORKS * +- MultipleSearch (vimscript #479) can highlight in a single window and in all + buffers, but still relies on the :syntax highlighting method, which is + slower and less reliable. +- http://vim.wikia.com/wiki/Highlight_multiple_words offers control over the + color used by mapping the 1-9 keys on the numeric keypad, persistence, and + highlights only a single window. + +============================================================================== +USAGE *mark-usage* + +Highlighting: + +m Mark or unmark the word under the cursor, similar to + the |star| command. +{Visual}m Mark or unmark the visual selection. +r Manually input a regular expression to highlight. +{Visual}r (Based on the visual selection.) + In accordance with the built-in |star| command, + all these mappings use 'ignorecase', but not + 'smartcase'. +n Clear the mark under the cursor / all marks. + *:Mark* +:Mark {pattern} Mark or unmark {pattern}. + For implementation reasons, {pattern} cannot use the + 'smartcase' setting, only 'ignorecase'. +:Mark Clear all marks. + +Searching: + +[count]* [count]# +[count]* [count]# +[count]/ [count]? + Use these six keys to jump to the [count]'th next / + previous occurrence of a mark. + You could also use Vim's / and ? to search, since the + mark patterns are (optionally, see configuration) + added to the search history, too. + + Cursor over mark Cursor not over mark + --------------------------------------------------------------------------- + * Jump to the next occurrence of Jump to the next occurrence of + current mark, and remember it "last mark". + as "last mark". + + / Jump to the next occurrence of Same as left. + ANY mark. + + * If * is the most recently Do Vim's original * command. + used, do a *; otherwise + (/ is the most recently + used), do a /. + + Note: When the cursor is on a mark, the backwards + search does not jump to the beginning of the current + mark (like the built-in search), but to the previous + mark. The entire mark text is treated as one entity. + +============================================================================== +INSTALLATION *mark-installation* + +This script is packaged as a|vimball|. If you have the "gunzip" decompressor +in your PATH, simply edit the *.vba.gz package in Vim; otherwise, decompress +the archive first, e.g. using WinZip. Inside Vim, install by sourcing the +vimball or via the|:UseVimball|command. > + vim mark.vba.gz + :so % +To uninstall, use the|:RmVimball|command. + +DEPENDENCIES *mark-dependencies* + +- Requires Vim 7.1 with "matchadd()", or Vim 7.2 or higher. + +============================================================================== +CONFIGURATION *mark-configuration* + +You may define your own colors or more than the default 6 highlightings in +your vimrc file (or anywhere before this plugin is sourced), in the following +form (where N = 1..): > + highlight MarkWordN ctermbg=Cyan ctermfg=Black guibg=#8CCBEA guifg=Black +< +The search type highlighting (in the search message) can be changed via: > + highlight link SearchSpecialSearchType MoreMsg +< +By default, any marked words are also added to the search (/) and input (@) +history; if you don't want that, remove the corresponding symbols from: > + let g:mwHistAdd = "/@" +< +You can use different mappings by mapping to the Mark... mappings before +this plugin is sourced. To remove the default overriding of * and #, use: > + nmap IgnoreMarkSearchNext MarkSearchNext + nmap IgnoreMarkSearchPrev MarkSearchPrev +< +============================================================================== +INTEGRATION *mark-integration* + +============================================================================== +LIMITATIONS *mark-limitations* + +- If the 'ignorecase' setting is changed, there will be discrepancies between + the highlighted marks and subsequent jumps to marks. +- If {pattern} in a :Mark command contains atoms that change the semantics of + the entire (|/\c|, |/\C|) or following (|/\v|,|/\V|, |/\M|) regular + expression, there may be discrepancies between the highlighted marks and + subsequent jumps to marks. + +KNOWN PROBLEMS *mark-known-problems* + +TODO *mark-todo* + +IDEAS *mark-ideas* + +Taken from an alternative implementation at +http://vim.wikia.com/wiki/Highlight_multiple_words: +- Allow to specify the highlight group number via :Mark [n] {regexp} +- Use keys 1-9 on the numeric keypad to toggle a highlight group number. +- Persist the patterns in a uppercase global variable across Vim sessions. + +============================================================================== +HISTORY *mark-history* + +2.3.3 19-Feb-2010 +- BUG: Clearing of an accidental zero-width match (e.g. via :Mark \zs) results + in endless loop. Thanks to Andy Wokula for the patch. + +2.3.2 17-Nov-2009 +- BUG: Creation of literal pattern via '\V' in {Visual}m mapping + collided with individual escaping done in m mapping so that an + escaped '\*' would be interpreted as a multi item when both modes are used + for marking. Thanks to Andy Wokula for the patch. + +2.3.1 06-Jul-2009 +- Now working correctly when 'smartcase' is set. All mappings and the :Mark + command use 'ignorecase', but not 'smartcase'. + +2.3.0 04-Jul-2009 +- All jump commands now take an optional [count], so you can quickly skip over + some marks, as with the built-in */# and n/N commands. For this, the entire + core search algorithm has been rewritten. The script's logic has been + simplified through the use of Vim 7 features like Lists. +- Now also printing a Vim-alike search error message when 'nowrapscan' is set. + +2.2.0 02-Jul-2009 +- Split off functions into autoload script. +- Initialization of global variables and autocommands is now done lazily on + the first use, not during loading of the plugin. This reduces Vim startup + time and footprint as long as the functionality isn't yet used. +- Split off documentation into separate help file. Now packaging as VimBall. + + +2.1.0 06-Jun-2009 +- Replaced highlighting via :syntax with matchadd() / matchdelete(). This + requires Vim 7.2 / 7.1 with patches. This method is faster, there are no + more clashes with syntax highlighting (:match always has preference), and + the background highlighting does not disappear under 'cursorline'. +- Using winrestcmd() to fix effects of :windo: By entering a window, its + height is potentially increased from 0 to 1. +- Handling multiple tabs by calling s:UpdateScope() on the TabEnter event. + +2.0.0 01-Jun-2009 +- Now using Vim List for g:mwWord and thus requiring Vim 7. g:mwCycle is now + zero-based, but the syntax groups "MarkWordx" are still one-based. +- Factored :syntax operations out of s:DoMark() and s:UpdateMark() so that + they can all be done in a single :windo. +- Normal mode MarkSet now has the same semantics as its visual mode + cousin: If the cursor is on an existing mark, the mark is removed. + Beforehand, one could only remove a visually selected mark via again + selecting it. Now, one simply can invoke the mapping when on such a mark. + +1.6.1 31-May-2009 +Publication of improved version by Ingo Karkat. +- Now prepending search type ("any-mark", "same-mark", "new-mark") for better + identification. +- Retired the algorithm in s:PrevWord in favor of simply using , which + makes mark.vim work like the * command. At the end of a line, non-keyword + characters may now be marked; the previous algorithm preferred any preceding + word. +- BF: If 'iskeyword' contains characters that have a special meaning in a + regexp (e.g. [.*]), these are now escaped properly. +- Highlighting can now actually be overridden in the vimrc (anywhere _before_ + sourcing this script) by using ':hi def'. +- Added missing setter for re-inclusion guard. + +1.5.0 01-Sep-2008 +Bug fixes and enhancements by Ingo Karkat. +- Added MarkAllClear (without a default mapping), which clears all + marks, even when the cursor is on a mark. +- Added ... mappings for hard-coded \*, \#, \/, \?, * and #, to allow + re-mapping and disabling. Beforehand, there were some ... mappings + and hard-coded ones; now, everything can be customized. +- BF: Using :autocmd without to avoid removing _all_ autocmds for the + BufWinEnter event. (Using a custom :augroup would be even better.) +- BF: Explicitly defining s:current_mark_position; some execution paths left + it undefined, causing errors. +- ENH: Make the match according to the 'ignorecase' setting, like the star + command. +- ENH: The jumps to the next/prev occurrence now print 'search hit BOTTOM, + continuing at TOP" and "Pattern not found:..." messages, like the * and n/N + Vim search commands. +- ENH: Jumps now open folds if the occurrence is inside a closed fold, just + like n/N do. + +1.1.8-g 25-Apr-2008 +Last version published by Yuheng Xie on vim.org. + +1.1.2 22-Mar-2005 +Initial version published by Yuheng Xie on vim.org. + +============================================================================== +Copyright: (C) 2005-2008 by Yuheng Xie + (C) 2008-2010 by Ingo Karkat +The VIM LICENSE applies to this script; see|copyright|. + +Maintainer: Ingo Karkat +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/pi_getscript.txt b/doc/pi_getscript.txt new file mode 100644 index 0000000..2833980 --- /dev/null +++ b/doc/pi_getscript.txt @@ -0,0 +1,414 @@ +*pi_getscript.txt* For Vim version 7.0. Last change: 2008 Jan 07 +> + GETSCRIPT REFERENCE MANUAL by Charles E. Campbell, Jr. +< +Authors: Charles E. Campbell, Jr. + (remove NOSPAM from the email address) + *GetLatestVimScripts-copyright* +Copyright: (c) 2004-2006 by Charles E. Campbell, Jr. *glvs-copyright* + The VIM LICENSE applies to getscript.vim and + pi_getscript.txt (see |copyright|) except use + "getscript" instead of "Vim". No warranty, express or implied. + Use At-Your-Own-Risk. + +Getscript is a plugin that simplifies retrieval of the latest versions of the +scripts that you yourself use! Typing |:GLVS| will invoke getscript; it will +then use the (see |GetLatestVimScripts_dat|) file to +get the latest versions of scripts listed therein from http://vim.sf.net/. + +============================================================================== +1. Contents *glvs-contents* *glvs* *getscript* + *GetLatestVimScripts* + + 1. Contents........................................: |glvs-contents| + 2. GetLatestVimScripts -- Getting Started..........: |glvs-install| + 3. GetLatestVimScripts Usage.......................: |glvs-usage| + 4. GetLatestVimScripts Data File...................: |glvs-data| + 5. GetLatestVimScripts Friendly Plugins............: |glvs-plugins| + 6. GetLatestVimScripts AutoInstall.................: |glvs-autoinstall| + 7. GetLatestViMScripts Options.....................: |glvs-options| + 8. GetLatestVimScripts Algorithm...................: |glvs-alg| + 9. GetLatestVimScripts History.....................: |glvs-hist| + + +============================================================================== +2. GetLatestVimScripts -- Getting Started *getscript-start* + *getlatestvimscripts-install* + + VERSION FROM VIM DISTRIBUTION *glvs-dist-install* + +Vim 7.0 does not include the GetLatestVimScripts.dist file which +serves as an example and a template. So, you'll need to create +your own! See |GetLatestVimScripts_dat|. + + VERSION FROM VIM SF NET *glvs-install* + +NOTE: The last step, that of renaming/moving the GetLatestVimScripts.dist +file, is for those who have just downloaded GetLatestVimScripts.tar.bz2 for +the first time. + +The GetLatestVimScripts.dist file serves as an example and a template for your +own personal list. Feel free to remove all the scripts mentioned within it; +the "important" part of it is the first two lines. + +Your computer needs to have wget for GetLatestVimScripts to do its work. + + 1. if compressed: gunzip getscript.vba.gz + 2. Unix: + vim getscript.vba + :so % + :q + cd ~/.vim/GetLatest + mv GetLatestVimScripts.dist GetLatestVimScripts.dat + (edit GetLatestVimScripts.dat to install your own personal + list of desired plugins -- see |GetLatestVimScripts_dat|) + + 3. Windows: + vim getscript.vba + :so % + :q + cd **path-to-vimfiles**/GetLatest + mv GetLatestVimScripts.dist GetLatestVimScripts.dat + (edit GetLatestVimScripts.dat to install your own personal + list of desired plugins -- see |GetLatestVimScripts_dat|) + + +============================================================================== +3. GetLatestVimScripts Usage *glvs-usage* *:GLVS* + +Unless its been defined elsewhere, > + :GLVS +will invoke GetLatestVimScripts(). If some other plugin has defined that +command, then you may type +> + :GetLatestVimScripts +< +The script will attempt to update and, if permitted, will automatically +install scripts from http://vim.sourceforge.net/. To do so it will peruse a +file, +> + .vim/GetLatest/GetLatestVimScripts.dat (unix) +< +or > + ..wherever..\vimfiles\GetLatest\GetLatestVimScripts.dat (windows) +(see |glvs-data|), and examine plugins in your [.vim|vimfiles]/plugin +directory (see |glvs-plugins|). + +Scripts which have been downloaded will appear in the +~/.vim/GetLatest (unix) or ..wherever..\vimfiles\GetLatest (windows) +subdirectory. GetLatestVimScripts will attempt to automatically +install them if you have the following line in your <.vimrc>: > + + let g:GetLatestVimScripts_allowautoinstall=1 + +The file will be automatically be updated to +reflect the latest version of script(s) so downloaded. +(also see |glvs-options|) + + +============================================================================== +4. GetLatestVimScripts Data File *getscript-data* *glvs-data* + *:GetLatestVimScripts_dat* +The data file must have for its first two lines +the following text: +> + ScriptID SourceID Filename + -------------------------- +< +Following those two lines are three columns; the first two are numeric +followed by a text column. The GetLatest/GetLatestVimScripts.dist file +contains an example of such a data file. Anything following a #... is +ignored, so you may embed comments in the file. + +The first number on each line gives the script's ScriptID. When you're about +to use a web browser to look at scripts on http://vim.sf.net/, just before you +click on the script's link, you'll see a line resembling + + http://vim.sourceforge.net/scripts/script.php?script_id=40 + +The "40" happens to be a ScriptID that GetLatestVimScripts needs to +download the associated page. + +The second number on each line gives the script's SourceID. The SourceID +records the count of uploaded scripts as determined by vim.sf.net; hence it +serves to indicate "when" a script was uploaded. Setting the SourceID to 1 +insures that GetLatestVimScripts will assume that the script it has is +out-of-date. + +The SourceID is extracted by GetLatestVimScripts from the script's page on +vim.sf.net; whenever its greater than the one stored in the +GetLatestVimScripts.dat file, the script will be downloaded +(see |GetLatestVimScripts_dat|). + +If your script's author has included a special comment line in his/her plugin, +the plugin itself will be used by GetLatestVimScripts to build your + file, including any dependencies on other scripts it +may have. As an example, consider: > + + " GetLatestVimScripts: 884 1 :AutoInstall: AutoAlign.vim + +This comment line tells getscript.vim to check vimscript #884 and that the +script is automatically installable. Getscript will also use this line to +help build the GetLatestVimScripts.dat file, by including a line such as: > + + 884 1 AutoAlign.vim +< +in it an AutoAlign.vim line isn't already in GetLatestVimScripts.dat file. +See |glvs-plugins| for more. Thus, GetLatestVimScripts thus provides a +comprehensive ability to keep your plugins up-to-date! + + *GetLatestVimScripts_dat* +As an example of a file: +> + ScriptID SourceID Filename + -------------------------- + 294 1 Align.vim + 120 2 decho.vim + 40 3 DrawIt.tar.gz + 451 4 EasyAccents.vim + 195 5 engspchk.vim + 642 6 GetLatestVimScripts.vim + 489 7 Manpageview.vim +< +Note: the first two lines are required, but essentially act as comments. + + +============================================================================== +5. GetLatestVimScripts Friendly Plugins *getscript-plugins* *glvs-plugins* + +If a plugin author includes the following comment anywhere in their plugin, +GetLatestVimScripts will find it and use it to automatically build the user's +GetLatestVimScripts.dat files: +> + src_id + v + " GetLatestVimScripts: ### ### yourscriptname + ^ + scriptid +< +As an author, you should include such a line in to refer to your own script +plus any additional lines describing any plugin dependencies it may have. +Same format, of course! + +If your command is auto-installable (see |glvs-autoinstall|), and most scripts +are, then you may include :AutoInstall: at the start of "yourscriptname". + +GetLatestVimScripts commands for those scripts are then appended, if not +already present, to the user's GetLatest/GetLatestVimScripts.dat file. Its a +relatively painless way to automate the acquisition of any scripts your +plugins depend upon. + +Now, as an author, you probably don't want GetLatestVimScripts to download +your own scripts for you yourself, thereby overwriting your not-yet-released +hard work. GetLatestVimScripts provides a solution for this: put +> + 0 0 yourscriptname +< +into your file and GetLatestVimScripts will skip +examining the "yourscriptname" scripts for those GetLatestVimScripts comment +lines. As a result, those lines won't be inadvertently installed into your + file and subsequently used to download your own +scripts. This is especially important to do if you've included the +:AutoInstall: option. + +Be certain to use the same "yourscriptname" in the "0 0 yourscriptname" line +as you've used in your GetLatestVimScripts comment! + + +============================================================================== +6. GetLatestVimScripts AutoInstall *getscript-autoinstall* + *glvs-autoinstall* + +GetLatestVimScripts now supports "AutoInstall". Not all scripts are +supportive of auto-install, as they may have special things you need to do to +install them (please refer to the script's "install" directions). On the +other hand, most scripts will be auto-installable. + +To let GetLatestVimScripts do an autoinstall, the data file's comment field +should begin with (surrounding blanks are ignored): > + + :AutoInstall: +< +Both colons are needed, and it should begin the comment (yourscriptname) +field. + +One may prevent any autoinstalling by putting the following line in your +<.vimrc>: > + + let g:GetLatestVimScripts_allowautoinstall= 0 +< +With :AutoInstall: enabled, as it is by default, files which end with + + ---.tar.bz2 : decompressed & untarred in .vim/ directory + ---.vba.bz2 : decompressed in .vim/ directory, then vimball handles it + ---.vim.bz2 : decompressed & moved into .vim/plugin directory + ---.tar.gz : decompressed & untarred in .vim/ directory + ---.vba.gz : decompressed in .vim/ directory, then vimball handles it + ---.vim.gz : decompressed & moved into .vim/plugin directory + ---.vba : unzipped in .vim/ directory + ---.vim : moved to .vim/plugin directory + ---.zip : unzipped in .vim/ directory + +and which merely need to have their components placed by the untar/gunzip or +move-to-plugin-directory process should be auto-installable. Vimballs, of +course, should always be auto-installable. + +When is a script not auto-installable? Let me give an example: + + .vim/after/syntax/blockhl.vim + +The script provides block highlighting for C/C++ programs; it is +available at: + + http://vim.sourceforge.net/scripts/script.php?script_id=104 + +Currently, vim's after/syntax only supports by-filetype scripts (in +blockhl.vim's case, that's after/syntax/c.vim). Hence, auto-install would +possibly overwrite the current user's after/syntax/c.vim file. + +In my own case, I use (renamed to after/syntax/c.vim) to +allow a after/syntax/c/ directory: + + http://vim.sourceforge.net/scripts/script.php?script_id=1023 + +The script allows multiple syntax files to exist separately in the +after/syntax/c subdirectory. I can't bundle aftersyntax.vim in and build an +appropriate tarball for auto-install because of the potential for the +after/syntax/c.vim contained in it to overwrite a user's c.vim. + + +============================================================================== +7. GetLatestVimScripts Options *glvs-options* +> + g:GetLatestVimScripts_wget +< default= "wget" + This variable holds the name of the command for obtaining + scripts. +> + g:GetLatestVimScripts_options +< default= "-q -O" + This variable holds the options to be used with the + g:GetLatestVimScripts_wget command. +> + g:getLatestVimScripts_allowautoinstall +< default= 1 + This variable indicates whether GetLatestVimScripts is allowed + to attempt to automatically install scripts. Note that it + doesn't understand vimballs (yet). Furthermore, the plugin + author has to have explicitly indicated that his/her plugin + is automatically installable. + + +============================================================================== +8. GetLatestVimScripts Algorithm *glvs-algorithm* *glvs-alg* + +The Vim sourceforge page dynamically creates a page by keying off of the +so-called script-id. Within the webpage of + + http://vim.sourceforge.net/scripts/script.php?script_id=40 + +is a line specifying the latest source-id (src_id). The source identifier +numbers are always increasing, hence if the src_id is greater than the one +recorded for the script in GetLatestVimScripts then it's time to download a +newer copy of that script. + +GetLatestVimScripts will then download the script and update its internal +database of script ids, source ids, and scriptnames. + +The AutoInstall process will: + + Move the file from GetLatest/ to the following directory + Unix : $HOME/.vim + Windows: $HOME\vimfiles + if the downloaded file ends with ".bz2" + bunzip2 it + else if the downloaded file ends with ".gz" + gunzip it + if the resulting file ends with ".zip" + unzip it + else if the resulting file ends with ".tar" + tar -oxvf it + else if the resulting file ends with ".vim" + move it to the plugin subdirectory + + +============================================================================== +9. GetLatestVimScripts History *getscript-history* *glvs-hist* {{{1 + +v29 Jan 07, 2008 : * Bram M pointed out that cpo is a global option and that + getscriptPlugin.vim was setting it but not restoring it. +v28 Jan 02, 2008 : * improved shell quoting character handling, cygwin + interface, register-a bypass + Oct 29, 2007 * Bill McCarthy suggested a change to getscript that avoids + creating pop-up windows +v24 Apr 16, 2007 : * removed save&restore of the fo option during script + loading +v23 Nov 03, 2006 : * ignores comments (#...) + * handles vimballs +v22 Oct 13, 2006 : * supports automatic use of curl if wget is not + available +v21 May 01, 2006 : * now takes advantage of autoloading. +v20 Dec 23, 2005 : * Eric Haarbauer found&fixed a bug with unzip use; + unzip needs the -o flag to overwrite. +v19 Nov 28, 2005 : * v18's GetLatestVimScript line accessed the wrong + script! Fixed. +v18 Mar 21, 2005 : * bugfix to automatic database construction + * bugfix - nowrapscan caused an error + (tnx to David Green for the fix) + Apr 01, 2005 * if shell is bash, "mv" instead of "ren" used in + :AutoInstall:s, even though its o/s is windows + Apr 01, 2005 * when downloading errors occurred, GLVS was + terminating early. It now just goes on to trying + the next script (after trying three times to + download a script description page) + Apr 20, 2005 * bugfix - when a failure to download occurred, + GetLatestVimScripts would stop early and claim that + everything was current. Fixed. +v17 Aug 25, 2004 : * g:GetLatestVimScripts_allowautoinstall, which + defaults to 1, can be used to prevent all + :AutoInstall: +v16 Aug 25, 2004 : * made execution of bunzip2/gunzip/tar/zip silent + * fixed bug with :AutoInstall: use of helptags +v15 Aug 24, 2004 : * bugfix: the "0 0 comment" download prevention wasn't + always preventing downloads (just usually). Fixed. +v14 Aug 24, 2004 : * bugfix -- helptags was using dotvim, rather than + s:dotvim. Fixed. +v13 Aug 23, 2004 : * will skip downloading a file if its scriptid or srcid + is zero. Useful for script authors; that way their + own GetLatestVimScripts activity won't overwrite + their scripts. +v12 Aug 23, 2004 : * bugfix - a "return" got left in the distribution that + was intended only for testing. Removed, now works. + * :AutoInstall: implemented +v11 Aug 20, 2004 : * GetLatestVimScripts is now a plugin: + * :GetLatestVimScripts command + * (runtimepath)/GetLatest/GetLatestVimScripts.dat + now holds scripts that need updating +v10 Apr 19, 2004 : * moved history from script to doc +v9 Jan 23, 2004 : windows (win32/win16/win95) will use + double quotes ("") whereas other systems will use + single quotes ('') around the urls in calls via wget +v8 Dec 01, 2003 : makes three tries at downloading +v7 Sep 02, 2003 : added error messages if "Click on..." or "src_id=" + not found in downloaded webpage + Uses t_ti, t_te, and rs to make progress visible +v6 Aug 06, 2003 : final status messages now display summary of work + ( "Downloaded someqty scripts" or + "Everything was current") + Now GetLatestVimScripts is careful about downloading + GetLatestVimScripts.vim itself! + (goes to ) +v5 Aug 04, 2003 : missing an endif near bottom +v4 Jun 17, 2003 : redraw! just before each "considering" message +v3 May 27, 2003 : Protects downloaded files from errant shell + expansions with single quotes: '...' +v2 May 14, 2003 : extracts name of item to be obtained from the + script file. Uses it instead of comment field + for output filename; comment is used in the + "considering..." line and is now just a comment! + * Fixed a bug: a string-of-numbers is not the + same as a number, so I added zero to them + and they became numbers. Fixes comparison. + +============================================================================== +vim:tw=78:ts=8:ft=help:fdm=marker diff --git a/doc/project.txt b/doc/project.txt new file mode 100644 index 0000000..8f85c23 --- /dev/null +++ b/doc/project.txt @@ -0,0 +1,710 @@ +*project.txt* Plugin for managing multiple projects with multiple sources + For Vim version 6.x and Vim version 7.x. + Last Change: Fri 13 Oct 2006 10:20:13 AM EDT + + + By Aric Blumer + aricvim email-at-sign charter.net + + *project* *project-plugin* + Contents: + + Commands...................|project-invoking| + Inheritance.............|project-inheritance| + Mappings...................|project-mappings| + Adding Mappings.....|project-adding-mappings| + Settings...................|project-settings| + Example File................|project-example| + Tips...........................|project-tips| + + +You can use this plugin's basic functionality to set up a list of +frequently-accessed files for easy navigation. The list of files will be +displayed in a window on the left side of the Vim window, and you can press + or double-click on filenames in the list to open the files. I find +this easier to use than having to navigate a directory hierarchy with the +|file-explorer|. + +You can also instruct the Plugin to change to a directory and to run Vim +scripts when you select a file. These scripts can, for example, modify the +environment to include compilers in $PATH. This makes it very easy to use +quickfix with multiple projects that use different environments. + +Other features include: + o Loading/Unloading all the files in a Project (\l, \L, \w, and \W) + o Grepping all the files in a Project (\g and \G) + o Running a user-specified script on a file (can be used to launch an + external program on the file) (\1 through \9) + o Running a user-specified script on all the files in a Project + (\f1-\f9 and \F1-\F9) + o High degree of user-configurability + o Also works with |netrw| using the XXXX://... notation where XXXX is + ftp, rcp, scp, or http. + +All of this is specified within a simple text file and a few global variables +in your vimrc file. + +You must set 'nocompatible' in your |vimrc| file to use this plugin. You can +stop the plugin from being loaded by setting the "loaded_project" variable: > + :let loaded_project = 1 + + +============================================================================== +COMMANDS *project-invoking* + +You can use the plugin by placing it in your plugin directory (e.g., +~/.vim/plugin). See |add-global-plugin|. When you start vim the next time, you +then enter the command > + :Project +or > + :Project {file} + +If you do not specify the filename, $HOME/.vimprojects is used. + +To have Vim come up with the Project Window enabled automatically (say, from a +GUI launcher), run Vim like this: [g]vim +Project + +Note that you can invoke :Project on only one file at a time. If you wish to +change the Project File, do a :bwipe in the Project Buffer, then re-invoke the +Plugin as described above. + +Several Projects can be kept and displayed in the same file, each in a fold +delimited by { and } (see |fold.txt|). There can be any number of nested +folds to provide you with a Project hierarchy. Any line without a { or a } in +the file is considered to be a filename. Blank lines are ignored, and any +text after a # is ignored. + +Because the plugin uses standard Vim folds, you can use any of the +|fold-commands|. You can double-click on the first line of a fold to open and +close it. You can select a file to open by putting the cursor on its name and +pressing or by double-clicking on it. The plugin will create a new +window to the right or use the |CTRL-W_p| equivalent if it exists. + + *project-syntax* +Each Project Entry has this form: + +project_entry ::= + ={projpath} [{options}] { + [ filename ] + [ project_entry ] + } + +{options} is one or more of the following (on the same line): + CD={path} + in={filename} + out={filename} + filter="{pat}" + flags={flag} + +Note that a project_entry can reside within a project_entry. This allows you +to set up a hierarchy within your Project. + +The will be displayed in the foldtext and cannot contain "=". +There can be no space character directly on either side of the =. + +The {projpath} is the path in which the files listed in the Project's fold +will be found, and it may contain environment variables. If the path is a +relative path, then the plugin constructs the whole path from the Project's +parent, grandparent, etc., all the way up the hierarchy. An outermost +project_entry must have an absolute path. See the |project-inheritance| +example below. {projpath} may contain spaces, but they must be escaped like +normal Vim escapes. Here are two examples of the same directory: +> + Example=/my/directory/with\ spaces { + } + Example="/my/directory/with spaces" { + } + +I recommend this for Windows®: > + + Example="c:\My Documents" { + } + +But Vim is smart enough to do this, too: > + + Example=c:\My\ Documents { + } + +CD= provides the directory that Vim will change to when you select a file in +that fold (using |:cd|). This allows you, for example, to enter |:make| to use +the local Makefile. A CD=. means that Vim will make {projpath} or its +inherited equivalent the current working directory. When CD is omitted, the +directory is not changed. There can be no space on either side of the =. The +value of CD can also be a relative path from a parent's CD. See the +|project-inheritance| example below. This directive is ignored for |netrw| +projects. Spaces are allowed in the path as for {projpath}. + +in= and out= provide the means to run arbitrary Vim scripts whenever you enter +or leave a file's buffer (see the |BufEnter| and |BufLeave| autocommand +events). The idea is to have a Vim script that sets up or tears down the +environment for the Project like this: + +in.vim: > + let $PROJECT_HOME='~/my_project' + " Put the compiler in $PATH + if $PATH !~ '/path/to/my/compiler' + let $PATH=$PATH.':/path/to/my/compiler' + endif + +out.vim: > + " Remove compiler from $PATH + if $PATH =~ '/path/to/my/compiler' + let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g') + endif + +Then you can use :make with the proper environment depending on what file you +are currently editing. If the path to the script is relative, then it is +relative from {projpath}. These directives are inherited by Subprojects +unless the Subproject specifies its own. For use with |netrw| projects, the +paths specified for in= and out= must be absolute and local. + +filter= specifies a |glob()| file pattern. It is used to regenerate the list +of files in a Project fold when using the \r (r) map in the +Project Window. The filter value must be in quotes because it can contain +multiple file patterns. If filter is omitted, then the * pattern is used. +There can be no space on either side of the =. A Subproject will inherit the +filter of its parent unless it specifies its own filter. + +flags= provides the means to enable/disable features for a particular fold. +The general mnemonic scheme is for lower case to turn something off and upper +case to turn something on. {flag} can contain any of the following +characters: + + flag Description ~ + + l Turn off recursion for this fold for \L. Subfolds are also + blocked from the recursion. + + r Turn off refresh. When present, do not refresh this fold when + \r or \R is used. This does not affect subfold recursion. + + S Turn on sorting for refresh and create. + + s Turn off sorting for refresh and create. + + T Turn on top gravity. Forces folds to the top of the current + fold when refreshing. It has the same affect as the 'T' flag + in g:proj_flags, but controls the feature on a per-fold basis. + + t Turn off top gravity. Forces folds to the bottom of the + current fold when refreshing. + + w Turn off recursion for this fold for \W. Subfolds are also + blocked from the recursion. + + +Flags are not inherited by Subprojects. + +Any text outside a fold is ignored. + + +============================================================================== +INHERITANCE *project-inheritance* + +It's best to show inheritance by comparing these two Project Files: +> + Parent=~/my_project CD=. filter="Make* *.mk" flags=r { + Child1=c_code { + } + Child2=include CD=. filter="*.h" { + } + } + +Child1's path is "~/my_project/c_code" because ~/my_project is inherited. It +also inherits the CD from Parent. Since Parent has CD=., the Parent's cwd is +"~/my_project". Child1 therefore inherits a CD of "~/my_project". Finally, +Child1 inherits the filter from Parent. The flags are not inherited. + +Child2 only inherits the "~/my_project" from Parent. + +Thus, the example above is exactly equivalent to this: +> + Parent=~/my_project CD=. filter="Make* *.mk" flags=r { + Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" { + } + Child2=~/my_project/include CD=~/my_project/include filter="*.h" { + } + } + +(For a real Project, Child1 would not want to inherit its parent's filter, but +this example shows the concept.) You can always enter \i to display what the +cursor's project inherits. + + +============================================================================== +MAPPINGS *project-mappings* + +Map Action ~ + +\r Refreshes the Project fold that the cursor is in by placing in the + fold all the files that match the filter. The Project is refreshed + using an indent of one space for every foldlevel in the hierarchy. + + You may place a "# pragma keep" (without the quotes) at the end of a + line, and the file entry on that line will not be removed when you + refresh. This is useful, for example, when you have . as an entry so + you can easily browse the directory. + + Note that this mapping is actually r, and the default of + || is \. + + This does not work for Projects using |netrw|. + +\R Executes \r recursively in the current fold and all folds below. + This does not work for Projects using |netrw|. + +\c Creates a Project fold entry. It asks for the description, the path + to the files, the CD parameter, and the filename |glob()| pattern. + From this information, it will create the Project Entry below the + cursor. + + This does not work for Projects using |netrw|. + +\C Creates a Project fold entry like \c, but recursively includes all the + subdirectories. + + + Select a file to open in the |CTRL-W_p| window or in a new window. If + the cursor is on a fold, open or close it. + + +\s + Same as but horizontally split the target window. + s is provided for those terminals that don't recognize + . + +\S + Load all files in a project by doing horizontal splits. + + +\o + Same as but ensure that the opened file is the only other + window. o is provided for those terminals that don't + recognize . + + +\v + Same as but only display the file--the cursor stays in the + Project Window. + +<2-LeftMouse> + (Double-click) If on a closed fold, open it. If on an open fold + boundary, close it. If on a filename, open the file in the |CTRL-W_p| + window or in a new window. + + + Same as . + + + Same as . + + + Increase the width of the Project Window by g:proj_window_increment or + toggle between a width of + g:proj_window_width + g:proj_window_increment + and + g:proj_window_width. + + Whether you toggle or monotonically increase the width is determined + by the 't' flag of the g:proj_flags variable (see |project-flags|). + + Note that a Right Mouse click will not automatically place the cursor + in the Project Window if it is in a different window. The window will + go back to the g:proj_window_width width when you leave the window. + + Same as + + +\ + Move the text or fold under the cursor up one row. This may not work + in a terminal because the terminal is unaware of this key combination. + is provided for those terminals that don't recognize + . + + + +\ + Move the text or fold under the cursor down one row. This may not work + in a terminal because the terminal is unaware of this key combination. + is provided for those terminals that don't + recognize . + +\i Show in the status line the completely resolved and inherited + parameters for the fold the cursor is in. This is intended for + debugging your relative path and inherited parameters for manually + entered Projects. + +\I Show in the status line the completely resolved filename. Uses the + Project_GetFname(line('.')) function. + +\1 - \9 + Run the command specified in g:proj_run{x} where {x} is the number + of the key. See the documentation of g:proj_run1 below. + +\f1-\f9 + Run the command specified in g:proj_run_fold{x} where {x} is the + number of the key. The command is run on the files at the current + Project level. See the |project-settings| below. + +\F1-\F9 + Run the command specified in g:proj_run_fold{x} where {x} is the + number of the key. The command is run on the files at the current + Project level and all Subprojects. See the |project-settings| below. + +\0 Display the commands that are defined for \1 through \9. + +\f0 Display the commands that are defined for \f1 through \f9 and \F1 + through \F0. Same as \F0. + +\l Load all the files in the current Project level into Vim. While files + are being loaded, you may press any key to stop. + +\L Load all the files in the current Project and all Subprojects into + Vim. Use this mapping with caution--I wouldn't suggest using \L to + load a Project with thousands of files. (BTW, my Project file has more + than 5,300 files in it!) While files are being loaded, you may press + any key to stop. + +\w Wipe all the files in the current Project level from Vim. (If files + are modified, they will be saved first.) While files are being wiped, + you may press any key to stop. + +\W Wipe all the files in the current Project and all Subprojects from + Vim. (If files are modified, they will be saved first.) While files + are being wiped, you may press any key to stop. + +\g Grep all the files in the current Project level. + +\G Grep all the files in the current Project level and all Subprojects. + +\e Set up the Environment for the Project File as though you had selected + it with . This allows you to do a \e and a :make without + having to open any files in the project. + +\E Explore (using |file-explorer|) the directory of the project the + cursor is in. Does not work with netrw. + + When the 'g' flag is present in g:proj_flags (see |project-flags|) + this key toggles the Project Window open and closed. You may remap + this toggle function by putting the following in your vimrc and + replacing P with whatever key combination you wish: + + nmap P ToggleProject + +Note that the Project Plugin remaps :help because the Help Window and the +Project Window get into a fight over placement. The mapping avoids the +problem. + +============================================================================== +ADDING MAPPINGS *project-adding-mappings* + +You can add your own mappings or change the mappings of the plugin by placing +them in the file $HOME/.vimproject_mappings. This file, if it exists, will be +sourced when the plugin in loaded. Here is an example that will count the +number of entries in a project when you press \K (Kount, C is taken :-): > + + function! s:Wc() + let b:loadcount=0 + function! SpawnExec(infoline, fname, lineno, data) + let b:loadcount = b:loadcount + 1 + if getchar(0) != 0 | let b:stop_everything=1 | endif + endfunction + call Project_ForEach(1, line('.'), "*SpawnExec", 0, '') + delfunction SpawnExec + echon b:loadcount." Files\r" + unlet b:loadcount + if exists("b:stop_everything") + unlet b:stop_everything + echon "Aborted.\r" + endif + endfunction + + nnoremap K :call Wc() + +Here's another example of how I integrated the use of perforce with the plugin +in my $HOME/.vimproject_mappings: +> + function! s:DoP4(cmd) + let name=Project_GetFname(line('.')) + let dir=substitute(name, '\(.*\)/.*', '\1', 'g') + exec 'cd '.dir + exec "!".a:cmd.' '.Project_GetFname(line('.')) + cd - + endfunction + + nmap \pa :call DoP4("p4add") + nmap \pe :call DoP4("p4edit") +< +(Note that I CD to the directory the file is in so I can pick of the $P4CONFIG +file. See the perforce documentation.) + +This creates the mappings \pe to check out the file for edit and \pa to add +the file to the depot. + +Here is another example where I remap the mapping to use an external +program to launch a special kind of file (in this case, it launches ee to view +a jpg file). It is a bit contrived, but it works. +> + let s:sid = substitute(maparg('', 'n'), '.*\(.\{-}\)_.*', '\1', '') + function! s:LaunchOrWhat() + let fname=Project_GetFname(line('.')) + if fname =~ '\.jpg$' + exec 'silent! !ee "'.fname.'"&' + else + call {s:sid}_DoFoldOrOpenEntry('', 'e') + endif + endfunction + nnoremap \|:call LaunchOrWhat() +< +If the file ends in .jpg, the external program is launched, otherwise the +original mapping of is run. + +============================================================================== +SETTINGS *project-settings* + +You can set these variables in your vimrc file before the plugin is loaded to +change its default behavior + +g:proj_window_width + The width of the Project Window that the plugin attempts to maintain. + Default: 24 + + The Project Plugin is not always successful in keeping the window + where I want it with the size specified here, but it does a decent + job. + +g:proj_window_increment + The increment by which to increase the width of the Project Window + when pressing or clicking the . Default: 100 + (See |project-mappings|.) + + *project-flags* +g:proj_flags + Default: "imst" + Various flags to control the behavior of the Project Plugin. This + variable can contain any of the following character flags. + + flag Description ~ + + b When present, use the |browse()| when selecting directories + for \c and \C. This is off by default for Windows, because + the windows browser does not allow you to select directories. + + c When present, the Project Window will automatically close when + you select a file. + + F Float the Project Window. That is, turn off automatic + resizing and placement. This allows placement between other + windows that wish to share similar placement at the side of + the screen. It is also particularly helpful for external + window managers. + + g When present, the mapping for will be created to toggle + the Project Window open and closed. + + i When present, display the filename and the current working + directory in the command line when a file is selected for + opening. + + l When present, the Project Plugin will use the |:lcd| command + rather than |:cd| to change directories when you select a file + to open. This flag is really obsolete and not of much use + because of L below. + + L Similar to l, but install a BufEnter/Leave |:autocommand| to + ensure that the current working directory is changed to the + one specified in the fold CD specification whenever that + buffer is active. (|:lcd| only changes the CWD for a window, + not a buffer.) + + m Turn on mapping of the |CTRL-W_o| and |CTRL-W_CTRL_O| normal + mode commands to make the current buffer the only visible + buffer, but keep the Project Window visible, too. + + n When present, numbers will be turned on for the project + window. + + s When present, the Project Plugin will use syntax highlighting + in the Project Window. + + S Turn on sorting for refresh and create. + + t When present, toggle the size of the window rather than just + increase the size when pressing or right-clicking. + See the entry for in |project-mappings|. + + T When present, put Subproject folds at the top of the fold when + refreshing. + + v When present, use :vimgrep rather than :grep when using \G. + +g:proj_run1 ... g:proj_run9 + Contains a Vim command to execute on the file. See the + mappings of \1 to \9 above. + + %f is replaced with the full path and filename + %F is replaced with the full path and filename with spaces + quoted + %n is replaced with the filename alone + %N is replaced with the filename alone with spaces quoted + %h is replaced with the home directory + %H is replaced with the home directory with spaces quoted + %r is replaced with the directory relative to the CD path + %R is replaced with the directory relative to the CD path + with spaces quoted + %d is replaced with the CD directory. + %D is replaced with the CD directory.with spaces quoted + %% is replaced with a single % that is not used in + expansion. + + (Deprecated: %s is also replaced with the full path and + filename for backward compatibility.) + + For example, gvim will be launched on the file under the + cursor when you enter \3 if the following is in your vimrc + file: > + let g:proj_run3='silent !gvim %f' +< Here are a few other examples: > + let g:proj_run1='!p4 edit %f' + let g:proj_run2='!p4 add %f' + let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &" +< + On Windows systems you will want to put the %f, %h, and %d in + single quotes to avoid \ escaping. + +g:proj_run_fold1 ... g:proj_run_fold9 + Contains a Vim command to execute on the files in a fold. See + the mappings of \f1 to \f9 and \F1 to \F9 above. + + %f is the filename, %h is replaced with the project home + directory, and %d is replaced with the CD directory. Multiple + filenames can be handled in two ways: + + The first (default) way is to have %f replaced with all the + absolute filenames, and the command is run once. The second + is to have the command run for each of the non-absolute + filenames (%f is replaced with one filename at a time). To + select the second behavior, put an '*' character at the + beginning of the g:proj_run_fold{x} variable. (The '*' is + stripped before the command is run.) + + For example, note the difference between the following: > + let g:proj_run_fold3="*echo '%h/%f'" + let g:proj_run_fold4="echo '%f'" +< + Note that on Windows systems, you will want the %f, %h, and %c + within single quotes, or the \ in the paths will cause + problems. The alternative is to put them in |escape()|. + + +============================================================================== +PROJECT EXAMPLE FILE *project-example* + +Here is an example ~/.vimprojects file: > + + 1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r { + 2 Makefile + 3 in.vim + 4 out.vim + 5 GUI Files=. filter="gui*.c gui*.h" { + 6 gui_window.c + 7 gui_dialog.c + 8 gui_list.c + 9 gui.h # Header file + 10 } + 11 Database Files=. filter="data*.c data*.h" { + 12 data_read.c + 13 data_write.c + 14 data.h + 15 } + 16 OS-Specific Files { + 17 Win32=. filter="os_win32*.c os_win32*.h" { + 18 os_win32_gui.c + 19 os_win32_io.c + 20 } + 21 Unix=. filter="os_unix*.c os_unix*.h" { + 22 os_unix_gui.c + 23 os_unix_io.c + 24 } + 25 } + 26 } + +(Don't type in the line numbers, of course.) + + +============================================================================== +TIPS ON USING PROJECT PLUGIN *project-tips* + +1. You can create a Project Entry by entering this: > + + Label=~/wherever CD=. filter="*.c *.h" { + } +< + Then you can put the cursor in the fold and press \r. The script will fill + in the files (C files in this case) from this directory for you. This is + equivalent to \c without any dialogs. + +2. You can edit the Project File at any time to add, remove, or reorder files + in the Project list. + +3. If the Project Window ever gets closed, you can just enter > + :Project +< to bring it back again. (You don't need to give it the filename; the + plugin remembers.) + + If you have the 'm' flag set in g:proj_flags, then you get the Project + Window to show up again by pressing |CTRL-W_o|. This, of course, will + close any other windows that may be open that the cursor is not in. + +4. Adding files to a Project is very easy. To add, for example, the 'more.c' + file to the Project, just insert the filename in the Project Entry then + hit on it. + +5. When |quickfix| loads files, it is not equivalent to pressing on + a filename, so the directory will not be changed and the scripts will not + be run. (If I could make this otherwise, I would.) The solution is to use + the \L key to load all of the files in the Project before running + quickfix. + +6. If the Project window gets a bit cluttered with folds partially + open/closed, you can press |zM| to close everything and tidy it up. + +7. For advanced users, I am exporting the function Project_GetAllFnames() + which returns all the filenames within a fold and optionally all its + Subprojects. Also, I export Project_ForEach() for running a function for + each filename in the project. See the code for examples on how to use + these. Finally, I export Project_GetFname(line_number) so that you can + write your own mappings and get the filename for it. + +8. Some people have asked how to do a global mapping to take the cursor to + the Project window. One of my goals for the plugin is for it to be as + self-contained as possible, so I'm not going to add it by default. But you + can put this in your vimrc: +> + nmap P :Project + +< +9. You can put the . entry in a project, and it will launch the + |file-explorer| plugin on the directory. To avoid removal when you + refresh, make the entry look like this: +> + . # pragma keep +< +============================================================================== +THANKS + + The following people have sent me patches to help with the Project + Plugin development: + + Tomas Zellerin + Lawrence Kesteloot + Dave Eggum + A Harrison + Thomas Link + Richard Bair + Eric Arnold + Peter Jones + Eric Van Dewoestine + + + vim:ts=8 sw=8 noexpandtab tw=78 ft=help: diff --git a/doc/showmarks.txt b/doc/showmarks.txt new file mode 100644 index 0000000..96dc1e1 --- /dev/null +++ b/doc/showmarks.txt @@ -0,0 +1,264 @@ +*showmarks.txt* Visually show the location of marks + + By Anthony Kruize + Michael Geddes + + +ShowMarks provides a visual representation of |marks| local to a buffer. +Marks are useful for jumping back and forth between interesting points in a +buffer, but can be hard to keep track of without any way to see where you have +placed them. + +ShowMarks hopefully makes life easier by placing a |sign| in the +leftmost column of the buffer. The sign indicates the label of the mark and +its location. + +ShowMarks is activated by the |CursorHold| |autocommand| which is triggered +every |updatetime| milliseconds. This is set to 4000(4 seconds) by default. +If this is too slow, setting it to a lower value will make it more responsive. + +Note: This plugin requires Vim 6.x compiled with the |+signs| feature. + +=============================================================================== +1. Contents *showmarks* *showmarks-contents* + + 1. Contents |showmarks-contents| + 2. Configuration |showmarks-configuration| + 3. Highlighting |showmarks-highlighting| + 4. Key mappings |showmarks-mappings| + 5. Commands |showmarks-commands| + 6. ChangeLog |showmarks-changelog| + + Appendix + A. Using marks |marks| + B. Using signs |sign| + C. Defining updatetime |updatetime| + D. Defining a mapleader |mapleader| + E. Defining highlighting |highlight| + +=============================================================================== +2. Configuration *showmarks-configuration* + +ShowMarks can be configured to suit your needs. +The following options can be added to your |vimrc| to change how ShowMarks +behaves: + + *'showmarks_enable'* +'showmarks_enable' boolean (default: 1) + global + This option enables or disables ShowMarks on startup. Normally ShowMarks + will be enabled when Vim starts, setting this to 0 will disable ShowMarks + by default. + ShowMarks can be turned back on using the |ShowMarksToggle| command. + + *'showmarks_include'* +'showmarks_include' string (default: +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.'`^<>[]{}()\"") + global or local to buffer + This option specifies which marks will be shown and in which order if + placed on the same line. Marks earlier in the list take precedence over + marks later in the list. + This option can also be specified as a buffer option which will override + the global version. + + NOTE: When including the " mark, it must be escaped with a \. + + For example to only include marks 'abcdefzxABHJio', in that order: +> + let g:showmarks_include="abcdefzxABJio" +< + To override this for a particular buffer with 'ABCDhj.'^': +> + let b:showmarks_include="abcdefzxABJio" +< + *'showmarks_ignore_type'* +'showmarks_ignore_type' string (default: "hq") + global + This option defines which types of buffers should be ignored. + Each type is represented by a letter. This option is not case-sensitive. + Valid buffer types are: + - h : Help + - m : Non-modifiable + - p : Preview + - q : Quickfix + - r : Readonly + + For example to ignore help, preview and readonly files: +> + let g:showmarks_ignore_type="hpr" +< + *'showmarks_ignore_name'* +'showmarks_textlower' string (default: ">" ) + global + This option defines how the marks a-z will be displayed. + A maximum of two characters can be defined. + To include the mark in the text use a tab(\t) character. A single + character will display as the mark with the character suffixed (same as + "\t"). Specifying two characters will simply display those two + characters. + + Some examples: + To display the mark with a > suffixed: > + let g:showmarks_textlower="\t>" +< or > + let g:showmarks_textlower=">" +< + To display the mark with a ( prefixed: > + let g:showmarks_textlower="(\t" +< + To display two > characters: > + let g:showmarks_textlower=">>" +< + *'showmarks_textupper'* +'showmarks_textupper' string (default: ">") + global + This option defines how the marks A-Z will be displayed. It behaves the same + as the |'showmarks_textlower'| option. + + *'showmarks_textother'* +'showmarks_textother' string (default: ">") + global + This option defines how all other marks will be displayed. It behaves the + same as the |'showmarks_textlower'| option. + +'showmarks_hlline_lower' boolean (default: 0) *'showmarks_hlline_lower'* + global + This option defines whether the entire line a lowercase mark is on will + be highlighted. + +'showmarks_hlline_upper' boolean (default: 0) *'showmarks_hlline_upper'* + global + This option defines whether the entire line an uppercase mark is on will + be highlighted. + +'showmarks_hlline_other' boolean (default: 0) *'showmarks_hlline_other'* + global + This option defines whether the entire line other marks are on will be + highlighted. + +=============================================================================== +3. Highlighting *showmarks-highlighting* + +Four highlighting groups are used by ShowMarks to define the colours used to +highlight each of the marks. + + - ShowMarksHLl : This group is used to highlight all the lowercase marks. + - ShowMarksHLu : This group is used to highlight all the uppercase marks. + - ShowMarksHLo : This group is used to highlight all other marks. + - ShowMarksHLm : This group is used when multiple marks are on the same line. + +You can define your own highlighting by overriding these groups in your |vimrc|. +For example: > + + highlight ShowMarksHLl guifg=red guibg=green +< +Will set all lowercase marks to be red on green when running in GVim. +See |highlight| for more information. + +=============================================================================== +4. Mappings *showmarks-mappings* + +The following mappings are setup by default: + + mt - Toggles ShowMarks on and off. + mo - Forces ShowMarks on. + mh - Clears the mark at the current line. + ma - Clears all marks in the current buffer. + mm - Places the next available mark on the current line. + +(see |mapleader| for how to setup the mapleader variable.) + +=============================================================================== +5. Commands *showmarks-commands* + + *ShowMarksToggle* +:ShowMarksToggle + This command will toggle the display of marks on or off. + + +:ShowMarksOn *ShowMarksOn* + This command will force the display of marks on. + + *ShowMarksClearMark* +:ShowMarksClearMark + This command will clear the mark on the current line. + It doesn't actually remove the mark, it simply moves it to line 1 and + removes the sign. + + *ShowMarksClearAll* +:ShowMarksClearAll + This command will clear all marks in the current buffer. + It doesn't actually remove the marks, it simply moves them to line 1 and + removes the signs. + + *ShowMarksPlaceMark* +:ShowMarksPlaceMark + This command will place the next available mark on the current line. This + effectively automates mark placement so you don't have to remember which + marks are placed or not. Hidden marks are considered to be available. + NOTE: Only marks a-z are supported by this function. + +=============================================================================== +6. ChangeLog *showmarks-changelog* + +2.2 - 2004-08-17 + Fixed highlighting of the A-Z marks when ignorecase is on. (Mike Kelly) + Fixed the delay with ShowMarks triggering when entering a buffer for the + first time. (Mikolaj Machowski) + Added support for highlighting the entire line where a mark is placed. + Now uses HelpExtractor by Charles E. Campbell to install the help file. + +2.1 - 2004-03-04 + Added ShowMarksOn. It forces ShowMarks to be enabled whether it's on or not. + (Gary Holloway) + Marks now have a definable order of precedence for when mulitple alpha marks + have been placed on the same line. A new highlight group, ShowMarksHLm is + used to identify this situation. (Gary Holloway) + - showmarks_include has changed accordingly. + - ShowMarksHL is now ShowMarksHLl. + ShowMarksPlaceMark now places marks in the order specified by + showmarks_include. (Gary Holloway) + showmarks_include can now be specified per buffer. (Gary Holloway) + +2.0 - 2003-08-11 + Added ability to ignore buffers by type. + Fixed toggling ShowMarks off when switching buffers. + ShowMarksHideMark and ShowMarksHideAll have been renamed to + ShowMarksClearMark and ShowMarksClearAll. + Marks a-z, A-Z and others now have different highlighting from each other. + Added support for all other marks. (Gary Holloway) + Enhanced customization of how marks are displayed by allowing a prefix to + be specified.(Gary Holloway & Anthony Kruize) + Fixed CursorHold autocmd triggering even when ShowMarks is disabled. + (Charles E. Campbell) + +1.5 - 2002-07-16 + Added ability to customize how the marks are displayed. + +1.4 - 2002-05-29 + Added support for placing the next available mark. + (Thanks to Shishir Ramam for the idea) + Added support for hiding all marks. + Marks on line 1 are no longer shown. This stops hidden marks from + reappearing when the file is opened again. + Added a help file. + +1.3 - 2002-05-20 + Fixed toggling ShowMarks not responding immediately. + Added user commands for toggling/hiding marks. + Added ability to disable ShowMarks by default. + +1.2 - 2002-03-06 + Added a check that Vim was compiled with +signs support. + Added the ability to define which marks are shown. + Removed debugging code that was accidently left in. + +1.1 - 2002-02-05 + Added support for the A-Z marks. + Fixed sign staying placed if the line it was on is deleted. + Clear autocommands before making new ones. + +1.0 - 2001-11-20 + First release. + +vim:tw=78:ts=8:ft=help diff --git a/doc/snipMate.txt b/doc/snipMate.txt new file mode 100644 index 0000000..704d44a --- /dev/null +++ b/doc/snipMate.txt @@ -0,0 +1,286 @@ +*snipMate.txt* Plugin for using TextMate-style snippets in Vim. + +snipMate *snippet* *snippets* *snipMate* +Last Change: July 13, 2009 + +|snipMate-description| Description +|snipMate-syntax| Snippet syntax +|snipMate-usage| Usage +|snipMate-settings| Settings +|snipMate-features| Features +|snipMate-disadvantages| Disadvantages to TextMate +|snipMate-contact| Contact + +For Vim version 7.0 or later. +This plugin only works if 'compatible' is not set. +{Vi does not have any of these features.} + +============================================================================== +DESCRIPTION *snipMate-description* + +snipMate.vim implements some of TextMate's snippets features in Vim. A +snippet is a piece of often-typed text that you can insert into your +document using a trigger word followed by a . + +For instance, in a C file using the default installation of snipMate.vim, if +you type "for" in insert mode, it will expand a typical for loop in C: > + + for (i = 0; i < count; i++) { + + } + + +To go to the next item in the loop, simply over to it; if there is +repeated code, such as the "i" variable in this example, you can simply +start typing once it's highlighted and all the matches specified in the +snippet will be updated. To go in reverse, use . + +============================================================================== +SYNTAX *snippet-syntax* + +Snippets can be defined in two ways. They can be in their own file, named +after their trigger in 'snippets//.snippet', or they can be +defined together in a 'snippets/.snippets' file. Note that dotted +'filetype' syntax is supported -- e.g., you can use > + + :set ft=html.eruby + +to activate snippets for both HTML and eRuby for the current file. + +The syntax for snippets in *.snippets files is the following: > + + snippet trigger + expanded text + more expanded text + +Note that the first hard tab after the snippet trigger is required, and not +expanded in the actual snippet. The syntax for *.snippet files is the same, +only without the trigger declaration and starting indentation. + +Also note that snippets must be defined using hard tabs. They can be expanded +to spaces later if desired (see |snipMate-indenting|). + +"#" is used as a line-comment character in *.snippets files; however, they can +only be used outside of a snippet declaration. E.g.: > + + # this is a correct comment + snippet trigger + expanded text + snippet another_trigger + # this isn't a comment! + expanded text +< +This should hopefully be obvious with the included syntax highlighting. + + *snipMate-${#}* +Tab stops ~ + +By default, the cursor is placed at the end of a snippet. To specify where the +cursor is to be placed next, use "${#}", where the # is the number of the tab +stop. E.g., to place the cursor first on the id of a
tag, and then allow +the user to press to go to the middle of it: + > + snippet div +
+ ${2} +
+< + *snipMate-placeholders* *snipMate-${#:}* *snipMate-$#* +Placeholders ~ + +Placeholder text can be supplied using "${#:text}", where # is the number of +the tab stop. This text then can be copied throughout the snippet using "$#", +given # is the same number as used before. So, to make a C for loop: > + + snippet for + for (${2:i}; $2 < ${1:count}; $1++) { + ${4} + } + +This will cause "count" to first be selected and change if the user starts +typing. When is pressed, the "i" in ${2}'s position will be selected; +all $2 variables will default to "i" and automatically be updated if the user +starts typing. +NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate. + +Variables within variables are also possible. For instance: > + + snippet opt + + +Will, as usual, cause "option" to first be selected and update all the $1 +variables if the user starts typing. Since one of these variables is inside of +${2}, this text will then be used as a placeholder for the next tab stop, +allowing the user to change it if he wishes. + +To copy a value throughout a snippet without supplying default text, simply +use the "${#:}" construct without the text; e.g.: > + + snippet foo + ${1:}bar$1 +< *snipMate-commands* +Interpolated Vim Script ~ + +Snippets can also contain Vim script commands that are executed (via |eval()|) +when the snippet is inserted. Commands are given inside backticks (`...`); for +TextMates's functionality, use the |system()| function. E.g.: > + + snippet date + `system("date +%Y-%m-%d")` + +will insert the current date, assuming you are on a Unix system. Note that you +can also (and should) use |strftime()| for this example. + +Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()* + +Since the current filename is used often in snippets, a default function +has been defined for it in snipMate.vim, appropriately called Filename(). + +With no arguments, the default filename without an extension is returned; +the first argument specifies what to place before or after the filename, +and the second argument supplies the default text to be used if the file +has not been named. "$1" in the first argument is replaced with the filename; +if you only want the filename to be returned, the first argument can be left +blank. Examples: > + + snippet filename + `Filename()` + snippet filename_with_default + `Filename('', 'name')` + snippet filename_foo + `filename('$1_foo')` + +The first example returns the filename if it the file has been named, and an +empty string if it hasn't. The second returns the filename if it's been named, +and "name" if it hasn't. The third returns the filename followed by "_foo" if +it has been named, and an empty string if it hasn't. + + *multi_snip* +To specify that a snippet can have multiple matches in a *.snippets file, use +this syntax: > + + snippet trigger A description of snippet #1 + expand this text + snippet trigger A description of snippet #2 + expand THIS text! + +In this example, when "trigger" is typed, a numbered menu containing all +of the descriptions of the "trigger" will be shown; when the user presses the +corresponding number, that snippet will then be expanded. + +To create a snippet with multiple matches using *.snippet files, +simply place all the snippets in a subdirectory with the trigger name: +'snippets///.snippet'. + +============================================================================== +USAGE *snipMate-usage* + + *'snippets'* *g:snippets_dir* +Snippets are by default looked for any 'snippets' directory in your +'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or +'$HOME\vimfiles\snippets\' on Windows. To change that location or add another +one, change the g:snippets_dir variable in your |.vimrc| to your preferred +directory, or use the |ExtractSnips()|function. This will be used by the +|globpath()| function, and so accepts the same syntax as it (e.g., +comma-separated paths). + +ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets* + +ExtractSnipsFile() extracts the specified *.snippets file for the given +filetype. A .snippets file contains multiple snippet declarations for the +filetype. It is further explained above, in |snippet-syntax|. + +ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet* + +ExtractSnips() extracts *.snippet files from the specified directory and +defines them as snippets for the given filetype. The directory tree should +look like this: 'snippets//.snippet'. If the snippet has +multiple matches, it should look like this: +'snippets///.snippet' (see |multi_snip|). + + *ResetSnippets()* +The ResetSnippets() function removes all snippets from memory. This is useful +to put at the top of a snippet setup file for if you would like to |:source| +it multiple times. + + *list-snippets* *i_CTRL-R_* +If you would like to see what snippets are available, simply type +in the current buffer to show a list via |popupmenu-completion|. + +============================================================================== +SETTINGS *snipMate-settings* *g:snips_author* + +The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set +to your name; it can then be used in snippets to automatically add it. E.g.: > + + let g:snips_author = 'Hubert Farnsworth' + snippet name + `g:snips_author` +< + *snipMate-expandtab* *snipMate-indenting* +If you would like your snippets to be expanded using spaces instead of tabs, +just enable 'expandtab' and set 'softtabstop' to your preferred amount of +spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead. + + *snipMate-remap* +snipMate does not come with a setting to customize the trigger key, but you +can remap it easily in the two lines it's defined in the 'after' directory +under 'plugin/snipMate.vim'. For instance, to change the trigger key +to CTRL-J, just change this: > + + ino =TriggerSnippet() + snor i=TriggerSnippet() + +to this: > + ino =TriggerSnippet() + snor i=TriggerSnippet() + +============================================================================== +FEATURES *snipMate-features* + +snipMate.vim has the following features among others: + - The syntax of snippets is very similar to TextMate's, allowing + easy conversion. + - The position of the snippet is kept transparently (i.e. it does not use + markers/placeholders written to the buffer), which allows you to escape + out of an incomplete snippet, something particularly useful in Vim. + - Variables in snippets are updated as-you-type. + - Snippets can have multiple matches. + - Snippets can be out of order. For instance, in a do...while loop, the + condition can be added before the code. + - [New] File-based snippets are supported. + - [New] Triggers after non-word delimiters are expanded, e.g. "foo" + in "bar.foo". + - [New] can now be used to jump tab stops in reverse order. + +============================================================================== +DISADVANTAGES *snipMate-disadvantages* + +snipMate.vim currently has the following disadvantages to TextMate's snippets: + - There is no $0; the order of tab stops must be explicitly stated. + - Placeholders within placeholders are not possible. E.g.: > + + '${3}
' +< + In TextMate this would first highlight ' id="some_id"', and if + you hit delete it would automatically skip ${2} and go to ${3} + on the next , but if you didn't delete it it would highlight + "some_id" first. You cannot do this in snipMate.vim. + - Regex cannot be performed on variables, such as "${1/.*/\U&}" + - Placeholders cannot span multiple lines. + - Activating snippets in different scopes of the same file is + not possible. + +Perhaps some of these features will be added in a later release. + +============================================================================== +CONTACT *snipMate-contact* *snipMate-author* + +To contact the author (Michael Sanders), please email: + msanders42+snipmate gmail com + +I greatly appreciate any suggestions or improvements offered for the script. + +============================================================================== + +vim:tw=78:ts=8:ft=help:norl: diff --git a/doc/taglist.txt b/doc/taglist.txt new file mode 100644 index 0000000..6a62b39 --- /dev/null +++ b/doc/taglist.txt @@ -0,0 +1,1501 @@ +*taglist.txt* Plugin for browsing source code + +Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +For Vim version 6.0 and above +Last change: 2007 May 24 + +1. Overview |taglist-intro| +2. Taglist on the internet |taglist-internet| +3. Requirements |taglist-requirements| +4. Installation |taglist-install| +5. Usage |taglist-using| +6. Options |taglist-options| +7. Commands |taglist-commands| +8. Global functions |taglist-functions| +9. Extending |taglist-extend| +10. FAQ |taglist-faq| +11. License |taglist-license| +12. Todo |taglist-todo| + +============================================================================== + *taglist-intro* +1. Overview~ + +The "Tag List" plugin is a source code browser plugin for Vim. This plugin +allows you to efficiently browse through source code files for different +programming languages. The "Tag List" plugin provides the following features: + + * Displays the tags (functions, classes, structures, variables, etc.) + defined in a file in a vertically or horizontally split Vim window. + * In GUI Vim, optionally displays the tags in the Tags drop-down menu and + in the popup menu. + * Automatically updates the taglist window as you switch between + files/buffers. As you open new files, the tags defined in the new files + are added to the existing file list and the tags defined in all the + files are displayed grouped by the filename. + * When a tag name is selected from the taglist window, positions the + cursor at the definition of the tag in the source file. + * Automatically highlights the current tag name. + * Groups the tags by their type and displays them in a foldable tree. + * Can display the prototype and scope of a tag. + * Can optionally display the tag prototype instead of the tag name in the + taglist window. + * The tag list can be sorted either by name or by chronological order. + * Supports the following language files: Assembly, ASP, Awk, Beta, C, + C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, + Lua, Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, + SML, Sql, TCL, Verilog, Vim and Yacc. + * Can be easily extended to support new languages. Support for + existing languages can be modified easily. + * Provides functions to display the current tag name in the Vim status + line or the window title bar. + * The list of tags and files in the taglist can be saved and + restored across Vim sessions. + * Provides commands to get the name and prototype of the current tag. + * Runs in both console/terminal and GUI versions of Vim. + * Works with the winmanager plugin. Using the winmanager plugin, you + can use Vim plugins like the file explorer, buffer explorer and the + taglist plugin at the same time like an IDE. + * Can be used in both Unix and MS-Windows systems. + +============================================================================== + *taglist-internet* +2. Taglist on the internet~ + +The home page of the taglist plugin is at: +> + http://vim-taglist.sourceforge.net/ +< +You can subscribe to the taglist mailing list to post your questions or +suggestions for improvement or to send bug reports. Visit the following page +for subscribing to the mailing list: +> + http://groups.yahoo.com/group/taglist +< +============================================================================== + *taglist-requirements* +3. Requirements~ + +The taglist plugin requires the following: + + * Vim version 6.0 and above + * Exuberant ctags 5.0 and above + +The taglist plugin will work on all the platforms where the exuberant ctags +utility and Vim are supported (this includes MS-Windows and Unix based +systems). + +The taglist plugin relies on the exuberant ctags utility to dynamically +generate the tag listing. The exuberant ctags utility must be installed in +your system to use this plugin. The exuberant ctags utility is shipped with +most of the Linux distributions. You can download the exuberant ctags utility +from +> + http://ctags.sourceforge.net +< +The taglist plugin doesn't use or create a tags file and there is no need to +create a tags file to use this plugin. The taglist plugin will not work with +the GNU ctags or the Unix ctags utility. + +This plugin relies on the Vim "filetype" detection mechanism to determine the +type of the current file. You have to turn on the Vim filetype detection by +adding the following line to your .vimrc file: +> + filetype on +< +The taglist plugin will not work if you run Vim in the restricted mode (using +the -Z command-line argument). + +The taglist plugin uses the Vim system() function to invoke the exuberant +ctags utility. If Vim is compiled without the system() function then you +cannot use the taglist plugin. Some of the Linux distributions (Suse) compile +Vim without the system() function for security reasons. + +============================================================================== + *taglist-install* +4. Installation~ + +1. Download the taglist.zip file and unzip the files to the $HOME/.vim or the + $HOME/vimfiles or the $VIM/vimfiles directory. After this step, you should + have the following two files (the directory structure should be preserved): + + plugin/taglist.vim - main taglist plugin file + doc/taglist.txt - documentation (help) file + + Refer to the |add-plugin|and |'runtimepath'| Vim help pages for more + details about installing Vim plugins. +2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or $VIM/vimfiles/doc + directory, start Vim and run the ":helptags ." command to process the + taglist help file. Without this step, you cannot jump to the taglist help + topics. +3. If the exuberant ctags utility is not present in one of the directories in + the PATH environment variable, then set the 'Tlist_Ctags_Cmd' variable to + point to the location of the exuberant ctags utility (not to the directory) + in the .vimrc file. +4. If you are running a terminal/console version of Vim and the terminal + doesn't support changing the window width then set the + 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file. +5. Restart Vim. +6. You can now use the ":TlistToggle" command to open/close the taglist + window. You can use the ":help taglist" command to get more information + about using the taglist plugin. + +To uninstall the taglist plugin, remove the plugin/taglist.vim and +doc/taglist.txt files from the $HOME/.vim or $HOME/vimfiles directory. + +============================================================================== + *taglist-using* +5. Usage~ + +The taglist plugin can be used in several different ways. + +1. You can keep the taglist window open during the entire editing session. On + opening the taglist window, the tags defined in all the files in the Vim + buffer list will be displayed in the taglist window. As you edit files, the + tags defined in them will be added to the taglist window. You can select a + tag from the taglist window and jump to it. The current tag will be + highlighted in the taglist window. You can close the taglist window when + you no longer need the window. +2. You can configure the taglist plugin to process the tags defined in all the + edited files always. In this configuration, even if the taglist window is + closed and the taglist menu is not displayed, the taglist plugin will + processes the tags defined in newly edited files. You can then open the + taglist window only when you need to select a tag and then automatically + close the taglist window after selecting the tag. +3. You can configure the taglist plugin to display only the tags defined in + the current file in the taglist window. By default, the taglist plugin + displays the tags defined in all the files in the Vim buffer list. As you + switch between files, the taglist window will be refreshed to display only + the tags defined in the current file. +4. In GUI Vim, you can use the Tags pull-down and popup menu created by the + taglist plugin to display the tags defined in the current file and select a + tag to jump to it. You can use the menu without opening the taglist window. + By default, the Tags menu is disabled. +5. You can configure the taglist plugin to display the name of the current tag + in the Vim window status line or in the Vim window title bar. For this to + work without the taglist window or menu, you need to configure the taglist + plugin to process the tags defined in a file always. +6. You can save the tags defined in multiple files to a taglist session file + and load it when needed. You can also configure the taglist plugin to not + update the taglist window when editing new files. You can then manually add + files to the taglist window. + +Opening the taglist window~ +You can open the taglist window using the ":TlistOpen" or the ":TlistToggle" +commands. The ":TlistOpen" command opens the taglist window and jumps to it. +The ":TlistToggle" command opens or closes (toggle) the taglist window and the +cursor remains in the current window. If the 'Tlist_GainFocus_On_ToggleOpen' +variable is set to 1, then the ":TlistToggle" command opens the taglist window +and moves the cursor to the taglist window. + +You can map a key to invoke these commands. For example, the following command +creates a normal mode mapping for the key to toggle the taglist window. +> + nnoremap :TlistToggle +< +Add the above mapping to your ~/.vimrc or $HOME/_vimrc file. + +To automatically open the taglist window on Vim startup, set the +'Tlist_Auto_Open' variable to 1. + +You can also open the taglist window on startup using the following command +line: +> + $ vim +TlistOpen +< +Closing the taglist window~ +You can close the taglist window from the taglist window by pressing 'q' or +using the Vim ":q" command. You can also use any of the Vim window commands to +close the taglist window. Invoking the ":TlistToggle" command when the taglist +window is opened, closes the taglist window. You can also use the +":TlistClose" command to close the taglist window. + +To automatically close the taglist window when a tag or file is selected, you +can set the 'Tlist_Close_On_Select' variable to 1. To exit Vim when only the +taglist window is present, set the 'Tlist_Exit_OnlyWindow' variable to 1. + +Jumping to a tag or a file~ +You can select a tag in the taglist window either by pressing the key +or by double clicking the tag name using the mouse. To jump to a tag on a +single mouse click set the 'Tlist_Use_SingleClick' variable to 1. + +If the selected file is already opened in a window, then the cursor is moved +to that window. If the file is not currently opened in a window then the file +is opened in the window used by the taglist plugin to show the previously +selected file. If there are no usable windows, then the file is opened in a +new window. The file is not opened in special windows like the quickfix +window, preview window and windows containing buffer with the 'buftype' option +set. + +To jump to the tag in a new window, press the 'o' key. To open the file in the +previous window (Ctrl-W_p) use the 'P' key. You can press the 'p' key to jump +to the tag but still keep the cursor in the taglist window (preview). + +To open the selected file in a tab, use the 't' key. If the file is already +present in a tab then the cursor is moved to that tab otherwise the file is +opened in a new tab. To jump to a tag in a new tab press Ctrl-t. The taglist +window is automatically opened in the newly created tab. + +Instead of jumping to a tag, you can open a file by pressing the key +or by double clicking the file name using the mouse. + +In the taglist window, you can use the [[ or key to jump to the +beginning of the previous file. You can use the ]] or key to jump to the +beginning of the next file. When you reach the first or last file, the search +wraps around and the jumps to the next/previous file. + +Highlighting the current tag~ +The taglist plugin automatically highlights the name of the current tag in the +taglist window. The Vim |CursorHold| autocmd event is used for this. If the +current tag name is not visible in the taglist window, then the taglist window +contents are scrolled to make that tag name visible. You can also use the +":TlistHighlightTag" command to force the highlighting of the current tag. + +The tag name is highlighted if no activity is performed for |'updatetime'| +milliseconds. The default value for this Vim option is 4 seconds. To avoid +unexpected problems, you should not set the |'updatetime'| option to a very +low value. + +To disable the automatic highlighting of the current tag name in the taglist +window, set the 'Tlist_Auto_Highlight_Tag' variable to zero. + +When entering a Vim buffer/window, the taglist plugin automatically highlights +the current tag in that buffer/window. If you like to disable the automatic +highlighting of the current tag when entering a buffer, set the +'Tlist_Highlight_Tag_On_BufEnter' variable to zero. + +Adding files to the taglist~ +When the taglist window is opened, all the files in the Vim buffer list are +processed and the supported files are added to the taglist. When you edit a +file in Vim, the taglist plugin automatically processes this file and adds it +to the taglist. If you close the taglist window, the tag information in the +taglist is retained. + +To process files even when the taglist window is not open, set the +'Tlist_Process_File_Always' variable to 1. + +You can manually add multiple files to the taglist without opening them using +the ":TlistAddFiles" and the ":TlistAddFilesRecursive" commands. + +For example, to add all the C files in the /my/project/dir directory to the +taglist, you can use the following command: +> + :TlistAddFiles /my/project/dir/*.c +< +Note that when adding several files with a large number of tags or a large +number of files, it will take several seconds to several minutes for the +taglist plugin to process all the files. You should not interrupt the taglist +plugin by pressing . + +You can recursively add multiple files from a directory tree using the +":TlistAddFilesRecursive" command: +> + :TlistAddFilesRecursive /my/project/dir *.c +< +This command takes two arguments. The first argument specifies the directory +from which to recursively add the files. The second optional argument +specifies the wildcard matching pattern for selecting the files to add. The +default pattern is * and all the files are added. + +Displaying tags for only one file~ +The taglist window displays the tags for all the files in the Vim buffer list +and all the manually added files. To display the tags for only the current +active buffer, set the 'Tlist_Show_One_File' variable to 1. + +Removing files from the taglist~ +You can remove a file from the taglist window, by pressing the 'd' key when the +cursor is on one of the tags listed for the file in the taglist window. The +removed file will no longer be displayed in the taglist window in the current +Vim session. To again display the tags for the file, open the file in a Vim +window and then use the ":TlistUpdate" command or use ":TlistAddFiles" command +to add the file to the taglist. + +When a buffer is removed from the Vim buffer list using the ":bdelete" or the +":bwipeout" command, the taglist is updated to remove the stored information +for this buffer. + +Updating the tags displayed for a file~ +The taglist plugin keeps track of the modification time of a file. When the +modification time changes (the file is modified), the taglist plugin +automatically updates the tags listed for that file. The modification time of +a file is checked when you enter a window containing that file or when you +load that file. + +You can also update or refresh the tags displayed for a file by pressing the +"u" key in the taglist window. If an existing file is modified, after the file +is saved, the taglist plugin automatically updates the tags displayed for the +file. + +You can also use the ":TlistUpdate" command to update the tags for the current +buffer after you made some changes to it. You should save the modified buffer +before you update the taglist window. Otherwise the listed tags will not +include the new tags created in the buffer. + +If you have deleted the tags displayed for a file in the taglist window using +the 'd' key, you can again display the tags for that file using the +":TlistUpdate" command. + +Controlling the taglist updates~ +To disable the automatic processing of new files or modified files, you can +set the 'Tlist_Auto_Update' variable to zero. When this variable is set to +zero, the taglist is updated only when you use the ":TlistUpdate" command or +the ":TlistAddFiles" or the ":TlistAddFilesRecursive" commands. You can use +this option to control which files are added to the taglist. + +You can use the ":TlistLock" command to lock the taglist contents. After this +command is executed, new files are not automatically added to the taglist. +When the taglist is locked, you can use the ":TlistUpdate" command to add the +current file or the ":TlistAddFiles" or ":TlistAddFilesRecursive" commands to +add new files to the taglist. To unlock the taglist, use the ":TlistUnlock" +command. + +Displaying the tag prototype~ +To display the prototype of the tag under the cursor in the taglist window, +press the space bar. If you place the cursor on a tag name in the taglist +window, then the tag prototype is displayed at the Vim status line after +|'updatetime'| milliseconds. The default value for the |'updatetime'| Vim +option is 4 seconds. + +You can get the name and prototype of a tag without opening the taglist window +and the taglist menu using the ":TlistShowTag" and the ":TlistShowPrototype" +commands. These commands will work only if the current file is already present +in the taglist. To use these commands without opening the taglist window, set +the 'Tlist_Process_File_Always' variable to 1. + +You can use the ":TlistShowTag" command to display the name of the tag at or +before the specified line number in the specified file. If the file name and +line number are not supplied, then this command will display the name of the +current tag. For example, +> + :TlistShowTag + :TlistShowTag myfile.java 100 +< +You can use the ":TlistShowPrototype" command to display the prototype of the +tag at or before the specified line number in the specified file. If the file +name and the line number are not supplied, then this command will display the +prototype of the current tag. For example, +> + :TlistShowPrototype + :TlistShowPrototype myfile.c 50 +< +In the taglist window, when the mouse is moved over a tag name, the tag +prototype is displayed in a balloon. This works only in GUI versions where +balloon evaluation is supported. + +Taglist window contents~ +The taglist window contains the tags defined in various files in the taglist +grouped by the filename and by the tag type (variable, function, class, etc.). +For tags with scope information (like class members, structures inside +structures, etc.), the scope information is displayed in square brackets "[]" +after the tag name. + +The contents of the taglist buffer/window are managed by the taglist plugin. +The |'filetype'| for the taglist buffer is set to 'taglist'. The Vim +|'modifiable'| option is turned off for the taglist buffer. You should not +manually edit the taglist buffer, by setting the |'modifiable'| flag. If you +manually edit the taglist buffer contents, then the taglist plugin will be out +of sync with the taglist buffer contents and the plugin will no longer work +correctly. To redisplay the taglist buffer contents again, close the taglist +window and reopen it. + +Opening and closing the tag and file tree~ +In the taglist window, the tag names are displayed as a foldable tree using +the Vim folding support. You can collapse the tree using the '-' key or using +the Vim |zc| fold command. You can open the tree using the '+' key or using +the Vim |zo| fold command. You can open all the folds using the '*' key or +using the Vim |zR| fold command. You can also use the mouse to open/close the +folds. You can close all the folds using the '=' key. You should not manually +create or delete the folds in the taglist window. + +To automatically close the fold for the inactive files/buffers and open only +the fold for the current buffer in the taglist window, set the +'Tlist_File_Fold_Auto_Close' variable to 1. + +Sorting the tags for a file~ +The tags displayed in the taglist window can be sorted either by their name or +by their chronological order. The default sorting method is by the order in +which the tags appear in a file. You can change the default sort method by +setting the 'Tlist_Sort_Type' variable to either "name" or "order". You can +sort the tags by their name by pressing the "s" key in the taglist window. You +can again sort the tags by their chronological order using the "s" key. Each +file in the taglist window can be sorted using different order. + +Zooming in and out of the taglist window~ +You can press the 'x' key in the taglist window to maximize the taglist +window width/height. The window will be maximized to the maximum possible +width/height without closing the other existing windows. You can again press +'x' to restore the taglist window to the default width/height. + + *taglist-session* +Taglist Session~ +A taglist session refers to the group of files and their tags stored in the +taglist in a Vim session. + +You can save and restore a taglist session (and all the displayed tags) using +the ":TlistSessionSave" and ":TlistSessionLoad" commands. + +To save the information about the tags and files in the taglist to a file, use +the ":TlistSessionSave" command and specify the filename: +> + :TlistSessionSave +< +To load a saved taglist session, use the ":TlistSessionLoad" command: > + + :TlistSessionLoad +< +When you load a taglist session file, the tags stored in the file will be +added to the tags already stored in the taglist. + +The taglist session feature can be used to save the tags for large files or a +group of frequently used files (like a project). By using the taglist session +file, you can minimize the amount to time it takes to load/refresh the taglist +for multiple files. + +You can create more than one taglist session file for multiple groups of +files. + +Displaying the tag name in the Vim status line or the window title bar~ +You can use the Tlist_Get_Tagname_By_Line() function provided by the taglist +plugin to display the current tag name in the Vim status line or the window +title bar. Similarly, you can use the Tlist_Get_Tag_Prototype_By_Line() +function to display the current tag prototype in the Vim status line or the +window title bar. + +For example, the following command can be used to display the current tag name +in the status line: +> + :set statusline=%<%f%=%([%{Tlist_Get_Tagname_By_Line()}]%) +< +The following command can be used to display the current tag name in the +window title bar: +> + :set title titlestring=%<%f\ %([%{Tlist_Get_Tagname_By_Line()}]%) +< +Note that the current tag name can be displayed only after the file is +processed by the taglist plugin. For this, you have to either set the +'Tlist_Process_File_Always' variable to 1 or open the taglist window or use +the taglist menu. For more information about configuring the Vim status line, +refer to the documentation for the Vim |'statusline'| option. + +Changing the taglist window highlighting~ +The following Vim highlight groups are defined and used to highlight the +various entities in the taglist window: + + TagListTagName - Used for tag names + TagListTagScope - Used for tag scope + TagListTitle - Used for tag titles + TagListComment - Used for comments + TagListFileName - Used for filenames + +By default, these highlight groups are linked to the standard Vim highlight +groups. If you want to change the colors used for these highlight groups, +prefix the highlight group name with 'My' and define it in your .vimrc or +.gvimrc file: MyTagListTagName, MyTagListTagScope, MyTagListTitle, +MyTagListComment and MyTagListFileName. For example, to change the colors +used for tag names, you can use the following command: +> + :highlight MyTagListTagName guifg=blue ctermfg=blue +< +Controlling the taglist window~ +To use a horizontally split taglist window, instead of a vertically split +window, set the 'Tlist_Use_Horiz_Window' variable to 1. + +To use a vertically split taglist window on the rightmost side of the Vim +window, set the 'Tlist_Use_Right_Window' variable to 1. + +You can specify the width of the vertically split taglist window, by setting +the 'Tlist_WinWidth' variable. You can specify the height of the horizontally +split taglist window, by setting the 'Tlist_WinHeight' variable. + +When opening a vertically split taglist window, the Vim window width is +increased to accommodate the new taglist window. When the taglist window is +closed, the Vim window is reduced. To disable this, set the +'Tlist_Inc_Winwidth' variable to zero. + +To reduce the number of empty lines in the taglist window, set the +'Tlist_Compact_Format' variable to 1. + +To not display the Vim fold column in the taglist window, set the +'Tlist_Enable_Fold_Column' variable to zero. + +To display the tag prototypes instead of the tag names in the taglist window, +set the 'Tlist_Display_Prototype' variable to 1. + +To not display the scope of the tags next to the tag names, set the +'Tlist_Display_Tag_Scope' variable to zero. + + *taglist-keys* +Taglist window key list~ +The following table lists the description of the keys that can be used +in the taglist window. + + Key Description~ + + Jump to the location where the tag under cursor is + defined. + o Jump to the location where the tag under cursor is + defined in a new window. + P Jump to the tag in the previous (Ctrl-W_p) window. + p Display the tag definition in the file window and + keep the cursor in the taglist window itself. + t Jump to the tag in a new tab. If the file is already + opened in a tab, move to that tab. + Ctrl-t Jump to the tag in a new tab. + Display the prototype of the tag under the cursor. + For file names, display the full path to the file, + file type and the number of tags. For tag types, display the + tag type and the number of tags. + u Update the tags listed in the taglist window + s Change the sort order of the tags (by name or by order) + d Remove the tags for the file under the cursor + x Zoom-in or Zoom-out the taglist window + + Open a fold + - Close a fold + * Open all folds + = Close all folds + [[ Jump to the beginning of the previous file + Jump to the beginning of the previous file + ]] Jump to the beginning of the next file + Jump to the beginning of the next file + q Close the taglist window + Display help + +The above keys will work in both the normal mode and the insert mode. + + *taglist-menu* +Taglist menu~ +When using GUI Vim, the taglist plugin can display the tags defined in the +current file in the drop-down menu and the popup menu. By default, this +feature is turned off. To turn on this feature, set the 'Tlist_Show_Menu' +variable to 1. + +You can jump to a tag by selecting the tag name from the menu. You can use the +taglist menu independent of the taglist window i.e. you don't need to open the +taglist window to get the taglist menu. + +When you switch between files/buffers, the taglist menu is automatically +updated to display the tags defined in the current file/buffer. + +The tags are grouped by their type (variables, functions, classes, methods, +etc.) and displayed as a separate sub-menu for each type. If all the tags +defined in a file are of the same type (e.g. functions), then the sub-menu is +not used. + +If the number of items in a tag type submenu exceeds the value specified by +the 'Tlist_Max_Submenu_Items' variable, then the submenu will be split into +multiple submenus. The default setting for 'Tlist_Max_Submenu_Items' is 25. +The first and last tag names in the submenu are used to form the submenu name. +The menu items are prefixed by alpha-numeric characters for easy selection by +keyboard. + +If the popup menu support is enabled (the |'mousemodel'| option contains +"popup"), then the tags menu is added to the popup menu. You can access +the popup menu by right clicking on the GUI window. + +You can regenerate the tags menu by selecting the 'Tags->Refresh menu' entry. +You can sort the tags listed in the menu either by name or by order by +selecting the 'Tags->Sort menu by->Name/Order' menu entry. + +You can tear-off the Tags menu and keep it on the side of the Vim window +for quickly locating the tags. + +Using the taglist plugin with the winmanager plugin~ +You can use the taglist plugin with the winmanager plugin. This will allow you +to use the file explorer, buffer explorer and the taglist plugin at the same +time in different windows. To use the taglist plugin with the winmanager +plugin, set 'TagList' in the 'winManagerWindowLayout' variable. For example, +to use the file explorer plugin and the taglist plugin at the same time, use +the following setting: > + + let winManagerWindowLayout = 'FileExplorer|TagList' +< +Getting help~ +If you have installed the taglist help file (this file), then you can use the +Vim ":help taglist-" command to get help on the various taglist +topics. + +You can press the key in the taglist window to display the help +information about using the taglist window. If you again press the key, +the help information is removed from the taglist window. + + *taglist-debug* +Debugging the taglist plugin~ +You can use the ":TlistDebug" command to enable logging of the debug messages +from the taglist plugin. To display the logged debug messages, you can use the +":TlistMessages" command. To disable the logging of the debug messages, use +the ":TlistUndebug" command. + +You can specify a file name to the ":TlistDebug" command to log the debug +messages to a file. Otherwise, the debug messages are stored in a script-local +variable. In the later case, to minimize memory usage, only the last 3000 +characters from the debug messages are stored. + +============================================================================== + *taglist-options* +6. Options~ + +A number of Vim variables control the behavior of the taglist plugin. These +variables are initialized to a default value. By changing these variables you +can change the behavior of the taglist plugin. You need to change these +settings only if you want to change the behavior of the taglist plugin. You +should use the |:let| command in your .vimrc file to change the setting of any +of these variables. + +The configurable taglist variables are listed below. For a detailed +description of these variables refer to the text below this table. + +|'Tlist_Auto_Highlight_Tag'| Automatically highlight the current tag in the + taglist. +|'Tlist_Auto_Open'| Open the taglist window when Vim starts. +|'Tlist_Auto_Update'| Automatically update the taglist to include + newly edited files. +|'Tlist_Close_On_Select'| Close the taglist window when a file or tag is + selected. +|'Tlist_Compact_Format'| Remove extra information and blank lines from + the taglist window. +|'Tlist_Ctags_Cmd'| Specifies the path to the ctags utility. +|'Tlist_Display_Prototype'| Show prototypes and not tags in the taglist + window. +|'Tlist_Display_Tag_Scope'| Show tag scope next to the tag name. +|'Tlist_Enable_Fold_Column'| Show the fold indicator column in the taglist + window. +|'Tlist_Exit_OnlyWindow'| Close Vim if the taglist is the only window. +|'Tlist_File_Fold_Auto_Close'| Close tag folds for inactive buffers. +|'Tlist_GainFocus_On_ToggleOpen'| + Jump to taglist window on open. +|'Tlist_Highlight_Tag_On_BufEnter'| + On entering a buffer, automatically highlight + the current tag. +|'Tlist_Inc_Winwidth'| Increase the Vim window width to accommodate + the taglist window. +|'Tlist_Max_Submenu_Items'| Maximum number of items in a tags sub-menu. +|'Tlist_Max_Tag_Length'| Maximum tag length used in a tag menu entry. +|'Tlist_Process_File_Always'| Process files even when the taglist window is + closed. +|'Tlist_Show_Menu'| Display the tags menu. +|'Tlist_Show_One_File'| Show tags for the current buffer only. +|'Tlist_Sort_Type'| Sort method used for arranging the tags. +|'Tlist_Use_Horiz_Window'| Use a horizontally split window for the + taglist window. +|'Tlist_Use_Right_Window'| Place the taglist window on the right side. +|'Tlist_Use_SingleClick'| Single click on a tag jumps to it. +|'Tlist_WinHeight'| Horizontally split taglist window height. +|'Tlist_WinWidth'| Vertically split taglist window width. + + *'Tlist_Auto_Highlight_Tag'* +Tlist_Auto_Highlight_Tag~ +The taglist plugin will automatically highlight the current tag in the taglist +window. If you want to disable this, then you can set the +'Tlist_Auto_Highlight_Tag' variable to zero. Note that even though the current +tag highlighting is disabled, the tags for a new file will still be added to +the taglist window. +> + let Tlist_Auto_Highlight_Tag = 0 +< +With the above variable set to 1, you can use the ":TlistHighlightTag" command +to highlight the current tag. + + *'Tlist_Auto_Open'* +Tlist_Auto_Open~ +To automatically open the taglist window, when you start Vim, you can set the +'Tlist_Auto_Open' variable to 1. By default, this variable is set to zero and +the taglist window will not be opened automatically on Vim startup. +> + let Tlist_Auto_Open = 1 +< +The taglist window is opened only when a supported type of file is opened on +Vim startup. For example, if you open text files, then the taglist window will +not be opened. + + *'Tlist_Auto_Update'* +Tlist_Auto_Update~ +When a new file is edited, the tags defined in the file are automatically +processed and added to the taglist. To stop adding new files to the taglist, +set the 'Tlist_Auto_Update' variable to zero. By default, this variable is set +to 1. +> + let Tlist_Auto_Update = 0 +< +With the above variable set to 1, you can use the ":TlistUpdate" command to +add the tags defined in the current file to the taglist. + + *'Tlist_Close_On_Select'* +Tlist_Close_On_Select~ +If you want to close the taglist window when a file or tag is selected, then +set the 'Tlist_Close_On_Select' variable to 1. By default, this variable is +set zero and when you select a tag or file from the taglist window, the window +is not closed. +> + let Tlist_Close_On_Select = 1 +< + *'Tlist_Compact_Format'* +Tlist_Compact_Format~ +By default, empty lines are used to separate different tag types displayed for +a file and the tags displayed for different files in the taglist window. If +you want to display as many tags as possible in the taglist window, you can +set the 'Tlist_Compact_Format' variable to 1 to get a compact display. +> + let Tlist_Compact_Format = 1 +< + *'Tlist_Ctags_Cmd'* +Tlist_Ctags_Cmd~ +The 'Tlist_Ctags_Cmd' variable specifies the location (path) of the exuberant +ctags utility. If exuberant ctags is present in any one of the directories in +the PATH environment variable, then there is no need to set this variable. + +The exuberant ctags tool can be installed under different names. When the +taglist plugin starts up, if the 'Tlist_Ctags_Cmd' variable is not set, it +checks for the names exuberant-ctags, exctags, ctags, ctags.exe and tags in +the PATH environment variable. If any one of the named executable is found, +then the Tlist_Ctags_Cmd variable is set to that name. + +If exuberant ctags is not present in one of the directories specified in the +PATH environment variable, then set this variable to point to the location of +the ctags utility in your system. Note that this variable should point to the +fully qualified exuberant ctags location and NOT to the directory in which +exuberant ctags is installed. If the exuberant ctags tool is not found in +either PATH or in the specified location, then the taglist plugin will not be +loaded. Examples: +> + let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe' + let Tlist_Ctags_Cmd = '/usr/local/bin/ctags' +< + *'Tlist_Display_Prototype'* +Tlist_Display_Prototype~ +By default, only the tag name will be displayed in the taglist window. If you +like to see tag prototypes instead of names, set the 'Tlist_Display_Prototype' +variable to 1. By default, this variable is set to zero and only tag names +will be displayed. +> + let Tlist_Display_Prototype = 1 +< + *'Tlist_Display_Tag_Scope'* +Tlist_Display_Tag_Scope~ +By default, the scope of a tag (like a C++ class) will be displayed in +square brackets next to the tag name. If you don't want the tag scopes +to be displayed, then set the 'Tlist_Display_Tag_Scope' to zero. By default, +this variable is set to 1 and the tag scopes will be displayed. +> + let Tlist_Display_Tag_Scope = 0 +< + *'Tlist_Enable_Fold_Column'* +Tlist_Enable_Fold_Column~ +By default, the Vim fold column is enabled and displayed in the taglist +window. If you wish to disable this (for example, when you are working with a +narrow Vim window or terminal), you can set the 'Tlist_Enable_Fold_Column' +variable to zero. +> + let Tlist_Enable_Fold_Column = 1 +< + *'Tlist_Exit_OnlyWindow'* +Tlist_Exit_OnlyWindow~ +If you want to exit Vim if only the taglist window is currently opened, then +set the 'Tlist_Exit_OnlyWindow' variable to 1. By default, this variable is +set to zero and the Vim instance will not be closed if only the taglist window +is present. +> + let Tlist_Exit_OnlyWindow = 1 +< + *'Tlist_File_Fold_Auto_Close'* +Tlist_File_Fold_Auto_Close~ +By default, the tags tree displayed in the taglist window for all the files is +opened. You can close/fold the tags tree for the files manually. To +automatically close the tags tree for inactive files, you can set the +'Tlist_File_Fold_Auto_Close' variable to 1. When this variable is set to 1, +the tags tree for the current buffer is automatically opened and for all the +other buffers is closed. +> + let Tlist_File_Fold_Auto_Close = 1 +< + *'Tlist_GainFocus_On_ToggleOpen'* +Tlist_GainFocus_On_ToggleOpen~ +When the taglist window is opened using the ':TlistToggle' command, this +option controls whether the cursor is moved to the taglist window or remains +in the current window. By default, this option is set to 0 and the cursor +remains in the current window. When this variable is set to 1, the cursor +moves to the taglist window after opening the taglist window. +> + let Tlist_GainFocus_On_ToggleOpen = 1 +< + *'Tlist_Highlight_Tag_On_BufEnter'* +Tlist_Highlight_Tag_On_BufEnter~ +When you enter a Vim buffer/window, the current tag in that buffer/window is +automatically highlighted in the taglist window. If the current tag name is +not visible in the taglist window, then the taglist window contents are +scrolled to make that tag name visible. If you like to disable the automatic +highlighting of the current tag when entering a buffer, you can set the +'Tlist_Highlight_Tag_On_BufEnter' variable to zero. The default setting for +this variable is 1. +> + let Tlist_Highlight_Tag_On_BufEnter = 0 +< + *'Tlist_Inc_Winwidth'* +Tlist_Inc_Winwidth~ +By default, when the width of the window is less than 100 and a new taglist +window is opened vertically, then the window width is increased by the value +set in the 'Tlist_WinWidth' variable to accommodate the new window. The value +of this variable is used only if you are using a vertically split taglist +window. + +If your terminal doesn't support changing the window width from Vim (older +version of xterm running in a Unix system) or if you see any weird problems in +the screen due to the change in the window width or if you prefer not to +adjust the window width then set the 'Tlist_Inc_Winwidth' variable to zero. +CAUTION: If you are using the MS-Windows version of Vim in a MS-DOS command +window then you must set this variable to zero, otherwise the system may hang +due to a Vim limitation (explained in :help win32-problems) +> + let Tlist_Inc_Winwidth = 0 +< + *'Tlist_Max_Submenu_Items'* +Tlist_Max_Submenu_Items~ +If a file contains too many tags of a particular type (function, variable, +class, etc.), greater than that specified by the 'Tlist_Max_Submenu_Items' +variable, then the menu for that tag type will be split into multiple +sub-menus. The default setting for the 'Tlist_Max_Submenu_Items' variable is +25. This can be changed by setting the 'Tlist_Max_Submenu_Items' variable: +> + let Tlist_Max_Submenu_Items = 20 +< +The name of the submenu is formed using the names of the first and the last +tag entries in that submenu. + + *'Tlist_Max_Tag_Length'* +Tlist_Max_Tag_Length~ +Only the first 'Tlist_Max_Tag_Length' characters from the tag names will be +used to form the tag type submenu name. The default value for this variable is +10. Change the 'Tlist_Max_Tag_Length' setting if you want to include more or +less characters: +> + let Tlist_Max_Tag_Length = 10 +< + *'Tlist_Process_File_Always'* +Tlist_Process_File_Always~ +By default, the taglist plugin will generate and process the tags defined in +the newly opened files only when the taglist window is opened or when the +taglist menu is enabled. When the taglist window is closed, the taglist plugin +will stop processing the tags for newly opened files. + +You can set the 'Tlist_Process_File_Always' variable to 1 to generate the list +of tags for new files even when the taglist window is closed and the taglist +menu is disabled. +> + let Tlist_Process_File_Always = 1 +< +To use the ":TlistShowTag" and the ":TlistShowPrototype" commands without the +taglist window and the taglist menu, you should set this variable to 1. + + *'Tlist_Show_Menu'* +Tlist_Show_Menu~ +When using GUI Vim, you can display the tags defined in the current file in a +menu named "Tags". By default, this feature is turned off. To turn on this +feature, set the 'Tlist_Show_Menu' variable to 1: +> + let Tlist_Show_Menu = 1 +< + *'Tlist_Show_One_File'* +Tlist_Show_One_File~ +By default, the taglist plugin will display the tags defined in all the loaded +buffers in the taglist window. If you prefer to display the tags defined only +in the current buffer, then you can set the 'Tlist_Show_One_File' to 1. When +this variable is set to 1, as you switch between buffers, the taglist window +will be refreshed to display the tags for the current buffer and the tags for +the previous buffer will be removed. +> + let Tlist_Show_One_File = 1 +< + *'Tlist_Sort_Type'* +Tlist_Sort_Type~ +The 'Tlist_Sort_Type' variable specifies the sort order for the tags in the +taglist window. The tags can be sorted either alphabetically by their name or +by the order of their appearance in the file (chronological order). By +default, the tag names will be listed by the order in which they are defined +in the file. You can change the sort type (from name to order or from order to +name) by pressing the "s" key in the taglist window. You can also change the +default sort order by setting 'Tlist_Sort_Type' to "name" or "order": +> + let Tlist_Sort_Type = "name" +< + *'Tlist_Use_Horiz_Window'* +Tlist_Use_Horiz_Window~ +Be default, the tag names are displayed in a vertically split window. If you +prefer a horizontally split window, then set the 'Tlist_Use_Horiz_Window' +variable to 1. If you are running MS-Windows version of Vim in a MS-DOS +command window, then you should use a horizontally split window instead of a +vertically split window. Also, if you are using an older version of xterm in a +Unix system that doesn't support changing the xterm window width, you should +use a horizontally split window. +> + let Tlist_Use_Horiz_Window = 1 +< + *'Tlist_Use_Right_Window'* +Tlist_Use_Right_Window~ +By default, the vertically split taglist window will appear on the left hand +side. If you prefer to open the window on the right hand side, you can set the +'Tlist_Use_Right_Window' variable to 1: +> + let Tlist_Use_Right_Window = 1 +< + *'Tlist_Use_SingleClick'* +Tlist_Use_SingleClick~ +By default, when you double click on the tag name using the left mouse +button, the cursor will be positioned at the definition of the tag. You +can set the 'Tlist_Use_SingleClick' variable to 1 to jump to a tag when +you single click on the tag name using the mouse. By default this variable +is set to zero. +> + let Tlist_Use_SingleClick = 1 +< +Due to a bug in Vim, if you set 'Tlist_Use_SingleClick' to 1 and try to resize +the taglist window using the mouse, then Vim will crash. This problem is fixed +in Vim 6.3 and above. In the meantime, instead of resizing the taglist window +using the mouse, you can use normal Vim window resizing commands to resize the +taglist window. + + *'Tlist_WinHeight'* +Tlist_WinHeight~ +The default height of the horizontally split taglist window is 10. This can be +changed by modifying the 'Tlist_WinHeight' variable: +> + let Tlist_WinHeight = 20 +< +The |'winfixheight'| option is set for the taglist window, to maintain the +height of the taglist window, when new Vim windows are opened and existing +windows are closed. + + *'Tlist_WinWidth'* +Tlist_WinWidth~ +The default width of the vertically split taglist window is 30. This can be +changed by modifying the 'Tlist_WinWidth' variable: +> + let Tlist_WinWidth = 20 +< +Note that the value of the |'winwidth'| option setting determines the minimum +width of the current window. If you set the 'Tlist_WinWidth' variable to a +value less than that of the |'winwidth'| option setting, then Vim will use the +value of the |'winwidth'| option. + +When new Vim windows are opened and existing windows are closed, the taglist +plugin will try to maintain the width of the taglist window to the size +specified by the 'Tlist_WinWidth' variable. + +============================================================================== + *taglist-commands* +7. Commands~ + +The taglist plugin provides the following ex-mode commands: + +|:TlistAddFiles| Add multiple files to the taglist. +|:TlistAddFilesRecursive| + Add files recursively to the taglist. +|:TlistClose| Close the taglist window. +|:TlistDebug| Start logging of taglist debug messages. +|:TlistLock| Stop adding new files to the taglist. +|:TlistMessages| Display the logged taglist plugin debug messages. +|:TlistOpen| Open and jump to the taglist window. +|:TlistSessionSave| Save the information about files and tags in the + taglist to a session file. +|:TlistSessionLoad| Load the information about files and tags stored + in a session file to taglist. +|:TlistShowPrototype| Display the prototype of the tag at or before the + specified line number. +|:TlistShowTag| Display the name of the tag defined at or before the + specified line number. +|:TlistHighlightTag| Highlight the current tag in the taglist window. +|:TlistToggle| Open or close (toggle) the taglist window. +|:TlistUndebug| Stop logging of taglist debug messages. +|:TlistUnlock| Start adding new files to the taglist. +|:TlistUpdate| Update the tags for the current buffer. + + *:TlistAddFiles* +:TlistAddFiles {file(s)} [file(s) ...] + Add one or more specified files to the taglist. You can + specify multiple filenames using wildcards. To specify a + file name with space character, you should escape the space + character with a backslash. + Examples: +> + :TlistAddFiles *.c *.cpp + :TlistAddFiles file1.html file2.html +< + If you specify a large number of files, then it will take some + time for the taglist plugin to process all of them. The + specified files will not be edited in a Vim window and will + not be added to the Vim buffer list. + + *:TlistAddFilesRecursive* +:TlistAddFilesRecursive {directory} [ {pattern} ] + Add files matching {pattern} recursively from the specified + {directory} to the taglist. If {pattern} is not specified, + then '*' is assumed. To specify the current directory, use "." + for {directory}. To specify a directory name with space + character, you should escape the space character with a + backslash. + Examples: +> + :TlistAddFilesRecursive myproject *.java + :TlistAddFilesRecursive smallproject +< + If large number of files are present in the specified + directory tree, then it will take some time for the taglist + plugin to process all of them. + + *:TlistClose* +:TlistClose Close the taglist window. This command can be used from any + one of the Vim windows. + + *:TlistDebug* +:TlistDebug [filename] + Start logging of debug messages from the taglist plugin. + If {filename} is specified, then the debug messages are stored + in the specified file. Otherwise, the debug messages are + stored in a script local variable. If the file {filename} is + already present, then it is overwritten. + + *:TlistLock* +:TlistLock + Lock the taglist and don't process new files. After this + command is executed, newly edited files will not be added to + the taglist. + + *:TlistMessages* +:TlistMessages + Display the logged debug messages from the taglist plugin + in a window. This command works only when logging to a + script-local variable. + + *:TlistOpen* +:TlistOpen Open and jump to the taglist window. Creates the taglist + window, if the window is not opened currently. After executing + this command, the cursor is moved to the taglist window. When + the taglist window is opened for the first time, all the files + in the buffer list are processed and the tags defined in them + are displayed in the taglist window. + + *:TlistSessionSave* +:TlistSessionSave {filename} + Saves the information about files and tags in the taglist to + the specified file. This command can be used to save and + restore the taglist contents across Vim sessions. + + *:TlistSessionLoad* +:TlistSessionLoad {filename} + Load the information about files and tags stored in the + specified session file to the taglist. + + *:TlistShowPrototype* +:TlistShowPrototype [filename] [linenumber] + Display the prototype of the tag at or before the specified + line number. If the file name and the line number are not + specified, then the current file name and line number are + used. A tag spans multiple lines starting from the line where + it is defined to the line before the next tag. This command + displays the prototype for the tag for any line number in this + range. + + *:TlistShowTag* +:TlistShowTag [filename] [linenumber] + Display the name of the tag defined at or before the specified + line number. If the file name and the line number are not + specified, then the current file name and line number are + used. A tag spans multiple lines starting from the line where + it is defined to the line before the next tag. This command + displays the tag name for any line number in this range. + + *:TlistHighlightTag* +:TlistHighlightTag + Highlight the current tag in the taglist window. By default, + the taglist plugin periodically updates the taglist window to + highlight the current tag. This command can be used to force + the taglist plugin to highlight the current tag. + + *:TlistToggle* +:TlistToggle Open or close (toggle) the taglist window. Opens the taglist + window, if the window is not opened currently. Closes the + taglist window, if the taglist window is already opened. When + the taglist window is opened for the first time, all the files + in the buffer list are processed and the tags are displayed in + the taglist window. After executing this command, the cursor + is not moved from the current window to the taglist window. + + *:TlistUndebug* +:TlistUndebug + Stop logging of debug messages from the taglist plugin. + + *:TlistUnlock* +:TlistUnlock + Unlock the taglist and start processing newly edited files. + + *:TlistUpdate* +:TlistUpdate Update the tags information for the current buffer. This + command can be used to re-process the current file/buffer and + get the tags information. As the taglist plugin uses the file + saved in the disk (instead of the file displayed in a Vim + buffer), you should save a modified buffer before you update + the taglist. Otherwise the listed tags will not include the + new tags created in the buffer. You can use this command even + when the taglist window is not opened. + +============================================================================== + *taglist-functions* +8. Global functions~ + +The taglist plugin provides several global functions that can be used from +other Vim plugins to interact with the taglist plugin. These functions are +described below. + +|Tlist_Update_File_Tags()| Update the tags for the specified file +|Tlist_Get_Tag_Prototype_By_Line()| Return the prototype of the tag at or + before the specified line number in the + specified file. +|Tlist_Get_Tagname_By_Line()| Return the name of the tag at or + before the specified line number in + the specified file. +|Tlist_Set_App()| Set the name of the application + controlling the taglist window. + + *Tlist_Update_File_Tags()* +Tlist_Update_File_Tags({filename}, {filetype}) + Update the tags for the file {filename}. The second argument + specifies the Vim filetype for the file. If the taglist plugin + has not processed the file previously, then the exuberant + ctags tool is invoked to generate the tags for the file. + + *Tlist_Get_Tag_Prototype_By_Line()* +Tlist_Get_Tag_Prototype_By_Line([{filename}, {linenumber}]) + Return the prototype of the tag at or before the specified + line number in the specified file. If the filename and line + number are not specified, then the current buffer name and the + current line number are used. + + *Tlist_Get_Tagname_By_Line()* +Tlist_Get_Tagname_By_Line([{filename}, {linenumber}]) + Return the name of the tag at or before the specified line + number in the specified file. If the filename and line number + are not specified, then the current buffer name and the + current line number are used. + + *Tlist_Set_App()* +Tlist_Set_App({appname}) + Set the name of the plugin that controls the taglist plugin + window and buffer. This can be used to integrate the taglist + plugin with other Vim plugins. + + For example, the winmanager plugin and the Cream package use + this function and specify the appname as "winmanager" and + "cream" respectively. + + By default, the taglist plugin is a stand-alone plugin and + controls the taglist window and buffer. If the taglist window + is controlled by an external plugin, then the appname should + be set appropriately. + +============================================================================== + *taglist-extend* +9. Extending~ + +The taglist plugin supports all the languages supported by the exuberant ctags +tool, which includes the following languages: Assembly, ASP, Awk, Beta, C, +C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, Lua, +Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, SML, Sql, +TCL, Verilog, Vim and Yacc. + +You can extend the taglist plugin to add support for new languages and also +modify the support for the above listed languages. + +You should NOT make modifications to the taglist plugin script file to add +support for new languages. You will lose these changes when you upgrade to the +next version of the taglist plugin. Instead you should follow the below +described instructions to extend the taglist plugin. + +You can extend the taglist plugin by setting variables in the .vimrc or _vimrc +file. The name of these variables depends on the language name and is +described below. + +Modifying support for an existing language~ +To modify the support for an already supported language, you have to set the +tlist_xxx_settings variable in the ~/.vimrc or $HOME/_vimrc file. Replace xxx +with the Vim filetype name for the language file. For example, to modify the +support for the perl language files, you have to set the tlist_perl_settings +variable. To modify the support for java files, you have to set the +tlist_java_settings variable. + +To determine the filetype name used by Vim for a file, use the following +command in the buffer containing the file: + + :set filetype + +The above command will display the Vim filetype for the current buffer. + +The format of the value set in the tlist_xxx_settings variable is + + ;flag1:name1;flag2:name2;flag3:name3 + +The different fields in the value are separated by the ';' character. + +The first field 'language_name' is the name used by exuberant ctags to refer +to this language file. This name can be different from the file type name used +by Vim. For example, for C++, the language name used by ctags is 'c++' but the +filetype name used by Vim is 'cpp'. To get the list of language names +supported by exuberant ctags, use the following command: + + $ ctags --list-maps=all + +The remaining fields follow the format "flag:name". The sub-field 'flag' is +the language specific flag used by exuberant ctags to generate the +corresponding tags. For example, for the C language, to list only the +functions, the 'f' flag is used. To get the list of flags supported by +exuberant ctags for the various languages use the following command: + + $ ctags --list-kinds=all + +The sub-field 'name' specifies the title text to use for displaying the tags +of a particular type. For example, 'name' can be set to 'functions'. This +field can be set to any text string name. + +For example, to list only the classes and functions defined in a C++ language +file, add the following line to your .vimrc file: + + let tlist_cpp_settings = 'c++;c:class;f:function' + +In the above setting, 'cpp' is the Vim filetype name and 'c++' is the name +used by the exuberant ctags tool. 'c' and 'f' are the flags passed to +exuberant ctags to list C++ classes and functions and 'class' is the title +used for the class tags and 'function' is the title used for the function tags +in the taglist window. + +For example, to display only functions defined in a C file and to use "My +Functions" as the title for the function tags, use + + let tlist_c_settings = 'c;f:My Functions' + +When you set the tlist_xxx_settings variable, you will override the default +setting used by the taglist plugin for the 'xxx' language. You cannot add to +the default options used by the taglist plugin for a particular file type. To +add to the options used by the taglist plugin for a language, copy the option +values from the taglist plugin file to your .vimrc file and modify it. + +Adding support for a new language~ +If you want to add support for a new language to the taglist plugin, you need +to first extend the exuberant ctags tool. For more information about extending +exuberant ctags, visit the following page: + + http://ctags.sourceforge.net/EXTENDING.html + +To add support for a new language, set the tlist_xxx_settings variable in the +~/.vimrc file appropriately as described above. Replace 'xxx' in the variable +name with the Vim filetype name for the new language. + +For example, to extend the taglist plugin to support the latex language, you +can use the following line (assuming, you have already extended exuberant +ctags to support the latex language): + + let tlist_tex_settings='latex;b:bibitem;c:command;l:label' + +With the above line, when you edit files of filetype "tex" in Vim, the taglist +plugin will invoke the exuberant ctags tool passing the "latex" filetype and +the flags b, c and l to generate the tags. The text heading 'bibitem', +'command' and 'label' will be used in the taglist window for the tags which +are generated for the flags b, c and l respectively. + +============================================================================== + *taglist-faq* +10. Frequently Asked Questions~ + +Q. The taglist plugin doesn't work. The taglist window is empty and the tags + defined in a file are not displayed. +A. Are you using Vim version 6.0 and above? The taglist plugin relies on the + features supported by Vim version 6.0 and above. You can use the following + command to get the Vim version: +> + $ vim --version +< + Are you using exuberant ctags version 5.0 and above? The taglist plugin + relies on the features supported by exuberant ctags and will not work with + GNU ctags or the Unix ctags utility. You can use the following command to + determine whether the ctags installed in your system is exuberant ctags: +> + $ ctags --version +< + Is exuberant ctags present in one of the directories in your PATH? If not, + you need to set the Tlist_Ctags_Cmd variable to point to the location of + exuberant ctags. Use the following Vim command to verify that this is setup + correctly: +> + :echo system(Tlist_Ctags_Cmd . ' --version') +< + The above command should display the version information for exuberant + ctags. + + Did you turn on the Vim filetype detection? The taglist plugin relies on + the filetype detected by Vim and passes the filetype to the exuberant ctags + utility to parse the tags. Check the output of the following Vim command: +> + :filetype +< + The output of the above command should contain "filetype detection:ON". + To turn on the filetype detection, add the following line to the .vimrc or + _vimrc file: +> + filetype on +< + Is your version of Vim compiled with the support for the system() function? + The following Vim command should display 1: +> + :echo exists('*system') +< + In some Linux distributions (particularly Suse Linux), the default Vim + installation is built without the support for the system() function. The + taglist plugin uses the system() function to invoke the exuberant ctags + utility. You need to rebuild Vim after enabling the support for the + system() function. If you use the default build options, the system() + function will be supported. + + Do you have the |'shellslash'| option set? You can try disabling the + |'shellslash'| option. When the taglist plugin invokes the exuberant ctags + utility with the path to the file, if the incorrect slashes are used, then + you will see errors. + + Check the shell related Vim options values using the following command: +> + :set shell? shellcmdflag? shellpipe? + :set shellquote? shellredir? shellxquote? +< + If these options are set in your .vimrc or _vimrc file, try removing those + lines. + + Are you using a Unix shell in a MS-Windows environment? For example, + the Unix shell from the MKS-toolkit. Do you have the SHELL environment + set to point to this shell? You can try resetting the SHELL environment + variable. + + If you are using a Unix shell on MS-Windows, you should try to use + exuberant ctags that is compiled for Unix-like environments so that + exuberant ctags will understand path names with forward slash characters. + + Is your filetype supported by the exuberant ctags utility? The file types + supported by the exuberant ctags utility are listed in the ctags help. If a + file type is not supported, you have to extend exuberant ctags. You can use + the following command to list the filetypes supported by exuberant ctags: +> + ctags --list-languages +< + Run the following command from the shell prompt and check whether the tags + defined in your file are listed in the output from exuberant ctags: +> + ctags -f - --format=2 --excmd=pattern --fields=nks +< + If you see your tags in the output from the above command, then the + exuberant ctags utility is properly parsing your file. + + Do you have the .ctags or _ctags or the ctags.cnf file in your home + directory for specifying default options or for extending exuberant ctags? + If you do have this file, check the options in this file and make sure + these options are not interfering with the operation of the taglist plugin. + + If you are using MS-Windows, check the value of the TEMP and TMP + environment variables. If these environment variables are set to a path + with space characters in the name, then try using the DOS 8.3 short name + for the path or set them to a path without the space characters in the + name. For example, if the temporary directory name is "C:\Documents and + Settings\xyz\Local Settings\Temp", then try setting the TEMP variable to + the following: +> + set TEMP=C:\DOCUMEN~1\xyz\LOCALS~1\Temp +< + If exuberant ctags is installed in a directory with space characters in the + name, then try adding the directory to the PATH environment variable or try + setting the 'Tlist_Ctags_Cmd' variable to the shortest path name to ctags + or try copying the exuberant ctags to a path without space characters in + the name. For example, if exuberant ctags is installed in the directory + "C:\Program Files\Ctags", then try setting the 'Tlist_Ctags_Cmd' variable + as below: +> + let Tlist_Ctags_Cmd='C:\Progra~1\Ctags\ctags.exe' +< + If you are using a cygwin compiled version of exuberant ctags on MS-Windows, + make sure that either you have the cygwin compiled sort utility installed + and available in your PATH or compile exuberant ctags with internal sort + support. Otherwise, when exuberant ctags sorts the tags output by invoking + the sort utility, it may end up invoking the MS-Windows version of + sort.exe, thereby resulting in failure. + +Q. When I try to open the taglist window, I am seeing the following error + message. How do I fix this problem? + + Taglist: Failed to generate tags for /my/path/to/file + ctags: illegal option -- -^@usage: ctags [-BFadtuwvx] [-f tagsfile] file ... + +A. The taglist plugin will work only with the exuberant ctags tool. You + cannot use the GNU ctags or the Unix ctags program with the taglist plugin. + You will see an error message similar to the one shown above, if you try + use a non-exuberant ctags program with Vim. To fix this problem, either add + the exuberant ctags tool location to the PATH environment variable or set + the 'Tlist_Ctags_Cmd' variable. + +Q. A file has more than one tag with the same name. When I select a tag name + from the taglist window, the cursor is positioned at the incorrect tag + location. +A. The taglist plugin uses the search pattern generated by the exuberant ctags + utility to position the cursor at the location of a tag definition. If a + file has more than one tag with the same name and same prototype, then the + search pattern will be the same. In this case, when searching for the tag + pattern, the cursor may be positioned at the incorrect location. + +Q. I have made some modifications to my file and introduced new + functions/classes/variables. I have not yet saved my file. The taglist + plugin is not displaying the new tags when I update the taglist window. +A. The exuberant ctags utility will process only files that are present in the + disk. To list the tags defined in a file, you have to save the file and + then update the taglist window. + +Q. I have created a ctags file using the exuberant ctags utility for my source + tree. How do I configure the taglist plugin to use this tags file? +A. The taglist plugin doesn't use a tags file stored in disk. For every opened + file, the taglist plugin invokes the exuberant ctags utility to get the + list of tags dynamically. The Vim system() function is used to invoke + exuberant ctags and get the ctags output. This function internally uses a + temporary file to store the output. This file is deleted after the output + from the command is read. So you will never see the file that contains the + output of exuberant ctags. + +Q. When I set the |'updatetime'| option to a low value (less than 1000) and if + I keep pressing a key with the taglist window open, the current buffer + contents are changed. Why is this? +A. The taglist plugin uses the |CursorHold| autocmd to highlight the current + tag. The CursorHold autocmd triggers for every |'updatetime'| milliseconds. + If the |'updatetime'| option is set to a low value, then the CursorHold + autocmd will be triggered frequently. As the taglist plugin changes + the focus to the taglist window to highlight the current tag, this could + interfere with the key movement resulting in changing the contents of + the current buffer. The workaround for this problem is to not set the + |'updatetime'| option to a low value. + +============================================================================== + *taglist-license* +11. License~ +Permission is hereby granted to use and distribute the taglist plugin, with or +without modifications, provided that this copyright notice is copied with it. +Like anything else that's free, taglist.vim is provided *as is* and comes with +no warranty of any kind, either expressed or implied. In no event will the +copyright holder be liable for any damamges resulting from the use of this +software. + +============================================================================== + *taglist-todo* +12. Todo~ + +1. Group tags according to the scope and display them. For example, + group all the tags belonging to a C++/Java class +2. Support for displaying tags in a modified (not-yet-saved) file. +3. Automatically open the taglist window only for selected filetypes. + For other filetypes, close the taglist window. +4. When using the shell from the MKS toolkit, the taglist plugin + doesn't work. +5. The taglist plugin doesn't work with files edited remotely using the + netrw plugin. The exuberant ctags utility cannot process files over + scp/rcp/ftp, etc. + +============================================================================== + +vim:tw=78:ts=8:noet:ft=help: diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..72c741b --- /dev/null +++ b/doc/tags @@ -0,0 +1,625 @@ +'NERDChristmasTree' NERD_tree.txt /*'NERDChristmasTree'* +'NERDTreeAutoCenter' NERD_tree.txt /*'NERDTreeAutoCenter'* +'NERDTreeAutoCenterThreshold' NERD_tree.txt /*'NERDTreeAutoCenterThreshold'* +'NERDTreeBookmarksFile' NERD_tree.txt /*'NERDTreeBookmarksFile'* +'NERDTreeCaseSensitiveSort' NERD_tree.txt /*'NERDTreeCaseSensitiveSort'* +'NERDTreeChDirMode' NERD_tree.txt /*'NERDTreeChDirMode'* +'NERDTreeHighlightCursorline' NERD_tree.txt /*'NERDTreeHighlightCursorline'* +'NERDTreeHijackNetrw' NERD_tree.txt /*'NERDTreeHijackNetrw'* +'NERDTreeIgnore' NERD_tree.txt /*'NERDTreeIgnore'* +'NERDTreeMouseMode' NERD_tree.txt /*'NERDTreeMouseMode'* +'NERDTreeQuitOnOpen' NERD_tree.txt /*'NERDTreeQuitOnOpen'* +'NERDTreeShowBookmarks' NERD_tree.txt /*'NERDTreeShowBookmarks'* +'NERDTreeShowFiles' NERD_tree.txt /*'NERDTreeShowFiles'* +'NERDTreeShowHidden' NERD_tree.txt /*'NERDTreeShowHidden'* +'NERDTreeShowLineNumbers' NERD_tree.txt /*'NERDTreeShowLineNumbers'* +'NERDTreeSortOrder' NERD_tree.txt /*'NERDTreeSortOrder'* +'NERDTreeStatusline' NERD_tree.txt /*'NERDTreeStatusline'* +'NERDTreeWinPos' NERD_tree.txt /*'NERDTreeWinPos'* +'NERDTreeWinSize' NERD_tree.txt /*'NERDTreeWinSize'* +'Tlist_Auto_Highlight_Tag' taglist.txt /*'Tlist_Auto_Highlight_Tag'* +'Tlist_Auto_Open' taglist.txt /*'Tlist_Auto_Open'* +'Tlist_Auto_Update' taglist.txt /*'Tlist_Auto_Update'* +'Tlist_Close_On_Select' taglist.txt /*'Tlist_Close_On_Select'* +'Tlist_Compact_Format' taglist.txt /*'Tlist_Compact_Format'* +'Tlist_Ctags_Cmd' taglist.txt /*'Tlist_Ctags_Cmd'* +'Tlist_Display_Prototype' taglist.txt /*'Tlist_Display_Prototype'* +'Tlist_Display_Tag_Scope' taglist.txt /*'Tlist_Display_Tag_Scope'* +'Tlist_Enable_Fold_Column' taglist.txt /*'Tlist_Enable_Fold_Column'* +'Tlist_Exit_OnlyWindow' taglist.txt /*'Tlist_Exit_OnlyWindow'* +'Tlist_File_Fold_Auto_Close' taglist.txt /*'Tlist_File_Fold_Auto_Close'* +'Tlist_GainFocus_On_ToggleOpen' taglist.txt /*'Tlist_GainFocus_On_ToggleOpen'* +'Tlist_Highlight_Tag_On_BufEnter' taglist.txt /*'Tlist_Highlight_Tag_On_BufEnter'* +'Tlist_Inc_Winwidth' taglist.txt /*'Tlist_Inc_Winwidth'* +'Tlist_Max_Submenu_Items' taglist.txt /*'Tlist_Max_Submenu_Items'* +'Tlist_Max_Tag_Length' taglist.txt /*'Tlist_Max_Tag_Length'* +'Tlist_Process_File_Always' taglist.txt /*'Tlist_Process_File_Always'* +'Tlist_Show_Menu' taglist.txt /*'Tlist_Show_Menu'* +'Tlist_Show_One_File' taglist.txt /*'Tlist_Show_One_File'* +'Tlist_Sort_Type' taglist.txt /*'Tlist_Sort_Type'* +'Tlist_Use_Horiz_Window' taglist.txt /*'Tlist_Use_Horiz_Window'* +'Tlist_Use_Right_Window' taglist.txt /*'Tlist_Use_Right_Window'* +'Tlist_Use_SingleClick' taglist.txt /*'Tlist_Use_SingleClick'* +'Tlist_WinHeight' taglist.txt /*'Tlist_WinHeight'* +'Tlist_WinWidth' taglist.txt /*'Tlist_WinWidth'* +'b:delimitMate_autoclose' delimitMate.txt /*'b:delimitMate_autoclose'* +'b:delimitMate_expand_cr' delimitMate.txt /*'b:delimitMate_expand_cr'* +'b:delimitMate_expand_space' delimitMate.txt /*'b:delimitMate_expand_space'* +'b:delimitMate_matchpairs' delimitMate.txt /*'b:delimitMate_matchpairs'* +'b:delimitMate_quotes' delimitMate.txt /*'b:delimitMate_quotes'* +'b:delimitMate_visual_leader' delimitMate.txt /*'b:delimitMate_visual_leader'* +'b:loaded_delimitMate' delimitMate.txt /*'b:loaded_delimitMate'* +'delimitMate_apostrophes' delimitMate.txt /*'delimitMate_apostrophes'* +'delimitMate_autoclose' delimitMate.txt /*'delimitMate_autoclose'* +'delimitMate_excluded_ft' delimitMate.txt /*'delimitMate_excluded_ft'* +'delimitMate_expand_cr' delimitMate.txt /*'delimitMate_expand_cr'* +'delimitMate_expand_space' delimitMate.txt /*'delimitMate_expand_space'* +'delimitMate_matchpairs' delimitMate.txt /*'delimitMate_matchpairs'* +'delimitMate_quotes' delimitMate.txt /*'delimitMate_quotes'* +'delimitMate_visual_leader' delimitMate.txt /*'delimitMate_visual_leader'* +'loaded_delimitMate' delimitMate.txt /*'loaded_delimitMate'* +'loaded_nerd_tree' NERD_tree.txt /*'loaded_nerd_tree'* +'showmarks_enable' showmarks.txt /*'showmarks_enable'* +'showmarks_hlline_lower' showmarks.txt /*'showmarks_hlline_lower'* +'showmarks_hlline_other' showmarks.txt /*'showmarks_hlline_other'* +'showmarks_hlline_upper' showmarks.txt /*'showmarks_hlline_upper'* +'showmarks_ignore_name' showmarks.txt /*'showmarks_ignore_name'* +'showmarks_ignore_type' showmarks.txt /*'showmarks_ignore_type'* +'showmarks_include' showmarks.txt /*'showmarks_include'* +'showmarks_textother' showmarks.txt /*'showmarks_textother'* +'showmarks_textupper' showmarks.txt /*'showmarks_textupper'* +'snippets' snipMate.txt /*'snippets'* +.snippet snipMate.txt /*.snippet* +.snippets snipMate.txt /*.snippets* +:CVSEdit vcscommand.txt /*:CVSEdit* +:CVSEditors vcscommand.txt /*:CVSEditors* +:CVSUnedit vcscommand.txt /*:CVSUnedit* +:CVSWatch vcscommand.txt /*:CVSWatch* +:CVSWatchAdd vcscommand.txt /*:CVSWatchAdd* +:CVSWatchOff vcscommand.txt /*:CVSWatchOff* +:CVSWatchOn vcscommand.txt /*:CVSWatchOn* +:CVSWatchRemove vcscommand.txt /*:CVSWatchRemove* +:CVSWatchers vcscommand.txt /*:CVSWatchers* +:DelimitMateReload delimitMate.txt /*:DelimitMateReload* +:DelimitMateTest delimitMate.txt /*:DelimitMateTest* +:FufAddBookmark fuf.txt /*:FufAddBookmark* +:FufAddBookmarkAsSelectedText fuf.txt /*:FufAddBookmarkAsSelectedText* +:FufBookmark fuf.txt /*:FufBookmark* +:FufBuffer fuf.txt /*:FufBuffer* +:FufChangeList fuf.txt /*:FufChangeList* +:FufDir fuf.txt /*:FufDir* +:FufDirWithCurrentBufferDir fuf.txt /*:FufDirWithCurrentBufferDir* +:FufDirWithFullCwd fuf.txt /*:FufDirWithFullCwd* +:FufEditInfo fuf.txt /*:FufEditInfo* +:FufFile fuf.txt /*:FufFile* +:FufFileWithCurrentBufferDir fuf.txt /*:FufFileWithCurrentBufferDir* +:FufFileWithFullCwd fuf.txt /*:FufFileWithFullCwd* +:FufHelp fuf.txt /*:FufHelp* +:FufJumpList fuf.txt /*:FufJumpList* +:FufLine fuf.txt /*:FufLine* +:FufMruCmd fuf.txt /*:FufMruCmd* +:FufMruFile fuf.txt /*:FufMruFile* +:FufQuickfix fuf.txt /*:FufQuickfix* +:FufRenewCache fuf.txt /*:FufRenewCache* +:FufTag fuf.txt /*:FufTag* +:FufTagWithCursorWord fuf.txt /*:FufTagWithCursorWord* +:FufTaggedFile fuf.txt /*:FufTaggedFile* +:GLVS pi_getscript.txt /*:GLVS* +:GetLatestVimScripts_dat pi_getscript.txt /*:GetLatestVimScripts_dat* +:Mark mark.txt /*:Mark* +:NERDTree NERD_tree.txt /*:NERDTree* +:NERDTreeClose NERD_tree.txt /*:NERDTreeClose* +:NERDTreeFind NERD_tree.txt /*:NERDTreeFind* +:NERDTreeFromBookmark NERD_tree.txt /*:NERDTreeFromBookmark* +:NERDTreeMirror NERD_tree.txt /*:NERDTreeMirror* +:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle* +:TlistAddFiles taglist.txt /*:TlistAddFiles* +:TlistAddFilesRecursive taglist.txt /*:TlistAddFilesRecursive* +:TlistClose taglist.txt /*:TlistClose* +:TlistDebug taglist.txt /*:TlistDebug* +:TlistHighlightTag taglist.txt /*:TlistHighlightTag* +:TlistLock taglist.txt /*:TlistLock* +:TlistMessages taglist.txt /*:TlistMessages* +:TlistOpen taglist.txt /*:TlistOpen* +:TlistSessionLoad taglist.txt /*:TlistSessionLoad* +:TlistSessionSave taglist.txt /*:TlistSessionSave* +:TlistShowPrototype taglist.txt /*:TlistShowPrototype* +:TlistShowTag taglist.txt /*:TlistShowTag* +:TlistToggle taglist.txt /*:TlistToggle* +:TlistUndebug taglist.txt /*:TlistUndebug* +:TlistUnlock taglist.txt /*:TlistUnlock* +:TlistUpdate taglist.txt /*:TlistUpdate* +:VCSAdd vcscommand.txt /*:VCSAdd* +:VCSAnnotate vcscommand.txt /*:VCSAnnotate* +:VCSBlame vcscommand.txt /*:VCSBlame* +:VCSCommit vcscommand.txt /*:VCSCommit* +:VCSDelete vcscommand.txt /*:VCSDelete* +:VCSDiff vcscommand.txt /*:VCSDiff* +:VCSGotoOriginal vcscommand.txt /*:VCSGotoOriginal* +:VCSInfo vcscommand.txt /*:VCSInfo* +:VCSLock vcscommand.txt /*:VCSLock* +:VCSLog vcscommand.txt /*:VCSLog* +:VCSRemove vcscommand.txt /*:VCSRemove* +:VCSRevert vcscommand.txt /*:VCSRevert* +:VCSReview vcscommand.txt /*:VCSReview* +:VCSStatus vcscommand.txt /*:VCSStatus* +:VCSUnlock vcscommand.txt /*:VCSUnlock* +:VCSUpdate vcscommand.txt /*:VCSUpdate* +:VCSVimDiff vcscommand.txt /*:VCSVimDiff* +:VWS vimwiki.txt /*:VWS* +:Vimwiki2HTML vimwiki.txt /*:Vimwiki2HTML* +:VimwikiAll2HTML vimwiki.txt /*:VimwikiAll2HTML* +:VimwikiDeleteWord vimwiki.txt /*:VimwikiDeleteWord* +:VimwikiFollowWord vimwiki.txt /*:VimwikiFollowWord* +:VimwikiGoBackWord vimwiki.txt /*:VimwikiGoBackWord* +:VimwikiGoHome vimwiki.txt /*:VimwikiGoHome* +:VimwikiMakeDiaryNote vimwiki.txt /*:VimwikiMakeDiaryNote* +:VimwikiNextWord vimwiki.txt /*:VimwikiNextWord* +:VimwikiPrevWord vimwiki.txt /*:VimwikiPrevWord* +:VimwikiRenameWord vimwiki.txt /*:VimwikiRenameWord* +:VimwikiSearch vimwiki.txt /*:VimwikiSearch* +:VimwikiSplitWord vimwiki.txt /*:VimwikiSplitWord* +:VimwikiTabGoHome vimwiki.txt /*:VimwikiTabGoHome* +:VimwikiTabMakeDiaryNote vimwiki.txt /*:VimwikiTabMakeDiaryNote* +:VimwikiTable vimwiki.txt /*:VimwikiTable* +:VimwikiToggleListItem vimwiki.txt /*:VimwikiToggleListItem* +:VimwikiUISelect vimwiki.txt /*:VimwikiUISelect* +:VimwikiVSplitWord vimwiki.txt /*:VimwikiVSplitWord* +DelimitMate_ExpandReturn() delimitMate.txt /*DelimitMate_ExpandReturn()* +DelimitMate_ExpandSpace() delimitMate.txt /*DelimitMate_ExpandSpace()* +DelimitMate_JumpAny() delimitMate.txt /*DelimitMate_JumpAny()* +DelimitMate_ShouldJump() delimitMate.txt /*DelimitMate_ShouldJump()* +ExtractSnips() snipMate.txt /*ExtractSnips()* +ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()* +Filename() snipMate.txt /*Filename()* +GetLatestVimScripts pi_getscript.txt /*GetLatestVimScripts* +GetLatestVimScripts-copyright pi_getscript.txt /*GetLatestVimScripts-copyright* +GetLatestVimScripts_dat pi_getscript.txt /*GetLatestVimScripts_dat* +NERDTree NERD_tree.txt /*NERDTree* +NERDTree-? NERD_tree.txt /*NERDTree-?* +NERDTree-A NERD_tree.txt /*NERDTree-A* +NERDTree-B NERD_tree.txt /*NERDTree-B* +NERDTree-C NERD_tree.txt /*NERDTree-C* +NERDTree-C-J NERD_tree.txt /*NERDTree-C-J* +NERDTree-C-K NERD_tree.txt /*NERDTree-C-K* +NERDTree-D NERD_tree.txt /*NERDTree-D* +NERDTree-F NERD_tree.txt /*NERDTree-F* +NERDTree-I NERD_tree.txt /*NERDTree-I* +NERDTree-J NERD_tree.txt /*NERDTree-J* +NERDTree-K NERD_tree.txt /*NERDTree-K* +NERDTree-O NERD_tree.txt /*NERDTree-O* +NERDTree-P NERD_tree.txt /*NERDTree-P* +NERDTree-R NERD_tree.txt /*NERDTree-R* +NERDTree-T NERD_tree.txt /*NERDTree-T* +NERDTree-U NERD_tree.txt /*NERDTree-U* +NERDTree-X NERD_tree.txt /*NERDTree-X* +NERDTree-cd NERD_tree.txt /*NERDTree-cd* +NERDTree-contents NERD_tree.txt /*NERDTree-contents* +NERDTree-e NERD_tree.txt /*NERDTree-e* +NERDTree-f NERD_tree.txt /*NERDTree-f* +NERDTree-gi NERD_tree.txt /*NERDTree-gi* +NERDTree-go NERD_tree.txt /*NERDTree-go* +NERDTree-gs NERD_tree.txt /*NERDTree-gs* +NERDTree-i NERD_tree.txt /*NERDTree-i* +NERDTree-m NERD_tree.txt /*NERDTree-m* +NERDTree-o NERD_tree.txt /*NERDTree-o* +NERDTree-p NERD_tree.txt /*NERDTree-p* +NERDTree-q NERD_tree.txt /*NERDTree-q* +NERDTree-r NERD_tree.txt /*NERDTree-r* +NERDTree-s NERD_tree.txt /*NERDTree-s* +NERDTree-t NERD_tree.txt /*NERDTree-t* +NERDTree-u NERD_tree.txt /*NERDTree-u* +NERDTree-x NERD_tree.txt /*NERDTree-x* +NERDTreeAPI NERD_tree.txt /*NERDTreeAPI* +NERDTreeAbout NERD_tree.txt /*NERDTreeAbout* +NERDTreeAddKeyMap() NERD_tree.txt /*NERDTreeAddKeyMap()* +NERDTreeAddMenuItem() NERD_tree.txt /*NERDTreeAddMenuItem()* +NERDTreeAddMenuSeparator() NERD_tree.txt /*NERDTreeAddMenuSeparator()* +NERDTreeAddSubmenu() NERD_tree.txt /*NERDTreeAddSubmenu()* +NERDTreeBookmarkCommands NERD_tree.txt /*NERDTreeBookmarkCommands* +NERDTreeBookmarkTable NERD_tree.txt /*NERDTreeBookmarkTable* +NERDTreeBookmarks NERD_tree.txt /*NERDTreeBookmarks* +NERDTreeChangelog NERD_tree.txt /*NERDTreeChangelog* +NERDTreeCredits NERD_tree.txt /*NERDTreeCredits* +NERDTreeFunctionality NERD_tree.txt /*NERDTreeFunctionality* +NERDTreeGlobalCommands NERD_tree.txt /*NERDTreeGlobalCommands* +NERDTreeInvalidBookmarks NERD_tree.txt /*NERDTreeInvalidBookmarks* +NERDTreeKeymapAPI NERD_tree.txt /*NERDTreeKeymapAPI* +NERDTreeLicense NERD_tree.txt /*NERDTreeLicense* +NERDTreeMappings NERD_tree.txt /*NERDTreeMappings* +NERDTreeMenu NERD_tree.txt /*NERDTreeMenu* +NERDTreeMenuAPI NERD_tree.txt /*NERDTreeMenuAPI* +NERDTreeOptionDetails NERD_tree.txt /*NERDTreeOptionDetails* +NERDTreeOptionSummary NERD_tree.txt /*NERDTreeOptionSummary* +NERDTreeOptions NERD_tree.txt /*NERDTreeOptions* +NERDTreeRender() NERD_tree.txt /*NERDTreeRender()* +NERD_tree.txt NERD_tree.txt /*NERD_tree.txt* +ResetSnippets() snipMate.txt /*ResetSnippets()* +ShowMarksClearAll showmarks.txt /*ShowMarksClearAll* +ShowMarksClearMark showmarks.txt /*ShowMarksClearMark* +ShowMarksOn showmarks.txt /*ShowMarksOn* +ShowMarksPlaceMark showmarks.txt /*ShowMarksPlaceMark* +ShowMarksToggle showmarks.txt /*ShowMarksToggle* +Tlist_Get_Tag_Prototype_By_Line() taglist.txt /*Tlist_Get_Tag_Prototype_By_Line()* +Tlist_Get_Tagname_By_Line() taglist.txt /*Tlist_Get_Tagname_By_Line()* +Tlist_Set_App() taglist.txt /*Tlist_Set_App()* +Tlist_Update_File_Tags() taglist.txt /*Tlist_Update_File_Tags()* +VCSCommandCVSDiffOpt vcscommand.txt /*VCSCommandCVSDiffOpt* +VCSCommandCVSExec vcscommand.txt /*VCSCommandCVSExec* +VCSCommandCommitOnWrite vcscommand.txt /*VCSCommandCommitOnWrite* +VCSCommandDeleteOnHide vcscommand.txt /*VCSCommandDeleteOnHide* +VCSCommandDiffSplit vcscommand.txt /*VCSCommandDiffSplit* +VCSCommandDisableAll vcscommand.txt /*VCSCommandDisableAll* +VCSCommandDisableExtensionMappings vcscommand.txt /*VCSCommandDisableExtensionMappings* +VCSCommandDisableMappings vcscommand.txt /*VCSCommandDisableMappings* +VCSCommandEdit vcscommand.txt /*VCSCommandEdit* +VCSCommandEnableBufferSetup vcscommand.txt /*VCSCommandEnableBufferSetup* +VCSCommandMapPrefix vcscommand.txt /*VCSCommandMapPrefix* +VCSCommandMappings vcscommand.txt /*VCSCommandMappings* +VCSCommandResultBufferNameExtension vcscommand.txt /*VCSCommandResultBufferNameExtension* +VCSCommandResultBufferNameFunction vcscommand.txt /*VCSCommandResultBufferNameFunction* +VCSCommandSVKExec vcscommand.txt /*VCSCommandSVKExec* +VCSCommandSVNDiffExt vcscommand.txt /*VCSCommandSVNDiffExt* +VCSCommandSVNDiffOpt vcscommand.txt /*VCSCommandSVNDiffOpt* +VCSCommandSVNExec vcscommand.txt /*VCSCommandSVNExec* +VCSCommandSplit vcscommand.txt /*VCSCommandSplit* +VCSCommandVCSTypeOverride vcscommand.txt /*VCSCommandVCSTypeOverride* +VimwikiWeblinkHandler vimwiki.txt /*VimwikiWeblinkHandler* +abc fuf.txt /*abc* +b:VCSCommandCommand vcscommand.txt /*b:VCSCommandCommand* +b:VCSCommandOriginalBuffer vcscommand.txt /*b:VCSCommandOriginalBuffer* +b:VCSCommandSourceFile vcscommand.txt /*b:VCSCommandSourceFile* +b:VCSCommandVCSType vcscommand.txt /*b:VCSCommandVCSType* +cvscommand-changes vcscommand.txt /*cvscommand-changes* +delimitMate delimitMate.txt /*delimitMate* +delimitMate-contents delimitMate.txt /*delimitMate-contents* +delimitMate.txt delimitMate.txt /*delimitMate.txt* +delimitMateAutoClose delimitMate.txt /*delimitMateAutoClose* +delimitMateBackspace delimitMate.txt /*delimitMateBackspace* +delimitMateCommands delimitMate.txt /*delimitMateCommands* +delimitMateCredits delimitMate.txt /*delimitMateCredits* +delimitMateExpansion delimitMate.txt /*delimitMateExpansion* +delimitMateFunctionality delimitMate.txt /*delimitMateFunctionality* +delimitMateFunctions delimitMate.txt /*delimitMateFunctions* +delimitMateHistory delimitMate.txt /*delimitMateHistory* +delimitMateIntro delimitMate.txt /*delimitMateIntro* +delimitMateMaintainer delimitMate.txt /*delimitMateMaintainer* +delimitMateOptionDetails delimitMate.txt /*delimitMateOptionDetails* +delimitMateOptionSummary delimitMate.txt /*delimitMateOptionSummary* +delimitMateOptions delimitMate.txt /*delimitMateOptions* +delimitMateSmartQuotes delimitMate.txt /*delimitMateSmartQuotes* +delimitMateTodo delimitMate.txt /*delimitMateTodo* +delimitMateVisualWrapping delimitMate.txt /*delimitMateVisualWrapping* +delimitMate_WithinEmptyPair delimitMate.txt /*delimitMate_WithinEmptyPair* +fuf fuf.txt /*fuf* +fuf-abbreviation fuf.txt /*fuf-abbreviation* +fuf-about fuf.txt /*fuf-about* +fuf-author fuf.txt /*fuf-author* +fuf-bookmark-mode fuf.txt /*fuf-bookmark-mode* +fuf-buffer-mode fuf.txt /*fuf-buffer-mode* +fuf-cache fuf.txt /*fuf-cache* +fuf-callbackfile-mode fuf.txt /*fuf-callbackfile-mode* +fuf-callbackitem-mode fuf.txt /*fuf-callbackitem-mode* +fuf-changelist-mode fuf.txt /*fuf-changelist-mode* +fuf-changelog fuf.txt /*fuf-changelog* +fuf-commands fuf.txt /*fuf-commands* +fuf-contact fuf.txt /*fuf-contact* +fuf-detailed-topics fuf.txt /*fuf-detailed-topics* +fuf-dir-mode fuf.txt /*fuf-dir-mode* +fuf-dot-sequence fuf.txt /*fuf-dot-sequence* +fuf-file-mode fuf.txt /*fuf-file-mode* +fuf-givencmd-mode fuf.txt /*fuf-givencmd-mode* +fuf-givendir-mode fuf.txt /*fuf-givendir-mode* +fuf-givenfile-mode fuf.txt /*fuf-givenfile-mode* +fuf-help-mode fuf.txt /*fuf-help-mode* +fuf-hiding-menu fuf.txt /*fuf-hiding-menu* +fuf-information-file fuf.txt /*fuf-information-file* +fuf-installation fuf.txt /*fuf-installation* +fuf-introduction fuf.txt /*fuf-introduction* +fuf-jumplist-mode fuf.txt /*fuf-jumplist-mode* +fuf-line-mode fuf.txt /*fuf-line-mode* +fuf-migemo fuf.txt /*fuf-migemo* +fuf-modes fuf.txt /*fuf-modes* +fuf-mrucmd-mode fuf.txt /*fuf-mrucmd-mode* +fuf-mrufile-mode fuf.txt /*fuf-mrufile-mode* +fuf-multiple-search fuf.txt /*fuf-multiple-search* +fuf-options fuf.txt /*fuf-options* +fuf-options-for-Bookmark-mode fuf.txt /*fuf-options-for-Bookmark-mode* +fuf-options-for-all-modes fuf.txt /*fuf-options-for-all-modes* +fuf-options-for-buffer-mode fuf.txt /*fuf-options-for-buffer-mode* +fuf-options-for-changelist-mode fuf.txt /*fuf-options-for-changelist-mode* +fuf-options-for-dir-mode fuf.txt /*fuf-options-for-dir-mode* +fuf-options-for-file-mode fuf.txt /*fuf-options-for-file-mode* +fuf-options-for-help-mode fuf.txt /*fuf-options-for-help-mode* +fuf-options-for-jumplist-mode fuf.txt /*fuf-options-for-jumplist-mode* +fuf-options-for-line-mode fuf.txt /*fuf-options-for-line-mode* +fuf-options-for-mrucmd-mode fuf.txt /*fuf-options-for-mrucmd-mode* +fuf-options-for-mrufile-mode fuf.txt /*fuf-options-for-mrufile-mode* +fuf-options-for-quickfix-mode fuf.txt /*fuf-options-for-quickfix-mode* +fuf-options-for-tag-mode fuf.txt /*fuf-options-for-tag-mode* +fuf-options-for-taggedfile-mode fuf.txt /*fuf-options-for-taggedfile-mode* +fuf-quickfix-mode fuf.txt /*fuf-quickfix-mode* +fuf-reusing-window fuf.txt /*fuf-reusing-window* +fuf-search-patterns fuf.txt /*fuf-search-patterns* +fuf-sorting-of-completion-items fuf.txt /*fuf-sorting-of-completion-items* +fuf-tag-mode fuf.txt /*fuf-tag-mode* +fuf-taggedfile-mode fuf.txt /*fuf-taggedfile-mode* +fuf-thanks fuf.txt /*fuf-thanks* +fuf-usage fuf.txt /*fuf-usage* +fuf-vimrc-example fuf.txt /*fuf-vimrc-example* +fuf.txt fuf.txt /*fuf.txt* +fuzzyfinder fuf.txt /*fuzzyfinder* +g:fuf_abbrevMap fuf.txt /*g:fuf_abbrevMap* +g:fuf_bookmark_keyDelete fuf.txt /*g:fuf_bookmark_keyDelete* +g:fuf_bookmark_prompt fuf.txt /*g:fuf_bookmark_prompt* +g:fuf_bookmark_searchRange fuf.txt /*g:fuf_bookmark_searchRange* +g:fuf_bookmark_switchOrder fuf.txt /*g:fuf_bookmark_switchOrder* +g:fuf_buffer_mruOrder fuf.txt /*g:fuf_buffer_mruOrder* +g:fuf_buffer_prompt fuf.txt /*g:fuf_buffer_prompt* +g:fuf_buffer_switchOrder fuf.txt /*g:fuf_buffer_switchOrder* +g:fuf_changelist_prompt fuf.txt /*g:fuf_changelist_prompt* +g:fuf_changelist_switchOrder fuf.txt /*g:fuf_changelist_switchOrder* +g:fuf_dir_exclude fuf.txt /*g:fuf_dir_exclude* +g:fuf_dir_prompt fuf.txt /*g:fuf_dir_prompt* +g:fuf_dir_switchOrder fuf.txt /*g:fuf_dir_switchOrder* +g:fuf_enumeratingLimit fuf.txt /*g:fuf_enumeratingLimit* +g:fuf_file_exclude fuf.txt /*g:fuf_file_exclude* +g:fuf_file_prompt fuf.txt /*g:fuf_file_prompt* +g:fuf_file_switchOrder fuf.txt /*g:fuf_file_switchOrder* +g:fuf_help_cache_dir fuf.txt /*g:fuf_help_cache_dir* +g:fuf_help_prompt fuf.txt /*g:fuf_help_prompt* +g:fuf_help_switchOrder fuf.txt /*g:fuf_help_switchOrder* +g:fuf_ignoreCase fuf.txt /*g:fuf_ignoreCase* +g:fuf_infoFile fuf.txt /*g:fuf_infoFile* +g:fuf_jumplist_prompt fuf.txt /*g:fuf_jumplist_prompt* +g:fuf_jumplist_switchOrder fuf.txt /*g:fuf_jumplist_switchOrder* +g:fuf_keyNextMode fuf.txt /*g:fuf_keyNextMode* +g:fuf_keyNextPattern fuf.txt /*g:fuf_keyNextPattern* +g:fuf_keyOpen fuf.txt /*g:fuf_keyOpen* +g:fuf_keyOpenSplit fuf.txt /*g:fuf_keyOpenSplit* +g:fuf_keyOpenTabpage fuf.txt /*g:fuf_keyOpenTabpage* +g:fuf_keyOpenVsplit fuf.txt /*g:fuf_keyOpenVsplit* +g:fuf_keyPrevMode fuf.txt /*g:fuf_keyPrevMode* +g:fuf_keyPrevPattern fuf.txt /*g:fuf_keyPrevPattern* +g:fuf_keyPreview fuf.txt /*g:fuf_keyPreview* +g:fuf_keySwitchMatching fuf.txt /*g:fuf_keySwitchMatching* +g:fuf_learningLimit fuf.txt /*g:fuf_learningLimit* +g:fuf_line_prompt fuf.txt /*g:fuf_line_prompt* +g:fuf_line_switchOrder fuf.txt /*g:fuf_line_switchOrder* +g:fuf_maxMenuWidth fuf.txt /*g:fuf_maxMenuWidth* +g:fuf_modesDisable fuf.txt /*g:fuf_modesDisable* +g:fuf_mrucmd_exclude fuf.txt /*g:fuf_mrucmd_exclude* +g:fuf_mrucmd_maxItem fuf.txt /*g:fuf_mrucmd_maxItem* +g:fuf_mrucmd_prompt fuf.txt /*g:fuf_mrucmd_prompt* +g:fuf_mrucmd_switchOrder fuf.txt /*g:fuf_mrucmd_switchOrder* +g:fuf_mrufile_exclude fuf.txt /*g:fuf_mrufile_exclude* +g:fuf_mrufile_maxItem fuf.txt /*g:fuf_mrufile_maxItem* +g:fuf_mrufile_prompt fuf.txt /*g:fuf_mrufile_prompt* +g:fuf_mrufile_switchOrder fuf.txt /*g:fuf_mrufile_switchOrder* +g:fuf_patternSeparator fuf.txt /*g:fuf_patternSeparator* +g:fuf_previewHeight fuf.txt /*g:fuf_previewHeight* +g:fuf_promptHighlight fuf.txt /*g:fuf_promptHighlight* +g:fuf_quickfix_prompt fuf.txt /*g:fuf_quickfix_prompt* +g:fuf_quickfix_switchOrder fuf.txt /*g:fuf_quickfix_switchOrder* +g:fuf_reuseWindow fuf.txt /*g:fuf_reuseWindow* +g:fuf_smartBs fuf.txt /*g:fuf_smartBs* +g:fuf_splitPathMatching fuf.txt /*g:fuf_splitPathMatching* +g:fuf_tag_cache_dir fuf.txt /*g:fuf_tag_cache_dir* +g:fuf_tag_prompt fuf.txt /*g:fuf_tag_prompt* +g:fuf_tag_switchOrder fuf.txt /*g:fuf_tag_switchOrder* +g:fuf_taggedfile_cache_dir fuf.txt /*g:fuf_taggedfile_cache_dir* +g:fuf_taggedfile_prompt fuf.txt /*g:fuf_taggedfile_prompt* +g:fuf_taggedfile_switchOrder fuf.txt /*g:fuf_taggedfile_switchOrder* +g:fuf_timeFormat fuf.txt /*g:fuf_timeFormat* +g:fuf_useMigemo fuf.txt /*g:fuf_useMigemo* +g:snippets_dir snipMate.txt /*g:snippets_dir* +g:snips_author snipMate.txt /*g:snips_author* +g:vimwiki_auto_checkbox vimwiki.txt /*g:vimwiki_auto_checkbox* +g:vimwiki_badsyms vimwiki.txt /*g:vimwiki_badsyms* +g:vimwiki_browsers vimwiki.txt /*g:vimwiki_browsers* +g:vimwiki_camel_case vimwiki.txt /*g:vimwiki_camel_case* +g:vimwiki_fold_lists vimwiki.txt /*g:vimwiki_fold_lists* +g:vimwiki_fold_trailing_empty_lines vimwiki.txt /*g:vimwiki_fold_trailing_empty_lines* +g:vimwiki_folding vimwiki.txt /*g:vimwiki_folding* +g:vimwiki_global_ext vimwiki.txt /*g:vimwiki_global_ext* +g:vimwiki_hl_cb_checked vimwiki.txt /*g:vimwiki_hl_cb_checked* +g:vimwiki_hl_headers vimwiki.txt /*g:vimwiki_hl_headers* +g:vimwiki_list vimwiki.txt /*g:vimwiki_list* +g:vimwiki_list_ignore_newline vimwiki.txt /*g:vimwiki_list_ignore_newline* +g:vimwiki_listsyms vimwiki.txt /*g:vimwiki_listsyms* +g:vimwiki_lower vimwiki.txt /*g:vimwiki_lower* +g:vimwiki_menu vimwiki.txt /*g:vimwiki_menu* +g:vimwiki_stripsym vimwiki.txt /*g:vimwiki_stripsym* +g:vimwiki_table_auto_fmt vimwiki.txt /*g:vimwiki_table_auto_fmt* +g:vimwiki_upper vimwiki.txt /*g:vimwiki_upper* +g:vimwiki_use_calendar vimwiki.txt /*g:vimwiki_use_calendar* +g:vimwiki_use_mouse vimwiki.txt /*g:vimwiki_use_mouse* +g:vimwiki_w32_dir_enc vimwiki.txt /*g:vimwiki_w32_dir_enc* +getlatestvimscripts-install pi_getscript.txt /*getlatestvimscripts-install* +getscript pi_getscript.txt /*getscript* +getscript-autoinstall pi_getscript.txt /*getscript-autoinstall* +getscript-data pi_getscript.txt /*getscript-data* +getscript-history pi_getscript.txt /*getscript-history* +getscript-plugins pi_getscript.txt /*getscript-plugins* +getscript-start pi_getscript.txt /*getscript-start* +glvs pi_getscript.txt /*glvs* +glvs-alg pi_getscript.txt /*glvs-alg* +glvs-algorithm pi_getscript.txt /*glvs-algorithm* +glvs-autoinstall pi_getscript.txt /*glvs-autoinstall* +glvs-contents pi_getscript.txt /*glvs-contents* +glvs-copyright pi_getscript.txt /*glvs-copyright* +glvs-data pi_getscript.txt /*glvs-data* +glvs-dist-install pi_getscript.txt /*glvs-dist-install* +glvs-hist pi_getscript.txt /*glvs-hist* +glvs-install pi_getscript.txt /*glvs-install* +glvs-options pi_getscript.txt /*glvs-options* +glvs-plugins pi_getscript.txt /*glvs-plugins* +glvs-usage pi_getscript.txt /*glvs-usage* +i_CTRL-R_ snipMate.txt /*i_CTRL-R_* +list-snippets snipMate.txt /*list-snippets* +mark-configuration mark.txt /*mark-configuration* +mark-dependencies mark.txt /*mark-dependencies* +mark-description mark.txt /*mark-description* +mark-history mark.txt /*mark-history* +mark-ideas mark.txt /*mark-ideas* +mark-installation mark.txt /*mark-installation* +mark-integration mark.txt /*mark-integration* +mark-known-problems mark.txt /*mark-known-problems* +mark-limitations mark.txt /*mark-limitations* +mark-todo mark.txt /*mark-todo* +mark-usage mark.txt /*mark-usage* +mark.txt mark.txt /*mark.txt* +mark.vim mark.txt /*mark.vim* +multi_snip snipMate.txt /*multi_snip* +pi_getscript.txt pi_getscript.txt /*pi_getscript.txt* +project project.txt /*project* +project-adding-mappings project.txt /*project-adding-mappings* +project-example project.txt /*project-example* +project-flags project.txt /*project-flags* +project-inheritance project.txt /*project-inheritance* +project-invoking project.txt /*project-invoking* +project-mappings project.txt /*project-mappings* +project-plugin project.txt /*project-plugin* +project-settings project.txt /*project-settings* +project-syntax project.txt /*project-syntax* +project-tips project.txt /*project-tips* +project.txt project.txt /*project.txt* +showmarks showmarks.txt /*showmarks* +showmarks-changelog showmarks.txt /*showmarks-changelog* +showmarks-commands showmarks.txt /*showmarks-commands* +showmarks-configuration showmarks.txt /*showmarks-configuration* +showmarks-contents showmarks.txt /*showmarks-contents* +showmarks-highlighting showmarks.txt /*showmarks-highlighting* +showmarks-mappings showmarks.txt /*showmarks-mappings* +showmarks.txt showmarks.txt /*showmarks.txt* +snipMate snipMate.txt /*snipMate* +snipMate-$# snipMate.txt /*snipMate-$#* +snipMate-${#:} snipMate.txt /*snipMate-${#:}* +snipMate-${#} snipMate.txt /*snipMate-${#}* +snipMate-author snipMate.txt /*snipMate-author* +snipMate-commands snipMate.txt /*snipMate-commands* +snipMate-contact snipMate.txt /*snipMate-contact* +snipMate-description snipMate.txt /*snipMate-description* +snipMate-disadvantages snipMate.txt /*snipMate-disadvantages* +snipMate-expandtab snipMate.txt /*snipMate-expandtab* +snipMate-features snipMate.txt /*snipMate-features* +snipMate-filename snipMate.txt /*snipMate-filename* +snipMate-indenting snipMate.txt /*snipMate-indenting* +snipMate-placeholders snipMate.txt /*snipMate-placeholders* +snipMate-remap snipMate.txt /*snipMate-remap* +snipMate-settings snipMate.txt /*snipMate-settings* +snipMate-usage snipMate.txt /*snipMate-usage* +snipMate.txt snipMate.txt /*snipMate.txt* +snippet snipMate.txt /*snippet* +snippet-syntax snipMate.txt /*snippet-syntax* +snippets snipMate.txt /*snippets* +taglist-commands taglist.txt /*taglist-commands* +taglist-debug taglist.txt /*taglist-debug* +taglist-extend taglist.txt /*taglist-extend* +taglist-faq taglist.txt /*taglist-faq* +taglist-functions taglist.txt /*taglist-functions* +taglist-install taglist.txt /*taglist-install* +taglist-internet taglist.txt /*taglist-internet* +taglist-intro taglist.txt /*taglist-intro* +taglist-keys taglist.txt /*taglist-keys* +taglist-license taglist.txt /*taglist-license* +taglist-menu taglist.txt /*taglist-menu* +taglist-options taglist.txt /*taglist-options* +taglist-requirements taglist.txt /*taglist-requirements* +taglist-session taglist.txt /*taglist-session* +taglist-todo taglist.txt /*taglist-todo* +taglist-using taglist.txt /*taglist-using* +taglist.txt taglist.txt /*taglist.txt* +vcscommand vcscommand.txt /*vcscommand* +vcscommand-buffer-management vcscommand.txt /*vcscommand-buffer-management* +vcscommand-buffer-variables vcscommand.txt /*vcscommand-buffer-variables* +vcscommand-bugs vcscommand.txt /*vcscommand-bugs* +vcscommand-commands vcscommand.txt /*vcscommand-commands* +vcscommand-config vcscommand.txt /*vcscommand-config* +vcscommand-contents vcscommand.txt /*vcscommand-contents* +vcscommand-customize vcscommand.txt /*vcscommand-customize* +vcscommand-events vcscommand.txt /*vcscommand-events* +vcscommand-install vcscommand.txt /*vcscommand-install* +vcscommand-intro vcscommand.txt /*vcscommand-intro* +vcscommand-manual vcscommand.txt /*vcscommand-manual* +vcscommand-mappings vcscommand.txt /*vcscommand-mappings* +vcscommand-mappings-override vcscommand.txt /*vcscommand-mappings-override* +vcscommand-naming vcscommand.txt /*vcscommand-naming* +vcscommand-options vcscommand.txt /*vcscommand-options* +vcscommand-ssh vcscommand.txt /*vcscommand-ssh* +vcscommand-ssh-config vcscommand.txt /*vcscommand-ssh-config* +vcscommand-ssh-env vcscommand.txt /*vcscommand-ssh-env* +vcscommand-ssh-other vcscommand.txt /*vcscommand-ssh-other* +vcscommand-ssh-wrapper vcscommand.txt /*vcscommand-ssh-wrapper* +vcscommand-statusline vcscommand.txt /*vcscommand-statusline* +vcscommand.txt vcscommand.txt /*vcscommand.txt* +vimwiki vimwiki.txt /*vimwiki* +vimwiki-author vimwiki.txt /*vimwiki-author* +vimwiki-calendar vimwiki.txt /*vimwiki-calendar* +vimwiki-changelog vimwiki.txt /*vimwiki-changelog* +vimwiki-commands vimwiki.txt /*vimwiki-commands* +vimwiki-contents vimwiki.txt /*vimwiki-contents* +vimwiki-diary vimwiki.txt /*vimwiki-diary* +vimwiki-folding vimwiki.txt /*vimwiki-folding* +vimwiki-global-commands vimwiki.txt /*vimwiki-global-commands* +vimwiki-global-mappings vimwiki.txt /*vimwiki-global-mappings* +vimwiki-help vimwiki.txt /*vimwiki-help* +vimwiki-license vimwiki.txt /*vimwiki-license* +vimwiki-local-commands vimwiki.txt /*vimwiki-local-commands* +vimwiki-local-mappings vimwiki.txt /*vimwiki-local-mappings* +vimwiki-mappings vimwiki.txt /*vimwiki-mappings* +vimwiki-multiple-wikies vimwiki.txt /*vimwiki-multiple-wikies* +vimwiki-option-auto_export vimwiki.txt /*vimwiki-option-auto_export* +vimwiki-option-css_name vimwiki.txt /*vimwiki-option-css_name* +vimwiki-option-diary_header vimwiki.txt /*vimwiki-option-diary_header* +vimwiki-option-diary_index vimwiki.txt /*vimwiki-option-diary_index* +vimwiki-option-diary_link_count vimwiki.txt /*vimwiki-option-diary_link_count* +vimwiki-option-diary_rel_path vimwiki.txt /*vimwiki-option-diary_rel_path* +vimwiki-option-ext vimwiki.txt /*vimwiki-option-ext* +vimwiki-option-gohome vimwiki.txt /*vimwiki-option-gohome* +vimwiki-option-html_footer vimwiki.txt /*vimwiki-option-html_footer* +vimwiki-option-html_header vimwiki.txt /*vimwiki-option-html_header* +vimwiki-option-index vimwiki.txt /*vimwiki-option-index* +vimwiki-option-maxhi vimwiki.txt /*vimwiki-option-maxhi* +vimwiki-option-nested_syntaxes vimwiki.txt /*vimwiki-option-nested_syntaxes* +vimwiki-option-path vimwiki.txt /*vimwiki-option-path* +vimwiki-option-path_html vimwiki.txt /*vimwiki-option-path_html* +vimwiki-option-syntax vimwiki.txt /*vimwiki-option-syntax* +vimwiki-options vimwiki.txt /*vimwiki-options* +vimwiki-placeholders vimwiki.txt /*vimwiki-placeholders* +vimwiki-prerequisites vimwiki.txt /*vimwiki-prerequisites* +vimwiki-syntax vimwiki.txt /*vimwiki-syntax* +vimwiki-syntax-blockquotes vimwiki.txt /*vimwiki-syntax-blockquotes* +vimwiki-syntax-comments vimwiki.txt /*vimwiki-syntax-comments* +vimwiki-syntax-headers vimwiki.txt /*vimwiki-syntax-headers* +vimwiki-syntax-links vimwiki.txt /*vimwiki-syntax-links* +vimwiki-syntax-lists vimwiki.txt /*vimwiki-syntax-lists* +vimwiki-syntax-paragraphs vimwiki.txt /*vimwiki-syntax-paragraphs* +vimwiki-syntax-preformatted vimwiki.txt /*vimwiki-syntax-preformatted* +vimwiki-syntax-tables vimwiki.txt /*vimwiki-syntax-tables* +vimwiki-syntax-typefaces vimwiki.txt /*vimwiki-syntax-typefaces* +vimwiki-table-mappings vimwiki.txt /*vimwiki-table-mappings* +vimwiki-table-of-contents vimwiki.txt /*vimwiki-table-of-contents* +vimwiki-tables vimwiki.txt /*vimwiki-tables* +vimwiki-temporary-wiki vimwiki.txt /*vimwiki-temporary-wiki* +vimwiki-text-objects vimwiki.txt /*vimwiki-text-objects* +vimwiki-toc vimwiki.txt /*vimwiki-toc* +vimwiki-todo-lists vimwiki.txt /*vimwiki-todo-lists* +vimwiki.txt vimwiki.txt /*vimwiki.txt* +vimwiki_- vimwiki.txt /*vimwiki_-* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_wd vimwiki.txt /*vimwiki_wd* +vimwiki_wr vimwiki.txt /*vimwiki_wr* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_ vimwiki.txt /*vimwiki_* +vimwiki_= vimwiki.txt /*vimwiki_=* +vimwiki_gqq vimwiki.txt /*vimwiki_gqq* +vimwiki_gww vimwiki.txt /*vimwiki_gww* +vimwiki_i_ vimwiki.txt /*vimwiki_i_* +vimwiki_i_ vimwiki.txt /*vimwiki_i_* +viwmiki-global-options vimwiki.txt /*viwmiki-global-options* +viwmiki-local-options vimwiki.txt /*viwmiki-local-options* diff --git a/doc/tags-ja b/doc/tags-ja new file mode 100644 index 0000000..623493f --- /dev/null +++ b/doc/tags-ja @@ -0,0 +1,143 @@ +!_TAG_FILE_ENCODING utf-8 // +:FufAddBookmark fuf.jax /*:FufAddBookmark* +:FufAddBookmarkAsSelectedText fuf.jax /*:FufAddBookmarkAsSelectedText* +:FufBookmark fuf.jax /*:FufBookmark* +:FufBuffer fuf.jax /*:FufBuffer* +:FufChangeList fuf.jax /*:FufChangeList* +:FufDir fuf.jax /*:FufDir* +:FufDirWithCurrentBufferDir fuf.jax /*:FufDirWithCurrentBufferDir* +:FufDirWithFullCwd fuf.jax /*:FufDirWithFullCwd* +:FufEditInfo fuf.jax /*:FufEditInfo* +:FufFile fuf.jax /*:FufFile* +:FufFileWithCurrentBufferDir fuf.jax /*:FufFileWithCurrentBufferDir* +:FufFileWithFullCwd fuf.jax /*:FufFileWithFullCwd* +:FufHelp fuf.jax /*:FufHelp* +:FufJumpList fuf.jax /*:FufJumpList* +:FufLine fuf.jax /*:FufLine* +:FufMruCmd fuf.jax /*:FufMruCmd* +:FufMruFile fuf.jax /*:FufMruFile* +:FufQuickfix fuf.jax /*:FufQuickfix* +:FufRenewCache fuf.jax /*:FufRenewCache* +:FufTag fuf.jax /*:FufTag* +:FufTagWithCursorWord fuf.jax /*:FufTagWithCursorWord* +:FufTaggedFile fuf.jax /*:FufTaggedFile* +abc fuf.jax /*abc* +fuf fuf.jax /*fuf* +fuf-abbreviation fuf.jax /*fuf-abbreviation* +fuf-about fuf.jax /*fuf-about* +fuf-author fuf.jax /*fuf-author* +fuf-bookmark-mode fuf.jax /*fuf-bookmark-mode* +fuf-buffer-mode fuf.jax /*fuf-buffer-mode* +fuf-cache fuf.jax /*fuf-cache* +fuf-callbackfile-mode fuf.jax /*fuf-callbackfile-mode* +fuf-callbackitem-mode fuf.jax /*fuf-callbackitem-mode* +fuf-changelist-mode fuf.jax /*fuf-changelist-mode* +fuf-commands fuf.jax /*fuf-commands* +fuf-contact fuf.jax /*fuf-contact* +fuf-detailed-topics fuf.jax /*fuf-detailed-topics* +fuf-dir-mode fuf.jax /*fuf-dir-mode* +fuf-dot-sequence fuf.jax /*fuf-dot-sequence* +fuf-file-mode fuf.jax /*fuf-file-mode* +fuf-givencmd-mode fuf.jax /*fuf-givencmd-mode* +fuf-givendir-mode fuf.jax /*fuf-givendir-mode* +fuf-givenfile-mode fuf.jax /*fuf-givenfile-mode* +fuf-help-mode fuf.jax /*fuf-help-mode* +fuf-hiding-menu fuf.jax /*fuf-hiding-menu* +fuf-information-file fuf.jax /*fuf-information-file* +fuf-installation fuf.jax /*fuf-installation* +fuf-introduction fuf.jax /*fuf-introduction* +fuf-jumplist-mode fuf.jax /*fuf-jumplist-mode* +fuf-line-mode fuf.jax /*fuf-line-mode* +fuf-migemo fuf.jax /*fuf-migemo* +fuf-modes fuf.jax /*fuf-modes* +fuf-mrucmd-mode fuf.jax /*fuf-mrucmd-mode* +fuf-mrufile-mode fuf.jax /*fuf-mrufile-mode* +fuf-multiple-search fuf.jax /*fuf-multiple-search* +fuf-options fuf.jax /*fuf-options* +fuf-options-for-Bookmark-mode fuf.jax /*fuf-options-for-Bookmark-mode* +fuf-options-for-all-modes fuf.jax /*fuf-options-for-all-modes* +fuf-options-for-buffer-mode fuf.jax /*fuf-options-for-buffer-mode* +fuf-options-for-changelist-mode fuf.jax /*fuf-options-for-changelist-mode* +fuf-options-for-dir-mode fuf.jax /*fuf-options-for-dir-mode* +fuf-options-for-file-mode fuf.jax /*fuf-options-for-file-mode* +fuf-options-for-help-mode fuf.jax /*fuf-options-for-help-mode* +fuf-options-for-jumplist-mode fuf.jax /*fuf-options-for-jumplist-mode* +fuf-options-for-line-mode fuf.jax /*fuf-options-for-line-mode* +fuf-options-for-mrucmd-mode fuf.jax /*fuf-options-for-mrucmd-mode* +fuf-options-for-mrufile-mode fuf.jax /*fuf-options-for-mrufile-mode* +fuf-options-for-quickfix-mode fuf.jax /*fuf-options-for-quickfix-mode* +fuf-options-for-tag-mode fuf.jax /*fuf-options-for-tag-mode* +fuf-options-for-taggedfile-mode fuf.jax /*fuf-options-for-taggedfile-mode* +fuf-quickfix-mode fuf.jax /*fuf-quickfix-mode* +fuf-reusing-window fuf.jax /*fuf-reusing-window* +fuf-search-patterns fuf.jax /*fuf-search-patterns* +fuf-sorting-of-completion-items fuf.jax /*fuf-sorting-of-completion-items* +fuf-tag-mode fuf.jax /*fuf-tag-mode* +fuf-taggedfile-mode fuf.jax /*fuf-taggedfile-mode* +fuf-usage fuf.jax /*fuf-usage* +fuf-vimrc-example fuf.jax /*fuf-vimrc-example* +fuf.jax fuf.jax /*fuf.jax* +fuzzyfinder fuf.jax /*fuzzyfinder* +g:fuf_abbrevMap fuf.jax /*g:fuf_abbrevMap* +g:fuf_bookmark_keyDelete fuf.jax /*g:fuf_bookmark_keyDelete* +g:fuf_bookmark_prompt fuf.jax /*g:fuf_bookmark_prompt* +g:fuf_bookmark_searchRange fuf.jax /*g:fuf_bookmark_searchRange* +g:fuf_bookmark_switchOrder fuf.jax /*g:fuf_bookmark_switchOrder* +g:fuf_buffer_mruOrder fuf.jax /*g:fuf_buffer_mruOrder* +g:fuf_buffer_prompt fuf.jax /*g:fuf_buffer_prompt* +g:fuf_buffer_switchOrder fuf.jax /*g:fuf_buffer_switchOrder* +g:fuf_changelist_prompt fuf.jax /*g:fuf_changelist_prompt* +g:fuf_changelist_switchOrder fuf.jax /*g:fuf_changelist_switchOrder* +g:fuf_dir_exclude fuf.jax /*g:fuf_dir_exclude* +g:fuf_dir_prompt fuf.jax /*g:fuf_dir_prompt* +g:fuf_dir_switchOrder fuf.jax /*g:fuf_dir_switchOrder* +g:fuf_enumeratingLimit fuf.jax /*g:fuf_enumeratingLimit* +g:fuf_file_exclude fuf.jax /*g:fuf_file_exclude* +g:fuf_file_prompt fuf.jax /*g:fuf_file_prompt* +g:fuf_file_switchOrder fuf.jax /*g:fuf_file_switchOrder* +g:fuf_help_cache_dir fuf.jax /*g:fuf_help_cache_dir* +g:fuf_help_prompt fuf.jax /*g:fuf_help_prompt* +g:fuf_help_switchOrder fuf.jax /*g:fuf_help_switchOrder* +g:fuf_ignoreCase fuf.jax /*g:fuf_ignoreCase* +g:fuf_infoFile fuf.jax /*g:fuf_infoFile* +g:fuf_jumplist_prompt fuf.jax /*g:fuf_jumplist_prompt* +g:fuf_jumplist_switchOrder fuf.jax /*g:fuf_jumplist_switchOrder* +g:fuf_keyNextMode fuf.jax /*g:fuf_keyNextMode* +g:fuf_keyNextPattern fuf.jax /*g:fuf_keyNextPattern* +g:fuf_keyOpen fuf.jax /*g:fuf_keyOpen* +g:fuf_keyOpenSplit fuf.jax /*g:fuf_keyOpenSplit* +g:fuf_keyOpenTabpage fuf.jax /*g:fuf_keyOpenTabpage* +g:fuf_keyOpenVsplit fuf.jax /*g:fuf_keyOpenVsplit* +g:fuf_keyPrevMode fuf.jax /*g:fuf_keyPrevMode* +g:fuf_keyPrevPattern fuf.jax /*g:fuf_keyPrevPattern* +g:fuf_keyPreview fuf.jax /*g:fuf_keyPreview* +g:fuf_keySwitchMatching fuf.jax /*g:fuf_keySwitchMatching* +g:fuf_learningLimit fuf.jax /*g:fuf_learningLimit* +g:fuf_line_prompt fuf.jax /*g:fuf_line_prompt* +g:fuf_line_switchOrder fuf.jax /*g:fuf_line_switchOrder* +g:fuf_maxMenuWidth fuf.jax /*g:fuf_maxMenuWidth* +g:fuf_modesDisable fuf.jax /*g:fuf_modesDisable* +g:fuf_mrucmd_exclude fuf.jax /*g:fuf_mrucmd_exclude* +g:fuf_mrucmd_maxItem fuf.jax /*g:fuf_mrucmd_maxItem* +g:fuf_mrucmd_prompt fuf.jax /*g:fuf_mrucmd_prompt* +g:fuf_mrucmd_switchOrder fuf.jax /*g:fuf_mrucmd_switchOrder* +g:fuf_mrufile_exclude fuf.jax /*g:fuf_mrufile_exclude* +g:fuf_mrufile_maxItem fuf.jax /*g:fuf_mrufile_maxItem* +g:fuf_mrufile_prompt fuf.jax /*g:fuf_mrufile_prompt* +g:fuf_mrufile_switchOrder fuf.jax /*g:fuf_mrufile_switchOrder* +g:fuf_patternSeparator fuf.jax /*g:fuf_patternSeparator* +g:fuf_previewHeight fuf.jax /*g:fuf_previewHeight* +g:fuf_promptHighlight fuf.jax /*g:fuf_promptHighlight* +g:fuf_quickfix_prompt fuf.jax /*g:fuf_quickfix_prompt* +g:fuf_quickfix_switchOrder fuf.jax /*g:fuf_quickfix_switchOrder* +g:fuf_reuseWindow fuf.jax /*g:fuf_reuseWindow* +g:fuf_smartBs fuf.jax /*g:fuf_smartBs* +g:fuf_splitPathMatching fuf.jax /*g:fuf_splitPathMatching* +g:fuf_tag_cache_dir fuf.jax /*g:fuf_tag_cache_dir* +g:fuf_tag_prompt fuf.jax /*g:fuf_tag_prompt* +g:fuf_tag_switchOrder fuf.jax /*g:fuf_tag_switchOrder* +g:fuf_taggedfile_cache_dir fuf.jax /*g:fuf_taggedfile_cache_dir* +g:fuf_taggedfile_prompt fuf.jax /*g:fuf_taggedfile_prompt* +g:fuf_taggedfile_switchOrder fuf.jax /*g:fuf_taggedfile_switchOrder* +g:fuf_timeFormat fuf.jax /*g:fuf_timeFormat* +g:fuf_useMigemo fuf.jax /*g:fuf_useMigemo* diff --git a/doc/vcscommand.txt b/doc/vcscommand.txt new file mode 100644 index 0000000..28d4e63 --- /dev/null +++ b/doc/vcscommand.txt @@ -0,0 +1,819 @@ +*vcscommand.txt* vcscommand +Copyright (c) 2007 Bob Hiestand + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +For instructions on installing this file, type + :help add-local-help +inside Vim. + +Author: Bob Hiestand +Credits: Benji Fisher's excellent MatchIt documentation + +============================================================================== +1. Contents *vcscommand-contents* + + Installation : |vcscommand-install| + vcscommand Intro : |vcscommand| + vcscommand Manual : |vcscommand-manual| + Customization : |vcscommand-customize| + SSH "integration" : |vcscommand-ssh| + Changes from cvscommand : |cvscommand-changes| + Bugs : |vcscommand-bugs| + +============================================================================== + +2. vcscommand Installation *vcscommand-install* + +The vcscommand plugin comprises five files: vcscommand.vim, vcssvn.vim, +vcscvs.vim, vcssvk.vim and vcscommand.txt (this file). In order to install +the plugin, place the vcscommand.vim, vcssvn.vim, vcssvk.vim, and vcscvs.vim +files into a plugin directory in your runtime path (please see +|add-global-plugin| and |'runtimepath'|. + +This help file can be included in the VIM help system by copying it into a +'doc' directory in your runtime path and then executing the |:helptags| +command, specifying the full path of the 'doc' directory. Please see +|add-local-help| for more details. + +vcscommand may be customized by setting variables, creating maps, and +specifying event handlers. Please see |vcscommand-customize| for more +details. + +============================================================================== + +3. vcscommand Intro *vcscommand* + *vcscommand-intro* + +The vcscommand plugin provides global ex commands for manipulating +version-controlled source files, currently those controlled either by CVS or +Subversion. In general, each command operates on the current buffer and +accomplishes a separate source control function, such as update, commit, log, +and others (please see |vcscommand-commands| for a list of all available +commands). The results of each operation are displayed in a scratch buffer. +Several buffer variables are defined for those scratch buffers (please see +|vcscommand-buffer-variables|). + +The notion of "current file" means either the current buffer, or, in the case +of a directory buffer (such as Explorer or netrw buffers), the directory (and +all subdirectories) represented by the the buffer. + +For convenience, any vcscommand invoked on a vcscommand scratch buffer acts as +though it was invoked on the original file and splits the screen so that the +output appears in a new window. + +Many of the commands accept revisions as arguments. By default, most operate +on the most recent revision on the current branch if no revision is specified. + +Each vcscommand is mapped to a key sequence starting with the || +keystroke. The default mappings may be overridden by supplying different +mappings before the plugin is loaded, such as in the vimrc, in the standard +fashion for plugin mappings. For examples, please see +|vcscommand-mappings-override|. + +The vcscommand plugin may be configured in several ways. For more details, +please see |vcscommand-customize|. + +============================================================================== + +4. vcscommand Manual *vcscommand-manual* + +4.1 vcscommand commands *vcscommand-commands* + +vcscommand defines the following commands: + +|:VCSAdd| +|:VCSAnnotate| +|:VCSBlame| +|:VCSCommit| +|:VCSDelete| +|:VCSDiff| +|:VCSGotoOriginal| +|:VCSLog| +|:VCSRemove| +|:VCSRevert| +|:VCSReview| +|:VCSStatus| +|:VCSUpdate| +|:VCSVimDiff| + +The following commands are specific to CVS files: + +|:CVSEdit| +|:CVSEditors| +|:CVSUnedit| +|:CVSWatch| +|:CVSWatchAdd| +|:CVSWatchOn| +|:CVSWatchOff| +|:CVSWatchRemove| +|:CVSWatchers| + +:VCSAdd *:VCSAdd* + +This command adds the current file to source control. Please note, this does +not commit the newly-added file. All parameters to the command are passed to +the underlying VCS. + +:VCSAnnotate[!] *:VCSAnnotate* + +This command displays the current file with each line annotated with the +version in which it was most recently changed. If an argument is given, the +argument is used as a revision number to display. If not given an argument, +it uses the most recent version of the file (on the current branch, if under +CVS control). Additionally, if the current buffer is a VCSAnnotate buffer +already, the version number on the current line is used. + +If '!' is used, the view of the annotated buffer is split so that the +annotation is in a separate window from the content, and each is highlighted +separately. + +For CVS buffers, the 'VCSCommandCVSAnnotateParent' option, if set to non-zero, +will cause the above behavior to change. Instead of annotating the version on +the current line, the parent revision is used instead, crossing branches if +necessary. + +With no arguments the cursor will jump to the line in the annotated buffer +corresponding to the current line in the source buffer. + +:VCSBlame[!] *:VCSBlame* + +Alias for |:VCSAnnotate|. + +:VCSCommit[!] *:VCSCommit* + +This command commits changes to the current file to source control. + +If called with arguments, the arguments are the log message. + +If '!' is used, an empty log message is committed. + +If called with no arguments, this is a two-step command. The first step opens +a buffer to accept a log message. When that buffer is written, it is +automatically closed and the file is committed using the information from that +log message. The commit can be abandoned if the log message buffer is deleted +or wiped before being written. + +Alternatively, the mapping that is used to invoke :VCSCommit (by default +||cc, please see |vcscommand-mappings|) can be used in the log message +buffer in Normal mode to immediately commit. This is useful if the +|VCSCommandCommitOnWrite| variable is set to 0 to disable the normal +commit-on-write behavior. + +:VCSDelete *:VCSDelete* + +Deletes the current file and removes it from source control. All parameters +to the command are passed to the underlying VCS. + +:VCSDiff *:VCSDiff* + +With no arguments, this displays the differences between the current file and +its parent version under source control in a new scratch buffer. + +With one argument, the diff is performed on the current file against the +specified revision. + +With two arguments, the diff is performed between the specified revisions of +the current file. + +For CVS, this command uses the |VCSCommandCVSDiffOpt| variable to specify diff +options. If that variable does not exist, a plugin-specific default is used. +If you wish to have no options, then set it to the empty string. + +For SVN, this command uses the |VCSCommandSVNDiffOpt| variable to specify diff +options. If that variable does not exist, the SVN default is used. +Additionally, |VCSCommandSVNDiffExt| can be used to select an external diff +application. + +:VCSGotoOriginal *:VCSGotoOriginal* + +This command jumps to the source buffer if the current buffer is a VCS scratch +buffer. + +:VCSGotoOriginal! + +Like ":VCSGotoOriginal" but also executes :bufwipeout on all VCS scrach +buffers associated with the original file. + +:VCSInfo *:VCSInfo* + +This command displays extended information about the current file in a new +scratch buffer. + +:VCSLock *:VCSLock* + +This command locks the current file in order to prevent other users from +concurrently modifying it. The exact semantics of this command depend on the +underlying VCS. This does nothing in CVS. All parameters are passed to the +underlying VCS. + +:VCSLog *:VCSLog* + +Displays the version history of the current file in a new scratch buffer. If +there is one parameter supplied, it is taken as as a revision parameters to be +passed through to the underlying VCS. Otherwise, all parameters are passed to +the underlying VCS. + +:VCSRemove *:VCSRemove* + +Alias for |:VCSDelete|. + +:VCSRevert *:VCSRevert* + +This command replaces the current file with the most recent version from the +repository in order to wipe out any undesired changes. + +:VCSReview *:VCSReview* + +Displays a particular version of the current file in a new scratch buffer. If +no argument is given, the most recent version of the file on the current +branch is retrieved. + +:VCSStatus *:VCSStatus* + +Displays versioning information about the current file in a new scratch +buffer. All parameters are passed to the underlying VCS. + + +:VCSUnlock *:VCSUnlock* + +Unlocks the current file in order to allow other users from concurrently +modifying it. The exact semantics of this command depend on the underlying +VCS. All parameters are passed to the underlying VCS. + +:VCSUpdate *:VCSUpdate* + +Updates the current file with any relevant changes from the repository. This +intentionally does not automatically reload the current buffer, though vim +should prompt the user to do so if the underlying file is altered by this +command. + +:VCSVimDiff *:VCSVimDiff* + +Uses vimdiff to display differences between versions of the current file. + +If no revision is specified, the most recent version of the file on the +current branch is used. With one argument, that argument is used as the +revision as above. With two arguments, the differences between the two +revisions is displayed using vimdiff. + +With either zero or one argument, the original buffer is used to perform the +vimdiff. When the scratch buffer is closed, the original buffer will be +returned to normal mode. + +Once vimdiff mode is started using the above methods, additional vimdiff +buffers may be added by passing a single version argument to the command. +There may be up to 4 vimdiff buffers total. + +Using the 2-argument form of the command resets the vimdiff to only those 2 +versions. Additionally, invoking the command on a different file will close +the previous vimdiff buffers. + +:CVSEdit *:CVSEdit* + +This command performs "cvs edit" on the current file. Yes, the output buffer +in this case is almost completely useless. + +:CVSEditors *:CVSEditors* + +This command performs "cvs edit" on the current file. + +:CVSUnedit *:CVSUnedit* + +Performs "cvs unedit" on the current file. Again, yes, the output buffer here +is basically useless. + +:CVSWatch *:CVSWatch* + +This command takes an argument which must be one of [on|off|add|remove]. The +command performs "cvs watch" with the given argument on the current file. + +:CVSWatchAdd *:CVSWatchAdd* + +This command is an alias for ":CVSWatch add" + +:CVSWatchOn *:CVSWatchOn* + +This command is an alias for ":CVSWatch on" + +:CVSWatchOff *:CVSWatchOff* + +This command is an alias for ":CVSWatch off" + +:CVSWatchRemove *:CVSWatchRemove* + +This command is an alias for ":CVSWatch remove" + +:CVSWatchers *:CVSWatchers* + +This command performs "cvs watchers" on the current file. + +4.2 Mappings *vcscommand-mappings* + +By default, a mapping is defined for each command. These mappings execute the +default (no-argument) form of each command. + +||ca VCSAdd +||cn VCSAnnotate +||cN VCSAnnotate! +||cc VCSCommit +||cD VCSDelete +||cd VCSDiff +||cg VCSGotoOriginal +||cG VCSGotoOriginal! +||ci VCSInfo +||cl VCSLog +||cL VCSLock +||cr VCSReview +||cs VCSStatus +||cu VCSUpdate +||cU VCSUnlock +||cv VCSVimDiff + +Only for CVS buffers: + +||ce CVSEdit +||cE CVSEditors +||ct CVSUnedit +||cwv CVSWatchers +||cwa CVSWatchAdd +||cwn CVSWatchOn +||cwf CVSWatchOff +||cwf CVSWatchRemove + + *vcscommand-mappings-override* + +The default mappings can be overridden by user-provided instead by mapping to +CommandName. This is especially useful when these mappings collide with +other existing mappings (vim will warn of this during plugin initialization, +but will not clobber the existing mappings). + +There are three methods for controlling mapping: + +First, maps can be overriden for individual commands. For instance, to +override the default mapping for :VCSAdd to set it to '\add', add the +following to the vimrc: + +nmap \add VCSAdd + +Second, the default map prefix ('c') can be overridden by defining the +|VCSCommandMapPrefix| variable. + +Third, the entire set of default maps can be overridden by defining the +|VCSCommandMappings| variable. + + +4.3 Automatic buffer variables *vcscommand-buffer-variables* + +Several buffer variables are defined in each vcscommand result buffer. These +may be useful for additional customization in callbacks defined in the event +handlers (please see |vcscommand-events|). + +The following variables are automatically defined: + +b:VCSCommandOriginalBuffer *b:VCSCommandOriginalBuffer* + +This variable is set to the buffer number of the source file. + +b:VCSCommandCommand *b:VCSCommandCommand* + +This variable is set to the name of the vcscommand that created the result +buffer. + +b:VCSCommandSourceFile *b:VCSCommandSourceFile* + +This variable is set to the name of the original file under source control. + +b:VCSCommandVCSType *b:VCSCommandVCSType* + +This variable is set to the type of the source control. This variable is also +set on the original file itself. +============================================================================== + +5. Configuration and customization *vcscommand-customize* + *vcscommand-config* + +The vcscommand plugin can be configured in several ways: by setting +configuration variables (see |vcscommand-options|) or by defining vcscommand +event handlers (see |vcscommand-events|). Additionally, the vcscommand plugin +supports a customized status line (see |vcscommand-statusline| and +|vcscommand-buffer-management|). + +5.1 vcscommand configuration variables *vcscommand-options* + +Several variables affect the plugin's behavior. These variables are checked +at time of execution, and may be defined at the window, buffer, or global +level and are checked in that order of precedence. + + +The following variables are available: + +|VCSCommandCommitOnWrite| +|VCSCommandCVSDiffOpt| +|VCSCommandCVSExec| +|VCSCommandDeleteOnHide| +|VCSCommandDiffSplit| +|VCSCommandDisableAll| +|VCSCommandDisableMappings| +|VCSCommandDisableExtensionMappings| +|VCSCommandEdit| +|VCSCommandEnableBufferSetup| +|VCSCommandMappings| +|VCSCommandMapPrefix| +|VCSCommandResultBufferNameExtension| +|VCSCommandResultBufferNameFunction| +|VCSCommandSplit| +|VCSCommandSVKExec| +|VCSCommandSVNDiffExt| +|VCSCommandSVNDiffOpt| +|VCSCommandSVNExec| +|VCSCommandVCSTypeOverride| + +VCSCommandCommitOnWrite *VCSCommandCommitOnWrite* + +This variable, if set to a non-zero value, causes the pending commit +to take place immediately as soon as the log message buffer is written. +If set to zero, only the VCSCommit mapping will cause the pending commit to +occur. If not set, it defaults to 1. + +VCSCommandCVSExec *VCSCommandCVSExec* + +This variable controls the executable used for all CVS commands If not set, +it defaults to "cvs". + +VCSCommandDeleteOnHide *VCSCommandDeleteOnHide* + +This variable, if set to a non-zero value, causes the temporary result buffers +to automatically delete themselves when hidden. + +VCSCommandCVSDiffOpt *VCSCommandCVSDiffOpt* + +This variable, if set, determines the options passed to the diff command of +CVS. If not set, it defaults to 'u'. + +VCSCommandDiffSplit *VCSCommandDiffSplit* + +This variable overrides the |VCSCommandSplit| variable, but only for buffers +created with |:VCSVimDiff|. + +VCSCommandDisableAll *VCSCommandDisableAll* + +This variable, if set, prevents the plugin or any extensions from loading at +all. This is useful when a single runtime distribution is used on multiple +systems with varying versions. + +VCSCommandDisableMappings *VCSCommandDisableMappings* + +This variable, if set to a non-zero value, prevents the default command +mappings from being set. This supercedes +|VCSCommandDisableExtensionMappings|. + +VCSCommandDisableExtensionMappings *VCSCommandDisableExtensionMappings* + +This variable, if set to a non-zero value, prevents the default command +mappings from being set for commands specific to an individual VCS. + +VCSCommandEdit *VCSCommandEdit* + +This variable controls whether the original buffer is replaced ('edit') or +split ('split'). If not set, it defaults to 'split'. + +VCSCommandEnableBufferSetup *VCSCommandEnableBufferSetup* + +This variable, if set to a non-zero value, activates VCS buffer management +mode see (|vcscommand-buffer-management|). This mode means that the +'VCSCommandBufferInfo' variable is filled with version information if the file +is VCS-controlled. This is useful for displaying version information in the +status bar. + +VCSCommandMappings *VCSCommandMappings* + +This variable, if set, overrides the default mappings used for shortcuts. It +should be a List of 2-element Lists, each containing a shortcut and function +name pair. The value of the '|VCSCommandMapPrefix|' variable will be added to +each shortcut. + +VCSCommandMapPrefix *VCSCommandMapPrefix* + +This variable, if set, overrides the default mapping prefix ('c'). +This allows customization of the mapping space used by the vcscommand +shortcuts. + +VCSCommandResultBufferNameExtension *VCSCommandResultBufferNameExtension* + +This variable, if set to a non-blank value, is appended to the name of the VCS +command output buffers. For example, '.vcs'. Using this option may help +avoid problems caused by autocommands dependent on file extension. + +VCSCommandResultBufferNameFunction *VCSCommandResultBufferNameFunction* + +This variable, if set, specifies a custom function for naming VCS command +output buffers. This function is expected to return the new buffer name, and +will be passed the following arguments: + + command - name of the VCS command being executed (such as 'Log' or + 'Diff'). + + originalBuffer - buffer number of the source file. + + vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN'). + + statusText - extra text associated with the VCS action (such as version + numbers). + +VCSCommandSplit *VCSCommandSplit* + +This variable controls the orientation of the various window splits that +may occur. + +If set to 'horizontal', the resulting windows will be on stacked on top of +one another. If set to 'vertical', the resulting windows will be +side-by-side. If not set, it defaults to 'horizontal' for all but +VCSVimDiff windows. VCSVimDiff windows default to the user's 'diffopt' +setting, if set, otherwise 'vertical'. + +VCSCommandSVKExec *VCSCommandSVKExec* + +This variable controls the executable used for all SVK commands If not set, +it defaults to "svk". + +VCSCommandSVNDiffExt *VCSCommandSVNDiffExt* + +This variable, if set, is passed to SVN via the --diff-cmd command to select +an external application for performing the diff. + +VCSCommandSVNDiffOpt *VCSCommandSVNDiffOpt* + +This variable, if set, determines the options passed with the '-x' parameter +to the SVN diff command. If not set, no options are passed. + +VCSCommandSVNExec *VCSCommandSVNExec* + +This variable controls the executable used for all SVN commands If not set, +it defaults to "svn". + +VCSCommandVCSTypeOverride *VCSCommandVCSTypeOverride* + +This variable allows the VCS type detection to be overridden on a path-by-path +basis. The value of this variable is expected to be a List of Lists. Each +item in the high-level List is a List containing two elements. The first +element is a regular expression that will be matched against the full file +name of a given buffer. If it matches, the second element will be used as the +VCS type. + +5.2 VCSCommand events *vcscommand-events* + +For additional customization, vcscommand can trigger user-defined events. +Event handlers are provided by defining User event autocommands (see +|autocommand|, |User|) in the vcscommand group with patterns matching the +event name. + +For instance, the following could be added to the vimrc to provide a 'q' +mapping to quit a vcscommand scratch buffer: + +augroup VCSCommand + au User VCSBufferCreated silent! nmap q :bwipeout +augroup END + +The following hooks are available: + +VCSBufferCreated This event is fired just after a vcscommand + result buffer is created and populated. It is + executed within the context of the vcscommand + buffer. The vcscommand buffer variables may + be useful for handlers of this event (please + see |vcscommand-buffer-variables|). + +VCSBufferSetup This event is fired just after vcscommand buffer + setup occurs, if enabled. + +VCSPluginInit This event is fired when the vcscommand plugin + first loads. + +VCSPluginFinish This event is fired just after the vcscommand + plugin loads. + +VCSVimDiffFinish This event is fired just after the VCSVimDiff + command executes to allow customization of, + for instance, window placement and focus. + +Additionally, there is another hook which is used internally to handle loading +the multiple scripts in order. This hook should probably not be used by an +end user without a good idea of how it works. Among other things, any events +associated with this hook are cleared after they are executed (during +vcscommand.vim script initialization). + +VCSLoadExtensions This event is fired just before the + VCSPluginFinish. It is used internally to + execute any commands from the VCS + implementation plugins that needs to be + deferred until the primary plugin is + initialized. + +5.3 vcscommand buffer naming *vcscommand-naming* + +vcscommand result buffers use the following naming convention: +[{VCS type} {VCS command} {Source file name}] + +If additional buffers are created that would otherwise conflict, a +distinguishing number is added: + +[{VCS type} {VCS command} {Source file name}] (1,2, etc) + +5.4 vcscommand status line support *vcscommand-statusline* + +It is intended that the user will customize the |'statusline'| option to +include vcscommand result buffer attributes. A sample function that may be +used in the |'statusline'| option is provided by the plugin, +VCSCommandGetStatusLine(). In order to use that function in the status line, do +something like the following: + +set statusline=%<%f\ %{VCSCommandGetStatusLine()}\ %h%m%r%=%l,%c%V\ %P + +of which %{VCSCommandGetStatusLine()} is the relevant portion. + +The sample VCSCommandGetStatusLine() function handles both vcscommand result +buffers and VCS-managed files if vcscommand buffer management is enabled +(please see |vcscommand-buffer-management|). + +5.5 vcscommand buffer management *vcscommand-buffer-management* + +The vcscommand plugin can operate in buffer management mode, which means that +it attempts to set a buffer variable ('VCSCommandBufferInfo') upon entry into +a buffer. This is rather slow because it means that the VCS will be invoked +at each entry into a buffer (during the |BufEnter| autocommand). + +This mode is disabled by default. In order to enable it, set the +|VCSCommandEnableBufferSetup| variable to a true (non-zero) value. Enabling +this mode simply provides the buffer variable mentioned above. The user must +explicitly include information from the variable in the |'statusline'| option +if they are to appear in the status line (but see |vcscommand-statusline| for +a simple way to do that). + +The 'VCSCommandBufferInfo' variable is a list which contains, in order, the +revision of the current file, the latest revision of the file in the +repository, and (for CVS) the name of the branch. If those values cannot be +determined, the list is a single element: 'Unknown'. + +============================================================================== + +6. SSH "integration" *vcscommand-ssh* + +The following instructions are intended for use in integrating the +vcscommand.vim plugin with an SSH-based CVS environment. + +Familiarity with SSH and CVS are assumed. + +These instructions assume that the intent is to have a message box pop up in +order to allow the user to enter a passphrase. If, instead, the user is +comfortable using certificate-based authentication, then only instructions +6.1.1 and 6.1.2 (and optionally 6.1.4) need to be followed; ssh should then +work transparently. + +6.1 Environment settings *vcscommand-ssh-env* + +6.1.1 CVSROOT should be set to something like: + + :ext:user@host:/path_to_repository + +6.1.2 CVS_RSH should be set to: + + ssh + + Together, those settings tell CVS to use ssh as the transport when + performing CVS calls. + +6.1.3 SSH_ASKPASS should be set to the password-dialog program. In my case, + running gnome, it's set to: + + /usr/libexec/openssh/gnome-ssh-askpass + + This tells SSH how to get passwords if no input is available. + +6.1.4 OPTIONAL. You may need to set SSH_SERVER to the location of the cvs + executable on the remote (server) machine. + +6.2 CVS wrapper program *vcscommand-ssh-wrapper* + +Now you need to convince SSH to use the password-dialog program. This means +you need to execute SSH (and therefore CVS) without standard input. The +following script is a simple perl wrapper that dissasociates the CVS command +from the current terminal. Specific steps to do this may vary from system to +system; the following example works for me on linux. + +#!/usr/bin/perl -w +use strict; +use POSIX qw(setsid); +open STDIN, '/dev/null'; +fork and do {wait; exit;}; +setsid; +exec('cvs', @ARGV); + +6.3 Configuring vcscommand.vim *vcscommand-ssh-config* + +At this point, you should be able to use your wrapper script to invoke CVS with +various commands, and get the password dialog. All that's left is to make CVS +use your newly-created wrapper script. + +6.3.1 Tell vcscommand.vim what CVS executable to use. The easiest way to do this + is globally, by putting the following in your .vimrc: + + let VCSCommandCVSExec=/path/to/cvs/wrapper/script + +6.4 Where to go from here *vcscommand-ssh-other* + +The script given above works even when non-SSH CVS connections are used, +except possibly when interactively entering the message for CVS commit log +(depending on the editor you use... VIM works fine). Since the vcscommand.vim +plugin handles that message without a terminal, the wrapper script can be used +all the time. + +This allows mixed-mode operation, where some work is done with SSH-based CVS +repositories, and others with pserver or local access. + +It is possible, though beyond the scope of the plugin, to dynamically set the +CVS executable based on the CVSROOT for the file being edited. The user +events provided (such as VCSBufferCreated and VCSBufferSetup) can be used to +set a buffer-local value (b:VCSCommandCVSExec) to override the CVS executable +on a file-by-file basis. Alternatively, much the same can be done (less +automatically) by the various project-oriented plugins out there. + +It is highly recommended for ease-of-use that certificates with no passphrase +or ssh-agent are employed so that the user is not given the password prompt +too often. + +============================================================================== + +7. Changes from cvscommand *cvscommand-changes* + +1. Require Vim 7 in order to leverage several convenient features; also +because I wanted to play with Vim 7. + +2. Renamed commands to start with 'VCS' instead of 'CVS'. The exceptions are +the 'CVSEdit' and 'CVSWatch' family of commands, which are specific to CVS. + +3. Renamed options, events to start with 'VCSCommand'. + +4. Removed option to jump to the parent version of the current line in an +annotated buffer, as opposed to the version on the current line. This made +little sense in the branching scheme used by subversion, where jumping to a +parent branch required finding a different location in the repository. It +didn't work consistently in CVS anyway. + +5. Removed option to have nameless scratch buffers. + +6. Changed default behavior of scratch buffers to split the window instead of +displaying in the current window. This may still be overridden using the +'VCSCommandEdit' option. + +7. Split plugin into multiple plugins. + +8. Added 'VCSLock' and 'VCSUnlock' commands. These are implemented for +subversion but not for CVS. These were not kept specific to subversion as they +seemed more general in nature and more likely to be supported by any future VCS +supported by this plugin. + +9. Changed name of buffer variables set by commands. + +'b:cvsOrigBuffNR' became 'b:VCSCommandOriginalBuffer' +'b:cvscmd' became 'b:VCSCommandCommand' + +10. Added new automatic variables to command result buffers. + +'b:VCSCommandSourceFile' +'b:VCSCommandVCSType' + +============================================================================== + +8. Known bugs *vcscommand-bugs* + +Please let me know if you run across any. + +CVSUnedit may, if a file is changed from the repository, provide prompt text +to determine whether the changes should be thrown away. Currently, that text +shows up in the CVS result buffer as information; there is no way for the user +to actually respond to the prompt and the CVS unedit command does nothing. If +this really bothers anyone, please let me know. + +VCSVimDiff, when using the original (real) source buffer as one of the diff +buffers, uses some hacks to try to restore the state of the original buffer +when the scratch buffer containing the other version is destroyed. There may +still be bugs in here, depending on many configuration details. + +vim:tw=78:ts=8:ft=help diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt new file mode 100644 index 0000000..b8836b9 --- /dev/null +++ b/doc/vimwiki.txt @@ -0,0 +1,1844 @@ +*vimwiki.txt* A Personal Wiki for Vim + + __ __ ______ __ __ ______ __ __ ______ ~ + /\ \/\ \/\__ _\ /'\_/`\/\ \ __/\ \/\__ _\ /\ \/\ \ /\__ _\ ~ + \ \ \ \ \/_/\ \/ /\ \ \ \/\ \ \ \/_/\ \/ \ \ \/'/'\/_/\ \/ ~ + \ \ \ \ \ \ \ \ \ \ \__\ \ \ \ \ \ \ \ \ \ \ \ \ , < \ \ \ ~ + \ \ \_/ \ \_\ \__\ \ \_/\ \ \ \_/ \_\ \ \_\ \__\ \ \\`\ \_\ \__ ~ + \ `\___/ /\_____\\ \_\\ \_\ `\___x___/ /\_____\\ \_\ \_\ /\_____\~ + `\/__/ \/_____/ \/_/ \/_/'\/__//__/ \/_____/ \/_/\/_/ \/_____/~ + + Version: 0.9.9 + +============================================================================== +CONTENTS *vimwiki-contents* + + 1. Intro |vimwiki| + 2. Prerequisites |vimwiki-prerequisites| + 3. Mappings |vimwiki-mappings| + 3.1. Global mappings |vimwiki-global-mappings| + 3.2. Local mappings |vimwiki-local-mappings| + 3.3. Text objects |vimwiki-text-objects| + 4. Commands |vimwiki-commands| + 4.1. Global commands |vimwiki-global-commands| + 4.2. Local commands |vimwiki-local-commands| + 5. Wiki syntax |vimwiki-syntax| + 5.1. Typefaces |vimwiki-syntax-typefaces| + 5.2. Links |vimwiki-syntax-links| + 5.3. Headers |vimwiki-syntax-headers| + 5.4. Paragraphs |vimwiki-syntax-paragraphs| + 5.5. Lists |vimwiki-syntax-lists| + 5.6. Tables |vimwiki-syntax-tables| + 5.7. Preformatted text |vimwiki-syntax-preformatted| + 5.8. Blockquotes |vimwiki-syntax-blockquotes| + 5.9. Comments |vimwiki-syntax-comments| + 6. Folding/Outline |vimwiki-folding| + 7. Placeholders |vimwiki-placeholders| + 7.1 Table of Contents |vimwiki-table-of-contents| + 8. Todo lists |vimwiki-todo-lists| + 9. Tables |vimwiki-tables| + 10. Diary |vimwiki-diary| + 11. Options |vimwiki-options| + 12. Help |vimwiki-help| + 13. Author |vimwiki-author| + 14. Changelog |vimwiki-changelog| + 15. License |vimwiki-license| + + +============================================================================== +1. Intro *vimwiki* + +Vimwiki is a personal wiki for Vim -- a number of linked text files that have +their own syntax highlighting. + +With vimwiki you can: + - organize notes and ideas; + - manage todo-lists; + - write documentation. + +To do a quick start press ww (this is usually \ww) to go to your index +wiki file. By default it is located in: > + ~/vimwiki/index.wiki + +Feed it with the following example: + += My knowledge base = + * MyUrgentTasks -- things to be done _yesterday_!!! + * ProjectGutenberg -- good books are power. + * ScratchPad -- various temporary stuff. + + +Notice that ProjectGutenberg, MyUrgentTasks and ScratchPad highlighted as +errors. These are links in CamelCase form that do not exists yet. (CamelCase +form -- capitalized word connected with other capitalized words) + +Place cursor on ProjectGutenberg and press . Now you are in +ProjectGutenberg. Edit and save it, then press Backspace to return to previous +wiki file. You should see the difference now -- ProjectGutenberg is +highlighted as a link. + + +============================================================================== +2. Prerequisites *vimwiki-prerequisites* + +Make sure you have these settings in your vimrc file: > + set nocompatible + filetype plugin on + syntax on + +Without them Vimwiki will not work properly. + + +============================================================================== +3. Mappings *vimwiki-mappings* + +There are global and local mappings in vimwiki. + +------------------------------------------------------------------------------ +3.1. Global mappings *vimwiki-global-mappings* + +[count]ww or VimwikiGoHome + Open index file of the [count]'s wiki. + + ww opens first wiki from |g:vimwiki_list|. + 1ww as above opens first wiki from |g:vimwiki_list|. + 2ww opens second wiki from |g:vimwiki_list|. + 3ww opens third wiki from |g:vimwiki_list|. + etc. + To remap: > + :map w VimwikiGoHome +< +See also|:VimwikiGoHome| + + +[count]wt or VimwikiTabGoHome + Open index file of the [count]'s wiki in a new tab. + + wt tabopens first wiki from |g:vimwiki_list|. + 1wt as above tabopens first wiki from |g:vimwiki_list|. + 2wt tabopens second wiki from |g:vimwiki_list|. + 3wt tabopens third wiki from |g:vimwiki_list|. + etc. + To remap: > + :map t VimwikiTabGoHome +< +See also|:VimwikiTabGoHome| + + +ws or VimwikiUISelect + List and select available wikies. + To remap: > + :map wq VimwikiUISelect +< +See also|:VimwikiUISelect| + + +[count]ww or VimwikiMakeDiaryNote + Open diary wiki-file for today of the [count]'s wiki. + + ww opens diary wiki-file for today in the first wiki + from |g:vimwiki_list|. + 1ww as above opens diary wiki-file for today in the + first wiki from |g:vimwiki_list|. + 2ww opens diary wiki-file for today in the second wiki + from |g:vimwiki_list|. + 3ww opens diary wiki-file for today in the third wiki + from |g:vimwiki_list|. + etc. + To remap: > + :map d VimwikiMakeDiaryNote +< +See also|:VimwikiMakeDiaryNote| + + +[count]wt or VimwikiTabMakeDiaryNote + Open diary wiki-file for today of the [count]'s wiki in a new tab. + + wt tabopens diary wiki-file for today in the first + wiki from |g:vimwiki_list|. + 1wt as above tabopens diary wiki-file for today in the + first wiki from |g:vimwiki_list|. + 2wt tabopens diary wiki-file for today in the second + wiki from |g:vimwiki_list|. + 3wt tabopens diary wiki-file for today in the third + wiki from |g:vimwiki_list|. + etc. + To remap: > + :map dt VimwikiTabMakeDiaryNote +< +See also|:VimwikiTabMakeDiaryNote| + + +------------------------------------------------------------------------------ +3.2. Local mappings + +NORMAL MODE *vimwiki-local-mappings* + *vimwiki_* + Follow/Create WikiWord. + Maps to|:VimwikiFollowWord|. + To remap: > + :map wf VimwikiFollowWord +< + *vimwiki_* + Split and follow/create WikiWord + Maps to|:VimwikiSplitWord|. + To remap: > + :map we VimwikiSplitWord +< + *vimwiki_* + Vertical split and follow/create WikiWord + Maps to|:VimwikiVSplitWord|. + To remap: > + :map wq VimwikiVSplitWord +< + *vimwiki_* + Go back to previous WikiWord + Maps to|:VimwikiGoBackWord|. + To remap: > + :map wb VimwikiGoBackWord +< + *vimwiki_* + Find next WikiWord + Maps to|:VimwikiNextWord|. + To remap: > + :map wn VimwikiNextWord +< + *vimwiki_* + Find previous WikiWord + Maps to|:VimwikiPrevWord|. + To remap: > + :map wp VimwikiPrevWord +< + *vimwiki_wd* +wd Delete WikiWord you are in. + Maps to|:VimwikiDeleteWord|. + To remap: > + :map dd VimwikiDeleteWord +< + *vimwiki_wr* +wr Rename WikiWord you are in. + Maps to|:VimwikiRenameWord|. + To remap: > + :map rr VimwikiRenameWord +< + *vimwiki_* + Toggle list item on/off (checked/unchecked) + Maps to|:VimwikiToggleListItem|. + To remap: > + :map tt VimwikiToggleListItem +< See |vimwiki-todo-lists|. + + *vimwiki_=* += Add header level. Create if needed. + There is nothing to indent with '==' command in + vimwiki, so it should be ok to use '=' here. + + *vimwiki_-* +- Remove header level. + + + *vimwiki_gqq* *vimwiki_gww* +gqq Format table. If you did some changes to a table + or without swapping insert/normal modes this command +gww reformat it. + + + + +Works only if |g:vimwiki_use_mouse| is set to 1. +<2-LeftMouse> Follow/Create WikiWord + + Split and follow/create WikiWord + + Vertical split and follow/create WikiWord + + Go back to previous WikiWord + +Note: <2-LeftMouse> is just left double click. + + + +INSERT MODE *vimwiki-table-mappings* + *vimwiki_i_* + Goto table cell down to the current, create new row if + on the last one. + + *vimwiki_i_* + Goto next table cell, create new row if on the last + cell. + + + +------------------------------------------------------------------------------ +3.3. Text objects *vimwiki-text-objects* + +ah A Header with leading empty lines. +ih Inner Header without leading empty lines. + +You can 'vah' to select a header with its contents or 'dah' to delete it or +'yah' to yank it or 'cah' to change it. + + +============================================================================== +4. Commands *vimwiki-commands* + +------------------------------------------------------------------------------ +4.1. Global Commands *vimwiki-global-commands* + +*:VimwikiGoHome* + Open index file of the current wiki. + +*:VimwikiTabGoHome* + Open index file of the current wiki in a new tab. + +*:VimwikiUISelect* + Open index file of the selected wiki. + +*:VimwikiMakeDiaryNote* + Open diary wiki-file for today of the current wiki. + +*:VimwikiTabMakeDiaryNote* + Open diary wiki-file for today of the current wiki in a new tab. + +------------------------------------------------------------------------------ +4.2. Local commands *vimwiki-local-commands* + +*:VimwikiFollowWord* + Follow/create WikiWord. + + +*:VimwikiGoBackWord* + Go back to previous WikiWord you come from. + + +*:VimwikiSplitWord* + Split and follow/create WikiWord. + + +*:VimwikiVSplitWord* + Vertical split and follow/create WikiWord. + + +*:VimwikiNextWord* + Find next WikiWord. + + +*:VimwikiPrevWord* + Find previous WikiWord. + + +*:VimwikiDeleteWord* + Delete WikiWord you are in. + + +*:VimwikiRenameWord* + Rename WikiWord you are in. + + +*:Vimwiki2HTML* + Convert current WikiPage to HTML. + + +*:VimwikiAll2HTML* + Convert all WikiPages to HTML. + + +*:VimwikiToggleListItem* + Toggle list item on/off (checked/unchecked) + See |vimwiki-todo-lists|. + + +*:VimwikiSearch* /pattern/ +*:VWS* /pattern/ + Search for /pattern/ in current wiki. + + +*:VimwikiTable* + Create a table with 5 cols and 2 rows. + + :VimwikiTable cols rows + Create a table with a given cols and rows + + :VimwikiTable cols + Create a table with a given cols and 2 rows + + +============================================================================== +5. Wiki syntax *vimwiki-syntax* + +There are a lot of different wikies out there. Most of them have their own +syntax and vimwiki is not an exception here. Default vimwiki's syntax is a +subset of google's wiki syntax markup. + +As for MediaWiki's syntax -- it is not that convenient for non English +(Russian in my case :)) keyboard layouts to emphasize text as it uses a lot +of '''''' to do it. You have to switch layouts every time you want some bold +non English text. This is the answer to "Why not MediaWiki?" + +Nevertheless, there is MediaWiki syntax file included in the distribution (it +doesn't have all the fancy stuff original MediaWiki syntax has though). +See |vimwiki-option-syntax|. + + +------------------------------------------------------------------------------ +5.1. Typefaces *vimwiki-syntax-typefaces* + +There are a few typefaces that gives you a bit of control on how your +text should be decorated: > + *bold text* + _italic text_ + ~~strikeout text~~ + `code (no syntax) text` + super^script^ + sub,,script,, + +------------------------------------------------------------------------------ +5.2. Links *vimwiki-syntax-links* + +Internal links~ +WikiWords: > + CapitalizedWordsConnected + +You can limit linking of WikiWords by adding an exclamation mark in front of +it: > + !CapitalizedWordsConnected + +Or disable it completely with |g:vimwiki_camel_case|. + +Link with spaces in it: > + [[This is a link]] +or: > + [[This is a link source|Description of the link]] +or: > + [[This is a link source][Description of the link]] + + +External links~ +Plain link: > + http://code.google.com/p/vimwiki + +Link with description: > + [http://habamax.ru/blog habamax home page] + + +Images and image links~ +Image link is the link with one of jpg, png or gif endings. +Plain image link: > + http://someaddr.com/picture.jpg +in html: > + + +Link to a local image: > + [[images/pabloymoira.jpg]] +in html: > + +Path to image (ie. images/pabloymoira.jpg) is relative to +|vimwiki-option-path_html|. + +Double bracketed link to an image: > + [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg]] +in html: > + + +Double bracketed link to an image with description text: > + [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg|dance]] +in html: > + dance + +Double bracketed link to an image with alternate text: > + [[http://habamax.ru/blog/wp-content/uploads/2009/01/2740254sm.jpg|dance|]] +in html: > + dance + +Double bracketed link to an image with alternate text and some style: > + [[http://helloworld.com/blabla.jpg|cool stuff|width:150px; height: 120px;]] +in html: > + cool stuff + +Double bracketed link to an image without alternate text and some style: > + [[http://helloworld.com/blabla.jpg||width:150px; height: 120px;]] +in html: > + + +Thumbnail link: > + [http://someaddr.com/bigpicture.jpg http://someaddr.com/thumbnail.jpg] +or > + [[http://someaddr.com/bigpicture.jpg|http://someaddr.com/thumbnail.jpg]] +in html: > + + + def hello(world): + for x in range(10): + print("Hello {0} number {1}".format(world, x)) +}}} + +Result of HTML export: > +
+ def hello(world):
+     for x in range(10):
+         print("Hello {0} number {1}".format(world, x))
+ 
+ +This might be useful for coloring some programming code with external js tools +like google syntax highlighter. + +You can setup vimwiki to highlight code snippets in preformatted text. +See |vimwiki-option-nested_syntaxes| + +------------------------------------------------------------------------------ +5.8. Blockquotes *vimwiki-syntax-blockquotes* + +Text started with 4 or more spaces is a blockquote. + + This would be a blockquote in vimwiki. It is not highlighted in vim but + could be styled by css in html. Blockquotes are usually used to quote a + long piece of text from another source. + +------------------------------------------------------------------------------ +5.9. Comments *vimwiki-syntax-comments* + +Text between is a comment. +Ex: > + +< + +============================================================================== +6. Folding/Outline *vimwiki-folding* + +Vimwiki can fold or outline headers and list items. + +Example: += My current task = + * [ ] Do stuff 1 + * [ ] Do substuff 1.1 + * [ ] Do substuff 1.2 + * [ ] Do substuff 1.2.1 + * [ ] Do substuff 1.2.2 + * [ ] Do substuff 1.3 + * [ ] Do stuff 2 + * [ ] Do stuff 3 + +Hit |zM| : += My current task = [8] --------------------------------------~ + +Hit |zr| : += My current task =~ + * [ ] Do stuff 1 [5] --------------------------------------~ + * [ ] Do stuff 2~ + * [ ] Do stuff 3~ + +Hit |zr| one more time: += My current task =~ + * [ ] Do stuff 1~ + * [ ] Do substuff 1.1~ + * [ ] Do substuff 1.2 [2] -------------------------------~ + * [ ] Do substuff 1.3~ + * [ ] Do stuff 2~ + * [ ] Do stuff 3~ + +NOTE: Whether you use default syntax, folding on list items should work +properly only if all of them are indented using current |shiftwidth|. +For MediaWiki * or # should be in the first column. + +To turn folding on/off check |g:vimwiki_folding|. + +============================================================================== +7. Placeholders *vimwiki-placeholders* + +------------------------------------------------------------------------------ +7.1. Table of Contents *vimwiki-toc* *vimwiki-table-of-contents* + +You can add 'table of contents' to your html page generated from wiki one. +Just place > + +%toc + +into your wiki page. +You can also add caption to your 'toc': > + +%toc Table of Contents + +or > + +%toc Whatever + + +============================================================================== +8. Todo lists *vimwiki-todo-lists* + +You can have todo lists -- lists of items you can check/uncheck. + +Consider the following example: += Toggleable list of todo items = + * [X] Toggle list item on/off. + * [X] Simple toggling between [ ] and [X]. + * [X] All list's subitems should be toggled on/off appropriately. + * [X] Toggle child subitems only if current line is list item + * [X] Parent list item should be toggled depending on it's child items. + * [X] Make numbered list items toggleable too + * [X] Add highlighting to list item boxes + * [X] Add [ ] to the next created with o, O and list item. + + +Pressing on the first list item will toggle it and all of it's child +items: += Toggleable list of todo items = + * [ ] Toggle list item on/off. + * [ ] Simple toggling between [ ] and [X]. + * [ ] All list's subitems should be toggled on/off appropriately. + * [ ] Toggle child subitems only if current line is list item + * [ ] Parent list item should be toggled depending on it's child items. + * [X] Make numbered list items toggleable too + * [X] Add highlighting to list item boxes + * [X] Add [ ] to the next created with o, O and list item. + +Pressing on the third list item will toggle it and all of it's +parent items: += Toggleable list of todo items = + * [.] Toggle list item on/off. + * [ ] Simple toggling between [ ] and [X]. + * [X] All list's subitems should be toggled on/off appropriately. + * [ ] Toggle child subitems only if current line is list item + * [ ] Parent list item should be toggled depending on it's child items. + * [ ] Make numbered list items toggleable too + * [ ] Add highlighting to list item boxes + * [ ] Add [ ] to the next created with o, O and list item. + +Parent items could be toggled by its child items. Symbol inside [ ] depends on +percentage of toggled child items(see also |g:vimwiki_listsyms|): > + [ ] -- 0% + [.] -- 1-33% + [o] -- 34-66% + [O] -- 67-99% + [X] -- 100% + +It is possible to toggle several list items using visual mode. + + +============================================================================== +9. Tables *vimwiki-tables* + +Use :VimwikiTable command to create default table with 5 columns and 2 rows: > + + | | | | | | + |---+---+---+---+---| + | | | | | | +< + +Tables are auto-formattable. Let's add some text into first cell: > + + | First Name | | | | | + |---+---+---+---+---| + | | | | | | +< + +Whenever you press , or leave Insert mode table is formatted: > + + | First Name | | | | | + |------------+---+---+---+---| + | | | | | | +< + +You can easily create nice looking text tables, just press and enter new +values: > + + | First Name | Last Name | Age | City | e-mail | + |------------+------------+-----+----------+----------------------| + | Vladislav | Pokrishkin | 31 | Moscow | vlad_pok@smail.com | + | James | Esfandiary | 27 | Istanbul | esfandiary@tmail.com | +< + + + +============================================================================== +10. Diary *vimwiki-diary* + +Diary helps you make daily notes. You can really easy add information into +vimwiki that should be sorted out later. Just hit ww to create +new daily note with name based on current date. The link to this newly created +file is added to a diary wiki file. + +Usage example with default settings: > + Consider today is 2010-01-27. + + Hit \w\w . + ~/vimwiki/diary.wiki is created. + + 2 following lines are added to ~/vimwiki/diary/diary.wiki : + = Diary = + | [[2010-01-27]] | + + ~/vimwiki/diary/2010-01-27.wiki is created. + You are ready to add your information there. + ------------------------------------------- + + On the next day. + Hit \w\w . + + The first line after = Diary = is changed in ~/vimwiki/diary/diary.wiki : + = Diary = + | [[2010-01-28]] | [[2010-01-27]] | + + ~/vimwiki/diary/2010-01-28.wiki is created. + You are ready to add your information there. +> + +By default there are 4 links on the line. All links are sorted by their dates. + +Calendar integration *vimwiki-calendar* +------------------------------------------------------------------------------ +If you have Calendar.vim installed you can use it to create diary notes. +Just open calendar with :Calendar and tap on the date. Wiki file would +be created in default wiki's diary. + +Get it from http://www.vim.org/scripts/script.php?script_id=52 + + + +============================================================================== +11. Options *vimwiki-options* + +There are global and per wiki(local) options available to tune vimwiki. +All global options are set using the following template: > + let g:option_name=option_value + +All per wiki options are |Dictionary|'s pairs in a list of wikies +(dictionaries). See |g:vimwiki_list| option for more details. + +------------------------------------------------------------------------------ +*g:vimwiki_list* *vimwiki-multiple-wikies* + +Each item in g:vimwiki_list is a |Dictionary| that holds all customization +available for a wiki represented by that item. It is in form of > + {'option1': 'value1', 'option2: 'value2', ...} + +Consider the following example: > + let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}] + +It gives us one wiki located at ~/my_site/ that could be htmlized to +~/public_html/ + +The next example: > + let g:vimwiki_list = [{'path': '~/my_site/', 'path_html': '~/public_html/'}, + \ {'path': '~/my_docs/', 'ext': '.mdox'}] +gives us 2 wikies, first wiki as in previous example, second one is located in +~/my_docs/ and its files have .mdox extension. + +Empty |Dictionary| in the g:vimwiki_list is the wiki with default options: > + let g:vimwiki_list = [{}, + \ {'path': '~/my_docs/', 'ext': '.mdox'}] + +< + + +PER WIKI OPTIONS *viwmiki-local-options* + + + +*vimwiki-option-path* +------------------------------------------------------------------------------ +Key Default value~ +path ~/vimwiki/ + +Description~ +Wiki files location: > + let g:vimwiki_list = [{'path': '~/my_site/'}] +< + +*vimwiki-option-path_html* +------------------------------------------------------------------------------ +Key Default value~ +path_html ~/vimwiki_html/ + +Description~ +HTML files converted from wiki files location: > + let g:vimwiki_list = [{'path': '~/my_site/', + \ 'path_html': '~/my_site_html/'}] + +If you omit this option path_html would be path - '/' + '_html/': > + let g:vimwiki_list = [{'path': '~/okidoki/'}] + +ie, path_html = '~/okidoki_html/' + +*vimwiki-option-auto_export* +------------------------------------------------------------------------------ +Key Default value Values~ +auto_export 0 0, 1 + +Description~ +Set this option to 1 to automatically generate HTML file when corresponding +wiki page is saved: > + let g:vimwiki_list = [{'path': '~/my_site/', 'auto_export': 1}] + +This will keep you HTML files up to date. + +*vimwiki-option-index* +------------------------------------------------------------------------------ +Key Default value~ +index index + +Description~ +Name of wiki index file: > + let g:vimwiki_list = [{'path': '~/my_site/', 'index': 'main'}] + +NOTE: Do not add extension. + + +*vimwiki-option-ext* +------------------------------------------------------------------------------ +Key Default value~ +ext .wiki + +Description~ +Extension of wiki files: > + let g:vimwiki_list = [{'path': '~/my_site/', + \ 'index': 'main', 'ext': '.document'}] + +< +*vimwiki-option-syntax* +------------------------------------------------------------------------------ +Key Default value Values~ +syntax default default, media + +Description~ +Wiki syntax. +You can use different markup languages (currently default vimwiki and +MediaWiki) but only vimwiki's default markup could be converted to HTML at the +moment. +To use MediaWiki's wiki markup: > + let g:vimwiki_list = [{'path': '~/my_site/', 'syntax': 'media'}] +< + +*vimwiki-option-html_header* +------------------------------------------------------------------------------ +Key Default value~ +html_header + +Description~ +Set up file name for html header template: > + let g:vimwiki_list = [{'path': '~/my_site/', + \ 'html_header': '~/public_html/header.tpl'}] + +This header.tpl could look like: > + + + + %title% + + + +
+ +where + %title% is replaced by a wiki page name + %root_path% is replaced by a count of ../ for pages buried in subdirs: + if you have wikilink [[dir1/dir2/dir3/my page in a subdir]] then + %root_path% is replaced by '../../../'. + + +*vimwiki-option-html_footer* +------------------------------------------------------------------------------ +Key Default value~ +html_footer + +Description~ +Set up file name for html footer template: > + let g:vimwiki_list = [{'path': '~/my_site/', + \ 'html_footer': '~/public_html/footer.tpl'}] + +This footer.tpl could look like: > +
+ + +< + +*vimwiki-option-css_name* +------------------------------------------------------------------------------ +Key Default value~ +css_name style.css + +Description~ +Set up css file name: > + let g:vimwiki_list = [{'path': '~/my_pages/', + \ 'css_name': 'main.css'}] +< +or even > + let g:vimwiki_list = [{'path': '~/my_pages/', + \ 'css_name': 'css/main.css'}] +< + +*vimwiki-option-gohome* +------------------------------------------------------------------------------ +Key Default value Values~ +gohome split split, vsplit, tabe + +Description~ +This option controls the way |:VimwikiGoHome| command works. +For instance you have 'No write since last change' buffer. After ww +(or :VimwikiGoHome) vimwiki index file will be splitted with it. Or vertically +splitted. Or opened in a new tab. +Ex: > + let g:vimwiki_list = [{'path': '~/my_site/', 'gohome': 'vsplit'}] +< + +*vimwiki-option-maxhi* +------------------------------------------------------------------------------ +Key Default value Values~ +maxhi 1 0, 1 + +Description~ +Non-existent WikiWord highlighting could be quite slow and if you don't want +it set maxhi to 0: > + let g:vimwiki_list = [{'path': '~/my_site/', 'maxhi': 0}] + +This disables filesystem checks for WikiWords. + + +*vimwiki-option-nested_syntaxes* +------------------------------------------------------------------------------ +Key Default value Values~ +nested_syntaxes {} pairs of highlight keyword and vim filetype + +Description~ +You can make preformatted text to be highlighted with a different syntaxes +available for vim. +For example the following setup: > + let wiki = {} + let wiki.path = '~/my_site/' + let wiki.nested_syntaxes = {'python': 'python', 'c++': 'cpp'} + let vimwiki_list = [wiki] + +would give you python and c++ highlighting in: > + {{{class="brush: python" + for i in range(1, 5): + print(i) + }}} + + {{{class="brush: c++" + #include "helloworld.h" + int helloworld() + { + printf("hello world"); + } + }}} + +or in: > + {{{c++ + #include "helloworld.h" + int helloworld() + { + printf("hello world"); + } + }}} + + {{{python + for i in range(1, 5): + print(i) + }}} + + + +*vimwiki-option-diary_rel_path* +------------------------------------------------------------------------------ +Key Default value~ +diary_rel_path diary/ + +Description~ +Related to |vimwiki-option-path| path for diary wiki-files. + + +*vimwiki-option-diary_index* +------------------------------------------------------------------------------ +Key Default value~ +diary_index diary + +Description~ +Name of wiki-file that holds all links to dated wiki-files. + + +*vimwiki-option-diary_header* +------------------------------------------------------------------------------ +Key Default value~ +diary_header Diary + +Description~ +Name of the header in |vimwiki-option-diary_index| where links to dated +wiki-files are located. + + +*vimwiki-option-diary_link_count* +------------------------------------------------------------------------------ +Key Default value~ +diary_link_count 4 + +Description~ +Number of maximum dated links placed on one line. +Ex: += Diary = +|| [[2010-01-30]] || [[2010-01-29]] || [[2010-01-28]] || [[2010-01-27]] || +|| [[2010-01-26]] || [[2010-01-25]] || + + + + +GLOBAL OPTIONS *viwmiki-global-options* + +Use: > + let g:option_name=option_value +to set them. + +------------------------------------------------------------------------------ +*g:vimwiki_hl_headers* + +Highlight headers with =Reddish=, ==Greenish==, ===Blueish=== colors. + +Value Description~ +1 Use predefined colors to highlight different header levels. +0 Use |hl-Title| or VimwikiHeader1-VimwikiHeader6 (if defined + in a colorscheme) + +Default: 1 + + +------------------------------------------------------------------------------ +*g:vimwiki_hl_cb_checked* + +Checked list items could be highlighted with a color: + + * [X] the whole line could be highlighted with the option set to 1. + * [ ] I wish vim could use strikethru. + +Value Description~ +1 Highlight checked [X] check box with |group-name| "Comment". +0 Don't. + +Default: 0 + + +------------------------------------------------------------------------------ +*g:vimwiki_global_ext* *vimwiki-temporary-wiki* + +If a file with a registered wiki extension is opened in a dir that is not +listed in |g:vimwiki_list| then: + +Value Description~ +1 make a temporary wiki in that dir. +0 don't make temporary wiki it that dir. + +Default: 1 + + +------------------------------------------------------------------------------ +*g:vimwiki_upper* *g:vimwiki_lower* + +This affects WikiWord detection. +By default WikiWord detection uses English and Russian letters. +You can set up your own: > + let g:vimwiki_upper = "A-Z\u0410-\u042f" + let g:vimwiki_lower = "a-z\u0430-\u044f" + + +------------------------------------------------------------------------------ +*g:vimwiki_auto_checkbox* + +if on, creates checkbox while toggling list item. + +Value Description~ +0 Do not create checkbox. +1 Create checkbox. + +Default: 1 + +Ex: +Press (|:VimwikiToggleListItem|) on a list item without checkbox to +create it: > + * List item +result: > + * [ ] List item + + +------------------------------------------------------------------------------ +*g:vimwiki_menu* + +GUI menu of available wikies to select. + +Value Description~ +'' No menu +'Vimwiki' Top level menu "Vimwiki" +'Plugin.Vimwiki' "Vimwiki" submenu of top level menu "Plugin" +etc. + +Default: 'Vimwiki' + +------------------------------------------------------------------------------ +*g:vimwiki_stripsym* + +Change strip symbol -- in Windows you cannot use /*?<>:" in file names so +vimwiki replaces them with neutral symbol (_ is default): > + let g:vimwiki_stripsym = '_' + +You can change it to a for example: > + let g:vimwiki_stripsym = ' ' + +------------------------------------------------------------------------------ +*g:vimwiki_badsyms* + +Consider you do not like spaces in filenames (as some vimwiki users do). +In that case you can set up bad symbols that would be converted to +|g:vimwiki_stripsym|: > + let g:vimwiki_badsyms = ' ' + +Now files for all [[links with spaces]] would be created like +'links_with_spaces'. + +This option is a complement one to |g:vimwiki_stripsym|. + +------------------------------------------------------------------------------ +*g:vimwiki_listsyms* + +String of 5 symbols for list items with checkboxes. +Default value is ' .oOX'. + +g:vimwiki_listsyms[0] is for 0% done items. +g:vimwiki_listsyms[4] is for 100% done items. + +------------------------------------------------------------------------------ +*g:vimwiki_use_mouse* + +Use local mouse mappings from |vimwiki-local-mappings|. + +Value Description~ +0 Do not use mouse mappings. +1 Use mouse mappings. + +Default: 0 + +------------------------------------------------------------------------------ +*g:vimwiki_folding* + +Enable/disable vimwiki's folding/outline. Folding in vimwiki is using 'expr' +foldmethod which is very flexible but really slow. + +Value Description~ +0 Disable folding. +1 Enable folding. + +Default: 0 + +------------------------------------------------------------------------------ +*g:vimwiki_fold_lists* + +Enable/disable folding of list subitems. + +Value Description~ +0 Disable list subitem's folding. +1 Enable list subitem's folding. + +Default: 0 + +------------------------------------------------------------------------------ +*g:vimwiki_fold_trailing_empty_lines* + +Fold or do not fold empty lines between folded headers. + +Value Description~ +0 Fold only one empty line. The rest empty lines are unfolded. +1 Fold in all empty lines. + +Default: 0 + +------------------------------------------------------------------------------ +*g:vimwiki_camel_case* + +If you do not want WikiWord to be a link this setting is just for you. + +Value Description~ +0 Do not make links from CamelCased words. +1 Make links from CamelCased words. + +Default: 1 + +------------------------------------------------------------------------------ +*g:vimwiki_list_ignore_newline* + +This is HTML related. +Convert newlines to
s in multiline list items. + +Value Description~ +0 Newlines in a list item are converted to
s. +1 Ignore newlines. + +Default: 1 + +------------------------------------------------------------------------------ +*g:vimwiki_use_calendar* + +Create new or open existing diary wiki-file for the date selected in Calendar. +See |vimwiki-calendar|. + +Value Description~ +0 Do not use calendar. +1 Use calendar. + +Default: 1 + + +------------------------------------------------------------------------------ +*g:vimwiki_browsers* *VimwikiWeblinkHandler* + +You can open external weblinks in a webbrowser. Webbrowsers are listed in +|g:vimwiki_browsers|. + +For win32 it is: chrome, opera, firefox and explorer. +For other OSes it is: opera, firefox and konqueror. + +The first available browser from the list is used to open weblink. +If you have opera and firefox and want weblinks to be opened in the latter +just: > + let g:vimwiki_browsers=['C:\Program Files\Firefox\firefox.exe'] + +or redefine VimwikiWeblinkHandler function: > + function! VimwikiWeblinkHandler(weblink) + let browser = 'C:\Program Files\Firefox\firefox.exe' + execute '!start "'.browser.'" ' . a:weblink + endfunction + + +------------------------------------------------------------------------------ +*g:vimwiki_table_auto_fmt* + +Turn on/off table auto-formatting. + +Value Description~ +0 Do not auto-format tables. +1 Auto-format tables. + +Default: 1 + + +------------------------------------------------------------------------------ +*g:vimwiki_w32_dir_enc* + +Convert directory name from current |encoding| into 'g:vimwiki_w32_dir_enc' +before it is created. + +If have 'enc=utf-8' and you set up > + let g:vimwiki_w32_dir_enc = 'cp1251' +< +then following the next link with : > + [[привет/мир]] +> +would convert utf-8 'привет' to cp1251 and create directory with that name. + +Default value: '' + + +============================================================================== +12. Help *vimwiki-help* + +As you could see I am not native English speaker (not a writer as well). +Please send me correct phrases instead of that incorrect stuff I have used +here. + +Any help is really appreciated! + +============================================================================== +13. Author *vimwiki-author* + +I live in Moscow and you may believe me -- there are no polar bears (no brown +too) here in the streets. + +I do not do programming for a living. So don't blame me for an ugly +ineffective code. Improvements are welcome. + +Many thanks to all of you for voting vimwiki up on www.vim.org. I do vimwiki +in my spare time I could use to dance argentine tango with beautiful women. +Your votes are kind of a good replacement. ;) + +Sincerely yours, +Maxim Kim . + +Vimwiki's website: http://code.google.com/p/vimwiki/ +Vim plugins website: http://www.vim.org/scripts/script.php?script_id=2226 + +============================================================================== +14. Changelog *vimwiki-changelog* + +0.9.9~ + * NEW: Diary. Help in making daily notes. See |vimwiki-diary|. Now you can + really easy add information into vimwiki that should be sorted out + later. + * NEW: Tables are redesigned. Syntax is changed. Now they are + auto-formattable. You can navigate them with and in insert + mode. See |vimwiki-syntax-tables| and |vimwiki-tables| for more details. + * NEW: Keyword STARTED: is added. + * NEW: Words TODO:, DONE:, STARTED:, XXX:, FIXME:, FIXED: are highlighed + inside headers. + * FIX: Export to html external links with 'file://' protocol. Ex: + [file:///home/user1/book.pdf my book]. + * FIX: Menu is corrupted if wiki's path contains spaces. + * FIX: Settings |wrap| and |linebreak| are removed from ftplugin. Add them + into your personal settings file `.vim/after/ftplugin/vimwiki.vim` if + needed. + * NEW: Headers are highlighted in different colors by default. + See |g:vimwiki_hl_headers| to turn it off. + * FIX: Issue 40: Links with russian subdirs don't work. + * NEW: It is now possible to generate HTML files automatically on page + save. See |vimwiki-option-auto_export|. + + +0.9.8~ + * NEW: Rename |g:vimwiki_fold_empty_lines| to + |g:vimwiki_fold_trailing_empty_lines|. + * NEW: One can use '-' along with '*' to start unordered list item. + * NEW: List items could be started from the first column. + As a result some limitations appeared: + - a space after *, - or # for a list item is mandatory. + - |g:vimwiki_fold_trailing_empty_lines| if set to 0 folds one trailing + empty line. + * NEW: Folding is off by default. Use |g:vimwiki_folding| to enable it. + * NEW: Speed up vimwiki's folding a bit. Should lag a bit less in a long + todo lists. + * NEW: Centered headers. Start header with at least one space to make it + html centered. + * NEW: Change in default css: header's colors. + * NEW: Vimwiki is aware of |GetLatestVimScripts| now. + * FIX: Use tag instead of custom in html. + * FIX: There are no text styling in htmlized quoted text. + * FIX: set default value of g:vimwiki_fold_lists to 0 as written in this + help. + * FIX: Issue 33: Folded list items have wrong indentation when 'tabs' are + used. + * FIX: Issue 34: vimwiki#subdir got wrong dir when VimwikiGet('path') is a + symbolic link. Thanks lilydjwg for the patch. + * FIX: Issue 28: todo-list auto-indent enhancement. New item should always + be unchecked. + * Issue 36: Change the name of the Search command to VimwikiSearch as it + conflicts with MultipleSearch. Alias :VWS is also available. + * NEW: You can generate 'Table of contents' of your wiki page. See + |vimwiki-toc| for details. + +0.9.701~ + * FIX: Issue 30: Highlighting doesn't work for checked list item. + +0.9.7~ + * NEW: Default checkbox symbols are changed to [ ], [.], [o], [O], [X]. + You can change them using |g:vimwiki_listsyms| variable. + * NEW: Color group names are renamed from wikiBold, wikiItalic, etc to + VimwikiBold, VimwikiItalic, etc. + * NEW: Open external links in a browser. There are default browsers + defined in |g:vimwiki_browsers| list. You can also redefine + |VimwikiWeblinkHandler| function to open weblinks in other programs. + * NEW: Issue 25: Toggle the states of multiple TODO list items at a time + (in VISUAL and in VISUAL LINE modes) + * NEW: Issue 26: Highlight code snippets in vimwiki's pre. See + |vimwiki-option-nested_syntaxes|. Thanks kriomant. + * NEW: Issue 27: Automatic garbage deletion from html directory. + * NEW: Save all open vimwiki buffers before export to html. + * NEW: Issue 29: Custom :Search command. + * NEW: Header text objects are now expandable in VISUAL mode. Tap 'vah' to + select a header. Tap again 'ah' to expand selection further. Thanks Andy + Wokula. + * FIX: Folding settings are reset to vim defaults in a new tab (think of + \wt) so you cannot hide things in folds. + * FIX: https links in form of [https://hello.world.com] are not exported + into html. Thanks Saurabh Sarpal for the patch. + +0.9.6~ + * NEW: You can have multiline list items. See |vimwiki-syntax-lists|. + * NEW: You can ignore newlines in multiline list items when do export to + html. See |g:vimwiki_list_ignore_newline| option. + * NEW: Different checkbox symbols [.], [:], [o] are added. See + |vimwiki-todo-lists|. + * NEW: Now there is no longer syntax of preformatted text that is started + by a whitespace. + * NEW: Blockquotes. See |vimwiki-syntax-blockquote|. + * NEW: Per wiki folding option (vimwiki-option-folding) is removed. Global + |g:vimwiki_folding| and |g:vimwiki_fold_lists| are added. + * NEW: Due to being quite slow folding of list items is off by default. + Use |g:vimwiki_fold_lists| to turn it on. + * NEW: If you want replace some symbols in a wikifilename use + |g:vimwiki_badsyms| option (Andreas Baldeau). + * FIX: Command |:VimwikiToggleListItem| doesn't work for one of the two + wikies opened at the same time with different syntaxes. + * FIX: Command |:VimwikiToggleListItem| do not switch parent checkboxes if + there are non-checkbox list items available. + * FIX: Issue 24: Link error in html when write [[one.two.three]]. + * FIX: Rename WikiWord to something with a colon (:) does nasty things. + * FIX: Command |:VimwikiToggleListItem| do not switch right if there are + list items without checkboxes in the list. + +0.9.5~ + * NEW: Added |g:vimwiki_global_ext| to control creation of temporary + wikies in dirs that are not listed in |g:vimwiki_list|. + * NEW: Added |g:vimwiki_hl_headers| to highlight headers with different + predefined colors. + * NEW: Checked [X] items are not highlighted with Comment syntax group by + default. Use |g:vimwiki_hl_cb_checked| to turn it on. + * NEW: Added new syntax for links: [[link address][link description]]. + * NEW: Added allias of mapping for *nix systems. + * NEW: Added |g:vimwiki_camel_case|. Set it to 0 if you do not want + CamelCased WikiWords to be linkified. + * FIX: Links with g:vimwiki_stripsym (default '_') [[My_Link|Text]] are + not highlighted when created. + * FIX: indent/vimwiki.vim is obsolete. If you upgrade from previous + versions remove it. It causes wrong list indentation if noexpandtab is + set. + * FIX: If tabs and spaces are used to indent list items html export gives + error. Thanks Klaus Ethgen for report. + * FIX: Some html export fixes. + +0.9.4~ + * NEW: Links with directories: [[dir1/dir2/Link|Text]]. Thanks Jie Wu. + * NEW: Added %root_path% template variable to get relative root dir of + path_html. See |vimwiki-option-html_header|. + * FIX: Indent is incorrect for vim without "float" compile option. Thanks + Julian Kooij. + * FIX: Convert to html doesn't work right with links like [[foo::bar]]. + * FIX: Rename wikiword doesn't work right when rename WikiWord to + [[WikiWord blablabla]]. + * FIX: Renaming of links with description doesn't work. + * FIX: Weblinks with commas are not highlighted. + * MISC: Some changes in default css file. + +0.9.3~ + * NEW: g:vimwiki_menu option is a string which is menu path. So one can + use let g:vimwiki_menu = 'Plugin.Vimwiki' to set the menu to the right + place. + * NEW: g:vimwiki_fold_empty_lines -- don't or do fold in empty lines + between headers. See |g:vimwiki_fold_empty_lines| + * FIX: Encoding error when running vimwiki in Windows XP Japanese. + Thanks KarasAya. + +0.9.2c~ + * FIX: Regression: Export HTML link error with [[Link|Text]]. + +0.9.2b~ + * FIX: Installation on Linux doesn't work. (Dos line endings in Vimball + archive file). + * FIX: Clear out FlexWiki ftplugin's setup. Now you don't have to hack + filetype.vim to get rid of unexpected ':setlocal bomb' from FlexWiki's + ftplugin. + * FIX: When write done: it will show another done: in html file. + +0.9.2a~ + * FIX: Installation on Linux doesn't work. (Dos line endings in + autoload/vimwiki_lst.vim and indent/vimwiki.vim). + +0.9.2~ + * NEW: Option 'folding' added to turn folding on/off. + * NEW: Header text object. See |vimwiki-text-objects|. + * NEW: Add/remove Header levels with '=' and '-'. See |vimwiki_=|. + * NEW: Vimwiki GUI menu to select available wikies. See |g:vimwiki_menu|. + * NEW: You can specify the name of your css file now. See + |vimwiki-option-css_name| + * NEW: You can add styles to image links, see |vimwiki-syntax-links|. + * FIX: History doesn't work after |VimwikiRenameWord|. + * FIX: Some of wikipedia links are not correctly highlighted. Links with + parentheses. + * MISC: Renamed vimwiki_gtd to vimwiki_lst. + +0.9.1~ + * NEW: HTML Table cell text alignment, see |vimwiki-syntax-tables| + * NEW: Wikipage history simplified. Each vimwiki buffer now holds + b:vimwiki_prev_word which is list of [PrevWord, getpos()]. + * NEW: If highlight for groups wikiHeader1..wikiHeader6 exist (defined in + a colorscheme) -- use it. Otherwise use Title highlight for all Headers. + * FIX: Warn only once if 'html_header' or 'html_footer' does not exist. + * FIX: Wrong folding for the text after the last nested list item. + * FIX: Bold and Italic aren't highlighted in tables without spaces + between || and * or _. ||*bold*||_asdf_ || (Thanks Brett Stahlman) + +0.9.0~ + * NEW: You can add classes to 'pre' tag -- |vimwiki-syntax-preformatted|. + This might be useful for coloring some programming code with external js + tools like google syntax highlighter. + * NEW: !WikiPage is not highlighted. It is just a plain word WikiPage in + HTML, without exclamation mark + * NEW: Definition lists, see |vimwiki-syntax-lists|. + * NEW: New implementation of |:VimwikiRenameWord|. CAUTION: It was tested + on 2 computers only, backup your wiki before use it. Email me if it + doesn't work for you. + * FIX: Less than 3 symbols are not highlighted in Bold and Italic. + * FIX: Added vimwiki autocmd group to avoid clashes with user defined + autocmds. + * FIX: Pressing ESC while |:VimwikiUISelect| opens current wiki index + file. Should cancel wiki selection. + +0.8.3~ + * NEW: on a list item creates checkbox. + * FIX: With * in the first column, shouldn't insert more * (default + syntax). + * FIX: With MediaWiki's ** [ ], should insert it on the next line. + * FIX: HTML export should use 'fileencoding' instead of 'encoding'. + * FIX: Code cleanup. + +0.8.2~ + * DEL: Removed google syntax file. + * NEW: Default vimwiki syntax is a subset of google's one. Header's has + been changed from !Header to =Header=. It is easier to maintain only 2 + syntaxes. See |vimwiki-syntax-headers|. + * NEW: Multiline paragraphs -- less longlines. + * NEW: Comments. See |vimwiki-syntax-comments|. + * DEL: Removed setlocal textwidth = 0 from ftplugin. + * FIX: New regexps for bold, italic, bolditalic. + * FIX: The last item in List sometimes fold-in incorrectly. + * FIX: Minor tweaks on default css. + +0.8.1~ + * NEW: Vimwiki's foldmethod changed from syntax to expr. Foldtext is + changed to be nicer with folded list items. + * NEW: Fold/outline list items. + * NEW: It is possible now to edit wiki files in arbitrary directories + which is not in g:vimwiki_list's paths. New WikiWords are created in the + path of the current WikiWord. + * NEW: User can remap Vimwiki's built in mappings. + * NEW: Added |g:vimwiki_use_mouse|. It is off by default. + * FIX: Removed mapping. + +0.8.0~ + * NEW: Multiple wikies support. A lot of options have been changed, see + |vimwiki-options| + * NEW: Auto create directories. + * NEW: Checked list item highlighted as comment. + * FIX: Multiple 'set ft=vimwiki' for each buffer disabled. Vimwiki should + load its buffers a bit faster now. + +0.7.1~ + * NEW: VimwikiToggleListItem added to be able to remap to + anything user prefers more. + * FIX: Toggleable list items do not work with MediaWiki markup. + * FIX: Changing g:vimwiki_home_html to path with ~ while vimwiki is + loaded gives errors for HTML export. + * DEL: Command :VimwikiExploreHome. + +0.7.0~ + * NEW: GTD stuff -- toggleable list items. See |vimwiki-todo-lists|. + * FIX: Headers do not fold inner headers. (Thanks Brett Stahlman) + * FIX: Remove last blank lines from preformatted text at the end of file. + * DEL: Removed g:vimwiki_smartCR option. + +0.6.2~ + * NEW: [[link|description]] is available now. + * FIX: Barebone links (ie: http://bla-bla-bla.org/h.pl?id=98) get extra + escaping of ? and friends so they become invalid in HTML. + * FIX: In linux going to [[wiki with whitespaces]] and then pressing BS + to go back to prev wikipage produce error. (Thanks Brendon Bensel for + the fix) + * FIX: Remove setlocal encoding and fileformat from vimwiki ftplugin. + * FIX: Some tweaks on default style.css + +0.6.1~ + * FIX: [blablabla bla] shouldn't be converted to a link. + * FIX: Remove extra annoing empty strings from PRE tag made from + whitespaces in HTML export. + * FIX: Moved functions related to HTML converting to new autoload module + to increase a bit vimwiki startup time. + +0.6~ + * NEW: Header and footer templates. See|g:vimwiki_html_header| and + |g:vimwiki_html_footer|. + * FIX: |:Vimwiki2HTML| does not recognize ~ as part of a valid path. + +0.5.3~ + * FIX: Fixed |:VimwikiRenameWord|. Error when g:vimwiki_home had + whitespaces in path. + * FIX: |:VimwikiSplitWord| and |:VimwikiVSplitWord| didn't work. + +0.5.2~ + * NEW: Added |:VimwikiGoHome|, |:VimwikiTabGoHome| and + |:VimwikiExploreHome| commands. + * NEW: Added wt mapping to open vimwiki index file in a new tab. + * NEW: Added g:vimwiki_gohome option that controls how|:VimwikiGoHome| + works when current buffer is changed. (Thanks Timur Zaripov) + * FIX: Fixed |:VimwikiRenameWord|. Very bad behaviour when autochdir + isn't set up. + * FIX: Fixed commands :Wiki2HTML and :WikiAll2HTML to be available only + for vimwiki buffers. + * FIX: Renamed :Wiki2HTML and :WikiAll2HTML to |:Vimwiki2HTML| and + |:VimwikiAll2HTML| commands. + * FIX: Help file corrections. + +0.5.1~ + * NEW: This help is created. + * NEW: Now you can fold headers. + * NEW: VimwikiGoHome and VimwikiExploreHome were added. + * FIX: Bug with {{{HelloWikiWord}}} export to HTML is fixed. + * DEL: Sync option removed from: Syntax highlighting for preformatted + text {{{ }}}. + +0.5~ + * NEW: vimwiki default markup to HTML conversion improved. + * NEW: Added basic GoogleWiki and MediaWiki markup languages. + * NEW: Chinese [[complex wiki words]]. + +0.4~ + * NEW: vimwiki=>HTML converter in plain Vim language. + * NEW: Plugin autoload. + +0.3.4~ + * FIX: Backup files (.wiki~) caused a bunch of errors while opening wiki + files. + +0.3.3~ + * FIX: [[wiki word with dots at the end...]] didn't work. + * NEW: Added error handling for delete wiki word function. + * NEW: Added keybindings o and O for list items when g:vimwiki_smartCR=1. + * NEW: Added keybinding wh to visit wiki home directory. + +0.3.2~ + * FIX: Renaming -- error if complex wiki word contains %. + * FIX: Syntax highlighting for preformatted text {{{ }}}. Sync option + added. + * FIX: smartCR bug fix. + +0.3.1~ + * FIX: Renaming -- [[hello world?]] to [[hello? world]] links are not + updated. + * FIX: Buffers menu is a bit awkward after renaming. + * NEW: Use mouse to follow links. Left double-click to follow WikiWord, + Rightclick then Leftclick to go back. + +0.3~ + * NEW: Highlight non-existent WikiWords. + * NEW: Delete current WikiWord (wd). + * NEW: g:vimwiki_smartCR=2 => use Vim comments (see :h comments :h + formatoptions) feature to deal with list items. (thx -- Dmitry + Alexandrov) + * NEW: Highlight TODO:, DONE:, FIXED:, FIXME:. + * NEW: Rename current WikiWord -- be careful on Windows you cannot rename + wikiword to WikiWord. After renaming update all links to that renamed + WikiWord. + * FIX: Bug -- do not duplicate WikiWords in wiki history. + * FIX: After renaming [[wiki word]] twice buffers are not deleted. + * FIX: Renaming from [[wiki word]] to WikiWord result is [[WikiWord]] + * FIX: More than one complex words on one line is bugging each other when + try go to one of them. [[bla bla bla]] [[dodo dodo dodo]] becomes bla + bla bla]] [[dodo dodo dodo. + + +0.2.2~ + * NEW: Added keybinding -- split WikiWord + * NEW: Added keybinding -- vertical split WikiWord + +0.2.1~ + * NEW: Install on Linux now works. + +0.2~ + * NEW: Added part of Google's Wiki syntax. + * NEW: Added auto insert # with ENTER. + * NEW: On/Off auto insert bullet with ENTER. + * NEW: Strip [[complex wiki name]] from symbols that cannot be used in + file names. + * NEW: Links to non-wiki files. Non wiki files are files with extensions + ie [[hello world.txt]] or [[my homesite.html]] + +0.1~ + * First public version. + +============================================================================== +15. License *vimwiki-license* + +The MIT Licence +http://www.opensource.org/licenses/mit-license.php + +Copyright (c) 2010 Maxim Kim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + + vim:tw=78:ts=8:ft=help diff --git a/doc2/test.png b/doc2/test.png new file mode 100644 index 0000000..961a238 Binary files /dev/null and b/doc2/test.png differ diff --git a/doc2/vst-s5.html b/doc2/vst-s5.html new file mode 100644 index 0000000..224e1fe --- /dev/null +++ b/doc2/vst-s5.html @@ -0,0 +1,783 @@ + + + + +Vim reStructured Text + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+
+ + + +
+
+

Vim reStructured Text

+ + + + + +
Title: Vim reStructured Text - A Quick Introduction
Author: George V. Reilly <george@reilly.org>
Date: 2006/05/12
+
+
+

What is VST?

+ +

+VST is an easy way to produce: +

+ +
    +
  • + +

    +HTML +

    + +
  • +
  • + +

    +S5 Slides, like this document +

    + +
  • +
  • + +

    +LaTeX and PDF +

    + + +
  • +
+ +

+from reStructured text: plain text +with minimal markup. +

+ +

+The powerful Vim editor is used to prepare the +material. +

+ +

+Please read the source of these slides to see how the effects used herein are +achieved. +

+ +
+
+

Simple markup

+
    +
  • + +

    +Bulleted Lists +

    + +
  • +
  • + +

    +Numeric lists (nested) +

    + + +
      +
    1. + +

      +Bold text +

      + +
    2. +
    3. + +

      +Italics text +

      + +
    4. +
    5. + +

      +typewriter text +

      + + +
    +
  • + +
  • + +

    +Subscripts, H2O. +

    + +
  • +
  • + +

    +Replacement -- Vim reStructured Text -- of text. +

    + + +
  • +
+
+
+

Blockquotes

+ +

+You can embed blockquotes inside your text: +

+ +
+ Simple markup
+ ==============
+
+ + Bulleted Lists
+ + Numeric lists (nested)
+
+     #. **Bold** text
+     2. *Italics* text
+     #. ``typewriter`` text
+
+ + Replacement -- |VST| -- of text.
+
+ +

+is most of the text of the previous slide. +

+ +
+
+

Links

+ +

+VST supports a variety of hyperlink notations. +

+ + + +

+The full effect of these links cannot be seen in the S5 slides. +Regenerate with :Vst instead. +

+ + +
+
+

Images

+

+ +http://www.vim.org/images/vim_header.gif + +

+
+

Tip

+ +

+You can apply a variety of attributes to images. +

+ + +
+ +

+ If you need really fine control, you may need to use .. raw:: html +

+ +
+
+
+
+

Simple Tables

++ + + + + + + + + + +
+ +

+su +

+ +
+ +

+mo +

+ +
+ +

+tu +

+ +
+ +

+we +

+ +
+ +

+th +

+ +
+ +

+fr +

+ +
+ +

+sa +

+ +
+ + + + + + + +

+1 +

+ +
+ +

+2 +

+ +
+ +

+3 +

+ +
+ +

+4 +

+ +
+ +

+5 +

+ +
+ +

+6 +

+ +
+ +

+7 +

+ +
+ +

+8 +

+ +
+ +

+9 +

+ +
+ +

+10 +

+ +
+ +

+11 +

+ +
+ +

+12 +

+ +
+ +

+13 +

+ +
+ +

+14 +

+ +
+ +

+15 +

+ +
+ +

+16 +

+ +
+ +

+17 +

+ +
+ +

+18 +

+ +
+ +

+19 +

+ +
+ +

+20 +

+ +
+ +

+21 +

+ +
+ +

+22 +

+ +
+ +

+23 +

+ +
+ +

+24 +

+ +
+ +

+25 +

+ +
+ +

+26 +

+ +
+ +

+27 +

+ +
+ +

+28 +

+ +
+ +

+29 +

+ +
+ +

+30 +

+ +
+ +

+31 +

+ +
+ + + + +
+
+
+

Rich Tables

++ + + + +
+ +

+Cells are +separated +

+ +
+ +

+by bar with +spaces around +

+ +
+ +

+<Space>|<Space> +

+ +
+ +

+You may use +inline +

+ +
+ +

+markup, +links +

+ +
+ +

+included. +

+ +
+ +

+You can use various +types of structure +elements: +

+ +
+ Welcome to world  
+ of preformatted   
+ text.
+
+ + +
+
    +
  • + +

    +like lists +

    + + +
      +
    • + +

      +various +

      + + +
    • +
    +
  • + +
  • + +

    +embedded +

    + +
  • +
  • + +

    +one into +other +

    + + +
  • +
+
+ +

+VST will +interpret them. +

+ +

+Even paragraphs. +

+ +
    +
  1. + +

    +And +

    + +
  2. +
  3. + +

    +not +

    + + +
+
+ +

+Text may span across several +columns. Cell can be also empty -> +

+ +
+
+
+
+

Conclusion

+ +

+VST is an easy way to produce marked-up documents with easy-to-read source, in +Vim. +

+ +

+This slideshow displays only a few features of VST. Be sure to read the +manual. +

+ + + + +
+ + + + diff --git a/doc2/vst-s5.txt b/doc2/vst-s5.txt new file mode 100644 index 0000000..e8893e8 --- /dev/null +++ b/doc2/vst-s5.txt @@ -0,0 +1,145 @@ +.. This is a comment +.. Use ":Vst s5" to generate the HTML for this document + +============================================ +Vim reStructured Text +============================================ + +:Title: Vim reStructured Text - A Quick Introduction +:Author: George V. Reilly +:Date: 2006/05/12 + + +What is VST? +============ + +`VST `_ is an easy way to produce: + +* HTML +* S5 Slides, like this document +* LaTeX and PDF + +from `reStructured text `_: plain text +with minimal markup. + +The powerful `Vim `_ editor is used to prepare the +material. + +Please read the _`source` of these slides to see how the effects used herein are +achieved. + + +Simple markup +============= + ++ Bulleted Lists ++ Numeric lists (nested) + + #. **Bold** text + 2. *Italics* text + #. ``typewriter`` text + ++ Subscripts, H\ :sub:`2`\ O. ++ Replacement -- |VST| -- of text. + + +Blockquotes +=========== + +You can embed blockquotes inside your text:: + + Simple markup + ============== + + + Bulleted Lists + + Numeric lists (nested) + + #. **Bold** text + 2. *Italics* text + #. ``typewriter`` text + + + Replacement -- |VST| -- of text. + +is most of the text of the previous slide. + + +Links +===== + +VST supports a variety of hyperlink notations. + +* Starting points: `What is VST?`_ +* `External links`_ +* Internal links, such as `source`_ +* Standalone links, http://www.vim.org +* `Embedded URIs `_ + +The full effect of these links cannot be seen in the S5 slides. +Regenerate with ``:Vst`` instead. + +.. _External links: http://skawina.eu.org/mikolaj/vst.html#lexternal-links + + +Images +====== + +.. image:: http://www.vim.org/images/vim_header.gif + :title: Vim + :target: http://www.vim.org/ + +.. tip:: You can apply a variety of attributes to images. + + If you need really fine control, you may need to use ``.. raw:: html`` + + +Simple Tables +============= + + +== == == == == == == +su mo tu we th fr sa +== == == == == == == + 1 +2 3 4 5 6 7 8 +9 10 11 12 13 14 15 +16 17 18 19 20 21 22 +23 24 25 26 27 28 29 +30 31 +== == == == == == == + + +Rich Tables +=========== + ++---------------------+----------------+------------------+ +| Cells are | by bar with | | | +| separated | spaces around | | ++---------------------+----------------+------------------+ +| *You* may use | markup, | included. | +| **inline** | links_ | | ++---------------------+----------------+------------------+ +| You can use various | - like lists | VST will | +| types of structure | | interpret them. | +| elements:: | + various | | +| | | Even paragraphs. | +| Welcome to world | - embedded | | +| of preformatted | - one into | 1. And | +| text. | other | 2. not | ++---------------------+----------------+------------------+ +| Text may span across several | | +| columns. Cell can be also empty -> | | ++---------------------+----------------+------------------+ + + +Conclusion +========== + +VST is an easy way to produce marked-up documents with easy-to-read source, in +Vim. + +This slideshow displays only a few features of VST. Be sure to read the +`manual `_. + +.. |VST| replace:: Vim reStructured Text + +.. vim:set tw=78 ai fo+=n fo-=l ft=rst: diff --git a/doc2/vst.txt b/doc2/vst.txt new file mode 100644 index 0000000..d13c714 --- /dev/null +++ b/doc2/vst.txt @@ -0,0 +1,2995 @@ +===================== +Vim reStructured Text +===================== +:Author: Mikolaj Machowski +:Title: Vim reStructured Text - HTML and LaTeX output +:Keywords: Vim, LaTeX, PDF, HTML, XML +:Version: 1.4 +:License: GPL v. 2 +:Date: 4 Nov 2006 + +For a long time Vim_ users were asking for "real" export to HTML. This is, +I believe, first real try to achieve this effect. This is Vim version of +reStructuredText_, popular Python_ language documentation tool (so I borrowed +parts of its documentation). + +.. contents:: + :depth: 3 + :class: new + +Introduction +------------ + +*Structured* means Vim script recognizes some patterns and translates them +into form recognizable by WWW browsers. In fact, Vim creates quasi-XML +form which can be exported into HTML and LaTeX. + +Major office suites OpenOffice.org_ and MS-Office_ can import HTML +(KOffice_ also can do this but results aren't good) and save files in +their native formats. + + +Download +-------- + +- Scripts themselves and docs in txt form: vst.zip_ + +All forms of documentation were created from the same txt source without +**any** corrections: + +- HTML documentation: vst.html_ +- PDF documentation: vst.pdf_ +- LaTeX source of documentation: vst.tex_ + +.. _vst.zip: http://skawina.eu.org/mikolaj/vst.zip +.. _vst.html: http://skawina.eu.org/mikolaj/vst.html +.. _vst.pdf: http://skawina.eu.org/mikolaj/vst.pdf +.. _vst.tex: http://skawina.eu.org/mikolaj/vst.tex + +.. _archive: + +Installation +------------ + +Put archive ``vst.zip`` into your ``~/.vim`` (Unices) or ``vimfiles`` +(MS-Windows) directory and unpack it there. It will create files:: + + |- doc2/vst.txt <- documentation + |- doc2/vst-s5.txt <- example of S5 presentation + |- doc2/test.png <- to complete documentation + |- plugin/vstplugin.vim <- small plugin file with commands + |- autoload/vst/vst.vim <- main script + |- autoload/vst/myhtmlvst.vim <- examples of macros + \- autoload/vst/s5ui/* <- S5 style files + +Usage +----- + +Transformation is called with command:: + + :Vst [{format}] + +Where ``{format}`` is format of exported file. Format argument is +optional and without it default value (HTML) will be used. Argument name +is case-insensitive: HTML, html, Html are equivalents. Formatted file +will be opened in new buffer without name. + +``g:vst_write_export`` + Boolean (0). If true, write file immediately with extension specific to + export format (html, tex, xml). Overwrite existing files without warning. + How to set it read ``:help :let``. + +Second command:: + + :Vsti [{format}] + +Instantly writes file with extension specific to export, overwrite existing +files without warning. + +Third command:: + + :Vstm + +Is calling menus. + + +Project file +~~~~~~~~~~~~ + +User can write variables specific to project into special file ``vstrc.vim``, +located into the same directory as processed file. This is regular Vim script +file which will be sourced at the time of export. + +Export to HTML +~~~~~~~~~~~~~~ + +These commands will create XHTML 1.0 file:: + + :Vst html + :Vst + +Vst command (with any export argument) accepts range:: + + :[range]Vst {[export]} + +When file use exclusively lists starting from 1/a/A/etc. doctype is Strict, in +other case it is Transitional. + +From special characters/entities |VST| handles at the moment:: + + <, >, &, (c) + +Results in: <, >, &, (c). + +List can be extended on request. + +.. _vhp: + +``g:vst_html_post`` + String (empty). Filename, sourced after whole processing. In that file + user can put specialized formatting commands, replacing custom or export + dependent templates from replacements etc. For examples check macros_ + section. How to set it read ``:help :let``. + +User CSS +```````` + +User can manipulate how CSS will be attached by combinations of these two +variables (how to use Vim variables read ``:help :let``): + +``g:vst_css_default`` + String (empty). When unmodified default CSS will be included in HTML file. + When non-empty default CSS will be written to external file. Existing file + will be overwritten without warning. If equal to NONE (case sensitive) any + reference to default CSS will be skipped. + +``g:vst_css_user`` + String (empty). When non-empty link to specified file will be included. + +Default CSS is in separate file in autoload/vst/default.css so it is easy to +make global-local modifications. + +Export to S5 +~~~~~~~~~~~~ + +Command:: + + :Vst s5 + +Will create S5_ -- Simple Standards Based Slide Show System. XHTML file steered +by JavaScript and CSS created by Eric Meyer. + +.. _S5: http://meyerweb.com/eric/tools/s5 + +Not every document will be good S5 presentation. All elements but table of +contents are supported but not every one will be good thing to place in one +screen. + +S5 document +``````````` + +File should begin with first level header. It will be title of document. Each +slide will begin with second level header. Author and date to place in footer +will be taken from appropriate fields of field list. + +.. Tip:: + + - it is unwise to use more than two levels of headers + +|VST| provides predefined classes. Both can be introduced by class_ or +container_ directives: + +``handout`` + Elements marked with that class will not be seen in presentation mode, + only handout mode. + +``incremental`` + Elements marked with that class will be displayed gradually, when using + normal forward. This one can be also introduced as a role -- usage of this + element is easier with `default role`_ directive. + +Good example of S5 document was prepared by George V. Reilly and its text +form is included in tarball (doc2/vst-s5.txt). Result can be viewed here__. + +__ http://skawina.eu.org/mikolaj/vst-s5.html + +Export to LaTeX +~~~~~~~~~~~~~~~ + +These commands will LaTeX version of |VST| file:: + + :Vst latex + :Vst tex + +Document will use ``hyperref`` package and it will be fully hyperlinked. +It is better to compile it with ``pdflatex``, directly to PDF than use +pure ``latex``. + +.. _vtp: + +``g:vst_tex_preamble`` + String (empty). User can define his own command (to use in + `raw latex`_) or change some defaults. Should be absolute or relative + path to processed file. Contents of file will be included with + ``\input{}``. + +``g:vst_tex_post`` + String (empty). Filename, sourced after whole processing. In that file + user can put specialized formatting commands, replacing custom or export + dependent templates from replacements etc. + +Current differences between HTML and LaTeX export: + +- 2html is treated as ordinary preformatted text +- custom roles are ignored +- right/left floating frames are ignored + +Export to PDF +~~~~~~~~~~~~~ + +This command will immediately compile PDF document after creation of +LaTeX source:: + + :Vst pdf + +Additional tuning of this command with variables (how to use variables read +``:help :let``): + +``g:vst_pdf_view`` + Boolean (0). When equal 1 immediately show result of compilation. + +``g:vst_pdf_viewer`` + String (default for unices is ``xpdf``, for MS-Windows empty + -- properly setup system will take care about choosing application). + +``g:vst_pdf_clean`` + Boolean (0). When equal 1 remove auxiliary files of PDF compilation + (including tex source -- use with caution!) + +``g:vst_pdf_command`` + String (``pdflatex -interaction=nonstopmode``). Value of this string will + be used to produce PDF document. User may need to modify this variable, + especially if document needs some preprocessing. + +Export to XML +~~~~~~~~~~~~~ + +This command will produce XML-like code:: + + :Vst xml + +For debugging purposes. + +Export to reST +~~~~~~~~~~~~~~ + +This command will remove incompatibilities with reST:: + + :Vst rest + +- identify option of images_ and figures_ will be deleted +- figalign option of figures_ will be deleted +- in Vim commands of `option list`_ leading colon will be replaced with + ``--VIM, :`` +- replace non-breaking space with plain space +- replace 2html directive declaration with '::' + +.. Warning:: This export can result in losing of some formatting. + +Auxiliary commands +~~~~~~~~~~~~~~~~~~ + +|VST| script provides set of auxiliary commands to make easier editing +of bigger files and especially navigating through them. + + +.. _headers: + +``head`` +```````` + +It is possible to lost orientation which type of underscore was used to +mark certain level of sections:: + + :Vst head + +Will show small table with level name and symbols used to mark them:: + + Level Symbol + h1 =========d + h2 --------- + h3 ~~~~~~~~~ + h4 +++++++++ + +This is result of ``Vst head`` for this manual. Letter ``d`` at the end of +ornament shows this is double ornament. + + +.. _contents: + +``toc`` +``````` + +In longer text documents it is very easy to be lost:: + + :Vst toc + +This command will present table of contents for current document. Here +is fragment of table of contents of this manual:: + + h3 ~~~~~~~~~ 5.3 Inline markup rules 553 + h3 ~~~~~~~~~ 5.4 Special characters 587 + h3 ~~~~~~~~~ [[[ 5.5 Roles ]]] 625 + h4 ````````` 5.5.1 Predefined roles 652 + h5 ''''''''' 5.5.1.1 Title reference 658 + h5 ''''''''' 5.5.1.2 Subscript 670 + +It gives plenty of information. First column is name of section level; second +column shows decoration for that level; third column are section titles with +numbers of sections as they will be shown in HTML and LaTeX export. Title of +section were cursor was at the moment of invoking command is taken into +``[[[ ]]]``; fourth column are line numbers of section titles -- user can +immediately issue Vim command, eg. ``:625`` to go to Roles section. + +``link`` and ``slink`` +`````````````````````` + +Commands will show all external links and internal explicit targets in +chronological order:: + + :Vst link + +In alphabetical order:: + + :Vst slink + +Fragment of link table for this document (in chronological order):: + + Text Link + Vim http://www.vim.org + reStructuredText http://docutils.sf.net + starting point http://www.vim.org + comment + Opera http://www.opera.com + vst.pdf http://skawina.eu.org/mikolaj/vst.pdf + +Item without Link part (second column) is internal explicit target. + +``rep`` and ``srep`` +```````````````````` + +Commands will show replace declarations. In chronological order:: + + :Vst rep + +And in alphabetical:: + + :Vst srep + +Replace table for this document (in chronological order):: + + Symbol Replacement + H2O H\ :sub:`2`\ O + from image:image.jpg width:20 height:20 target:URL + VST Vim reStructured Text + + +Folding +``````` + +|VST| offers whole family of commands for folding of file. + +This command will create simple folds for document, each section has its own +fold on the same level:: + + :Vst fold + +Folds are created based on regular expressions and when you add new text to +section fold will be expanded to include them. New sections won't be +recognized automatically and you should recreate folds to include new +sections. + +In front of header text you will see numbers of section as they will be +visible in HTML and LaTeX formats. + +At the end of line enclosed in parenthesis are charaters used as ornament of +section title. + +Command:: + + :Vst foldr + +Will create folds recursively, each level of headers will have its own level +of folding. + +Commands:: + + :Vst fold1 + :Vst fold2 + :Vst fold3 + :Vst fold4 + :Vst fold5 + +Will create one level of folds down to this level of headers. This is can be +useful for visualization of table of contents and faster navigation by big +structures of text. + +Folding by directive +```````````````````` + +For easier finding of some directives user can use special case of folding:: + + :Vst f{directive} + +Where ``{directive}`` is name of directive, eg.: container, blockquote, +image, figure, tip, note, etc. Directive name is case insensitive. + +Special case is:: + + :Vst fblank + +Document will be folded by paragraphs -- fragments of text separated by +blank lines. + +``help`` +```````` + +This command will show short summary of |VST| commands:: + + :Vst help + +``preproc`` +``````````` + +This command will preprocess file and include in file all including commands:: + + :Vst preproc + +This command is recursive. For details see `including commands`_ + +Ornament mapping +```````````````` + +Manual insertion of sections_ or transitions_ ornaments is boring. To speed +things up in Vim way auxiliary mapping was created: o. + +When placed below line of text and above empty one it will fill line to length +of line above. It may use character before cursor, when not available it will +use last single ornamented section title as hint. + +When placed above line of text and below empty line it will embrace line below +in section ornaments. It may use character before cursor, when not available it +will use last double ornamented section title as hint. + +When placed between empty lines it will fill it as transition element. It may +use character before cursor, when not available it will use last transition as +hint. + +Vim settings +~~~~~~~~~~~~ + +Set of Vim settings which can be useful for editing of |VST| files:: + + set nocompatible + set autoindent + set formatoptions+=tqn + set formatlistpat=^\\s*\\(\\d\\+\\\|[a-z]\\)[\\].)]\\s* + set textwidth=78 " purely arbitrary value, just remember to set it + set expandtab + set softtabstop=4 " less than 4 may result in breaking of lists + set shiftwidth=4 + set formatoptions+=tqn + +Syntax highlighting +~~~~~~~~~~~~~~~~~~~ + +Structure of document will be more visible with syntax highlighting. It is +possible to use Vim default syntax highlighting file by Nicolai Weibull just +by issuing Vim command:: + + :set ft=rst + +On `vim-online`_ site is another syntax file by Estienne Swart. + +You can plase filetype declaration in Vim modeline, it will be removed from +output file to not confuse Vim filetype detection (modelines have the highest +priority). But it will work only if filetype setting is in separate |VST| +comment, line matching:: + + ^\s*\.\. vim: + +This line has to be also inside of 'modelines' Vim option range. + +.. _vim-online: http://www.vim.org/scripts/script.php?script_id=973 + + +Menus +~~~~~ + +Command:: + + :Vstm + +in GUI version (gvim) will create menu with most common commands: + +:Export to HTML: `export to HTML`_ +:Export to LaTeX: `export to LaTeX`_ +:Export to PDF: `export to PDF`_ +:Export to reST: `export to reST`_ +:Fold: folding_ of document +:Headers: show symbols of headers_ for various levels +:TOC: show contents_ of text document +:Help: show short help at the bottom of screen + +To show menu always put this command in .vimrc: + +``g:vst_showmenu`` + Boolean (0). When 1 and set in .vimrc it will always show menu. + +Structure +--------- + +Paragraphs +~~~~~~~~~~ + +Base unit of text is **paragraph**, text separated by at least one blank +line. All lines in paragraphs must have the same indentation. Paragraph +indented will be displayed as quotation (blockquote). It is possible to +embed any type and any number of elements inside blockquote -- respecting +their own rules of embedding. Example:: + + This is example of paragraph. This + is continuation of paragraph. + + This is indented paragraph. Looking + like quoted text. + + This is quoted quoted text. Indented two times. + + This is another one. + +Results in: + +This is example of paragraph. This +is continuation of paragraph. + + This is indented paragraph. Looking + like quoted text. + + This is quoted quoted text. Indented two times. + +This is another one. + +Embedding of elements is supported for paragraphs, blockquotes, ordered +lists, unordered lists and tip, note, warning directives. In all of them +can be embedded the rest of one-level elements. + +Text styles +~~~~~~~~~~~ + +Inside of paragraph (and other text elements you can use another markup +-- *italics* with ``*italics*``, **bold** with ``**bold**``, +````double back-quotes```` for ``typewriter text``. + +This text is *italicised*. + +This text is **strongly emphasised**. + +This text is ``a code``. + +If you find that you want to use one of the "special" characters in +text, it should be OK -- |VST| can deal with most typical situations. +For example, this * asterisk is handled just fine. If you actually +want text \*surrounded by asterisks* to **not** be italicised, then +you need to indicate that the asterisk is not special. You do this by +placing a backslash just before it, like so "``\\*``". Remember: special +treatment of these few characters is entering inline literals -- even +there you have to escape it with double backslash:: + + ``\\*`` + +For another method of font manipulation check Roles_. + +Inline markup rules +~~~~~~~~~~~~~~~~~~~ + +These rules apply for `text styles`_ and all other types of inline markup, +especially links_. + +The inline markup start-string and end-string recognition rules are as +follows. If any of the conditions are not met, the start-string or +end-string will not be recognized or processed. + +1. Inline markup start-strings must start a text block or be + immediately preceded by whitespace or one of:: + + ' " ( [ { < - / : + +2. Inline markup start-strings must be immediately followed by + non-whitespace. + +3. Inline markup end-strings must be immediately preceded by + non-whitespace. + +4. Inline markup end-strings must end a text block or be immediately + followed by whitespace or one of:: + + ' " ) ] } > - / : . , ; ! ? \ + +5. If an inline markup start-string is immediately preceded by a + single or double quote, "(", "[", "{", or "<", it must not be + immediately followed by the corresponding single or double quote, + ")", "]", "}", or ">". + +6. An inline markup end-string must be separated by at least one + character from the start-string. + +Special characters +~~~~~~~~~~~~~~~~~~ + +Sometimes it is necessary to escape special treatment of some +characters (or give that meaning). Then you have to put backslash ``\`` +before them. + +Remove space:: + + this\ that + +Result: this\ that + +Do not italicise word:: + + not \*this* word + +Result: not \*this* word + +Insert non-breaking space:: + + non\-breaking\-space + +Result: non\-breaking\-space (``&nbsp;`` in HTML) + +.. Note:: This construction should be avoided and use non-breaking space + instead. It will be replaced with tilde in LaTeX export and leaved + as-is in HTML (it is correctly interpreted by browsers. + + To input non-breaking space in Vim use: + + - 160 in Latin1 and Latin2 encodings (``:help i_CTRL-V_digit``) + - NS (``:help i_digraph``) + +Backslash should be escaped by putting before it another backslash only in +case when backslash could be used in special character. Slight inconsistency +but generally makes text more readable. + +Roles +~~~~~ + +|VST| supports additional methods of text manipulation. They are called +*roles*. Usual form is:: + + :name:`text` + +Roles are requiring white spaces or non-word characters around them. You +can escape them so they will be:: + + H\ :sub:`2`\ O + +Result: H\ :sub:`2`\ O + +It looks awkwardly, especially if repeated many times in text. You can +help it with replacement_:: + + |H2O| + + .. |H2O| replace:: H\ :sub:`2`\ O + +Result is: |H2O| + +.. |H2O| replace:: H\ :sub:`2`\ O + + +Predefined roles +```````````````` + +All predefined roles can be recognized as arguments for `default role`_ +directive. + +Title reference +''''''''''''''' + +This role will should be used to display :t:`Titles of books` and similar +citation sources. There are three ways to declare it in text:: + + :title-reference:`Title` + :title:`Title` + :t:`Title` + +Title reference is default role for interpreted text. + +Subscript +''''''''' + +This role will show :sub:`small text below` normal line of text:: + + :sub:`small text below` + +Superscript +''''''''''' + +This role will show :sup:`small text over` normal line of text:: + + :sup:`small text over` + +Big +''' + +This role will show some :big:`bigger text`:: + + :big:`bigger text` + +Small +''''' + +This role will show some :small:`smaller text`:: + + :small:`smaller text` + +Strong +'''''' + +This role will show :strong:`bold text`:: + + :strong:`bold text` + +Emphasis +'''''''' + +This role will show :emphasis:`emphasised text`:: + + :emphasis:`emphasised text` + +Literal +''''''' + +This role will show :literal:`monospaced text`:: + + :literal:`monospaced text` + +Custom roles +```````````` + +You can use custom roles which will be marked in |VST| source as:: + + :custom:`special text` + +And in HTML output:: + + special text + +In LaTeX output:: + + \vstcustom{special text} + +Note ``vst`` prefix to avoid possible conflicts with built-in (La)TeX +commands. In preamble will be inserted simple template to allow compilation of +document without stopping on unknown commands:: + + \newcommand{\vstcustom}[1]{\textnormal{#1}} + +It will be inserted before declaration of extension of preamble by `external +file`__. If user wants to declare there these new commands he should +use ``renewcommand`` LaTeX command. + +__ vtp_ + +Roles have to be declared through _`role directive`. When not declared will be +silently ignored and any sign of them will be removed from output. Declaration +of role:: + + .. role:: custom + +May be used for example to underline fragment of text (style of decoration not +supported by reST_ or |VST|):: + + .. role:: ul + + This fragment :ul:`will be underlined` + +And in `user CSS`_ file:: + + span.ul { text-decoration: underline } + +Role directive may have an option ``class``:: + + .. role:: name + :class: special + +It will turn:: + + This is :name:`wonderful` feature. + +Into:: + + This is wonderful feature. + +Useful when CSS name is long or not meaningful. + +Reversed notation +````````````````` + +|VST| supports also reversed notation of roles:: + + `text`:name: + +But be careful. Use of it in some cases (replacement-link combo) can give +weird results. + +Lists +~~~~~ + +Lists of items come in three main flavours: **enumerated**, **bulleted** and +**definitions**. List element can contain many body elements. + +Lists must always start a new paragraph -- that is, they must appear +after a blank line. + +Enumerated lists +```````````````` + +Start a line off with a number or letter followed by a period ".", +right bracket ")" or colon ":", also enclosed in parenthesis (a). Following +forms are recognised:: + + 1. numbers + + A. upper-case letters + and it goes over many lines and may contain body elements like + + 1. sub- + 2. -lists + + :: + + Or preformatted text + + a. lower-case letters + + 1) numbers again + + i. lower roman numerals + + I. and upper roman literals + + (a) enumerator enclosed in parenthesis + +Results in: + +1. numbers + +A. upper-case letters + and it goes over many lines and may contain body elements like + + 1. sub- + 2. -lists + + :: + + Or preformatted text + + Or many other elements. + +a. lower-case letters + +1) numbers again + +i. lower roman numerals + +I. and upper roman literals + +(a) enumerator enclosed in parenthesis + +|VST| is taking numeration of first element as numeration of whole +list. This code:: + + a. alpha list + 2. decimal list + +Will be rendered as: + + a. alpha list + b. decimal list + +Two lists of the same type must have separator between them. In other +cause they will be rendered as one:: + + 1. List1 Elem1 + 2. List1 Elem2 + + 1. List2 Elem1 + 2. List2 Elem2 + +Results in: + +1. List1 Elem1 +2. List1 Elem2 + +1. List2 Elem1 +2. List2 Elem2 + +Placing between them empty comment_ is enough. Anyway, short +description is always good thing. + +List does not have to start from 1, a or A. Example:: + + 5. First element of list + #. Second element + +Will become: + +5. First element of list +#. Second element + +And:: + + h. lower alpha list + #. also don't have to start from a + +Results in: + +h. lower alpha list +#. also don't have to start from a + +Also roman numerals can begin not only with i/I. Note however they have to +begin with number containing more than one letter (xl, iii, CV), in other case +they will be treated as alpha lists. Also each list beginning with i/I will be +treated as roman, never as alpha which begins at 9\ :sup:`th` letter of Latin +alphabet. + +.. Warning:: In LaTeX export starting of lists not from 1/a/A/i/I requires + enumitem_ package. + + .. _enumitem: http://www.ctan.org/tex-archive/macros/latex/contrib/enumitem + +Auto numerated lists +```````````````````` + +Lists can be auto numerated. Begin list item with ``#``:: + + #. First item of list + #. Second item of list + +All lists created with ``#`` will be displayed as numerated lists. Result: + +#: First item of list +#: Second item of list + +Bulleted lists +`````````````` + +Just like enumerated lists, start the line off with a bullet point +character -- either "-", "+" or "*":: + + * a bullet using "*" + + - list using "-" + + + yet another list + +Results in: + + * a bullet using "*" + + - list using "-" + + + yet another list + +These elements are connected (HTML only). ``*`` bulleted list always will be +``circle``, ``-`` will be ``disc`` and ``+`` will be ``square``. + +In UTF-8 it is possible to use unicode BULLET characters: + +- \u2022 BULLET +- \u2023 TRIANGULAR BULLET +- \u2043 HYPHEN BULLET +- \u204C BLACK LEFTWARDS BULLET +- \u204D BLACK RIGHTWARDS BULLET +- \u2219 BULLET OPERATOR +- \u25D8 INVERSE BULLET +- \u25E6 WHITE BULLET +- \u2619 REVERSED ROTATED FLORAL HEART BULLET +- \u2765 ROTATED HEAVY BLACK HEART BULLET +- \u2767 ROTATED FLORAL HEART BULLET +- \u29BE CIRCLED WHITE BULLET +- \u29BF CIRCLED BULLET + +To make nicely looking text documents, however all of them will be treated in +output as ``-``. + + +Embedding of lists +`````````````````` + +Enumerated and bulleted lists can contain many elements and can be +nested. This code will be rendered:: + + 1. This is description how to make lists embeddable + one into other. + + - start one list + - insert blank line and bigger indentation + - start another list + - insert blank line before next element + + 2. It is possible to embed paragraphs into list (and blockquotes) + also. + + Paragraphs and blockquotes have to be separated by blank line and + start where list begins: indentation of list "leader" plus + "leader", punctuation sign and space. + + That is memorable quote. + + Those features are not implemented for other types of elements. + Only: plain paragraphs, blockquotes, ordered lists, bulleted + lists. + + Indentation level is *very* important. One space can break + things. + +Results in: + +1. This is description how to make lists embeddable + one into other. + + - start one list + - insert blank line and bigger indentation + - start another list + - insert blank line before next element + +2. It is possible to embed paragraphs into list (and blockquotes) + also. + + Paragraphs and blockquotes have to be separated by blank line and + start where list begins: indentation of list "leader" plus + "leader", punctuation sign and space. + + That is memorable quote. + + Those features are not implemented for other types of elements. Only: + plain paragraphs, blockquotes, ordered lists, bulleted lists. + + Indentation level is *very* important. One space can break things. + +Definition lists +```````````````` + +Unlike the other two, the definition lists consist of a term, and +the definition of that term. The format of a definition list is:: + + what + Definition lists associate a term with a definition. + + *how* + The term is a one-line phrase, and the definition are body elements, + indented relative to the term. Blank lines are not allowed between + term and first line of definition. + + list + 1. First element of definition + 2. don't have to be + 3. plain paragraph. + +Results in: + +what + Definition lists associate a term with a definition. + +*how* + The term is a one-line phrase, and the definition are body elements, + indented relative to the term. Blank lines are not allowed between term + and first line of definition. + +list + 1. First element of definition + 2. don't have to be + 3. plain paragraph. + +Field list +~~~~~~~~~~ + +Special kind of list designed for headers of files or highlighting +important information. Paragraph in form:: + + :Author: Mikolaj Machowski + :Something: Somewhere + +Results in: + +:Author: Mikolaj Machowski +:Something: Somewhere + +Vim recognizes some names of field list as special and places them in +meta info of created documents: + +- Author +- Title +- Date +- Subject +- Keywords + +By default date is displayed in LaTeX documents. User can suppress it by using +keyword NONE:: + + :Date: NONE + +This line will be removed from output and there will be no info about date in +exported document. + +Option list +~~~~~~~~~~~ + +|VST| recognizes also special type of lists: option lists. It is +designed for listing of command options and Vim commands. + +It is possible to create list from various types of command line +options:: + + -a Short form of an option + --all-name Long form of an option + -a, --all-name Combined listing of option + +option Old style options + /VMS VMS and DOS style options + :Vim command And Vim command -- not available in reST + --multi-struct It is possible to use structure elements in + option lists:: + + To present examples of use + + 1. Or possible + 2. uses + 3. Or any other structure element. + + --in-case-of-very-long-option + definition may begin in next line, no trailing space + after option name allowed. + +Option (command) have to be separated from description by at least two +spaces. Above example results in: + +-a Short form of an option +--all-name Long form of an option +-a, --all-name Combined listing of option ++option Old style options +/VMS VMS and DOS style options +:Vim command And Vim command -- not available in reST +--multi-struct It is possible to use structure elements in + option lists:: + + To present examples of use + + 1. Or possible + 2. uses + 3. Or any other structure element. + +--in-case-of-very-long-option + definition may begin in next line, no trailing space + after option name allowed. + +Line blocks +~~~~~~~~~~~ + +Useful for presenting poetry or some preformatted text but not in monospace +font like addresses:: + + | This is *first* line + | This is indented **second** line + | This is indented slightly less then second + line, third (long) line + | And last, :small:`fourth` line + +Will result in: + +| This is *first* line +| This is indented **second** line +| This is indented slightly less then second + line, third (long) line +| And last, :small:`fourth` line + +As you see, you can use markup inside of line block paragraphs. Line without +"| " starting sequence will be treated as continuation of previous line. + +To use | at the beginning of paragraph but without intention of line block +creation, escape it with backslash. + +.. Tip:: Indentation provided by output writers is visually much smaller than + presented in monospace font. Make correction for that. + +.. _double colon: + +Preformatting +~~~~~~~~~~~~~ + +To just include a chunk of preformatted, text, finish the prior +paragraph with "``::``". The preformatted block is finished when the +text falls back to the same indentation level as a paragraph prior to +the preformatted block. For example:: + + An example:: + + Whitespace, newlines, blank lines, and all kinds of markup + (like *this* or \this) is preserved by literal blocks. + Lookie here, I've dropped an indentation level + (but not far enough) + + no more example + +Results in: + +An example:: + + Whitespace, newlines, blank lines, and all kinds of markup + (like *this* or \this) is preserved by literal blocks. + Lookie here, I've dropped an indentation level + (but not far enough) + +no more example + +.. _empty double colon: + +Note that if a paragraph consists only of "``::``", then it's removed +from the output:: + + :: + + This is preformatted text, and the + last "::" paragraph is removed + +Results in: + +:: + + This is preformatted text, and the + last "::" paragraph is removed + +Quoted literal blocks +````````````````````` + +Quoted literal blocks are unindented blocks of text where each line begins +with the same character:: + + ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~ + +**And** previous paragraph ends with ``::``. + +Blank line ends quoted literal block. Quoting characters are preserved. +Example:: + + You wrote:: + + >> Thanks for your work + > + > Glad you appreciate it + + Ha! + +Results in: + +You wrote:: + +>> Thanks for your work +> +> Glad you appreciate it + +Ha! + +Doctest +~~~~~~~ + +Special case of preformatted text are doctest blocks. First line have to begin +with ">>>" and can contain only one paragraph of text (without blank lines):: + + >>> print 'Python-specific usage examples; begun with ">>>"' + Python-specific usage examples; begun with ">>>" + >>> print '(cut and pasted from interactive Python sessions)' + (cut and pasted from interactive Python sessions) + +Sections +~~~~~~~~ + +To break longer text up into sections, you use **section headers**. These are +a single line of text (one or more words) with adornment: an underline, in +dashes "``-----``", equals "``======``", tildes "``~~~~~~``" or any of the +non-alphanumeric characters ``= - ~ ^ ` * + # `` that you feel comfortable +with (full list of chars is in `quoted literal blocks`_ section). The +underline must be at least as long as the title text. Be consistent, since +all sections marked with the same adornment style are deemed to be at the same +level:: + + Chapter 1 Title + =============== + + Section 1.1 Title + ----------------- + + Subsection 1.1.1 Title + ~~~~~~~~~~~~~~~~~~~~~~ + + Section 1.2 Title + ----------------- + + Chapter 2 Title + =============== + +To make some section titles more outstanding you can use double style headers, +with adornments below and *above* of title. These special lines **must** be +equal, both in characters and length. However, these two titles:: + + ================= + Document title + ================= + + Section title + ============= + +Will be treated as two different levels. + +In HTML export sections will be numbered thanks to ``content`` property. +Alas, only small number of WWW browsers are supporting this feature +(Konqueror_, Opera_, Firefox 1.5). + +Section headers don't have to be separated with blank line from next paragraph +but it is recommended. Simple paragraphs not separated from section header +will be treated as subtitles_, rest will be treated normally, only directives +and special markup explicit blocks are forbidden. + +Subtitles +````````` + +It is possible to provide subtitles for section headers. It should be one, +short paragraph placed directly under ornament which will be rendered slightly +bigger than normal text. Example:: + + Directives + ---------- + Or how to place special elements in text + +Check rendering of Directives_ section header. + + +Links +~~~~~ + +Links are important part of modern document. |VST| allows to create +external and internal links. All names declarations are case +insensitive. It means both examples will be working:: + + start_ + + _start: http://www.vim.org + + `Starting point`_ + + .. _starting point: http://www.vim.org + +Jump to tables_ (which is section with title "Tables"). + +Starting point +`````````````` + +Starting point looks like this:: + + We explained `starting point`_ somewhere else + + The same for start_ + +Note: when start is single entity made from ``[:alnum:]``, ``.``, ``-``, +``_`` characters it may not be enclosed in backticks, also if word +is constructed from ``iskeyword`` characters. + + +External links +`````````````` + +Definition of external target:: + + .. _starting point: http://www.vim.org + .. _start: http://skawina.eu.org/mikolaj + +Note: lack of backticks around titles, even when there is more than one +word. Links can be split for several lines:: + + .. _very, very long link description: + http://this.is.address.com/of/this/description + + +Internal links +`````````````` + +Definition of internal target can be done in two ways. + +First is to put definition in text:: + + some text about _`starting point` explaining this term + +Backticks are obligatory. + +Second way is anonymous target:: + + .. _starting point: + +Very similar to external target just pointing nowhere. + + +Standalone links +```````````````` + +Links can be put directly into text when written explicitly in text:: + + This link to http://skawina.eu.org/mikolaj page by + mailto:mikmach@wp.pl. + +Results in: + +This link to http://skawina.eu.org/mikolaj page by mailto:mikmach@wp.pl. + +Supported protocols: http, https, ftp, mailto. + + +Anonymous hyperlinks +```````````````````` + +Definitions of links are boring. For creation of fast links use anonymous +hyperlinks. Example:: + + This is link__ to external document. I don't have time to write__ full + definition. + + __ http://link.to.some.external.doc + .. __: http://second.link.to.external.doc + +As you can see order of links and definitions is important. Should be used +only for fast and dirty work. + + +Indirect links +`````````````` + +Links definitions can be starting points defined elsewhere. Example:: + + .. _my wonderful page: start_ + .. _start: http://skawina.eu.org/mikolaj + +Should point to `my wonderful page`_. + +.. _my wonderful page: start_ +.. _start: http://skawina.eu.org/mikolaj + +This can be also used in anonymous links:: + + __ start_ + +User can even create multi element chains:: + + .. _first elem: secondelem_ + .. _secondelem: thirdelem_ + .. _thirdelem: http://skawina.eu.org/mikolaj + +Here is `first elem`_ link. + +.. _first elem: secondelem_ +.. _secondelem: thirdelem_ +.. _thirdelem: http://skawina.eu.org/mikolaj + + +Embedded URIs +````````````` + +A hyperlink reference may directly embed a target URI inline, within +angle brackets ("<...>") as follows:: + + See the `Vim-online page `_ for info. + +This is exactly equivalent to:: + + See the `Vim-online page`_ for info. + + .. _Vim-online page: http://www.vim.org + +The bracketed URI must be preceded by whitespace and be the last text +before the end string. With a single trailing underscore, the +reference is named and the same target URI may be referred to again. + +With two trailing underscores, the reference and target are both +anonymous, and the target cannot be referred to again. These are +"one-off" hyperlinks in form:: + + This is `embedded URI `__ + This is `John Smith's mail `__ + +Note double underscore at the end and declaration of ``mailto:`` with e-mail. + +There is also possible ultimate compact form:: + + This is link to ``__. + +Results in: + +This is link to ``__. + +Replacement-link combo +`````````````````````` + +It is often boring to write long link texts. Shortening of them is very handy. +|VST| can do that with:: + + This is |vrest|_. + + .. |vrest| replace:: reST implementation for Vim, **the best** editor of Earth + .. _vrest: http://skawina.eu.org/mikolaj/vst.html + +Results in: + +This is |vrest|_. + +.. |vrest| replace:: reST implementation for Vim, **the best** editor of Earth +.. _vrest: http://skawina.eu.org/mikolaj/vst.html + +This also a way to use inline markup inside of links. + +Transitions +~~~~~~~~~~~ + +It is a nice touch to separate some paragraphs and parts of text +visually. In some old-fashioned books it is done with small graphics, in +newer with eg. row of asterisks ``* * *``. + +In |VST| you can do this with line of letters, preferred are characters +used for sections_ underscoring:: + + ================================================ + + ------------------------------------------------ + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ************************************************ + +etc. It have to be separated from other elements with blank lines. In +exported file they will look like straight line: + + ================================================ + + +Attribution +~~~~~~~~~~~ + +When quoting text it is nice to add mention about author of quote. Special +element of text looks like:: + + This is memorable quote. + + -- John Smith, Esq. + +Results in: + + This is memorable quote. + + -- John Smith, Esq. + +Some things which may not be visible: + + - Must be last paragraph of block quote + - Must begin with '--' or '---' and space + +Tables +~~~~~~ + +|VST| provides support for two types of tables. With border:: + + +---------------------+----------------+------------------+ + | Cells are | by bar with | | | + | separated | spaces around | | + +---------------------+----------------+------------------+ + | *You* may use | markup, | included. | + | **inline** | links_ | | + +---------------------+----------------+------------------+ + | You can use various | - like lists | |VST| will | + | types of structure | | interpret them. | + | elements:: | + various | | + | | | Even paragraphs. | + | Welcome to world | - embedded | | + | of preformatted | - one into | 1. And | + | text. | other | 2. not | + | | | 3. only | + +---------------------+----------------+------------------+ + | Text may span across several | | + | columns. Cell can be also empty -> | | + +---------------------+----------------+------------------+ + +This is result of table: + ++---------------------+----------------+------------------+ +| Cells are | by bar with | | | +| separated | spaces around | | ++---------------------+----------------+------------------+ +| *You* may use | markup, | included. | +| **inline** | links_ | | ++---------------------+----------------+------------------+ +| You can use various | - like lists | |VST| will | +| types of structure | | interpret them. | +| elements:: | + various | | +| | | Even paragraphs. | +| Welcome to world | - embedded | | +| of preformatted | - one into | 1. And | +| text. | other | 2. not | +| | | 3. only | ++---------------------+----------------+------------------+ +| Text may span across several | | +| columns. Cell can be also empty -> | | ++---------------------+----------------+------------------+ + +For tables containing bigger chunks of structured text it may be better +to use border less tables. They are looking almost the same as regular +tables with exception of first line which is created with from equal +sign:: + + +======================================================================+ + | This is converted fragment of ChangeLog_ | + +============+=========================================================+ + | 5 Apr 2005 | - FIX: [HTML] properly indent preformatted | + | | text when first line has bigger | + | | indentation than next ones | + | | - CHG: [LaTeX] improve displaying | + | | of field lists | + +------------+---------------------------------------------------------+ + | 6 Apr 2005 | - ADD: Rawlatex directive | + | | - ADD: [HTML] use counters in CSS for | + | | numbering of `table of contents`_ | + | | and sections_ in text. At the moment | + | | this numbering can be seen only in | + | | Konqueror_ 3.4 and Opera_ ver. ? | + +------------+---------------------------------------------------------+ + +Result of above example: + ++======================================================================+ +| This is converted fragment of ChangeLog_ | ++============+=========================================================+ +| 5 Apr 2005 | - FIX: [HTML] properly indent preformatted | +| | text when first line has bigger | +| | indentation than next ones | +| | - CHG: [LaTeX] improve displaying | +| | of field lists | ++------------+---------------------------------------------------------+ +| 6 Apr 2005 | - ADD: Rawlatex directive | +| | - ADD: [HTML] use counters in CSS for | +| | numbering of `table of contents`_ | +| | and sections_ in text. At the moment | +| | this numbering can be seen only in | +| | Konqueror_ 3.4 and Opera_ ver. ? | ++------------+---------------------------------------------------------+ + +Row separator from ``=`` will create head of table. Second such row will +create foot of table (only in HTML export). + +Simple tables +~~~~~~~~~~~~~ + +Full tables are hard to correct and in most cases not necessary. Simple tables +are much simpler to write and maintain. They have also less features. The most +important difference is lack of support for spanning columns. Fragment of +changelog rewritten as simple table:: + + ============ ======================================================== + Date This is converted fragment of ChangeLog_ + ============ ======================================================== + 5 Apr 2005 - FIX: [HTML] properly indent preformatted + text when first line has bigger + indentation than next ones + - CHG: [LaTeX] improve displaying + of field lists + 6 Apr 2005 - ADD: Rawlatex directive + - ADD: [HTML] use counters in CSS for + numbering of `table of contents`_ + and sections_ in text. At the moment + this numbering can be seen only in + Konqueror_ 3.4 and Opera_ ver. ? + ============ ======================================================== + +Results in: + +============ ======================================================== +Date This is converted fragment of ChangeLog_ +============ ======================================================== +5 Apr 2005 - FIX: [HTML] properly indent preformatted + text when first line has bigger + indentation than next ones + - CHG: [LaTeX] improve displaying + of field lists +6 Apr 2005 - ADD: Rawlatex directive + - ADD: [HTML] use counters in CSS for + numbering of `table of contents`_ + and sections_ in text. At the moment + this numbering can be seen only in + Konqueror_ 3.4 and Opera_ ver. ? +============ ======================================================== + +Another nice example is output of ``cal`` program with slight modifications:: + + == == == == == == == + su mo tu we th fr sa + == == == == == == == + 1 + 2 3 4 5 6 7 8 + 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 + 30 31 + == == == == == == == + +Will be shown as: + +== == == == == == == +su mo tu we th fr sa +== == == == == == == + 1 +2 3 4 5 6 7 8 +9 10 11 12 13 14 15 +16 17 18 19 20 21 22 +23 24 25 26 27 28 29 +30 31 +== == == == == == == + +.. _comment: + +Comments +~~~~~~~~ + +To comment fragment of text it should be prepended with two dots:: + + .. This text will be commented. + + This text also will be commented. + + But this not. + +To make commenting easier dots can be in previous line:: + + .. + This line will be commented. + + And this not. + +However, when line with two dots (and only two dots, eventually spaces) will +be followed by blank line even indented lines won't be commented out. + +Comments may be useful to place in output code useful things like Vim +modelines:: + + .. vim:set tw=72: + +or folding markers:: + + .. {{{ + .. }}} + +These lines will be in exported format, just not visible. + +Footnotes +--------- + +You can include in text special links to fragments which don't match +into current paragraph, and place those fragments wherever you want in +document. |VST| supports three types of footnotes: **numbered**, **labeled** +and **auto-numbered**. + +It is possible to use many structure elements in footnotes. They have to be +indented up to ``[`` opening footnote declaration. + +Text of footnotes cannot be placed inside of tables. + +Numbered footnotes +~~~~~~~~~~~~~~~~~~ + +The simplest one. Number is manually assigned to footnote. Example:: + + This doesn't belong here[1]_. + + .. [1] I will describe it here. + +Results in: + +This doesn't belong here[1]_. + +.. [1] I will describe it here. + +There are numbered footnotes, try to keep them in order to not +disorientate readers. |VST| will not warn about duplicate footnotes. + +Auto-numbered footnotes +~~~~~~~~~~~~~~~~~~~~~~~ + +In this type footnotes are declared by author only with ``[#]_``. Text of +footnote will look like:: + + .. [#] Footnote text. + +Order of ``#`` signs is very important. First ``[#]_`` will be +connected with first ``.. [#]``, second ``[#]_`` with second ``.. [#]`` +and so on. + +Labeled footnotes +~~~~~~~~~~~~~~~~~ + +Marking footnotes with ``[#]_`` is fast but user can easily lost orientation. +Solution can be use of labeled footnotes. Example:: + + This is labeled[#lfoot]_ footnote. + + .. [#lfoot] Labeled footnote looks similar to auto numbered but # is + followed by short alphanumeric description. + +Mixing of footnotes +~~~~~~~~~~~~~~~~~~~ + +User can mix types of footnotes but results can be unexpected (and for sure +they will be different from reST_). + +First numbers will be assigned to numbered footnotes, labeled footnotes will +follow with first number bigger then maximum number of numbered footnotes. +Numbers to labels will be assigned in order of use of labels in text. The last +ones will be auto-numbered footnotes. + +.. Note:: Numbering of footnotes in LaTeX will strictly follow order of + footnotes. With mixed types is high probability numbers of footnotes in two + types of export will be different. + + +Citations +--------- + +Special case of footnotes_ are citations. In form:: + + This is citation [Smith1995]_ + + .. [Smith1995] John Smith, *Something about nothing*, Kein Press, 1995. + +Will create footnote-like paragraph and link to this paragraph. + +Directives +---------- +Or how to place special elements in text + +You can achieve special treating of some paragraphs by using +directives. They have always a form of:: + + .. directive:: + +Some directives can contain many various elements of text like lists, +preformatted text, even other directives. + +Unknown directives will be displayed in red frame and in monospace font. + +Images +~~~~~~ + +To include an image in your document, you use the ``image`` directive. +For example:: + + .. image:: test.png + +Spaces in filename should be avoided (or encoded as %20, but can work properly +on standard settings. + +- **Argument**: path to image +- **Options**: + + ``:width:`` + Sets width of image in output document. Example:: + + :width: 200 + + ``:height:`` + Sets height of image in output document. Example:: + + :height: 100 + + ``:identify:`` + Calls ``identify`` program from ImageMagick_ suite to identify + dimensions of image. Possible use of argument -- number will be value + how to scale image in percents. When containing non digit chars, + ignored. Example:: + + :identify: 50 + + .. Note:: Not available in reST. + + ``:scale:`` + Scale values from ``width``, ``height`` and/or ``identify``. Ignored + when values not supplied or argument contain non digit chars. Example:: + + :scale: 50 + + ``:alt:`` + Alternative text to show in WWW browsers when image not loaded. HTML + export only. Example:: + + :alt: Alternative text + + ``:title:`` + Title of image to show in WWW browsers and as caption of image in + LaTeX/PDF output. Example:: + + :title: Title of image + + ``:target:`` + Makes image a link. Argument is a path to location. Special argument + ``self`` points to image itself. Examples:: + + :target: URL + :target: start_ + :target: self + + ``:align:`` + Moves image to the side of document making text flowing around it. + Allowed arguments are ``right`` and ``left``. HTML export only. + + ``:class:`` + Apply special class to image. HTML export only. + +- **Content**: NONE + +Image examples +`````````````` + +You can supply additional information about image with options:: + + .. image:: test.png + :width: 200 + :height: 100 + :alt: Alternative text + :title: Title of image + +Results in: + +.. image:: test.png + :width: 200 + :height: 100 + :alt: Alternative text + :title: Title of image + +Getting info about image dimensions is boring. You can use special +option ``:identify:`` which uses program from ImageMagick_ suite +of programs (available on most OS where Vim is available):: + + .. image:: test.png + :identify: + :alt: Alternative text + :title: Title of image + +``identify:`` can handle argument which will serve as scale factor. 100 +is scale 1:1, scale will decrease size of image **only in document**. Real +size of image will not change:: + + .. image:: test.png + :identify: 50 + :alt: Alternative text + :title: Title of image + +Similar effect can be achieved with option ``:scale:``. Note that +``:identify:`` argument and ``:scale:`` will accumulate. If you declare 50 in +both image will have only 25% of linear size. + +It is possible to make image a link with option ``:target:``:: + + .. image:: test.png + :target: http://www.vst.info/test.png + +It will make image a link to other image. When you are scaling image +view it is a good idea to make it clickable and point to full scale +version -- possible with special argument ``self`` (note limited +usability in LaTeX export):: + + .. image:: test.png + :identify: 50 + :target: self + :alt: Alternative text + :title: Title of image + +Results in: + +.. image:: test.png + :identify: 50 + :target: self + :alt: Alternative text + :title: Title of image + +Figures +~~~~~~~ + +Figure is special construction which creates image with following text +elements will be placed in separate frame with possible text flowing around +(HTML only):: + + .. figure:: test.png + :identify: + + This is description of this figure. + + 1. Can use + 2. Different elements + +Spaces in filename should be avoided (or encoded as %20, but can work properly +on standard settings. + +- **Argument**: path to image +- **Options**: + + ``:width:`` + Sets width of image in output document. Example:: + + :width: 200 + + ``:height:`` + Sets height of image in output document. Example:: + + :height: 100 + + ``:identify:`` + Calls ``identify`` program from ImageMagick_ suite to identify + dimensions of image. Possible use of argument -- number will be value + hot to scale image. When containing non digit chars, ignored. + Example:: + + :identify: 50 + + .. Note:: Not available in reST. + + ``:scale:`` + Scale values from ``width``, ``height`` and/or ``identify``. Ignored + when values not supplied or argument contain non digit chars. Example:: + + :scale: 50 + + ``:alt:`` + Alternative text to show in WWW browsers when image not loaded. HTML + export only. Example:: + + :alt: Alternative text + + ``:title:`` + Title of image to show in WWW browsers and as caption of image in + LaTeX/PDF output. Example:: + + :title: Title of image + + ``:target:`` + Makes image a link. Argument is a path to location. Special argument + ``self`` points to image itself. Examples:: + + :target: URL + :target: start_ + :target: self + + ``:align:`` + Moves image to the side of document making text flowing around it. + Allowed arguments are ``right`` and ``left``. HTML export only. + + .. Note:: When in options without ``:figalign:`` will be interpreted + as align of figure, not image. + + ``:class:`` + Apply special class to image. HTML export only. + + ``:figwidth:`` + Width of figure. By default 400px on HTML export and 0.6 of textwidth + in LaTeX. HTML export only. + + ``:figalign:`` + Side where figure will be placed and text will flow around it. HTML + export only. + + ``:figclass:`` + Apply special class to figure. HTML export only. + +- **Content**: Interpreted as body elements. + +Topic +~~~~~ + +A topic is like a block quote with a title, or a self-contained section with +no subsections. Use the "topic" directive to indicate a self-contained idea +that is separate from the flow of the document. Topics may occur anywhere +a section or transition may occur. + +The directive's sole argument is interpreted as the topic title; the next line +must be blank. All subsequent lines make up the topic body, interpreted as +body elements. Example:: + + .. topic:: Header of topic + + These lines are topic content interpreted + as body elements. + +- **Argument**: header of topic +- **Options**: + + ``:class:`` + Name of class applied to the topic. Only in HTML export. + + One class is predefined -- sidebar:: + + .. topic:: Notes on margin + :class: sidebar + + Elements from that topic will be put in float on right margin. + +- **Content**: Interpreted as body elements + +Sidebar +~~~~~~~ + +A sidebar is like a block quote with a title (also can be subtitle). Use the +"sidebar" directive to indicate a self-contained idea that is separate from +the flow of the document. + +The directive's sole argument is interpreted as the sidebar title; the next +line must be blank. All subsequent lines make up the sidebar body, interpreted +as body elements. Example:: + + .. sidebar:: Header of subtitle + :subtitle: Why this is important + + These lines are sidebar content interpreted + as body elements. + +- **Argument**: header of sidebar +- **Options**: + + ``:class:`` + Name of class applied to the topic. Only in HTML export. + + ``:subtitle:`` + Subtitle of topic. + +- **Content**: Interpreted as body elements + +Table of contents +~~~~~~~~~~~~~~~~~ + +For longer text it is good idea to put in document table of contents. +In |VST| you can place table of contents at desired position with +directive:: + + .. contents:: + +In exported document it will be replaced by unordered list with elements +indented to present structure of document. + +When contents directive is used sections headers will become links to +corresponding entries in table of contents. + +- **Argument**: This directive automatically places also title. Default is + 'Contents'. If you want give title in your language add this as argument to + directive (example for Polish):: + + .. contents:: Spis tresci + + I have omitted Polish diacritics to avoid encoding problems. + +- **Options**: + + ``:depth:`` + Directive ``contents`` accepts option ``:depth:`` which + argument is level of headers shown in table of contents:: + + .. contents: + :depth: 3 + + Will show in table of contents only headers down to 3\ :sup:`rd` + level. + + ``:class:`` + Class of table of contents. In HTML CSS it is presented by two + elements: ``span`` (TOC header) and ``ul`` (TOC contents). + +- **Content**: NONE + +In HTML export table of contents will be numbered thanks to ``content`` +property. Alas, only small number of WWW browsers are supporting this +feature (Konqueror_, Opera_, Firefox1.5). + +Replacement +~~~~~~~~~~~ + +This is an exception from general format of directive:: + + .. |from| replace:: into + +It consists of four parts: leading commas; source part enclosed in +bars; name of directive -- ``replace::``; and the rest of line which will +replace source in file (without leading space). Beware: ``from`` and ``into`` +elements are processed through ``substitute()`` Vim function and have to be +proper Vim regexps. Three characters will be escaped automatically: ``\ & ~``. + +Inline images +````````````` + +Special type of replacement, designed for placement of images inline and +in tables_. + +In text you can use it as normal replacement_ but declaration is +different:: + + .. |from| image::image.jpg + :width: 20 + :height: 20 + :target: URL + +All options of Images_ directive are supported. + +Result looks like that: |from|. + +.. |from| image:: test.png + :width: 20 + :height: 20 + :target: self + +Unicode +``````` + +Not all characters can be shown in localized encodings. For the rest it is +possible to use Unicode (U+ followed by hexadecimal number):: + + .. |from| unicode:: U+2211 .. Sigma sign + +This text will replace marker into unicode sigma sign. Encoding of output +document, regardless of current Vim encoding will be set to utf-8. Text after +two dots will be ignored. + +User can put longer text in replacement:: + + .. |200E| unicode:: 200 U+20AC .. 200 euro + +Spaces will be removed from output. + +Unicode directive accepts one of three options: + +``:ltrim:`` + Will remove space from the left side of sign. + +``:trim:`` + Will remove space from left and right side of sign. + +``:rtrim:`` + Will remove space from right side of sign. + +.. Warning:: + + - Encoding of Vim will not be changed and characters encoded in + utf-8 may be unreadable on terminal with non utf-8 encoding. + - Unicode replacements doesn't work for standard LaTeX + configuration. Direct PDF export will not work and LaTeX may need special + configuration. + +Date +```` + +Inserting of date is tedious. To make it simpler use date replacement +directive:: + + .. |date| date:: + .. |time| date:: %H:%M + +Without arguments placeholder will be replaced with date in ISO format +YYYY-MM-DD. Arguments are following ``strftime()`` syntax. This function isn't +available on all systems, in such case placeholder will be replaced with +seconds from epoch :) + +Including commands +~~~~~~~~~~~~~~~~~~ + +With bigger sets of documents some parts can be repeated. In such case it is +good idea to put them in external file and only include it in proper place. +Also it gives profits when making changes. User have to only make correction +in one file, not in whole collection. |VST| provides three directives. All are +making the same thing -- include text file -- written in VST before any other +activity. + +1. This command will include file in given place:: + + .. header:: {filename} + + Regardless of placement of this directive file will be put in the + beginning of exported file. + +2. This command will include file in given place:: + + .. include:: {filename} + +3. This command will include file in given place:: + + .. footer:: {filename} + + Regardless of placement of this directive file will be put at the end of + exported file. + +- **Argument**: String. + + - If it is readable file its contents will be included and parsed as |VST|. + - Predefined name: ``vstfooter``. Contains date of generation and link to + source file. ``vstfooter`` will be used also in case when argument will be + empty. + - When filename is enclosed in <> |VST| will search in directory defined by + ``g:vst_included`` variable. By default it is defined as: first element of + 'runtimepath' option plus ``autoload/vst/include/`` directory. For example + on Linux it will be:: + + $HOME/.vim/autoload/vst/include/ + + This can be used for standard substitutions like provided by `reST + substitutes`_, personal set of substitutions or other type of data. + + - For header and footer in other cases it will be treated as short message + to include at the top or bottom of the document and separated with + horizontal line from the rest of document. + - When including files indentation of directive will be taken into account. + It may be convenient to produce program listings in connection with `double + colon`_ or 2html_ directive. + +- **Options**: NONE +- **Content**: NONE + +.. Note:: To avoid endless loops level of recursiveness is equal to Vim's + option 'maxfuncdepth'/2 (default: 50). + +.. _reST substitutes: + http://docutils.sf.net/docs/ref/rst/substitutions.html#character-entity-sets + +Tip +~~~ + +This directive can contain many various elements:: + + .. tip:: First paragraph. + + 1. List element + 2. List element + + Second paragraph + +- **Argument**: NONE +- **Options**: NONE +- **Content**: Interpreted as body elements + +Above example results in: + +.. tip:: First paragraph. + + 1. List element + 2. List element + + Second paragraph + +All elements must have bigger indentation than directive. These +elements will be placed in green frame and with title 'Tip'. + +Note +~~~~ + +This directive can contain many various elements:: + + .. Note:: First paragraph. + + Remember these noble words. + + Second paragraph + +- **Argument**: NONE +- **Options**: NONE +- **Content**: Interpreted as body elements + +Above example results in: + + .. Note:: First paragraph. + + Remember these noble words. + + Second paragraph + +All elements must have bigger indentation than directive. These +elements will be placed in black frame and with title 'Note'. + +Warning +~~~~~~~ + +This directive can contain many various elements:: + + .. Warning:: First paragraph. + + - List element + - List element + + Second paragraph + +- **Argument**: NONE +- **Options**: NONE +- **Content**: Interpreted as body elements + +Above example results in: + +.. Warning:: First paragraph. + + - List element + - List element + + Second paragraph + +All elements must have bigger indentation than directive. These +elements will be placed in red frame and with title 'Warning'. + +Admonition +~~~~~~~~~~ + +General form of multi element message directive (MEMD). Have form:: + + .. admonition:: + :class: <class> + + Text of admonition (many elements). + +- **Argument**: title of admonition +- **Options** + + ``:class:`` + describes look of admonition. By default ``note``, available three + classes: ``note``, ``tip``, ``warning``. + +- **Content**: Interpreted as body elements. MUST be separated from header by + blank line. + +Directive can be used as i18n version of any other MEMD. + +Pull-quote +~~~~~~~~~~ + +Semantically similar to blockquote but in addition to being indented text will +be displayed with bigger font to attract attention:: + + .. pull-quote:: + + This is time of our lives! + +Results in: + +.. pull-quote:: + + This is time of our lives! + +- **Argument**: NONE +- **Options**: NONE +- **Content**: Interpreted as block quote. + + +Container +~~~~~~~~~ + +General block directive:: + + .. container:: classname + +- **Argument**: class name, may use any character, string will be parsed to + eliminate them +- **Options**: NONE +- **Content**: Interpreted as body elements + +HTML output:: + + <div class="classname"> content of container </div> + +LaTeX output:: + + \vstclassname{ content of container } + +Note ``vst`` prefix to avoid possible conflicts with built-in (La)TeX +commands. In preamble will be inserted simple template to allow compilation of +document without stopping on unknown commands:: + + \newcommand{\vstclassname}[1]{#1} + +It will be inserted before declaration of extension of preamble by `external +file`__. If user wants to declare there these new commands he should +use ``renewcommand`` LaTeX command. + +__ vtp_ + +Compound +~~~~~~~~ + +Similar to container_ but designed to distinguish text rather semantically, not +visually: + + .. compound:: <class> + +- **Argument**: NONE +- **Options** + + ``:class:`` + describes look of admonition + +- **Content**: Interpreted as body elements + +Class +~~~~~ + +This directive allows to apply arbitrary class name to most block elements +(HTML only):: + + .. class:: name + +There is an exception: Class directive will be ignored for directives which +has ``:class:`` option. + +If next element has the same level of indentation class will be applied only +to that alement. But if next elements has bigger indentation class will be +applied to all of them:: + + .. class:: name + + First paragraph + + Second paragraph + + Third paragraph + +``name`` class will be applied to first and second paragraph but to to third. + +.. Note:: ``name`` class style will be added to default style, not replace it. + +- **Argument**: class name, may use any character, string will be parsed to + eliminate them +- **Options**: NONE +- **Content**: Interpreted as body elements + +Default role +~~~~~~~~~~~~ + +This role sets default text role used for interpreted tex without declared +role. For example, after setting:: + + .. default-role:: newstyle + +Text enclosed in backticks will be presented with help of ``newstyle`` class. +Default role for |VST| is `title reference`_. + +- **Argument**: class name, may use any character, string will be parsed to + eliminate them +- **Options**: NONE +- **Content**: NONE + +Meta +~~~~ + +This directive can be useful when providing meta data which user don't want to +be visible in form of `field list`_:: + + .. meta:: + :author: Mikolaj Machowski + :subject: Vim reStructured Text + :http-equiv=Content-Type: text/html; charset=iso-8859-2 + :description lang=en: Special text formatting + +In HTML export this list will be included into meta tags of header. In LaTeX +four keywords will be recognized and put into PDF info: author, title, +subject, keywords. + +- **Argument**: List of keywords with descriptions. +- **Options**: NONE +- **Content**: NONE + +Title +~~~~~ + +Title directive may be used to place your own text in title tag of HTML export +or in PDF info fields. This title will not be visible in document itself:: + + .. title:: VST documentation + +- **Argument**: Title of document +- **Options**: NONE +- **Content**: NONE + +Rubric +~~~~~~ + +This directive shows line as header but without semantic meaning of header:: + + .. rubric:: This may be of interest for readers + +- **Argument**: class name, may use any character, string will be parsed to + eliminate them +- **Options**: NONE +- **Content**: NONE + +Raw +~~~ + +Raw latex +````````` + +HTML and pure text are often not enough to present some mathematical +concepts. You can use then raw LaTeX directive:: + + .. raw:: latex + .. raw:: tex + +- **Argument**: name of export: html, latex (case sensitive) +- **Options**: + + ``:file:`` + External file which will be read into file. Example:: + + :file: path/to/file.tex + + Contrary to treating of content there is no fall back for other + format. + +- **Content**: one indented paragraph of LaTeX source + +Content of this directive will not be visible in HTML export and in LaTeX +literally. This directive must be a one paragraph of |VST| -- without blank +lines. But you can make it multi paragraph LaTeX content with ``\par`` +command:: + + .. raw:: latex + + This is first par with special $\pi$ content. + \par + This is second par with special $\alpha$ content. + \par + \emph{Indentation} doesn't have special meaning but it is + good for visual separation of \texttt{paragraphs}. + +Results in: + +.. raw:: latex + + This is first par with special $\pi$ content. + \par + This is second par with special $\alpha$ content. + \par + \emph{Indentation} doesn't have special meaning but it is + good for visual separation of \texttt{paragraphs}. + +Content of this directive (and above example) will not be visible in HTML +export. This directive must be a one paragraph of |VST| -- without blank lines. + +Raw latex replaces ``latexonly`` directive which is considered deprecated. + +Raw html +```````` + +:: + + .. raw:: html + +- **Argument**: name of export: html, latex (case sensitive) +- **Options**: + + ``:file:`` + External file which will be read into file. Example:: + + :file: path/to/file.html + + Contrary to treating of content there is no fall back for other + format. + +- **Content**: one indented paragraph + +:: + + .. raw:: html + + <p>CO<sub>2</sub></p> + +Results in: + +.. raw:: html + + <p>CO<sub>2</sub></p> + +Content of this directive (and above example) will not be visible in LaTeX +export. This directive must be a one paragraph of |VST| -- without blank lines. + +Raw html replaces ``htmlonly`` directive which is considered deprecated. + +Both +```` + +Directive will accept also two arguments (HTML and LaTeX), it will be passed +without any modifications in two exports:: + + .. raw:: html latex + +Order is not significant. + +2html +~~~~~ + +.. Note:: Not available in reST. Colors in HTML only. + +Directive designed to make use from ``2html.vim`` script for syntax +highlighting of code:: + + .. 2html:: [{filetype}] + .. 2html:: filetype [{colorscheme}] + +``2html`` directive is extended declaration of `empty double colon`_. +Following paragraphs have to be separated by blank line and must have +bigger indentation. + +- **Arguments**: + + ``filetype`` + Argument will set proper highlighting for the following fragment of + code (usually those snippets will be too short for automatic + recognition). May be omitted, following paragraphs will be treated + as normal code snippets -- without coloring. Obligatory if you want + to declare ``colorscheme``. + + ``colorscheme`` + Will set color scheme used for syntax highlighting. If omitted + current color scheme will be used. If you started without color + scheme and declared ``colorscheme`` argument it will be set. When + declared colorscheme doesn't exist default/current colorscheme will + be used. + +- **Options**: NONE +- **Content**: Interpreted as preformatted text + +.. Tip:: Not all colorschemes look good when exported to HTML. It is wise idea + to check result before official presentation. Especially ``default`` is + hard to read on white background -- and this is default combination when + doing export from non-GUI version of Vim. It is a good idea to set + ``g:colors_name`` somewhere because it will be used in such case. When you + try to export this document on your system check example below with manxome + colorscheme which is not included in default Vim distribution. + +2html examples +`````````````` + +Fragment of ``vst.vim`` in blue colorscheme:: + + .. 2html:: vim blue + + if exists('depth') && depth != '' + let hdepth = strpart(g:ptype[j], '1') + if hdepth > depth + let j += 1 + continue + endif + endif + +Result: + +.. 2html:: vim blue + + if exists('depth') && depth != '' + let hdepth = strpart(g:ptype[j], '1') + if hdepth > depth + let j += 1 + continue + endif + endif + +The same fragment in manxome: + +.. 2html:: vim manxome + + if exists('depth') && depth != '' + let hdepth = strpart(g:ptype[j], '1') + if hdepth > depth + let j += 1 + continue + endif + endif + +And fragment of Vim itself -- ex_cmds.c by murphy. Declaration:: + + .. 2html:: c murphy + +.. 2html:: c murphy + + if (fp_out != NULL) + { + (void)mch_setperm(tempname, + (long)((st_old.st_mode & 0777) | 0600)); + /* this only works for root: */ + (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid); + } + + +Macros +------ + +Not everything can be done with VST syntax. Here are coming **macros**. Macro +is keyword with optional value after colon like:: + + {macroname:argument} + +They are not codified. To show what can be achieved with them to distribution +is added ``myhtmlvst.vim`` file with examples of two macros: + +1. :: + + {read:file} + + First macro read file and put it inside of ``pre`` tag (it is like Vim + ``:read`` command). + +2. :: + + {readpython:file} + + Second _macro interpret contents of file and put it also in ``pre`` tag + (like Vim ``:read!`` command). + + This command is smart. It can catch name of program between read and : and + call it later. Thus it can become {readperl}, {readruby}, {readbash}, etc. + Program name has to match ``\w\+`` regexp. + + ``readbang`` has special value -- it will execute shell command. + + .. Warning:: This macro can have serious security consequences!!! + +These two macros are line wise and must be kept in separate lines with +nothing around them. + +Macro file is executed with help of `g:vst_html_post variable`__. + +__ vhp_ + +Thanks +------ + +I'd like to say thanks to: + +- Bram Moolenaar for great editor +- All authors of ``2html.vim`` +- Authors of reST_ documentation +- George V. Reilly for extensive testing +- Edward G.J. Lee for traditional Chinese support in LaTeX + +FAQ +--- + +- **Why VST was created?** For long time Vim users were asking for export + to real, human readable HTML text. Default 2html.vim does wonderful job but + only in regard to code. For other documents it is not well suited. + +- **Why reST_ syntax and not ...?** I was looking through several text format + syntaxes but only reStructuredText was looking complete enough for me. Also + major plus for reST was fact that (contrary to all Wikis I saw) it was + designed to look equally good in original text form. + +- **Will VST support all reST features?** Rather not. It is too big project + and develop too fast to catch up. All major features at the moment (1 Dec + 2005) were implemented, minor features are covered to satisfy most users + IMO -- you can compare differences in `compatibility table`_. + + .. _compatibility table: http://skawina.eu.org/mikolaj/restdiff.html + + Also there are many pythonisms in reST I am personally not interested. Vim + Python users will probably install reST and will be happy, other wont be + interested in them. + +- **Will be VST files fully compatible with reST?** It depends on user. There + are features Vim specific (like accepting of Vim commands in option lists), + or features that could not find in reST and seemed necessary for me. Also + some structure elements are practically impossible to implement in the same + way as in reST. I decided it is better to provide different implementation + that nothing. + +- **How to make...?** Not everything can be made by pure VST or syntax. That + is what ``g:vst_xxx_post`` is for. For example, if you really must break + lines in HTML with ``br`` tag put placeholder ``{br}`` in your document, + and write:: + + %s/{br}/<br\/>/ge + + in ``myhtmlvst.vim`` file and set:: + + let g:vst_html_post = "myhtmlvst.vim" + + For other examples check macros_ section. + +- **How to get only body of document?** Yes, this can be useful for writing blogs + or embedding text in other documents. As in previous question the answer is: + ``g:vst_xxx_post``. Example for HTML:: + + :1,/<body>/ d + :/<\/body/,$ d + + Also it is possible to get rid of VST specific ``id``\ s and ``class``\ es + with:: + + :%s/\(id\|class\)=".\{-}"//ge + +- **Why should I choose VST over reST?** + + 1. No dependency on external tools. Unpack .zip archive and everything is ready. + 2. reST is hard to install. I tried several times on Linux to set it up + properly -- $PATH and everything. Failed each time. Don't want even + think how to install it on MS-Windows. Plus installation of Python + itself. + 3. 2html_ directive. Whole power of Vim syntax and colorscheme files on + your command! + + Still, reST users may find some commands provided by VST useful. Check + `auxiliary commands`_ section. + +- **What are the differences between VST and reST?** Comparison table is long + and is in `separate file`_. + + .. _separate file: http://skawina.eu.org/mikolaj/restdiff.html + +ChangeLog +--------- + +:FIX: bug fix +:ADD: new feature +:CHG: change of behaviour +:RMV: remove feature +:LaTeX/HTML/etc: apply to export, without that tag -- global + +Full ChangeLog is here: `vst-changelog`_. + +.. _vst-changelog: http://skawina.eu.org/mikolaj/vst-changelog.html + +Changes from last announcement: + +- 31 Oct 2006 - **1.3** announcement + + - FIX: Vst link broken + - FIX: & in URLs double encoded + - FIX: broken chained links with uppercase letters + + +- REMEMBER ABOUT UPDATING DOCS + +TODO +---- + +There is no roadmap for these things, they are just loose thoughts what +can be done in the future. + +reST compatibility things are in `compatibility table`_ with (td) note. + +- rotation of ornaments in titles +- option for XHTML doctype with proper content? +- image inside of admonition in LaTeX export (minipage conflicts...) +- show worded reference as label +- (doc) Quick start table +- start description of option in next line if option name too long +- fix _top in CSS (IE...) + ++ REMEMBER ABOUT UPDATING DOCS + +Copyright (c) Mikolaj Machowski, 2006 + + +.. |VST| replace:: Vim reStructured Text + +.. _reStructuredText: http://docutils.sf.net +.. _reST: http://docutils.sf.net +.. _Python: http://www.python.org +.. _Vim: http://www.vim.org +.. _OpenOffice.org: http://www.openoffice.org +.. _KOffice: http://koffice.kde.org +.. _MS-Office: http://www.microsoft.com +.. _ImageMagick: http://www.imagemagick.org +.. _Konqueror: http://www.kde.org +.. _Opera: http://www.opera.com + +.. vim:set tw=78 ai fo+=n fo-=l ft=rst: diff --git a/filetype.vim b/filetype.vim new file mode 100644 index 0000000..363ec0b --- /dev/null +++ b/filetype.vim @@ -0,0 +1,9 @@ +" markdown filetype file +if exists("did\_load\_filetypes") + finish +endif + +augroup markdown + au! BufRead,BufNewFile *.mkd setfiletype mkd +augroup END + diff --git a/ftplugin/html_snip_helper.vim b/ftplugin/html_snip_helper.vim new file mode 100644 index 0000000..2e54570 --- /dev/null +++ b/ftplugin/html_snip_helper.vim @@ -0,0 +1,10 @@ +" Helper function for (x)html snippets +if exists('s:did_snip_helper') || &cp || !exists('loaded_snips') + finish +endif +let s:did_snip_helper = 1 + +" Automatically closes tag if in xhtml +fun! Close() + return stridx(&ft, 'xhtml') == -1 ? '' : ' /' +endf diff --git a/ftplugin/python/eclim_py.vim b/ftplugin/python/eclim_py.vim new file mode 100644 index 0000000..4966061 --- /dev/null +++ b/ftplugin/python/eclim_py.vim @@ -0,0 +1,28 @@ +" ftplugin for python. +" See: eclim_py plugin in plugins dir +" Global Variables {{{ + +if !exists("g:EclimPythonValidate") + let g:EclimPythonValidate = 1 +endif + +" }}} + +" Autocmds {{{ + +if g:EclimPythonValidate + augroup eclim_python_validate + autocmd! BufWritePost <buffer> + autocmd BufWritePost <buffer> call Validate(1) + augroup END +endif + +" }}} + +if !exists(":Validate") + command -nargs=0 -buffer Validate :call Validate(0) +endif +if !exists(":PyLint") + command -nargs=0 -buffer PyLint :call PyLint() +endif + diff --git a/ftplugin/python/pyflakes.vim b/ftplugin/python/pyflakes.vim new file mode 100644 index 0000000..4739c2f --- /dev/null +++ b/ftplugin/python/pyflakes.vim @@ -0,0 +1,226 @@ +" pyflakes.vim - A script to highlight Python code on the fly with warnings +" from Pyflakes, a Python lint tool. +" +" Place this script and the accompanying pyflakes directory in +" .vim/ftplugin/python. +" +" See README for additional installation and information. +" +" Thanks to matlib.vim for ideas/code on interactive linting. +" +" Maintainer: Kevin Watters <kevin.watters@gmail.com> +" Version: 0.1 + +if exists("b:did_pyflakes_plugin") + finish " only load once +else + let b:did_pyflakes_plugin = 1 +endif + +if !exists('g:pyflakes_builtins') + let g:pyflakes_builtins = [] +endif + +if !exists("b:did_python_init") + let b:did_python_init = 0 + + if !has('python') + echoerr "Error: the pyflakes.vim plugin requires Vim to be compiled with +python" + finish + endif + + python << EOF +import vim +import os.path +import sys + +if sys.version_info[:2] < (2, 5): + raise AssertionError('Vim must be compiled with Python 2.5 or higher; you have ' + sys.version) + +# get the directory this script is in: the pyflakes python module should be installed there. +scriptdir = os.path.join(os.path.dirname(vim.eval('expand("<sfile>")')), 'pyflakes') +sys.path.insert(0, scriptdir) + +from pyflakes import checker, ast, messages +from operator import attrgetter + +class SyntaxError(messages.Message): + message = 'could not compile: %s' + def __init__(self, filename, lineno, col, message): + messages.Message.__init__(self, filename, lineno, col) + self.message_args = (message,) + +class blackhole(object): + write = flush = lambda *a, **k: None + +def check(buffer): + filename = buffer.name + contents = '\n'.join(buffer[:]) + '\n' + + vimenc = vim.eval('&encoding') + if vimenc: + contents = contents.decode(vimenc) + + builtins = [] + try: + builtins = eval(vim.eval('string(g:pyflakes_builtins)')) + except Exception: + pass + + try: + # TODO: use warnings filters instead of ignoring stderr + old_stderr, sys.stderr = sys.stderr, blackhole() + try: + tree = ast.parse(contents, filename) + finally: + sys.stderr = old_stderr + except: + try: + value = sys.exc_info()[1] + lineno, offset, line = value[1][1:] + except IndexError: + lineno, offset, line = 1, 0, '' + if line and line.endswith("\n"): + line = line[:-1] + + return [SyntaxError(filename, lineno, offset, str(value))] + else: + w = checker.Checker(tree, filename, builtins = builtins) + w.messages.sort(key = attrgetter('lineno')) + return w.messages + + +def vim_quote(s): + return s.replace("'", "''") +EOF + let b:did_python_init = 1 +endif + +if !b:did_python_init + finish +endif + +au BufLeave <buffer> call s:ClearPyflakes() + +au BufEnter <buffer> call s:RunPyflakes() +au InsertLeave <buffer> call s:RunPyflakes() +au InsertEnter <buffer> call s:RunPyflakes() +au BufWritePost <buffer> call s:RunPyflakes() + +au CursorHold <buffer> call s:RunPyflakes() +au CursorHoldI <buffer> call s:RunPyflakes() + +au CursorHold <buffer> call s:GetPyflakesMessage() +au CursorMoved <buffer> call s:GetPyflakesMessage() + +if !exists("*s:PyflakesUpdate") + function s:PyflakesUpdate() + silent call s:RunPyflakes() + call s:GetPyflakesMessage() + endfunction +endif + +" Call this function in your .vimrc to update PyFlakes +if !exists(":PyflakesUpdate") + command PyflakesUpdate :call s:PyflakesUpdate() +endif + +" Hook common text manipulation commands to update PyFlakes +" TODO: is there a more general "text op" autocommand we could register +" for here? +noremap <buffer><silent> dd dd:PyflakesUpdate<CR> +noremap <buffer><silent> dw dw:PyflakesUpdate<CR> +noremap <buffer><silent> u u:PyflakesUpdate<CR> +noremap <buffer><silent> <C-R> <C-R>:PyflakesUpdate<CR> + +" WideMsg() prints [long] message up to (&columns-1) length +" guaranteed without "Press Enter" prompt. +if !exists("*s:WideMsg") + function s:WideMsg(msg) + let x=&ruler | let y=&showcmd + set noruler noshowcmd + redraw + echo a:msg + let &ruler=x | let &showcmd=y + endfun +endif + +if !exists("*s:RunPyflakes") + function s:RunPyflakes() + highlight link PyFlakes SpellBad + + if exists("b:cleared") + if b:cleared == 0 + silent call s:ClearPyflakes() + let b:cleared = 1 + endif + else + let b:cleared = 1 + endif + + let b:matched = [] + let b:matchedlines = {} + python << EOF +for w in check(vim.current.buffer): + vim.command('let s:matchDict = {}') + vim.command("let s:matchDict['lineNum'] = " + str(w.lineno)) + vim.command("let s:matchDict['message'] = '%s'" % vim_quote(w.message % w.message_args)) + vim.command("let b:matchedlines[" + str(w.lineno) + "] = s:matchDict") + + if w.col is None or isinstance(w, SyntaxError): + # without column information, just highlight the whole line + # (minus the newline) + vim.command(r"let s:mID = matchadd('PyFlakes', '\%" + str(w.lineno) + r"l\n\@!')") + else: + # with a column number, highlight the first keyword there + vim.command(r"let s:mID = matchadd('PyFlakes', '^\%" + str(w.lineno) + r"l\_.\{-}\zs\k\+\k\@!\%>" + str(w.col) + r"c')") + + vim.command("call add(b:matched, s:matchDict)") +EOF + let b:cleared = 0 + endfunction +end + +" keep track of whether or not we are showing a message +let b:showing_message = 0 + +if !exists("*s:GetPyflakesMessage") + function s:GetPyflakesMessage() + let s:cursorPos = getpos(".") + + " Bail if RunPyflakes hasn't been called yet. + if !exists('b:matchedlines') + return + endif + + " if there's a message for the line the cursor is currently on, echo + " it to the console + if has_key(b:matchedlines, s:cursorPos[1]) + let s:pyflakesMatch = get(b:matchedlines, s:cursorPos[1]) + call s:WideMsg(s:pyflakesMatch['message']) + let b:showing_message = 1 + return + endif + + " otherwise, if we're showing a message, clear it + if b:showing_message == 1 + echo + let b:showing_message = 0 + endif + endfunction +endif + +if !exists('*s:ClearPyflakes') + function s:ClearPyflakes() + let s:matches = getmatches() + for s:matchId in s:matches + if s:matchId['group'] == 'PyFlakes' + call matchdelete(s:matchId['id']) + endif + endfor + let b:matched = [] + let b:matchedlines = {} + let b:cleared = 1 + endfunction +endif + diff --git a/ftplugin/python/pyflakes/LICENSE b/ftplugin/python/pyflakes/LICENSE new file mode 100644 index 0000000..42b8cf3 --- /dev/null +++ b/ftplugin/python/pyflakes/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2005 Divmod, Inc., http://www.divmod.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ftplugin/python/pyflakes/README.rst b/ftplugin/python/pyflakes/README.rst new file mode 100644 index 0000000..9ac34fc --- /dev/null +++ b/ftplugin/python/pyflakes/README.rst @@ -0,0 +1,36 @@ +pyflakes +======== + +This version of PyFlakes_ has been improved to use Python's newer ``ast`` +module, instead of ``compiler``. So code checking happens faster, and will stay +up to date with new language changes. + +.. _PyFlakes: http://http://www.divmod.org/trac/wiki/DivmodPyflakes + +TODO +---- + +Importing several modules from the same package results in unnecessary warnings: + +:: + + import a.b + import a.c # Redefinition of unused "a" from line 1 + +The following construct for defining a function differently depending on some +condition results in a redefinition warning: + +:: + + if some_condition: + def foo(): do_foo() + else: + def foo(): do_bar() # redefinition of function 'foo' from line 2 + +IDE Integration +--------------- + +* vim: pyflakes-vim_ + +.. _pyflakes-vim: http://github.com/kevinw/pyflakes-vim + diff --git a/ftplugin/python/pyflakes/TODO b/ftplugin/python/pyflakes/TODO new file mode 100644 index 0000000..69f3f12 --- /dev/null +++ b/ftplugin/python/pyflakes/TODO @@ -0,0 +1,11 @@ + - Check for methods that override other methods except that they vary by case. + - assign/increment + unbound local error not caught + def foo(): + bar = 5 + def meep(): + bar += 2 + meep() + print bar + + print foo() + diff --git a/ftplugin/python/pyflakes/bin/pyflakes b/ftplugin/python/pyflakes/bin/pyflakes new file mode 100644 index 0000000..3f50805 --- /dev/null +++ b/ftplugin/python/pyflakes/bin/pyflakes @@ -0,0 +1,4 @@ +#!/usr/bin/python + +from pyflakes.scripts.pyflakes import main +main() diff --git a/ftplugin/python/pyflakes/pyflakes/__init__.py b/ftplugin/python/pyflakes/pyflakes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ftplugin/python/pyflakes/pyflakes/__init__.pyc b/ftplugin/python/pyflakes/pyflakes/__init__.pyc new file mode 100644 index 0000000..bb3ff8a Binary files /dev/null and b/ftplugin/python/pyflakes/pyflakes/__init__.pyc differ diff --git a/ftplugin/python/pyflakes/pyflakes/ast.py b/ftplugin/python/pyflakes/pyflakes/ast.py new file mode 100644 index 0000000..d52025f --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/ast.py @@ -0,0 +1,311 @@ +# -*- coding: utf-8 -*- +""" + ast + ~~~ + + The `ast` module helps Python applications to process trees of the Python + abstract syntax grammar. The abstract syntax itself might change with + each Python release; this module helps to find out programmatically what + the current grammar looks like and allows modifications of it. + + An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as + a flag to the `compile()` builtin function or by using the `parse()` + function from this module. The result will be a tree of objects whose + classes all inherit from `ast.AST`. + + A modified abstract syntax tree can be compiled into a Python code object + using the built-in `compile()` function. + + Additionally various helper functions are provided that make working with + the trees simpler. The main intention of the helper functions and this + module in general is to provide an easy to use interface for libraries + that work tightly with the python syntax (template engines for example). + + + :copyright: Copyright 2008 by Armin Ronacher. + :license: Python License. +""" +from _ast import * +from _ast import __version__ + + +def parse(expr, filename='<unknown>', mode='exec'): + """ + Parse an expression into an AST node. + Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST). + """ + return compile(expr, filename, mode, PyCF_ONLY_AST) + + +def literal_eval(node_or_string): + """ + Safely evaluate an expression node or a string containing a Python + expression. The string or node provided may only consist of the following + Python literal structures: strings, numbers, tuples, lists, dicts, booleans, + and None. + """ + _safe_names = {'None': None, 'True': True, 'False': False} + if isinstance(node_or_string, basestring): + node_or_string = parse(node_or_string, mode='eval') + if isinstance(node_or_string, Expression): + node_or_string = node_or_string.body + def _convert(node): + if isinstance(node, Str): + return node.s + elif isinstance(node, Num): + return node.n + elif isinstance(node, Tuple): + return tuple(map(_convert, node.elts)) + elif isinstance(node, List): + return list(map(_convert, node.elts)) + elif isinstance(node, Dict): + return dict((_convert(k), _convert(v)) for k, v + in zip(node.keys, node.values)) + elif isinstance(node, Name): + if node.id in _safe_names: + return _safe_names[node.id] + raise ValueError('malformed string') + return _convert(node_or_string) + + +def dump(node, annotate_fields=True, include_attributes=False): + """ + Return a formatted dump of the tree in *node*. This is mainly useful for + debugging purposes. The returned string will show the names and the values + for fields. This makes the code impossible to evaluate, so if evaluation is + wanted *annotate_fields* must be set to False. Attributes such as line + numbers and column offsets are not dumped by default. If this is wanted, + *include_attributes* can be set to True. + """ + def _format(node): + if isinstance(node, AST): + fields = [(a, _format(b)) for a, b in iter_fields(node)] + rv = '%s(%s' % (node.__class__.__name__, ', '.join( + ('%s=%s' % field for field in fields) + if annotate_fields else + (b for a, b in fields) + )) + if include_attributes and node._attributes: + rv += fields and ', ' or ' ' + rv += ', '.join('%s=%s' % (a, _format(getattr(node, a))) + for a in node._attributes) + return rv + ')' + elif isinstance(node, list): + return '[%s]' % ', '.join(_format(x) for x in node) + return repr(node) + if not isinstance(node, AST): + raise TypeError('expected AST, got %r' % node.__class__.__name__) + return _format(node) + + +def copy_location(new_node, old_node): + """ + Copy source location (`lineno` and `col_offset` attributes) from + *old_node* to *new_node* if possible, and return *new_node*. + """ + for attr in 'lineno', 'col_offset': + if attr in old_node._attributes and attr in new_node._attributes \ + and hasattr(old_node, attr): + setattr(new_node, attr, getattr(old_node, attr)) + return new_node + + +def fix_missing_locations(node): + """ + When you compile a node tree with compile(), the compiler expects lineno and + col_offset attributes for every node that supports them. This is rather + tedious to fill in for generated nodes, so this helper adds these attributes + recursively where not already set, by setting them to the values of the + parent node. It works recursively starting at *node*. + """ + def _fix(node, lineno, col_offset): + if 'lineno' in node._attributes: + if not hasattr(node, 'lineno'): + node.lineno = lineno + else: + lineno = node.lineno + if 'col_offset' in node._attributes: + if not hasattr(node, 'col_offset'): + node.col_offset = col_offset + else: + col_offset = node.col_offset + for child in iter_child_nodes(node): + _fix(child, lineno, col_offset) + _fix(node, 1, 0) + return node + +def add_col_end(node): + def _fix(node, next): + children = list(iter_child_nodes(node)) + for i, child in enumerate(children): + next_offset = children[i+1].col_offset if i < len(children) else next.col_offset + child.col_end = next_offset + + +def increment_lineno(node, n=1): + """ + Increment the line number of each node in the tree starting at *node* by *n*. + This is useful to "move code" to a different location in a file. + """ + if 'lineno' in node._attributes: + node.lineno = getattr(node, 'lineno', 0) + n + for child in walk(node): + if 'lineno' in child._attributes: + child.lineno = getattr(child, 'lineno', 0) + n + return node + + +def iter_fields(node): + """ + Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields`` + that is present on *node*. + """ + if node._fields is None: + return + + for field in node._fields: + try: + yield field, getattr(node, field) + except AttributeError: + pass + + +def iter_child_nodes(node): + """ + Yield all direct child nodes of *node*, that is, all fields that are nodes + and all items of fields that are lists of nodes. + """ + for name, field in iter_fields(node): + if isinstance(field, AST): + yield field + elif isinstance(field, list): + for item in field: + if isinstance(item, AST): + yield item + + +def get_docstring(node, clean=True): + """ + Return the docstring for the given node or None if no docstring can + be found. If the node provided does not have docstrings a TypeError + will be raised. + """ + if not isinstance(node, (FunctionDef, ClassDef, Module)): + raise TypeError("%r can't have docstrings" % node.__class__.__name__) + if node.body and isinstance(node.body[0], Expr) and \ + isinstance(node.body[0].value, Str): + if clean: + import inspect + return inspect.cleandoc(node.body[0].value.s) + return node.body[0].value.s + + +def walk(node): + """ + Recursively yield all child nodes of *node*, in no specified order. This is + useful if you only want to modify nodes in place and don't care about the + context. + """ + from collections import deque + todo = deque([node]) + while todo: + node = todo.popleft() + todo.extend(iter_child_nodes(node)) + yield node + + +class NodeVisitor(object): + """ + A node visitor base class that walks the abstract syntax tree and calls a + visitor function for every node found. This function may return a value + which is forwarded by the `visit` method. + + This class is meant to be subclassed, with the subclass adding visitor + methods. + + Per default the visitor functions for the nodes are ``'visit_'`` + + class name of the node. So a `TryFinally` node visit function would + be `visit_TryFinally`. This behavior can be changed by overriding + the `visit` method. If no visitor function exists for a node + (return value `None`) the `generic_visit` visitor is used instead. + + Don't use the `NodeVisitor` if you want to apply changes to nodes during + traversing. For this a special visitor exists (`NodeTransformer`) that + allows modifications. + """ + + def visit(self, node): + """Visit a node.""" + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + return visitor(node) + + def generic_visit(self, node): + """Called if no explicit visitor function exists for a node.""" + for field, value in iter_fields(node): + if isinstance(value, list): + for item in value: + if isinstance(item, AST): + self.visit(item) + elif isinstance(value, AST): + self.visit(value) + + +class NodeTransformer(NodeVisitor): + """ + A :class:`NodeVisitor` subclass that walks the abstract syntax tree and + allows modification of nodes. + + The `NodeTransformer` will walk the AST and use the return value of the + visitor methods to replace or remove the old node. If the return value of + the visitor method is ``None``, the node will be removed from its location, + otherwise it is replaced with the return value. The return value may be the + original node in which case no replacement takes place. + + Here is an example transformer that rewrites all occurrences of name lookups + (``foo``) to ``data['foo']``:: + + class RewriteName(NodeTransformer): + + def visit_Name(self, node): + return copy_location(Subscript( + value=Name(id='data', ctx=Load()), + slice=Index(value=Str(s=node.id)), + ctx=node.ctx + ), node) + + Keep in mind that if the node you're operating on has child nodes you must + either transform the child nodes yourself or call the :meth:`generic_visit` + method for the node first. + + For nodes that were part of a collection of statements (that applies to all + statement nodes), the visitor may also return a list of nodes rather than + just a single node. + + Usually you use the transformer like this:: + + node = YourTransformer().visit(node) + """ + + def generic_visit(self, node): + for field, old_value in iter_fields(node): + old_value = getattr(node, field, None) + if isinstance(old_value, list): + new_values = [] + for value in old_value: + if isinstance(value, AST): + value = self.visit(value) + if value is None: + continue + elif not isinstance(value, AST): + new_values.extend(value) + continue + new_values.append(value) + old_value[:] = new_values + elif isinstance(old_value, AST): + new_node = self.visit(old_value) + if new_node is None: + delattr(node, field) + else: + setattr(node, field, new_node) + return node diff --git a/ftplugin/python/pyflakes/pyflakes/ast.pyc b/ftplugin/python/pyflakes/pyflakes/ast.pyc new file mode 100644 index 0000000..d8a7bf0 Binary files /dev/null and b/ftplugin/python/pyflakes/pyflakes/ast.pyc differ diff --git a/ftplugin/python/pyflakes/pyflakes/checker.py b/ftplugin/python/pyflakes/pyflakes/checker.py new file mode 100644 index 0000000..2d933a0 --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/checker.py @@ -0,0 +1,389 @@ +import ast +from pyflakes import messages +import __builtin__ + + +allowed_before_future = (ast.Module, ast.ImportFrom, ast.Expr, ast.Str) +defined_names = set(('__file__', '__builtins__')) + +class Binding(object): + """ + @ivar used: pair of (L{Scope}, line-number) indicating the scope and + line number that this binding was last used + """ + def __init__(self, name, source): + self.name = name + self.source = source + self.used = False + + def __str__(self): + return self.name + + def __repr__(self): + return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__, + self.name, + self.source.lineno, + id(self)) + +class UnBinding(Binding): + '''Created by the 'del' operator.''' + +class Importation(Binding): + def __init__(self, name, source): + name = name.split('.')[0] + super(Importation, self).__init__(name, source) + +class Assignment(Binding): + pass + +class FunctionDefinition(Binding): + pass + + +class Scope(dict): + import_starred = False # set to True when import * is found + + def __repr__(self): + return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self)) + + def __init__(self): + super(Scope, self).__init__() + +class ClassScope(Scope): + pass + + + +class FunctionScope(Scope): + """ + I represent a name scope for a function. + + @ivar globals: Names declared 'global' in this function. + """ + def __init__(self): + super(FunctionScope, self).__init__() + self.globals = {} + + + +class ModuleScope(Scope): + pass + +class Checker(ast.NodeVisitor): + def __init__(self, tree, filename='(none)', builtins = None): + ast.NodeVisitor.__init__(self) + + self.deferred = [] + self.dead_scopes = [] + self.messages = [] + self.filename = filename + self.scope_stack = [ModuleScope()] + self.futures_allowed = True + self.builtins = frozenset(builtins or []) + + self.visit(tree) + for handler, scope in self.deferred: + self.scope_stack = scope + handler() + del self.scope_stack[1:] + self.pop_scope() + self.check_dead_scopes() + + def defer(self, callable): + '''Schedule something to be called after just before completion. + + This is used for handling function bodies, which must be deferred + because code later in the file might modify the global scope. When + `callable` is called, the scope at the time this is called will be + restored, however it will contain any new bindings added to it. + ''' + self.deferred.append( (callable, self.scope_stack[:]) ) + + def check_dead_scopes(self): + # Check for modules that were imported but unused + for scope in self.dead_scopes: + for importation in scope.itervalues(): + if isinstance(importation, Importation) and not importation.used: + self.report(messages.UnusedImport, importation.source.lineno, importation.name) + + def push_function_scope(self): + self.scope_stack.append(FunctionScope()) + + def push_class_scope(self): + self.scope_stack.append(ClassScope()) + + def pop_scope(self): + scope = self.scope_stack.pop() + self.dead_scopes.append(scope) + + @property + def scope(self): + return self.scope_stack[-1] + + def report(self, message_class, *args, **kwargs): + self.messages.append(message_class(self.filename, *args, **kwargs)) + + def visit_Import(self, node): + for name_node in node.names: + # "import bar as foo" -> name=bar, asname=foo + name = name_node.asname or name_node.name + self.add_binding(node, Importation(name, node)) + + def visit_GeneratorExp(self, node): + for generator in node.generators: + self.visit(generator.iter) + self.assign_vars(generator.target) + + for generator in node.generators: + if hasattr(node, 'elt'): + self.visit(node.elt) + + self.visit_nodes(generator.ifs) + + visit_ListComp = visit_GeneratorExp + + def visit_For(self, node): + ''' + Process bindings for loop variables. + ''' + self.visit_nodes(node.iter) + + for var in self.flatten(node.target): + upval = self.scope.get(var.id) + if isinstance(upval, Importation) and upval.used: + self.report(messages.ImportShadowedByLoopVar, + node.lineno, node.col_offset, var.id, upval.source.lineno) + + self.add_binding(var, Assignment(var.id, var)) + + self.visit_nodes(node.body + node.orelse) + + def visit_FunctionDef(self, node): + + try: + decorators = node.decorator_list + except AttributeError: + # Use .decorators for Python 2.5 compatibility + decorators = node.decorators + + self.visit_nodes(decorators) + self.add_binding(node, FunctionDefinition(node.name, node)) + self.visit_Lambda(node) + + def visit_Lambda(self, node): + self.visit_nodes(node.args.defaults) + + def run_function(): + self.push_function_scope() + + # Check for duplicate arguments + argnames = set() + for arg in self.flatten(node.args.args): + if arg.id in argnames: + self.report(messages.DuplicateArgument, arg.lineno, arg.col_offset, arg.id) + argnames.add(arg.id) + + self.assign_vars(node.args.args, report_redef=False) + if node.args.vararg is not None: + self.add_binding(node, Assignment(node.args.vararg, node), False) + if node.args.kwarg is not None: + self.add_binding(node, Assignment(node.args.kwarg, node), False) + self.visit_nodes(node.body) + self.pop_scope() + + self.defer(run_function) + + def visit_Name(self, node): + ''' + Locate names in locals / function / globals scopes. + ''' + scope, name = self.scope, node.id + + # try local scope + import_starred = scope.import_starred + try: + scope[name].used = (scope, node.lineno, node.col_offset) + except KeyError: + pass + else: + return + + # try enclosing function scopes + for func_scope in self.scope_stack[-2:0:-1]: + import_starred = import_starred or func_scope.import_starred + if not isinstance(func_scope, FunctionScope): + continue + try: + func_scope[name].used = (scope, node.lineno, node.col_offset) + except KeyError: + pass + else: + return + + # try global scope + import_starred = import_starred or self.scope_stack[0].import_starred + try: + self.scope_stack[0][node.id].used = (scope, node.lineno, node.col_offset) + except KeyError: + if not import_starred and not self.is_builtin(name): + self.report(messages.UndefinedName, node.lineno, node.col_offset, name) + + def assign_vars(self, targets, report_redef=True): + scope = self.scope + + for target in self.flatten(targets): + name = target.id + # if the name hasn't already been defined in the current scope + if isinstance(scope, FunctionScope) and name not in scope: + # for each function or module scope above us + for upscope in self.scope_stack[:-1]: + if not isinstance(upscope, (FunctionScope, ModuleScope)): + continue + + upval = upscope.get(name) + # if the name was defined in that scope, and the name has + # been accessed already in the current scope, and hasn't + # been declared global + if upval is not None: + if upval.used and upval.used[0] is scope and name not in scope.globals: + # then it's probably a mistake + self.report(messages.UndefinedLocal, + upval.used[1], upval.used[2], name, upval.source.lineno, upval.source.col_offset) + + self.add_binding(target, Assignment(name, target), report_redef) + + def visit_Assign(self, node): + for target in node.targets: + self.visit_nodes(node.value) + self.assign_vars(node.targets) + + def visit_Delete(self, node): + for target in self.flatten(node.targets): + if isinstance(self.scope, FunctionScope) and target.id in self.scope.globals: + del self.scope.globals[target.id] + else: + self.add_binding(target, UnBinding(target.id, target)) + + def visit_With(self, node): + self.visit(node.context_expr) + + # handle new bindings made by optional "as" part + if node.optional_vars is not None: + self.assign_vars(node.optional_vars) + + self.visit_nodes(node.body) + + def visit_ImportFrom(self, node): + if node.module == '__future__': + if not self.futures_allowed: + self.report(messages.LateFutureImport, node.lineno, node.col_offset, [alias.name for alias in node.names]) + else: + self.futures_allowed = False + + for alias in node.names: + if alias.name == '*': + self.scope.import_starred = True + self.report(messages.ImportStarUsed, node.lineno, node.col_offset, node.module) + continue + name = alias.asname or alias.name + importation = Importation(name, node) + if node.module == '__future__': + importation.used = (self.scope, node.lineno, node.col_offset) + self.add_binding(node, importation) + + def visit_Global(self, node): + ''' + Keep track of global declarations. + ''' + scope = self.scope + if isinstance(scope, FunctionScope): + scope.globals.update(dict.fromkeys(node.names)) + + def visit_ClassDef(self, node): + self.add_binding(node, Assignment(node.name, node)) + self.visit_nodes(node.bases) + + self.push_class_scope() + self.visit_nodes(node.body) + self.pop_scope() + + def visit_excepthandler(self, node): + if node.type is not None: + self.visit(node.type) + if node.name is not None: + self.assign_vars(node.name) + self.visit_nodes(node.body) + + visit_ExceptHandler = visit_excepthandler # in 2.6, this was CamelCased + + def flatten(self, nodes): + if isinstance(nodes, ast.Attribute): + self.visit(nodes) + return [] + elif isinstance(nodes, ast.Subscript): + self.visit(nodes.value) + self.visit(nodes.slice) + return [] + elif isinstance(nodes, ast.Name): + return [nodes] + elif isinstance(nodes, (ast.Tuple, ast.List)): + return self.flatten(nodes.elts) + + flattened_nodes = [] + for node in nodes: + if hasattr(node, 'elts'): + flattened_nodes += self.flatten(node.elts) + elif node is not None: + flattened_nodes += self.flatten(node) + + return flattened_nodes + + def add_binding(self, node, value, report_redef=True): + line, col, scope, name = node.lineno, node.col_offset, self.scope, value.name + + # Check for a redefined function + func = scope.get(name) + if (isinstance(func, FunctionDefinition) and isinstance(value, FunctionDefinition)): + self.report(messages.RedefinedFunction, line, name, func.source.lineno) + + # Check for redefining an unused import + if report_redef and not isinstance(scope, ClassScope): + for up_scope in self.scope_stack[::-1]: + upval = up_scope.get(name) + if isinstance(upval, Importation) and not upval.used: + self.report(messages.RedefinedWhileUnused, line, col, name, upval.source.lineno) + + # Check for "del undefined_name" + if isinstance(value, UnBinding): + try: + del scope[name] + except KeyError: + self.report(messages.UndefinedName, line, col, name) + else: + scope[name] = value + + def visit(self, node): + if not isinstance(node, allowed_before_future): + self.futures_allowed = False + + return super(Checker, self).visit(node) + + def visit_nodes(self, nodes): + try: + nodes = list(getattr(nodes, 'elts', nodes)) + except TypeError: + nodes = [nodes] + + for node in nodes: + self.visit(node) + + def is_builtin(self, name): + if hasattr(__builtin__, name): + return True + if name in defined_names: + return True + if name in self.builtins: + return True + + return False + diff --git a/ftplugin/python/pyflakes/pyflakes/checker.pyc b/ftplugin/python/pyflakes/pyflakes/checker.pyc new file mode 100644 index 0000000..47fb4e9 Binary files /dev/null and b/ftplugin/python/pyflakes/pyflakes/checker.pyc differ diff --git a/ftplugin/python/pyflakes/pyflakes/messages.py b/ftplugin/python/pyflakes/pyflakes/messages.py new file mode 100644 index 0000000..15a920e --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/messages.py @@ -0,0 +1,77 @@ +# (c) 2005 Divmod, Inc. See LICENSE file for details + +class Message(object): + message = '' + message_args = () + def __init__(self, filename, lineno, col = None): + self.filename = filename + self.lineno = lineno + self.col = col + def __str__(self): + if self.col is not None: + return '%s:%s(%d): %s' % (self.filename, self.lineno, self.col, self.message % self.message_args) + else: + return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args) + + +class UnusedImport(Message): + message = '%r imported but unused' + def __init__(self, filename, lineno, name): + Message.__init__(self, filename, lineno) + self.message_args = (name,) + + +class RedefinedWhileUnused(Message): + message = 'redefinition of unused %r from line %r' + def __init__(self, filename, lineno, col, name, orig_lineno): + Message.__init__(self, filename, lineno) + self.message_args = (name, orig_lineno) + + +class ImportShadowedByLoopVar(Message): + message = 'import %r from line %r shadowed by loop variable' + def __init__(self, filename, lineno, col, name, orig_lineno): + Message.__init__(self, filename, lineno, col) + self.message_args = (name, orig_lineno) + + +class ImportStarUsed(Message): + message = "'from %s import *' used; unable to detect undefined names" + def __init__(self, filename, lineno, col, modname): + Message.__init__(self, filename, lineno, col) + self.message_args = (modname,) + + +class UndefinedName(Message): + message = 'undefined name %r' + def __init__(self, filename, lineno, col, name): + Message.__init__(self, filename, lineno, col) + self.message_args = (name,) + + +class UndefinedLocal(Message): + message = "local variable %r (defined in enclosing scope on line %r) referenced before assignment" + def __init__(self, filename, lineno, col, name, orig_lineno, orig_col): + Message.__init__(self, filename, lineno) + self.message_args = (name, orig_lineno) + + +class DuplicateArgument(Message): + message = 'duplicate argument %r in function definition' + def __init__(self, filename, lineno, col, name): + Message.__init__(self, filename, lineno, col) + self.message_args = (name,) + + +class RedefinedFunction(Message): + message = 'redefinition of function %r from line %r' + def __init__(self, filename, lineno, name, orig_lineno): + Message.__init__(self, filename, lineno) + self.message_args = (name, orig_lineno) + + +class LateFutureImport(Message): + message = 'future import(s) %r after other statements' + def __init__(self, filename, lineno, col, names): + Message.__init__(self, filename, lineno) + self.message_args = (names,) diff --git a/ftplugin/python/pyflakes/pyflakes/messages.pyc b/ftplugin/python/pyflakes/pyflakes/messages.pyc new file mode 100644 index 0000000..746f6ae Binary files /dev/null and b/ftplugin/python/pyflakes/pyflakes/messages.pyc differ diff --git a/ftplugin/python/pyflakes/pyflakes/scripts/__init__.py b/ftplugin/python/pyflakes/pyflakes/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ftplugin/python/pyflakes/pyflakes/scripts/pyflakes.py b/ftplugin/python/pyflakes/pyflakes/scripts/pyflakes.py new file mode 100644 index 0000000..06937a7 --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/scripts/pyflakes.py @@ -0,0 +1,63 @@ + +""" +Implementation of the command-line I{pyflakes} tool. +""" + +import _ast +import sys +import os + +checker = __import__('pyflakes.checker').checker + +def check(codeString, filename): + try: + tree = compile(codeString, filename, 'exec', _ast.PyCF_ONLY_AST) + except (SyntaxError, IndentationError): + value = sys.exc_info()[1] + try: + (lineno, offset, line) = value[1][1:] + except IndexError: + print >> sys.stderr, 'could not compile %r' % (filename,) + return 1 + if line.endswith("\n"): + line = line[:-1] + print >> sys.stderr, '%s:%d: could not compile' % (filename, lineno) + print >> sys.stderr, line + print >> sys.stderr, " " * (offset-2), "^" + return 1 + else: + w = checker.Checker(tree, filename) + w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) + for warning in w.messages: + print warning + return len(w.messages) + + +def checkPath(filename): + """ + Check the given path, printing out any warnings detected. + + @return: the number of warnings printed + """ + if os.path.exists(filename): + return check(file(filename, 'U').read() + '\n', filename) + else: + print >> sys.stderr, '%s: no such file' % (filename,) + return 1 + +def main(): + warnings = 0 + args = sys.argv[1:] + if args: + for arg in args: + if os.path.isdir(arg): + for dirpath, dirnames, filenames in os.walk(arg): + for filename in filenames: + if filename.endswith('.py'): + warnings += checkPath(os.path.join(dirpath, filename)) + else: + warnings += checkPath(arg) + else: + warnings += check(sys.stdin.read(), '<stdin>') + + raise SystemExit(warnings > 0) diff --git a/ftplugin/python/pyflakes/pyflakes/test/__init__.py b/ftplugin/python/pyflakes/pyflakes/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ftplugin/python/pyflakes/pyflakes/test/harness.py b/ftplugin/python/pyflakes/pyflakes/test/harness.py new file mode 100644 index 0000000..765cda4 --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/test/harness.py @@ -0,0 +1,24 @@ + +import textwrap + +from twisted.trial import unittest + +from pyflakes import checker, ast + + +class Test(unittest.TestCase): + + def flakes(self, input, *expectedOutputs): + w = checker.Checker(ast.parse(textwrap.dedent(input))) + outputs = [type(o) for o in w.messages] + expectedOutputs = list(expectedOutputs) + outputs.sort() + expectedOutputs.sort() + self.assert_(outputs == expectedOutputs, '''\ +for input: +%s +expected outputs: +%s +but got: +%s''' % (input, repr(expectedOutputs), '\n'.join([str(o) for o in w.messages]))) + return w diff --git a/ftplugin/python/pyflakes/pyflakes/test/test_imports.py b/ftplugin/python/pyflakes/pyflakes/test/test_imports.py new file mode 100644 index 0000000..4f87f3e --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/test/test_imports.py @@ -0,0 +1,512 @@ + +from sys import version_info + +from pyflakes import messages as m +from pyflakes.test import harness + +class Test(harness.Test): + + def test_unusedImport(self): + self.flakes('import fu, bar', m.UnusedImport, m.UnusedImport) + self.flakes('from baz import fu, bar', m.UnusedImport, m.UnusedImport) + + def test_aliasedImport(self): + self.flakes('import fu as FU, bar as FU', m.RedefinedWhileUnused, m.UnusedImport) + self.flakes('from moo import fu as FU, bar as FU', m.RedefinedWhileUnused, m.UnusedImport) + + def test_usedImport(self): + self.flakes('import fu; print fu') + self.flakes('from baz import fu; print fu') + + def test_redefinedWhileUnused(self): + self.flakes('import fu; fu = 3', m.RedefinedWhileUnused) + self.flakes('import fu; del fu', m.RedefinedWhileUnused) + self.flakes('import fu; fu, bar = 3', m.RedefinedWhileUnused) + self.flakes('import fu; [fu, bar] = 3', m.RedefinedWhileUnused) + + def test_redefinedByFunction(self): + self.flakes(''' + import fu + def fu(): + pass + ''', m.RedefinedWhileUnused) + + def test_redefinedInNestedFunction(self): + """ + Test that shadowing a global name with a nested function definition + generates a warning. + """ + self.flakes(''' + import fu + def bar(): + def baz(): + def fu(): + pass + ''', m.RedefinedWhileUnused, m.UnusedImport) + + def test_redefinedByClass(self): + self.flakes(''' + import fu + class fu: + pass + ''', m.RedefinedWhileUnused) + + def test_redefinedInClass(self): + """ + Test that shadowing a global with a class attribute does not produce a + warning. + """ + self.flakes(''' + import fu + class bar: + fu = 1 + print fu + ''') + + def test_usedInFunction(self): + self.flakes(''' + import fu + def fun(): + print fu + ''') + + def test_shadowedByParameter(self): + self.flakes(''' + import fu + def fun(fu): + print fu + ''', m.UnusedImport) + + self.flakes(''' + import fu + def fun(fu): + print fu + print fu + ''') + + def test_newAssignment(self): + self.flakes('fu = None') + + def test_usedInGetattr(self): + self.flakes('import fu; fu.bar.baz') + self.flakes('import fu; "bar".fu.baz', m.UnusedImport) + + def test_usedInSlice(self): + self.flakes('import fu; print fu.bar[1:]') + + def test_usedInIfBody(self): + self.flakes(''' + import fu + if True: print fu + ''') + + def test_usedInIfConditional(self): + self.flakes(''' + import fu + if fu: pass + ''') + + def test_usedInElifConditional(self): + self.flakes(''' + import fu + if False: pass + elif fu: pass + ''') + + def test_usedInElse(self): + self.flakes(''' + import fu + if False: pass + else: print fu + ''') + + def test_usedInCall(self): + self.flakes('import fu; fu.bar()') + + def test_usedInClass(self): + self.flakes(''' + import fu + class bar: + bar = fu + ''') + + def test_usedInClassBase(self): + self.flakes(''' + import fu + class bar(object, fu.baz): + pass + ''') + + def test_notUsedInNestedScope(self): + self.flakes(''' + import fu + def bleh(): + pass + print fu + ''') + + def test_usedInFor(self): + self.flakes(''' + import fu + for bar in range(9): + print fu + ''') + + def test_usedInForElse(self): + self.flakes(''' + import fu + for bar in range(10): + pass + else: + print fu + ''') + + def test_redefinedByFor(self): + self.flakes(''' + import fu + for fu in range(2): + pass + ''', m.RedefinedWhileUnused) + + def test_shadowedByFor(self): + """ + Test that shadowing a global name with a for loop variable generates a + warning. + """ + self.flakes(''' + import fu + fu.bar() + for fu in (): + pass + ''', m.ImportShadowedByLoopVar) + + def test_shadowedByForDeep(self): + """ + Test that shadowing a global name with a for loop variable nested in a + tuple unpack generates a warning. + """ + self.flakes(''' + import fu + fu.bar() + for (x, y, z, (a, b, c, (fu,))) in (): + pass + ''', m.ImportShadowedByLoopVar) + + def test_usedInReturn(self): + self.flakes(''' + import fu + def fun(): + return fu + ''') + + def test_usedInOperators(self): + self.flakes('import fu; 3 + fu.bar') + self.flakes('import fu; 3 % fu.bar') + self.flakes('import fu; 3 - fu.bar') + self.flakes('import fu; 3 * fu.bar') + self.flakes('import fu; 3 ** fu.bar') + self.flakes('import fu; 3 / fu.bar') + self.flakes('import fu; 3 // fu.bar') + self.flakes('import fu; -fu.bar') + self.flakes('import fu; ~fu.bar') + self.flakes('import fu; 1 == fu.bar') + self.flakes('import fu; 1 | fu.bar') + self.flakes('import fu; 1 & fu.bar') + self.flakes('import fu; 1 ^ fu.bar') + self.flakes('import fu; 1 >> fu.bar') + self.flakes('import fu; 1 << fu.bar') + + def test_usedInAssert(self): + self.flakes('import fu; assert fu.bar') + + def test_usedInSubscript(self): + self.flakes('import fu; fu.bar[1]') + + def test_usedInLogic(self): + self.flakes('import fu; fu and False') + self.flakes('import fu; fu or False') + self.flakes('import fu; not fu.bar') + + def test_usedInList(self): + self.flakes('import fu; [fu]') + + def test_usedInTuple(self): + self.flakes('import fu; (fu,)') + + def test_usedInTry(self): + self.flakes(''' + import fu + try: fu + except: pass + ''') + + def test_usedInExcept(self): + self.flakes(''' + import fu + try: fu + except: pass + ''') + + def test_redefinedByExcept(self): + self.flakes(''' + import fu + try: pass + except Exception, fu: pass + ''', m.RedefinedWhileUnused) + + def test_usedInRaise(self): + self.flakes(''' + import fu + raise fu.bar + ''') + + def test_usedInYield(self): + self.flakes(''' + import fu + def gen(): + yield fu + ''') + + def test_usedInDict(self): + self.flakes('import fu; {fu:None}') + self.flakes('import fu; {1:fu}') + + def test_usedInParameterDefault(self): + self.flakes(''' + import fu + def f(bar=fu): + pass + ''') + + def test_usedInAttributeAssign(self): + self.flakes('import fu; fu.bar = 1') + + def test_usedInKeywordArg(self): + self.flakes('import fu; fu.bar(stuff=fu)') + + def test_usedInAssignment(self): + self.flakes('import fu; bar=fu') + self.flakes('import fu; n=0; n+=fu') + + def test_usedInListComp(self): + self.flakes('import fu; [fu for _ in range(1)]') + self.flakes('import fu; [1 for _ in range(1) if fu]') + + def test_redefinedByListComp(self): + self.flakes('import fu; [1 for fu in range(1)]', m.RedefinedWhileUnused) + + + def test_usedInTryFinally(self): + self.flakes(''' + import fu + try: pass + finally: fu + ''') + + self.flakes(''' + import fu + try: fu + finally: pass + ''') + + def test_usedInWhile(self): + self.flakes(''' + import fu + while 0: + fu + ''') + + self.flakes(''' + import fu + while fu: pass + ''') + + def test_usedInGlobal(self): + self.flakes(''' + import fu + def f(): global fu + ''', m.UnusedImport) + + def test_usedInBackquote(self): + self.flakes('import fu; `fu`') + + def test_usedInExec(self): + self.flakes('import fu; exec "print 1" in fu.bar') + + def test_usedInLambda(self): + self.flakes('import fu; lambda: fu') + + def test_shadowedByLambda(self): + self.flakes('import fu; lambda fu: fu', m.UnusedImport) + + def test_usedInSliceObj(self): + self.flakes('import fu; "meow"[::fu]') + + def test_unusedInNestedScope(self): + self.flakes(''' + def bar(): + import fu + fu + ''', m.UnusedImport, m.UndefinedName) + + def test_methodsDontUseClassScope(self): + self.flakes(''' + class bar: + import fu + def fun(self): + fu + ''', m.UnusedImport, m.UndefinedName) + + def test_nestedFunctionsNestScope(self): + self.flakes(''' + def a(): + def b(): + fu + import fu + ''') + + def test_nestedClassAndFunctionScope(self): + self.flakes(''' + def a(): + import fu + class b: + def c(self): + print fu + ''') + + def test_importStar(self): + self.flakes('from fu import *', m.ImportStarUsed) + + def test_packageImport(self): + self.flakes('import fu.bar; fu.bar') + test_packageImport.todo = "this has been hacked to treat 'import fu.bar' as just 'import fu'" + + def test_assignRHSFirst(self): + self.flakes('import fu; fu = fu') + self.flakes('import fu; fu, bar = fu') + self.flakes('import fu; [fu, bar] = fu') + self.flakes('import fu; fu += fu') + + def test_tryingMultipleImports(self): + self.flakes(''' + try: + import fu + except ImportError: + import bar as fu + ''') + test_tryingMultipleImports.todo = '' + + def test_nonGlobalDoesNotRedefine(self): + self.flakes(''' + import fu + def a(): + fu = 3 + fu + ''') + + def test_functionsRunLater(self): + self.flakes(''' + def a(): + fu + import fu + ''') + + def test_functionNamesAreBoundNow(self): + self.flakes(''' + import fu + def fu(): + fu + fu + ''', m.RedefinedWhileUnused) + + def test_ignoreNonImportRedefinitions(self): + self.flakes('a = 1; a = 2') + + def test_importingForImportError(self): + self.flakes(''' + try: + import fu + except ImportError: + pass + ''') + test_importingForImportError.todo = '' + + def test_explicitlyPublic(self): + '''imports mentioned in __all__ are not unused''' + self.flakes('import fu; __all__ = ["fu"]') + test_explicitlyPublic.todo = "this would require importing the module or doing smarter parsing" + + def test_importedInClass(self): + '''Imports in class scope can be used through self''' + self.flakes(''' + class c: + import i + def __init__(self): + self.i + ''') + test_importedInClass.todo = 'requires evaluating attribute access' + + def test_futureImport(self): + '''__future__ is special''' + self.flakes('from __future__ import division') + + def test_futureImportFirst(self): + """ + __future__ imports must come before anything else. + """ + self.flakes(''' + x = 5 + from __future__ import division + ''', m.LateFutureImport) + + + +class Python24Tests(harness.Test): + """ + Tests for checking of syntax which is valid in Python 2.4 and newer. + """ + if version_info < (2, 4): + skip = "Python 2.4 required for generator expression and decorator tests." + + + def test_usedInGenExp(self): + """ + Using a global in a generator expression results in no warnings. + """ + self.flakes('import fu; (fu for _ in range(1))') + self.flakes('import fu; (1 for _ in range(1) if fu)') + + + def test_redefinedByGenExp(self): + """ + Re-using a global name as the loop variable for a generator + expression results in a redefinition warning. + """ + self.flakes('import fu; (1 for fu in range(1))', m.RedefinedWhileUnused) + + + def test_usedAsDecorator(self): + """ + Using a global name in a decorator statement results in no warnings, + but using an undefined name in a decorator statement results in an + undefined name warning. + """ + self.flakes(''' + from interior import decorate + @decorate + def f(): + return "hello" + ''') + + self.flakes(''' + from interior import decorate + @decorate('value') + def f(): + return "hello" + ''') + + self.flakes(''' + @decorate + def f(): + return "hello" + ''', m.UndefinedName) diff --git a/ftplugin/python/pyflakes/pyflakes/test/test_other.py b/ftplugin/python/pyflakes/pyflakes/test/test_other.py new file mode 100644 index 0000000..26a306c --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/test/test_other.py @@ -0,0 +1,234 @@ +# (c) 2005-2008 Divmod, Inc. +# See LICENSE file for details + +""" +Tests for various Pyflakes behavior. +""" + +from sys import version_info + +from pyflakes import messages as m +from pyflakes.test import harness + + +class Test(harness.Test): + + def test_duplicateArgs(self): + self.flakes('def fu(bar, bar): pass', m.DuplicateArgument) + + def test_localReferencedBeforeAssignment(self): + self.flakes(''' + a = 1 + def f(): + a; a=1 + f() + ''', m.UndefinedName) + test_localReferencedBeforeAssignment.todo = 'this requires finding all assignments in the function body first' + + def test_redefinedFunction(self): + """ + Test that shadowing a function definition with another one raises a + warning. + """ + self.flakes(''' + def a(): pass + def a(): pass + ''', m.RedefinedFunction) + + def test_redefinedClassFunction(self): + """ + Test that shadowing a function definition in a class suite with another + one raises a warning. + """ + self.flakes(''' + class A: + def a(): pass + def a(): pass + ''', m.RedefinedFunction) + + def test_functionDecorator(self): + """ + Test that shadowing a function definition with a decorated version of + that function does not raise a warning. + """ + self.flakes(''' + from somewhere import somedecorator + + def a(): pass + a = somedecorator(a) + ''') + + def test_classFunctionDecorator(self): + """ + Test that shadowing a function definition in a class suite with a + decorated version of that function does not raise a warning. + """ + self.flakes(''' + class A: + def a(): pass + a = classmethod(a) + ''') + + def test_unaryPlus(self): + '''Don't die on unary +''' + self.flakes('+1') + + + +class Python25Test(harness.Test): + """ + Tests for checking of syntax only available in Python 2.5 and newer. + """ + if version_info < (2, 5): + skip = "Python 2.5 required for if-else and with tests" + + def test_ifexp(self): + """ + Test C{foo if bar else baz} statements. + """ + self.flakes("a = 'moo' if True else 'oink'") + self.flakes("a = foo if True else 'oink'", m.UndefinedName) + self.flakes("a = 'moo' if True else bar", m.UndefinedName) + + + def test_withStatementNoNames(self): + """ + No warnings are emitted for using inside or after a nameless C{with} + statement a name defined beforehand. + """ + self.flakes(''' + from __future__ import with_statement + bar = None + with open("foo"): + bar + bar + ''') + + def test_withStatementSingleName(self): + """ + No warnings are emitted for using a name defined by a C{with} statement + within the suite or afterwards. + """ + self.flakes(''' + from __future__ import with_statement + with open('foo') as bar: + bar + bar + ''') + + + def test_withStatementTupleNames(self): + """ + No warnings are emitted for using any of the tuple of names defined by + a C{with} statement within the suite or afterwards. + """ + self.flakes(''' + from __future__ import with_statement + with open('foo') as (bar, baz): + bar, baz + bar, baz + ''') + + + def test_withStatementSingleNameUndefined(self): + """ + An undefined name warning is emitted if the name first defined by a + C{with} statement is used before the C{with} statement. + """ + self.flakes(''' + from __future__ import with_statement + bar + with open('foo') as bar: + pass + ''', m.UndefinedName) + + + def test_withStatementTupleNamesUndefined(self): + """ + An undefined name warning is emitted if a name first defined by a the + tuple-unpacking form of the C{with} statement is used before the + C{with} statement. + """ + self.flakes(''' + from __future__ import with_statement + baz + with open('foo') as (bar, baz): + pass + ''', m.UndefinedName) + + + def test_withStatementSingleNameRedefined(self): + """ + A redefined name warning is emitted if a name bound by an import is + rebound by the name defined by a C{with} statement. + """ + self.flakes(''' + from __future__ import with_statement + import bar + with open('foo') as bar: + pass + ''', m.RedefinedWhileUnused) + + + def test_withStatementTupleNamesRedefined(self): + """ + A redefined name warning is emitted if a name bound by an import is + rebound by one of the names defined by the tuple-unpacking form of a + C{with} statement. + """ + self.flakes(''' + from __future__ import with_statement + import bar + with open('foo') as (bar, baz): + pass + ''', m.RedefinedWhileUnused) + + + def test_withStatementUndefinedInside(self): + """ + An undefined name warning is emitted if a name is used inside the + body of a C{with} statement without first being bound. + """ + self.flakes(''' + from __future__ import with_statement + with open('foo') as bar: + baz + ''', m.UndefinedName) + + + def test_withStatementNameDefinedInBody(self): + """ + A name defined in the body of a C{with} statement can be used after + the body ends without warning. + """ + self.flakes(''' + from __future__ import with_statement + with open('foo') as bar: + baz = 10 + baz + ''') + + + def test_withStatementUndefinedInExpression(self): + """ + An undefined name warning is emitted if a name in the I{test} + expression of a C{with} statement is undefined. + """ + self.flakes(''' + from __future__ import with_statement + with bar as baz: + pass + ''', m.UndefinedName) + + self.flakes(''' + from __future__ import with_statement + with bar as bar: + pass + ''', m.UndefinedName) + + def test_listNestedListComprehension(self): + self.flakes(''' + root = [['213', '123'], ['4354']] + foo = [int(c) for group in root for c in group] + ''') + diff --git a/ftplugin/python/pyflakes/pyflakes/test/test_script.py b/ftplugin/python/pyflakes/pyflakes/test/test_script.py new file mode 100644 index 0000000..b6fb685 --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/test/test_script.py @@ -0,0 +1,48 @@ + +""" +Tests for L{pyflakes.scripts.pyflakes}. +""" + +import sys +from StringIO import StringIO + +from twisted.python.filepath import FilePath +from twisted.trial.unittest import TestCase + +from pyflakes.scripts.pyflakes import checkPath + +def withStderrTo(stderr, f): + """ + Call C{f} with C{sys.stderr} redirected to C{stderr}. + """ + (outer, sys.stderr) = (sys.stderr, stderr) + try: + return f() + finally: + sys.stderr = outer + + + +class CheckTests(TestCase): + """ + Tests for L{check} and L{checkPath} which check a file for flakes. + """ + def test_missingTrailingNewline(self): + """ + Source which doesn't end with a newline shouldn't cause any + exception to be raised nor an error indicator to be returned by + L{check}. + """ + fName = self.mktemp() + FilePath(fName).setContent("def foo():\n\tpass\n\t") + self.assertFalse(checkPath(fName)) + + + def test_checkPathNonExisting(self): + """ + L{checkPath} handles non-existing files. + """ + err = StringIO() + count = withStderrTo(err, lambda: checkPath('extremo')) + self.assertEquals(err.getvalue(), 'extremo: no such file\n') + self.assertEquals(count, 1) diff --git a/ftplugin/python/pyflakes/pyflakes/test/test_undefined_names.py b/ftplugin/python/pyflakes/pyflakes/test/test_undefined_names.py new file mode 100644 index 0000000..57e4e3c --- /dev/null +++ b/ftplugin/python/pyflakes/pyflakes/test/test_undefined_names.py @@ -0,0 +1,182 @@ + +from sys import version_info + +from pyflakes import messages as m +from pyflakes.test import harness + + +class Test(harness.Test): + def test_undefined(self): + self.flakes('bar', m.UndefinedName) + + def test_definedInListComp(self): + self.flakes('[a for a in range(10) if a]') + + + def test_functionsNeedGlobalScope(self): + self.flakes(''' + class a: + def b(): + fu + fu = 1 + ''') + + def test_builtins(self): + self.flakes('range(10)') + + def test_magic_globals(self): + self.flakes('__file__') + + def test_globalImportStar(self): + '''Can't find undefined names with import *''' + self.flakes('from fu import *; bar', m.ImportStarUsed) + + def test_localImportStar(self): + '''A local import * still allows undefined names to be found in upper scopes''' + self.flakes(''' + def a(): + from fu import * + bar + ''', m.ImportStarUsed, m.UndefinedName) + + def test_unpackedParameter(self): + '''Unpacked function parameters create bindings''' + self.flakes(''' + def a((bar, baz)): + bar; baz + ''') + + def test_definedByGlobal(self): + '''"global" can make an otherwise undefined name in another function defined''' + self.flakes(''' + def a(): global fu; fu = 1 + def b(): fu + ''') + test_definedByGlobal.todo = '' + + def test_del(self): + '''del deletes bindings''' + self.flakes('a = 1; del a; a', m.UndefinedName) + + def test_delGlobal(self): + '''del a global binding from a function''' + self.flakes(''' + a = 1 + def f(): + global a + del a + a + ''') + + def test_delUndefined(self): + '''del an undefined name''' + self.flakes('del a', m.UndefinedName) + + def test_globalFromNestedScope(self): + '''global names are available from nested scopes''' + self.flakes(''' + a = 1 + def b(): + def c(): + a + ''') + + def test_laterRedefinedGlobalFromNestedScope(self): + """ + Test that referencing a local name that shadows a global, before it is + defined, generates a warning. + """ + self.flakes(''' + a = 1 + def fun(): + a + a = 2 + ''', m.UndefinedLocal) + + def test_laterRedefinedGlobalFromNestedScope2(self): + """ + Test that referencing a local name in a nested scope that shadows a + global declared in an enclosing scope, before it is defined, generates + a warning. + """ + self.flakes(''' + a = 1 + def fun(): + global a + def fun2(): + a + a = 2 + ''', m.UndefinedLocal) + + + def test_doubleNestingReportsClosestName(self): + """ + Test that referencing a local name in a nested scope that shadows a + variable declared in two different outer scopes before it is defined + in the innermost scope generates an UnboundLocal warning which + refers to the nearest shadowed name. + """ + exc = self.flakes(''' + def a(): + x = 1 + def b(): + x = 2 # line 5 + def c(): + x + x = 3 + ''', m.UndefinedLocal).messages[0] + self.assertEqual(exc.message_args, ('x', 5)) + + + def test_laterRedefinedGlobalFromNestedScope3(self): + """ + Test that referencing a local name in a nested scope that shadows a + global, before it is defined, generates a warning. + """ + self.flakes(''' + def fun(): + a = 1 + def fun2(): + a + a = 1 + ''', m.UndefinedLocal) + + def test_nestedClass(self): + '''nested classes can access enclosing scope''' + self.flakes(''' + def f(foo): + class C: + bar = foo + def f(self): + return foo + return C() + + f(123).f() + ''') + + def test_badNestedClass(self): + '''free variables in nested classes must bind at class creation''' + self.flakes(''' + def f(): + class C: + bar = foo + foo = 456 + + f() + ''', m.UndefinedName) + + + +class Python24Test(harness.Test): + """ + Tests for checking of syntax which is valid in Python 2.4 and newer. + """ + if version_info < (2, 4): + skip = "Python 2.4 required for generator expression tests." + + def test_definedInGenExp(self): + """ + Using the loop variable of a generator expression results in no + warnings. + """ + self.flakes('(a for a in xrange(10) if a)') diff --git a/ftplugin/python/pyflakes/setup.py b/ftplugin/python/pyflakes/setup.py new file mode 100644 index 0000000..d875a9e --- /dev/null +++ b/ftplugin/python/pyflakes/setup.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# (c) 2005 Divmod, Inc. See LICENSE file for details + +from distutils.core import setup + +setup( + name="pyflakes", + license="MIT", + version="0.2.1", + description="passive checker of Python programs", + author="Phil Frost", + maintainer="Moe Aboulkheir", + maintainer_email="moe@divmod.com", + url="http://www.divmod.org/projects/pyflakes", + packages=["pyflakes", "pyflakes.scripts"], + scripts=["bin/pyflakes"], + long_description="""Pyflakes is program to analyze Python programs and detect various errors. It +works by parsing the source file, not importing it, so it is safe to use on +modules with side effects. It's also much faster.""") diff --git a/ftplugin/python/python_fn.vim b/ftplugin/python/python_fn.vim new file mode 100644 index 0000000..7c7cf21 --- /dev/null +++ b/ftplugin/python/python_fn.vim @@ -0,0 +1,446 @@ +" -*- vim -*- +" FILE: python_fn.vim +" LAST MODIFICATION: 2008-08-28 8:19pm +" (C) Copyright 2001-2005 Mikael Berthe <bmikael@lists.lilotux.net> +" Maintained by Jon Franklin <jvfranklin@gmail.com> +" Version: 1.13 + +" USAGE: +" +" Save this file to $VIMFILES/ftplugin/python.vim. You can have multiple +" python ftplugins by creating $VIMFILES/ftplugin/python and saving your +" ftplugins in that directory. If saving this to the global ftplugin +" directory, this is the recommended method, since vim ships with an +" ftplugin/python.vim file already. +" You can set the global variable "g:py_select_leading_comments" to 0 +" if you don't want to select comments preceding a declaration (these +" are usually the description of the function/class). +" You can set the global variable "g:py_select_trailing_comments" to 0 +" if you don't want to select comments at the end of a function/class. +" If these variables are not defined, both leading and trailing comments +" are selected. +" Example: (in your .vimrc) "let g:py_select_leading_comments = 0" +" You may want to take a look at the 'shiftwidth' option for the +" shift commands... +" +" REQUIREMENTS: +" vim (>= 7) +" +" Shortcuts: +" ]t -- Jump to beginning of block +" ]e -- Jump to end of block +" ]v -- Select (Visual Line Mode) block +" ]< -- Shift block to left +" ]> -- Shift block to right +" ]# -- Comment selection +" ]u -- Uncomment selection +" ]c -- Select current/previous class +" ]d -- Select current/previous function +" ]<up> -- Jump to previous line with the same/lower indentation +" ]<down> -- Jump to next line with the same/lower indentation + +" Only do this when not done yet for this buffer +if exists("b:loaded_py_ftplugin") + finish +endif +let b:loaded_py_ftplugin = 1 + +map ]t :PBoB<CR> +vmap ]t :<C-U>PBOB<CR>m'gv`` +map ]e :PEoB<CR> +vmap ]e :<C-U>PEoB<CR>m'gv`` + +map ]v ]tV]e +map ]< ]tV]e< +vmap ]< < +map ]> ]tV]e> +vmap ]> > + +map ]# :call PythonCommentSelection()<CR> +vmap ]# :call PythonCommentSelection()<CR> +map ]u :call PythonUncommentSelection()<CR> +vmap ]u :call PythonUncommentSelection()<CR> + +map ]c :call PythonSelectObject("class")<CR> +map ]d :call PythonSelectObject("function")<CR> + +map ]<up> :call PythonNextLine(-1)<CR> +map ]<down> :call PythonNextLine(1)<CR> +" You may prefer use <s-up> and <s-down>... :-) + +" jump to previous class +map ]J :call PythonDec("class", -1)<CR> +vmap ]J :call PythonDec("class", -1)<CR> + +" jump to next class +map ]j :call PythonDec("class", 1)<CR> +vmap ]j :call PythonDec("class", 1)<CR> + +" jump to previous function +map ]F :call PythonDec("function", -1)<CR> +vmap ]F :call PythonDec("function", -1)<CR> + +" jump to next function +map ]f :call PythonDec("function", 1)<CR> +vmap ]f :call PythonDec("function", 1)<CR> + + + +" Menu entries +nmenu <silent> &Python.Update\ IM-Python\ Menu + \:call UpdateMenu()<CR> +nmenu &Python.-Sep1- : +nmenu <silent> &Python.Beginning\ of\ Block<Tab>[t + \]t +nmenu <silent> &Python.End\ of\ Block<Tab>]e + \]e +nmenu &Python.-Sep2- : +nmenu <silent> &Python.Shift\ Block\ Left<Tab>]< + \]< +vmenu <silent> &Python.Shift\ Block\ Left<Tab>]< + \]< +nmenu <silent> &Python.Shift\ Block\ Right<Tab>]> + \]> +vmenu <silent> &Python.Shift\ Block\ Right<Tab>]> + \]> +nmenu &Python.-Sep3- : +vmenu <silent> &Python.Comment\ Selection<Tab>]# + \]# +nmenu <silent> &Python.Comment\ Selection<Tab>]# + \]# +vmenu <silent> &Python.Uncomment\ Selection<Tab>]u + \]u +nmenu <silent> &Python.Uncomment\ Selection<Tab>]u + \]u +nmenu &Python.-Sep4- : +nmenu <silent> &Python.Previous\ Class<Tab>]J + \]J +nmenu <silent> &Python.Next\ Class<Tab>]j + \]j +nmenu <silent> &Python.Previous\ Function<Tab>]F + \]F +nmenu <silent> &Python.Next\ Function<Tab>]f + \]f +nmenu &Python.-Sep5- : +nmenu <silent> &Python.Select\ Block<Tab>]v + \]v +nmenu <silent> &Python.Select\ Function<Tab>]d + \]d +nmenu <silent> &Python.Select\ Class<Tab>]c + \]c +nmenu &Python.-Sep6- : +nmenu <silent> &Python.Previous\ Line\ wrt\ indent<Tab>]<up> + \]<up> +nmenu <silent> &Python.Next\ Line\ wrt\ indent<Tab>]<down> + \]<down> + +:com! PBoB execute "normal ".PythonBoB(line('.'), -1, 1)."G" +:com! PEoB execute "normal ".PythonBoB(line('.'), 1, 1)."G" +:com! UpdateMenu call UpdateMenu() + + +" Go to a block boundary (-1: previous, 1: next) +" If force_sel_comments is true, 'g:py_select_trailing_comments' is ignored +function! PythonBoB(line, direction, force_sel_comments) + let ln = a:line + let ind = indent(ln) + let mark = ln + let indent_valid = strlen(getline(ln)) + let ln = ln + a:direction + if (a:direction == 1) && (!a:force_sel_comments) && + \ exists("g:py_select_trailing_comments") && + \ (!g:py_select_trailing_comments) + let sel_comments = 0 + else + let sel_comments = 1 + endif + + while((ln >= 1) && (ln <= line('$'))) + if (sel_comments) || (match(getline(ln), "^\\s*#") == -1) + if (!indent_valid) + let indent_valid = strlen(getline(ln)) + let ind = indent(ln) + let mark = ln + else + if (strlen(getline(ln))) + if (indent(ln) < ind) + break + endif + let mark = ln + endif + endif + endif + let ln = ln + a:direction + endwhile + + return mark +endfunction + + +" Go to previous (-1) or next (1) class/function definition +function! PythonDec(obj, direction) + if (a:obj == "class") + let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+" + \ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:" + else + let objregexp = "^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:" + endif + let flag = "W" + if (a:direction == -1) + let flag = flag."b" + endif + let res = search(objregexp, flag) +endfunction + + +" Comment out selected lines +" commentString is inserted in non-empty lines, and should be aligned with +" the block +function! PythonCommentSelection() range + let commentString = "#" + let cl = a:firstline + let ind = 1000 " I hope nobody use so long lines! :) + + " Look for smallest indent + while (cl <= a:lastline) + if strlen(getline(cl)) + let cind = indent(cl) + let ind = ((ind < cind) ? ind : cind) + endif + let cl = cl + 1 + endwhile + if (ind == 1000) + let ind = 1 + else + let ind = ind + 1 + endif + + let cl = a:firstline + execute ":".cl + " Insert commentString in each non-empty line, in column ind + while (cl <= a:lastline) + if strlen(getline(cl)) + execute "normal ".ind."|i".commentString + endif + execute "normal \<Down>" + let cl = cl + 1 + endwhile +endfunction + +" Uncomment selected lines +function! PythonUncommentSelection() range + " commentString could be different than the one from CommentSelection() + " For example, this could be "# \\=" + let commentString = "#" + let cl = a:firstline + while (cl <= a:lastline) + let ul = substitute(getline(cl), + \"\\(\\s*\\)".commentString."\\(.*\\)$", "\\1\\2", "") + call setline(cl, ul) + let cl = cl + 1 + endwhile +endfunction + + +" Select an object ("class"/"function") +function! PythonSelectObject(obj) + " Go to the object declaration + normal $ + call PythonDec(a:obj, -1) + let beg = line('.') + + if !exists("g:py_select_leading_comments") || (g:py_select_leading_comments) + let decind = indent(beg) + let cl = beg + while (cl>1) + let cl = cl - 1 + if (indent(cl) == decind) && (getline(cl)[decind] == "#") + let beg = cl + else + break + endif + endwhile + endif + + if (a:obj == "class") + let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*" + \ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:" + else + let eod = "\\(^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*\\)\\@<=:" + endif + " Look for the end of the declaration (not always the same line!) + call search(eod, "") + + " Is it a one-line definition? + if match(getline('.'), "^\\s*\\(#.*\\)\\=$", col('.')) == -1 + let cl = line('.') + execute ":".beg + execute "normal V".cl."G" + else + " Select the whole block + execute "normal \<Down>" + let cl = line('.') + execute ":".beg + execute "normal V".PythonBoB(cl, 1, 0)."G" + endif +endfunction + + +" Jump to the next line with the same (or lower) indentation +" Useful for moving between "if" and "else", for example. +function! PythonNextLine(direction) + let ln = line('.') + let ind = indent(ln) + let indent_valid = strlen(getline(ln)) + let ln = ln + a:direction + + while((ln >= 1) && (ln <= line('$'))) + if (!indent_valid) && strlen(getline(ln)) + break + else + if (strlen(getline(ln))) + if (indent(ln) <= ind) + break + endif + endif + endif + let ln = ln + a:direction + endwhile + + execute "normal ".ln."G" +endfunction + +function! UpdateMenu() + " delete menu if it already exists, then rebuild it. + " this is necessary in case you've got multiple buffers open + " a future enhancement to this would be to make the menu aware of + " all buffers currently open, and group classes and functions by buffer + if exists("g:menuran") + aunmenu IM-Python + endif + let restore_fe = &foldenable + set nofoldenable + " preserve disposition of window and cursor + let cline=line('.') + let ccol=col('.') - 1 + norm H + let hline=line('.') + " create the menu + call MenuBuilder() + " restore disposition of window and cursor + exe "norm ".hline."Gzt" + let dnscroll=cline-hline + exe "norm ".dnscroll."j".ccol."l" + let &foldenable = restore_fe +endfunction + +function! MenuBuilder() + norm gg0 + let currentclass = -1 + let classlist = [] + let parentclass = "" + while line(".") < line("$") + " search for a class or function + if match ( getline("."), '^\s*class\s\+[_a-zA-Z].*\|^\s*def\s\+[_a-zA-Z].*' ) != -1 + norm ^ + let linenum = line('.') + let indentcol = col('.') + norm "nye + let classordef=@n + norm w"nywge + let objname=@n + let parentclass = FindParentClass(classlist, indentcol) + if classordef == "class" + call AddClass(objname, linenum, parentclass) + else " this is a function + call AddFunction(objname, linenum, parentclass) + endif + " We actually created a menu, so lets set the global variable + let g:menuran=1 + call RebuildClassList(classlist, [objname, indentcol], classordef) + endif " line matched + norm j + endwhile +endfunction + +" classlist contains the list of nested classes we are in. +" in most cases it will be empty or contain a single class +" but where a class is nested within another, it will contain 2 or more +" this function adds or removes classes from the list based on indentation +function! RebuildClassList(classlist, newclass, classordef) + let i = len(a:classlist) - 1 + while i > -1 + if a:newclass[1] <= a:classlist[i][1] + call remove(a:classlist, i) + endif + let i = i - 1 + endwhile + if a:classordef == "class" + call add(a:classlist, a:newclass) + endif +endfunction + +" we found a class or function, determine its parent class based on +" indentation and what's contained in classlist +function! FindParentClass(classlist, indentcol) + let i = 0 + let parentclass = "" + while i < len(a:classlist) + if a:indentcol <= a:classlist[i][1] + break + else + if len(parentclass) == 0 + let parentclass = a:classlist[i][0] + else + let parentclass = parentclass.'\.'.a:classlist[i][0] + endif + endif + let i = i + 1 + endwhile + return parentclass +endfunction + +" add a class to the menu +function! AddClass(classname, lineno, parentclass) + if len(a:parentclass) > 0 + let classstring = a:parentclass.'\.'.a:classname + else + let classstring = a:classname + endif + exe 'menu IM-Python.classes.'.classstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>' +endfunction + +" add a function to the menu, grouped by member class +function! AddFunction(functionname, lineno, parentclass) + if len(a:parentclass) > 0 + let funcstring = a:parentclass.'.'.a:functionname + else + let funcstring = a:functionname + endif + exe 'menu IM-Python.functions.'.funcstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>' +endfunction + + +function! s:JumpToAndUnfold(line) + " Go to the right line + execute 'normal '.a:line.'gg' + " Check to see if we are in a fold + let lvl = foldlevel(a:line) + if lvl != 0 + " and if so, then expand the fold out, other wise, ignore this part. + execute 'normal 15zo' + endif +endfunction + +"" This one will work only on vim 6.2 because of the try/catch expressions. +" function! s:JumpToAndUnfoldWithExceptions(line) +" try +" execute 'normal '.a:line.'gg15zo' +" catch /^Vim\((\a\+)\)\=:E490:/ +" " Do nothing, just consume the error +" endtry +"endfunction + + +" vim:set et sts=2 sw=2: + diff --git a/ftplugin/python/pythoncomplete.vim b/ftplugin/python/pythoncomplete.vim new file mode 100644 index 0000000..57add71 --- /dev/null +++ b/ftplugin/python/pythoncomplete.vim @@ -0,0 +1,625 @@ +"pythoncomplete.vim - Omni Completion for python +" Maintainer: Aaron Griffin <aaronmgriffin@gmail.com> +" Version: 0.9 +" Last Updated: 18 Jun 2009 +" +" Changes +" TODO: +" 'info' item output can use some formatting work +" Add an "unsafe eval" mode, to allow for return type evaluation +" Complete basic syntax along with import statements +" i.e. "import url<c-x,c-o>" +" Continue parsing on invalid line?? +" +" v 0.9 +" * Fixed docstring parsing for classes and functions +" * Fixed parsing of *args and **kwargs type arguments +" * Better function param parsing to handle things like tuples and +" lambda defaults args +" +" v 0.8 +" * Fixed an issue where the FIRST assignment was always used instead of +" using a subsequent assignment for a variable +" * Fixed a scoping issue when working inside a parameterless function +" +" +" v 0.7 +" * Fixed function list sorting (_ and __ at the bottom) +" * Removed newline removal from docs. It appears vim handles these better in +" recent patches +" +" v 0.6: +" * Fixed argument completion +" * Removed the 'kind' completions, as they are better indicated +" with real syntax +" * Added tuple assignment parsing (whoops, that was forgotten) +" * Fixed import handling when flattening scope +" +" v 0.5: +" Yeah, I skipped a version number - 0.4 was never public. +" It was a bugfix version on top of 0.3. This is a complete +" rewrite. +" + +if !has('python') + echo "Error: Required vim compiled with +python" + finish +endif + +function! pythoncomplete#Complete(findstart, base) + "findstart = 1 when we need to get the text length + if a:findstart == 1 + let line = getline('.') + let idx = col('.') + while idx > 0 + let idx -= 1 + let c = line[idx] + if c =~ '\w' + continue + elseif ! c =~ '\.' + let idx = -1 + break + else + break + endif + endwhile + + return idx + "findstart = 0 when we need to return the list of completions + else + "vim no longer moves the cursor upon completion... fix that + let line = getline('.') + let idx = col('.') + let cword = '' + while idx > 0 + let idx -= 1 + let c = line[idx] + if c =~ '\w' || c =~ '\.' + let cword = c . cword + continue + elseif strlen(cword) > 0 || idx == 0 + break + endif + endwhile + execute "python vimcomplete('" . cword . "', '" . a:base . "')" + return g:pythoncomplete_completions + endif +endfunction + +function! s:DefPython() +python << PYTHONEOF +import sys, tokenize, cStringIO, types +from token import NAME, DEDENT, NEWLINE, STRING + +debugstmts=[] +def dbg(s): debugstmts.append(s) +def showdbg(): + for d in debugstmts: print "DBG: %s " % d + +def vimcomplete(context,match): + global debugstmts + debugstmts = [] + try: + import vim + def complsort(x,y): + try: + xa = x['abbr'] + ya = y['abbr'] + if xa[0] == '_': + if xa[1] == '_' and ya[0:2] == '__': + return xa > ya + elif ya[0:2] == '__': + return -1 + elif y[0] == '_': + return xa > ya + else: + return 1 + elif ya[0] == '_': + return -1 + else: + return xa > ya + except: + return 0 + cmpl = Completer() + cmpl.evalsource('\n'.join(vim.current.buffer),vim.eval("line('.')")) + all = cmpl.get_completions(context,match) + all.sort(complsort) + dictstr = '[' + # have to do this for double quoting + for cmpl in all: + dictstr += '{' + for x in cmpl: dictstr += '"%s":"%s",' % (x,cmpl[x]) + dictstr += '"icase":0},' + if dictstr[-1] == ',': dictstr = dictstr[:-1] + dictstr += ']' + #dbg("dict: %s" % dictstr) + vim.command("silent let g:pythoncomplete_completions = %s" % dictstr) + #dbg("Completion dict:\n%s" % all) + except vim.error: + dbg("VIM Error: %s" % vim.error) + +class Completer(object): + def __init__(self): + self.compldict = {} + self.parser = PyParser() + + def evalsource(self,text,line=0): + sc = self.parser.parse(text,line) + src = sc.get_code() + dbg("source: %s" % src) + try: exec(src) in self.compldict + except: dbg("parser: %s, %s" % (sys.exc_info()[0],sys.exc_info()[1])) + for l in sc.locals: + try: exec(l) in self.compldict + except: dbg("locals: %s, %s [%s]" % (sys.exc_info()[0],sys.exc_info()[1],l)) + + def _cleanstr(self,doc): + return doc.replace('"',' ').replace("'",' ') + + def get_arguments(self,func_obj): + def _ctor(obj): + try: return class_ob.__init__.im_func + except AttributeError: + for base in class_ob.__bases__: + rc = _find_constructor(base) + if rc is not None: return rc + return None + + arg_offset = 1 + if type(func_obj) == types.ClassType: func_obj = _ctor(func_obj) + elif type(func_obj) == types.MethodType: func_obj = func_obj.im_func + else: arg_offset = 0 + + arg_text='' + if type(func_obj) in [types.FunctionType, types.LambdaType]: + try: + cd = func_obj.func_code + real_args = cd.co_varnames[arg_offset:cd.co_argcount] + defaults = func_obj.func_defaults or '' + defaults = map(lambda name: "=%s" % name, defaults) + defaults = [""] * (len(real_args)-len(defaults)) + defaults + items = map(lambda a,d: a+d, real_args, defaults) + if func_obj.func_code.co_flags & 0x4: + items.append("...") + if func_obj.func_code.co_flags & 0x8: + items.append("***") + arg_text = (','.join(items)) + ')' + + except: + dbg("arg completion: %s: %s" % (sys.exc_info()[0],sys.exc_info()[1])) + pass + if len(arg_text) == 0: + # The doc string sometimes contains the function signature + # this works for alot of C modules that are part of the + # standard library + doc = func_obj.__doc__ + if doc: + doc = doc.lstrip() + pos = doc.find('\n') + if pos > 0: + sigline = doc[:pos] + lidx = sigline.find('(') + ridx = sigline.find(')') + if lidx > 0 and ridx > 0: + arg_text = sigline[lidx+1:ridx] + ')' + if len(arg_text) == 0: arg_text = ')' + return arg_text + + def get_completions(self,context,match): + dbg("get_completions('%s','%s')" % (context,match)) + stmt = '' + if context: stmt += str(context) + if match: stmt += str(match) + try: + result = None + all = {} + ridx = stmt.rfind('.') + if len(stmt) > 0 and stmt[-1] == '(': + result = eval(_sanitize(stmt[:-1]), self.compldict) + doc = result.__doc__ + if doc is None: doc = '' + args = self.get_arguments(result) + return [{'word':self._cleanstr(args),'info':self._cleanstr(doc)}] + elif ridx == -1: + match = stmt + all = self.compldict + else: + match = stmt[ridx+1:] + stmt = _sanitize(stmt[:ridx]) + result = eval(stmt, self.compldict) + all = dir(result) + + dbg("completing: stmt:%s" % stmt) + completions = [] + + try: maindoc = result.__doc__ + except: maindoc = ' ' + if maindoc is None: maindoc = ' ' + for m in all: + if m == "_PyCmplNoType": continue #this is internal + try: + dbg('possible completion: %s' % m) + if m.find(match) == 0: + if result is None: inst = all[m] + else: inst = getattr(result,m) + try: doc = inst.__doc__ + except: doc = maindoc + typestr = str(inst) + if doc is None or doc == '': doc = maindoc + + wrd = m[len(match):] + c = {'word':wrd, 'abbr':m, 'info':self._cleanstr(doc)} + if "function" in typestr: + c['word'] += '(' + c['abbr'] += '(' + self._cleanstr(self.get_arguments(inst)) + elif "method" in typestr: + c['word'] += '(' + c['abbr'] += '(' + self._cleanstr(self.get_arguments(inst)) + elif "module" in typestr: + c['word'] += '.' + elif "class" in typestr: + c['word'] += '(' + c['abbr'] += '(' + completions.append(c) + except: + i = sys.exc_info() + dbg("inner completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt)) + return completions + except: + i = sys.exc_info() + dbg("completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt)) + return [] + +class Scope(object): + def __init__(self,name,indent,docstr=''): + self.subscopes = [] + self.docstr = docstr + self.locals = [] + self.parent = None + self.name = name + self.indent = indent + + def add(self,sub): + #print 'push scope: [%s@%s]' % (sub.name,sub.indent) + sub.parent = self + self.subscopes.append(sub) + return sub + + def doc(self,str): + """ Clean up a docstring """ + d = str.replace('\n',' ') + d = d.replace('\t',' ') + while d.find(' ') > -1: d = d.replace(' ',' ') + while d[0] in '"\'\t ': d = d[1:] + while d[-1] in '"\'\t ': d = d[:-1] + dbg("Scope(%s)::docstr = %s" % (self,d)) + self.docstr = d + + def local(self,loc): + self._checkexisting(loc) + self.locals.append(loc) + + def copy_decl(self,indent=0): + """ Copy a scope's declaration only, at the specified indent level - not local variables """ + return Scope(self.name,indent,self.docstr) + + def _checkexisting(self,test): + "Convienance function... keep out duplicates" + if test.find('=') > -1: + var = test.split('=')[0].strip() + for l in self.locals: + if l.find('=') > -1 and var == l.split('=')[0].strip(): + self.locals.remove(l) + + def get_code(self): + str = "" + if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n' + for l in self.locals: + if l.startswith('import'): str += l+'\n' + str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n' + for sub in self.subscopes: + str += sub.get_code() + for l in self.locals: + if not l.startswith('import'): str += l+'\n' + + return str + + def pop(self,indent): + #print 'pop scope: [%s] to [%s]' % (self.indent,indent) + outer = self + while outer.parent != None and outer.indent >= indent: + outer = outer.parent + return outer + + def currentindent(self): + #print 'parse current indent: %s' % self.indent + return ' '*self.indent + + def childindent(self): + #print 'parse child indent: [%s]' % (self.indent+1) + return ' '*(self.indent+1) + +class Class(Scope): + def __init__(self, name, supers, indent, docstr=''): + Scope.__init__(self,name,indent, docstr) + self.supers = supers + def copy_decl(self,indent=0): + c = Class(self.name,self.supers,indent, self.docstr) + for s in self.subscopes: + c.add(s.copy_decl(indent+1)) + return c + def get_code(self): + str = '%sclass %s' % (self.currentindent(),self.name) + if len(self.supers) > 0: str += '(%s)' % ','.join(self.supers) + str += ':\n' + if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n' + if len(self.subscopes) > 0: + for s in self.subscopes: str += s.get_code() + else: + str += '%spass\n' % self.childindent() + return str + + +class Function(Scope): + def __init__(self, name, params, indent, docstr=''): + Scope.__init__(self,name,indent, docstr) + self.params = params + def copy_decl(self,indent=0): + return Function(self.name,self.params,indent, self.docstr) + def get_code(self): + str = "%sdef %s(%s):\n" % \ + (self.currentindent(),self.name,','.join(self.params)) + if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n' + str += "%spass\n" % self.childindent() + return str + +class PyParser: + def __init__(self): + self.top = Scope('global',0) + self.scope = self.top + + def _parsedotname(self,pre=None): + #returns (dottedname, nexttoken) + name = [] + if pre is None: + tokentype, token, indent = self.next() + if tokentype != NAME and token != '*': + return ('', token) + else: token = pre + name.append(token) + while True: + tokentype, token, indent = self.next() + if token != '.': break + tokentype, token, indent = self.next() + if tokentype != NAME: break + name.append(token) + return (".".join(name), token) + + def _parseimportlist(self): + imports = [] + while True: + name, token = self._parsedotname() + if not name: break + name2 = '' + if token == 'as': name2, token = self._parsedotname() + imports.append((name, name2)) + while token != "," and "\n" not in token: + tokentype, token, indent = self.next() + if token != ",": break + return imports + + def _parenparse(self): + name = '' + names = [] + level = 1 + while True: + tokentype, token, indent = self.next() + if token in (')', ',') and level == 1: + if '=' not in name: name = name.replace(' ', '') + names.append(name.strip()) + name = '' + if token == '(': + level += 1 + name += "(" + elif token == ')': + level -= 1 + if level == 0: break + else: name += ")" + elif token == ',' and level == 1: + pass + else: + name += "%s " % str(token) + return names + + def _parsefunction(self,indent): + self.scope=self.scope.pop(indent) + tokentype, fname, ind = self.next() + if tokentype != NAME: return None + + tokentype, open, ind = self.next() + if open != '(': return None + params=self._parenparse() + + tokentype, colon, ind = self.next() + if colon != ':': return None + + return Function(fname,params,indent) + + def _parseclass(self,indent): + self.scope=self.scope.pop(indent) + tokentype, cname, ind = self.next() + if tokentype != NAME: return None + + super = [] + tokentype, next, ind = self.next() + if next == '(': + super=self._parenparse() + elif next != ':': return None + + return Class(cname,super,indent) + + def _parseassignment(self): + assign='' + tokentype, token, indent = self.next() + if tokentype == tokenize.STRING or token == 'str': + return '""' + elif token == '(' or token == 'tuple': + return '()' + elif token == '[' or token == 'list': + return '[]' + elif token == '{' or token == 'dict': + return '{}' + elif tokentype == tokenize.NUMBER: + return '0' + elif token == 'open' or token == 'file': + return 'file' + elif token == 'None': + return '_PyCmplNoType()' + elif token == 'type': + return 'type(_PyCmplNoType)' #only for method resolution + else: + assign += token + level = 0 + while True: + tokentype, token, indent = self.next() + if token in ('(','{','['): + level += 1 + elif token in (']','}',')'): + level -= 1 + if level == 0: break + elif level == 0: + if token in (';','\n'): break + assign += token + return "%s" % assign + + def next(self): + type, token, (lineno, indent), end, self.parserline = self.gen.next() + if lineno == self.curline: + #print 'line found [%s] scope=%s' % (line.replace('\n',''),self.scope.name) + self.currentscope = self.scope + return (type, token, indent) + + def _adjustvisibility(self): + newscope = Scope('result',0) + scp = self.currentscope + while scp != None: + if type(scp) == Function: + slice = 0 + #Handle 'self' params + if scp.parent != None and type(scp.parent) == Class: + slice = 1 + newscope.local('%s = %s' % (scp.params[0],scp.parent.name)) + for p in scp.params[slice:]: + i = p.find('=') + if len(p) == 0: continue + pvar = '' + ptype = '' + if i == -1: + pvar = p + ptype = '_PyCmplNoType()' + else: + pvar = p[:i] + ptype = _sanitize(p[i+1:]) + if pvar.startswith('**'): + pvar = pvar[2:] + ptype = '{}' + elif pvar.startswith('*'): + pvar = pvar[1:] + ptype = '[]' + + newscope.local('%s = %s' % (pvar,ptype)) + + for s in scp.subscopes: + ns = s.copy_decl(0) + newscope.add(ns) + for l in scp.locals: newscope.local(l) + scp = scp.parent + + self.currentscope = newscope + return self.currentscope + + #p.parse(vim.current.buffer[:],vim.eval("line('.')")) + def parse(self,text,curline=0): + self.curline = int(curline) + buf = cStringIO.StringIO(''.join(text) + '\n') + self.gen = tokenize.generate_tokens(buf.readline) + self.currentscope = self.scope + + try: + freshscope=True + while True: + tokentype, token, indent = self.next() + #dbg( 'main: token=[%s] indent=[%s]' % (token,indent)) + + if tokentype == DEDENT or token == "pass": + self.scope = self.scope.pop(indent) + elif token == 'def': + func = self._parsefunction(indent) + if func is None: + print "function: syntax error..." + continue + dbg("new scope: function") + freshscope = True + self.scope = self.scope.add(func) + elif token == 'class': + cls = self._parseclass(indent) + if cls is None: + print "class: syntax error..." + continue + freshscope = True + dbg("new scope: class") + self.scope = self.scope.add(cls) + + elif token == 'import': + imports = self._parseimportlist() + for mod, alias in imports: + loc = "import %s" % mod + if len(alias) > 0: loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + elif token == 'from': + mod, token = self._parsedotname() + if not mod or token != "import": + print "from: syntax error..." + continue + names = self._parseimportlist() + for name, alias in names: + loc = "from %s import %s" % (mod,name) + if len(alias) > 0: loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + elif tokentype == STRING: + if freshscope: self.scope.doc(token) + elif tokentype == NAME: + name,token = self._parsedotname(token) + if token == '=': + stmt = self._parseassignment() + dbg("parseassignment: %s = %s" % (name, stmt)) + if stmt != None: + self.scope.local("%s = %s" % (name,stmt)) + freshscope = False + except StopIteration: #thrown on EOF + pass + except: + dbg("parse error: %s, %s @ %s" % + (sys.exc_info()[0], sys.exc_info()[1], self.parserline)) + return self._adjustvisibility() + +def _sanitize(str): + val = '' + level = 0 + for c in str: + if c in ('(','{','['): + level += 1 + elif c in (']','}',')'): + level -= 1 + elif level == 0: + val += c + return val + +sys.path.extend(['.','..']) +PYTHONEOF +endfunction + +call s:DefPython() +" vim: set et ts=4: diff --git a/ftplugin/rst/word_utils.vim b/ftplugin/rst/word_utils.vim new file mode 100644 index 0000000..9ef4f50 --- /dev/null +++ b/ftplugin/rst/word_utils.vim @@ -0,0 +1,29 @@ +function! WordFrequency() range + let all = split(join(getline(a:firstline, a:lastline)), '\k\+') + let frequencies = {} + for word in all + let frequencies[word] = get(frequencies, word, 0) + 1 + endfor + new + setlocal buftype=nofile bufhidden=hide noswapfile tabstop=4 + for [key,value] in items(frequencies) + call append('$', value."\t".key) + endfor + sort i +endfunction +command! -range=% WordFrequency <line1>,<line2>call WordFrequency() + +function! CreateDict() range + let all = split(join(getline(a:firstline, a:lastline)), '[^A-Za-zęóąśłżźćńĘÓĄŚÅŻŹĆŃ]\+') + let frequencies = {} + for word in all + let frequencies[word] = get(frequencies, word, 0) + 1 + endfor + new + setlocal buftype=nofile bufhidden=hide noswapfile + for [key,value] in items(frequencies) + call append('$', key) + endfor + sort i +endfunction +command! -range=% CreateDict <line1>,<line2>call CreateDict() diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim new file mode 100644 index 0000000..edda29f --- /dev/null +++ b/ftplugin/vimwiki.vim @@ -0,0 +1,322 @@ +" Vimwiki filetype plugin file +" Author: Maxim Kim <habamax@gmail.com> +" Home: http://code.google.com/p/vimwiki/ + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 " Don't load another plugin for this buffer + +" UNDO list {{{ +" Reset the following options to undo this plugin. +let b:undo_ftplugin = "setlocal ". + \ "suffixesadd< isfname< comments< ". + \ "autowriteall< ". + \ "formatoptions< foldtext< ". + \ "foldmethod< foldexpr< commentstring< " +" UNDO }}} + +" MISC STUFF {{{ + +setlocal autowriteall +setlocal commentstring=<!--%s--> +" MISC }}} + +" GOTO FILE: gf {{{ +execute 'setlocal suffixesadd='.VimwikiGet('ext') +setlocal isfname-=[,] +" gf}}} + +" Autocreate list items {{{ +" for list items, and list items with checkboxes +if VimwikiGet('syntax') == 'default' + setl comments=b:*,b:#,b:- + setl formatlistpat=^\\s*[*#-]\\s* +else + setl comments=n:*,n:# +endif +setlocal formatoptions=tnro + +inoremap <buffer> <expr> <CR> vimwiki_lst#insertCR() +nnoremap <buffer> o :call vimwiki_lst#insertOo('o')<CR>a +nnoremap <buffer> O :call vimwiki_lst#insertOo('O')<CR>a + +" COMMENTS }}} + +" FOLDING for headers and list items using expr fold method. {{{ +if g:vimwiki_folding == 1 + setlocal fdm=expr + setlocal foldexpr=VimwikiFoldLevel(v:lnum) + setlocal foldtext=VimwikiFoldText() +endif + +function! VimwikiFoldLevel(lnum) "{{{ + let line = getline(a:lnum) + + " Header folding... + if line =~ g:vimwiki_rxHeader + let n = vimwiki#count_first_sym(line) + return '>'.n + endif + + if g:vimwiki_fold_trailing_empty_lines == 0 + if line =~ '^\s*$' + let nnline = getline(nextnonblank(a:lnum + 1)) + if nnline =~ g:vimwiki_rxHeader + let n = vimwiki#count_first_sym(nnline) + return '<'.n + endif + endif + endif + + " List item folding... + if g:vimwiki_fold_lists + let base_level = s:get_base_level(a:lnum) + + let rx_list_item = '\('. + \ g:vimwiki_rxListBullet.'\|'.g:vimwiki_rxListNumber. + \ '\)' + + + if line =~ rx_list_item + let [nnum, nline] = s:find_forward(rx_list_item, a:lnum) + let level = s:get_li_level(a:lnum) + let leveln = s:get_li_level(nnum) + let adj = s:get_li_level(s:get_start_list(rx_list_item, a:lnum)) + + if leveln > level + return ">".(base_level+leveln-adj) + else + return (base_level+level-adj) + endif + else + " process multilined list items + let [pnum, pline] = s:find_backward(rx_list_item, a:lnum) + if pline =~ rx_list_item + if indent(a:lnum) > indent(pnum) + let level = s:get_li_level(pnum) + let adj = s:get_li_level(s:get_start_list(rx_list_item, pnum)) + + let [nnum, nline] = s:find_forward(rx_list_item, a:lnum) + if nline =~ rx_list_item + let leveln = s:get_li_level(nnum) + if leveln > level + return (base_level+leveln-adj) + endif + endif + + return (base_level+level-adj) + endif + endif + endif + + return base_level + endif + + return -1 +endfunction "}}} + +function! s:get_base_level(lnum) "{{{ + let lnum = a:lnum - 1 + while lnum > 0 + if getline(lnum) =~ g:vimwiki_rxHeader + return vimwiki#count_first_sym(getline(lnum)) + endif + let lnum -= 1 + endwhile + return 0 +endfunction "}}} + +function! s:find_forward(rx_item, lnum) "{{{ + let lnum = a:lnum + 1 + + while lnum <= line('$') + let line = getline(lnum) + if line =~ a:rx_item + \ || line =~ '^\S' + \ || line =~ g:vimwiki_rxHeader + break + endif + let lnum += 1 + endwhile + + return [lnum, getline(lnum)] +endfunction "}}} + +function! s:find_backward(rx_item, lnum) "{{{ + let lnum = a:lnum - 1 + + while lnum > 1 + let line = getline(lnum) + if line =~ a:rx_item + \ || line =~ '^\S' + break + endif + let lnum -= 1 + endwhile + + return [lnum, getline(lnum)] +endfunction "}}} + +function! s:get_li_level(lnum) "{{{ + if VimwikiGet('syntax') == 'media' + let level = vimwiki#count_first_sym(getline(a:lnum)) + else + let level = (indent(a:lnum) / &sw) + endif + return level +endfunction "}}} + +function! s:get_start_list(rx_item, lnum) "{{{ + let lnum = a:lnum + while lnum >= 1 + let line = getline(lnum) + if line !~ a:rx_item && line =~ '^\S' + return nextnonblank(lnum + 1) + endif + let lnum -= 1 + endwhile + return 0 +endfunction "}}} + +function! VimwikiFoldText() "{{{ + let line = substitute(getline(v:foldstart), '\t', + \ repeat(' ', &tabstop), 'g') + return line.' ['.(v:foldend - v:foldstart).']' +endfunction "}}} + +" FOLDING }}} + +" COMMANDS {{{ +command! -buffer Vimwiki2HTML + \ call vimwiki_html#Wiki2HTML(expand(VimwikiGet('path_html')), + \ expand('%')) +command! -buffer VimwikiAll2HTML + \ call vimwiki_html#WikiAll2HTML(expand(VimwikiGet('path_html'))) + +command! -buffer VimwikiNextWord call vimwiki#WikiNextWord() +command! -buffer VimwikiPrevWord call vimwiki#WikiPrevWord() +command! -buffer VimwikiDeleteWord call vimwiki#WikiDeleteWord() +command! -buffer VimwikiRenameWord call vimwiki#WikiRenameWord() +command! -buffer VimwikiFollowWord call vimwiki#WikiFollowWord('nosplit') +command! -buffer VimwikiGoBackWord call vimwiki#WikiGoBackWord() +command! -buffer VimwikiSplitWord call vimwiki#WikiFollowWord('split') +command! -buffer VimwikiVSplitWord call vimwiki#WikiFollowWord('vsplit') + +command! -buffer -range VimwikiToggleListItem call vimwiki_lst#ToggleListItem(<line1>, <line2>) + +exe 'command! -buffer -nargs=* VimwikiSearch vimgrep <args> '. + \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') + +exe 'command! -buffer -nargs=* VWS vimgrep <args> '. + \ escape(VimwikiGet('path').'**/*'.VimwikiGet('ext'), ' ') + +" table commands +command! -buffer -nargs=* VimwikiTable call vimwiki_tbl#create(<f-args>) +command! -buffer VimwikiTableAlignQ call vimwiki_tbl#align_or_cmd('gqq') +command! -buffer VimwikiTableAlignW call vimwiki_tbl#align_or_cmd('gww') + +" COMMANDS }}} + +" KEYBINDINGS {{{ +if g:vimwiki_use_mouse + nmap <buffer> <S-LeftMouse> <NOP> + nmap <buffer> <C-LeftMouse> <NOP> + noremap <silent><buffer> <2-LeftMouse> :VimwikiFollowWord<CR> + noremap <silent><buffer> <S-2-LeftMouse> <LeftMouse>:VimwikiSplitWord<CR> + noremap <silent><buffer> <C-2-LeftMouse> <LeftMouse>:VimwikiVSplitWord<CR> + noremap <silent><buffer> <RightMouse><LeftMouse> :VimwikiGoBackWord<CR> +endif + +if !hasmapto('<Plug>VimwikiFollowWord') + nmap <silent><buffer> <CR> <Plug>VimwikiFollowWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiFollowWord :VimwikiFollowWord<CR> + +if !hasmapto('<Plug>VimwikiSplitWord') + nmap <silent><buffer> <S-CR> <Plug>VimwikiSplitWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiSplitWord :VimwikiSplitWord<CR> + +if !hasmapto('<Plug>VimwikiVSplitWord') + nmap <silent><buffer> <C-CR> <Plug>VimwikiVSplitWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiVSplitWord :VimwikiVSplitWord<CR> + +if !hasmapto('<Plug>VimwikiGoBackWord') + nmap <silent><buffer> <BS> <Plug>VimwikiGoBackWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiGoBackWord :VimwikiGoBackWord<CR> + +if !hasmapto('<Plug>VimwikiNextWord') + nmap <silent><buffer> <TAB> <Plug>VimwikiNextWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiNextWord :VimwikiNextWord<CR> + +if !hasmapto('<Plug>VimwikiPrevWord') + nmap <silent><buffer> <S-TAB> <Plug>VimwikiPrevWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiPrevWord :VimwikiPrevWord<CR> + +if !hasmapto('<Plug>VimwikiDeleteWord') + nmap <silent><buffer> <Leader>wd <Plug>VimwikiDeleteWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiDeleteWord :VimwikiDeleteWord<CR> + +if !hasmapto('<Plug>VimwikiRenameWord') + nmap <silent><buffer> <Leader>wr <Plug>VimwikiRenameWord +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiRenameWord :VimwikiRenameWord<CR> + +if !hasmapto('<Plug>VimwikiToggleListItem') + nmap <silent><buffer> <C-Space> <Plug>VimwikiToggleListItem + vmap <silent><buffer> <C-Space> <Plug>VimwikiToggleListItem + if has("unix") + nmap <silent><buffer> <C-@> <Plug>VimwikiToggleListItem + endif +endif +noremap <silent><script><buffer> + \ <Plug>VimwikiToggleListItem :VimwikiToggleListItem<CR> + + +" Table mappings +if g:vimwiki_table_auto_fmt + inoremap <expr> <buffer> <CR> vimwiki_tbl#kbd_cr() + inoremap <expr> <buffer> <Tab> vimwiki_tbl#kbd_tab() +endif + +nnoremap <buffer> gqq :VimwikiTableAlignQ<CR> +nnoremap <buffer> gww :VimwikiTableAlignW<CR> + + +" Text objects {{{ +omap <silent><buffer> ah :<C-U>call vimwiki#TO_header(0, 0)<CR> +vmap <silent><buffer> ah :<C-U>call vimwiki#TO_header(0, 1)<CR> + +omap <silent><buffer> ih :<C-U>call vimwiki#TO_header(1, 0)<CR> +vmap <silent><buffer> ih :<C-U>call vimwiki#TO_header(1, 1)<CR> + +nmap <silent><buffer> = :call vimwiki#AddHeaderLevel()<CR> +nmap <silent><buffer> - :call vimwiki#RemoveHeaderLevel()<CR> + +" }}} + +" KEYBINDINGS }}} + +" AUTOCOMMANDS {{{ +if VimwikiGet('auto_export') + " Automatically generate HTML on page write. + augroup vimwiki + au BufWritePost <buffer> Vimwiki2HTML + augroup END +endif + +" AUTOCOMMANDS }}} diff --git a/indent/javascript.vim b/indent/javascript.vim new file mode 100644 index 0000000..2b4afc7 --- /dev/null +++ b/indent/javascript.vim @@ -0,0 +1,83 @@ +" Vim indent file +" Language: JavaScript +" Author: Ryan (ryanthe) Fabella <ryanthe at gmail dot com> +" URL: - +" Last Change: 2007 september 25 + +if exists('b:did_indent') + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetJsIndent() +setlocal indentkeys=0{,0},0),:,!^F,o,O,e,*<Return>,=*/ +" Clean CR when the file is in Unix format +if &fileformat == "unix" + silent! %s/\r$//g +endif +" Only define the functions once per Vim session. +if exists("*GetJsIndent") + finish +endif +function! GetJsIndent() + let pnum = prevnonblank(v:lnum - 1) + if pnum == 0 + return 0 + endif + let line = getline(v:lnum) + let pline = getline(pnum) + let ind = indent(pnum) + + if pline =~ '{\s*$\|[\s*$\|(\s*$' + let ind = ind + &sw + endif + + if pline =~ ';\s*$' && line =~ '^\s*}' + let ind = ind - &sw + endif + + if pline =~ '\s*]\s*$' && line =~ '^\s*),\s*$' + let ind = ind - &sw + endif + + if pline =~ '\s*]\s*$' && line =~ '^\s*}\s*$' + let ind = ind - &sw + endif + + if line =~ '^\s*});\s*$\|^\s*);\s*$' && pline !~ ';\s*$' + let ind = ind - &sw + endif + + if line =~ '^\s*})' && pline =~ '\s*,\s*$' + let ind = ind - &sw + endif + + if line =~ '^\s*}();\s*$' && pline =~ '^\s*}\s*$' + let ind = ind - &sw + endif + + if line =~ '^\s*}),\s*$' + let ind = ind - &sw + endif + + if pline =~ '^\s*}\s*$' && line =~ '),\s*$' + let ind = ind - &sw + endif + + if pline =~ '^\s*for\s*' && line =~ ')\s*$' + let ind = ind + &sw + endif + + if line =~ '^\s*}\s*$\|^\s*]\s*$\|\s*},\|\s*]);\s*\|\s*}]\s*$\|\s*};\s*$\|\s*})$\|\s*}).el$' && pline !~ '\s*;\s*$\|\s*]\s*$' && line !~ '^\s*{' && line !~ '\s*{\s*}\s*' + let ind = ind - &sw + endif + + if pline =~ '^\s*/\*' + let ind = ind + 1 + endif + + if pline =~ '\*/$' + let ind = ind - 1 + endif + return ind +endfunction diff --git a/indent/python.vim b/indent/python.vim new file mode 100644 index 0000000..e8c551b --- /dev/null +++ b/indent/python.vim @@ -0,0 +1,262 @@ +" Vim indent file +" Language: Python +" Maintainer: Bram Moolenaar <Bram@vim.org> +" Original Author: David Bustos <bustos@caltech.edu> +" Last Change: 2008 Mar 14 +" Changed my Jason Casden to try to prettify the line continuations + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 +let g:linecont = 0 + +" Some preliminary settings +setlocal nolisp " Make sure lisp indenting doesn't supersede us +setlocal autoindent " indentexpr isn't much help otherwise + +setlocal indentexpr=GetPythonIndent(v:lnum) +setlocal indentkeys+=<:>,=elif,=except + +" Only define the function once. +if exists("*GetPythonIndent") + finish +endif + +" Come here when loading the script the first time. + +let s:maxoff = 50 " maximum number of lines to look backwards for () + + +function GetPythonParenContinue(lnum3) + call cursor(a:lnum3,1) + + + "JMC + let pnum2 = searchpair('(\|{\|\[', '', ')\|}\|\]', 'rnbW', + \ "line('.') < " . (a:lnum3 - s:maxoff) . " ? dummy :" + \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + \ . " =~ '\\(Comment\\|String\\)$'") + + if pnum2 > 0 + let g:linecont = 1 + return pnum2 + else + return a:lnum3 + endif + +endfunction + + +function GetPythonExplicitContinue(lnum2) + + let i = 1 + let ret_lnum = a:lnum2 + + while (getline(a:lnum2 - i) =~ '\\\s*$') + let g:linecont = 1 + let ret_lnum = a:lnum2 - i + let i = i + 1 + endwhile + + return ret_lnum + +endfunction + +function GetPythonIndent(lnum) + +" " If this line is explicitly joined: If the previous line was also joined, + "" line it up with that one, otherwise add two 'shiftwidth' + "if getline(a:lnum - 1) =~ '\\$' + "if a:lnum > 1 && getline(a:lnum - 2) =~ '\\\s*$' + "return indent(a:lnum - 1) + "endif + "return indent(a:lnum - 1) + (exists("g:pyindent_continue") ? eval(g:pyindent_continue) : (&sw * 2)) + "endif + + " If the start of the line is in a string don't change the indent. + if has('syntax_items') + \ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$" + return -1 + endif + + " Search backwards for the previous non-empty line. + let plnum = prevnonblank(v:lnum - 1) + + if plnum == 0 + " This is the first non-empty line, use zero indent. + return 0 + endif + + " If the previous line is inside parenthesis, use the indent of the starting + " line. + " Trick: use the non-existing "dummy" variable to break out of the loop when + " going too far back. + call cursor(plnum, 1) + + "JMC +" let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'rnbW', + "\ "line('.') < " . (plnum - s:maxoff) . " ? dummy :" + "\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + "\ . " =~ '\\(Comment\\|String\\)$'") + let parlnumcomp = 0 + let parlnum = plnum + while (parlnumcomp != parlnum) + let parlnumcomp = parlnum + let parlnum = GetPythonParenContinue(parlnum) + let parlnum = GetPythonExplicitContinue(parlnum) + endwhile + " If this line is explicitly joined: If the previous line was also joined, + " line it up with that one, otherwise add two 'shiftwidth' + if getline(plnum) =~ '\\$' + return indent(parlnum) + (&sw * 2) + else + let plindent = indent(parlnum) + endif + + let plnumstart = parlnum + + " When inside parenthesis: If at the first line below the parenthesis add + " two 'shiftwidth', otherwise same as previous line. + " i = (a + " + b + " + c) + call cursor(a:lnum, 1) + " JMC, changed to searchpairpos + let [p,parcol] = searchpairpos('(\|{\|\[', '', ')\|}\|\]', 'bW', + \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" + \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + \ . " =~ '\\(Comment\\|String\\)$'") + if p > 0 + "if p == plnum + " JMC +" let [pp,parcol2] = searchpairpos('(\|{\|\[', '', ')\|}\|\]', 'bW', + "\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" + "\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + "\ . " =~ '\\(Comment\\|String\\)$'") + "if pp > 0 + "return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : parcol2) + "endif + + " JMC, changed to return column position, unless specifically asked + " otherwise + "return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (&sw * 2)) + return (exists("g:pyindent_open_paren") ? indent(p) + eval(g:pyindent_open_paren) : parcol) + "endif + "if plnumstart == p + "return parcol + "endif + "return plindent + endif + + + " Get the line and remove a trailing comment. + " Use syntax highlighting attributes when possible. + let pline = getline(plnum) + let pline_len = strlen(pline) + if has('syntax_items') + " If the last character in the line is a comment, do a binary search for + " the start of the comment. synID() is slow, a linear search would take + " too long on a long line. + if synIDattr(synID(plnum, pline_len, 1), "name") =~ "Comment$" + let min = 1 + let max = pline_len + while min < max + let col = (min + max) / 2 + if synIDattr(synID(plnum, col, 1), "name") =~ "Comment$" + let max = col + else + let min = col + 1 + endif + endwhile + let pline = strpart(pline, 0, min - 1) + endif + else + let col = 0 + while col < pline_len + if pline[col] == '#' + let pline = strpart(pline, 0, col) + break + endif + let col = col + 1 + endwhile + endif + + " If the previous line ended with a colon, indent this line + if pline =~ ':\s*$' + " commented because it might not be a good idea: + " only for new lines + " JMC + "if (getline(a:lnum) =~ '^\s*$') + return plindent + &sw + "endif + endif + + " If the previous line was a stop-execution statement... + if getline(plnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\)\>' + " See if the user has already dedented + if indent(a:lnum) > indent(plnum) - &sw + " If not, recommend one dedent + return indent(plnum) - &sw + endif + " Otherwise, trust the user + return -1 + endif + + " If the current line begins with a keyword that lines up with "try" + if getline(a:lnum) =~ '^\s*\(except\|finally\)\>' + let lnum = a:lnum - 1 + while lnum >= 1 + if getline(lnum) =~ '^\s*\(try\|except\)\>' + let ind = indent(lnum) + if ind >= indent(a:lnum) + return -1 " indent is already less than this + endif + return ind " line up with previous try or except + endif + let lnum = lnum - 1 + endwhile + return -1 " no matching "try"! + endif + + " If the current line begins with a header keyword, dedent + if getline(a:lnum) =~ '^\s*\(elif\|else\)\>' + + " Unless the previous line was a one-liner + if getline(plnumstart) =~ '^\s*\(for\|if\|try\)\>' + return plindent + endif + + " Or the user has already dedented + if indent(a:lnum) <= plindent - &sw + return -1 + endif + + return plindent - &sw + endif + + " JMC + " If the previous line is a continuation + " make the next line line up, but only for new lines +"let curline = getline(a:lnum) + if (g:linecont == 1) + if (getline(a:lnum) =~ '^\s*$') + return plindent + endif +endif + + " JMC commented + " When after a () construct we probably want to go back to the start line. + " a = (b + " + c) + " here + "if parlnum > 0 + "return plindent + "endif + + return -1 + +endfunction + +" vim:sw=2 diff --git a/indent/vimwiki.vim b/indent/vimwiki.vim new file mode 100644 index 0000000..acb429b --- /dev/null +++ b/indent/vimwiki.vim @@ -0,0 +1,55 @@ +" Vimwiki indent file +" Author: Maxim Kim <habamax@gmail.com> +" Home: http://code.google.com/p/vimwiki/ + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +" Some preliminary settings +setlocal nolisp " Make sure lisp indenting doesn't supersede us +setlocal autoindent " indentexpr isn't much help otherwise + +setlocal indentexpr=GetVimwikiIndent(v:lnum) +setlocal indentkeys+=<:> + +" Only define the function once. +if exists("*GetVimwikiIndent") + finish +endif + +" Come here when loading the script the first time. + +function GetVimwikiIndent(lnum) + " Search backwards for the previous non-empty line. + let plnum = prevnonblank(v:lnum - 1) + if plnum == 0 + " This is the first non-empty line, use zero indent. + return 0 + endif + + " TODO: use g:vimwiki_rxList here + let lst_indent = len(matchstr(getline(a:lnum), '^\s\+\ze\(\*\|#\)')) + if lst_indent > 0 + if lst_indent < &sw + return &sw + endif + + if has("float") + let mul = round(lst_indent * 1.0 / &sw) + let ind = float2nr(mul * &sw) + else + let mul = lst_indent / &sw + let ind = mul * &sw + endif + + return ind + endif + + + return -1 +endfunction + +" vim:sw=2 diff --git a/nerdtree_plugin/exec_menuitem.vim b/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..e7a7c53 --- /dev/null +++ b/nerdtree_plugin/exec_menuitem.vim @@ -0,0 +1,41 @@ +" ============================================================================ +" File: exec_menuitem.vim +" Description: plugin for NERD Tree that provides an execute file menu item +" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com> +" Last Change: 22 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_exec_menuitem") + finish +endif +let g:loaded_nerdtree_exec_menuitem = 1 + +call NERDTreeAddMenuItem({ + \ 'text': '(!)Execute file', + \ 'shortcut': '!', + \ 'callback': 'NERDTreeExecFile', + \ 'isActiveCallback': 'NERDTreeExecFileActive' }) + +function! NERDTreeExecFileActive() + let node = g:NERDTreeFileNode.GetSelected() + return !node.path.isDirectory && node.path.isExecutable +endfunction + +function! NERDTreeExecFile() + let treenode = g:NERDTreeFileNode.GetSelected() + echo "==========================================================\n" + echo "Complete the command to execute (add arguments etc):\n" + let cmd = treenode.path.str({'escape': 1}) + let cmd = input(':!', cmd . ' ') + + if cmd != '' + exec ':!' . cmd + else + echo "Aborted" + endif +endfunction diff --git a/nerdtree_plugin/fs_menu.vim b/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..e25b38c --- /dev/null +++ b/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,194 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com> +" Last Change: 17 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_fs_menu") + finish +endif +let g:loaded_nerdtree_fs_menu = 1 + +call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) +call NERDTreeAddMenuItem({'text': '(m)ove the curent node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the curent node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) +if g:NERDTreePath.CopyingSupported() + call NERDTreeAddMenuItem({'text': '(c)copy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'}) +endif + +"FUNCTION: s:echo(msg){{{1 +function! s:echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction + +"FUNCTION: s:echoWarning(msg){{{1 +function! s:echoWarning(msg) + echohl warningmsg + call s:echo(a:msg) + echohl normal +endfunction + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if nr2char(getchar()) ==# 'y' + exec "silent bdelete! " . a:bufnum + endif +endfunction + +"FUNCTION: NERDTreeAddNode(){{{1 +function! NERDTreeAddNode() + let curDirNode = g:NERDTreeDirNode.GetSelected() + + let newNodeName = input("Add a childnode\n". + \ "==========================================================\n". + \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . + \ "", curDirNode.path.str({'format': 'Glob'}) . g:NERDTreePath.Slash()) + + if newNodeName ==# '' + call s:echo("Node Creation Aborted.") + return + endif + + try + let newPath = g:NERDTreePath.Create(newNodeName) + let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) + + let newTreeNode = g:NERDTreeFileNode.New(newPath) + if parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call NERDTreeRender() + call newTreeNode.putCursorHere(1, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Node Not Created.") + endtry +endfunction + +"FUNCTION: NERDTreeMoveNode(){{{1 +function! NERDTreeMoveNode() + let curNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Rename the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path for the node: \n" . + \ "", curNode.path.str()) + + if newNodePath ==# '' + call s:echo("Node Renaming Aborted.") + return + endif + + try + let bufnum = bufnr(curNode.path.str()) + + call curNode.rename(newNodePath) + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + if bufnum != -1 + let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + call curNode.putCursorHere(1, 0) + + redraw + catch /^NERDTree/ + call s:echoWarning("Node Not Renamed.") + endtry +endfunction + +" FUNCTION: NERDTreeDeleteNode() {{{1 +function! NERDTreeDeleteNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let confirmed = 0 + + if currentNode.path.isDirectory + let choice =input("Delete the current node\n" . + \ "==========================================================\n" . + \ "STOP! To delete this entire directory, type 'yes'\n" . + \ "" . currentNode.path.str() . ": ") + let confirmed = choice ==# 'yes' + else + echo "Delete the current node\n" . + \ "==========================================================\n". + \ "Are you sure you wish to delete the node:\n" . + \ "" . currentNode.path.str() . " (yN):" + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + + if confirmed + try + call currentNode.delete() + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr(currentNode.path.str()) + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove node") + endtry + else + call s:echo("delete aborted") + endif + +endfunction + +" FUNCTION: NERDTreeCopyNode() {{{1 +function! NERDTreeCopyNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Copy the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path to copy the node to: \n" . + \ "", currentNode.path.str()) + + if newNodePath != "" + "strip trailing slash + let newNodePath = substitute(newNodePath, '\/$', '', '') + + let confirmed = 1 + if currentNode.path.copyingWillOverwrite(newNodePath) + call s:echo("Warning: copying may overwrite files! Continue? (yN)") + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + let newNode = currentNode.copy(newNodePath) + call NERDTreeRender() + call newNode.putCursorHere(0, 0) + catch /^NERDTree/ + call s:echoWarning("Could not copy node") + endtry + endif + else + call s:echo("Copy aborted.") + endif + redraw +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/plugin/DirDiff.vim b/plugin/DirDiff.vim new file mode 100644 index 0000000..044577f --- /dev/null +++ b/plugin/DirDiff.vim @@ -0,0 +1,1070 @@ +" -*- vim -*- +" FILE: "/home/wlee/.vim/plugin/DirDiff.vim" {{{ +" LAST MODIFICATION: "Mon, 20 Oct 2008 09:04:59 -0500 (wlee)" +" HEADER MAINTAINED BY: N/A +" VERSION: 1.1.2 +" (C) 2001-2006 by William Lee, <wl1012@yahoo.com> +" }}} + + +" PURPOSE: {{{ +" - Diffing a directory recursively and enable easy merging, copying and +" deleting of files and directories. +" +" REQUIREMENTS: +" - Make sure you have GNU diff in your path on Unix and Windows. I only +" tested this on cygwin's version on Windows. If you have a diff that +" doesn't support -x or -I flag, do not set variable g:DirDiffExcludes and +" g:DirDiffIgnore to "". It should still work. +" - On Windows, you need to have "xcopy", "copy", "del", and "rd" in your +" path. +" - On Unix, you need to have "rm" and "cp" in your path. +" +" USAGE: +" Put this file in your ~/.vim/plugin +" +" Doing the following will generate a diff window. +" +" :DirDiff <A:Src Directory> <B:Src Directory> +" e.g. +" :DirDiff ../something/dir1 /usr/bin/somethingelse/dir2 +" +" The following commands can be used inside the diff window: +" 'Enter','o' - Diff open: open the diff file(s) where your cursor is at +" 's' - Synchronize the current diff. You can also select +" a range (through visual) and press 's' to synchronize differences +" across a range. +" +" - There are 6 Options you can choose when you hit 's': +" 1. A -> B +" Copy A to overwrite B +" If A's file actually points to a directory, it'll copy it to B +" recursively. +" 2. B -> A +" Copy B to overwrite A +" If B's file actually points to a directory, it'll copy it to A +" recursively. +" 3. Always A +" For the rest of the items that you've selected, +" synchronize like (1). +" 4. Always B +" For the rest of the items that you've selected, +" synchronize like (2). +" 5. Skip +" Skip this diff entry. +" 6. Cancel +" Quit the loop and exit. +" +" 'u' - Diff update: update the diff window +" 'x' - Sets the exclude pattern, separated by ',' +" 'i' - Sets the ignore pattern, separated by ',' +" 'a' - Sets additional arguments for diff, eg. -w to ignore white space, +" etc. +" 'q' - Quit DirDiff +" +" The following comamnds can be used in the Vim diff mode +" \dg - Diff get: maps to :diffget<CR> +" \dp - Diff put: maps to :diffput<CR> +" \dj - Diff next: (think j for down) +" \dk - Diff previous: (think k for up) +" +" You can set the following DirDiff variables. You can add the following +" "let" lines in your .vimrc file. +" +" Sets default exclude pattern: +" let g:DirDiffExcludes = "CVS,*.class,*.exe,.*.swp" +" +" Sets default ignore pattern: +" let g:DirDiffIgnore = "Id:,Revision:,Date:" +" +" If DirDiffSort is set to 1, sorts the diff lines. +" let g:DirDiffSort = 1 +" +" Sets the diff window (bottom window) height (rows) +" let g:DirDiffWindowSize = 14 +" +" Ignore case during diff +" let g:DirDiffIgnoreCase = 0 +" +" Dynamically figure out the diff text. If you are using and i18n version +" of diff, this will try to get the specific diff text during runtime. It's +" turned off by default. If you are always targetting a specific version of +" diff, you can turn this off and set the DirDiffText* variables +" accordingly. +" let g:DirDiffDynamicDiffText = 0 +" +" String used for the English equivalent "Files " +" let g:DirDiffTextFiles = "Files " + +" String used for the English equivalent " and " +" let g:DirDiffTextAnd = " and " +" +" String used for the English equivalent " differ") +" let g:DirDiffTextDiffer = " differ" +" +" String used for the English equivalent "Only in ") +" let g:DirDiffTextOnlyIn = "Only in " +" +" NOTES: +" This script can copy and remove your files. This can be powerful (or too +" powerful) at times. Please do not blame me if you use this and +" disintegrate your hard work. Be warned! +" +" CREDITS: +" +" Please mail any comment/suggestion/patch to +" William Lee <wl1012@yahoo.com> +" +" LICENSE: +" Copyright (c) 2001-2006 William Lee +" All rights reserved. +" +" Redistribution and use in source and binary forms, with or without +" modification, are permitted provided that the following conditions are +" met: +" +" * Redistributions of source code must retain the above copyright +" notice, this list of conditions and the following disclaimer. +" * Redistributions in binary form must reproduce the above copyright +" notice, this list of conditions and the following disclaimer in the +" documentation and/or other materials provided with the distribution. +" * Neither the name William Lee nor the names of its contributors may be +" used to endorse or promote products derived from this software without +" specific prior written permission. +" +" THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +" WILLIAM LEE AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +" +" THANKS: +" +" Florian Delizy for the i18n diff patch +" Robert Webb for his sorting function +" Salman Halim, Yosuke Kimura, and others for their suggestions +" +" HISTORY: +" 1.1.2 - Applied the patch to 1.1.0 instead of 1.0.2. Please do not use +" 1.1.1 +" 1.1.1 - Make it work with filename with spaces. (Thanks to Atte Kojo) +" 1.1.0 - Added support for i18n (tested on a French version for now only). +" Can dynamically figure out the diff strings output by diff. +" 1.0.2 - Fixed a small typo bug in the quit function. +" 1.0.1 - Ensure the path separator is correct when running in W2K +" 1.0 - Fixed a bug that flags errors if the user use the nowrapscan option. +" Implements a quit function that exit the diff windows. +" 0.94 - Fixed a bug where the diff will give incorrect A and B file due to +" similarity of directory names. Allow you to modify the diff +" argument. +" 0.93 - Opps, messed up the key mapping usage. +" 0.92 - Doesn't use n and p mappings since it confuses the search next key +" mapping and causes some bugs. Minor modification to change the +" exclude and ignore pattern. +" 0.91 - Clean up delete routine. +" - Added interactive mode. +" - Added multiple entries of exclude and ignore pattern. +" - Custom configuration through global variables. +" - Change exclude and ignore patterns on the fly. +" +" 0.9 - Reorganization of the interface. Much simplier dialog for +" synchronization. Support for range synchronization option (REALLY +" powerful) +" - Removed unnecessary key bindings. All key bindings are local to +" the diff window. (except for the \dg and \dp) +" +" 0.8 - Added syntax highlighting. +" - Enter and double-click in buffer opens diff. +" - Removed dependency on "sort" +" - Removed usage of registry and marker +" - Code cleanup and some bug fixes +" - On Windows the diff command will use the -i flag instead +" - Changed mappings for diff next (\dj) and diff previous (\dk) +" - Added mappings for vim diff mode (\dg, \dp) +" +" 0.7 Initial Release +" +" }}} + +" Public Interface: +command! -nargs=* -complete=dir DirDiff call <SID>DirDiff (<f-args>) +command! -nargs=0 DirDiffOpen call <SID>DirDiffOpen () +command! -nargs=0 DirDiffNext call <SID>DirDiffNext () +command! -nargs=0 DirDiffPrev call <SID>DirDiffPrev () +command! -nargs=0 DirDiffUpdate call <SID>DirDiffUpdate () +command! -nargs=0 DirDiffQuit call <SID>DirDiffQuit () + +if !hasmapto('<Plug>DirDiffGet') + map <unique> <Leader>dg <Plug>DirDiffGet +endif +if !hasmapto('<Plug>DirDiffPut') + map <unique> <Leader>dp <Plug>DirDiffPut +endif +if !hasmapto('<Plug>DirDiffNext') + map <unique> <Leader>dj <Plug>DirDiffNext +endif +if !hasmapto('<Plug>DirDiffPrev') + map <unique> <Leader>dk <Plug>DirDiffPrev +endif + +" Global Maps: +map <unique> <script> <Plug>DirDiffGet :diffget<CR> +map <unique> <script> <Plug>DirDiffPut :diffput<CR> +map <unique> <script> <Plug>DirDiffNext :call <SID>DirDiffNext()<CR> +map <unique> <script> <Plug>DirDiffPrev :call <SID>DirDiffPrev()<CR> +map <unique> <script> <Plug>DirDiffQuit :call <SID>DirDiffQuit()<CR> + +" Default Variables. You can override these in your global variables +" settings. +" +" For DirDiffExcludes and DirDiffIgnore, separate different patterns with a +" ',' (comma and no space!). +" +" eg. in your .vimrc file: let g:DirDiffExcludes = "CVS,*.class,*.o" +" let g:DirDiffIgnore = "Id:" +" " ignore white space in diff +" let g:DirDiffAddArgs = "-w" +" +" You can set the pattern that diff excludes. Defaults to the CVS directory +if !exists("g:DirDiffExcludes") + let g:DirDiffExcludes = "" +endif +" This is the -I argument of the diff, ignore the lines of differences that +" matches the pattern +if !exists("g:DirDiffIgnore") + let g:DirDiffIgnore = "" +endif +if !exists("g:DirDiffSort") + let g:DirDiffSort = 1 +endif +if !exists("g:DirDiffWindowSize") + let g:DirDiffWindowSize = 14 +endif +if !exists("g:DirDiffInteractive") + let g:DirDiffInteractive = 0 +endif +if !exists("g:DirDiffIgnoreCase") + let g:DirDiffIgnoreCase = 0 +endif +" Additional arguments +if !exists("g:DirDiffAddArgs") + let g:DirDiffAddArgs = "" +endif +" Support for i18n (dynamically figure out the diff text) +" Defaults to off +if !exists("g:DirDiffDynamicDiffText") + let g:DirDiffDynamicDiffText = 0 +endif + +" String used for the English equivalent "Files " +if !exists("g:DirDiffTextFiles") + let g:DirDiffTextFiles = "Files " +endif + +" String used for the English equivalent " and " +if !exists("g:DirDiffTextAnd") + let g:DirDiffTextAnd = " and " +endif + +" String used for the English equivalent " differ") +if !exists("g:DirDiffTextDiffer") + let g:DirDiffTextDiffer = " differ" +endif + +" String used for the English equivalent "Only in ") +if !exists("g:DirDiffTextOnlyIn") + let g:DirDiffTextOnlyIn = "Only in " +endif + +" Set some script specific variables: +" +let s:DirDiffFirstDiffLine = 6 +let s:DirDiffALine = 1 +let s:DirDiffBLine = 2 + +" -- Variables used in various utilities +if has("unix") + let s:DirDiffCopyCmd = "cp" + let s:DirDiffCopyFlags = "" + let s:DirDiffCopyDirCmd = "cp" + let s:DirDiffCopyDirFlags = "-rf" + let s:DirDiffCopyInteractiveFlag = "-i" + + let s:DirDiffDeleteCmd = "rm" + let s:DirDiffDeleteFlags = "" + let s:DirDiffDeleteInteractiveFlag = "-i" + + let s:DirDiffDeleteDirCmd = "rm" + let s:DirDiffDeleteDirFlags = "-rf" + + let s:sep = "/" + + let s:DirDiffMakeDirCmd = "!mkdir " + +elseif has("win32") + let s:DirDiffCopyCmd = "copy" + let s:DirDiffCopyFlags = "" + let s:DirDiffCopyDirCmd = "xcopy" + let s:DirDiffCopyDirFlags = "/e /i /q" + let s:DirDiffCopyInteractiveFlag = "/-y" + + let s:DirDiffDeleteCmd = "del" + let s:DirDiffDeleteFlags = "/s /q" + let s:DirDiffDeleteInteractiveFlag = "/p" + " Windows is somewhat stupid since "del" can only remove the files, not + " the directory. The command "rd" would remove files recursively, but it + " doesn't really work on a file (!). where is the deltree command??? + + let s:DirDiffDeleteDirCmd = "rd" + " rd is by default prompting, we need to handle this in a different way + let s:DirDiffDeleteDirFlags = "/s" + let s:DirDiffDeleteDirQuietFlag = "/q" + + let s:sep = "\\" + + let s:DirDiffMakeDirCmd = "!mkdir " +else + " Platforms not supported + let s:DirDiffCopyCmd = "" + let s:DirDiffCopyFlags = "" + let s:DirDiffDeleteCmd = "" + let s:DirDiffDeleteFlags = "" + let s:sep = "" +endif + + +function! <SID>DirDiff(srcA, srcB) + " Setup + let DirDiffAbsSrcA = fnamemodify(expand(a:srcA, ":p"), ":p") + let DirDiffAbsSrcB = fnamemodify(expand(a:srcB, ":p"), ":p") + + " Check for an internationalized version of diff ? + call <SID>GetDiffStrings() + + " Remove the trailing \ or / + let DirDiffAbsSrcA = substitute(DirDiffAbsSrcA, '\\$\|/$', '', '') + let DirDiffAbsSrcB = substitute(DirDiffAbsSrcB, '\\$\|/$', '', '') + + let DiffBuffer = tempname() + " We first write to that file + " Constructs the command line + let cmd = "!diff" + let cmdarg = " -r --brief" + + " If variable is set, we ignore the case + if (g:DirDiffIgnoreCase) + let cmdarg = cmdarg." -i" + endif + if (g:DirDiffAddArgs != "") + let cmdarg = cmdarg." ".g:DirDiffAddArgs." " + endif + if (g:DirDiffExcludes != "") + let cmdarg = cmdarg.' -x"'.substitute(g:DirDiffExcludes, ',', '" -x"', 'g').'"' + endif + if (g:DirDiffIgnore != "") + let cmdarg = cmdarg.' -I"'.substitute(g:DirDiffIgnore, ',', '" -I"', 'g').'"' + endif + " Prompt the user for additional arguments +" let addarg = input("Additional diff args (current =". cmdarg. "): ") + let addarg = "" + let cmd = cmd.cmdarg." ".addarg." \"".DirDiffAbsSrcA."\" \"".DirDiffAbsSrcB."\"" + let cmd = cmd." > \"".DiffBuffer."\"" + + echo "Diffing directories, it may take a while..." + let error = <SID>DirDiffExec(cmd, 0) + if (error == 0) + echo "There is no diff here." + return + endif + silent exe "edit ".DiffBuffer + echo "Defining [A] and [B] ... " + " We then do a substitution on the directory path + " We need to do substitution of the the LONGER string first, otherwise + " it'll mix up the A and B directory + if (strlen(DirDiffAbsSrcA) > strlen(DirDiffAbsSrcB)) + silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcA)."/[A]/" + silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcB)."/[B]/" + else + silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcB)."/[B]/" + silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcA)."/[A]/" + endif + " In windows, diff behaves somewhat weirdly, for the appened path it'll + " use "/" instead of "\". Convert this to \ + if (has("win32")) + silent! %s/\//\\/g + endif + + echo "Sorting entries ..." + " We then sort the lines if the option is set + if (g:DirDiffSort == 1) + 1,$call <SID>Sort("s:Strcmp") + endif + + " Put in spacer in front of each line + silent! %s/^/ / + + " We then put the file [A] and [B] on top of the diff lines + call append(0, "[A]=". DirDiffAbsSrcA) + call append(1, "[B]=". DirDiffAbsSrcB) + call append(2, "Usage: <Enter>/'o'=open,'s'=sync,'\\dj'=next,'\\dk'=prev, 'q'=quit") + call append(3, "Options: 'u'=update,'x'=set excludes,'i'=set ignore,'a'=set args" ) + call append(4, "Diff Args:" . cmdarg) + call append(5, "") + " go to the beginning of the file + 0 + setlocal nomodified + setlocal nomodifiable + setlocal buftype=nowrite + setlocal bufhidden=delete + setlocal nowrap + + " Set up local key bindings + " 'n' actually messes with the search next pattern, I think using \dj and + " \dk is enough. Otherwise, use j,k, and enter. +" nnoremap <buffer> n :call <SID>DirDiffNext()<CR> +" nnoremap <buffer> p :call <SID>DirDiffPrev()<CR> + nnoremap <buffer> s :. call <SID>DirDiffSync()<CR> + vnoremap <buffer> s :call <SID>DirDiffSync()<CR> + nnoremap <buffer> u :call <SID>DirDiffUpdate()<CR> + nnoremap <buffer> x :call <SID>ChangeExcludes()<CR> + nnoremap <buffer> a :call <SID>ChangeArguments()<CR> + nnoremap <buffer> i :call <SID>ChangeIgnore()<CR> + nnoremap <buffer> q :call <SID>DirDiffQuit()<CR> + + nnoremap <buffer> o :call <SID>DirDiffOpen()<CR> + nnoremap <buffer> <CR> :call <SID>DirDiffOpen()<CR> + nnoremap <buffer> <2-Leftmouse> :call <SID>DirDiffOpen()<CR> + call <SID>SetupSyntax() + + " Open the first diff + call <SID>DirDiffNext() +endfunction + +" Set up syntax highlighing for the diff window +function! <SID>SetupSyntax() + if has("syntax") && exists("g:syntax_on") + "&& !has("syntax_items") + syn match DirDiffSrcA "\[A\]" + syn match DirDiffSrcB "\[B\]" + syn match DirDiffUsage "^Usage.*" + syn match DirDiffOptions "^Options.*" + exec 'syn match DirDiffFiles "' . s:DirDiffDifferLine .'"' + exec 'syn match DirDiffOnly "' . s:DirDiffDiffOnlyLine . '"' + syn match DirDiffSelected "^==>.*" contains=DirDiffSrcA,DirDiffSrcB + + hi def link DirDiffSrcA Directory + hi def link DirDiffSrcB Type + hi def link DirDiffUsage Special + hi def link DirDiffOptions Special + hi def link DirDiffFiles String + hi def link DirDiffOnly PreProc + hi def link DirDiffSelected DiffChange + endif +endfunction + +" You should call this within the diff window +function! <SID>DirDiffUpdate() + let dirA = <SID>GetBaseDir("A") + let dirB = <SID>GetBaseDir("B") + call <SID>DirDiff(dirA, dirB) +endfun + +" Quit the DirDiff mode +function! <SID>DirDiffQuit() + let in = confirm ("Are you sure you want to quit DirDiff?", "&Yes\n&No", 2) + if (in == 1) + call <SID>CloseDiffWindows() + bd! + endif +endfun + +" Returns an escaped version of the path for regex uses +function! <SID>EscapeDirForRegex(path) + " This list is probably not complete, modify later + return escape(a:path, "/\\[]$^~") +endfunction + +" Close the opened diff comparison windows if they exist +function! <SID>CloseDiffWindows() + if (<SID>AreDiffWinsOpened()) + wincmd k + " Ask the user to save if buffer is modified + call <SID>AskIfModified() + bd! + " User may just have one window opened, we may not need to close + " the second diff window + if (&diff) + call <SID>AskIfModified() + bd! + endif + endif +endfunction + + +function! <SID>DirDiffOpen() + " First dehighlight the last marked + call <SID>DeHighlightLine() + + " Mark the current location of the line + "mark n + let b:currentDiff = line(".") + + " We first parse back the [A] and [B] directories from the top of the line + let dirA = <SID>GetBaseDir("A") + let dirB = <SID>GetBaseDir("B") + + call <SID>CloseDiffWindows() + + let line = getline(".") + " Parse the line and see whether it's a "Only in" or "Files Differ" + call <SID>HighlightLine() + let fileA = <SID>GetFileNameFromLine("A", line) + let fileB = <SID>GetFileNameFromLine("B", line) + if <SID>IsOnly(line) + " We open the file + let fileSrc = <SID>ParseOnlySrc(line) + if (fileSrc == "A") + let fileToOpen = fileA + elseif (fileSrc == "B") + let fileToOpen = fileB + endif + split + wincmd k + silent exec "edit ".fnameescape(fileToOpen) + " Fool the window saying that this is diff + diffthis + wincmd j + " Resize the window + exe("resize " . g:DirDiffWindowSize) + exe (b:currentDiff) + elseif <SID>IsDiffer(line) + "Open the diff windows + split + wincmd k + silent exec "edit ".fnameescape(fileB) + silent exec "vert diffsplit ".fnameescape(fileA) + " Go back to the diff window + wincmd j + " Resize the window + exe("resize " . g:DirDiffWindowSize) + exe (b:currentDiff) + " Center the line + exe ("normal z.") + else + echo "There is no diff at the current line!" + endif +endfunction + +" Ask the user to save if the buffer is modified +" +function! <SID>AskIfModified() + if (&modified) + let input = confirm("File " . expand("%:p") . " has been modified.", "&Save\nCa&ncel", 1) + if (input == 1) + w! + endif + endif +endfunction + +function! <SID>HighlightLine() + let savedLine = line(".") + exe (b:currentDiff) + setlocal modifiable + let line = getline(".") + if (match(line, "^ ") == 0) + s/^ /==> / + endif + setlocal nomodifiable + setlocal nomodified + exe (savedLine) + redraw +endfunction + +function! <SID>DeHighlightLine() + let savedLine = line(".") + exe (b:currentDiff) + let line = getline(".") + setlocal modifiable + if (match(line, "^==> ") == 0) + s/^==> / / + endif + setlocal nomodifiable + setlocal nomodified + exe (savedLine) + redraw +endfunction + +" Returns the directory for buffer "A" or "B". You need to be in the diff +" buffer though. +function! <SID>GetBaseDir(diffName) + let currLine = line(".") + if (a:diffName == "A") + let baseLine = s:DirDiffALine + else + let baseLine = s:DirDiffBLine + endif + let regex = '\['.a:diffName.'\]=\(.*\)' + let line = getline(baseLine) + let rtn = substitute(line, regex , '\1', '') + return rtn +endfunction + +function! <SID>DirDiffNext() + " If the current window is a diff, go down one + if (&diff == 1) + wincmd j + endif + " if the current line is <= 6, (within the header range), we go to the + " first diff line open it + if (line(".") < s:DirDiffFirstDiffLine) + exe (s:DirDiffFirstDiffLine) + let b:currentDiff = line(".") + endif + silent! exe (b:currentDiff + 1) + call <SID>DirDiffOpen() +endfunction + +function! <SID>DirDiffPrev() + " If the current window is a diff, go down one + if (&diff == 1) + wincmd j + endif + silent! exe (b:currentDiff - 1) + call <SID>DirDiffOpen() +endfunction + +" For each line, we can perform a recursive copy or delete to sync up the +" difference. Returns non-zero if the operation is NOT successful, returns 0 +" if everything is fine. +" +function! <SID>DirDiffSyncHelper(AB, line) + let fileA = <SID>GetFileNameFromLine("A", a:line) + let fileB = <SID>GetFileNameFromLine("B", a:line) +" echo "Helper line is ". a:line. " fileA " . fileA . " fileB " . fileB + if <SID>IsOnly(a:line) + " If a:AB is "A" and the ParseOnlySrc returns "A", that means we need to + " copy + let fileSrc = <SID>ParseOnlySrc(a:line) + let operation = "" + if (a:AB == "A" && fileSrc == "A") + let operation = "Copy" + " Use A, and A has source, thus copy the file from A to B + let fileFrom = fileA + let fileTo = fileB + elseif (a:AB == "A" && fileSrc == "B") + let operation = "Delete" + " Use A, but B has source, thus delete the file from B + let fileFrom = fileB + let fileTo = fileA + elseif (a:AB == "B" && fileSrc == "A") + let operation = "Delete" + " Use B, but the source file is A, thus removing A + let fileFrom = fileA + let fileTo = fileB + elseif (a:AB == "B" && fileSrc == "B") + " Use B, and B has the source file, thus copy B to A + let operation = "Copy" + let fileFrom = fileB + let fileTo = fileA + endif + elseif <SID>IsDiffer(a:line) + " Copy no matter what + let operation = "Copy" + if (a:AB == "A") + let fileFrom = fileA + let fileTo = fileB + elseif (a:AB == "B") + let fileFrom = fileB + let fileTo = fileA + endif + else + echo "There is no diff here!" + " Error + return 1 + endif + if (operation == "Copy") + let rtnCode = <SID>Copy(fileFrom, fileTo) + elseif (operation == "Delete") + let rtnCode = <SID>Delete(fileFrom) + endif + return rtnCode +endfunction + +" Synchronize the range +function! <SID>DirDiffSync() range + let answer = 1 + let silence = 0 + let syncMaster = "A" + let currLine = a:firstline + let lastLine = a:lastline + let syncCount = 0 + + while ((currLine <= lastLine)) + " Update the highlight + call <SID>DeHighlightLine() + let b:currentDiff = currLine + call <SID>HighlightLine() + let line = getline(currLine) + if (!silence) + let answer = confirm(substitute(line, "^....", '', ''). "\nSynchronization option:" , "&A -> B\n&B -> A\nA&lways A\nAl&ways B\n&Skip\nCa&ncel", 6) + if (answer == 1 || answer == 3) + let syncMaster = "A" + endif + if (answer == 2 || answer == 4) + let syncMaster = "B" + endif + if (answer == 3 || answer == 4) + let silence = 1 + endif + if (answer == 5) + let currLine = currLine + 1 + continue + endif + if (answer == 6) + break + endif + endif + +" call <SID>DeHighlightLine() + let rtnCode = <SID>DirDiffSyncHelper(syncMaster, line) + if (rtnCode == 0) + " Successful + let syncCount = syncCount + 1 + " Assume that the line is synchronized, we delete the entry + setlocal modifiable + exe (currLine.",".currLine." delete") + setlocal nomodifiable + setlocal nomodified + let lastLine = lastLine - 1 + else + " Failed! + let currLine = currLine + 1 + endif + endwhile + echo syncCount . " diff item(s) synchronized." +endfunction + +" Return file "A" or "B" depending on the line given. If it's a Only line, +" either A or B does not exist, but the according value would be returned. +function! <SID>GetFileNameFromLine(AB, line) + " Determine where the source of the copy is. + let dirA = <SID>GetBaseDir("A") + let dirB = <SID>GetBaseDir("B") + + let fileToProcess = "" + + if <SID>IsOnly(a:line) + let fileToProcess = <SID>ParseOnlyFile(a:line) + elseif <SID>IsDiffer(a:line) + let regex = '^.*' . s:DirDiffDifferLine . '\[A\]\(.*\)' . s:DirDiffDifferAndLine . '\[B\]\(.*\)' . s:DirDiffDifferEndLine . '.*$' + let fileToProcess = substitute(a:line, regex, '\1', '') + else + endif + + "echo "line : " . a:line. "AB = " . a:AB . " File to Process " . fileToProcess + if (a:AB == "A") + return dirA . fileToProcess + elseif (a:AB == "B") + return dirB . fileToProcess + else + return "" + endif +endfunction + +"Returns the source (A or B) of the "Only" line +function! <SID>ParseOnlySrc(line) + return substitute(a:line, '^.*' . s:DirDiffDiffOnlyLine . '\[\(.\)\].*:.*', '\1', '') +endfunction + +function! <SID>ParseOnlyFile(line) + let regex = '^.*' . s:DirDiffDiffOnlyLine . '\[.\]\(.*\): \(.*\)' + let root = substitute(a:line, regex , '\1', '') + let file = root . s:sep . substitute(a:line, regex , '\2', '') + return file +endfunction + +function! <SID>Copy(fileFromOrig, fileToOrig) + let fileFrom = substitute(a:fileFromOrig, '/', s:sep, 'g') + let fileTo = substitute(a:fileToOrig, '/', s:sep, 'g') + echo "Copy from " . fileFrom . " to " . fileTo + if (s:DirDiffCopyCmd == "") + echo "Copy not supported on this platform" + return 1 + endif + + " Constructs the copy command + let copycmd = "!".s:DirDiffCopyCmd." ".s:DirDiffCopyFlags + " Append the interactive flag + if (g:DirDiffInteractive) + let copycmd = copycmd . " " . s:DirDiffCopyInteractiveFlag + endif + let copycmd = copycmd . " \"".fileFrom."\" \"".fileTo."\"" + + " Constructs the copy directory command + let copydircmd = "!".s:DirDiffCopyDirCmd." ".s:DirDiffCopyDirFlags + " Append the interactive flag + if (g:DirDiffInteractive) + let copydircmd = copydircmd . " " . s:DirDiffCopyInteractiveFlag + endif + let copydircmd = copydircmd . " \"".fileFrom."\" \"".fileTo."\"" + + let error = 0 + if (isdirectory(fileFrom)) + let error = <SID>DirDiffExec(copydircmd, g:DirDiffInteractive) + else + let error = <SID>DirDiffExec(copycmd, g:DirDiffInteractive) + endif + if (error != 0) + echo "Can't copy from " . fileFrom . " to " . fileTo + return 1 + endif + return 0 +endfunction + +" Would execute the command, either silent or not silent, by the +" interactive flag ([0|1]). Returns the v:shell_error after +" executing the command. +function! <SID>DirDiffExec(cmd, interactive) + let error = 0 + if (a:interactive) + exe (a:cmd) + let error = v:shell_error + else + silent exe (a:cmd) + let error = v:shell_error + endif +" let d = input("DirDiffExec: " . a:cmd . " " . a:interactive . " returns " . v:shell_error) + return error +endfunction + +" Delete the file or directory. Returns 0 if nothing goes wrong, error code +" otherwise. +function! <SID>Delete(fileFromOrig) + let fileFrom = substitute(a:fileFromOrig, '/', s:sep, 'g') + echo "Deleting from " . fileFrom + if (s:DirDiffDeleteCmd == "") + echo "Delete not supported on this platform" + return 1 + endif + + let delcmd = "" + + if (isdirectory(fileFrom)) + let delcmd = "!".s:DirDiffDeleteDirCmd." ".s:DirDiffDeleteDirFlags + if (g:DirDiffInteractive) + " If running on Unix, and we're running in interactive mode, we + " append the -i tag + if (has("unix")) + let delcmd = delcmd . " " . s:DirDiffDeleteInteractiveFlag + endif + else + " If running on windows, and we're not running in interactive + " mode, we append the quite flag to the "rd" command + if (has("win32")) + let delcmd = delcmd . " " . s:DirDiffDeleteDirQuietFlag + endif + endif + else + let delcmd = "!".s:DirDiffDeleteCmd." ".s:DirDiffDeleteFlags + if (g:DirDiffInteractive) + let delcmd = delcmd . " " . s:DirDiffDeleteInteractiveFlag + endif + endif + + let delcmd = delcmd ." \"".fileFrom."\"" + let error = <SID>DirDiffExec(delcmd, g:DirDiffInteractive) + if (error != 0) + echo "Can't delete " . fileFrom + endif + return error +endfunction + +function! <SID>AreDiffWinsOpened() + let currBuff = expand("%:p") + let currLine = line(".") + wincmd k + let abovedBuff = expand("%:p") + if (&diff) + let abovedIsDiff = 1 + else + let abovedIsDiff = 0 + endif + " Go Back if the aboved buffer is not the same + if (currBuff != abovedBuff) + wincmd j + " Go back to the same line + exe (currLine) + if (abovedIsDiff == 1) + return 1 + else + " Aboved is just a bogus buffer, not a diff buffer + return 0 + endif + else + exe (currLine) + return 0 + endif +endfunction + +" The given line begins with the "Only in" +function! <SID>IsOnly(line) + return (match(a:line, "^ *" . s:DirDiffDiffOnlyLine . "\\|^==> " . s:DirDiffDiffOnlyLine ) == 0) +endfunction + +" The given line begins with the "Files" +function! <SID>IsDiffer(line) + return (match(a:line, "^ *" . s:DirDiffDifferLine . "\\|^==> " . s:DirDiffDifferLine ) == 0) +endfunction + +" Let you modify the Exclude patthern +function! <SID>ChangeExcludes() + let g:DirDiffExcludes = input ("Exclude pattern (separate multiple patterns with ','): ", g:DirDiffExcludes) + echo "\nPress update ('u') to refresh the diff." +endfunction + +" Let you modify additional arguments for diff +function! <SID>ChangeArguments() + let g:DirDiffAddArgs = input ("Additional diff args: ", g:DirDiffAddArgs) + echo "\nPress update ('u') to refresh the diff." +endfunction + +" Let you modify the Ignore patthern +function! <SID>ChangeIgnore() + let g:DirDiffIgnore = input ("Ignore pattern (separate multiple patterns with ','): ", g:DirDiffIgnore) + echo "\nPress update ('u') to refresh the diff." +endfunction + +" Sorting functions from the Vim docs. Use this instead of the sort binary. +" +" Function for use with Sort(), to compare two strings. +func! <SID>Strcmp(str1, str2) + if (a:str1 < a:str2) + return -1 + elseif (a:str1 > a:str2) + return 1 + else + return 0 + endif +endfunction + +" Sort lines. SortR() is called recursively. +func! <SID>SortR(start, end, cmp) + if (a:start >= a:end) + return + endif + let partition = a:start - 1 + let middle = partition + let partStr = getline((a:start + a:end) / 2) + let i = a:start + while (i <= a:end) + let str = getline(i) + exec "let result = " . a:cmp . "(str, partStr)" + if (result <= 0) + " Need to put it before the partition. Swap lines i and partition. + let partition = partition + 1 + if (result == 0) + let middle = partition + endif + if (i != partition) + let str2 = getline(partition) + call setline(i, str2) + call setline(partition, str) + endif + endif + let i = i + 1 + endwhile + + " Now we have a pointer to the "middle" element, as far as partitioning + " goes, which could be anywhere before the partition. Make sure it is at + " the end of the partition. + if (middle != partition) + let str = getline(middle) + let str2 = getline(partition) + call setline(middle, str2) + call setline(partition, str) + endif + call <SID>SortR(a:start, partition - 1, a:cmp) + call <SID>SortR(partition + 1, a:end, a:cmp) +endfunc + +" To Sort a range of lines, pass the range to Sort() along with the name of a +" function that will compare two lines. +func! <SID>Sort(cmp) range + call <SID>SortR(a:firstline, a:lastline, a:cmp) +endfunc + +" Added to deal with internationalized version of diff, which returns a +" different string than "Files ... differ" or "Only in ... " + +function! <SID>GetDiffStrings() + " Check if we have the dynamic text string turned on. If not, just return + " what's set in the global variables + + if (g:DirDiffDynamicDiffText == 0) + let s:DirDiffDiffOnlyLine = g:DirDiffTextOnlyIn + let s:DirDiffDifferLine = g:DirDiffTextFiles + let s:DirDiffDifferAndLine = g:DirDiffTextAnd + let s:DirDiffDifferEndLine = g:DirDiffTextDiffer + return + endif + + let tmp1 = tempname() + let tmp2 = tempname() + let tmpdiff = tempname() + + " We need to pad the backslashes in order to make it match + let tmp1rx = <SID>EscapeDirForRegex(tmp1) + let tmp2rx = <SID>EscapeDirForRegex(tmp2) + let tmpdiffrx = <SID>EscapeDirForRegex(tmpdiff) + + silent exe s:DirDiffMakeDirCmd . "\"" . tmp1 . "\"" + silent exe s:DirDiffMakeDirCmd . "\"" . tmp2 . "\"" + silent exe "!echo test > \"" . tmp1 . s:sep . "test" . "\"" + silent exe "!diff -r --brief \"" . tmp1 . "\" \"" . tmp2 . "\" > \"" . tmpdiff . "\"" + + " Now get the result of that diff cmd + silent exe "split ". tmpdiff + "echo "First line: " . getline(1) + "echo "tmp1: " . tmp1 + "echo "tmp1rx: " . tmp1rx + let s:DirDiffDiffOnlyLine = substitute( getline(1), tmp1rx . ".*$", "", '') + "echo "DirDiff Only: " . s:DirDiffDiffOnlyLine + + q + + " Now let's get the Differ string + "echo "Getting the diff in GetDiffStrings" + + silent exe "!echo testdifferent > \"" . tmp2 . s:sep . "test" . "\"" + silent exe "!diff -r --brief \"" . tmp1 . "\" \"" . tmp2 . "\" > \"" . tmpdiff . "\"" + + silent exe "split ". tmpdiff + let s:DirDiffDifferLine = substitute( getline(1), tmp1rx . ".*$", "", '') + " Note that the diff on cygwin may output '/' instead of '\' for the + " separator, so we need to accomodate for both cases + let andrx = "^.*" . tmp1rx . "[\\\/]test\\(.*\\)" . tmp2rx . "[\\\/]test.*$" + let endrx = "^.*" . tmp1rx . "[\\\/]test.*" . tmp2rx . "[\\\/]test\\(.*$\\)" + "echo "andrx : " . andrx + "echo "endrx : " . endrx + let s:DirDiffDifferAndLine = substitute( getline(1), andrx , "\\1", '') + let s:DirDiffDifferEndLine = substitute( getline(1), endrx, "\\1", '') + + "echo "s:DirDiffDifferLine = " . s:DirDiffDifferLine + "echo "s:DirDiffDifferAndLine = " . s:DirDiffDifferAndLine + "echo "s:DirDiffDifferEndLine = " . s:DirDiffDifferEndLine + + q + + " Delete tmp files + "echo "Deleting tmp files." + + call <SID>Delete(tmp1) + call <SID>Delete(tmp2) + call <SID>Delete(tmpdiff) + +endfunction diff --git a/plugin/EnhancedCommentify.vim b/plugin/EnhancedCommentify.vim deleted file mode 100644 index 1451373..0000000 --- a/plugin/EnhancedCommentify.vim +++ /dev/null @@ -1,1579 +0,0 @@ -" EnhancedCommentify.vim -" Maintainer: Meikel Brandmeyer <Brandels_Mikesh@web.de> -" Version: 2.2 -" Last Change: Monday, 27th September 2004 - -" License: -" Copyright (c) 2002,2003,2004 Meikel Brandmeyer, Kaiserslautern. -" All rights reserved. -" -" Redistribution and use in source and binary forms, with or without -" modification, are permitted provided that the following conditions are met: -" -" * Redistributions of source code must retain the above copyright notice, -" this list of conditions and the following disclaimer. -" * Redistributions in binary form must reproduce the above copyright notice, -" this list of conditions and the following disclaimer in the documentation -" and/or other materials provided with the distribution. -" * Neither the name of the author nor the names of its contributors may be -" used to endorse or promote products derived from this software without -" specific prior written permission. -" -" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -" DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -" Description: -" This is a (well... more or less) simple script to comment lines in a program. -" Currently supported languages are C, C++, PHP, the vim scripting -" language, python, HTML, Perl, LISP, Tex, Shell, CAOS and others. - -" Bugfixes: -" 2.2 -" Fixed problem with UseSyntax (thanks to Pieter Naaijkens) -" Fixed typo in ParseCommentsOp (commstr -> commStr). -" Fixed support for ocaml (thanks to Zhang Le) -" 2.1 -" Fixed problems with alignement when a line contains tabs -" Fixed (resp. cleaned up) issues with overrideEL (thanks to Steve Hall) -" Fixed problems with javascript detection (thanks to Brian Neu) -" Changed Buffer init to BufWinEnter in order to use the modelines. -" 2.0 -" Fixed invalid expression '\'' -> "'" (thanks to Zak Beck) -" Setting AltOpen/AltClose to '' (ie. disabling it) would -" insert '/*' resp. '*/' for character in a line (thanks to Ben Kibbey) -" 1.8 -" Backslashes in comment symbols should not be escaped. -" typo (commensSymbol -> commentSymbol) (thanks to Steve Butts) -" typo (== -> =) -" Fixed hardwired '|+'-'+|' pair. -" 1.7 -" Lines were not correctly decommentified, when there was whitespace -" at the beginning of the line. (thanks to Xiangjiang Ma) -" Fixed error detecting '*sh' filetypes. -" 1.3 -" hlsearch was set unconditionally (thanks to Mary Ellen Foster) -" made function silent (thanks to Mare Ellen Foster) - -" Changelog: -" 2.2 -" Added possibility to override the modes, in which keybindings are -" defined. -" Keybindings may be defined local to every buffer now. -" If a filetype is unknown, one can turn off the keybindings now. -" 2.1 -" Removed any cursor movement. The script should now be free of -" side-effects. -" The script now uses &commentstring to determine the right -" comment strings. Fallback is still the ugly if-thingy. -" Script can now interpret &comments in order to add a middle -" string in blocks. -" Added EnhancedCommentifySet for use by other scripts. (Necessary?) -" Added MultiPartBlocks for languages with multipart-comments. -" Added parsing for comments option if using MultiPartBlocks. -" 2.0 -" IMPORTANT: EnhancedCommentify is now licensed under BSD license -" for distribution with Cream! However this shouldn't -" change anything... -" useBlockIndent does no longer depend on respectIndent. -" Added code to cope with 'C' in '&cpo'. (thanks to Luc Hermitte -" for pointing this out!) -" Added EnhCommentifyIdentFrontOnly option. -" All options are now handled on a per buffer basis. So options -" can be overriden for different buffers. -" 1.9 -" Filetype is now recognized via regular expressions. -" All known filetypes are (more or less) supported. -" Decomments multipart-block comments. -" Added RespectIndent, AlignRight and synID-guessing. -" Switched to buffer variables. -" 1.8 -" Added Ada support. (thanks to Preben Randhol) -" Added Latte support. -" Added blocksupport and possibility to specify action (comment or -" decomment). It's also possible to guess the action line by line or -" using the first line of a block. -" Thanks to Xiangjiang Ma and John Orr for the rich feedback on these -" issues. -" Decomments /*foo();*/, when PrettyComments is set. -" Added 'vhdl' and 'verilog'. (thanks to Steve Butts) -" 1.7 -" Added different options to control behaviour of the plugin. -" Changed default Keybindings to proper plugin settings. -" 1.6 -" Now supports 'm4', 'config', 'automake' -" 'vb', 'aspvbs', 'plsql' (thanks to Zak Beck) -" 1.5 -" Now supports 'java', 'xml', 'jproperties'. (thanks to Scott Stirling) -" 1.4 -" Lines containing only whitespace are now considered empty. -" Added Tcl support. -" Multipart comments are now escaped with configurable alternative -" strings. Prevents nesting errors (eg. /**/*/ in C) -" 1.3 -" Doesn't break lines like -" foo(); /* bar */ -" when doing commentify. - -" Install Details: -" Simply drop this file into your $HOME/.vim/plugin directory. - -if exists("DidEnhancedCommentify") - finish -endif -let DidEnhancedCommentify = 1 - -let s:savedCpo = &cpo -set cpo-=C - -" Note: These must be defined here, since they are used during -" initialisation. -" -" InitBooleanVariable(confVar, scriptVar, defaultVal) -" confVar -- name of the configuration variable -" scriptVar -- name of the variable to set -" defaultVal -- default value -" -" Tests on existence of configuration variable and sets scriptVar -" according to its contents. -" -function s:InitBooleanVariable(confVar, scriptVar, defaultVal) - let regex = a:defaultVal ? 'no*' : 'ye*s*' - - if exists(a:confVar) && {a:confVar} =~? regex - let {a:scriptVar} = !a:defaultVal - else - let {a:scriptVar} = a:defaultVal - endif -endfunction - -" -" InitStringVariable(confVar, scriptVar, defaultVal) -" confVar -- name of the configuration variable -" scriptVar -- name of the variable to set -" defaultVal -- default value -" -" Tests on existence of configuration variable and sets scriptVar -" to its contents. -" -function s:InitStringVariable(confVar, scriptVar, defaultVal) - if exists(a:confVar) - execute "let ". a:scriptVar ." = ". a:confVar - else - let {a:scriptVar} = a:defaultVal - endif -endfunction - -" -" InitScriptVariables(nameSpace) -" nameSpace -- may be "g" for global or "b" for local -" -" Initialises the script variables. -" -function s:InitScriptVariables(nameSpace) - let ns = a:nameSpace " just for abbreviation - let lns = (ns == "g") ? "s" : "b" " 'local namespace' - - " Comment escape strings... - call s:InitStringVariable(ns .":EnhCommentifyAltOpen", lns .":ECaltOpen", - \ s:ECaltOpen) - call s:InitStringVariable(ns .":EnhCommentifyAltClose", lns .":ECaltClose", - \ s:ECaltClose) - - call s:InitBooleanVariable(ns .":EnhCommentifyIgnoreWS", lns .":ECignoreWS", - \ s:ECignoreWS) - - " Adding a space between comment strings and code... - if exists(ns .":EnhCommentifyPretty") - if {ns}:EnhCommentifyPretty =~? 'ye*s*' - let {lns}:ECprettyComments = ' ' - let {lns}:ECprettyUnComments = ' \=' - else - let {lns}:ECprettyComments = '' - let {lns}:ECprettyUnComments = '' - endif - else - let {lns}:ECprettyComments = s:ECprettyComments - let {lns}:ECprettyUnComments = s:ECprettyUnComments - endif - - " Identification string settings... - call s:InitStringVariable(ns .":EnhCommentifyIdentString", - \ lns .":ECidentFront", s:ECidentFront) - let {lns}:ECidentBack = - \ (exists(ns .":EnhCommentifyIdentFrontOnly") - \ && {ns}:EnhCommentifyIdentFrontOnly =~? 'ye*s*') - \ ? '' - \ : {lns}:ECidentFront - - " Wether to use syntax items... - call s:InitBooleanVariable(ns .":EnhCommentifyUseSyntax", - \ lns .":ECuseSyntax", s:ECuseSyntax) - - " Should the script respect line indentation, when inserting strings? - call s:InitBooleanVariable(ns .":EnhCommentifyRespectIndent", - \ lns .":ECrespectIndent", s:ECrespectIndent) - - " Keybindings... - call s:InitBooleanVariable(ns .":EnhCommentifyUseAltKeys", - \ lns .":ECuseAltKeys", s:ECuseAltKeys) - call s:InitBooleanVariable(ns .":EnhCommentifyBindPerBuffer", - \ lns .":ECbindPerBuffer", s:ECbindPerBuffer) - call s:InitBooleanVariable(ns .":EnhCommentifyBindInNormal", - \ lns .":ECbindInNormal", s:ECbindInNormal) - call s:InitBooleanVariable(ns .":EnhCommentifyBindInInsert", - \ lns .":ECbindInInsert", s:ECbindInInsert) - call s:InitBooleanVariable(ns .":EnhCommentifyBindInVisual", - \ lns .":ECbindInVisual", s:ECbindInVisual) - call s:InitBooleanVariable(ns .":EnhCommentifyUserBindings", - \ lns .":ECuserBindings", s:ECuserBindings) - call s:InitBooleanVariable(ns .":EnhCommentifyTraditionalMode", - \ lns .":ECtraditionalMode", s:ECtraditionalMode) - call s:InitBooleanVariable(ns .":EnhCommentifyFirstLineMode", - \ lns .":ECfirstLineMode", s:ECfirstLineMode) - call s:InitBooleanVariable(ns .":EnhCommentifyUserMode", - \ lns .":ECuserMode", s:ECuserMode) - call s:InitBooleanVariable(ns .":EnhCommentifyBindUnknown", - \ lns .":ECbindUnknown", s:ECbindUnknown) - - " Block stuff... - call s:InitBooleanVariable(ns .":EnhCommentifyAlignRight", - \ lns .":ECalignRight", s:ECalignRight) - call s:InitBooleanVariable(ns .":EnhCommentifyUseBlockIndent", - \ lns .":ECuseBlockIndent", s:ECuseBlockIndent) - call s:InitBooleanVariable(ns .":EnhCommentifyMultiPartBlocks", - \ lns .":ECuseMPBlock", s:ECuseMPBlock) - call s:InitBooleanVariable(ns .":EnhCommentifyCommentsOp", - \ lns .":ECuseCommentsOp", s:ECuseCommentsOp) - - let {lns}:ECsaveWhite = ({lns}:ECrespectIndent - \ || {lns}:ECignoreWS || {lns}:ECuseBlockIndent) - \ ? '\(\s*\)' - \ : '' - - if !{lns}:ECrespectIndent - let {lns}:ECuseBlockIndent = 0 - endif - - if {lns}:ECrespectIndent - let {lns}:ECrespectWhite = '\1' - let {lns}:ECignoreWhite = '' - elseif {lns}:ECignoreWS - let {lns}:ECrespectWhite = '' - let {lns}:ECignoreWhite = '\1' - else - let {lns}:ECrespectWhite = '' - let {lns}:ECignoreWhite = '' - endif - - " Using comments option, doesn't make sense without useMPBlock - "if lns == 'b' && b:ECuseCommentsOp - " let b:ECuseMPBlock = 1 - "endif -endfunction - -" -" EnhancedCommentifySet(option, value, ...) -" option -- which option -" value -- value which will be asigned to the option -" -" The purpose of this function is mainly to act as an interface to the -" outer world. It hides the internally used variables. -" -function EnhancedCommentifySet(option, value) - if a:option == 'AltOpen' - let oldval = b:ECaltOpen - let b:ECaltOpen = a:value - elseif a:option == 'AltClose' - let oldval = b:ECaltClose - let b:ECaltClose = a:value - elseif a:option == 'IdentString' - let oldval = b:ECidentFront - let b:ECidentFront = a:value - elseif a:option == 'IdentFrontOnly' - let oldval = (b:ECidentBack == '') ? 'Yes' : 'No' - let b:ECidentBack = (a:value =~? 'ye*s*') ? '' : b:ECidentFront - elseif a:option == 'RespectIndent' - let oldval = b:ECrespectIndent - let b:ECrespectIndent = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'IgnoreWS' - let oldval = b:ECignoreWS - let b:ECignoreWS = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'Pretty' - let oldval = (b:ECprettyComments == ' ') ? 'Yes' : 'No' - if a:value =~? 'ye*s*' - let b:ECprettyComments = ' ' - let b:ECprettyUnComments = ' \=' - else - let b:ECprettyComments = '' - let b:ECprettyUnComments = '' - endif - elseif a:option == 'MultiPartBlocks' - let oldval = b:ECuseMPBlock - let b:ECuseMPBlock = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'CommentsOp' - let oldval = b:ECuseCommentsOp - let b:ECuseCommentsOp = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'UseBlockIndent' - let oldval = b:ECuseBlockIndent - let b:ECuseBlockIndent = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'AlignRight' - let oldval = b:ECalignRight - let b:ECalignRight = (a:value =~? 'ye*s*') ? 1 : 0 - elseif a:option == 'UseSyntax' - let oldval = b:ECuseSyntax - let b:ECuseSyntax = (a:value =~? 'ye*s*') ? 1 : 0 - else - if (has("dialog_gui") && has("gui_running")) - call confirm("EnhancedCommentifySet: Unknwon option '" - \ . option . "'") - else - echohl ErrorMsg - echo "EnhancedCommentifySet: Unknown option '". option ."'" - echohl None - endif - endif - - if oldval == 1 - let oldval = 'Yes' - elseif oldval == 0 - let oldval = 'No' - endif - - return oldval -endfunction - -" Initial settings. -" -" Setting the default options resp. taking user preferences. -if !exists("g:EnhCommentifyUserMode") - \ && !exists("g:EnhCommentifyFirstLineMode") - \ && !exists("g:EnhCommentifyTraditionalMode") - \ && !exists("g:EnhCommentifyUserBindings") - let g:EnhCommentifyTraditionalMode = 'Yes' -endif - -" These will be the default settings for the script: -let s:ECaltOpen = "|+" -let s:ECaltClose = "+|" -let s:ECignoreWS = 1 -let s:ECprettyComments = '' -let s:ECprettyUnComments = '' -let s:ECidentFront = '' -let s:ECuseSyntax = 0 -let s:ECrespectIndent = 0 -let s:ECalignRight = 0 -let s:ECuseBlockIndent = 0 -let s:ECuseMPBlock = 0 -let s:ECuseCommentsOp = 0 -let s:ECuseAltKeys = 0 -let s:ECbindPerBuffer = 0 -let s:ECbindInNormal = 1 -let s:ECbindInInsert = 1 -let s:ECbindInVisual = 1 -let s:ECuserBindings = 0 -let s:ECtraditionalMode = 0 -let s:ECfirstLineMode = 0 -let s:ECuserMode = 1 -let s:ECbindUnknown = 1 - -" Now initialise the global defaults with the preferences set -" by the user in his .vimrc. Settings local to a buffer will be -" done later on, when the script is first called in a buffer. -" -call s:InitScriptVariables("g") - -" Globally used variables with some initialisation. -" FIXME: explain what they are good for -" -let s:Action = 'guess' -let s:firstOfBlock = 1 -let s:blockAction = 'comment' -let s:blockIndentRegex = '' -let s:blockIndent = 0 -let s:inBlock = 0 -let s:tabConvert = '' -let s:overrideEmptyLines = 0 -let s:emptyLines = 'no' -let s:maxLen = 0 - -function EnhancedCommentifyInitBuffer() - if !exists("b:ECdidBufferInit") - call s:InitScriptVariables("b") - - if !exists("b:EnhCommentifyFallbackTest") - let b:EnhCommentifyFallbackTest = 0 - endif - - call s:GetFileTypeSettings(&ft) - call s:CheckPossibleEmbedding(&ft) - - " - " If the filetype is not supported and the user wants us to, we do not - " add keybindings. - " - if s:ECbindPerBuffer - if b:ECcommentOpen != "" || b:ECbindUnknown - call s:SetKeybindings("l") - endif - endif - - let b:ECdidBufferInit = 1 - let b:ECsyntax = &ft - endif -endfunction - -autocmd BufWinEnter,BufNewFile * call EnhancedCommentifyInitBuffer() - -" -" EnhancedCommentify(emptyLines, action, ...) -" overrideEL -- commentify empty lines -" may be 'yes', 'no' or '' for guessing -" action -- action which should be executed: -" * guess: -" toggle commetification (old behaviour) -" * comment: -" comment lines -" * decomment: -" decomment lines -" * first: -" use first line of block to determine action -" a:1, a:2 -- first and last line of block, which should be -" processed. -" -" Commentifies the current line. -" -function EnhancedCommentify(overrideEL, action, ...) - if a:overrideEL != '' - let s:overrideEmptyLines = 1 - endif - - " Now do the buffer initialisation. Every buffer will get - " it's pendant to a global variable (eg. s:ECalignRight -> b:ECalignRight). - " The local variable is actually used, whereas the global variable - " holds the defaults from the user's .vimrc. In this way the settings - " can be overriden for single buffers. - " - " NOTE: Buffer init is done by autocommands now. - " - - let b:ECemptyLines = a:overrideEL - - " The language is not supported. - if b:ECcommentOpen == '' - if (has("dialog_gui") && has("gui_running")) - call confirm("This filetype is currently _not_ supported!\n" - \ ."Please consider contacting the author in order" - \ ." to add this filetype.", "", 1, "Error") - else - echohl ErrorMsg - echo "This filetype is currently _not_ supported!" - echo "Please consider contacting the author in order to add" - echo "this filetype in future releases!" - echohl None - endif - return - endif - - let lnum = line(".") - - " Now some initialisations... - let s:Action = a:action - - " FIXME: Is there really _no_ function to simplify this??? - " (Maybe something like 'let foo = 8x" "'?) - if s:tabConvert == '' && strlen(s:tabConvert) != &tabstop - let s:tabConvert = '' - let i = 0 - while i < &tabstop - let s:tabConvert = s:tabConvert .' ' - let i = i + 1 - endwhile - endif - - if a:0 == 2 - let s:startBlock = a:1 - let s:i = a:1 - let s:endBlock = a:2 - - let s:inBlock = 1 - else - let s:startBlock = lnum - let s:i = lnum - let s:endBlock = lnum - - let s:inBlock = 0 - endif - - if b:ECuseSyntax && b:ECpossibleEmbedding - let column = indent(s:startBlock) + 1 - if !&expandtab - let rem = column % &tabstop - let column = ((column - rem) / &tabstop) + rem - endif - call s:CheckSyntax(s:startBlock, column) - endif - - " Get the indent of the less indented line of the block. - if s:inBlock && (b:ECuseBlockIndent || b:ECalignRight) - call s:DoBlockComputations(s:startBlock, s:endBlock) - endif - - while s:i <= s:endBlock - let lineString = getline(s:i) - let lineString = s:TabsToSpaces(lineString) - - " If we should comment "empty" lines, we have to add - " the correct indent, if we use blockIndent. - if b:ECemptyLines =~? 'ye*s*' - \ && b:ECuseBlockIndent - \ && lineString =~ "^\s*$" - let i = 0 - while i < s:blockIndent - let lineString = " " . lineString - let i = i + 1 - endwhile - endif - - " Don't comment empty lines. - if lineString !~ "^\s*$" - \ || b:ECemptyLines =~? 'ye*s*' - if b:ECcommentClose != '' - let lineString = s:CommentifyMultiPart(lineString, - \ b:ECcommentOpen, - \ b:ECcommentClose, - \ b:ECcommentMiddle) - else - let lineString = s:CommentifySinglePart(lineString, - \ b:ECcommentOpen) - endif - endif - - " Revert the above: If the line is "empty" and we - " used blockIndent, we remove the spaces. - " FIXME: Why does "^\s*$" not work? - if b:ECemptyLines =~? 'ye*s*' - \ && b:ECuseBlockIndent - \ && lineString =~ "^" . s:blockIndentRegex ."\s*$" - let lineString = - \ substitute(lineString, s:blockIndentRegex, - \ '', '') - endif - - let lineString = s:SpacesToTabs(lineString) - call setline(s:i, lineString) - - let s:i = s:i + 1 - let s:firstOfBlock = 0 - endwhile - - let s:firstOfBlock = 1 -endfunction - -" -" DoBlockComputations(start, end) -" start -- number of first line -" end -- number of last line -" -" This function does some computations which are necessary for useBlockIndent -" and alignRight. ie. find smallest indent and longest line. -" -function s:DoBlockComputations(start, end) - let i = a:start - let len = 0 - let amount = 100000 " this should be enough ... - - while i <= a:end - if b:ECuseBlockIndent && getline(i) !~ '^\s*$' - let cur = indent(i) - if cur < amount - let amount = cur - endif - endif - - if b:ECalignRight - let cur = s:GetLineLen(s:TabsToSpaces(getline(i)), - \ s:GetLineLen(b:ECcommentOpen, 0) - \ + strlen(b:ECprettyComments)) - if b:ECuseMPBlock - let cur = cur + s:GetLineLen(b:ECcommentOpen, 0) - \ + strlen(b:ECprettyComments) - endif - - if len < cur - let len = cur - endif - endif - - let i = i + 1 - endwhile - - if b:ECuseBlockIndent - if amount > 0 - let regex = '\( \{'. amount .'}\)' - else - let regex = '' - endif - let s:blockIndentRegex = regex - let s:blockIndent = amount - endif - - if b:ECalignRight - let s:maxLen = len - endif -endfunction - -" -" CheckSyntax(line, column) -" line -- line of line -" column -- column of line -" Check what syntax is active during call of main function. First hit -" wins. If the filetype changes during the block, we ignore that. -" Adjust the filetype if necessary. -" -function s:CheckSyntax(line, column) - let ft = "" - let synFiletype = synIDattr(synID(a:line, a:column, 1), "name") - - " FIXME: This feature currently relies on a certain format - " of the names of syntax items: the filetype must be prepended - " in lowwer case letters, followed by at least one upper case - " letter. - if match(synFiletype, '\l\+\u') == 0 - let ft = substitute(synFiletype, '^\(\l\+\)\u.*$', '\1', "") - endif - - if ft == "" - execute "let specialCase = ". b:EnhCommentifyFallbackTest - - if specialCase - let ft = b:EnhCommentifyFallbackValue - else - " Fallback: If nothing holds, use normal filetype! - let ft = &ft - endif - endif - - " Nothing changed! - if ft == b:ECsyntax - return - endif - - let b:ECsyntax = ft - call s:GetFileTypeSettings(ft) -endfunction - -" -" GetFileTypeSettings(ft) -" ft -- filetype -" -" This functions sets some buffer-variables, which control the comment -" strings and 'empty lines'-handling. -" -function s:GetFileTypeSettings(ft) - let fileType = a:ft - - " I learned about the commentstring option. Let's use it. - " For now we ignore it, if it is "/*%s*/". This is the - " default. We cannot check wether this is default or C or - " something other like CSS, etc. We have to wait, until the - " filetypes adopt this option. - if &commentstring != "/*%s*/" && !b:ECuseSyntax - let b:ECcommentOpen = - \ substitute(&commentstring, '%s.*', "", "") - let b:ECcommentClose = - \ substitute(&commentstring, '.*%s', "", "") - " Multipart comments: - elseif fileType =~ '^\(c\|b\|css\|csc\|cupl\|indent\|jam\|lex\|lifelines\|'. - \ 'lite\|nqc\|phtml\|progress\|rexx\|rpl\|sas\|sdl\|sl\|'. - \ 'strace\|xpm\|yacc\)$' - let b:ECcommentOpen = '/*' - let b:ECcommentClose = '*/' - elseif fileType =~ '^\(html\|xml\|dtd\|sgmllnx\)$' - let b:ECcommentOpen = '<!--' - let b:ECcommentClose = '-->' - elseif fileType =~ '^\(sgml\|smil\)$' - let b:ECcommentOpen = '<!' - let b:ECcommentClose = '>' - elseif fileType == 'atlas' - let b:ECcommentOpen = 'C' - let b:ECcommentClose = '$' - elseif fileType =~ '^\(catalog\|sgmldecl\)$' - let b:ECcommentOpen = '--' - let b:ECcommentClose = '--' - elseif fileType == 'dtml' - let b:ECcommentOpen = '<dtml-comment>' - let b:ECcommentClose = '</dtml-comment>' - elseif fileType == 'htmlos' - let b:ECcommentOpen = '#' - let b:ECcommentClose = '/#' - elseif fileType =~ '^\(jgraph\|lotos\|mma\|modula2\|modula3\|pascal\|'. - \ 'ocaml\|sml\)$' - let b:ECcommentOpen = '(*' - let b:ECcommentClose = '*)' - elseif fileType == 'jsp' - let b:ECcommentOpen = '<%--' - let b:ECcommentClose = '--%>' - elseif fileType == 'model' - let b:ECcommentOpen = '$' - let b:ECcommentClose = '$' - elseif fileType == 'st' - let b:ECcommentOpen = '"' - let b:ECcommentClose = '"' - elseif fileType =~ '^\(tssgm\|tssop\)$' - let b:ECcommentOpen = 'comment = "' - let b:ECcommentClose = '"' - " Singlepart comments: - elseif fileType =~ '^\(ox\|cpp\|php\|java\|verilog\|acedb\|ch\|clean\|'. - \ 'clipper\|cs\|dot\|dylan\|hercules\|idl\|ishd\|javascript\|'. - \ 'kscript\|mel\|named\|openroad\|pccts\|pfmain\|pike\|'. - \ 'pilrc\|plm\|pov\|rc\|scilab\|specman\|tads\|tsalt\|uc\|'. - \ 'xkb\)$' - let b:ECcommentOpen = '//' - let b:ECcommentClose = '' - elseif fileType =~ '^\(vim\|abel\)$' - let b:ECcommentOpen = '"' - let b:ECcommentClose = '' - elseif fileType =~ '^\(lisp\|scheme\|scsh\|amiga\|asm\|asm68k\|bindzone\|'. - \ 'def\|dns\|dosini\|dracula\|dsl\|idlang\|iss\|jess\|kix\|'. - \ 'masm\|monk\|nasm\|ncf\|omnimark\|pic\|povini\|rebol\|'. - \ 'registry\|samba\|skill\|smith\|tags\|tasm\|tf\|winbatch\|'. - \ 'wvdial\|z8a\)$' - let b:ECcommentOpen = ';' - let b:ECcommentClose = '' - elseif fileType =~ '^\(python\|perl\|[^w]*sh$\|tcl\|jproperties\|make\|'. - \ 'robots\|apacha\|apachestyle\|awk\|bc\|cfg\|cl\|conf\|'. - \ 'crontab\|diff\|ecd\|elmfilt\|eterm\|expect\|exports\|'. - \ 'fgl\|fvwm\|gdb\|gnuplot\|gtkrc\|hb\|hog\|ia64\|icon\|'. - \ 'inittab\|lftp\|lilo\|lout\|lss\|lynx\|maple\|mush\|'. - \ 'muttrc\|nsis\|ora\|pcap\|pine\|po\|procmail\|'. - \ 'psf\|ptcap\|r\|radiance\|ratpoison\|readline\remind\|'. - \ 'ruby\|screen\|sed\|sm\|snnsnet\|snnspat\|snnsres\|spec\|'. - \ 'squid\|terminfo\|tidy\|tli\|tsscl\|vgrindefs\|vrml\|'. - \ 'wget\|wml\|xf86conf\|xmath\)$' - let b:ECcommentOpen = '#' - let b:ECcommentClose = '' - elseif fileType == 'webmacro' - let b:ECcommentOpen = '##' - let b:ECcommentClose = '' - elseif fileType == 'ppwiz' - let b:ECcommentOpen = ';;' - let b:ECcommentClose = '' - elseif fileType == 'latte' - let b:ECcommentOpen = '\\;' - let b:ECcommentClose = '' - elseif fileType =~ '^\(tex\|abc\|erlang\|ist\|lprolog\|matlab\|mf\|'. - \ 'postscr\|ppd\|prolog\|simula\|slang\|slrnrc\|slrnsc\|'. - \ 'texmf\|virata\)$' - let b:ECcommentOpen = '%' - let b:ECcommentClose = '' - elseif fileType =~ '^\(caos\|cterm\|form\|foxpro\|sicad\|snobol4\)$' - let b:ECcommentOpen = '*' - let b:ECcommentClose = '' - elseif fileType =~ '^\(m4\|config\|automake\)$' - let b:ECcommentOpen = 'dnl ' - let b:ECcommentClose = '' - elseif fileType =~ '^\(vb\|aspvbs\|ave\|basic\|elf\|lscript\)$' - let b:ECcommentOpen = "'" - let b:ECcommentClose = '' - elseif fileType =~ '^\(plsql\|vhdl\|ahdl\|ada\|asn\|csp\|eiffel\|gdmo\|'. - \ 'haskell\|lace\|lua\|mib\|sather\|sql\|sqlforms\|sqlj\|'. - \ 'stp\)$' - let b:ECcommentOpen = '--' - let b:ECcommentClose = '' - elseif fileType == 'abaqus' - let b:ECcommentOpen = '**' - let b:ECcommentClose = '' - elseif fileType =~ '^\(aml\|natural\|vsejcl\)$' - let b:ECcommentOpen = '/*' - let b:ECcommentClose = '' - elseif fileType == 'ampl' - let b:ECcommentOpen = '\\#' - let b:ECcommentClose = '' - elseif fileType == 'bdf' - let b:ECcommentOpen = 'COMMENT ' - let b:ECcommentClose = '' - elseif fileType == 'btm' - let b:ECcommentOpen = '::' - let b:ECcommentClose = '' - elseif fileType == 'dcl' - let b:ECcommentOpen = '$!' - let b:ECcommentClose = '' - elseif fileType == 'dosbatch' - let b:ECcommentOpen = 'rem ' - let b:ECcommentClose = '' - elseif fileType == 'focexec' - let b:ECcommentOpen = '-*' - let b:ECcommentClose = '' - elseif fileType == 'forth' - let b:ECcommentOpen = '\\ ' - let b:ECcommentClose = '' - elseif fileType =~ '^\(fortran\|inform\|sqr\|uil\|xdefaults\|'. - \ 'xmodmap\|xpm2\)$' - let b:ECcommentOpen = '!' - let b:ECcommentClose = '' - elseif fileType == 'gp' - let b:ECcommentOpen = '\\\\' - let b:ECcommentClose = '' - elseif fileType =~ '^\(master\|nastran\|sinda\|spice\|tak\|trasys\)$' - let b:ECcommentOpen = '$' - let b:ECcommentClose = '' - elseif fileType == 'nroff' || fileType == 'groff' - let b:ECcommentOpen = ".\\\\\"" - let b:ECcommentClose = '' - elseif fileType == 'opl' - let b:ECcommentOpen = 'REM ' - let b:ECcommentClose = '' - elseif fileType == 'texinfo' - let b:ECcommentOpen = '@c ' - let b:ECcommentClose = '' - else - let b:ECcommentOpen = '' - let b:ECcommentClose = '' - endif - - if b:ECuseCommentsOp - let b:ECcommentMiddle = - \ s:ParseCommentsOp(b:ECcommentOpen, b:ECcommentClose) - if b:ECcommentMiddle == '' - let b:ECuseCommentsOp = 0 - endif - else - let b:ECcommentMiddle = '' - endif - - if !s:overrideEmptyLines - call s:CommentEmptyLines(fileType) - endif -endfunction - -" -" ParseCommentsOp(commentOpen, commentClose) -" commentOpen -- comment-open string -" commentClose-- comment-close string -" -" Try to extract the middle comment string from &comments. First hit wins. -" If nothing is found '' is returned. -" -function s:ParseCommentsOp(commentOpen, commentClose) - let commStr = &comments - let offset = 0 - let commentMiddle = '' - - while commStr != '' - " - " First decompose &omments into consecutive s-, m- and e-parts. - " - let s = stridx(commStr, 's') - if s == -1 - return '' - endif - - let commStr = strpart(commStr, s) - let comma = stridx(commStr, ',') - if comma == -1 - return '' - endif - let sPart = strpart(commStr, 0, comma) - - let commStr = strpart(commStr, comma) - let m = stridx(commStr, 'm') - if m == -1 - return '' - endif - - let commStr = strpart(commStr, m) - let comma = stridx(commStr, ',') - if comma == -1 - return '' - endif - let mPart = strpart(commStr, 0, comma) - - let commStr = strpart(commStr, comma) - let e = stridx(commStr, 'e') - if e == -1 - return '' - endif - - let commStr = strpart(commStr, e) - let comma = stridx(commStr, ',') - if comma == -1 - let comma = strlen(commStr) - endif - let ePart = strpart(commStr, 0, comma) - - let commStr = strpart(commStr, comma) - - " - " Now check wether this is what we want: - " Are the comment string the same? - " - let sColon = stridx(sPart, ':') - let eColon = stridx(ePart, ':') - if sColon == -1 || eColon == -1 - return '' - endif - if strpart(sPart, sColon + 1) != a:commentOpen - \ || strpart(ePart, eColon + 1) != a:commentClose - continue - endif - - let mColon = stridx(mPart, ':') - if mColon == -1 - return '' - endif - let commentMiddle = strpart(mPart, mColon + 1) - - " - " Check for any alignement. - " - let i = 1 - while sPart[i] != ':' - if sPart[i] == 'r' - let offset = strlen(a:commentOpen) - strlen(commentMiddle) - break - elseif sPart[i] == 'l' - let offset = 0 - break - elseif s:isDigit(sPart[i]) - let j = 1 - while s:isDigit(sPart[i + j]) - let j = j + 1 - endwhile - let offset = 1 * strpart(sPart, i, j) - break - endif - let i = i + 1 - endwhile - - if offset == 0 - let i = 1 - while ePart[i] != ':' - if ePart[i] == 'r' - let offset = strlen(a:commentClose) - strlen(commentMiddle) - break - elseif ePart[i] == 'l' - let offset = 0 - break - elseif s:isDigit(ePart[i]) - let j = 1 - while s:isDigit(ePart[i + j]) - let j = j + 1 - endwhile - let offset = 1 * strpart(ePart, i, j) - break - endif - - let i = i + 1 - endwhile - endif - - while offset > 0 - let commentMiddle = " " . commentMiddle - let offset = offset - 1 - endwhile - - break - endwhile - - return commentMiddle -endfunction - -" -" isDigit(char) -" -" Nomen est Omen. -" -function s:isDigit(char) - let r = 0 - - let charVal = char2nr(a:char) - - if charVal >= 48 && charVal <= 57 - let r = 1 - endif - - return r -endfunction - -" -" CommentEmptyLines(ft) -" ft -- filetype of current buffer -" -" Decides, if empty lines should be commentified or not. Add the filetype, -" you want to change, to the apropriate if-clause. -" -function s:CommentEmptyLines(ft) - " FIXME: Quick hack (tm)! - if 0 - " Add special filetypes here. - elseif b:ECcommentClose == '' - let b:ECemptyLines = 'yes' - else - let b:ECemptyLines = 'no' - endif -endfunction - -" -" CheckPossibleEmbedding(ft) -" ft -- the filetype of current buffer -" -" Check wether it makes sense to allow checking for the synIDs. -" Eg. C will never have embedded code... -" -function s:CheckPossibleEmbedding(ft) - if a:ft =~ '^\(php\|vim\|latte\|html\)$' - let b:ECpossibleEmbedding = 1 - else - " Since getting the synID is slow, we set the default to 'no'! - " There are also some 'broken' languages like the filetype for - " autoconf's configure.in's ('config'). - let b:ECpossibleEmbedding = 0 - endif -endfunction - -" -" CommentifyMultiPart(lineString, commentStart, commentEnd, action) -" lineString -- line to commentify -" commentStart -- comment-start string, eg '/*' -" commentEnd -- comment-end string, eg. '*/' -" commentMiddle -- comment-middle string, eg. ' *' -" -" This function commentifies code of languages, which have multipart -" comment strings, eg. '/*' - '*/' of C. -" -function s:CommentifyMultiPart(lineString, commentStart, - \ commentEnd, commentMiddle) - if s:Action == 'guess' || s:Action == 'first' || b:ECuseMPBlock - let todo = s:DecideWhatToDo(a:lineString, a:commentStart, a:commentEnd) - else - let todo = s:Action - endif - - if todo == 'decomment' - return s:UnCommentify(a:lineString, a:commentStart, - \ a:commentEnd, a:commentMiddle) - else - return s:Commentify(a:lineString, a:commentStart, - \ a:commentEnd, a:commentMiddle) - endif -endfunction - -" -" CommentifySinglePart(lineString, commentSymbol) -" lineString -- line to commentify -" commentSymbol -- comment string, eg '#' -" -" This function is used for all languages, whose comment strings -" consist only of one string at the beginning of a line. -" -function s:CommentifySinglePart(lineString, commentSymbol) - if s:Action == 'guess' || s:Action == 'first' - let todo = s:DecideWhatToDo(a:lineString, a:commentSymbol) - else - let todo = s:Action - endif - - if todo == 'decomment' - return s:UnCommentify(a:lineString, a:commentSymbol) - else - return s:Commentify(a:lineString, a:commentSymbol) - endif -endfunction - -" -" Escape(lineString, commentStart, commentEnd) -" -" Escape already present symbols. -" -function s:Escape(lineString, commentStart, commentEnd) - let line = a:lineString - - if b:ECaltOpen != '' - let line = substitute(line, s:EscapeString(a:commentStart), - \ b:ECaltOpen, "g") - endif - if b:ECaltClose != '' - let line = substitute(line, s:EscapeString(a:commentEnd), - \ b:ECaltClose, "g") - endif - - return line -endfunction - -" -" UnEscape(lineString, commentStart, commentEnd) -" -" Unescape already present escape symbols. -" -function s:UnEscape(lineString, commentStart, commentEnd) - let line = a:lineString - - if b:ECaltOpen != '' - let line = substitute(line, s:EscapeString(b:ECaltOpen), - \ a:commentStart, "g") - endif - if b:ECaltClose != '' - let line = substitute(line, s:EscapeString(b:ECaltClose), - \ a:commentEnd, "g") - endif - - return line -endfunction - -" -" Commentify(lineString, commentSymbol, [commentEnd]) -" lineString -- the line in work -" commentSymbol -- string to insert at the beginning of the line -" commentEnd -- string to insert at the end of the line -" may be omitted -" -" This function inserts the start- (and if given the end-) string of the -" comment in the current line. -" -function s:Commentify(lineString, commentSymbol, ...) - let line = a:lineString - let j = 0 - - " If a end string is present, insert it too. - if a:0 > 0 - " First we have to escape any comment already contained in the line, - " since (at least for C) comments are not allowed to nest. - let line = s:Escape(line, a:commentSymbol, a:1) - - if b:ECuseCommentsOp && b:ECuseMPBlock - \ && a:0 > 1 - \ && s:i > s:startBlock - let line = substitute(line, s:LookFor('commentmiddle'), - \ s:SubstituteWith('commentmiddle', a:2), "") - endif - - if !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:endBlock) - " Align the closing part to the right. - if b:ECalignRight && s:inBlock - let len = s:GetLineLen(line, strlen(a:commentSymbol) - \ + strlen(b:ECprettyComments)) - while j < s:maxLen - len - let line = line .' ' - let j = j + 1 - endwhile - endif - - let line = substitute(line, s:LookFor('commentend'), - \ s:SubstituteWith('commentend', a:1), "") - endif - endif - - " insert the comment symbol - if !b:ECuseMPBlock || a:0 == 0 || (b:ECuseMPBlock && s:i == s:startBlock) - let line = substitute(line, s:LookFor('commentstart'), - \ s:SubstituteWith('commentstart', a:commentSymbol), "") - endif - - return line -endfunction - -" -" UnCommentify(lineString, commentSymbol, [commentEnd]) -" lineString -- the line in work -" commentSymbol -- string to remove at the beginning of the line -" commentEnd -- string to remove at the end of the line -" may be omitted -" -" This function removes the start- (and if given the end-) string of the -" comment in the current line. -" -function s:UnCommentify(lineString, commentSymbol, ...) - let line = a:lineString - - " remove the first comment symbol found on a line - if a:0 == 0 || !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:startBlock) - let line = substitute(line, s:LookFor('decommentstart', - \ a:commentSymbol), - \ s:SubstituteWith('decommentstart'), "") - endif - - " If a end string is present, we have to remove it, too. - if a:0 > 0 - " First, we remove the trailing comment symbol. - if !b:ECuseMPBlock || (b:ECuseMPBlock && s:i == s:endBlock) - let line = substitute(line, s:LookFor('decommentend', a:1), - \ s:SubstituteWith('decommentend'), "") - - " Remove any trailing whitespace, if we used alignRight. - if b:ECalignRight - let line = substitute(line, ' *$', '', "") - endif - endif - - " Maybe we added a middle string. Remove it here. - if b:ECuseCommentsOp && b:ECuseMPBlock - \ && a:0 > 1 - \ && s:i > s:startBlock - let line = substitute(line, s:LookFor('decommentmiddle', a:2), - \ s:SubstituteWith('decommentmiddle'), "") - endif - - " Remove escaped inner comments. - let line = s:UnEscape(line, a:commentSymbol, a:1) - endif - - return line -endfunction - -" -" GetLineLen(line, offset) -" line -- line of which length should be computed -" offset -- maybe a shift of the line to the right -" -" Expands '\t' to it's tabstop value. -" -function s:GetLineLen(line, offset) - let len = a:offset - let i = 0 - - while a:line[i] != "" - if a:line[i] == "\t" - let len = (((len / &tabstop) + 1) * &tabstop) - else - let len = len + 1 - endif - let i = i + 1 - endwhile - - return len -endfunction - -" -" EscapeString(string) -" string -- string to process -" -" Escapes characters in 'string', which have some function in -" regular expressions, with a '\'. -" -" Returns the escaped string. -" -function s:EscapeString(string) - return escape(a:string, "*{}[]$^-") -endfunction - -" -" LookFor(what, ...) -" what -- what type of regular expression -" * checkstart: -" * checkend: -" check for comment at start/end of line -" * commentstart: -" * commentend: -" insert comment strings -" * decommentstart: -" * decommentend: -" remove comment strings -" a:1 -- comment string -" -function s:LookFor(what, ...) - if b:ECuseBlockIndent && s:inBlock - let handleWhitespace = s:blockIndentRegex - else - let handleWhitespace = b:ECsaveWhite - endif - - if a:what == 'checkstart' - let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1) - \ . s:EscapeString(b:ECidentFront) - elseif a:what == 'checkend' - let regex = s:EscapeString(b:ECidentBack) - \ . s:EscapeString(a:1) . b:ECsaveWhite . '$' - elseif a:what == 'commentstart' - let regex = '^'. handleWhitespace - elseif a:what == 'commentmiddle' - let regex = '^'. handleWhitespace - elseif a:what == 'commentend' - let regex = '$' - elseif a:what == 'decommentstart' - let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1) - \ . s:EscapeString(b:ECidentFront) . b:ECprettyUnComments - elseif a:what == 'decommentmiddle' - let regex = '^'. b:ECsaveWhite . s:EscapeString(a:1) - \ . s:EscapeString(b:ECidentFront) . b:ECprettyUnComments - elseif a:what == 'decommentend' - let regex = b:ECprettyUnComments . s:EscapeString(b:ECidentBack) - \ . s:EscapeString(a:1) . b:ECsaveWhite .'$' - endif - - return regex -endfunction - -" -" SubstituteWith(what, ...) -" what -- what type of regular expression -" * commentstart: -" * commentend: -" insert comment strings -" * decommentstart: -" * decommentend: -" remove comment strings -" a:1 -- comment string -" -function s:SubstituteWith(what, ...) - if a:what == 'commentstart' - \ || a:what == 'commentmiddle' - \ || a:what == 'commentend' - let commentSymbol = a:1 - else - let commentSymbol = '' - endif - - if b:ECuseBlockIndent && s:inBlock - let handleWhitespace = '\1' . commentSymbol - else - let handleWhitespace = b:ECrespectWhite . commentSymbol - \ . b:ECignoreWhite - endif - - if a:what == 'commentstart' - let regex = handleWhitespace . b:ECidentFront - \ . b:ECprettyComments - elseif a:what == 'commentmiddle' - let regex = handleWhitespace . b:ECidentFront - \ . b:ECprettyComments - elseif a:what == 'commentend' - let regex = b:ECprettyComments . b:ECidentBack . a:1 - elseif a:what == 'decommentstart' - \ || a:what == 'decommentmiddle' - \ || a:what == 'decommentend' - let regex = handleWhitespace - endif - - return regex -endfunction - -" -" -" DecideWhatToDo(lineString, commentStart, ...) -" lineString -- first line of block -" commentStart -- comment start symbol -" a:1 -- comment end symbol -" -function s:DecideWhatToDo(lineString, commentStart, ...) - " If we checked already, we return our previous result. - if !s:firstOfBlock - \ && (s:Action == 'first' - \ || (b:ECuseMPBlock && s:inBlock && a:0)) - return s:blockAction - endif - - let s:blockAction = 'comment' - - if s:inBlock && a:0 && b:ECuseMPBlock - let first = getline(s:startBlock) - let last = getline(s:endBlock) - - if first =~ s:LookFor('checkstart', a:commentStart) - \ && first !~ s:LookFor('checkend', a:1) - \ && last !~ s:LookFor('checkstart', a:commentStart) - \ && last =~ s:LookFor('checkend', a:1) - let s:blockAction = 'decomment' - endif - - return s:blockAction - endif - - if a:lineString =~ s:LookFor('checkstart', a:commentStart) - let s:blockAction = 'decomment' - endif - - if a:0 - if a:lineString !~ s:LookFor('checkend', a:1) - let s:blockAction = 'comment' - endif - endif - - let s:firstOfBlock = 0 - return s:blockAction -endfunction - -" -" TabsToSpaces(str) -" str -- string to convert -" -" Convert leading tabs of given string to spaces. -" -function s:TabsToSpaces(str) - let string = a:str - - " FIXME: Can we use something like retab? I don't think so, - " because retab changes every whitespace in the line, but we - " wan't to modify only the leading spaces. Is this a problem? - while string =~ '^\( *\)\t' - let string = substitute(string, '^\( *\)\t', '\1'. s:tabConvert, "") - endwhile - - return string -endfunction - -" -" SpacesToTabs(str) -" str -- string to convert -" -" Convert leading spaces of given string to tabs. -" -function s:SpacesToTabs(str) - let string = a:str - - if !&expandtab - while string =~ '^\(\t*\)'. s:tabConvert - let string = substitute(string, '^\(\t*\)'. s:tabConvert, - \ '\1\t', "") - endwhile - endif - - return string -endfunction - -" -" EnhCommentifyFallback4Embedded(test, fallback) -" test -- test for the special case -" fallback -- filetype instead of normal fallback -" -" This function is global. It should be called from filetype -" plugins like php, where the normal fallback behaviour may -" not work. One may use 'synFiletype' to reference the guessed -" filetype via synID. -" -function EnhCommentifyFallback4Embedded(test, fallback) - let b:EnhCommentifyFallbackTest = a:test - let b:EnhCommentifyFallbackValue = a:fallback -endfunction - -" -" Keyboard mappings. -" -noremap <Plug>Comment - \ :call EnhancedCommentify('', 'comment')<CR> -noremap <Plug>DeComment - \ :call EnhancedCommentify('', 'decomment')<CR> -noremap <Plug>Traditional - \ :call EnhancedCommentify('', 'guess')<CR> -noremap <Plug>FirstLine - \ :call EnhancedCommentify('', 'first')<CR> - -noremap <Plug>VisualComment - \ <Esc>:call EnhancedCommentify('', 'comment', - \ line("'<"), line("'>"))<CR> -noremap <Plug>VisualDeComment - \ <Esc>:call EnhancedCommentify('', 'decomment', - \ line("'<"), line("'>"))<CR> -noremap <Plug>VisualTraditional - \ <Esc>:call EnhancedCommentify('', 'guess', - \ line("'<"), line("'>"))<CR> -noremap <Plug>VisualFirstLine - \ <Esc>:call EnhancedCommentify('', 'first', - \ line("'<"), line("'>"))<CR> -" -" Finally set keybindings. -" -" SetKeybindings(where) -" where -- "l" for local to the buffer, "g" for global -" -function s:SetKeybindings(where) - if a:where == "l" - let where = "<buffer>" - let ns = "b" - else - let where = "" - let ns = "s" - endif - - execute "let userBindings = ". ns .":ECuserBindings" - execute "let useAltKeys = ". ns .":ECuseAltKeys" - execute "let traditionalMode = ". ns .":ECtraditionalMode" - execute "let firstLineMode = ". ns .":ECfirstLineMode" - execute "let bindInNormal = ". ns .":ECbindInNormal" - execute "let bindInInsert = ". ns .":ECbindInInsert" - execute "let bindInVisual = ". ns .":ECbindInVisual" - - if userBindings - " - " *** Put your personal bindings here! *** - " - else - if useAltKeys - let s:c = '<M-c>' - let s:x = '<M-x>' - let s:C = '<M-v>' - let s:X = '<M-y>' - else - let s:c = '<Leader>c' - let s:x = '<Leader>x' - let s:C = '<Leader>C' - let s:X = '<Leader>X' - endif - - if traditionalMode - let s:Method = 'Traditional' - elseif firstLineMode - let s:Method = 'FirstLine' - else - let s:Method = 'Comment' - - " Decomment must be defined here. Everything else is mapped below. - if bindInNormal - execute 'nmap '. where .' <silent> <unique> '. s:C - \ .' <Plug>DeCommentj' - execute 'nmap '. where .' <silent> <unique> '. s:X - \ .' <Plug>DeComment' - endif - - if bindInInsert - execute 'imap '. where .' <silent> <unique> '. s:C - \ .' <Esc><Plug>DeCommentji' - execute 'imap '. where .' <silent> <unique> '. s:X - \ .' <Esc><Plug>DeCommenti' - endif - - if bindInVisual - execute 'vmap '. where .' <silent> <unique> '. s:C - \ .' <Plug>VisualDeCommentj' - execute 'vmap '. where .' <silent> <unique> '. s:X - \ .' <Plug>VisualDeComment' - endif - endif - - if bindInNormal - execute 'nmap '. where .' <silent> <unique> '. s:c - \ .' <Plug>'. s:Method .'j' - execute 'nmap '. where .' <silent> <unique> '. s:x - \ .' <Plug>'. s:Method - endif - - if bindInInsert - execute 'imap '. where .' <silent> <unique> '. s:c - \ .' <Esc><Plug>'. s:Method .'ji' - execute 'imap '. where .' <silent> <unique> '. s:x - \ .' <Esc><Plug>'. s:Method - endif - - if bindInVisual - execute 'vmap <silent> <unique> '. s:c - \ .' <Plug>Visual'. s:Method .'j' - execute 'vmap '. where .' <silent> <unique> '. s:x - \ .' <Plug>Visual'. s:Method - endif - endif -endfunction - -if !s:ECbindPerBuffer - call s:SetKeybindings("g") -endif - -let &cpo = s:savedCpo - -" vim: set sts=4 sw=4 ts=8 : diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim new file mode 100644 index 0000000..6411b1d --- /dev/null +++ b/plugin/NERD_tree.vim @@ -0,0 +1,4059 @@ +" ============================================================================ +" File: NERD_tree.vim +" Description: vim global plugin that provides a nice tree explorer +" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com> +" Last Change: 1 December, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +let s:NERD_tree_version = '4.1.0' + +" SECTION: Script init stuff {{{1 +"============================================================ +if exists("loaded_nerd_tree") + finish +endif +if v:version < 700 + echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!" + finish +endif +let loaded_nerd_tree = 1 + +"for line continuation - i.e dont want C in &cpo +let s:old_cpo = &cpo +set cpo&vim + +"Function: s:initVariable() function {{{2 +"This function is used to initialise a given variable to a given value. The +"variable is only initialised if it does not exist prior +" +"Args: +"var: the name of the var to be initialised +"value: the value to initialise var to +" +"Returns: +"1 if the var is set, 0 otherwise +function! s:initVariable(var, value) + if !exists(a:var) + exec 'let ' . a:var . ' = ' . "'" . a:value . "'" + return 1 + endif + return 0 +endfunction + +"SECTION: Init variable calls and other random constants {{{2 +call s:initVariable("g:NERDChristmasTree", 1) +call s:initVariable("g:NERDTreeAutoCenter", 1) +call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) +call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) +call s:initVariable("g:NERDTreeChDirMode", 0) +if !exists("g:NERDTreeIgnore") + let g:NERDTreeIgnore = ['\~$'] +endif +call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks') +call s:initVariable("g:NERDTreeHighlightCursorline", 1) +call s:initVariable("g:NERDTreeHijackNetrw", 1) +call s:initVariable("g:NERDTreeMouseMode", 1) +call s:initVariable("g:NERDTreeNotificationThreshold", 100) +call s:initVariable("g:NERDTreeQuitOnOpen", 0) +call s:initVariable("g:NERDTreeShowBookmarks", 0) +call s:initVariable("g:NERDTreeShowFiles", 1) +call s:initVariable("g:NERDTreeShowHidden", 0) +call s:initVariable("g:NERDTreeShowLineNumbers", 0) +call s:initVariable("g:NERDTreeSortDirs", 1) + +if !exists("g:NERDTreeSortOrder") + let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$'] +else + "if there isnt a * in the sort sequence then add one + if count(g:NERDTreeSortOrder, '*') < 1 + call add(g:NERDTreeSortOrder, '*') + endif +endif + +"we need to use this number many times for sorting... so we calculate it only +"once here +let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*') + +if !exists('g:NERDTreeStatusline') + + "the exists() crap here is a hack to stop vim spazzing out when + "loading a session that was created with an open nerd tree. It spazzes + "because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash) + let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}" + +endif +call s:initVariable("g:NERDTreeWinPos", "left") +call s:initVariable("g:NERDTreeWinSize", 31) + +let s:running_windows = has("win16") || has("win32") || has("win64") + +"init the shell commands that will be used to copy nodes, and remove dir trees +" +"Note: the space after the command is important +if s:running_windows + call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ') +else + call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ') + call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ') +endif + + +"SECTION: Init variable calls for key mappings {{{2 +call s:initVariable("g:NERDTreeMapActivateNode", "o") +call s:initVariable("g:NERDTreeMapChangeRoot", "C") +call s:initVariable("g:NERDTreeMapChdir", "cd") +call s:initVariable("g:NERDTreeMapCloseChildren", "X") +call s:initVariable("g:NERDTreeMapCloseDir", "x") +call s:initVariable("g:NERDTreeMapDeleteBookmark", "D") +call s:initVariable("g:NERDTreeMapMenu", "m") +call s:initVariable("g:NERDTreeMapHelp", "?") +call s:initVariable("g:NERDTreeMapJumpFirstChild", "K") +call s:initVariable("g:NERDTreeMapJumpLastChild", "J") +call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>") +call s:initVariable("g:NERDTreeMapJumpParent", "p") +call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>") +call s:initVariable("g:NERDTreeMapJumpRoot", "P") +call s:initVariable("g:NERDTreeMapOpenExpl", "e") +call s:initVariable("g:NERDTreeMapOpenInTab", "t") +call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T") +call s:initVariable("g:NERDTreeMapOpenRecursively", "O") +call s:initVariable("g:NERDTreeMapOpenSplit", "i") +call s:initVariable("g:NERDTreeMapOpenVSplit", "s") +call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode) +call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit) +call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit) +call s:initVariable("g:NERDTreeMapQuit", "q") +call s:initVariable("g:NERDTreeMapRefresh", "r") +call s:initVariable("g:NERDTreeMapRefreshRoot", "R") +call s:initVariable("g:NERDTreeMapToggleBookmarks", "B") +call s:initVariable("g:NERDTreeMapToggleFiles", "F") +call s:initVariable("g:NERDTreeMapToggleFilters", "f") +call s:initVariable("g:NERDTreeMapToggleHidden", "I") +call s:initVariable("g:NERDTreeMapToggleZoom", "A") +call s:initVariable("g:NERDTreeMapUpdir", "u") +call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U") + +"SECTION: Script level variable declaration{{{2 +if s:running_windows + let s:escape_chars = " `\|\"#%&,?()\*^<>" +else + let s:escape_chars = " \\`\|\"#%&,?()\*^<>" +endif +let s:NERDTreeBufName = 'NERD_tree_' + +let s:tree_wid = 2 +let s:tree_markup_reg = '^[ `|]*[\-+~]' +let s:tree_up_dir_line = '.. (up a dir)' + +"the number to add to the nerd tree buffer name to make the buf name unique +let s:next_buffer_number = 1 + +" SECTION: Commands {{{1 +"============================================================ +"init the command that users start the nerd tree with +command! -n=? -complete=dir -bar NERDTree :call s:initNerdTree('<args>') +command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('<args>') +command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen() +command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('<args>') +command! -n=0 -bar NERDTreeMirror call s:initNerdTreeMirror() +command! -n=0 -bar NERDTreeFind call s:findAndRevealPath() +" SECTION: Auto commands {{{1 +"============================================================ +augroup NERDTree + "Save the cursor position whenever we close the nerd tree + exec "autocmd BufWinLeave ". s:NERDTreeBufName ."* call <SID>saveScreenState()" + "cache bookmarks when vim loads + autocmd VimEnter * call s:Bookmark.CacheBookmarks(0) + + "load all nerdtree plugins after vim starts + autocmd VimEnter * runtime! nerdtree_plugin/**/*.vim +augroup END + +if g:NERDTreeHijackNetrw + augroup NERDTreeHijackNetrw + autocmd VimEnter * silent! autocmd! FileExplorer + au BufEnter,VimEnter * call s:checkForBrowse(expand("<amatch>")) + augroup END +endif + +"SECTION: Classes {{{1 +"============================================================ +"CLASS: Bookmark {{{2 +"============================================================ +let s:Bookmark = {} +" FUNCTION: Bookmark.activate() {{{3 +function! s:Bookmark.activate() + if self.path.isDirectory + call self.toRoot() + else + if self.validate() + let n = s:TreeFileNode.New(self.path) + call n.open() + endif + endif +endfunction +" FUNCTION: Bookmark.AddBookmark(name, path) {{{3 +" Class method to add a new bookmark to the list, if a previous bookmark exists +" with the same name, just update the path for that bookmark +function! s:Bookmark.AddBookmark(name, path) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + let i.path = a:path + return + endif + endfor + call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) + call s:Bookmark.Sort() +endfunction +" Function: Bookmark.Bookmarks() {{{3 +" Class method to get all bookmarks. Lazily initializes the bookmarks global +" variable +function! s:Bookmark.Bookmarks() + if !exists("g:NERDTreeBookmarks") + let g:NERDTreeBookmarks = [] + endif + return g:NERDTreeBookmarks +endfunction +" Function: Bookmark.BookmarkExistsFor(name) {{{3 +" class method that returns 1 if a bookmark with the given name is found, 0 +" otherwise +function! s:Bookmark.BookmarkExistsFor(name) + try + call s:Bookmark.BookmarkFor(a:name) + return 1 + catch /^NERDTree.BookmarkNotFoundError/ + return 0 + endtry +endfunction +" Function: Bookmark.BookmarkFor(name) {{{3 +" Class method to get the bookmark that has the given name. {} is return if no +" bookmark is found +function! s:Bookmark.BookmarkFor(name) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + return i + endif + endfor + throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"' +endfunction +" Function: Bookmark.BookmarkNames() {{{3 +" Class method to return an array of all bookmark names +function! s:Bookmark.BookmarkNames() + let names = [] + for i in s:Bookmark.Bookmarks() + call add(names, i.name) + endfor + return names +endfunction +" FUNCTION: Bookmark.CacheBookmarks(silent) {{{3 +" Class method to read all bookmarks from the bookmarks file intialize +" bookmark objects for each one. +" +" Args: +" silent - dont echo an error msg if invalid bookmarks are found +function! s:Bookmark.CacheBookmarks(silent) + if filereadable(g:NERDTreeBookmarksFile) + let g:NERDTreeBookmarks = [] + let g:NERDTreeInvalidBookmarks = [] + let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) + let invalidBookmarksFound = 0 + for i in bookmarkStrings + + "ignore blank lines + if i != '' + + let name = substitute(i, '^\(.\{-}\) .*$', '\1', '') + let path = substitute(i, '^.\{-} \(.*\)$', '\1', '') + + try + let bookmark = s:Bookmark.New(name, s:Path.New(path)) + call add(g:NERDTreeBookmarks, bookmark) + catch /^NERDTree.InvalidArgumentsError/ + call add(g:NERDTreeInvalidBookmarks, i) + let invalidBookmarksFound += 1 + endtry + endif + endfor + if invalidBookmarksFound + call s:Bookmark.Write() + if !a:silent + call s:echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") + endif + endif + call s:Bookmark.Sort() + endif +endfunction +" FUNCTION: Bookmark.compareTo(otherbookmark) {{{3 +" Compare these two bookmarks for sorting purposes +function! s:Bookmark.compareTo(otherbookmark) + return a:otherbookmark.name < self.name +endfunction +" FUNCTION: Bookmark.ClearAll() {{{3 +" Class method to delete all bookmarks. +function! s:Bookmark.ClearAll() + for i in s:Bookmark.Bookmarks() + call i.delete() + endfor + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.delete() {{{3 +" Delete this bookmark. If the node for this bookmark is under the current +" root, then recache bookmarks for its Path object +function! s:Bookmark.delete() + let node = {} + try + let node = self.getNode(1) + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self)) + if !empty(node) + call node.path.cacheDisplayString() + endif + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{3 +" Gets the treenode for this bookmark +" +" Args: +" searchFromAbsoluteRoot: specifies whether we should search from the current +" tree root, or the highest cached node +function! s:Bookmark.getNode(searchFromAbsoluteRoot) + let searchRoot = a:searchFromAbsoluteRoot ? s:TreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot + let targetNode = searchRoot.findNode(self.path) + if empty(targetNode) + throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name + endif + return targetNode +endfunction +" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3 +" Class method that finds the bookmark with the given name and returns the +" treenode for it. +function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) + let bookmark = s:Bookmark.BookmarkFor(a:name) + return bookmark.getNode(a:searchFromAbsoluteRoot) +endfunction +" FUNCTION: Bookmark.GetSelected() {{{3 +" returns the Bookmark the cursor is over, or {} +function! s:Bookmark.GetSelected() + let line = getline(".") + let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '') + if name != line + try + return s:Bookmark.BookmarkFor(name) + catch /^NERDTree.BookmarkNotFoundError/ + return {} + endtry + endif + return {} +endfunction + +" Function: Bookmark.InvalidBookmarks() {{{3 +" Class method to get all invalid bookmark strings read from the bookmarks +" file +function! s:Bookmark.InvalidBookmarks() + if !exists("g:NERDTreeInvalidBookmarks") + let g:NERDTreeInvalidBookmarks = [] + endif + return g:NERDTreeInvalidBookmarks +endfunction +" FUNCTION: Bookmark.mustExist() {{{3 +function! s:Bookmark.mustExist() + if !self.path.exists() + call s:Bookmark.CacheBookmarks(1) + throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"". + \ self.name ."\" points to a non existing location: \"". self.path.str() + endif +endfunction +" FUNCTION: Bookmark.New(name, path) {{{3 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.New(name, path) + if a:name =~ ' ' + throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name + endif + + let newBookmark = copy(self) + let newBookmark.name = a:name + let newBookmark.path = a:path + return newBookmark +endfunction +" FUNCTION: Bookmark.openInNewTab(options) {{{3 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.openInNewTab(options) + let currentTab = tabpagenr() + if self.path.isDirectory + tabnew + call s:initNerdTree(self.name) + else + exec "tabedit " . bookmark.path.str({'format': 'Edit'}) + endif + + if has_key(a:options, 'stayInCurrentTab') + exec "tabnext " . currentTab + endif +endfunction +" Function: Bookmark.setPath(path) {{{3 +" makes this bookmark point to the given path +function! s:Bookmark.setPath(path) + let self.path = a:path +endfunction +" Function: Bookmark.Sort() {{{3 +" Class method that sorts all bookmarks +function! s:Bookmark.Sort() + let CompareFunc = function("s:compareBookmarks") + call sort(s:Bookmark.Bookmarks(), CompareFunc) +endfunction +" Function: Bookmark.str() {{{3 +" Get the string that should be rendered in the view for this bookmark +function! s:Bookmark.str() + let pathStrMaxLen = winwidth(s:getTreeWinNum()) - 4 - len(self.name) + if &nu + let pathStrMaxLen = pathStrMaxLen - &numberwidth + endif + + let pathStr = self.path.str({'format': 'UI'}) + if len(pathStr) > pathStrMaxLen + let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen) + endif + return '>' . self.name . ' ' . pathStr +endfunction +" FUNCTION: Bookmark.toRoot() {{{3 +" Make the node for this bookmark the new tree root +function! s:Bookmark.toRoot() + if self.validate() + try + let targetNode = self.getNode(1) + catch /^NERDTree.BookmarkedNodeNotFoundError/ + let targetNode = s:TreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path) + endtry + call targetNode.makeRoot() + call s:renderView() + call targetNode.putCursorHere(0, 0) + endif +endfunction +" FUNCTION: Bookmark.ToRoot(name) {{{3 +" Make the node for this bookmark the new tree root +function! s:Bookmark.ToRoot(name) + let bookmark = s:Bookmark.BookmarkFor(a:name) + call bookmark.toRoot() +endfunction + + +"FUNCTION: Bookmark.validate() {{{3 +function! s:Bookmark.validate() + if self.path.exists() + return 1 + else + call s:Bookmark.CacheBookmarks(1) + call s:renderView() + call s:echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.") + return 0 + endif +endfunction + +" Function: Bookmark.Write() {{{3 +" Class method to write all bookmarks to the bookmarks file +function! s:Bookmark.Write() + let bookmarkStrings = [] + for i in s:Bookmark.Bookmarks() + call add(bookmarkStrings, i.name . ' ' . i.path.str()) + endfor + + "add a blank line before the invalid ones + call add(bookmarkStrings, "") + + for j in s:Bookmark.InvalidBookmarks() + call add(bookmarkStrings, j) + endfor + call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) +endfunction +"CLASS: KeyMap {{{2 +"============================================================ +let s:KeyMap = {} +"FUNCTION: KeyMap.All() {{{3 +function! s:KeyMap.All() + if !exists("s:keyMaps") + let s:keyMaps = [] + endif + return s:keyMaps +endfunction + +"FUNCTION: KeyMap.BindAll() {{{3 +function! s:KeyMap.BindAll() + for i in s:KeyMap.All() + call i.bind() + endfor +endfunction + +"FUNCTION: KeyMap.bind() {{{3 +function! s:KeyMap.bind() + exec "nnoremap <silent> <buffer> ". self.key ." :call ". self.callback ."()<cr>" +endfunction + +"FUNCTION: KeyMap.Create(options) {{{3 +function! s:KeyMap.Create(options) + let newKeyMap = copy(self) + let newKeyMap.key = a:options['key'] + let newKeyMap.quickhelpText = a:options['quickhelpText'] + let newKeyMap.callback = a:options['callback'] + call add(s:KeyMap.All(), newKeyMap) +endfunction +"CLASS: MenuController {{{2 +"============================================================ +let s:MenuController = {} +"FUNCTION: MenuController.New(menuItems) {{{3 +"create a new menu controller that operates on the given menu items +function! s:MenuController.New(menuItems) + let newMenuController = copy(self) + if a:menuItems[0].isSeparator() + let newMenuController.menuItems = a:menuItems[1:-1] + else + let newMenuController.menuItems = a:menuItems + endif + return newMenuController +endfunction + +"FUNCTION: MenuController.showMenu() {{{3 +"start the main loop of the menu and get the user to choose/execute a menu +"item +function! s:MenuController.showMenu() + call self._saveOptions() + + try + let self.selection = 0 + + let done = 0 + while !done + redraw! + call self._echoPrompt() + let key = nr2char(getchar()) + let done = self._handleKeypress(key) + endwhile + finally + call self._restoreOptions() + endtry + + if self.selection != -1 + let m = self._current() + call m.execute() + endif +endfunction + +"FUNCTION: MenuController._echoPrompt() {{{3 +function! s:MenuController._echoPrompt() + echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated" + echo "==========================================================" + + for i in range(0, len(self.menuItems)-1) + if self.selection == i + echo "> " . self.menuItems[i].text + else + echo " " . self.menuItems[i].text + endif + endfor +endfunction + +"FUNCTION: MenuController._current(key) {{{3 +"get the MenuItem that is curently selected +function! s:MenuController._current() + return self.menuItems[self.selection] +endfunction + +"FUNCTION: MenuController._handleKeypress(key) {{{3 +"change the selection (if appropriate) and return 1 if the user has made +"their choice, 0 otherwise +function! s:MenuController._handleKeypress(key) + if a:key == 'j' + call self._cursorDown() + elseif a:key == 'k' + call self._cursorUp() + elseif a:key == nr2char(27) "escape + let self.selection = -1 + return 1 + elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j + return 1 + else + let index = self._nextIndexFor(a:key) + if index != -1 + let self.selection = index + if len(self._allIndexesFor(a:key)) == 1 + return 1 + endif + endif + endif + + return 0 +endfunction + +"FUNCTION: MenuController._allIndexesFor(shortcut) {{{3 +"get indexes to all menu items with the given shortcut +function! s:MenuController._allIndexesFor(shortcut) + let toReturn = [] + + for i in range(0, len(self.menuItems)-1) + if self.menuItems[i].shortcut == a:shortcut + call add(toReturn, i) + endif + endfor + + return toReturn +endfunction + +"FUNCTION: MenuController._nextIndexFor(shortcut) {{{3 +"get the index to the next menu item with the given shortcut, starts from the +"current cursor location and wraps around to the top again if need be +function! s:MenuController._nextIndexFor(shortcut) + for i in range(self.selection+1, len(self.menuItems)-1) + if self.menuItems[i].shortcut == a:shortcut + return i + endif + endfor + + for i in range(0, self.selection) + if self.menuItems[i].shortcut == a:shortcut + return i + endif + endfor + + return -1 +endfunction + +"FUNCTION: MenuController._setCmdheight() {{{3 +"sets &cmdheight to whatever is needed to display the menu +function! s:MenuController._setCmdheight() + let &cmdheight = len(self.menuItems) + 3 +endfunction + +"FUNCTION: MenuController._saveOptions() {{{3 +"set any vim options that are required to make the menu work (saving their old +"values) +function! s:MenuController._saveOptions() + let self._oldLazyredraw = &lazyredraw + let self._oldCmdheight = &cmdheight + set nolazyredraw + call self._setCmdheight() +endfunction + +"FUNCTION: MenuController._restoreOptions() {{{3 +"restore the options we saved in _saveOptions() +function! s:MenuController._restoreOptions() + let &cmdheight = self._oldCmdheight + let &lazyredraw = self._oldLazyredraw +endfunction + +"FUNCTION: MenuController._cursorDown() {{{3 +"move the cursor to the next menu item, skipping separators +function! s:MenuController._cursorDown() + let done = 0 + while !done + if self.selection < len(self.menuItems)-1 + let self.selection += 1 + else + let self.selection = 0 + endif + + if !self._current().isSeparator() + let done = 1 + endif + endwhile +endfunction + +"FUNCTION: MenuController._cursorUp() {{{3 +"move the cursor to the previous menu item, skipping separators +function! s:MenuController._cursorUp() + let done = 0 + while !done + if self.selection > 0 + let self.selection -= 1 + else + let self.selection = len(self.menuItems)-1 + endif + + if !self._current().isSeparator() + let done = 1 + endif + endwhile +endfunction + +"CLASS: MenuItem {{{2 +"============================================================ +let s:MenuItem = {} +"FUNCTION: MenuItem.All() {{{3 +"get all top level menu items +function! s:MenuItem.All() + if !exists("s:menuItems") + let s:menuItems = [] + endif + return s:menuItems +endfunction + +"FUNCTION: MenuItem.AllEnabled() {{{3 +"get all top level menu items that are currently enabled +function! s:MenuItem.AllEnabled() + let toReturn = [] + for i in s:MenuItem.All() + if i.enabled() + call add(toReturn, i) + endif + endfor + return toReturn +endfunction + +"FUNCTION: MenuItem.Create(options) {{{3 +"make a new menu item and add it to the global list +function! s:MenuItem.Create(options) + let newMenuItem = copy(self) + + let newMenuItem.text = a:options['text'] + let newMenuItem.shortcut = a:options['shortcut'] + let newMenuItem.children = [] + + let newMenuItem.isActiveCallback = -1 + if has_key(a:options, 'isActiveCallback') + let newMenuItem.isActiveCallback = a:options['isActiveCallback'] + endif + + let newMenuItem.callback = -1 + if has_key(a:options, 'callback') + let newMenuItem.callback = a:options['callback'] + endif + + if has_key(a:options, 'parent') + call add(a:options['parent'].children, newMenuItem) + else + call add(s:MenuItem.All(), newMenuItem) + endif + + return newMenuItem +endfunction + +"FUNCTION: MenuItem.CreateSeparator(options) {{{3 +"make a new separator menu item and add it to the global list +function! s:MenuItem.CreateSeparator(options) + let standard_options = { 'text': '--------------------', + \ 'shortcut': -1, + \ 'callback': -1 } + let options = extend(a:options, standard_options, "force") + + return s:MenuItem.Create(options) +endfunction + +"FUNCTION: MenuItem.CreateSubmenu(options) {{{3 +"make a new submenu and add it to global list +function! s:MenuItem.CreateSubmenu(options) + let standard_options = { 'callback': -1 } + let options = extend(a:options, standard_options, "force") + + return s:MenuItem.Create(options) +endfunction + +"FUNCTION: MenuItem.enabled() {{{3 +"return 1 if this menu item should be displayed +" +"delegates off to the isActiveCallback, and defaults to 1 if no callback was +"specified +function! s:MenuItem.enabled() + if self.isActiveCallback != -1 + return {self.isActiveCallback}() + endif + return 1 +endfunction + +"FUNCTION: MenuItem.execute() {{{3 +"perform the action behind this menu item, if this menuitem has children then +"display a new menu for them, otherwise deletegate off to the menuitem's +"callback +function! s:MenuItem.execute() + if len(self.children) + let mc = s:MenuController.New(self.children) + call mc.showMenu() + else + if self.callback != -1 + call {self.callback}() + endif + endif +endfunction + +"FUNCTION: MenuItem.isSeparator() {{{3 +"return 1 if this menuitem is a separator +function! s:MenuItem.isSeparator() + return self.callback == -1 && self.children == [] +endfunction + +"FUNCTION: MenuItem.isSubmenu() {{{3 +"return 1 if this menuitem is a submenu +function! s:MenuItem.isSubmenu() + return self.callback == -1 && !empty(self.children) +endfunction + +"CLASS: TreeFileNode {{{2 +"This class is the parent of the TreeDirNode class and constitures the +"'Component' part of the composite design pattern between the treenode +"classes. +"============================================================ +let s:TreeFileNode = {} +"FUNCTION: TreeFileNode.activate(forceKeepWinOpen) {{{3 +function! s:TreeFileNode.activate(forceKeepWinOpen) + call self.open() + if !a:forceKeepWinOpen + call s:closeTreeIfQuitOnOpen() + end +endfunction +"FUNCTION: TreeFileNode.bookmark(name) {{{3 +"bookmark this node with a:name +function! s:TreeFileNode.bookmark(name) + try + let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1) + call oldMarkedNode.path.cacheDisplayString() + catch /^NERDTree.BookmarkNotFoundError/ + endtry + + call s:Bookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call s:Bookmark.Write() +endfunction +"FUNCTION: TreeFileNode.cacheParent() {{{3 +"initializes self.parent if it isnt already +function! s:TreeFileNode.cacheParent() + if empty(self.parent) + let parentPath = self.path.getParent() + if parentPath.equals(self.path) + throw "NERDTree.CannotCacheParentError: already at root" + endif + let self.parent = s:TreeFileNode.New(parentPath) + endif +endfunction +"FUNCTION: TreeFileNode.compareNodes {{{3 +"This is supposed to be a class level method but i cant figure out how to +"get func refs to work from a dict.. +" +"A class level method that compares two nodes +" +"Args: +"n1, n2: the 2 nodes to compare +function! s:compareNodes(n1, n2) + return a:n1.path.compareTo(a:n2.path) +endfunction + +"FUNCTION: TreeFileNode.clearBoomarks() {{{3 +function! s:TreeFileNode.clearBoomarks() + for i in s:Bookmark.Bookmarks() + if i.path.equals(self.path) + call i.delete() + end + endfor + call self.path.cacheDisplayString() +endfunction +"FUNCTION: TreeFileNode.copy(dest) {{{3 +function! s:TreeFileNode.copy(dest) + call self.path.copy(a:dest) + let newPath = s:Path.New(a:dest) + let parent = b:NERDTreeRoot.findNode(newPath.getParent()) + if !empty(parent) + call parent.refresh() + endif + return parent.findNode(newPath) +endfunction + +"FUNCTION: TreeFileNode.delete {{{3 +"Removes this node from the tree and calls the Delete method for its path obj +function! s:TreeFileNode.delete() + call self.path.delete() + call self.parent.removeChild(self) +endfunction + +"FUNCTION: TreeFileNode.displayString() {{{3 +" +"Returns a string that specifies how the node should be represented as a +"string +" +"Return: +"a string that can be used in the view to represent this node +function! s:TreeFileNode.displayString() + return self.path.displayString() +endfunction + +"FUNCTION: TreeFileNode.equals(treenode) {{{3 +" +"Compares this treenode to the input treenode and returns 1 if they are the +"same node. +" +"Use this method instead of == because sometimes when the treenodes contain +"many children, vim seg faults when doing == +" +"Args: +"treenode: the other treenode to compare to +function! s:TreeFileNode.equals(treenode) + return self.path.str() ==# a:treenode.path.str() +endfunction + +"FUNCTION: TreeFileNode.findNode(path) {{{3 +"Returns self if this node.path.Equals the given path. +"Returns {} if not equal. +" +"Args: +"path: the path object to compare against +function! s:TreeFileNode.findNode(path) + if a:path.equals(self.path) + return self + endif + return {} +endfunction +"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{3 +" +"Finds the next sibling for this node in the indicated direction. This sibling +"must be a directory and may/may not have children as specified. +" +"Args: +"direction: 0 if you want to find the previous sibling, 1 for the next sibling +" +"Return: +"a treenode object or {} if no appropriate sibling could be found +function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) + "if we have no parent then we can have no siblings + if self.parent != {} + let nextSibling = self.findSibling(a:direction) + + while nextSibling != {} + if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen + return nextSibling + endif + let nextSibling = nextSibling.findSibling(a:direction) + endwhile + endif + + return {} +endfunction +"FUNCTION: TreeFileNode.findSibling(direction) {{{3 +" +"Finds the next sibling for this node in the indicated direction +" +"Args: +"direction: 0 if you want to find the previous sibling, 1 for the next sibling +" +"Return: +"a treenode object or {} if no sibling could be found +function! s:TreeFileNode.findSibling(direction) + "if we have no parent then we can have no siblings + if self.parent != {} + + "get the index of this node in its parents children + let siblingIndx = self.parent.getChildIndex(self.path) + + if siblingIndx != -1 + "move a long to the next potential sibling node + let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1 + + "keep moving along to the next sibling till we find one that is valid + let numSiblings = self.parent.getChildCount() + while siblingIndx >= 0 && siblingIndx < numSiblings + + "if the next node is not an ignored node (i.e. wont show up in the + "view) then return it + if self.parent.children[siblingIndx].path.ignore() ==# 0 + return self.parent.children[siblingIndx] + endif + + "go to next node + let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1 + endwhile + endif + endif + + return {} +endfunction + +"FUNCTION: TreeFileNode.getLineNum(){{{3 +"returns the line number this node is rendered on, or -1 if it isnt rendered +function! s:TreeFileNode.getLineNum() + "if the node is the root then return the root line no. + if self.isRoot() + return s:TreeFileNode.GetRootLineNum() + endif + + let totalLines = line("$") + + "the path components we have matched so far + let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')] + "the index of the component we are searching for + let curPathComponent = 1 + + let fullpath = self.path.str({'format': 'UI'}) + + + let lnum = s:TreeFileNode.GetRootLineNum() + while lnum > 0 + let lnum = lnum + 1 + "have we reached the bottom of the tree? + if lnum ==# totalLines+1 + return -1 + endif + + let curLine = getline(lnum) + + let indent = s:indentLevelFor(curLine) + if indent ==# curPathComponent + let curLine = s:stripMarkupFromLine(curLine, 1) + + let curPath = join(pathcomponents, '/') . '/' . curLine + if stridx(fullpath, curPath, 0) ==# 0 + if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/' + let curLine = substitute(curLine, '/ *$', '', '') + call add(pathcomponents, curLine) + let curPathComponent = curPathComponent + 1 + + if fullpath ==# curPath + return lnum + endif + endif + endif + endif + endwhile + return -1 +endfunction + +"FUNCTION: TreeFileNode.GetRootForTab(){{{3 +"get the root node for this tab +function! s:TreeFileNode.GetRootForTab() + if s:treeExistsForTab() + return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot') + end + return {} +endfunction +"FUNCTION: TreeFileNode.GetRootLineNum(){{{3 +"gets the line number of the root node +function! s:TreeFileNode.GetRootLineNum() + let rootLine = 1 + while getline(rootLine) !~ '^\(/\|<\)' + let rootLine = rootLine + 1 + endwhile + return rootLine +endfunction + +"FUNCTION: TreeFileNode.GetSelected() {{{3 +"gets the treenode that the cursor is currently over +function! s:TreeFileNode.GetSelected() + try + let path = s:getPath(line(".")) + if path ==# {} + return {} + endif + return b:NERDTreeRoot.findNode(path) + catch /NERDTree/ + return {} + endtry +endfunction +"FUNCTION: TreeFileNode.isVisible() {{{3 +"returns 1 if this node should be visible according to the tree filters and +"hidden file filters (and their on/off status) +function! s:TreeFileNode.isVisible() + return !self.path.ignore() +endfunction +"FUNCTION: TreeFileNode.isRoot() {{{3 +"returns 1 if this node is b:NERDTreeRoot +function! s:TreeFileNode.isRoot() + if !s:treeExistsForBuf() + throw "NERDTree.NoTreeError: No tree exists for the current buffer" + endif + + return self.equals(b:NERDTreeRoot) +endfunction + +"FUNCTION: TreeFileNode.makeRoot() {{{3 +"Make this node the root of the tree +function! s:TreeFileNode.makeRoot() + if self.path.isDirectory + let b:NERDTreeRoot = self + else + call self.cacheParent() + let b:NERDTreeRoot = self.parent + endif + + call b:NERDTreeRoot.open() + + "change dir to the dir of the new root if instructed to + if g:NERDTreeChDirMode ==# 2 + exec "cd " . b:NERDTreeRoot.path.str({'format': 'Edit'}) + endif +endfunction +"FUNCTION: TreeFileNode.New(path) {{{3 +"Returns a new TreeNode object with the given path and parent +" +"Args: +"path: a path object representing the full filesystem path to the file/dir that the node represents +function! s:TreeFileNode.New(path) + if a:path.isDirectory + return s:TreeDirNode.New(a:path) + else + let newTreeNode = copy(self) + let newTreeNode.path = a:path + let newTreeNode.parent = {} + return newTreeNode + endif +endfunction + +"FUNCTION: TreeFileNode.open() {{{3 +"Open the file represented by the given node in the current window, splitting +"the window if needed +" +"ARGS: +"treenode: file node to open +function! s:TreeFileNode.open() + if b:NERDTreeType ==# "secondary" + exec 'edit ' . self.path.str({'format': 'Edit'}) + return + endif + + "if the file is already open in this tab then just stick the cursor in it + let winnr = bufwinnr('^' . self.path.str() . '$') + if winnr != -1 + call s:exec(winnr . "wincmd w") + + else + if !s:isWindowUsable(winnr("#")) && s:firstUsableWindow() ==# -1 + call self.openSplit() + else + try + if !s:isWindowUsable(winnr("#")) + call s:exec(s:firstUsableWindow() . "wincmd w") + else + call s:exec('wincmd p') + endif + exec ("edit " . self.path.str({'format': 'Edit'})) + catch /^Vim\%((\a\+)\)\=:E37/ + call s:putCursorInTreeWin() + throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified." + catch /^Vim\%((\a\+)\)\=:/ + echo v:exception + endtry + endif + endif +endfunction +"FUNCTION: TreeFileNode.openSplit() {{{3 +"Open this node in a new window +function! s:TreeFileNode.openSplit() + + if b:NERDTreeType ==# "secondary" + exec "split " . self.path.str({'format': 'Edit'}) + return + endif + + " Save the user's settings for splitbelow and splitright + let savesplitbelow=&splitbelow + let savesplitright=&splitright + + " 'there' will be set to a command to move from the split window + " back to the explorer window + " + " 'back' will be set to a command to move from the explorer window + " back to the newly split window + " + " 'right' and 'below' will be set to the settings needed for + " splitbelow and splitright IF the explorer is the only window. + " + let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l" + let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h" + let right= g:NERDTreeWinPos ==# "left" + let below=0 + + " Attempt to go to adjacent window + call s:exec(back) + + let onlyOneWin = (winnr("$") ==# 1) + + " If no adjacent window, set splitright and splitbelow appropriately + if onlyOneWin + let &splitright=right + let &splitbelow=below + else + " found adjacent window - invert split direction + let &splitright=!right + let &splitbelow=!below + endif + + let splitMode = onlyOneWin ? "vertical" : "" + + " Open the new window + try + exec(splitMode." sp " . self.path.str({'format': 'Edit'})) + catch /^Vim\%((\a\+)\)\=:E37/ + call s:putCursorInTreeWin() + throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified." + catch /^Vim\%((\a\+)\)\=:/ + "do nothing + endtry + + "resize the tree window if no other window was open before + if onlyOneWin + let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize + call s:exec(there) + exec("silent ". splitMode ." resize ". size) + call s:exec('wincmd p') + endif + + " Restore splitmode settings + let &splitbelow=savesplitbelow + let &splitright=savesplitright +endfunction +"FUNCTION: TreeFileNode.openVSplit() {{{3 +"Open this node in a new vertical window +function! s:TreeFileNode.openVSplit() + if b:NERDTreeType ==# "secondary" + exec "vnew " . self.path.str({'format': 'Edit'}) + return + endif + + let winwidth = winwidth(".") + if winnr("$")==#1 + let winwidth = g:NERDTreeWinSize + endif + + call s:exec("wincmd p") + exec "vnew " . self.path.str({'format': 'Edit'}) + + "resize the nerd tree back to the original size + call s:putCursorInTreeWin() + exec("silent vertical resize ". winwidth) + call s:exec('wincmd p') +endfunction +"FUNCTION: TreeFileNode.openInNewTab(options) {{{3 +function! s:TreeFileNode.openInNewTab(options) + let currentTab = tabpagenr() + + if !has_key(a:options, 'keepTreeOpen') + call s:closeTreeIfQuitOnOpen() + endif + + exec "tabedit " . self.path.str({'format': 'Edit'}) + + if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab'] + exec "tabnext " . currentTab + endif + +endfunction +"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{3 +"Places the cursor on the line number this node is rendered on +" +"Args: +"isJump: 1 if this cursor movement should be counted as a jump by vim +"recurseUpward: try to put the cursor on the parent if the this node isnt +"visible +function! s:TreeFileNode.putCursorHere(isJump, recurseUpward) + let ln = self.getLineNum() + if ln != -1 + if a:isJump + mark ' + endif + call cursor(ln, col(".")) + else + if a:recurseUpward + let node = self + while node != {} && node.getLineNum() ==# -1 + let node = node.parent + call node.open() + endwhile + call s:renderView() + call node.putCursorHere(a:isJump, 0) + endif + endif +endfunction + +"FUNCTION: TreeFileNode.refresh() {{{3 +function! s:TreeFileNode.refresh() + call self.path.refresh() +endfunction +"FUNCTION: TreeFileNode.rename() {{{3 +"Calls the rename method for this nodes path obj +function! s:TreeFileNode.rename(newName) + let newName = substitute(a:newName, '\(\\\|\/\)$', '', '') + call self.path.rename(newName) + call self.parent.removeChild(self) + + let parentPath = self.path.getParent() + let newParent = b:NERDTreeRoot.findNode(parentPath) + + if newParent != {} + call newParent.createChild(self.path, 1) + call newParent.refresh() + endif +endfunction +"FUNCTION: TreeFileNode.renderToString {{{3 +"returns a string representation for this tree to be rendered in the view +function! s:TreeFileNode.renderToString() + return self._renderToString(0, 0, [], self.getChildCount() ==# 1) +endfunction + + +"Args: +"depth: the current depth in the tree for this call +"drawText: 1 if we should actually draw the line for this node (if 0 then the +"child nodes are rendered only) +"vertMap: a binary array that indicates whether a vertical bar should be draw +"for each depth in the tree +"isLastChild:true if this curNode is the last child of its parent +function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild) + let output = "" + if a:drawText ==# 1 + + let treeParts = '' + + "get all the leading spaces and vertical tree parts for this line + if a:depth > 1 + for j in a:vertMap[0:-2] + if j ==# 1 + let treeParts = treeParts . '| ' + else + let treeParts = treeParts . ' ' + endif + endfor + endif + + "get the last vertical tree part for this line which will be different + "if this node is the last child of its parent + if a:isLastChild + let treeParts = treeParts . '`' + else + let treeParts = treeParts . '|' + endif + + + "smack the appropriate dir/file symbol on the line before the file/dir + "name itself + if self.path.isDirectory + if self.isOpen + let treeParts = treeParts . '~' + else + let treeParts = treeParts . '+' + endif + else + let treeParts = treeParts . '-' + endif + let line = treeParts . self.displayString() + + let output = output . line . "\n" + endif + + "if the node is an open dir, draw its children + if self.path.isDirectory ==# 1 && self.isOpen ==# 1 + + let childNodesToDraw = self.getVisibleChildren() + if len(childNodesToDraw) > 0 + + "draw all the nodes children except the last + let lastIndx = len(childNodesToDraw)-1 + if lastIndx > 0 + for i in childNodesToDraw[0:lastIndx-1] + let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0) + endfor + endif + + "draw the last child, indicating that it IS the last + let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1) + endif + endif + + return output +endfunction +"CLASS: TreeDirNode {{{2 +"This class is a child of the TreeFileNode class and constitutes the +"'Composite' part of the composite design pattern between the treenode +"classes. +"============================================================ +let s:TreeDirNode = copy(s:TreeFileNode) +"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{3 +"class method that returns the highest cached ancestor of the current root +function! s:TreeDirNode.AbsoluteTreeRoot() + let currentNode = b:NERDTreeRoot + while currentNode.parent != {} + let currentNode = currentNode.parent + endwhile + return currentNode +endfunction +"FUNCTION: TreeDirNode.activate(forceKeepWinOpen) {{{3 +unlet s:TreeDirNode.activate +function! s:TreeDirNode.activate(forceKeepWinOpen) + call self.toggleOpen() + call s:renderView() + call self.putCursorHere(0, 0) +endfunction +"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{3 +"Adds the given treenode to the list of children for this node +" +"Args: +"-treenode: the node to add +"-inOrder: 1 if the new node should be inserted in sorted order +function! s:TreeDirNode.addChild(treenode, inOrder) + call add(self.children, a:treenode) + let a:treenode.parent = self + + if a:inOrder + call self.sortChildren() + endif +endfunction + +"FUNCTION: TreeDirNode.close() {{{3 +"Closes this directory +function! s:TreeDirNode.close() + let self.isOpen = 0 +endfunction + +"FUNCTION: TreeDirNode.closeChildren() {{{3 +"Closes all the child dir nodes of this node +function! s:TreeDirNode.closeChildren() + for i in self.children + if i.path.isDirectory + call i.close() + call i.closeChildren() + endif + endfor +endfunction + +"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{3 +"Instantiates a new child node for this node with the given path. The new +"nodes parent is set to this node. +" +"Args: +"path: a Path object that this node will represent/contain +"inOrder: 1 if the new node should be inserted in sorted order +" +"Returns: +"the newly created node +function! s:TreeDirNode.createChild(path, inOrder) + let newTreeNode = s:TreeFileNode.New(a:path) + call self.addChild(newTreeNode, a:inOrder) + return newTreeNode +endfunction + +"FUNCTION: TreeDirNode.findNode(path) {{{3 +"Will find one of the children (recursively) that has the given path +" +"Args: +"path: a path object +unlet s:TreeDirNode.findNode +function! s:TreeDirNode.findNode(path) + if a:path.equals(self.path) + return self + endif + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return {} + endif + + if self.path.isDirectory + for i in self.children + let retVal = i.findNode(a:path) + if retVal != {} + return retVal + endif + endfor + endif + return {} +endfunction +"FUNCTION: TreeDirNode.getChildCount() {{{3 +"Returns the number of children this node has +function! s:TreeDirNode.getChildCount() + return len(self.children) +endfunction + +"FUNCTION: TreeDirNode.getChild(path) {{{3 +"Returns child node of this node that has the given path or {} if no such node +"exists. +" +"This function doesnt not recurse into child dir nodes +" +"Args: +"path: a path object +function! s:TreeDirNode.getChild(path) + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return {} + endif + + let index = self.getChildIndex(a:path) + if index ==# -1 + return {} + else + return self.children[index] + endif + +endfunction + +"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{3 +"returns the child at the given index +"Args: +"indx: the index to get the child from +"visible: 1 if only the visible children array should be used, 0 if all the +"children should be searched. +function! s:TreeDirNode.getChildByIndex(indx, visible) + let array_to_search = a:visible? self.getVisibleChildren() : self.children + if a:indx > len(array_to_search) + throw "NERDTree.InvalidArgumentsError: Index is out of bounds." + endif + return array_to_search[a:indx] +endfunction + +"FUNCTION: TreeDirNode.getChildIndex(path) {{{3 +"Returns the index of the child node of this node that has the given path or +"-1 if no such node exists. +" +"This function doesnt not recurse into child dir nodes +" +"Args: +"path: a path object +function! s:TreeDirNode.getChildIndex(path) + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return -1 + endif + + "do a binary search for the child + let a = 0 + let z = self.getChildCount() + while a < z + let mid = (a+z)/2 + let diff = a:path.compareTo(self.children[mid].path) + + if diff ==# -1 + let z = mid + elseif diff ==# 1 + let a = mid+1 + else + return mid + endif + endwhile + return -1 +endfunction + +"FUNCTION: TreeDirNode.GetSelected() {{{3 +"Returns the current node if it is a dir node, or else returns the current +"nodes parent +unlet s:TreeDirNode.GetSelected +function! s:TreeDirNode.GetSelected() + let currentDir = s:TreeFileNode.GetSelected() + if currentDir != {} && !currentDir.isRoot() + if currentDir.path.isDirectory ==# 0 + let currentDir = currentDir.parent + endif + endif + return currentDir +endfunction +"FUNCTION: TreeDirNode.getVisibleChildCount() {{{3 +"Returns the number of visible children this node has +function! s:TreeDirNode.getVisibleChildCount() + return len(self.getVisibleChildren()) +endfunction + +"FUNCTION: TreeDirNode.getVisibleChildren() {{{3 +"Returns a list of children to display for this node, in the correct order +" +"Return: +"an array of treenodes +function! s:TreeDirNode.getVisibleChildren() + let toReturn = [] + for i in self.children + if i.path.ignore() ==# 0 + call add(toReturn, i) + endif + endfor + return toReturn +endfunction + +"FUNCTION: TreeDirNode.hasVisibleChildren() {{{3 +"returns 1 if this node has any childre, 0 otherwise.. +function! s:TreeDirNode.hasVisibleChildren() + return self.getVisibleChildCount() != 0 +endfunction + +"FUNCTION: TreeDirNode._initChildren() {{{3 +"Removes all childen from this node and re-reads them +" +"Args: +"silent: 1 if the function should not echo any "please wait" messages for +"large directories +" +"Return: the number of child nodes read +function! s:TreeDirNode._initChildren(silent) + "remove all the current child nodes + let self.children = [] + + "get an array of all the files in the nodes dir + let dir = self.path + let globDir = dir.str({'format': 'Glob'}) + let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*') + let files = split(filesStr, "\n") + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call s:echo("Please wait, caching a large dir ...") + endif + + let invalidFilesFound = 0 + for i in files + + "filter out the .. and . directories + "Note: we must match .. AND ../ cos sometimes the globpath returns + "../ for path with strange chars (eg $) + if i !~ '\/\.\.\/\?$' && i !~ '\/\.\/\?$' + + "put the next file in a new node and attach it + try + let path = s:Path.New(i) + call self.createChild(path, 0) + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + let invalidFilesFound += 1 + endtry + endif + endfor + + call self.sortChildren() + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call s:echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).") + endif + + if invalidFilesFound + call s:echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree") + endif + return self.getChildCount() +endfunction +"FUNCTION: TreeDirNode.New(path) {{{3 +"Returns a new TreeNode object with the given path and parent +" +"Args: +"path: a path object representing the full filesystem path to the file/dir that the node represents +unlet s:TreeDirNode.New +function! s:TreeDirNode.New(path) + if a:path.isDirectory != 1 + throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object." + endif + + let newTreeNode = copy(self) + let newTreeNode.path = a:path + + let newTreeNode.isOpen = 0 + let newTreeNode.children = [] + + let newTreeNode.parent = {} + + return newTreeNode +endfunction +"FUNCTION: TreeDirNode.open() {{{3 +"Reads in all this nodes children +" +"Return: the number of child nodes read +unlet s:TreeDirNode.open +function! s:TreeDirNode.open() + let self.isOpen = 1 + if self.children ==# [] + return self._initChildren(0) + else + return 0 + endif +endfunction + +" FUNCTION: TreeDirNode.openExplorer() {{{3 +" opens an explorer window for this node in the previous window (could be a +" nerd tree or a netrw) +function! s:TreeDirNode.openExplorer() + let oldwin = winnr() + call s:exec('wincmd p') + if oldwin ==# winnr() || (&modified && s:bufInWindows(winbufnr(winnr())) < 2) + call s:exec('wincmd p') + call self.openSplit() + else + exec ("silent edit " . self.path.str({'format': 'Edit'})) + endif +endfunction +"FUNCTION: TreeDirNode.openInNewTab(options) {{{3 +unlet s:TreeDirNode.openInNewTab +function! s:TreeDirNode.openInNewTab(options) + let currentTab = tabpagenr() + + if !has_key(a:options, 'keepTreeOpen') || !a:options['keepTreeOpen'] + call s:closeTreeIfQuitOnOpen() + endif + + tabnew + call s:initNerdTree(self.path.str()) + + if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab'] + exec "tabnext " . currentTab + endif +endfunction +"FUNCTION: TreeDirNode.openRecursively() {{{3 +"Opens this treenode and all of its children whose paths arent 'ignored' +"because of the file filters. +" +"This method is actually a wrapper for the OpenRecursively2 method which does +"the work. +function! s:TreeDirNode.openRecursively() + call self._openRecursively2(1) +endfunction + +"FUNCTION: TreeDirNode._openRecursively2() {{{3 +"Opens this all children of this treenode recursively if either: +" *they arent filtered by file filters +" *a:forceOpen is 1 +" +"Args: +"forceOpen: 1 if this node should be opened regardless of file filters +function! s:TreeDirNode._openRecursively2(forceOpen) + if self.path.ignore() ==# 0 || a:forceOpen + let self.isOpen = 1 + if self.children ==# [] + call self._initChildren(1) + endif + + for i in self.children + if i.path.isDirectory ==# 1 + call i._openRecursively2(0) + endif + endfor + endif +endfunction + +"FUNCTION: TreeDirNode.refresh() {{{3 +unlet s:TreeDirNode.refresh +function! s:TreeDirNode.refresh() + call self.path.refresh() + + "if this node was ever opened, refresh its children + if self.isOpen || !empty(self.children) + "go thru all the files/dirs under this node + let newChildNodes = [] + let invalidFilesFound = 0 + let dir = self.path + let globDir = dir.str({'format': 'Glob'}) + let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*') + let files = split(filesStr, "\n") + for i in files + "filter out the .. and . directories + "Note: we must match .. AND ../ cos sometimes the globpath returns + "../ for path with strange chars (eg $) + if i !~ '\/\.\.\/\?$' && i !~ '\/\.\/\?$' + + try + "create a new path and see if it exists in this nodes children + let path = s:Path.New(i) + let newNode = self.getChild(path) + if newNode != {} + call newNode.refresh() + call add(newChildNodes, newNode) + + "the node doesnt exist so create it + else + let newNode = s:TreeFileNode.New(path) + let newNode.parent = self + call add(newChildNodes, newNode) + endif + + + catch /^NERDTree.InvalidArgumentsError/ + let invalidFilesFound = 1 + endtry + endif + endfor + + "swap this nodes children out for the children we just read/refreshed + let self.children = newChildNodes + call self.sortChildren() + + if invalidFilesFound + call s:echoWarning("some files could not be loaded into the NERD tree") + endif + endif +endfunction + +"FUNCTION: TreeDirNode.reveal(path) {{{3 +"reveal the given path, i.e. cache and open all treenodes needed to display it +"in the UI +function! s:TreeDirNode.reveal(path) + if !a:path.isUnder(self.path) + throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str() + endif + + call self.open() + + if self.path.equals(a:path.getParent()) + let n = self.findNode(a:path) + call s:renderView() + call n.putCursorHere(1,0) + return + endif + + let p = a:path + while !p.getParent().equals(self.path) + let p = p.getParent() + endwhile + + let n = self.findNode(p) + call n.reveal(a:path) +endfunction +"FUNCTION: TreeDirNode.removeChild(treenode) {{{3 +" +"Removes the given treenode from this nodes set of children +" +"Args: +"treenode: the node to remove +" +"Throws a NERDTree.ChildNotFoundError if the given treenode is not found +function! s:TreeDirNode.removeChild(treenode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:treenode) + call remove(self.children, i) + return + endif + endfor + + throw "NERDTree.ChildNotFoundError: child node was not found" +endfunction + +"FUNCTION: TreeDirNode.sortChildren() {{{3 +" +"Sorts the children of this node according to alphabetical order and the +"directory priority. +" +function! s:TreeDirNode.sortChildren() + let CompareFunc = function("s:compareNodes") + call sort(self.children, CompareFunc) +endfunction + +"FUNCTION: TreeDirNode.toggleOpen() {{{3 +"Opens this directory if it is closed and vice versa +function! s:TreeDirNode.toggleOpen() + if self.isOpen ==# 1 + call self.close() + else + call self.open() + endif +endfunction + +"FUNCTION: TreeDirNode.transplantChild(newNode) {{{3 +"Replaces the child of this with the given node (where the child node's full +"path matches a:newNode's fullpath). The search for the matching node is +"non-recursive +" +"Arg: +"newNode: the node to graft into the tree +function! s:TreeDirNode.transplantChild(newNode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:newNode) + let self.children[i] = a:newNode + let a:newNode.parent = self + break + endif + endfor +endfunction +"============================================================ +"CLASS: Path {{{2 +"============================================================ +let s:Path = {} +"FUNCTION: Path.AbsolutePathFor(str) {{{3 +function! s:Path.AbsolutePathFor(str) + let prependCWD = 0 + if s:running_windows + let prependCWD = a:str !~ '^.:\(\\\|\/\)' + else + let prependCWD = a:str !~ '^/' + endif + + let toReturn = a:str + if prependCWD + let toReturn = getcwd() . s:Path.Slash() . a:str + endif + + return toReturn +endfunction +"FUNCTION: Path.bookmarkNames() {{{3 +function! s:Path.bookmarkNames() + if !exists("self._bookmarkNames") + call self.cacheDisplayString() + endif + return self._bookmarkNames +endfunction +"FUNCTION: Path.cacheDisplayString() {{{3 +function! s:Path.cacheDisplayString() + let self.cachedDisplayString = self.getLastPathComponent(1) + + if self.isExecutable + let self.cachedDisplayString = self.cachedDisplayString . '*' + endif + + let self._bookmarkNames = [] + for i in s:Bookmark.Bookmarks() + if i.path.equals(self) + call add(self._bookmarkNames, i.name) + endif + endfor + if !empty(self._bookmarkNames) + let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}' + endif + + if self.isSymLink + let self.cachedDisplayString .= ' -> ' . self.symLinkDest + endif + + if self.isReadOnly + let self.cachedDisplayString .= ' [RO]' + endif +endfunction +"FUNCTION: Path.changeToDir() {{{3 +function! s:Path.changeToDir() + let dir = self.str({'format': 'Cd'}) + if self.isDirectory ==# 0 + let dir = self.getParent().str({'format': 'Cd'}) + endif + + try + execute "cd " . dir + call s:echo("CWD is now: " . getcwd()) + catch + throw "NERDTree.PathChangeError: cannot change CWD to " . dir + endtry +endfunction + +"FUNCTION: Path.compareTo() {{{3 +" +"Compares this Path to the given path and returns 0 if they are equal, -1 if +"this Path is "less than" the given path, or 1 if it is "greater". +" +"Args: +"path: the path object to compare this to +" +"Return: +"1, -1 or 0 +function! s:Path.compareTo(path) + let thisPath = self.getLastPathComponent(1) + let thatPath = a:path.getLastPathComponent(1) + + "if the paths are the same then clearly we return 0 + if thisPath ==# thatPath + return 0 + endif + + let thisSS = self.getSortOrderIndex() + let thatSS = a:path.getSortOrderIndex() + + "compare the sort sequences, if they are different then the return + "value is easy + if thisSS < thatSS + return -1 + elseif thisSS > thatSS + return 1 + else + "if the sort sequences are the same then compare the paths + "alphabetically + let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath + if pathCompare + return -1 + else + return 1 + endif + endif +endfunction + +"FUNCTION: Path.Create(fullpath) {{{3 +" +"Factory method. +" +"Creates a path object with the given path. The path is also created on the +"filesystem. If the path already exists, a NERDTree.Path.Exists exception is +"thrown. If any other errors occur, a NERDTree.Path exception is thrown. +" +"Args: +"fullpath: the full filesystem path to the file/dir to create +function! s:Path.Create(fullpath) + "bail if the a:fullpath already exists + if isdirectory(a:fullpath) || filereadable(a:fullpath) + throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'" + endif + + try + + "if it ends with a slash, assume its a dir create it + if a:fullpath =~ '\(\\\|\/\)$' + "whack the trailing slash off the end if it exists + let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '') + + call mkdir(fullpath, 'p') + + "assume its a file and create + else + call writefile([], a:fullpath) + endif + catch + throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'" + endtry + + return s:Path.New(a:fullpath) +endfunction + +"FUNCTION: Path.copy(dest) {{{3 +" +"Copies the file/dir represented by this Path to the given location +" +"Args: +"dest: the location to copy this dir/file to +function! s:Path.copy(dest) + if !s:Path.CopyingSupported() + throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS" + endif + + let dest = s:Path.WinToUnixPath(a:dest) + + let cmd = g:NERDTreeCopyCmd . " " . self.str() . " " . dest + let success = system(cmd) + if success != 0 + throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'" + endif +endfunction + +"FUNCTION: Path.CopyingSupported() {{{3 +" +"returns 1 if copying is supported for this OS +function! s:Path.CopyingSupported() + return exists('g:NERDTreeCopyCmd') +endfunction + + +"FUNCTION: Path.copyingWillOverwrite(dest) {{{3 +" +"returns 1 if copy this path to the given location will cause files to +"overwritten +" +"Args: +"dest: the location this path will be copied to +function! s:Path.copyingWillOverwrite(dest) + if filereadable(a:dest) + return 1 + endif + + if isdirectory(a:dest) + let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0)) + if filereadable(path) + return 1 + endif + endif +endfunction + +"FUNCTION: Path.delete() {{{3 +" +"Deletes the file represented by this path. +"Deletion of directories is not supported +" +"Throws NERDTree.Path.Deletion exceptions +function! s:Path.delete() + if self.isDirectory + + let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1}) + let success = system(cmd) + + if v:shell_error != 0 + throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'" + endif + else + let success = delete(self.str()) + if success != 0 + throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'" + endif + endif + + "delete all bookmarks for this path + for i in self.bookmarkNames() + let bookmark = s:Bookmark.BookmarkFor(i) + call bookmark.delete() + endfor +endfunction + +"FUNCTION: Path.displayString() {{{3 +" +"Returns a string that specifies how the path should be represented as a +"string +function! s:Path.displayString() + if self.cachedDisplayString ==# "" + call self.cacheDisplayString() + endif + + return self.cachedDisplayString +endfunction +"FUNCTION: Path.extractDriveLetter(fullpath) {{{3 +" +"If running windows, cache the drive letter for this path +function! s:Path.extractDriveLetter(fullpath) + if s:running_windows + let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '') + else + let self.drive = '' + endif + +endfunction +"FUNCTION: Path.exists() {{{3 +"return 1 if this path points to a location that is readable or is a directory +function! s:Path.exists() + let p = self.str() + return filereadable(p) || isdirectory(p) +endfunction +"FUNCTION: Path.getDir() {{{3 +" +"Returns this path if it is a directory, else this paths parent. +" +"Return: +"a Path object +function! s:Path.getDir() + if self.isDirectory + return self + else + return self.getParent() + endif +endfunction +"FUNCTION: Path.getParent() {{{3 +" +"Returns a new path object for this paths parent +" +"Return: +"a new Path object +function! s:Path.getParent() + if s:running_windows + let path = self.drive . '\' . join(self.pathSegments[0:-2], '\') + else + let path = '/'. join(self.pathSegments[0:-2], '/') + endif + + return s:Path.New(path) +endfunction +"FUNCTION: Path.getLastPathComponent(dirSlash) {{{3 +" +"Gets the last part of this path. +" +"Args: +"dirSlash: if 1 then a trailing slash will be added to the returned value for +"directory nodes. +function! s:Path.getLastPathComponent(dirSlash) + if empty(self.pathSegments) + return '' + endif + let toReturn = self.pathSegments[-1] + if a:dirSlash && self.isDirectory + let toReturn = toReturn . '/' + endif + return toReturn +endfunction + +"FUNCTION: Path.getSortOrderIndex() {{{3 +"returns the index of the pattern in g:NERDTreeSortOrder that this path matches +function! s:Path.getSortOrderIndex() + let i = 0 + while i < len(g:NERDTreeSortOrder) + if self.getLastPathComponent(1) =~ g:NERDTreeSortOrder[i] + return i + endif + let i = i + 1 + endwhile + return s:NERDTreeSortStarIndex +endfunction + +"FUNCTION: Path.ignore() {{{3 +"returns true if this path should be ignored +function! s:Path.ignore() + let lastPathComponent = self.getLastPathComponent(0) + + "filter out the user specified paths to ignore + if b:NERDTreeIgnoreEnabled + for i in g:NERDTreeIgnore + if lastPathComponent =~ i + return 1 + endif + endfor + endif + + "dont show hidden files unless instructed to + if b:NERDTreeShowHidden ==# 0 && lastPathComponent =~ '^\.' + return 1 + endif + + if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0 + return 1 + endif + + return 0 +endfunction + +"FUNCTION: Path.isUnder(path) {{{3 +"return 1 if this path is somewhere under the given path in the filesystem. +" +"a:path should be a dir +function! s:Path.isUnder(path) + if a:path.isDirectory == 0 + return 0 + endif + + let this = self.str() + let that = a:path.str() + return stridx(this, that . s:Path.Slash()) == 0 +endfunction + +"FUNCTION: Path.JoinPathStrings(...) {{{3 +function! s:Path.JoinPathStrings(...) + let components = [] + for i in a:000 + let components = extend(components, split(i, '/')) + endfor + return '/' . join(components, '/') +endfunction + +"FUNCTION: Path.equals() {{{3 +" +"Determines whether 2 path objects are "equal". +"They are equal if the paths they represent are the same +" +"Args: +"path: the other path obj to compare this with +function! s:Path.equals(path) + return self.str() ==# a:path.str() +endfunction + +"FUNCTION: Path.New() {{{3 +"The Constructor for the Path object +function! s:Path.New(path) + let newPath = copy(self) + + call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path)) + + let newPath.cachedDisplayString = "" + + return newPath +endfunction + +"FUNCTION: Path.Slash() {{{3 +"return the slash to use for the current OS +function! s:Path.Slash() + return s:running_windows ? '\' : '/' +endfunction + +"FUNCTION: Path.readInfoFromDisk(fullpath) {{{3 +" +" +"Throws NERDTree.Path.InvalidArguments exception. +function! s:Path.readInfoFromDisk(fullpath) + call self.extractDriveLetter(a:fullpath) + + let fullpath = s:Path.WinToUnixPath(a:fullpath) + + if getftype(fullpath) ==# "fifo" + throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath + endif + + let self.pathSegments = split(fullpath, '/') + + let self.isReadOnly = 0 + if isdirectory(a:fullpath) + let self.isDirectory = 1 + elseif filereadable(a:fullpath) + let self.isDirectory = 0 + let self.isReadOnly = filewritable(a:fullpath) ==# 0 + else + throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath + endif + + let self.isExecutable = 0 + if !self.isDirectory + let self.isExecutable = getfperm(a:fullpath) =~ 'x' + endif + + "grab the last part of the path (minus the trailing slash) + let lastPathComponent = self.getLastPathComponent(0) + + "get the path to the new node with the parent dir fully resolved + let hardPath = resolve(self.strTrunk()) . '/' . lastPathComponent + + "if the last part of the path is a symlink then flag it as such + let self.isSymLink = (resolve(hardPath) != hardPath) + if self.isSymLink + let self.symLinkDest = resolve(fullpath) + + "if the link is a dir then slap a / on the end of its dest + if isdirectory(self.symLinkDest) + + "we always wanna treat MS windows shortcuts as files for + "simplicity + if hardPath !~ '\.lnk$' + + let self.symLinkDest = self.symLinkDest . '/' + endif + endif + endif +endfunction + +"FUNCTION: Path.refresh() {{{3 +function! s:Path.refresh() + call self.readInfoFromDisk(self.str()) + call self.cacheDisplayString() +endfunction + +"FUNCTION: Path.rename() {{{3 +" +"Renames this node on the filesystem +function! s:Path.rename(newPath) + if a:newPath ==# '' + throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath + endif + + let success = rename(self.str(), a:newPath) + if success != 0 + throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath + endif + call self.readInfoFromDisk(a:newPath) + + for i in self.bookmarkNames() + let b = s:Bookmark.BookmarkFor(i) + call b.setPath(copy(self)) + endfor + call s:Bookmark.Write() +endfunction + +"FUNCTION: Path.str() {{{3 +" +"Returns a string representation of this Path +" +"Takes an optional dictionary param to specify how the output should be +"formatted. +" +"The dict may have the following keys: +" 'format' +" 'escape' +" 'truncateTo' +" +"The 'format' key may have a value of: +" 'Cd' - a string to be used with the :cd command +" 'Edit' - a string to be used with :e :sp :new :tabedit etc +" 'UI' - a string used in the NERD tree UI +" +"The 'escape' key, if specified will cause the output to be escaped with +"shellescape() +" +"The 'truncateTo' key causes the resulting string to be truncated to the value +"'truncateTo' maps to. A '<' char will be prepended. +function! s:Path.str(...) + let options = a:0 ? a:1 : {} + let toReturn = "" + + if has_key(options, 'format') + let format = options['format'] + if has_key(self, '_strFor' . format) + exec 'let toReturn = self._strFor' . format . '()' + else + raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"' + endif + else + let toReturn = self._str() + endif + + if has_key(options, 'escape') && options['escape'] + let toReturn = shellescape(toReturn) + endif + + if has_key(options, 'truncateTo') + let limit = options['truncateTo'] + if len(toReturn) > limit + let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1) + endif + endif + + return toReturn +endfunction + +"FUNCTION: Path._strForUI() {{{3 +function! s:Path._strForUI() + let toReturn = '/' . join(self.pathSegments, '/') + if self.isDirectory && toReturn != '/' + let toReturn = toReturn . '/' + endif + return toReturn +endfunction + +"FUNCTION: Path._strForCd() {{{3 +" +" returns a string that can be used with :cd +function! s:Path._strForCd() + return escape(self.str(), s:escape_chars) +endfunction +"FUNCTION: Path._strForEdit() {{{3 +" +"Return: the string for this path that is suitable to be used with the :edit +"command +function! s:Path._strForEdit() + let p = self.str({'format': 'UI'}) + let cwd = getcwd() + + if s:running_windows + let p = tolower(self.str()) + let cwd = tolower(getcwd()) + endif + + let p = escape(p, s:escape_chars) + + let cwd = cwd . s:Path.Slash() + + "return a relative path if we can + if stridx(p, cwd) ==# 0 + let p = strpart(p, strlen(cwd)) + endif + + if p ==# '' + let p = '.' + endif + + return p + +endfunction +"FUNCTION: Path._strForGlob() {{{3 +function! s:Path._strForGlob() + let lead = s:Path.Slash() + + "if we are running windows then slap a drive letter on the front + if s:running_windows + let lead = self.drive . '\' + endif + + let toReturn = lead . join(self.pathSegments, s:Path.Slash()) + + if !s:running_windows + let toReturn = escape(toReturn, s:escape_chars) + endif + return toReturn +endfunction +"FUNCTION: Path._str() {{{3 +" +"Gets the string path for this path object that is appropriate for the OS. +"EG, in windows c:\foo\bar +" in *nix /foo/bar +function! s:Path._str() + let lead = s:Path.Slash() + + "if we are running windows then slap a drive letter on the front + if s:running_windows + let lead = self.drive . '\' + endif + + return lead . join(self.pathSegments, s:Path.Slash()) +endfunction + +"FUNCTION: Path.strTrunk() {{{3 +"Gets the path without the last segment on the end. +function! s:Path.strTrunk() + return self.drive . '/' . join(self.pathSegments[0:-2], '/') +endfunction + +"FUNCTION: Path.WinToUnixPath(pathstr){{{3 +"Takes in a windows path and returns the unix equiv +" +"A class level method +" +"Args: +"pathstr: the windows path to convert +function! s:Path.WinToUnixPath(pathstr) + if !s:running_windows + return a:pathstr + endif + + let toReturn = a:pathstr + + "remove the x:\ of the front + let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "") + + "convert all \ chars to / + let toReturn = substitute(toReturn, '\', '/', "g") + + return toReturn +endfunction + +" SECTION: General Functions {{{1 +"============================================================ +"FUNCTION: s:bufInWindows(bnum){{{2 +"[[STOLEN FROM VTREEEXPLORER.VIM]] +"Determine the number of windows open to this buffer number. +"Care of Yegappan Lakshman. Thanks! +" +"Args: +"bnum: the subject buffers buffer number +function! s:bufInWindows(bnum) + let cnt = 0 + let winnum = 1 + while 1 + let bufnum = winbufnr(winnum) + if bufnum < 0 + break + endif + if bufnum ==# a:bnum + let cnt = cnt + 1 + endif + let winnum = winnum + 1 + endwhile + + return cnt +endfunction " >>> +"FUNCTION: s:checkForBrowse(dir) {{{2 +"inits a secondary nerd tree in the current buffer if appropriate +function! s:checkForBrowse(dir) + if a:dir != '' && isdirectory(a:dir) + call s:initNerdTreeInPlace(a:dir) + endif +endfunction +"FUNCTION: s:compareBookmarks(first, second) {{{2 +"Compares two bookmarks +function! s:compareBookmarks(first, second) + return a:first.compareTo(a:second) +endfunction + +" FUNCTION: s:completeBookmarks(A,L,P) {{{2 +" completion function for the bookmark commands +function! s:completeBookmarks(A,L,P) + return filter(s:Bookmark.BookmarkNames(), 'v:val =~ "^' . a:A . '"') +endfunction +" FUNCTION: s:exec(cmd) {{{2 +" same as :exec cmd but eventignore=all is set for the duration +function! s:exec(cmd) + let old_ei = &ei + set ei=all + exec a:cmd + let &ei = old_ei +endfunction +" FUNCTION: s:findAndRevealPath() {{{2 +function! s:findAndRevealPath() + try + let p = s:Path.New(expand("%")) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("no file for the current buffer") + return + endtry + + if !s:treeExistsForTab() + call s:initNerdTree(p.getParent().str()) + else + if !p.isUnder(s:TreeFileNode.GetRootForTab().path) + call s:initNerdTree(p.getParent().str()) + else + if !s:isTreeOpen() + call s:toggle("") + endif + endif + endif + call s:putCursorInTreeWin() + call b:NERDTreeRoot.reveal(p) +endfunction +"FUNCTION: s:initNerdTree(name) {{{2 +"Initialise the nerd tree for this tab. The tree will start in either the +"given directory, or the directory associated with the given bookmark +" +"Args: +"name: the name of a bookmark or a directory +function! s:initNerdTree(name) + let path = {} + if s:Bookmark.BookmarkExistsFor(a:name) + let path = s:Bookmark.BookmarkFor(a:name).path + else + let dir = a:name ==# '' ? getcwd() : a:name + + "hack to get an absolute path if a relative path is given + if dir =~ '^\.' + let dir = getcwd() . s:Path.Slash() . dir + endif + let dir = resolve(dir) + + try + let path = s:Path.New(dir) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("No bookmark or directory found for: " . a:name) + return + endtry + endif + if !path.isDirectory + let path = path.getParent() + endif + + "if instructed to, then change the vim CWD to the dir the NERDTree is + "inited in + if g:NERDTreeChDirMode != 0 + call path.changeToDir() + endif + + if s:treeExistsForTab() + if s:isTreeOpen() + call s:closeTree() + endif + unlet t:NERDTreeBufName + endif + + let newRoot = s:TreeDirNode.New(path) + call newRoot.open() + + call s:createTreeWin() + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + let b:NERDTreeRoot = newRoot + + let b:NERDTreeType = "primary" + + call s:renderView() + call b:NERDTreeRoot.putCursorHere(0, 0) +endfunction + +"FUNCTION: s:initNerdTreeInPlace(dir) {{{2 +function! s:initNerdTreeInPlace(dir) + try + let path = s:Path.New(a:dir) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("Invalid directory name:" . a:name) + return + endtry + + "we want the directory buffer to disappear when we do the :edit below + setlocal bufhidden=wipe + + let previousBuf = expand("#") + + "we need a unique name for each secondary tree buffer to ensure they are + "all independent + exec "silent edit " . s:nextBufferName() + + let b:NERDTreePreviousBuf = bufnr(previousBuf) + + let b:NERDTreeRoot = s:TreeDirNode.New(path) + call b:NERDTreeRoot.open() + + "throwaway buffer options + setlocal noswapfile + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + if g:NERDTreeShowLineNumbers + setlocal nu + else + setlocal nonu + endif + + iabc <buffer> + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call s:setupStatusline() + + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + + let b:NERDTreeType = "secondary" + + call s:bindMappings() + setfiletype nerdtree + " syntax highlighting + if has("syntax") && exists("g:syntax_on") + call s:setupSyntaxHighlighting() + endif + + call s:renderView() +endfunction +" FUNCTION: s:initNerdTreeMirror() {{{2 +function! s:initNerdTreeMirror() + + "get the names off all the nerd tree buffers + let treeBufNames = [] + for i in range(1, tabpagenr("$")) + let nextName = s:tabpagevar(i, 'NERDTreeBufName') + if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName) + call add(treeBufNames, nextName) + endif + endfor + let treeBufNames = s:unique(treeBufNames) + + "map the option names (that the user will be prompted with) to the nerd + "tree buffer names + let options = {} + let i = 0 + while i < len(treeBufNames) + let bufName = treeBufNames[i] + let treeRoot = getbufvar(bufName, "NERDTreeRoot") + let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName + let i = i + 1 + endwhile + + "work out which tree to mirror, if there is more than 1 then ask the user + let bufferName = '' + if len(keys(options)) > 1 + let choices = ["Choose a tree to mirror"] + let choices = extend(choices, sort(keys(options))) + let choice = inputlist(choices) + if choice < 1 || choice > len(options) || choice ==# '' + return + endif + + let bufferName = options[sort(keys(options))[choice-1]] + elseif len(keys(options)) ==# 1 + let bufferName = values(options)[0] + else + call s:echo("No trees to mirror") + return + endif + + if s:treeExistsForTab() && s:isTreeOpen() + call s:closeTree() + endif + + let t:NERDTreeBufName = bufferName + call s:createTreeWin() + exec 'buffer ' . bufferName + if !&hidden + call s:renderView() + endif +endfunction +" FUNCTION: s:nextBufferName() {{{2 +" returns the buffer name for the next nerd tree +function! s:nextBufferName() + let name = s:NERDTreeBufName . s:next_buffer_number + let s:next_buffer_number += 1 + return name +endfunction +" FUNCTION: s:tabpagevar(tabnr, var) {{{2 +function! s:tabpagevar(tabnr, var) + let currentTab = tabpagenr() + let old_ei = &ei + set ei=all + + exec "tabnext " . a:tabnr + let v = -1 + if exists('t:' . a:var) + exec 'let v = t:' . a:var + endif + exec "tabnext " . currentTab + + let &ei = old_ei + + return v +endfunction +" Function: s:treeExistsForBuffer() {{{2 +" Returns 1 if a nerd tree root exists in the current buffer +function! s:treeExistsForBuf() + return exists("b:NERDTreeRoot") +endfunction +" Function: s:treeExistsForTab() {{{2 +" Returns 1 if a nerd tree root exists in the current tab +function! s:treeExistsForTab() + return exists("t:NERDTreeBufName") +endfunction +" Function: s:unique(list) {{{2 +" returns a:list without duplicates +function! s:unique(list) + let uniqlist = [] + for elem in a:list + if index(uniqlist, elem) ==# -1 + let uniqlist += [elem] + endif + endfor + return uniqlist +endfunction +" SECTION: Public API {{{1 +"============================================================ +let g:NERDTreePath = s:Path +let g:NERDTreeDirNode = s:TreeDirNode +let g:NERDTreeFileNode = s:TreeFileNode +let g:NERDTreeBookmark = s:Bookmark + +function! NERDTreeAddMenuItem(options) + call s:MenuItem.Create(a:options) +endfunction + +function! NERDTreeAddMenuSeparator(...) + let opts = a:0 ? a:1 : {} + call s:MenuItem.CreateSeparator(opts) +endfunction + +function! NERDTreeAddSubmenu(options) + return s:MenuItem.Create(a:options) +endfunction + +function! NERDTreeAddKeyMap(options) + call s:KeyMap.Create(a:options) +endfunction + +function! NERDTreeRender() + call s:renderView() +endfunction + +" SECTION: View Functions {{{1 +"============================================================ +"FUNCTION: s:centerView() {{{2 +"centers the nerd tree window around the cursor (provided the nerd tree +"options permit) +function! s:centerView() + if g:NERDTreeAutoCenter + let current_line = winline() + let lines_to_top = current_line + let lines_to_bottom = winheight(s:getTreeWinNum()) - current_line + if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold + normal! zz + endif + endif +endfunction +"FUNCTION: s:closeTree() {{{2 +"Closes the primary NERD tree window for this tab +function! s:closeTree() + if !s:isTreeOpen() + throw "NERDTree.NoTreeFoundError: no NERDTree is open" + endif + + if winnr("$") != 1 + call s:exec(s:getTreeWinNum() . " wincmd w") + close + call s:exec("wincmd p") + else + close + endif +endfunction + +"FUNCTION: s:closeTreeIfOpen() {{{2 +"Closes the NERD tree window if it is open +function! s:closeTreeIfOpen() + if s:isTreeOpen() + call s:closeTree() + endif +endfunction +"FUNCTION: s:closeTreeIfQuitOnOpen() {{{2 +"Closes the NERD tree window if the close on open option is set +function! s:closeTreeIfQuitOnOpen() + if g:NERDTreeQuitOnOpen && s:isTreeOpen() + call s:closeTree() + endif +endfunction +"FUNCTION: s:createTreeWin() {{{2 +"Inits the NERD tree window. ie. opens it, sizes it, sets all the local +"options etc +function! s:createTreeWin() + "create the nerd tree window + let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright " + let splitSize = g:NERDTreeWinSize + + if !exists('t:NERDTreeBufName') + let t:NERDTreeBufName = s:nextBufferName() + silent! exec splitLocation . 'vertical ' . splitSize . ' new' + silent! exec "edit " . t:NERDTreeBufName + else + silent! exec splitLocation . 'vertical ' . splitSize . ' split' + silent! exec "buffer " . t:NERDTreeBufName + endif + + setlocal winfixwidth + + "throwaway buffer options + setlocal noswapfile + setlocal buftype=nofile + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + if g:NERDTreeShowLineNumbers + setlocal nu + else + setlocal nonu + endif + + iabc <buffer> + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call s:setupStatusline() + + call s:bindMappings() + setfiletype nerdtree + " syntax highlighting + if has("syntax") && exists("g:syntax_on") + call s:setupSyntaxHighlighting() + endif +endfunction + +"FUNCTION: s:dumpHelp {{{2 +"prints out the quick help +function! s:dumpHelp() + let old_h = @h + if b:treeShowHelp ==# 1 + let @h= "\" NERD tree (" . s:NERD_tree_version . ") quickhelp~\n" + let @h=@h."\" ============================\n" + let @h=@h."\" File node mappings~\n" + let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n" + let @h=@h."\" <CR>,\n" + if b:NERDTreeType ==# "primary" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n" + else + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n" + endif + if b:NERDTreeType ==# "primary" + let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n" + endif + let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let @h=@h."\" middle-click,\n" + let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n" + let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n" + let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n" + let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Directory node mappings~\n" + let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n" + let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n" + let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n" + let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n" + let @h=@h."\" current node recursively\n" + let @h=@h."\" middle-click,\n" + let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Bookmark table mappings~\n" + let @h=@h."\" double-click,\n" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Tree navigation mappings~\n" + let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n" + let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n" + let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n" + let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n" + let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n" + let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Filesystem mappings~\n" + let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n" + let @h=@h."\" selected dir\n" + let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n" + let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n" + let @h=@h."\" but leave old root open\n" + let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n" + let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n" + let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n" + let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n" + let @h=@h."\" selected dir\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Tree filtering mappings~\n" + let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n" + + "add quickhelp entries for each custom key map + if len(s:KeyMap.All()) + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Custom mappings~\n" + for i in s:KeyMap.All() + let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n" + endfor + endif + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Other mappings~\n" + let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n" + let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n" + let @h=@h."\" the NERDTree window\n" + let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n" + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Bookmark commands~\n" + let @h=@h."\" :Bookmark <name>\n" + let @h=@h."\" :BookmarkToRoot <name>\n" + let @h=@h."\" :RevealBookmark <name>\n" + let @h=@h."\" :OpenBookmark <name>\n" + let @h=@h."\" :ClearBookmarks [<names>]\n" + let @h=@h."\" :ClearAllBookmarks\n" + else + let @h="\" Press ". g:NERDTreeMapHelp ." for help\n" + endif + + silent! put h + + let @h = old_h +endfunction +"FUNCTION: s:echo {{{2 +"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages +" +"Args: +"msg: the message to echo +function! s:echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction +"FUNCTION: s:echoWarning {{{2 +"Wrapper for s:echo, sets the message type to warningmsg for this message +"Args: +"msg: the message to echo +function! s:echoWarning(msg) + echohl warningmsg + call s:echo(a:msg) + echohl normal +endfunction +"FUNCTION: s:echoError {{{2 +"Wrapper for s:echo, sets the message type to errormsg for this message +"Args: +"msg: the message to echo +function! s:echoError(msg) + echohl errormsg + call s:echo(a:msg) + echohl normal +endfunction +"FUNCTION: s:firstUsableWindow(){{{2 +"find the window number of the first normal window +function! s:firstUsableWindow() + let i = 1 + while i <= winnr("$") + let bnum = winbufnr(i) + if bnum != -1 && getbufvar(bnum, '&buftype') ==# '' + \ && !getwinvar(i, '&previewwindow') + \ && (!getbufvar(bnum, '&modified') || &hidden) + return i + endif + + let i += 1 + endwhile + return -1 +endfunction +"FUNCTION: s:getPath(ln) {{{2 +"Gets the full path to the node that is rendered on the given line number +" +"Args: +"ln: the line number to get the path for +" +"Return: +"A path if a node was selected, {} if nothing is selected. +"If the 'up a dir' line was selected then the path to the parent of the +"current root is returned +function! s:getPath(ln) + let line = getline(a:ln) + + let rootLine = s:TreeFileNode.GetRootLineNum() + + "check to see if we have the root node + if a:ln == rootLine + return b:NERDTreeRoot.path + endif + + " in case called from outside the tree + if line !~ '^ *[|`]' || line =~ '^$' + return {} + endif + + if line ==# s:tree_up_dir_line + return b:NERDTreeRoot.path.getParent() + endif + + let indent = s:indentLevelFor(line) + + "remove the tree parts and the leading space + let curFile = s:stripMarkupFromLine(line, 0) + + let wasdir = 0 + if curFile =~ '/$' + let wasdir = 1 + let curFile = substitute(curFile, '/\?$', '/', "") + endif + + let dir = "" + let lnum = a:ln + while lnum > 0 + let lnum = lnum - 1 + let curLine = getline(lnum) + let curLineStripped = s:stripMarkupFromLine(curLine, 1) + + "have we reached the top of the tree? + if lnum == rootLine + let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir + break + endif + if curLineStripped =~ '/$' + let lpindent = s:indentLevelFor(curLine) + if lpindent < indent + let indent = indent - 1 + + let dir = substitute (curLineStripped,'^\\', "", "") . dir + continue + endif + endif + endwhile + let curFile = b:NERDTreeRoot.path.drive . dir . curFile + let toReturn = s:Path.New(curFile) + return toReturn +endfunction + +"FUNCTION: s:getTreeWinNum() {{{2 +"gets the nerd tree window number for this tab +function! s:getTreeWinNum() + if exists("t:NERDTreeBufName") + return bufwinnr(t:NERDTreeBufName) + else + return -1 + endif +endfunction +"FUNCTION: s:indentLevelFor(line) {{{2 +function! s:indentLevelFor(line) + return match(a:line, '[^ \-+~`|]') / s:tree_wid +endfunction +"FUNCTION: s:isTreeOpen() {{{2 +function! s:isTreeOpen() + return s:getTreeWinNum() != -1 +endfunction +"FUNCTION: s:isWindowUsable(winnumber) {{{2 +"Returns 0 if opening a file from the tree in the given window requires it to +"be split, 1 otherwise +" +"Args: +"winnumber: the number of the window in question +function! s:isWindowUsable(winnumber) + "gotta split if theres only one window (i.e. the NERD tree) + if winnr("$") ==# 1 + return 0 + endif + + let oldwinnr = winnr() + call s:exec(a:winnumber . "wincmd p") + let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') + let modified = &modified + call s:exec(oldwinnr . "wincmd p") + + "if its a special window e.g. quickfix or another explorer plugin then we + "have to split + if specialWindow + return 0 + endif + + if &hidden + return 1 + endif + + return !modified || s:bufInWindows(winbufnr(a:winnumber)) >= 2 +endfunction + +" FUNCTION: s:jumpToChild(direction) {{{2 +" Args: +" direction: 0 if going to first child, 1 if going to last +function! s:jumpToChild(direction) + let currentNode = s:TreeFileNode.GetSelected() + if currentNode ==# {} || currentNode.isRoot() + call s:echo("cannot jump to " . (a:direction ? "last" : "first") . " child") + return + end + let dirNode = currentNode.parent + let childNodes = dirNode.getVisibleChildren() + + let targetNode = childNodes[0] + if a:direction + let targetNode = childNodes[len(childNodes) - 1] + endif + + if targetNode.equals(currentNode) + let siblingDir = currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction) + if siblingDir != {} + let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0 + let targetNode = siblingDir.getChildByIndex(indx, 1) + endif + endif + + call targetNode.putCursorHere(1, 0) + + call s:centerView() +endfunction + + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{2 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if nr2char(getchar()) ==# 'y' + exec "silent bdelete! " . a:bufnum + endif +endfunction + +"FUNCTION: s:putCursorOnBookmarkTable(){{{2 +"Places the cursor at the top of the bookmarks table +function! s:putCursorOnBookmarkTable() + if !b:NERDTreeShowBookmarks + throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active" + endif + + let rootNodeLine = s:TreeFileNode.GetRootLineNum() + + let line = 1 + while getline(line) !~ '^>-\+Bookmarks-\+$' + let line = line + 1 + if line >= rootNodeLine + throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table" + endif + endwhile + call cursor(line, 0) +endfunction + +"FUNCTION: s:putCursorInTreeWin(){{{2 +"Places the cursor in the nerd tree window +function! s:putCursorInTreeWin() + if !s:isTreeOpen() + throw "NERDTree.InvalidOperationError: cant put cursor in NERD tree window, no window exists" + endif + + call s:exec(s:getTreeWinNum() . "wincmd w") +endfunction + +"FUNCTION: s:renderBookmarks {{{2 +function! s:renderBookmarks() + + call setline(line(".")+1, ">----------Bookmarks----------") + call cursor(line(".")+1, col(".")) + + for i in s:Bookmark.Bookmarks() + call setline(line(".")+1, i.str()) + call cursor(line(".")+1, col(".")) + endfor + + call setline(line(".")+1, '') + call cursor(line(".")+1, col(".")) +endfunction +"FUNCTION: s:renderView {{{2 +"The entry function for rendering the tree +function! s:renderView() + setlocal modifiable + + "remember the top line of the buffer and the current line so we can + "restore the view exactly how it was + let curLine = line(".") + let curCol = col(".") + let topLine = line("w0") + + "delete all lines in the buffer (being careful not to clobber a register) + silent 1,$delete _ + + call s:dumpHelp() + + "delete the blank line before the help and add one after it + call setline(line(".")+1, "") + call cursor(line(".")+1, col(".")) + + if b:NERDTreeShowBookmarks + call s:renderBookmarks() + endif + + "add the 'up a dir' line + call setline(line(".")+1, s:tree_up_dir_line) + call cursor(line(".")+1, col(".")) + + "draw the header line + let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)}) + call setline(line(".")+1, header) + call cursor(line(".")+1, col(".")) + + "draw the tree + let old_o = @o + let @o = b:NERDTreeRoot.renderToString() + silent put o + let @o = old_o + + "delete the blank line at the top of the buffer + silent 1,1delete _ + + "restore the view + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(topLine, 1) + normal! zt + call cursor(curLine, curCol) + let &scrolloff = old_scrolloff + + setlocal nomodifiable +endfunction + +"FUNCTION: s:renderViewSavingPosition {{{2 +"Renders the tree and ensures the cursor stays on the current node or the +"current nodes parent if it is no longer available upon re-rendering +function! s:renderViewSavingPosition() + let currentNode = s:TreeFileNode.GetSelected() + + "go up the tree till we find a node that will be visible or till we run + "out of nodes + while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot() + let currentNode = currentNode.parent + endwhile + + call s:renderView() + + if currentNode != {} + call currentNode.putCursorHere(0, 0) + endif +endfunction +"FUNCTION: s:restoreScreenState() {{{2 +" +"Sets the screen state back to what it was when s:saveScreenState was last +"called. +" +"Assumes the cursor is in the NERDTree window +function! s:restoreScreenState() + if !exists("b:NERDTreeOldTopLine") || !exists("b:NERDTreeOldPos") || !exists("b:NERDTreeOldWindowSize") + return + endif + exec("silent vertical resize ".b:NERDTreeOldWindowSize) + + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(b:NERDTreeOldTopLine, 0) + normal! zt + call setpos(".", b:NERDTreeOldPos) + let &scrolloff=old_scrolloff +endfunction + +"FUNCTION: s:saveScreenState() {{{2 +"Saves the current cursor position in the current buffer and the window +"scroll position +function! s:saveScreenState() + let win = winnr() + try + call s:putCursorInTreeWin() + let b:NERDTreeOldPos = getpos(".") + let b:NERDTreeOldTopLine = line("w0") + let b:NERDTreeOldWindowSize = winwidth("") + call s:exec(win . "wincmd w") + catch /^NERDTree.InvalidOperationError/ + endtry +endfunction + +"FUNCTION: s:setupStatusline() {{{2 +function! s:setupStatusline() + if g:NERDTreeStatusline != -1 + let &l:statusline = g:NERDTreeStatusline + endif +endfunction +"FUNCTION: s:setupSyntaxHighlighting() {{{2 +function! s:setupSyntaxHighlighting() + "treeFlags are syntax items that should be invisible, but give clues as to + "how things should be highlighted + syn match treeFlag #\~# + syn match treeFlag #\[RO\]# + + "highlighting for the .. (up dir) line at the top of the tree + execute "syn match treeUp #". s:tree_up_dir_line ."#" + + "highlighting for the ~/+ symbols for the directory nodes + syn match treeClosable #\~\<# + syn match treeClosable #\~\.# + syn match treeOpenable #+\<# + syn match treeOpenable #+\.#he=e-1 + + "highlighting for the tree structural parts + syn match treePart #|# + syn match treePart #`# + syn match treePartFile #[|`]-#hs=s+1 contains=treePart + + "quickhelp syntax elements + syn match treeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1 + syn match treeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1 + syn match treeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=treeFlag + syn match treeToggleOn #".*(on)#hs=e-2,he=e-1 contains=treeHelpKey + syn match treeToggleOff #".*(off)#hs=e-3,he=e-1 contains=treeHelpKey + syn match treeHelpCommand #" :.\{-}\>#hs=s+3 + syn match treeHelp #^".*# contains=treeHelpKey,treeHelpTitle,treeFlag,treeToggleOff,treeToggleOn,treeHelpCommand + + "highlighting for readonly files + syn match treeRO #.*\[RO\]#hs=s+2 contains=treeFlag,treeBookmark,treePart,treePartFile + + "highlighting for sym links + syn match treeLink #[^-| `].* -> # contains=treeBookmark,treeOpenable,treeClosable,treeDirSlash + + "highlighing for directory nodes and file nodes + syn match treeDirSlash #/# + syn match treeDir #[^-| `].*/# contains=treeLink,treeDirSlash,treeOpenable,treeClosable + syn match treeExecFile #[|`]-.*\*\($\| \)# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark + syn match treeFile #|-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile + syn match treeFile #`-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile + syn match treeCWD #^/.*$# + + "highlighting for bookmarks + syn match treeBookmark # {.*}#hs=s+1 + + "highlighting for the bookmarks table + syn match treeBookmarksLeader #^># + syn match treeBookmarksHeader #^>-\+Bookmarks-\+$# contains=treeBookmarksLeader + syn match treeBookmarkName #^>.\{-} #he=e-1 contains=treeBookmarksLeader + syn match treeBookmark #^>.*$# contains=treeBookmarksLeader,treeBookmarkName,treeBookmarksHeader + + if g:NERDChristmasTree + hi def link treePart Special + hi def link treePartFile Type + hi def link treeFile Normal + hi def link treeExecFile Title + hi def link treeDirSlash Identifier + hi def link treeClosable Type + else + hi def link treePart Normal + hi def link treePartFile Normal + hi def link treeFile Normal + hi def link treeClosable Title + endif + + hi def link treeBookmarksHeader statement + hi def link treeBookmarksLeader ignore + hi def link treeBookmarkName Identifier + hi def link treeBookmark normal + + hi def link treeHelp String + hi def link treeHelpKey Identifier + hi def link treeHelpCommand Identifier + hi def link treeHelpTitle Macro + hi def link treeToggleOn Question + hi def link treeToggleOff WarningMsg + + hi def link treeDir Directory + hi def link treeUp Directory + hi def link treeCWD Statement + hi def link treeLink Macro + hi def link treeOpenable Title + hi def link treeFlag ignore + hi def link treeRO WarningMsg + hi def link treeBookmark Statement + + hi def link NERDTreeCurrentNode Search +endfunction + +"FUNCTION: s:stripMarkupFromLine(line, removeLeadingSpaces){{{2 +"returns the given line with all the tree parts stripped off +" +"Args: +"line: the subject line +"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces = +"any spaces before the actual text of the node) +function! s:stripMarkupFromLine(line, removeLeadingSpaces) + let line = a:line + "remove the tree parts and the leading space + let line = substitute (line, s:tree_markup_reg,"","") + + "strip off any read only flag + let line = substitute (line, ' \[RO\]', "","") + + "strip off any bookmark flags + let line = substitute (line, ' {[^}]*}', "","") + + "strip off any executable flags + let line = substitute (line, '*\ze\($\| \)', "","") + + let wasdir = 0 + if line =~ '/$' + let wasdir = 1 + endif + let line = substitute (line,' -> .*',"","") " remove link to + if wasdir ==# 1 + let line = substitute (line, '/\?$', '/', "") + endif + + if a:removeLeadingSpaces + let line = substitute (line, '^ *', '', '') + endif + + return line +endfunction + +"FUNCTION: s:toggle(dir) {{{2 +"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is +"closed it is restored or initialized (if it doesnt exist) +" +"Args: +"dir: the full path for the root node (is only used if the NERD tree is being +"initialized. +function! s:toggle(dir) + if s:treeExistsForTab() + if !s:isTreeOpen() + call s:createTreeWin() + if !&hidden + call s:renderView() + endif + call s:restoreScreenState() + else + call s:closeTree() + endif + else + call s:initNerdTree(a:dir) + endif +endfunction +"SECTION: Interface bindings {{{1 +"============================================================ +"FUNCTION: s:activateNode(forceKeepWindowOpen) {{{2 +"If the current node is a file, open it in the previous window (or a new one +"if the previous is modified). If it is a directory then it is opened. +" +"args: +"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set +function! s:activateNode(forceKeepWindowOpen) + if getline(".") ==# s:tree_up_dir_line + return s:upDir(0) + endif + + let treenode = s:TreeFileNode.GetSelected() + if treenode != {} + call treenode.activate(a:forceKeepWindowOpen) + else + let bookmark = s:Bookmark.GetSelected() + if !empty(bookmark) + call bookmark.activate() + endif + endif +endfunction + +"FUNCTION: s:bindMappings() {{{2 +function! s:bindMappings() + " set up mappings and commands for this buffer + nnoremap <silent> <buffer> <middlerelease> :call <SID>handleMiddleMouse()<cr> + nnoremap <silent> <buffer> <leftrelease> <leftrelease>:call <SID>checkForActivate()<cr> + nnoremap <silent> <buffer> <2-leftmouse> :call <SID>activateNode(0)<cr> + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapActivateNode . " :call <SID>activateNode(0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenSplit ." :call <SID>openEntrySplit(0,0)<cr>" + exec "nnoremap <silent> <buffer> <cr> :call <SID>activateNode(0)<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreview ." :call <SID>previewNode(0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreviewSplit ." :call <SID>previewNode(1)<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenVSplit ." :call <SID>openEntrySplit(1,0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreviewVSplit ." :call <SID>previewNode(2)<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenRecursively ." :call <SID>openNodeRecursively()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdirKeepOpen ." :call <SID>upDir(1)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdir ." :call <SID>upDir(0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChangeRoot ." :call <SID>chRoot()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChdir ." :call <SID>chCwd()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapQuit ." :call <SID>closeTreeWindow()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefreshRoot ." :call <SID>refreshRoot()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefresh ." :call <SID>refreshCurrent()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapHelp ." :call <SID>displayHelp()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleZoom ." :call <SID>toggleZoom()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleHidden ." :call <SID>toggleShowHidden()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFilters ." :call <SID>toggleIgnoreFilter()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFiles ." :call <SID>toggleShowFiles()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleBookmarks ." :call <SID>toggleShowBookmarks()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseDir ." :call <SID>closeCurrentDir()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseChildren ." :call <SID>closeChildren()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapMenu ." :call <SID>showMenu()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpParent ." :call <SID>jumpToParent()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpNextSibling ." :call <SID>jumpToSibling(1)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpPrevSibling ." :call <SID>jumpToSibling(0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpFirstChild ." :call <SID>jumpToFirstChild()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpLastChild ." :call <SID>jumpToLastChild()<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpRoot ." :call <SID>jumpToRoot()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTab ." :call <SID>openInNewTab(0)<cr>" + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTabSilent ." :call <SID>openInNewTab(1)<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenExpl ." :call <SID>openExplorer()<cr>" + + exec "nnoremap <silent> <buffer> ". g:NERDTreeMapDeleteBookmark ." :call <SID>deleteBookmark()<cr>" + + "bind all the user custom maps + call s:KeyMap.BindAll() + + command! -buffer -nargs=1 Bookmark :call <SID>bookmarkNode('<args>') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call <SID>revealBookmark('<args>') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call <SID>openBookmark('<args>') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call <SID>clearBookmarks('<args>') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('<args>') + command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() <bar> call <SID>renderView() + command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) <bar> call <SID>renderView() + command! -buffer -nargs=0 WriteBookmarks call s:Bookmark.Write() +endfunction + +" FUNCTION: s:bookmarkNode(name) {{{2 +" Associate the current node with the given name +function! s:bookmarkNode(name) + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + try + call currentNode.bookmark(a:name) + call s:renderView() + catch /^NERDTree.IllegalBookmarkNameError/ + call s:echo("bookmark names must not contain spaces") + endtry + else + call s:echo("select a node first") + endif +endfunction +"FUNCTION: s:checkForActivate() {{{2 +"Checks if the click should open the current node, if so then activate() is +"called (directories are automatically opened if the symbol beside them is +"clicked) +function! s:checkForActivate() + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + let startToCur = strpart(getline(line(".")), 0, col(".")) + let char = strpart(startToCur, strlen(startToCur)-1, 1) + + "if they clicked a dir, check if they clicked on the + or ~ sign + "beside it + if currentNode.path.isDirectory + if startToCur =~ s:tree_markup_reg . '$' && char =~ '[+~]' + call s:activateNode(0) + return + endif + endif + + if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3 + if char !~ s:tree_markup_reg && startToCur !~ '\/$' + call s:activateNode(0) + return + endif + endif + endif +endfunction + +" FUNCTION: s:chCwd() {{{2 +function! s:chCwd() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + try + call treenode.path.changeToDir() + catch /^NERDTree.PathChangeError/ + call s:echoWarning("could not change cwd") + endtry +endfunction + +" FUNCTION: s:chRoot() {{{2 +" changes the current root to the selected one +function! s:chRoot() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + call treenode.makeRoot() + call s:renderView() + call b:NERDTreeRoot.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:clearBookmarks(bookmarks) {{{2 +function! s:clearBookmarks(bookmarks) + if a:bookmarks ==# '' + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + call currentNode.clearBoomarks() + endif + else + for name in split(a:bookmarks, ' ') + let bookmark = s:Bookmark.BookmarkFor(name) + call bookmark.delete() + endfor + endif + call s:renderView() +endfunction +" FUNCTION: s:closeChildren() {{{2 +" closes all childnodes of the current node +function! s:closeChildren() + let currentNode = s:TreeDirNode.GetSelected() + if currentNode ==# {} + call s:echo("Select a node first") + return + endif + + call currentNode.closeChildren() + call s:renderView() + call currentNode.putCursorHere(0, 0) +endfunction +" FUNCTION: s:closeCurrentDir() {{{2 +" closes the parent dir of the current node +function! s:closeCurrentDir() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + let parent = treenode.parent + if parent ==# {} || parent.isRoot() + call s:echo("cannot close tree root") + else + call treenode.parent.close() + call s:renderView() + call treenode.parent.putCursorHere(0, 0) + endif +endfunction +" FUNCTION: s:closeTreeWindow() {{{2 +" close the tree window +function! s:closeTreeWindow() + if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1 + exec "buffer " . b:NERDTreePreviousBuf + else + if winnr("$") > 1 + call s:closeTree() + else + call s:echo("Cannot close last window") + endif + endif +endfunction +" FUNCTION: s:deleteBookmark() {{{2 +" if the cursor is on a bookmark, prompt to delete +function! s:deleteBookmark() + let bookmark = s:Bookmark.GetSelected() + if bookmark ==# {} + call s:echo("Put the cursor on a bookmark") + return + endif + + echo "Are you sure you wish to delete the bookmark:\n\"" . bookmark.name . "\" (yN):" + + if nr2char(getchar()) ==# 'y' + try + call bookmark.delete() + call s:renderView() + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove bookmark") + endtry + else + call s:echo("delete aborted" ) + endif + +endfunction + +" FUNCTION: s:displayHelp() {{{2 +" toggles the help display +function! s:displayHelp() + let b:treeShowHelp = b:treeShowHelp ? 0 : 1 + call s:renderView() + call s:centerView() +endfunction + +" FUNCTION: s:handleMiddleMouse() {{{2 +function! s:handleMiddleMouse() + let curNode = s:TreeFileNode.GetSelected() + if curNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + if curNode.path.isDirectory + call s:openExplorer() + else + call s:openEntrySplit(0,0) + endif +endfunction + + +" FUNCTION: s:jumpToFirstChild() {{{2 +" wrapper for the jump to child method +function! s:jumpToFirstChild() + call s:jumpToChild(0) +endfunction + +" FUNCTION: s:jumpToLastChild() {{{2 +" wrapper for the jump to child method +function! s:jumpToLastChild() + call s:jumpToChild(1) +endfunction + +" FUNCTION: s:jumpToParent() {{{2 +" moves the cursor to the parent of the current node +function! s:jumpToParent() + let currentNode = s:TreeFileNode.GetSelected() + if !empty(currentNode) + if !empty(currentNode.parent) + call currentNode.parent.putCursorHere(1, 0) + call s:centerView() + else + call s:echo("cannot jump to parent") + endif + else + call s:echo("put the cursor on a node first") + endif +endfunction + +" FUNCTION: s:jumpToRoot() {{{2 +" moves the cursor to the root node +function! s:jumpToRoot() + call b:NERDTreeRoot.putCursorHere(1, 0) + call s:centerView() +endfunction + +" FUNCTION: s:jumpToSibling() {{{2 +" moves the cursor to the sibling of the current node in the given direction +" +" Args: +" forward: 1 if the cursor should move to the next sibling, 0 if it should +" move back to the previous sibling +function! s:jumpToSibling(forward) + let currentNode = s:TreeFileNode.GetSelected() + if !empty(currentNode) + let sibling = currentNode.findSibling(a:forward) + + if !empty(sibling) + call sibling.putCursorHere(1, 0) + call s:centerView() + endif + else + call s:echo("put the cursor on a node first") + endif +endfunction + +" FUNCTION: s:openBookmark(name) {{{2 +" put the cursor on the given bookmark and, if its a file, open it +function! s:openBookmark(name) + try + let targetNode = s:Bookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + redraw! + catch /^NERDTree.BookmarkedNodeNotFoundError/ + call s:echo("note - target node is not cached") + let bookmark = s:Bookmark.BookmarkFor(a:name) + let targetNode = s:TreeFileNode.New(bookmark.path) + endtry + if targetNode.path.isDirectory + call targetNode.openExplorer() + else + call targetNode.open() + endif +endfunction +" FUNCTION: s:openEntrySplit(vertical, forceKeepWindowOpen) {{{2 +"Opens the currently selected file from the explorer in a +"new window +" +"args: +"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set +function! s:openEntrySplit(vertical, forceKeepWindowOpen) + let treenode = s:TreeFileNode.GetSelected() + if treenode != {} + if a:vertical + call treenode.openVSplit() + else + call treenode.openSplit() + endif + if !a:forceKeepWindowOpen + call s:closeTreeIfQuitOnOpen() + endif + else + call s:echo("select a node first") + endif +endfunction + +" FUNCTION: s:openExplorer() {{{2 +function! s:openExplorer() + let treenode = s:TreeDirNode.GetSelected() + if treenode != {} + call treenode.openExplorer() + else + call s:echo("select a node first") + endif +endfunction + +" FUNCTION: s:openInNewTab(stayCurrentTab) {{{2 +" Opens the selected node or bookmark in a new tab +" Args: +" stayCurrentTab: if 1 then vim will stay in the current tab, if 0 then vim +" will go to the tab where the new file is opened +function! s:openInNewTab(stayCurrentTab) + let target = s:TreeFileNode.GetSelected() + if target == {} + let target = s:Bookmark.GetSelected() + endif + + if target != {} + call target.openInNewTab({'stayInCurrentTab': a:stayCurrentTab}) + endif +endfunction + +" FUNCTION: s:openNodeRecursively() {{{2 +function! s:openNodeRecursively() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} || treenode.path.isDirectory ==# 0 + call s:echo("Select a directory node first" ) + else + call s:echo("Recursively opening node. Please wait...") + call treenode.openRecursively() + call s:renderView() + redraw + call s:echo("Recursively opening node. Please wait... DONE") + endif + +endfunction + +"FUNCTION: s:previewNode() {{{2 +"Args: +" openNewWin: if 0, use the previous window, if 1 open in new split, if 2 +" open in a vsplit +function! s:previewNode(openNewWin) + let currentBuf = bufnr("") + if a:openNewWin > 0 + call s:openEntrySplit(a:openNewWin ==# 2,1) + else + call s:activateNode(1) + end + call s:exec(bufwinnr(currentBuf) . "wincmd w") +endfunction + +" FUNCTION: s:revealBookmark(name) {{{2 +" put the cursor on the node associate with the given name +function! s:revealBookmark(name) + try + let targetNode = s:Bookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + catch /^NERDTree.BookmarkNotFoundError/ + call s:echo("Bookmark isnt cached under the current root") + endtry +endfunction +" FUNCTION: s:refreshRoot() {{{2 +" Reloads the current root. All nodes below this will be lost and the root dir +" will be reloaded. +function! s:refreshRoot() + call s:echo("Refreshing the root node. This could take a while...") + call b:NERDTreeRoot.refresh() + call s:renderView() + redraw + call s:echo("Refreshing the root node. This could take a while... DONE") +endfunction + +" FUNCTION: s:refreshCurrent() {{{2 +" refreshes the root for the current node +function! s:refreshCurrent() + let treenode = s:TreeDirNode.GetSelected() + if treenode ==# {} + call s:echo("Refresh failed. Select a node first") + return + endif + + call s:echo("Refreshing node. This could take a while...") + call treenode.refresh() + call s:renderView() + redraw + call s:echo("Refreshing node. This could take a while... DONE") +endfunction +" FUNCTION: s:showMenu() {{{2 +function! s:showMenu() + let curNode = s:TreeFileNode.GetSelected() + if curNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + let mc = s:MenuController.New(s:MenuItem.AllEnabled()) + call mc.showMenu() +endfunction + +" FUNCTION: s:toggleIgnoreFilter() {{{2 +" toggles the use of the NERDTreeIgnore option +function! s:toggleIgnoreFilter() + let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +" FUNCTION: s:toggleShowBookmarks() {{{2 +" toggles the display of bookmarks +function! s:toggleShowBookmarks() + let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks + if b:NERDTreeShowBookmarks + call s:renderView() + call s:putCursorOnBookmarkTable() + else + call s:renderViewSavingPosition() + endif + call s:centerView() +endfunction +" FUNCTION: s:toggleShowFiles() {{{2 +" toggles the display of hidden files +function! s:toggleShowFiles() + let b:NERDTreeShowFiles = !b:NERDTreeShowFiles + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +" FUNCTION: s:toggleShowHidden() {{{2 +" toggles the display of hidden files +function! s:toggleShowHidden() + let b:NERDTreeShowHidden = !b:NERDTreeShowHidden + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +" FUNCTION: s:toggleZoom() {{2 +" zoom (maximize/minimize) the NERDTree window +function! s:toggleZoom() + if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed + let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize + exec "silent vertical resize ". size + let b:NERDTreeZoomed = 0 + else + exec "vertical resize" + let b:NERDTreeZoomed = 1 + endif +endfunction + +"FUNCTION: s:upDir(keepState) {{{2 +"moves the tree up a level +" +"Args: +"keepState: 1 if the current root should be left open when the tree is +"re-rendered +function! s:upDir(keepState) + let cwd = b:NERDTreeRoot.path.str({'format': 'UI'}) + if cwd ==# "/" || cwd =~ '^[^/]..$' + call s:echo("already at top dir") + else + if !a:keepState + call b:NERDTreeRoot.close() + endif + + let oldRoot = b:NERDTreeRoot + + if empty(b:NERDTreeRoot.parent) + let path = b:NERDTreeRoot.path.getParent() + let newRoot = s:TreeDirNode.New(path) + call newRoot.open() + call newRoot.transplantChild(b:NERDTreeRoot) + let b:NERDTreeRoot = newRoot + else + let b:NERDTreeRoot = b:NERDTreeRoot.parent + endif + + if g:NERDTreeChDirMode ==# 2 + call b:NERDTreeRoot.path.changeToDir() + endif + + call s:renderView() + call oldRoot.putCursorHere(0, 0) + endif +endfunction + + +"reset &cpo back to users setting +let &cpo = s:old_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/plugin/delimitMate.vim b/plugin/delimitMate.vim new file mode 100644 index 0000000..de0067f --- /dev/null +++ b/plugin/delimitMate.vim @@ -0,0 +1,635 @@ +" ============================================================================ +" File: delimitMate.vim +" Version: 2.0 +" Description: This plugin tries to emulate the auto-completion of delimiters +" that TextMate provides. +" Maintainer: Israel Chauca F. <israelchauca@gmail.com> +" Manual: Read ":help delimitMate". +" Credits: Some of the code is modified or just copied from the following: +" +" - Ian McCracken +" Post titled: Vim, Part II: Matching Pairs: +" http://concisionandconcinnity.blogspot.com/ +" +" - Aristotle Pagaltzis +" From the comments on the previous blog post and from: +" http://gist.github.com/144619 +" +" - Vim Scripts: +" http://www.vim.org/scripts/ + +" Initialization: {{{ +if exists("g:loaded_delimitMate") "{{{ + " User doesn't want this plugin, let's get out! + finish +endif +let g:loaded_delimitMate = 1 + +if exists("s:loaded_delimitMate") && !exists("g:delimitMate_testing") + " Don't define the functions if they already exist: just do the work + " (unless we are testing): + call s:DelimitMateDo() + finish +endif + +if v:version < 700 + echoerr "delimitMate: this plugin requires vim >= 7!" + finish +endif + +let s:loaded_delimitMate = 1 " }}} +let delimitMate_version = '2.0' + +function! s:Init() "{{{ + + let b:loaded_delimitMate = 1 + + " delimitMate_autoclose {{{ + if !exists("b:delimitMate_autoclose") && !exists("g:delimitMate_autoclose") + let b:delimitMate_autoclose = 1 + elseif !exists("b:delimitMate_autoclose") && exists("g:delimitMate_autoclose") + let b:delimitMate_autoclose = g:delimitMate_autoclose + else + " Nothing to do. + endif " }}} + + " delimitMate_matchpairs {{{ + if !exists("b:delimitMate_matchpairs") && !exists("g:delimitMate_matchpairs") + if s:ValidMatchpairs(&matchpairs) == 1 + let s:matchpairs_temp = &matchpairs + else + echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." + finish + endif + elseif exists("b:delimitMate_matchpairs") + if s:ValidMatchpairs(b:delimitMate_matchpairs) || b:delimitMate_matchpairs == "" + let s:matchpairs_temp = b:delimitMate_matchpairs + else + echoerr "delimitMate: Invalid format in 'b:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again." + if s:ValidMatchpairs(&matchpairs) == 1 + let s:matchpairs_temp = &matchpairs + else + echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." + let s:matchpairs_temp = "" + endif + endif + else + if s:ValidMatchpairs(g:delimitMate_matchpairs) || g:delimitMate_matchpairs == "" + let s:matchpairs_temp = g:delimitMate_matchpairs + else + echoerr "delimitMate: Invalid format in 'g:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again." + if s:ValidMatchpairs(&matchpairs) == 1 + let s:matchpairs_temp = &matchpairs + else + echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." + let s:matchpairs_temp = "" + endif + endif + + endif " }}} + + " delimitMate_quotes {{{ + if exists("b:delimitMate_quotes") + if b:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || b:delimitMate_quotes == "" + let s:quotes = split(b:delimitMate_quotes) + else + let s:quotes = split("\" ' `") + echoerr "delimitMate: There is a problem with the format of 'b:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values." + endif + elseif exists("g:delimitMate_quotes") + if g:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || g:delimitMate_quotes == "" + let s:quotes = split(g:delimitMate_quotes) + else + let s:quotes = split("\" ' `") + echoerr "delimitMate: There is a problem with the format of 'g:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values." + endif + else + let s:quotes = split("\" ' `") + endif + let b:delimitMate_quotes_list = s:quotes " }}} + + " delimitMate_visual_leader {{{ + if !exists("b:delimitMate_visual_leader") && !exists("g:delimitMate_visual_leader") + let b:delimitMate_visual_leader = exists('b:maplocalleader') ? b:maplocalleader : + \ exists('g:mapleader') ? g:mapleader : "\\" + elseif !exists("b:delimitMate_visual_leader") && exists("g:delimitMate_visual_leader") + let b:delimitMate_visual_leader = g:delimitMate_visual_leader + else + " Nothing to do. + endif " }}} + + " delimitMate_expand_space {{{ + if !exists("b:delimitMate_expand_space") && !exists("g:delimitMate_expand_space") + let b:delimitMate_expand_space = 0 + elseif !exists("b:delimitMate_expand_space") && !exists("g:delimitMate_expand_space") + let b:delimitMate_expand_space = g:delimitMate_expand_space + else + " Nothing to do. + endif " }}} + + " delimitMate_expand_cr {{{ + if !exists("b:delimitMate_expand_cr") && !exists("g:delimitMate_expand_cr") + let b:delimitMate_expand_cr = 0 + elseif !exists("b:delimitMate_expand_cr") && exists("g:delimitMate_expand_cr") + let b:delimitMate_expand_cr = g:delimitMate_expand_cr + else + " Nothing to do. + endif " }}} + + " delimitMate_smart_quotes {{{ + if !exists("b:delimitMate_smart_quotes") && !exists("g:delimitMate_smart_quotes") + let b:delimitMate_smart_quotes = 1 + elseif !exists("b:delimitMate_smart_quotes") && exists("g:delimitMate_smart_quotes") + let b:delimitMate_smart_quotes = split(g:delimitMate_smart_quotes) + else + " Nothing to do. + endif " }}} + + " delimitMate_apostrophes {{{ + if !exists("b:delimitMate_apostrophes") && !exists("g:delimitMate_apostrophes") + "let s:apostrophes = split("n't:'s:'re:'m:'d:'ll:'ve:s'",':') + let s:apostrophes = [] + elseif !exists("b:delimitMate_apostrophes") && exists("g:delimitMate_apostrophes") + let s:apostrophes = split(g:delimitMate_apostrophes) + else + let s:apostrophes = split(b:delimitMate_apostrophes) + endif + let b:delimitMate_apostrophes_list = s:apostrophes " }}} + + " delimitMate_tab2exit {{{ + if !exists("b:delimitMate_tab2exit") && !exists("g:delimitMate_tab2exit") + let b:delimitMate_tab2exit = 1 + elseif !exists("b:delimitMate_tab2exit") && exists("g:delimitMate_tab2exit") + let b:delimitMate_tab2exit = g:delimitMate_tab2exit + else + " Nothing to do. + endif " }}} + + let b:delimitMate_matchpairs_list = split(s:matchpairs_temp, ',') + let b:delimitMate_left_delims = split(s:matchpairs_temp, ':.,\=') + let b:delimitMate_right_delims = split(s:matchpairs_temp, ',\=.:') + let s:VMapMsg = "delimitMate: delimitMate is disabled on blockwise visual mode." + + call s:UnMap() + if b:delimitMate_autoclose + call s:AutoClose() + else + call s:NoAutoClose() + endif + call s:VisualMaps() + call s:ExtraMappings() + +endfunction "}}} Init() +"}}} + +" Utilities: {{{ +function! s:ValidMatchpairs(str) "{{{ + if a:str !~ '^.:.\(,.:.\)*$' + return 0 + endif + for pair in split(a:str,',') + if strpart(pair, 0, 1) == strpart(pair, 2, 1) || strlen(pair) != 3 + return 0 + endif + endfor + return 1 +endfunction "}}} + +function! DelimitMate_ShouldJump() "{{{ + let char = getline('.')[col('.') - 1] + for pair in b:delimitMate_matchpairs_list + if char == split( pair, ':' )[1] + " Same character on the rigth, jump over it. + return 1 + endif + endfor + for quote in b:delimitMate_quotes_list + if char == quote + " Same character on the rigth, jump over it. + return 1 + endif + endfor + return 0 +endfunction "}}} + +function! s:IsBlockVisual() " {{{ + if visualmode() == "<C-V>" + return 1 + endif + " Store unnamed register values for later use in s:RestoreRegister(). + let s:save_reg = getreg('"') + let s:save_reg_mode = getregtype('"') + + if len(getline('.')) == 0 + " This for proper wrap of empty lines. + let @" = "\n" + endif + return 0 +endfunction " }}} + +function! s:IsEmptyPair(str) "{{{ + for pair in b:delimitMate_matchpairs_list + if a:str == join( split( pair, ':' ),'' ) + return 1 + endif + endfor + for quote in b:delimitMate_quotes_list + if a:str == quote . quote + return 1 + endif + endfor + return 0 +endfunction "}}} + +function! DelimitMate_WithinEmptyPair() "{{{ + let cur = strpart( getline('.'), col('.')-2, 2 ) + return s:IsEmptyPair( cur ) +endfunction "}}} + +function! s:WriteBefore(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if col < 0 + call setline('.',line[(col+len+1):]) + else + call setline('.',line[:(col)].line[(col+len+1):]) + endif + return a:str +endfunction " }}} + +function! s:WriteAfter(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if (col) < 0 + call setline('.',a:str.line) + else + call setline('.',line[:(col)].a:str.line[(col+len):]) + endif + return '' +endfunction " }}} + +function! s:RestoreRegister() " {{{ + " Restore unnamed register values store in s:IsBlockVisual(). + call setreg('"', s:save_reg, s:save_reg_mode) + echo "" +endfunction " }}} +" }}} + +" Doers: {{{ +function! s:JumpIn(char) " {{{ + let line = getline('.') + let col = col('.')-2 + if (col) < 0 + call setline('.',a:char.line) + else + "echom string(col).':'.line[:(col)].'|'.line[(col+1):] + call setline('.',line[:(col)].a:char.line[(col+1):]) + endif + return '' +endfunction " }}} + +function! s:JumpOut(char) "{{{ + let line = getline('.') + let col = col('.')-2 + if line[col+1] == a:char + call setline('.',line[:(col)].line[(col+2):]) + endif + return a:char +endfunction " }}} + +function! DelimitMate_JumpAny() " {{{ + let nchar = getline('.')[col('.')-1] + return nchar . "\<Del>" +endfunction " DelimitMate_JumpAny() }}} + +function! s:SkipDelim(char) "{{{ + let cur = strpart( getline('.'), col('.')-2, 3 ) + if cur[0] == "\\" + " Escaped character + return a:char + elseif cur[1] == a:char + " Exit pair + return s:WriteBefore(a:char) + "elseif cur[1] == ' ' && cur[2] == a:char + "" I'm leaving this in case someone likes it. Jump an space and delimiter. + "return "\<Right>\<Right>" + elseif s:IsEmptyPair( cur[0] . a:char ) + " Add closing delimiter and jump back to the middle. + return s:WriteAfter(a:char) + else + " Nothing special here, return the same character. + return a:char + endif +endfunction "}}} + +function! s:QuoteDelim(char) "{{{ + let line = getline('.') + let col = col('.') - 2 + if line[col] == "\\" + " Seems like a escaped character, insert one quotation mark. + return a:char + elseif line[col + 1] == a:char + " Get out of the string. + return s:WriteBefore(a:char) + elseif (line[col] =~ '[a-zA-Z0-9]' && a:char == "'") || + \(line[col] =~ '[a-zA-Z0-9]' && b:delimitMate_smart_quotes) + " Seems like an apostrophe or a closing, insert a single quote. + return a:char + elseif (line[col] == a:char && line[col + 1 ] != a:char) && b:delimitMate_smart_quotes + " Seems like we have an unbalanced quote, insert one quotation mark and jump to the middle. + return s:WriteAfter(a:char) + else + " Insert a pair and jump to the middle. + call s:WriteAfter(a:char) + return a:char + endif +endfunction "}}} + +function! s:MapMsg(msg) "{{{ + redraw + echomsg a:msg + return "" +endfunction "}}} +"}}} + +" Mappings: {{{ +function! s:NoAutoClose() "{{{ + " inoremap <buffer> ) <C-R>=<SID>SkipDelim('\)')<CR> + for delim in b:delimitMate_right_delims + b:delimitMate_quotes_list + exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>SkipDelim("' . escape(delim,'"') . '")<CR>' + endfor +endfunction "}}} + +function! s:AutoClose() "{{{ + " Add matching pair and jump to the midle: + " inoremap <buffer> ( ()<Left> + let i = 0 + while i < len(b:delimitMate_matchpairs_list) + let ld = b:delimitMate_left_delims[i] + let rd = b:delimitMate_right_delims[i] + exec 'inoremap <buffer> ' . ld . ' ' . ld . '<C-R>=<SID>JumpIn("' . rd . '")<CR>' + let i += 1 + endwhile + + " Add matching quote and jump to the midle, or exit if inside a pair of matching quotes: + " inoremap <buffer> " <C-R>=<SID>QuoteDelim("\"")<CR> + for delim in b:delimitMate_quotes_list + exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>QuoteDelim("\' . delim . '")<CR>' + endfor + + " Exit from inside the matching pair: + for delim in b:delimitMate_right_delims + exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>JumpOut("\' . delim . '")<CR>' + endfor + + " Try to fix the use of apostrophes (de-activated by default): + " inoremap <buffer> n't n't + for map in b:delimitMate_apostrophes_list + exec "inoremap <buffer> " . map . " " . map + endfor + +endfunction "}}} + +function! s:VisualMaps() " {{{ + let vleader = b:delimitMate_visual_leader + " Wrap the selection with matching pairs, but do nothing if blockwise visual mode is active: + let i = 0 + while i < len(b:delimitMate_matchpairs_list) + " Map left delimiter: + let ld = b:delimitMate_left_delims[i] + let rd = b:delimitMate_right_delims[i] + exec 'vnoremap <buffer> <expr> ' . vleader . ld . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . ld . '\<C-R>\"' . rd . '\<Esc>:call <SID>RestoreRegister()<CR>"' + + " Map right delimiter: + exec 'vnoremap <buffer> <expr> ' . vleader . rd . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . ld . '\<C-R>\"' . rd . '\<Esc>:call <SID>RestoreRegister()<CR>"' + let i += 1 + endwhile + + " Wrap the selection with matching quotes, but do nothing if blockwise visual mode is active: + for quote in b:delimitMate_quotes_list + " vnoremap <buffer> <expr> \' <SID>IsBlockVisual() ? <SID>MapMsg("Message") : "s'\<C-R>\"'\<Esc>:call <SID>RestoreRegister()<CR>" + exec 'vnoremap <buffer> <expr> ' . vleader . quote . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') .'\<C-R>\"' . escape(quote,'"') . '\<Esc>:call <SID>RestoreRegister()<CR>"' + endfor +endfunction "}}} + +function! DelimitMate_ExpandReturn() "{{{ + " Expand: + return "\<Esc>a\<CR>x\<CR>\<Esc>k$\"_xa" +endfunction "}}} + +function! DelimitMate_ExpandSpace() "{{{ + " Expand: + return s:WriteAfter(' ') . "\<Space>" +endfunction "}}} + +function! s:ExtraMappings() "{{{ + " If pair is empty, delete both delimiters: + inoremap <buffer> <expr> <BS> DelimitMate_WithinEmptyPair() ? "\<Right>\<BS>\<BS>" : "\<BS>" + + " If pair is empty, delete closing delimiter: + inoremap <buffer> <expr> <S-BS> DelimitMate_WithinEmptyPair() ? "\<Del>" : "\<S-BS>" + + " Expand return if inside an empty pair: + if b:delimitMate_expand_cr != 0 + inoremap <buffer> <expr> <CR> DelimitMate_WithinEmptyPair() ? + \ DelimitMate_ExpandReturn() : "\<CR>" + endif + + " Expand space if inside an empty pair: + if b:delimitMate_expand_space != 0 + inoremap <buffer> <expr> <Space> DelimitMate_WithinEmptyPair() ? + \ DelimitMate_ExpandSpace() : "\<Space>" + endif + + " Jump out ot any empty pair: + if b:delimitMate_tab2exit + inoremap <buffer> <expr> <S-Tab> DelimitMate_ShouldJump() ? DelimitMate_JumpAny() : "\<S-Tab>" + endif +endfunction "}}} +"}}} + +" Tools: {{{ +function! s:TestMappings() "{{{ + if b:delimitMate_autoclose + exec "normal i* AUTOCLOSE:\<CR>" + for i in range(len(b:delimitMate_left_delims)) + exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i]. "|" + exec "normal A\<CR>Delete: " . b:delimitMate_left_delims[i] . "\<BS>|" + exec "normal A\<CR>Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\<CR>Space: " . b:delimitMate_left_delims[i] . " |" + exec "normal GGA\<CR>Visual-L: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] + exec "normal A\<CR>Visual-R: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] + exec "normal A\<CR>Car return: " . b:delimitMate_left_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>" + endfor + for i in range(len(b:delimitMate_quotes_list)) + exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . "|" + exec "normal A\<CR>Delete: " + exec "normal A". b:delimitMate_quotes_list[i] + exec "normal a\<BS>|" + exec "normal A\<CR>Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\<CR>Space: " . b:delimitMate_quotes_list[i] . " |" + exec "normal GGA\<CR>Visual: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] + exec "normal A\<CR>Car return: " . b:delimitMate_quotes_list[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>" + endfor + else + exec "normal i* NO AUTOCLOSE:\<CR>" + for i in range(len(b:delimitMate_left_delims)) + exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\<CR>Delete: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\<BS>|" + exec "normal A\<CR>Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\<CR>Space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " |" + exec "normal GGA\<CR>Visual-L: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] + exec "normal A\<CR>Visual-R: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] + exec "normal A\<CR>Car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>" + endfor + for i in range(len(b:delimitMate_quotes_list)) + exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\<CR>Delete: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\<BS>|" + exec "normal A\<CR>Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\<CR>Space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " |" + exec "normal GGA\<CR>Visual: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] + exec "normal A\<CR>Car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>" + endfor + endif + exec "normal \<Esc>i" +endfunction "}}} + +function! s:SwitchAutoclose() "{{{ + if !exists("g:delimitMate_autoclose") + let g:delimitMate_autoclose = 1 + elseif g:delimitMate_autoclose == 1 + let g:delimitMate_autoclose = 0 + else + let g:delimitMate_autoclose = 1 + endif + DelimitMateReload +endfunction "}}} + +function! s:UnMap() " {{{ + " No Autoclose Mappings: + for char in b:delimitMate_right_delims + b:delimitMate_quotes_list + if maparg(char,"i") =~? 'SkipDelim' + exec 'silent! iunmap <buffer> ' . char + "echomsg 'iunmap <buffer> ' . char + endif + endfor + + " Autoclose Mappings: + let i = 0 + let l = len(b:delimitMate_matchpairs_list) + while i < l + if maparg(b:delimitMate_left_delims[i],"i") =~? 'JumpIn' + exec 'silent! iunmap <buffer> ' . b:delimitMate_left_delims[i] + "echomsg 'iunmap <buffer> ' . b:delimitMate_left_delims[i] + endif + let i += 1 + endwhile + for char in b:delimitMate_quotes_list + if maparg(char, "i") =~? 'QuoteDelim' + exec 'silent! iunmap <buffer> ' . char + "echomsg 'iunmap <buffer> ' . char + endif + endfor + for char in b:delimitMate_right_delims + if maparg(char, "i") =~? 'JumpOut' + exec 'silent! iunmap <buffer> ' . char + "echomsg 'iunmap <buffer> ' . char + endif + endfor + for map in b:delimitMate_apostrophes_list + exec "silent! iunmap <buffer> " . map + endfor + + " Visual Mappings: + for char in b:delimitMate_right_delims + b:delimitMate_left_delims + b:delimitMate_quotes_list + if maparg(b:delimitMate_visual_leader . char,"v") =~? 'IsBlock' + exec 'silent! vunmap <buffer> ' . b:delimitMate_visual_leader . char + "echomsg 'vunmap <buffer> ' . b:delimitMate_visual_leader . char + endif + endfor + + " Expansion Mappings: + if maparg('<BS>', "i") =~? 'WithinEmptyPair' + silent! iunmap <buffer> <BS> + "echomsg "silent! iunmap <buffer> <BS>" + endif + if maparg('<S-BS>', "i") =~? 'WithinEmptyPair' + silent! iunmap <buffer> <BS> + "echomsg "silent! iunmap <buffer> <BS>" + endif + if maparg('<CR>',"i") =~? 'DelimitMate_ExpandReturn' + silent! iunmap <buffer> <CR> + "echomsg "silent! iunmap <buffer> <CR>" + endif + if maparg('<Space>',"i") =~? 'DelimitMate_ExpandSpace' + silent! iunmap <buffer> <Space> + "echomsg "silent! iunmap <buffer> <Space>" + endif + if maparg('<S-Tab>', "i") =~? 'ShouldJump' + silent! iunmap <buffer> <S-Tab> + "echomsg "silent! iunmap <buffer> <S-Tab>" + endif +endfunction " }}} s:ExtraMappings() + +function! s:TestMappingsDo() "{{{ + "DelimitMateReload + if !exists("g:delimitMate_testing") + "call s:DelimitMateDo() + call s:TestMappings() + else + call s:SwitchAutoclose() + call s:TestMappings() + exec "normal i\<CR>" + call s:SwitchAutoclose() + call s:TestMappings() + endif +endfunction "}}} + +function! s:DelimitMateDo() "{{{ + if exists("g:delimitMate_excluded_ft") + " Check if this file type is excluded: + for ft in split(g:delimitMate_excluded_ft,',') + if ft ==? &filetype + if !exists("b:delimitMate_quotes_list") + return 1 + endif + "echomsg "excluded" + call s:UnMap() + return 1 + endif + endfor + endif + try + "echomsg "included" + let save_cpo = &cpo + set cpo&vim + call s:Init() + finally + let &cpo = save_cpo + endtry +endfunction "}}} +"}}} + +" Commands: {{{ +call s:DelimitMateDo() + +" Let me refresh without re-loading the buffer: +command! DelimitMateReload call s:DelimitMateDo() + +" Quick test: +command! DelimitMateTest call s:TestMappingsDo() + +" Run on file type events. +"autocmd VimEnter * autocmd FileType * call <SID>DelimitMateDo() +autocmd FileType * call <SID>DelimitMateDo() + +" Run on new buffers. +autocmd BufNewFile,BufRead,BufEnter * if !exists("b:loaded_delimitMate") | call <SID>DelimitMateDo() | endif + +"function! s:GetSynRegion () | echo synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') | endfunction +"}}} + +" GetLatestVimScripts: 2754 1 :AutoInstall: delimitMate.vim +" vim:foldmethod=marker:foldcolumn=4 diff --git a/plugin/eclim_py.vim b/plugin/eclim_py.vim new file mode 100644 index 0000000..d1af92f --- /dev/null +++ b/plugin/eclim_py.vim @@ -0,0 +1,1788 @@ +" ============================================================================ +" File: eclim_py.vim +" Description: vim plugin that provides some python helpers. Most of parts are +" taken from Eclim project <http://eclim.sourceforge.net> +" Maintainer: Roman 'gryf' Dobosz <gryf73@gmail.com> +" Last Change: 2010-02-10 +" License: This program is free software: you can redistribute it and/or +" modify it under the terms of the GNU General Public License as +" published by the Free Software Foundation, either version 3 of +" the License, or (at your option) any later version. +" +" This program is distributed in the hope that it will be useful, +" but WITHOUT ANY WARRANTY; without even the implied warranty of +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +" GNU General Public License for more details. +" +" You should have received a copy of the GNU General Public +" License along with this program. If not, see +" <http://www.gnu.org/licenses/>. +" ============================================================================ +let s:Eclim_ver = '1.5.4' + +" Further Description: {{{1 +" @gryf: Python and editor helpers taken over from Eclim project. There are +" couple of nice tools, which I want to have separately from Eclim project. +" Just for my conviniece and because I mainly work with Python files, I'll +" put all of necessary thing into this one file. +" +" Added: +" :Buffers +" :Sign +" :Signs +" :PyLint +" :Validate (pyflakes) +" :QuickFixClear +" :LocationListClear +" TODO: +" :Validate (rope) [this one is not crucial. at least for now.] +" :SignClearUser +" :SignClearAll +" (w daleszej kolejnoÅ›ci) +" :PythonRegex +" :LocateFile (do silnego przerobienia) +" +" }}} + +" Eclim: {{{1 +" files: +" - plugin/eclim.vim (global vars) +" - plugin/common.vim (commands) + +" Global Variables {{{2 + +if has("signs") + if !exists("g:EclimSignLevel") + let g:EclimSignLevel = 5 + endif +else + let g:EclimSignLevel = 0 +endif + +if !exists("g:EclimInfoHighlight") + let g:EclimInfoHighlight = "Statement" +endif + +if !exists("g:EclimLogLevel") + let g:EclimLogLevel = 4 +endif + +if !exists("g:EclimTraceHighlight") + let g:EclimTraceHighlight = "Normal" +endif +if !exists("g:EclimDebugHighlight") + let g:EclimDebugHighlight = "Normal" +endif +if !exists("g:EclimInfoHighlight") + let g:EclimInfoHighlight = "Statement" +endif +if !exists("g:EclimWarningHighlight") + let g:EclimWarningHighlight = "WarningMsg" +endif +if !exists("g:EclimErrorHighlight") + let g:EclimErrorHighlight = "Error" +endif +if !exists("g:EclimFatalHighlight") + let g:EclimFatalHighlight = "Error" +endif + +if !exists("g:EclimShowCurrentError") + let g:EclimShowCurrentError = 1 +endif + +if !exists("g:EclimShowCurrentErrorBalloon") + let g:EclimShowCurrentErrorBalloon = 1 +endif + +if !exists("g:EclimOpenQFLists") + let g:EclimOpenQFLists = 1 +endif + +" }}} + +" Command Declarations {{{2 + +if !exists(":Buffers") + command Buffers :call Buffers() +endif + +if has('signs') + if !exists(":Sign") + command Sign :call SignsToggle('user', line('.')) + endif + if !exists(":Signs") + command Signs :call SignsViewSigns('user') + endif + if !exists(":SignClearUser") + command SignClearUser :call SignsUnplaceAll(SignsGetExisting('user')) + endif + if !exists(":SignClearAll") + command SignClearAll :call SignsUnplaceAll(SignsGetExisting()) + endif +endif + +if !exists(":QuickFixClear") + command QuickFixClear :call setqflist([]) | call SignsUpdate() +endif +if !exists(":LocationListClear") + command LocationListClear :call setloclist(0, []) | call SignsUpdate() +endif + +" }}} + +" Auto Commands{{{2 + +if g:EclimSignLevel + augroup eclim_qf + autocmd QuickFixCmdPost *make* call SignsShow('', 'qf') + autocmd QuickFixCmdPost grep*,vimgrep* call SignsShow('i', 'qf') + autocmd QuickFixCmdPost lgrep*,lvimgrep* call SignsShow('i', 'loc') + autocmd BufWinEnter * call SignsUpdate() + augroup END +endif + +if g:EclimShowCurrentError + augroup eclim_show_error + autocmd! + autocmd CursorMoved * call ShowCurrentError() + augroup END +endif + +if g:EclimShowCurrentErrorBalloon && has('balloon_eval') + set ballooneval + set balloonexpr=Balloon(GetLineError(line('.'))) +endif + +" }}} + +" End Eclim: }}} + +" Common Buffers: {{{1 + +" Global Variables {{{2 +if !exists('g:EclimBuffersSort') + let g:EclimBuffersSort = 'file' +endif +if !exists('g:EclimBuffersSortDirection') + let g:EclimBuffersSortDirection = 'asc' +endif +if !exists('g:EclimBuffersDefaultAction') + let g:EclimBuffersDefaultAction = 'edit' +endif +if !exists('g:EclimOnlyExclude') + let g:EclimOnlyExclude = + \ '\(NERD_tree_*\|__Tag_List__\|command-line\)' +endif +" }}} + +" Buffers() eclim/autoload/eclim/common/buffers.vim {{{2 +" Like, :buffers, but opens a temporary buffer. +function! Buffers() + redir => list + silent exec 'buffers' + redir END + + let buffers = [] + let filelength = 0 + for entry in split(list, '\n') + let buffer = {} + let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '') + let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '') + let buffer.path = fnamemodify(buffer.path, ':p') + let buffer.file = fnamemodify(buffer.path, ':p:t') + let buffer.dir = fnamemodify(buffer.path, ':p:h') + exec 'let buffer.bufnr = ' . substitute(entry, '\s*\([0-9]\+\).*', '\1', '') + exec 'let buffer.lnum = ' . + \ substitute(entry, '.*"\s\+line\s\+\([0-9]\+\).*', '\1', '') + call add(buffers, buffer) + + if len(buffer.file) > filelength + let filelength = len(buffer.file) + endif + endfor + + if g:EclimBuffersSort != '' + call sort(buffers, 'BufferCompare') + endif + + let lines = [] + for buffer in buffers + call add(lines, s:BufferEntryToLine(buffer, filelength)) + endfor + + call TempWindow('[buffers]', lines) + let b:eclim_buffers = buffers + + setlocal modifiable noreadonly + call append(line('$'), ['', '" use ? to view help']) + setlocal nomodifiable readonly + + let b:eclim_buffers = buffers + + " syntax + set ft=eclim_buffers + hi link BufferActive Special + hi link BufferHidden Comment + syntax match BufferActive /+\?active\s\+\(\[RO\]\)\?/ + syntax match BufferHidden /+\?hidden\s\+\(\[RO\]\)\?/ + syntax match Comment /^".*/ + + " mappings + nnoremap <silent> <buffer> <cr> :call <SID>BufferOpen2(g:EclimBuffersDefaultAction)<cr> + nnoremap <silent> <buffer> E :call <SID>BufferOpen2('edit')<cr> + nnoremap <silent> <buffer> S :call <SID>BufferOpen2('split')<cr> + nnoremap <silent> <buffer> T :call <SID>BufferOpen('tablast \| tabnew')<cr> + nnoremap <silent> <buffer> D :call <SID>BufferDelete()<cr> + + " assign to buffer var to get around weird vim issue passing list containing + " a string w/ a '<' in it on execution of mapping. + let b:buffers_help = [ + \ '<cr> - open buffer with default action', + \ 'E - open with :edit', + \ 'S - open in a new split window', + \ 'T - open in a new tab', + \ 'D - delete the buffer', + \ ] + nnoremap <buffer> <silent> ? + \ :call BufferHelp(b:buffers_help, 'vertical', 40)<cr> + + "augroup eclim_buffers + " autocmd! + " autocmd BufAdd,BufWinEnter,BufDelete,BufWinLeave * + " \ call eclim#common#buffers#BuffersUpdate() + " autocmd BufUnload <buffer> autocmd! eclim_buffers + "augroup END +endfunction " }}} + +" BufferCompare(buffer1, buffer2) eclim/autoload/eclim/common/buffers.vim {{{2 +function! BufferCompare(buffer1, buffer2) + exec 'let attr1 = a:buffer1.' . g:EclimBuffersSort + exec 'let attr2 = a:buffer2.' . g:EclimBuffersSort + let compare = attr1 == attr2 ? 0 : attr1 > attr2 ? 1 : -1 + if g:EclimBuffersSortDirection == 'desc' + let compare = 0 - compare + endif + return compare +endfunction " }}} + +" s:BufferDelete() {{{2 +function! s:BufferDelete() + let line = line('.') + if line > len(b:eclim_buffers) + return + endif + + let index = line - 1 + exec 'bd ' . b:eclim_buffers[index].bufnr + setlocal modifiable + setlocal noreadonly + exec line . ',' . line . 'delete _' + setlocal nomodifiable + setlocal readonly + call remove(b:eclim_buffers, index) +endfunction " }}} + +" s:BufferEntryToLine(buffer, filelength) eclim/autoload/eclim/common/buffers.vim {{{2 +function! s:BufferEntryToLine(buffer, filelength) + let line = '' + let line .= a:buffer.status =~ '+' ? '+' : ' ' + let line .= a:buffer.status =~ 'a' ? 'active' : 'hidden' + let line .= a:buffer.status =~ '[-=]' ? ' [RO] ' : ' ' + let line .= a:buffer.file + + let pad = a:filelength - len(a:buffer.file) + 2 + while pad > 0 + let line .= ' ' + let pad -= 1 + endwhile + + let line .= a:buffer.dir + return line +endfunction " }}} + +" s:BufferOpen(cmd) eclim/autoload/eclim/common/buffers.vim {{{2 +function! s:BufferOpen(cmd) + let line = line('.') + if line > len(b:eclim_buffers) + return + endif + + let file = bufname(b:eclim_buffers[line - 1].bufnr) + let winnr = b:winnr + close + exec winnr . 'winc w' + call GoToBufferWindowOrOpen(file, a:cmd) +endfunction " }}} + +" End Common Buffers: }}} + +" Util: {{{1 + +" Script Variables eclim/autoload/eclim/util.vim {{{2 + let s:buffer_write_closing_commands = '^\s*\(' . + \ 'wq\|xa\|' . + \ '\d*w[nN]\|\d*wp\|' . + \ 'ZZ' . + \ '\)' + + let s:bourne_shells = ['sh', 'bash', 'dash', 'ksh', 'zsh'] + let s:c_shells = ['csh', 'tcsh'] + + let s:show_current_error_displaying = 0 +" }}} + +" Balloon(message) eclim/autoload/eclim/util.vim {{{2 +" Function for use as a vim balloonexpr expression. +function! Balloon(message) + let message = a:message + if !has('balloon_multiline') + " remove any new lines + let message = substitute(message, '\n', ' ', 'g') + endif + return message +endfunction " }}} + +" DelayedCommand(command, [delay]) eclim/autoload/eclim/util.vim {{{2 +" Executes a delayed command. Useful in cases where one would expect an +" autocommand event (WinEnter, etc) to fire, but doesn't, or you need a +" command to execute after other autocommands have finished. +" Note: Nesting is not supported. A delayed command cannot be invoke off +" another delayed command. +function! DelayedCommand(command, ...) + let uid = fnamemodify(tempname(), ':t:r') + if &updatetime > 1 + exec 'let g:eclim_updatetime_save' . uid . ' = &updatetime' + endif + exec 'let g:eclim_delayed_command' . uid . ' = a:command' + let &updatetime = len(a:000) ? a:000[0] : 1 + exec 'augroup delayed_command' . uid + exec 'autocmd CursorHold * ' . + \ ' if exists("g:eclim_updatetime_save' . uid . '") | ' . + \ ' let &updatetime = g:eclim_updatetime_save' . uid . ' | ' . + \ ' unlet g:eclim_updatetime_save' . uid . ' | ' . + \ ' endif | ' . + \ ' exec g:eclim_delayed_command' . uid . ' | ' . + \ ' unlet g:eclim_delayed_command' . uid . ' | ' . + \ ' autocmd! delayed_command' . uid + exec 'augroup END' +endfunction " }}} + +" EchoTrace(message) eclim/autoload/eclim/util.vim {{{2 +function! EchoTrace(message) + call s:EchoLevel(a:message, 6, g:EclimTraceHighlight) +endfunction " }}} + +" EchoWarning(message) eclim/autoload/eclim/util.vim {{{2 +function! EchoWarning(message) + call s:EchoLevel(a:message, 3, g:EclimWarningHighlight) +endfunction " }}} + +" EchoError(message) eclim/autoload/eclim/util.vim {{{2 +function! EchoError(message) + call s:EchoLevel(a:message, 2, g:EclimErrorHighlight) +endfunction " }}} + +" s:EchoLevel(message) eclim/autoload/eclim/util.vim {{{2 +" Echos the supplied message at the supplied level with the specified +" highlight. +function! s:EchoLevel(message, level, highlight) + " only echo if the result is not 0, which signals that ExecuteEclim failed. + if a:message != "0" && g:EclimLogLevel >= a:level + exec "echohl " . a:highlight + redraw + for line in split(a:message, '\n') + echom line + endfor + echohl None + endif +endfunction " }}} + +" Echo(message) eclim/autoload/eclim/util.vim {{{2 +" Echos a message using the info highlight regardless of what log level is set. +function! Echo(message) + if a:message != "0" && g:EclimLogLevel > 0 + exec "echohl " . g:EclimInfoHighlight + redraw + for line in split(a:message, '\n') + echom line + endfor + echohl None + endif +endfunction " }}} + +" EscapeBufferName(name) eclim/autoload/eclim/util.vim {{{2 +" Escapes the supplied buffer name so that it can be safely used by buf* +" functions. +function! EscapeBufferName(name) + let name = escape(a:name, ' ') + return substitute(name, '\(.\{-}\)\[\(.\{-}\)\]\(.\{-}\)', '\1[[]\2[]]\3', 'g') +endfunction " }}} + +" GetLineError(line) eclim/autoload/eclim/util.vim {{{2 +" Gets the error (or message) for the supplie line number if one. +function! GetLineError(line) + let line = line('.') + let col = col('.') + + let errornum = 0 + let errorcol = 0 + let index = 0 + + let locerrors = getloclist(0) + let qferrors = getqflist() + let bufname = expand('%') + let lastline = line('$') + for error in qferrors + locerrors + let index += 1 + if bufname(error.bufnr) == bufname && + \ (error.lnum == line || (error.lnum > lastline && line == lastline)) + if errornum == 0 || (col >= error.col && error.col != errorcol) + let errornum = index + let errorcol = error.col + endif + endif + endfor + + if errornum > 0 + let src = 'qf' + let cnt = len(qferrors) + let errors = qferrors + if errornum > cnt + let errornum -= cnt + let src = 'loc' + let cnt = len(locerrors) + let errors = locerrors + endif + + let message = src . ' - (' . errornum . ' of ' . cnt . '): ' + \ . substitute(errors[errornum - 1].text, '^\s\+', '', '') + return message + endif + return '' +endfunction " }}} + +" GoToBufferWindow(buf) eclim/autoload/eclim/util.vim {{{2 +" Focuses the window containing the supplied buffer name or buffer number. +" Returns 1 if the window was found, 0 otherwise. +function! GoToBufferWindow(buf) + if type(a:buf) == 0 + let winnr = bufwinnr(a:buf) + else + let name = EscapeBufferName(a:buf) + let winnr = bufwinnr(bufnr('^' . name)) + endif + if winnr != -1 + exec winnr . "winc w" + call DelayedCommand('doautocmd WinEnter') + return 1 + endif + return 0 +endfunction " }}} + +" GoToBufferWindowOrOpen(name, cmd) eclim/autoload/eclim/util.vim {{{2 +" Gives focus to the window containing the buffer for the supplied file, or if +" none, opens the file using the supplied command. +function! GoToBufferWindowOrOpen(name, cmd) + let name = EscapeBufferName(a:name) + let winnr = bufwinnr(bufnr('^' . name)) + if winnr != -1 + exec winnr . "winc w" + call DelayedCommand('doautocmd WinEnter') + else + silent exec a:cmd . ' ' . escape(Simplify(a:name), ' ') + endif +endfunction " }}} + +" GoToBufferWindowRegister(buf) eclim/autoload/eclim/util.vim {{{2 +" Registers the autocmd for returning the user to the supplied buffer when the +" current buffer is closed. +function! GoToBufferWindowRegister(buf) + exec 'autocmd BufWinLeave <buffer> ' . + \ 'call GoToBufferWindow("' . escape(a:buf, '\') . '") | ' . + \ 'doautocmd BufEnter' +endfunction " }}} + +" SetLocationList(list, [action]) eclim/autoload/eclim/util.vim {{{2 +" Sets the contents of the location list for the current window. +function! SetLocationList(list, ...) + let loclist = a:list + + " filter the list if the current buffer defines a list of filters. + if exists('b:EclimLocationListFilter') + let newlist = [] + for item in loclist + let addit = 1 + + for filter in b:EclimLocationListFilter + if item.text =~ filter + let addit = 0 + break + endif + endfor + + if addit + call add(newlist, item) + endif + endfor + let loclist = newlist + endif + + if a:0 == 0 + call setloclist(0, loclist) + else + call setloclist(0, loclist, a:1) + endif + if g:EclimShowCurrentError && len(loclist) > 0 + call DelayedCommand('call ShowCurrentError()') + endif + call SignsUpdate() +endfunction " }}} + +" ClearLocationList([namespace, namespace, ...]) eclim/autoload/eclim/util.vim {{{2 +" Clears the current location list. Optionally 'namespace' arguments can be +" supplied which will only clear items with text prefixed with '[namespace]'. +" Also the special namespace 'global' may be supplied which will only remove +" items with no namepace prefix. +function! ClearLocationList(...) + if a:0 > 0 + let loclist = getloclist(0) + if len(loclist) > 0 + let pattern = '' + for ns in a:000 + if pattern != '' + let pattern .= '\|' + endif + if ns == 'global' + let pattern .= '\(\[\w\+\]\)\@!' + else + let pattern .= '\[' . ns . '\]' + endif + endfor + let pattern = '^\(' . pattern . '\)' + + call filter(loclist, 'v:val.text !~ pattern') + call setloclist(0, loclist, 'r') + endif + else + call setloclist(0, [], 'r') + endif + call SignsUpdate() +endfunction " }}} + +" SetQuickfixList(list, [action]) eclim/autoload/eclim/util.vim {{{2 +" Sets the contents of the quickfix list. +function! SetQuickfixList(list, ...) + let qflist = a:list + if exists('b:EclimQuickfixFilter') + let newlist = [] + for item in qflist + let addit = 1 + + for filter in b:EclimQuickfixFilter + if item.text =~ filter + let addit = 0 + break + endif + endfor + + if addit + call add(newlist, item) + endif + endfor + let qflist = newlist + endif + if a:0 == 0 + call setqflist(qflist) + else + call setqflist(qflist, a:1) + endif + if g:EclimShowCurrentError && len(qflist) > 0 + call DelayedCommand('call ShowCurrentError()') + endif + call SignsUpdate() +endfunction " }}} + +" ShowCurrentError() eclim/autoload/eclim/util.vim {{{2 +" Shows the error on the cursor line if one. +function! ShowCurrentError() + let message = GetLineError(line('.')) + if message != '' + " remove any new lines + let message = substitute(message, '\n', ' ', 'g') + + if len(message) > (&columns - 1) + let message = strpart(message, 0, &columns - 4) . '...' + endif + + call WideMessage('echo', message) + let s:show_current_error_displaying = 1 + else + " clear the message if one of our error messages was displaying + if s:show_current_error_displaying + call WideMessage('echo', message) + let s:show_current_error_displaying = 0 + endif + endif +endfunction " }}} + +" Simplify(file) eclim/autoload/eclim/util.vim {{{2 +" Simply the supplied file to the shortest valid name. +function! Simplify(file) + let file = a:file + + " Don't run simplify on url files, it will screw them up. + if file !~ '://' + let file = simplify(file) + endif + + " replace all '\' chars with '/' except those escaping spaces. + let file = substitute(file, '\\\([^[:space:]]\)', '/\1', 'g') + let cwd = substitute(getcwd(), '\', '/', 'g') + if cwd !~ '/$' + let cwd .= '/' + endif + + if file =~ '^' . cwd + let file = substitute(file, '^' . cwd, '', '') + endif + + return file +endfunction " }}} + +" System(cmd, [exec]) eclim/autoload/eclim/util.vim {{{2 +" Executes system() accounting for possibly disruptive vim options. +function! System(cmd, ...) + let saveshell = &shell + let saveshellcmdflag = &shellcmdflag + let saveshellpipe = &shellpipe + let saveshellquote = &shellquote + let saveshellredir = &shellredir + let saveshellslash = &shellslash + let saveshelltemp = &shelltemp + let saveshellxquote = &shellxquote + + if has("win32") || has("win64") + set shell=cmd.exe + set shellcmdflag=/c + set shellpipe=>%s\ 2>&1 + set shellquote= + set shellredir=>%s\ 2>&1 + set noshellslash + set shelltemp + set shellxquote= + else + if executable('/bin/bash') + set shell=/bin/bash + else + set shell=/bin/sh + endif + set shell=/bin/sh + set shellcmdflag=-c + set shellpipe=2>&1\|\ tee + set shellquote= + set shellredir=>%s\ 2>&1 + set noshellslash + set shelltemp + set shellxquote= + endif + + if len(a:000) > 0 && a:000[0] + let result = '' + call EchoTrace('exec: ' . a:cmd) + exec a:cmd + else + call EchoTrace('system: ' . a:cmd) + let result = system(a:cmd) + endif + + let &shell = saveshell + let &shellcmdflag = saveshellcmdflag + let &shellquote = saveshellquote + let &shellslash = saveshellslash + let &shelltemp = saveshelltemp + let &shellxquote = saveshellxquote + + " If a System call is executed at startup, it appears to interfere with + " vim's setting of 'shellpipe' and 'shellredir' to their shell specific + " values. So, if we detect that the values we are restoring look like + " uninitialized defaults, then attempt to mimic vim's documented + " (:h 'shellpipe' :h 'shellredir') logic for setting the proper values based + " on the shell. + " Note: still doesn't handle more obscure shells + if saveshellredir == '>' + if index(s:bourne_shells, fnamemodify(&shell, ':t')) != -1 + set shellpipe=2>&1\|\ tee + set shellredir=>%s\ 2>&1 + elseif index(s:c_shells, fnamemodify(&shell, ':t')) != -1 + set shellpipe=\|&\ tee + set shellredir=>& + else + let &shellpipe = saveshellpipe + let &shellredir = saveshellredir + endif + else + let &shellpipe = saveshellpipe + let &shellredir = saveshellredir + endif + + return result +endfunction " }}} + +" TempWindow(name, lines, [readonly]) eclim/autoload/eclim/util.vim {{{2 +" Opens a temp window w/ the given name and contents which is readonly unless +" specified otherwise. +function! TempWindow(name, lines, ...) + let filename = expand('%:p') + let winnr = winnr() + + call TempWindowClear(a:name) + let name = EscapeBufferName(a:name) + + if bufwinnr(name) == -1 + silent! noautocmd exec "botright 10sview " . escape(a:name, ' ') + let b:eclim_temp_window = 1 + + " play nice with maximize.vim + "if eclim#display#maximize#GetMaximizedWindow() + " call eclim#display#maximize#AdjustFixedWindow(10, 1) + "endif + + setlocal nowrap + setlocal winfixheight + setlocal noswapfile + setlocal nobuflisted + setlocal buftype=nofile + setlocal bufhidden=delete + else + exec bufwinnr(name) . "winc w" + endif + + set modifiable + set noreadonly + call append(1, a:lines) + retab + silent 1,1delete _ + + if len(a:000) == 0 || a:000[0] + setlocal nomodified + setlocal nomodifiable + setlocal readonly + endif + + doautocmd BufEnter + + " Store filename and window number so that plugins can use it if necessary. + if filename != expand('%:p') + let b:filename = filename + let b:winnr = winnr + + augroup eclim_temp_window + autocmd! BufWinLeave <buffer> + call GoToBufferWindowRegister(b:filename) + augroup END + endif +endfunction " }}} + +" TempWindowClear(name) eclim/autoload/eclim/util.vim {{{2 +" Clears the contents of the temp window with the given name. +function! TempWindowClear(name) + let name = EscapeBufferName(a:name) + if bufwinnr(name) != -1 + let curwinnr = winnr() + exec bufwinnr(name) . "winc w" + setlocal modifiable + setlocal noreadonly + silent 1,$delete _ + exec curwinnr . "winc w" + endif +endfunction " }}} + +" WideMessage(command, message) eclim/autoload/eclim/util.vim {{{2 +" Executes the supplied echo command and forces vim to display as much as +" possible without the "Press Enter" prompt. +" Thanks to vimtip #1289 +function! WideMessage(command, message) + let saved_ruler = &ruler + let saved_showcmd = &showcmd + + let message = substitute(a:message, '^\s\+', '', '') + + set noruler noshowcmd + redraw + exec a:command . ' "' . escape(message, '"\') . '"' + + let &ruler = saved_ruler + let &showcmd = saved_showcmd +endfunction " }}} + +" WillWrittenBufferClose() eclim/autoload/eclim/util.vim {{{2 +" Returns 1 if the current buffer is to be hidden/closed/deleted after it is +" written, or 0 otherwise. This function is useful during a post write auto +" command for determining whether or not to perform some operation based on +" whether the buffer will still be visible to the user once the current +" command has finished. +" Note: This function only detects command typed by the user at the +" command (:) prompt, not any normal mappings which may hide/close/delete the +" buffer. +function! WillWrittenBufferClose() + return histget("cmd") =~ s:buffer_write_closing_commands +endfunction " }}} + +" End Util: }}} + +" Display Signs: {{{1 + +" Global Variables eclim/autoload/eclim/display/signs.vim {{{2 +if !exists("g:EclimShowQuickfixSigns") + let g:EclimShowQuickfixSigns = 1 +endif + +if !exists("g:EclimUserSignText") + let g:EclimUserSignText = '#' +endif + +if !exists("g:EclimUserSignHighlight") + let g:EclimUserSignHighlight = g:EclimInfoHighlight +endif +" }}} + +" Define(name, text, highlight) eclim/autoload/eclim/display/signs.vim {{{2 +" Defines a new sign name or updates an existing one. +function! SignsDefine(name, text, highlight) + exec "sign define " . a:name . " text=" . a:text . " texthl=" . a:highlight +endfunction " }}} + +" Place(name, line) eclim/autoload/eclim/display/signs.vim {{{2 +" Places a sign in the current buffer. +function! SignsPlace(name, line) + if a:line > 0 + let lastline = line('$') + let line = a:line <= lastline ? a:line : lastline + exec "sign place " . line . " line=" . line . " name=" . a:name . + \ " buffer=" . bufnr('%') + endif +endfunction " }}} + +" PlaceAll(name, list) eclim/autoload/eclim/display/signs.vim {{{2 +" Places a sign in the current buffer for each line in the list. +function! SignsPlaceAll(name, list) + let lastline = line('$') + for line in a:list + if line > 0 + let line = line <= lastline ? line : lastline + exec "sign place " . line . " line=" . line . " name=" . a:name . + \ " buffer=" . bufnr('%') + endif + endfor +endfunction " }}} + +" Unplace(id) eclim/autoload/eclim/display/signs.vim {{{2 +" Un-places a sign in the current buffer. +function! SignsUnplace(id) + exec 'sign unplace ' . a:id . ' buffer=' . bufnr('%') +endfunction " }}} + +" Toggle(name, line) eclim/autoload/eclim/display/signs.vim {{{2 +" Toggle a sign on the current line. +function! SignsToggle(name, line) + if a:line > 0 + let existing = SignsGetExisting(a:name) + let exists = len(filter(existing, "v:val['line'] == a:line")) + if exists + call SignsUnplace(a:line) + else + call SignsPlace(a:name, a:line) + endif + endif +endfunction " }}} + +" CompareSigns(s1, s2) eclim/autoload/eclim/display/signs.vim {{{2 +" Used by ViewSigns to sort list of sign dictionaries. +function! s:CompareSigns(s1, s2) + if a:s1.line == a:s2.line + return 0 + endif + if a:s1.line > a:s2.line + return 1 + endif + return -1 +endfunction " }}} + +" ViewSigns(name) eclim/autoload/eclim/display/signs.vim {{{2 +" Open a window to view all placed signs with the given name in the current +" buffer. +function! SignsViewSigns(name) + let filename = expand('%:p') + let signs = SignsGetExisting(a:name) + call sort(signs, 's:CompareSigns') + let content = map(signs, "v:val.line . '|' . getline(v:val.line)") + + call TempWindow('[Sign List]', content) + + set ft=qf + nnoremap <silent> <buffer> <cr> :call <SID>JumpToSign()<cr> + + " Store filename so that plugins can use it if necessary. + let b:filename = filename + augroup temp_window + autocmd! BufWinLeave <buffer> + call GoToBufferWindowRegister(filename) + augroup END +endfunction " }}} + +" JumpToSign() eclim/autoload/eclim/display/signs.vim {{{2 +function! s:JumpToSign() + let winnr = bufwinnr(bufnr('^' . b:filename)) + if winnr != -1 + let line = substitute(getline('.'), '^\(\d\+\)|.*', '\1', '') + exec winnr . "winc w" + call cursor(line, 1) + endif +endfunction " }}} + +" GetExisting(...) eclim/autoload/eclim/display/signs.vim {{{2 +" Gets a list of existing signs for the current buffer. +" The list consists of dictionaries with the following keys: +" id: The sign id. +" line: The line number. +" name: The sign name (erorr, warning, etc.) +" +" Optionally a sign name may be supplied to only retrieve signs of that name. +function! SignsGetExisting(...) + let bufnr = bufnr('%') + + redir => signs + silent exec 'sign place buffer=' . bufnr + redir END + + let existing = [] + for sign in split(signs, '\n') + if sign =~ 'id=' + " for multi language support, don't have have regex w/ english + " identifiers + let id = substitute(sign, '.\{-}=.\{-}=\(.\{-}\)\s.*', '\1', '') + exec 'let line = ' . substitute(sign, '.\{-}=\(.\{-}\)\s.*', '\1', '') + let name = substitute(sign, '.\{-}=.\{-}=.\{-}=\(.\{-}\)\s*$', '\1', '') + call add(existing, {'id': id, 'line': line, 'name': name}) + endif + endfor + + if len(a:000) > 0 + call filter(existing, "v:val['name'] == a:000[0]") + endif + + return existing +endfunction " }}} + +" HasExisting(...) eclim/autoload/eclim/display/signs.vim {{{2 +" Determines if there are an existing signs. +" Optionally a sign name may be supplied to only test for signs of that name. +function! SignsHasExisting(...) + let bufnr = bufnr('%') + + redir => results + silent exec 'sign place buffer=' . bufnr + redir END + + for sign in split(results, '\n') + if sign =~ 'id=' + if len(a:000) == 0 + return 1 + endif + let name = substitute(sign, '.\{-}=.\{-}=.\{-}=\(.\{-}\)\s*$', '\1', '') + if name == a:000[0] + return 1 + endif + endif + endfor + + return 0 +endfunction " }}} + +" Update() eclim/autoload/eclim/display/signs.vim {{{2 +" Updates the signs for the current buffer. This function will read both the +" location list and the quickfix list and place a sign for any entries for the +" current file. +" This function supports a severity level by examining the 'type' key of the +" dictionaries in the location or quickfix list. It supports 'i' (info), 'w' +" (warning), and 'e' (error). +function! SignsUpdate() + if !has('signs') || !g:EclimSignLevel + return + endif + + let save_lazy = &lazyredraw + set lazyredraw + + call SignsDefine('error', '>>', g:EclimErrorHighlight) + let placeholder = SignsSetPlaceholder() + + " remove all existing signs + let existing = SignsGetExisting() + for exists in existing + if exists.name =~ '^\(error\|info\|warning\|qf_error\|qf_warning\)$' + call SignsUnplace(exists.id) + endif + endfor + + let qflist = getqflist() + + if g:EclimShowQuickfixSigns + let errors = filter(copy(qflist), + \ 'bufnr("%") == v:val.bufnr && (v:val.type == "" || v:val.type == "e")') + let warnings = filter(copy(qflist), + \ 'bufnr("%") == v:val.bufnr && v:val.type == "w"') + call map(errors, 'v:val.lnum') + call map(warnings, 'v:val.lnum') + call SignsDefine("qf_error", "> ", g:EclimErrorHighlight) + call SignsDefine("qf_warning", "> ", g:EclimWarningHighlight) + call SignsPlaceAll("qf_error", errors) + call SignsPlaceAll("qf_warning", warnings) + endif + + let list = filter(getloclist(0), 'bufnr("%") == v:val.bufnr') + + if g:EclimSignLevel >= 4 + let info = filter(copy(qflist) + copy(list), + \ 'bufnr("%") == v:val.bufnr && v:val.type == "i"') + let locinfo = filter(copy(list), + \ 'bufnr("%") == v:val.bufnr && v:val.type == ""') + call extend(info, locinfo) + call map(info, 'v:val.lnum') + call SignsDefine("info", ">>", g:EclimInfoHighlight) + call SignsPlaceAll("info", info) + endif + + if g:EclimSignLevel >= 3 + let warnings = filter(copy(list), 'v:val.type == "w"') + call map(warnings, 'v:val.lnum') + call SignsDefine("warning", ">>", g:EclimWarningHighlight) + call SignsPlaceAll("warning", warnings) + endif + + if g:EclimSignLevel >= 2 + let errors = filter(copy(list), 'v:val.type == "e"') + call map(errors, 'v:val.lnum') + call SignsPlaceAll("error", errors) + endif + + if placeholder + call SignsRemovePlaceholder() + endif + + let &lazyredraw = save_lazy +endfunction " }}} + +" Show(type, list) eclim/autoload/eclim/display/signs.vim {{{2 +" Set the type on each entry in the specified list ('qf' or 'loc') and mark +" any matches in the current file. +function! SignsShow(type, list) + if a:type != '' + if a:list == 'qf' + let list = getqflist() + else + let list = getloclist(0) + endif + + let newentries = [] + for entry in list + let newentry = { + \ 'filename': bufname(entry.bufnr), + \ 'lnum': entry.lnum, + \ 'col': entry.col, + \ 'text': entry.text, + \ 'type': a:type + \ } + call add(newentries, newentry) + endfor + + if a:list == 'qf' + call setqflist(newentries, 'r') + else + call setloclist(0, newentries, 'r') + endif + endif + + call SignsUpdate() + + redraw! +endfunction " }}} + +" SetPlaceholder([only_if_necessary]) eclim/autoload/eclim/display/signs.vim {{{2 +" Set sign at line 1 to prevent sign column from collapsing, and subsiquent +" screen redraw. +function! SignsSetPlaceholder(...) + if !has('signs') || !g:EclimSignLevel + return + endif + + if len(a:000) > 0 && a:000[0] + let existing = SignsGetExisting() + if !len(existing) + return + endif + endif + + call SignsDefine('placeholder', '_ ', g:EclimInfoHighlight) + let existing = SignsGetExisting('placeholder') + if len(existing) == 0 && SignsHasExisting() + call SignsPlace('placeholder', 1) + return 1 + endif + return +endfunction " }}} + +" RemovePlaceholder() eclim/autoload/eclim/display/signs.vim {{{2 +function! SignsRemovePlaceholder() + if !has('signs') || !g:EclimSignLevel + return + endif + + let existing = SignsGetExisting('placeholder') + for exists in existing + call SignsUnplace(exists.id) + endfor +endfunction " }}} + +" define signs for manually added user marks. eclim/autoload/eclim/display/signs.vim {{{2 +if has('signs') + let s:name = 'user' + exec "sign define " . s:name . " text=" . g:EclimUserSignText . " texthl=" . g:EclimUserSignHighlight +endif " }}} + +" End Display Signs: }}} + +" Python Django: {{{1 + +" GetProjectPath([path]) eclim/autoload/eclim/python/django/util.vim {{{2 +function! DjangoGetProjectPath(...) + let path = len(a:000) > 0 ? a:000[0] : escape(expand('%:p:h'), ' ') + let dir = findfile("manage.py", path . ';') + if dir != '' + let dir = substitute(fnamemodify(dir, ':p:h'), '\', '/', 'g') + " secondary check on the dir, if settings.py exists, then probably the + " right dir, otherwise, search again from the parent. + if !filereadable(dir . '/settings.py') + return DjangoGetProjectPath(path . '/..') + endif + endif + return dir +endfunction " }}} + +" }}} + +" Python Validate: {{{1 + +" Global Variables eclim/autoload/eclim/python/validate.vim {{{2 + " if the user has the pyflakes plugin from vim.org, then disable our + " validation since the two overlap and may result in errors + let s:pyflakes_enabled = 1 + if exists('g:pyflakes_builtins') + let s:pyflakes_enabled = 0 + endif + if !exists('g:EclimValidateBuffer') + let g:EclimValidateBuffer = 1 + endif +" }}} + +" Script Variables eclim/autoload/eclim/python/validate.vim {{{2 + let s:warnings = '\(' . join([ + \ 'imported but unused', + \ 'local variable .* assigned to but never used', + \ ], '\|') . '\)' +" }}} + +" Validate(on_save) eclim/autoload/eclim/python/validate.vim {{{2 +" Validates the current file. +function! Validate(on_save) + if g:EclimValidateBuffer == 0 + return + endif + + if WillWrittenBufferClose() + return + endif + + if &filetype != "python" + return + endif + + let results = [] + let syntax_error = ValidateSyntax() + + if syntax_error == '' + if s:pyflakes_enabled + if !executable('pyflakes') + if !exists('g:eclim_python_pyflakes_warn') + call EchoWarning("Unable to find 'pyflakes' command.") + let g:eclim_python_pyflakes_warn = 1 + endif + else + let command = 'pyflakes "' . expand('%:p') . '"' + let results = split(System(command), '\n') + if v:shell_error > 1 " pyflakes returns 1 if there where warnings. + call EchoError('Error running command: ' . command) + let results = [] + endif + endif + endif + + " rope validation + " currently too slow for running on every save. + " + " gryf: this stuff should be rewriten somehow. For now it is just to + " complicated. + " + "if eclim#project#util#IsCurrentFileInProject(0) && !a:on_save + " let project = eclim#project#util#GetCurrentProjectRoot() + " let filename = eclim#project#util#GetProjectRelativeFilePath(expand('%:p')) + " let rope_results = eclim#python#rope#Validate(project, filename) + " " currently rope gets confused with iterator var on list comprehensions + " let rope_results = filter(rope_results, "v:val !~ '^Unresolved variable'") + " let results += rope_results + "endif + endif + + if !empty(results) || syntax_error != '' + call filter(results, "v:val !~ 'unable to detect undefined names'") + + let errors = [] + if syntax_error != '' + let lnum = substitute(syntax_error, '.*(line \(\d\+\))', '\1', '') + let text = substitute(syntax_error, '\(.*\)\s\+(line .*', '\1', '') + if lnum == syntax_error + let lnum = 1 + let text .= ' (unknown line)' + endif + call add(errors, { + \ 'filename': Simplify(expand('%')), + \ 'lnum': lnum, + \ 'text': text, + \ 'type': 'e' + \ }) + endif + + if syntax_error == '' + for error in results + let file = substitute(error, '\(.\{-}\):[0-9]\+:.*', '\1', '') + let line = substitute(error, '.\{-}:\([0-9]\+\):.*', '\1', '') + let message = substitute(error, '.\{-}:[0-9]\+:\(.*\)', '\1', '') + let dict = { + \ 'filename': Simplify(file), + \ 'lnum': line, + \ 'text': message, + \ 'type': message =~ s:warnings ? 'w' : 'e', + \ } + + call add(errors, dict) + endfor + endif + + call SetLocationList(errors) + if g:EclimOpenQFLists + :lopen + endif + else + call ClearLocationList() + endif +endfunction " }}} + +" ValidateSyntax() eclim/autoload/eclim/python/validate.vim {{{2 +function ValidateSyntax() + let syntax_error = '' + + if has('python') + +python << EOF +import re, vim +from compiler import parseFile +try: + parseFile(vim.eval('expand("%:p")')) +except SyntaxError, se: + vim.command("let syntax_error = \"%s\"" % re.sub(r'"', r'\"', str(se))) +except IndentationError, ie: + vim.command("let syntax_error = \"%s (line %s)\"" % ( + re.sub(r'"', r'\"', ie.msg), ie.lineno) + ) +EOF + + endif + + return syntax_error +endfunction " }}} + +" PyLint() eclim/autoload/eclim/python/validate.vim {{{2 +function! PyLint() + + if &filetype != "python" + return + endif + + let file = expand('%:p') + + if !executable('pylint') + call EchoError("Unable to find 'pylint' command.") + return + endif + + let pylint_env = '' + if exists('g:EclimPyLintEnv') + let pylint_env = g:EclimPyLintEnv + else + let paths = [] + + let django_dir = DjangoGetProjectPath() + if django_dir != '' + call add(paths, fnamemodify(django_dir, ':h')) + let settings = fnamemodify(django_dir, ':t') + if has('win32') || has('win64') + let pylint_env = + \ 'set DJANGO_SETTINGS_MODULE='. settings . '.settings && ' + else + let pylint_env = + \ 'DJANGO_SETTINGS_MODULE="'. settings . '.settings" ' + endif + endif + + if !empty(paths) + if has('win32') || has('win64') + let pylint_env .= 'set "PYTHONPATH=' . join(paths, ';') . '" && ' + else + let pylint_env .= 'PYTHONPATH="$PYTHONPATH:' . join(paths, ':') . '"' + endif + endif + endif + + " TODO: switch to 'parseable' output format. + let command = pylint_env . + \ ' pylint --reports=n --output-format=text "' . file . '"' + if has('win32') || has('win64') + let command = 'cmd /c "' . command . '"' + endif + + call Echo('Running pylint (ctrl-c to cancel) ...') + let result = System(command) + call Echo(' ') + if v:shell_error == 1 + call EchoError('Error running command: ' . command) + return + endif + + if result =~ ':' + let errors = [] + for error in split(result, '\n') + if error =~ '^[CWERF]\(: \)\?[0-9]' + let line = substitute(error, '.\{-}:\s*\([0-9]\+\):.*', '\1', '') + let message = substitute(error, '.\{-}:\s*[0-9]\+:\(.*\)', '\1', '') + let dict = { + \ 'filename': Simplify(file), + \ 'lnum': line, + \ 'text': message, + \ 'type': error =~ '^E' ? 'e' : 'w', + \ } + + call add(errors, dict) + endif + endfor + call SetQuickfixList(errors) + if g:EclimOpenQFLists + :copen + endif + else + call SetQuickfixList([], 'r') + endif +endfunction " }}} + +" }}} + +" Eclim Help: {{{1 + +" BufferHelp(lines, orientation, size) eclim/autoload/eclim/help.vim {{{ +" Function to display a help window for the current buffer. +function! BufferHelp(lines, orientation, size) + let orig_bufnr = bufnr('%') + let name = expand('%') + if name =~ '^\W.*\W$' + let name = name[:-2] . ' Help' . name[len(name) - 1] + else + let name .= ' Help' + endif + + let bname = EscapeBufferName(name) + + let orient = a:orientation == 'vertical' ? 'v' : '' + if bufwinnr(bname) != -1 + exec 'bd ' . bufnr(bname) + return + endif + + silent! noautocmd exec a:size . orient . "new " . escape(name, ' ') + let b:eclim_temp_window = 1 + setlocal nowrap winfixheight + setlocal noswapfile nobuflisted nonumber + setlocal buftype=nofile bufhidden=delete + nnoremap <buffer> <silent> ? :bd<cr> + + set modifiable noreadonly + silent 1,$delete _ + call append(1, a:lines) + retab + silent 1,1delete _ + + if len(a:000) == 0 || a:000[0] + setlocal nomodified nomodifiable readonly + endif + + let help_bufnr = bufnr('%') + augroup eclim_help_buffer + autocmd! BufWinLeave <buffer> + autocmd BufWinLeave <buffer> nested autocmd! eclim_help_buffer * <buffer> + exec 'autocmd BufWinLeave <buffer> nested ' . + \ 'autocmd! eclim_help_buffer * <buffer=' . orig_bufnr . '>' + exec 'autocmd! BufWinLeave <buffer=' . orig_bufnr . '>' + exec 'autocmd BufWinLeave <buffer=' . orig_bufnr . '> nested bd ' . help_bufnr + augroup END + + return help_bufnr +endfunction " }}} + +" }}} + +" Gryf: {{{1 + +" GetAllBuffers {{{2 +function! GetAllBuffers() + redir => list + silent exec 'buffers' + redir END + + for entry in split(list, '\n') + echo entry + endfor + echo expand('%:p') + + let buffers = [] + let filelength = 0 + for entry in split(list, '\n') + let buffer = {} + let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '') + let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '') + let buffer.path = fnamemodify(buffer.path, ':p') + let buffer.file = fnamemodify(buffer.path, ':p:t') + let buffer.dir = fnamemodify(buffer.path, ':p:h') + exec 'let buffer.bufnr = ' . substitute(entry, '\s*\([0-9]\+\).*', '\1', '') + exec 'let buffer.lnum = ' . + \ substitute(entry, '.*"\s\+line\s\+\([0-9]\+\).*', '\1', '') + call add(buffers, buffer) + + if len(buffer.file) > filelength + let filelength = len(buffer.file) + endif + endfor + + echo buffers + return buffers + + "let buffers = [] + "let filelength = 0 + "for entry in split(list, '\n') + " let buffer = {} + " let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '') + " let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '') + " let buffer.path = fnamemodify(buffer.path, ':p') + " let buffer.file = fnamemodify(buffer.path, ':p:t') + " let buffer.dir = fnamemodify(buffer.path, ':p:h') + " exec 'let buffer.bufnr = ' . substitute(entry, '\s*\([0-9]\+\).*', '\1', '') + " exec 'let buffer.lnum = ' . + " \ substitute(entry, '.*"\s\+line\s\+\([0-9]\+\).*', '\1', '') + " call add(buffers, buffer) + + " if len(buffer.file) > filelength + " let filelength = len(buffer.file) + " endif + "endfor + + "if g:EclimBuffersSort != '' + " call sort(buffers, 'BufferCompare') + "endif + + "let lines = [] + "for buffer in buffers + " call add(lines, s:BufferEntryToLine(buffer, filelength)) + "endfor + + "call TempWindow('[buffers]', lines) + "let b:eclim_buffers = buffers + + "" syntax + "set ft=eclim_buffers + "hi link BufferActive Special + "hi link BufferHidden Comment + "syntax match BufferActive /+\?active\s\+\(\[RO\]\)\?/ + "syntax match BufferHidden /+\?hidden\s\+\(\[RO\]\)\?/ + + "" mappings + "nnoremap <silent> <buffer> <cr> :call <SID>BufferOpen(g:EclimBuffersDefaultAction)<cr> + "nnoremap <silent> <buffer> E :call <SID>BufferOpen('edit')<cr> + "nnoremap <silent> <buffer> S :call <SID>BufferOpen('split')<cr> + "nnoremap <silent> <buffer> T :call <SID>BufferOpen('tablast \| tabnew')<cr> + "nnoremap <silent> <buffer> D :call <SID>BufferDelete()<cr> + + "augroup eclim_buffers + " autocmd! + " autocmd BufAdd,BufWinEnter,BufDelete,BufWinLeave * + " \ call eclim#common#buffers#BuffersUpdate() + " autocmd BufUnload <buffer> autocmd! eclim_buffers + "augroup END +endfunction " }}} + +" ViewAllSigns(name) {{{2 +" Open a window to view all placed signs with the given name in the all +" buffers. +function! SignsViewAllSigns(name) + for buf in GetAllBuffers() + echo buf + endfor + return + + if buf.file not in ('[Quickfix List]', '[Location List]') + let filename = expand("%:p") "buf.path + let signs = SignsGetExisting(a:name) + call sort(signs, 's:CompareSigns') + let content = map(signs, "v:val.line . '|' . getline(v:val.line)") + + call TempWindow('[Sign List]', content) + + set ft=qf + nnoremap <silent> <buffer> <cr> :call <SID>JumpToSign()<cr> + + " Store filename so that plugins can use it if necessary. + let b:filename = filename + augroup temp_window + autocmd! BufWinLeave <buffer> + call GoToBufferWindowRegister(filename) + augroup END + endif + endfor + + "let filename = expand('%:p') + "let signs = SignsGetExisting(a:name) + "call sort(signs, 's:CompareSigns') + "let content = map(signs, "v:val.line . '|' . getline(v:val.line)") + + "call TempWindow('[Sign List]', content) + + "set ft=qf + "nnoremap <silent> <buffer> <cr> :call <SID>JumpToSign()<cr> + + "" Store filename so that plugins can use it if necessary. + "let b:filename = filename + "augroup temp_window + " autocmd! BufWinLeave <buffer> + " call GoToBufferWindowRegister(filename) + "augroup END +endfunction " }}} + +" TODO: remove this +map <F4> <esc>:Signs<cr> +map <F3> <esc>:Sign<cr> + +" GetAllExisting(...) {{{2 +" Gets a list of existing signs for all the buffers. +" The list consists of dictionaries with the following keys: +" buffer: Buffer number +" id: The sign id. +" line: The line number. +" name: The sign name (erorr, warning, etc.) +" +" Optionally a sign name may be supplied to only retrieve signs of that name. +function! SignsGetAllExisting(buffernr, mark_name) + let bufnr = bufnr('%') + + redir => signs + silent exec 'sign place buffer=' . a:buffernr + redir END + + let existing = [] + for sign in split(signs, '\n') + if sign =~ 'id=' + " for multi language support, don't have have regex w/ english + " identifiers + let id = substitute(sign, '.\{-}=.\{-}=\(.\{-}\)\s.*', '\1', '') + exec 'let line = ' . substitute(sign, '.\{-}=\(.\{-}\)\s.*', '\1', '') + let name = substitute(sign, '.\{-}=.\{-}=.\{-}=\(.\{-}\)\s*$', '\1', '') + call add(existing, {'id': id, 'line': line, 'name': name}) + endif + endfor + + if len(a:000) > 0 + call filter(existing, "v:val['name'] == a:mark_name") + endif + + return existing +endfunction " }}} + +" PyLintBuf() create pylint-output buffer {{{2 +function! PyLintBuf() + + if &filetype != "python" + return + endif + + let file = expand('%:p') + + if !executable('pylint') + call EchoError("Unable to find 'pylint' command.") + return + endif + + let pylint_env = '' + if exists('g:EclimPyLintEnv') + let pylint_env = g:EclimPyLintEnv + else + let paths = [] + + if !empty(paths) + if has('win32') || has('win64') + let pylint_env .= 'set "PYTHONPATH=' . join(paths, ';') . '" && ' + else + let pylint_env .= 'PYTHONPATH="$PYTHONPATH:' . join(paths, ':') . '"' + endif + endif + endif + + " TODO: switch to 'parseable' output format. + let command = pylint_env . + \ ' pylint --reports=n --output-format=text "' . file . '"' + if has('win32') || has('win64') + let command = 'cmd /c "' . command . '"' + endif + + call Echo('Running pylint (ctrl-c to cancel) ...') + let result = System(command) + call Echo(' ') + if v:shell_error == 1 + call EchoError('Error running command: ' . command) + return + endif + + exec "bel silent new " . file . ".lint" + + for i in split(result, "\n") + call append("$", i) + endfor + + "remove first empty line + exec "delete 1" +endfunction " }}} + +" Marks() {{{2 +" Like, :marks, but opens a temporary buffer. +function! Marks() + redir => list + silent exec 'marks' + redir END + + let marks = [] + let filelength = 0 + for entry in split(list, '\n') + echo entry + let buffer = {} + let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '') + let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '') + let buffer.path = fnamemodify(buffer.path, ':p') + let buffer.file = fnamemodify(buffer.path, ':p:t') + let buffer.dir = fnamemodify(buffer.path, ':p:h') + exec 'let buffer.bufnr = ' . substitute(entry, '\s*\([0-9]\+\).*', '\1', '') + exec 'let buffer.lnum = ' . + \ substitute(entry, '.*"\s\+line\s\+\([0-9]\+\).*', '\1', '') + call add(marks, buffer) + + if len(buffer.file) > filelength + let filelength = len(buffer.file) + endif + endfor + + if g:EclimBuffersSort != '' + call sort(buffers, 'BufferCompare') + endif + + let lines = [] + for buffer in buffers + call add(lines, s:BufferEntryToLine(buffer, filelength)) + endfor + + call TempWindow('[marks]', lines) + let b:eclim_buffers = buffers + + " syntax + set ft=eclim_buffers + hi link BufferActive Special + hi link BufferHidden Comment + syntax match BufferActive /+\?active\s\+\(\[RO\]\)\?/ + syntax match BufferHidden /+\?hidden\s\+\(\[RO\]\)\?/ + + " mappings + nnoremap <silent> <buffer> <cr> :call <SID>BufferOpen(g:EclimBuffersDefaultAction)<cr> + nnoremap <silent> <buffer> E :call <SID>BufferOpen('edit')<cr> + nnoremap <silent> <buffer> S :call <SID>BufferOpen('split')<cr> + nnoremap <silent> <buffer> T :call <SID>BufferOpen('tablast \| tabnew')<cr> + nnoremap <silent> <buffer> D :call <SID>BufferDelete()<cr> + + "augroup eclim_buffers + " autocmd! + " autocmd BufAdd,BufWinEnter,BufDelete,BufWinLeave * + " \ call eclim#common#buffers#BuffersUpdate() + " autocmd BufUnload <buffer> autocmd! eclim_buffers + "augroup END +endfunction " }}} +command Marks :call Marks() + +" s:BufferOpen2(cmd) {{{2 +function! s:BufferOpen2(cmd) + let line = line('.') + if line > len(b:eclim_buffers) + return + endif + + let bufnr = b:eclim_buffers[line - 1].bufnr + let winnr = b:winnr + close + exec winnr . 'winc w' + call GoToBufferWindowOrOpen2(bufnr, a:cmd) +endfunction " }}} + +" GoToBufferWindowOrOpen2(nr, cmd) {{{2 +" modified function GoToBufferWindowOrOpen. instead of buffer name it accepts +" buffer number. +function! GoToBufferWindowOrOpen2(nr, cmd) + let winnr = bufwinnr(a:nr) + if winnr != -1 + exec winnr . "winc w" + call DelayedCommand('doautocmd WinEnter') + else + if a:cmd == 'edit' + silent exec 'buffer ' . a:nr + elseif a:cmd == 'split' + silent exec 'sbuffer ' . a:nr + endif + endif +endfunction " }}} + +" ToggleQFonValidate() {{{2 +" Nice on/off feature for open/not open qf window after save validation. To be +" mapped on convinent shortcut or called in command line. +function! ToggleQFonValidate() + if g:EclimOpenQFLists + let g:EclimOpenQFLists = 0 + call Echo('QF on validate off') + else + let g:EclimOpenQFLists = 1 + call Echo('QF on validate on') + endif +endfun " }}} + +" }}} + +" vim:ft=vim:fdm=marker + diff --git a/plugin/fuf.vim b/plugin/fuf.vim new file mode 100644 index 0000000..c215748 --- /dev/null +++ b/plugin/fuf.vim @@ -0,0 +1,177 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +" GetLatestVimScripts: 1984 1 :AutoInstall: FuzzyFinder +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_fuf') + finish +elseif v:version < 702 + echoerr 'FuzzyFinder does not support this version of vim (' . v:version . ').' + finish +endif +let g:loaded_fuf = 1 + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS {{{1 + +" +function s:initialize() + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_modes' , [ + \ 'buffer', 'file', 'dir', 'mrufile', 'mrucmd', + \ 'bookmark', 'tag', 'taggedfile', + \ 'jumplist', 'changelist', 'quickfix', 'line', 'help', + \ 'givenfile', 'givendir', 'givencmd', + \ 'callbackfile', 'callbackitem', + \ ]) + call s:defineOption('g:fuf_modesDisable' , [ 'mrufile', 'mrucmd', ]) + call s:defineOption('g:fuf_keyOpen' , '<CR>') + call s:defineOption('g:fuf_keyOpenSplit' , '<C-j>') + call s:defineOption('g:fuf_keyOpenVsplit' , '<C-k>') + call s:defineOption('g:fuf_keyOpenTabpage' , '<C-l>') + call s:defineOption('g:fuf_keyPreview' , '<C-@>') + call s:defineOption('g:fuf_keyNextMode' , '<C-t>') + call s:defineOption('g:fuf_keyPrevMode' , '<C-y>') + call s:defineOption('g:fuf_keyPrevPattern' , '<C-s>') + call s:defineOption('g:fuf_keyNextPattern' , '<C-_>') + call s:defineOption('g:fuf_keySwitchMatching', '<C-\><C-\>') + call s:defineOption('g:fuf_infoFile' , '~/.vim-fuf') + call s:defineOption('g:fuf_abbrevMap' , {}) + call s:defineOption('g:fuf_patternSeparator' , ';') + call s:defineOption('g:fuf_promptHighlight' , 'Question') + call s:defineOption('g:fuf_ignoreCase' , 1) + call s:defineOption('g:fuf_splitPathMatching', 1) + call s:defineOption('g:fuf_smartBs' , 1) + call s:defineOption('g:fuf_reuseWindow' , 1) + call s:defineOption('g:fuf_timeFormat' , '(%Y-%m-%d %H:%M:%S)') + call s:defineOption('g:fuf_learningLimit' , 100) + call s:defineOption('g:fuf_enumeratingLimit' , 50) + call s:defineOption('g:fuf_maxMenuWidth' , 78) + call s:defineOption('g:fuf_previewHeight' , 10) + call s:defineOption('g:fuf_useMigemo' , 0) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_buffer_prompt' , '>Buffer[]>') + call s:defineOption('g:fuf_buffer_switchOrder', 10) + call s:defineOption('g:fuf_buffer_mruOrder' , 1) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_file_prompt' , '>File[]>') + call s:defineOption('g:fuf_file_switchOrder', 20) + call s:defineOption('g:fuf_file_exclude' , '\v\~$|\.(o|exe|dll|bak|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])') + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_dir_prompt' , '>Dir[]>') + call s:defineOption('g:fuf_dir_switchOrder', 30) + call s:defineOption('g:fuf_dir_exclude' , '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])') + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_mrufile_prompt' , '>Mru-File[]>') + call s:defineOption('g:fuf_mrufile_switchOrder', 40) + call s:defineOption('g:fuf_mrufile_exclude' , '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)') + call s:defineOption('g:fuf_mrufile_maxItem' , 200) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_mrucmd_prompt' , '>Mru-Cmd[]>') + call s:defineOption('g:fuf_mrucmd_switchOrder', 50) + call s:defineOption('g:fuf_mrucmd_exclude' , '^$') + call s:defineOption('g:fuf_mrucmd_maxItem' , 200) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_bookmark_prompt' , '>Bookmark[]>') + call s:defineOption('g:fuf_bookmark_switchOrder', 60) + call s:defineOption('g:fuf_bookmark_searchRange', 400) + call s:defineOption('g:fuf_bookmark_keyDelete' , '<C-]>') + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_tag_prompt' , '>Tag[]>') + call s:defineOption('g:fuf_tag_switchOrder', 70) + call s:defineOption('g:fuf_tag_cache_dir' , '~/.vim-fuf-cache/tag') + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_taggedfile_prompt' , '>Tagged-File[]>') + call s:defineOption('g:fuf_taggedfile_switchOrder', 80) + call s:defineOption('g:fuf_taggedfile_cache_dir' , '~/.vim-fuf-cache/taggedfile') + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_jumplist_prompt' , '>Jump-List[]>') + call s:defineOption('g:fuf_jumplist_switchOrder', 90) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_changelist_prompt' , '>Change-List[]>') + call s:defineOption('g:fuf_changelist_switchOrder', 100) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_quickfix_prompt' , '>Quickfix[]>') + call s:defineOption('g:fuf_quickfix_switchOrder', 110) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_line_prompt' , '>Line[]>') + call s:defineOption('g:fuf_line_switchOrder', 120) + "--------------------------------------------------------------------------- + call s:defineOption('g:fuf_help_prompt' , '>Help[]>') + call s:defineOption('g:fuf_help_switchOrder', 130) + call s:defineOption('g:fuf_help_cache_dir' , '~/.vim-fuf-cache/help') + "--------------------------------------------------------------------------- + call filter(g:fuf_modes, 'count(g:fuf_modesDisable, v:val) == 0') + for m in g:fuf_modes + call fuf#{m}#renewCache() + call fuf#{m}#onInit() + endfor + "--------------------------------------------------------------------------- + command! -bang -narg=0 FufEditInfo call fuf#editInfoFile() + command! -bang -narg=0 FufRenewCache call s:renewCachesOfAllModes() + "--------------------------------------------------------------------------- + for m in g:fuf_modes + if fuf#{m}#requiresOnCommandPre() + " cnoremap has a problem, which doesn't expand cabbrev. + cmap <silent> <expr> <CR> <SID>onCommandPre() + break + endif + endfor + "--------------------------------------------------------------------------- +endfunction + +" +function s:initMisc() +endfunction + +" +function s:defineOption(name, default) + if !exists(a:name) + let {a:name} = a:default + endif +endfunction + +" +function s:renewCachesOfAllModes() + for m in g:fuf_modes + call fuf#{m}#renewCache() + endfor +endfunction + +" +function s:onBufEnter() + for m in g:fuf_modes + call fuf#{m}#onBufEnter() + endfor +endfunction + +" +function s:onBufWritePost() + for m in g:fuf_modes + call fuf#{m}#onBufWritePost() + endfor +endfunction + +" +function s:onCommandPre() + for m in filter(copy(g:fuf_modes), 'fuf#{v:val}#requiresOnCommandPre()') + call fuf#{m}#onCommandPre(getcmdtype() . getcmdline()) + endfor + " lets last entry become the newest in the history + call histadd(getcmdtype(), getcmdline()) + " this is not mapped again (:help recursive_mapping) + return "\<CR>" +endfunction + +" }}}1 +"============================================================================= +" INITIALIZATION {{{1 + +call s:initialize() + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/plugin/getscriptPlugin.vim b/plugin/getscriptPlugin.vim new file mode 100644 index 0000000..e88db7f --- /dev/null +++ b/plugin/getscriptPlugin.vim @@ -0,0 +1,38 @@ +" --------------------------------------------------------------------- +" getscriptPlugin.vim +" Author: Charles E. Campbell, Jr. +" Date: Jan 07, 2008 +" Installing: :help glvs-install +" Usage: :help glvs +" +" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim +" +" (Rom 15:11 WEB) Again, "Praise the Lord, all you Gentiles! Let +" all the peoples praise Him." +" --------------------------------------------------------------------- +" Initialization: {{{1 +" if you're sourcing this file, surely you can't be +" expecting vim to be in its vi-compatible mode +if &cp || exists("g:loaded_getscriptPlugin") + if &verbose + echo "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)" + endif + finish +endif +let g:loaded_getscriptPlugin = "v29" +let s:keepcpo = &cpo +set cpo&vim + +" --------------------------------------------------------------------- +" Public Interface: {{{1 +com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts() +com! -nargs=0 GetScripts call getscript#GetLatestVimScripts() +silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts() + +" --------------------------------------------------------------------- +" Restore Options: {{{1 +let &cpo= s:keepcpo +unlet s:keepcpo + +" --------------------------------------------------------------------- +" vim: ts=8 sts=2 fdm=marker nowrap diff --git a/plugin/grep.vim b/plugin/grep.vim new file mode 100644 index 0000000..b9e8f32 --- /dev/null +++ b/plugin/grep.vim @@ -0,0 +1,854 @@ +" File: grep.vim +" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +" Version: 1.9 +" Last Modified: September 10, 2007 +" +" Overview +" -------- +" The grep plugin integrates the grep, fgrep, egrep, and agrep tools with +" Vim and allows you to search for a pattern in one or more files and jump +" to them. +" +" To use this plugin, you need the grep, fgrep, egrep, agrep, find and +" xargs utilities. These tools are present in most of the Unix installations. +" For MS-Windows systems, you can download the GNU grep and find utilities +" from the following sites: +" +" http://gnuwin32.sourceforge.net/packages/grep.htm +" http://gnuwin32.sourceforge.net/packages/findutils.htm +" +" Installation +" ------------ +" 1. Copy the grep.vim file to the $HOME/.vim/plugin or $HOME/vimfiles/plugin +" or $VIM/vimfiles/plugin directory. +" Refer to the following Vim help topics for more information about Vim +" plugins: +" :help add-plugin +" :help add-global-plugin +" :help runtimepath +" 2. If the grep executables are not already present in one of the directories +" in the PATH environment variable, then set the Grep_Path and other _Path +" variables to point to the location of the grep utilites in the .vimrc +" file. +" 3. Restart Vim. +" 4. You can now use the ":Grep" and other commands to search for patterns in +" files. +" +" Usage +" ----- +" The grep.vim plugin introduces the following Vim commands: +" +" :Grep - Search for the specified pattern in the specified files +" :GrepAdd - Same as ":Grep" but adds the results to the current results +" :Rgrep - Run recursive grep +" :RgrepAdd - Same as ":Rgrep" but adds the results to the current results +" :GrepBuffer - Search for a pattern on all open buffers +" :GrepBufferAdd - Same as ":GrepBuffer" but adds the results to the current +" results +" :Bgrep - Same as :GrepBuffer +" :BgrepAdd - Same as :GrepBufferAdd +" :GrepArgs - Search for a pattern on all the Vim argument +" filenames (:args) +" :GrepArgsAdd - Same as ":GrepArgs" but adds the results to the current +" results +" :Fgrep - Run fgrep +" :FgrepAdd - Same as ":Fgrep" but adds the results to the current +" results +" :Rfgrep - Run recursive fgrep +" :RfgrepAdd - Same as ":Rfgrep" but adds the results to the current +" results +" :Egrep - Run egrep +" :EgrepAdd - Same as ":Egrep" but adds the results to the current +" results +" :Regrep - Run recursive egrep +" :RegrepAdd - Same as ":Regrep" but adds the results to the current +" results +" :Agrep - Run agrep +" :AgrepAdd - Same as ":Agrep" but adds the results to the current +" results +" :Ragrep - Run recursive agrep +" :RagrepAdd - Same as ":Ragrep" but adds the results to the current +" results +" +" The above commands can be invoked like this: +" +" :Grep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Rgrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Fgrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Rfgrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Egrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Regrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Agrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :Ragrep [<grep_options>] [<search_pattern> [<file_name(s)>]] +" +" :GrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :RgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :FgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :RfgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :EgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :RegrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :AgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" :RagrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]] +" +" :GrepBuffer [<grep_options>] [<search_pattern>] +" :Bgrep [<grep_options>] [<search_pattern>] +" :GrepArgs [<grep_options>] [<search_pattern>] +" +" :GrepBufferAdd [<grep_options>] [<search_pattern>] +" :BgrepAdd [<grep_options>] [<search_pattern>] +" :GrepArgsAdd [<grep_options>] [<search_pattern>] +" +" In the above commands, all the arguments are optional. +" +" You can specify grep options like -i (ignore case) or -w (search for a word) +" to the above commands. If the <grep_options> are not specified, then the +" default grep options specified by the variable Grep_Default_Options is +" used. +" +" You can specify the grep pattern to search as an argument to the above +" commands. If the <search_pattern> is not specified, then you will be +" prompted to enter a search pattern. By default, the keyword under the cursor +" is displayed for the search pattern prompt. You can accept the default or +" modify it. +" +" The search pattern is automatically enclosed by the character specified in +" the Grep_Shell_Quote_Char variable. You should not enclose the search +" pattern with a shell escape character. +" +" If you want to specify a search pattern with space characters or a +" multi-word pattern, then you should use the Grep command pattern input +" prompt to supply the pattern. +" +" You can specify one or more file names (or file patterns) to the above +" commands. If the <file_names> are not specified, then you will be prompted +" to enter file names. By default, the pattern specified by the +" Grep_Default_Filelist variable is used. To specify the file name(s) as an +" argument to the above commands, you have to specify the search pattern also. +" +" When you enter only the command name, you will be prompted to enter the +" search pattern and the files in which to search for the pattern. By default, +" the keyword under the cursor is displayed for the search pattern prompt. +" Depending on the command, you may prompted for additional parameters like +" the directories to search for the pattern. +" +" You can retrieve previously entered values for the Grep prompts using the up +" and down arrow keys. You can cancel the command by pressing the escape key. +" You can use CTRL-U to erase the default shown for the prompt and CTRL-W to +" erase the previous word in the prompt. For more information about editing +" the prompt, read ':help cmdline-editing' Vim help topic. +" +" After invoking any of the grep commands, you can cancel the command, when +" you are prompted for a search pattern or file names or a directory by +" pressing the <Esc> key. You cannot cancel (or kill) the +" grep/fgrep/egrep/agrep commands after the external command is invoked. +" +" The GrepAdd, RgrepAdd and other *Add commands append the search output to +" the current search output. This is useful if you want to see the search +" results for multiple patterns at the same time. These commands are available +" only in Vim version 7.0 and above. +" +" You can map a key to invoke any of the above commands. For example, the +" following map invokes the :Grep command to search for the keyword under the +" cursor: +" +" nnoremap <silent> <F3> :Grep<CR> +" +" The output of the grep command will be listed in the Vim quickfix window. +" 1. You can select a line in the quickfix window and press <Enter> or double +" click on a match to jump to that line. +" 2. You can use the ":cnext" and ":cprev" commands to the jump to the next or +" previous output line. +" 3. You can use the ":colder" and ":cnewer" commands to go between multiple +" grep quickfix output windows. +" 4. The quickfix window need not be opened always to use the grep output. +" You can close the quickfix window and use the quickfix commands to jump +" to the grep matches. Use the ":copen" command to open the quickfix +" window again. +" +" For more information about other quickfix commands read ":help quickfix" +" +" When using GUI Vim, the Tools->Search menu item with a few sub-menu items is +" created for few variations of the search command. +" +" Configuration +" ------------- +" By changing the following variables you can configure the behavior of this +" plugin. Set the following variables in your .vimrc file using the 'let' +" command. +" +" The 'Grep_Path' variable is used to locate the grep utility. By default, +" this is set to grep. You can change this using the let command: +" +" :let Grep_Path = 'd:\tools\grep.exe' +" +" The 'Fgrep_Path' variable is used to locate the fgrep utility. By default, +" this is set to fgrep. You can change this using the let command: +" +" :let Fgrep_Path = 'd:\tools\fgrep.exe' +" +" The 'Egrep_Path' variable is used to locate the egrep utility. By default, +" this is set to egrep. You can change this using the let command: +" +" :let Egrep_Path = 'd:\tools\egrep.exe' +" +" The 'Agrep_Path' variable is used to locate the agrep utility. By default, +" this is set to agrep. You can change this using the let command: +" +" :let Agrep_Path = 'd:\tools\agrep.exe' +" +" The 'Grep_Find_Path' variable is used to locate the find utility. By +" default, this is set to d:\tools\find.exe. You can change this using the let +" command: +" +" :let Grep_Find_Path = 'd:\tools\find.exe' +" +" The 'Grep_Xargs_Path' variable is used to locate the xargs utility. By +" default, this is set to xargs. You can change this using the let +" command: +" +" :let Grep_Xargs_Path = 'd:\tools\xargs.exe' +" +" When running any one of the Grep commands, you will be prompted for the +" files in which to search for the pattern. The 'Grep_Default_Filelist' +" variable is used to specify to default for this prompt. By default, this +" variable is set to '*'. You can specify multiple matching patterns separated +" by spaces. You can change this settings using the let command: +" +" :let Grep_Default_Filelist = '*.[chS]' +" :let Grep_Default_Filelist = '*.c *.cpp *.asm' +" +" The 'Grep_Default_Options' is used to pass default command line options to +" the grep/fgrep/egrep/agrep utilities. By default, this is set to an empty +" string. You can change this using the let command: +" +" :let Grep_Default_Options = '-i' +" +" The 'Grep_Skip_Dirs' variable specifies the list of directories to skip +" while doing recursive searches. By default, this is set to 'RCS CVS SCCS'. +" You can change this using the let command: +" +" :let Grep_Skip_Dirs = 'dir1 dir2 dir3' +" +" The 'Grep_Skip_Files' variable specifies the list of files to skip while +" doing recursive searches. By default, this is set to '*~ *,v s.*'. You can +" change this using the let command: +" +" :let Grep_Skip_Files = '*.bak *~' +" +" By default, when you invoke the Grep commands the quickfix window will be +" opened with the grep output. You can disable opening the quickfix window, +" by setting the 'Grep_OpenQuickfixWindow' variable to zero: +" +" :let Grep_OpenQuickfixWindow = 0 +" +" You can manually open the quickfix window using the :cwindow command. +" +" By default, for recursive searches, the 'find' and 'xargs' utilities are +" used. If you don't have the 'xargs' utility or don't want to use the +" 'xargs' utility, " then you can set the 'Grep_Find_Use_Xargs' variable to +" zero. If this is set to zero, then only the 'find' utility is used for +" recursive searches: +" +" :let Grep_Find_Use_Xargs = 0 +" +" To handle file names with space characters in them, the xargs utility +" is invoked with the '--null' argument. If the xargs utility in your system +" doesn't accept the '--null' argument, then you can change the +" Grep_Xargs_Options variable. For example, to use the '--print0' xargs +" argument, you can use the following command: +" +" :let Grep_Xargs_Options = '--print0' +" +" The Grep_Cygwin_Find variable should be set to 1, if you are using the find +" utility from the cygwin package. This setting is used to handle the +" difference between the backslash and forward slash path separators. +" +" :let Grep_Cygwin_Find = 1 +" +" The 'Grep_Null_Device' variable specifies the name of the null device to +" pass to the grep commands. This is needed to force the grep commands to +" print the name of the file in which a match is found, if only one filename +" is specified. For Unix systems, this is set to /dev/null and for MS-Windows +" systems, this is set to NUL. You can modify this by using the let command: +" +" :let Grep_Null_Device = '/dev/null' +" +" The 'Grep_Shell_Quote_Char' variable specifies the quote character to use +" for protecting patterns from being interpreted by the shell. For Unix +" systems, this is set to "'" and for MS-Window systems, this is set to an +" empty string. You can change this using the let command: +" +" :let Grep_Shell_Quote_Char = "'" +" +" The 'Grep_Shell_Escape_Char' variable specifies the escape character to use +" for protecting special characters from being interpreted by the shell. For +" Unix systems, this is set to '\' and for MS-Window systems, this is set to +" an empty string. You can change this using the let command: +" +" :let Grep_Shell_Escape_Char = "'" +" +" --------------------- Do not modify after this line --------------------- +if exists("loaded_grep") + finish +endif +let loaded_grep = 1 + +" Line continuation used here +let s:cpo_save = &cpo +set cpo&vim + +" Location of the grep utility +if !exists("Grep_Path") + let Grep_Path = 'grep' +endif + +" Location of the fgrep utility +if !exists("Fgrep_Path") + let Fgrep_Path = 'fgrep' +endif + +" Location of the egrep utility +if !exists("Egrep_Path") + let Egrep_Path = 'egrep' +endif + +" Location of the agrep utility +if !exists("Agrep_Path") + let Agrep_Path = 'agrep' +endif + +" Location of the find utility +if !exists("Grep_Find_Path") + let Grep_Find_Path = 'find' +endif + +" Location of the xargs utility +if !exists("Grep_Xargs_Path") + let Grep_Xargs_Path = 'xargs' +endif + +" Open the Grep output window. Set this variable to zero, to not open +" the Grep output window by default. You can open it manually by using +" the :cwindow command. +if !exists("Grep_OpenQuickfixWindow") + let Grep_OpenQuickfixWindow = 1 +endif + +" Default grep file list +if !exists("Grep_Default_Filelist") + let Grep_Default_Filelist = '*' +endif + +" Default grep options +if !exists("Grep_Default_Options") + let Grep_Default_Options = '' +endif + +" Use the 'xargs' utility in combination with the 'find' utility. Set this +" to zero to not use the xargs utility. +if !exists("Grep_Find_Use_Xargs") + let Grep_Find_Use_Xargs = 1 +endif + +" The command-line arguments to supply to the xargs utility +if !exists('Grep_Xargs_Options') + let Grep_Xargs_Options = '--null' +endif + +" The find utility is from the cygwin package or some other find utility. +if !exists("Grep_Cygwin_Find") + let Grep_Cygwin_Find = 0 +endif + +" NULL device name to supply to grep. We need this because, grep will not +" print the name of the file, if only one filename is supplied. We need the +" filename for Vim quickfix processing. +if !exists("Grep_Null_Device") + if has("win32") || has("win16") || has("win95") + let Grep_Null_Device = 'NUL' + else + let Grep_Null_Device = '/dev/null' + endif +endif + +" Character to use to quote patterns and filenames before passing to grep. +if !exists("Grep_Shell_Quote_Char") + if has("win32") || has("win16") || has("win95") + let Grep_Shell_Quote_Char = '' + else + let Grep_Shell_Quote_Char = "'" + endif +endif + +" Character to use to escape special characters before passing to grep. +if !exists("Grep_Shell_Escape_Char") + if has("win32") || has("win16") || has("win95") + let Grep_Shell_Escape_Char = '' + else + let Grep_Shell_Escape_Char = '\' + endif +endif + +" The list of directories to skip while searching for a pattern. Set this +" variable to '', if you don't want to skip directories. +if !exists("Grep_Skip_Dirs") + let Grep_Skip_Dirs = 'RCS CVS SCCS' +endif + +" The list of files to skip while searching for a pattern. Set this variable +" to '', if you don't want to skip any files. +if !exists("Grep_Skip_Files") + let Grep_Skip_Files = '*~ *,v s.*' +endif + +" RunGrepCmd() +" Run the specified grep command using the supplied pattern +function! s:RunGrepCmd(cmd, pattern, action) + let cmd_output = system(a:cmd) + + if cmd_output == "" + echohl WarningMsg | + \ echomsg "Error: Pattern " . a:pattern . " not found" | + \ echohl None + return + endif + + let tmpfile = tempname() + + let old_verbose = &verbose + set verbose&vim + + exe "redir! > " . tmpfile + silent echon '[Search results for pattern: ' . a:pattern . "]\n" + silent echon cmd_output + redir END + + let &verbose = old_verbose + + let old_efm = &efm + set efm=%f:%\\s%#%l:%m + + if v:version >= 700 && a:action == 'add' + execute "silent! caddfile " . tmpfile + else + if exists(":cgetfile") + execute "silent! cgetfile " . tmpfile + else + execute "silent! cfile " . tmpfile + endif + endif + + let &efm = old_efm + + " Open the grep output window + if g:Grep_OpenQuickfixWindow == 1 + " Open the quickfix window below the current window + botright copen + endif + + call delete(tmpfile) +endfunction + +" RunGrepRecursive() +" Run specified grep command recursively +function! s:RunGrepRecursive(cmd_name, grep_cmd, action, ...) + if a:0 > 0 && (a:1 == "-?" || a:1 == "-h") + echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern> " . + \ "[<file_name(s)>]]" + return + endif + + let grep_opt = "" + let pattern = "" + let filepattern = "" + + let argcnt = 1 + while argcnt <= a:0 + if a:{argcnt} =~ '^-' + let grep_opt = grep_opt . " " . a:{argcnt} + elseif pattern == "" + let pattern = g:Grep_Shell_Quote_Char . a:{argcnt} . + \ g:Grep_Shell_Quote_Char + else + let filepattern = filepattern . " " . a:{argcnt} + endif + let argcnt= argcnt + 1 + endwhile + if grep_opt == "" + let grep_opt = g:Grep_Default_Options + endif + + if a:grep_cmd != 'agrep' + " Don't display messages about non-existent files + " Agrep doesn't support the -s option + let grep_opt = grep_opt . " -s" + endif + + if a:grep_cmd == 'grep' + let grep_path = g:Grep_Path + let grep_expr_option = '--' + elseif a:grep_cmd == 'fgrep' + let grep_path = g:Fgrep_Path + let grep_expr_option = '-e' + elseif a:grep_cmd == 'egrep' + let grep_path = g:Egrep_Path + let grep_expr_option = '-e' + elseif a:grep_cmd == 'agrep' + let grep_path = g:Agrep_Path + let grep_expr_option = '' + else + return + endif + + " No argument supplied. Get the identifier and file list from user + if pattern == "" + let pattern = input("Search for pattern: ", expand("<cword>")) + if pattern == "" + return + endif + let pattern = g:Grep_Shell_Quote_Char . pattern . + \ g:Grep_Shell_Quote_Char + endif + + let cwd = getcwd() + if g:Grep_Cygwin_Find == 1 + let cwd = substitute(cwd, "\\", "/", "g") + endif + if v:version >= 700 + let startdir = input("Start searching from directory: ", cwd, "dir") + else + let startdir = input("Start searching from directory: ", cwd) + endif + if startdir == "" + return + endif + + if filepattern == "" + let filepattern = input("Search in files matching pattern: ", + \ g:Grep_Default_Filelist) + if filepattern == "" + return + endif + endif + + let txt = filepattern . ' ' + let find_file_pattern = '' + while txt != '' + let one_pattern = strpart(txt, 0, stridx(txt, ' ')) + if find_file_pattern != '' + let find_file_pattern = find_file_pattern . ' -o' + endif + let find_file_pattern = find_file_pattern . ' -name ' . + \ g:Grep_Shell_Quote_Char . one_pattern . g:Grep_Shell_Quote_Char + let txt = strpart(txt, stridx(txt, ' ') + 1) + endwhile + let find_file_pattern = g:Grep_Shell_Escape_Char . '(' . + \ find_file_pattern . ' ' . g:Grep_Shell_Escape_Char . ')' + + let txt = g:Grep_Skip_Dirs + let find_prune = '' + if txt != '' + let txt = txt . ' ' + while txt != '' + let one_dir = strpart(txt, 0, stridx(txt, ' ')) + if find_prune != '' + let find_prune = find_prune . ' -o' + endif + let find_prune = find_prune . ' -name ' . one_dir + let txt = strpart(txt, stridx(txt, ' ') + 1) + endwhile + let find_prune = '-type d ' . g:Grep_Shell_Escape_Char . '(' . + \ find_prune + let find_prune = find_prune . ' ' . g:Grep_Shell_Escape_Char . ')' + endif + + let txt = g:Grep_Skip_Files + let find_skip_files = '-type f' + if txt != '' + let txt = txt . ' ' + while txt != '' + let one_file = strpart(txt, 0, stridx(txt, ' ')) + let find_skip_files = find_skip_files . ' ! -name ' . + \ g:Grep_Shell_Quote_Char . one_file . + \ g:Grep_Shell_Quote_Char + let txt = strpart(txt, stridx(txt, ' ') + 1) + endwhile + endif + + if g:Grep_Find_Use_Xargs == 1 + let cmd = g:Grep_Find_Path . " " . startdir + let cmd = cmd . " " . find_prune . " -prune -o" + let cmd = cmd . " " . find_skip_files + let cmd = cmd . " " . find_file_pattern + let cmd = cmd . " -print0 | " + let cmd = cmd . g:Grep_Xargs_Path . ' ' . g:Grep_Xargs_Options + let cmd = cmd . ' ' . grep_path . " " . grep_opt . " -n " + let cmd = cmd . grep_expr_option . " " . pattern + let cmd = cmd . ' ' . g:Grep_Null_Device + else + let cmd = g:Grep_Find_Path . " " . startdir + let cmd = cmd . " " . find_prune . " -prune -o" + let cmd = cmd . " " . find_skip_files + let cmd = cmd . " " . find_file_pattern + let cmd = cmd . " -exec " . grep_path . " " . grep_opt . " -n " + let cmd = cmd . grep_expr_option . " " . pattern + let cmd = cmd . " {} " . g:Grep_Null_Device . ' ' . + \ g:Grep_Shell_Escape_Char . ';' + endif + + call s:RunGrepCmd(cmd, pattern, a:action) +endfunction + +" RunGrepSpecial() +" Search for a pattern in all the opened buffers or filenames in the +" argument list +function! s:RunGrepSpecial(cmd_name, which, action, ...) + if a:0 > 0 && (a:1 == "-?" || a:1 == "-h") + echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern>]" + return + endif + + " Search in all the Vim buffers + if a:which == 'buffer' + " Get a list of all the buffer names + let last_bufno = bufnr("$") + + let i = 1 + let filenames = "" + + while i <= last_bufno + if bufexists(i) && buflisted(i) + let filenames = filenames . " " . bufname(i) + endif + let i = i + 1 + endwhile + + " No buffers + if filenames == "" + return + endif + elseif a:which == 'args' + " Search in all the filenames in the argument list + let arg_cnt = argc() + + if arg_cnt == 0 + echohl WarningMsg + echomsg "Error: Argument list is empty" + echohl None + return + endif + + let i = 0 + let filenames = "" + + while i < arg_cnt + let filenames = filenames . " " . argv(i) + let i = i + 1 + endwhile + + " No arguments + if filenames == "" + echohl WarningMsg + echomsg "Error: Argument list is empty" + echohl None + return + endif + endif + + let grep_opt = "" + let pattern = "" + + " Get the list of optional grep command-line options (if present) + " supplied by the user. All the grep options will be preceded + " by a '-' + let argcnt= 1 + while argcnt <= a:0 && a:{argcnt} =~ '^-' + let grep_opt = grep_opt . " " . a:{argcnt} + let argcnt = argcnt + 1 + endwhile + + " If the user didn't specify the option, then use the defaults + if grep_opt == "" + let grep_opt = g:Grep_Default_Options + endif + + " Don't display messages about non-existent files + let grep_opt = grep_opt . " -s" + + " The last argument specified by the user is the pattern + if argcnt == a:0 + let pattern = a:{argcnt} + else + " No argument supplied. Get the identifier and file list from user + let pattern = input("Search for pattern: ", expand("<cword>")) + if pattern == "" + return + endif + endif + + let pattern = g:Grep_Shell_Quote_Char . pattern . g:Grep_Shell_Quote_Char + + " Add /dev/null to the list of filenames, so that grep print the + " filename and linenumber when grepping in a single file + let filenames = filenames . " " . g:Grep_Null_Device + let cmd = g:Grep_Path . " " . grep_opt . " -n -- " + let cmd = cmd . pattern . " " . filenames + + call s:RunGrepCmd(cmd, pattern, a:action) +endfunction + +" RunGrep() +" Run the specified grep command +function! s:RunGrep(cmd_name, grep_cmd, action, ...) + if a:0 > 0 && (a:1 == "-?" || a:1 == "-h") + echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern> " . + \ "[<file_name(s)>]]" + return + endif + + let grep_opt = "" + let pattern = "" + let filenames = "" + + " Parse the arguments + " grep command-line flags are specified using the "-flag" format + " the next argument is assumed to be the pattern + " and the next arguments are assumed to be filenames or file patterns + let argcnt = 1 + while argcnt <= a:0 + if a:{argcnt} =~ '^-' + let grep_opt = grep_opt . " " . a:{argcnt} + elseif pattern == "" + let pattern = g:Grep_Shell_Quote_Char . a:{argcnt} . + \ g:Grep_Shell_Quote_Char + else + let filenames= filenames . " " . a:{argcnt} + endif + let argcnt = argcnt + 1 + endwhile + + if grep_opt == "" + let grep_opt = g:Grep_Default_Options + endif + + if a:grep_cmd != 'agrep' + " Don't display messages about non-existent files + " Agrep doesn't support the -s option + let grep_opt = grep_opt . " -s" + endif + + if a:grep_cmd == 'grep' + let grep_path = g:Grep_Path + let grep_expr_option = '--' + elseif a:grep_cmd == 'fgrep' + let grep_path = g:Fgrep_Path + let grep_expr_option = '-e' + elseif a:grep_cmd == 'egrep' + let grep_path = g:Egrep_Path + let grep_expr_option = '-e' + elseif a:grep_cmd == 'agrep' + let grep_path = g:Agrep_Path + let grep_expr_option = '' + else + return + endif + + " Get the identifier and file list from user + if pattern == "" + let pattern = input("Search for pattern: ", expand("<cword>")) + if pattern == "" + return + endif + let pattern = g:Grep_Shell_Quote_Char . pattern . + \ g:Grep_Shell_Quote_Char + endif + + if filenames == "" + if v:version >= 700 + let filenames = input("Search in files: ", g:Grep_Default_Filelist, + \ "file") + else + let filenames = input("Search in files: ", g:Grep_Default_Filelist) + endif + if filenames == "" + return + endif + endif + + " Add /dev/null to the list of filenames, so that grep print the + " filename and linenumber when grepping in a single file + let filenames = filenames . " " . g:Grep_Null_Device + let cmd = grep_path . " " . grep_opt . " -n " + let cmd = cmd . grep_expr_option . " " . pattern + let cmd = cmd . " " . filenames + + call s:RunGrepCmd(cmd, pattern, a:action) +endfunction + +" Define the set of grep commands +command! -nargs=* -complete=file Grep + \ call s:RunGrep('Grep', 'grep', 'set', <f-args>) +command! -nargs=* -complete=file Rgrep + \ call s:RunGrepRecursive('Rgrep', 'grep', 'set', <f-args>) +command! -nargs=* GrepBuffer + \ call s:RunGrepSpecial('GrepBuffer', 'buffer', 'set', <f-args>) +command! -nargs=* Bgrep + \ call s:RunGrepSpecial('Bgrep', 'buffer', 'set', <f-args>) +command! -nargs=* GrepArgs + \ call s:RunGrepSpecial('GrepArgs', 'args', 'set', <f-args>) + +command! -nargs=* -complete=file Fgrep + \ call s:RunGrep('Fgrep', 'fgrep', 'set', <f-args>) +command! -nargs=* -complete=file Rfgrep + \ call s:RunGrepRecursive('Rfgrep', 'fgrep', 'set', <f-args>) +command! -nargs=* -complete=file Egrep + \ call s:RunGrep('Egrep', 'egrep', 'set', <f-args>) +command! -nargs=* -complete=file Regrep + \ call s:RunGrepRecursive('Regrep', 'egrep', 'set', <f-args>) +command! -nargs=* -complete=file Agrep + \ call s:RunGrep('Agrep', 'agrep', 'set', <f-args>) +command! -nargs=* -complete=file Ragrep + \ call s:RunGrepRecursive('Ragrep', 'agrep', 'set', <f-args>) + +if v:version >= 700 +command! -nargs=* -complete=file GrepAdd + \ call s:RunGrep('GrepAdd', 'grep', 'add', <f-args>) +command! -nargs=* -complete=file RgrepAdd + \ call s:RunGrepRecursive('RgrepAdd', 'grep', 'add', <f-args>) +command! -nargs=* GrepBufferAdd + \ call s:RunGrepSpecial('GrepBufferAdd', 'buffer', 'add', <f-args>) +command! -nargs=* BgrepAdd + \ call s:RunGrepSpecial('BgrepAdd', 'buffer', 'add', <f-args>) +command! -nargs=* GrepArgsAdd + \ call s:RunGrepSpecial('GrepArgsAdd', 'args', 'add', <f-args>) + +command! -nargs=* -complete=file FgrepAdd + \ call s:RunGrep('FgrepAdd', 'fgrep', 'add', <f-args>) +command! -nargs=* -complete=file RfgrepAdd + \ call s:RunGrepRecursive('RfgrepAdd', 'fgrep', 'add', <f-args>) +command! -nargs=* -complete=file EgrepAdd + \ call s:RunGrep('EgrepAdd', 'egrep', 'add', <f-args>) +command! -nargs=* -complete=file RegrepAdd + \ call s:RunGrepRecursive('RegrepAdd', 'egrep', 'add', <f-args>) +command! -nargs=* -complete=file AgrepAdd + \ call s:RunGrep('AgrepAdd', 'agrep', 'add', <f-args>) +command! -nargs=* -complete=file RagrepAdd + \ call s:RunGrepRecursive('RagrepAdd', 'agrep', 'add', <f-args>) +endif + +" Add the Tools->Search Files menu +if has('gui_running') + anoremenu <silent> Tools.Search.Current\ Directory<Tab>:Grep + \ :Grep<CR> + anoremenu <silent> Tools.Search.Recursively<Tab>:Rgrep + \ :Rgrep<CR> + anoremenu <silent> Tools.Search.Buffer\ List<Tab>:Bgrep + \ :Bgrep<CR> + anoremenu <silent> Tools.Search.Argument\ List<Tab>:GrepArgs + \ :GrepArgs<CR> +endif + +" restore 'cpo' +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/plugin/jsbeautify.vim b/plugin/jsbeautify.vim new file mode 100644 index 0000000..2512aa1 --- /dev/null +++ b/plugin/jsbeautify.vim @@ -0,0 +1,623 @@ +if &cp || exists("loaded_jsbeautify") + finish +endif +let loaded_jsbeautify = 3 + + + +function! s:trim_output() + while len(s:output) > 0 && (s:output[len(s:output)-1] == " " || s:output[len(s:output)-1] == s:indent_string) + call remove(s:output, -1) + endwhile +endfunction + +function! s:print_newline(ignore_repeated) + let s:if_line_flag = 0 + call s:trim_output() + if len(s:output)==0 + return + endif + if s:output[len(s:output)-1] != "\n" || !a:ignore_repeated + call add(s:output, "\n") + endif + let index = 0 + while index < s:indent_level + call add(s:output, s:indent_string) + let index += 1 + endwhile +endfunction + +function! s:print_space() + let last_output = " " + if len(s:output) > 0 + let last_output = s:output[len(s:output) - 1] + endif + if last_output != " " && last_output != "\n" && last_output != s:indent_string + call add(s:output, " ") + endif +endfunction + +function! s:print_token() + call add(s:output, s:token_text) +endfunctio + +function! s:indent() + let s:indent_level += 1 +endfunction + +function! s:unindent() + if s:indent_level + let s:indent_level -= 1 + endif +endfunction + +function! s:remove_indent() + if len(s:output)>0 && s:output[len(s:output) -1] == s:indent_string + call remove(s:output, -1) + endif +endfunction + +function! s:set_mode(mode) + call add(s:modes, s:current_mode) + let s:current_mode = a:mode +endfunction + +function! s:restore_mode() + if s:current_mode == "DO_BLOCK" + let s:do_block_just_closed = 1 + else + let s:do_block_just_closed = 0 + endif + let s:current_mode = remove(s:modes, -1) +endfunction + +function! s:in_array(what, arr) + return index(a:arr, a:what) != -1 +endfunction + +function! s:get_next_token() + let n_newlines = 0 + + if s:parser_pos >= len(s:input) + return ["", "TK_EOF"] + endif + + let c = s:input[s:parser_pos] + let s:parser_pos += 1 + + while s:in_array(c, s:whitespace) + if s:parser_pos >= len(s:input) + return ["", "TK_EOF"] + endif + + if c == "\n" + let n_newlines += 1 + endif + + let c = s:input[s:parser_pos] + let s:parser_pos += 1 + endwhile + + let wanted_newline = 0 + + if s:opt_preserve_newlines + if n_newlines > 1 + for i in [0, 1] + call s:print_newline(i==0) + endfor + endif + let wanted_newline = n_newlines == 1 + endif + + if s:in_array(c, s:wordchar) + if s:parser_pos < len(s:input) + while s:in_array(s:input[s:parser_pos], s:wordchar) + let c .= s:input[s:parser_pos] + let s:parser_pos += 1 + if s:parser_pos == len(s:input) + break + endif + endwhile + endif + + "if s:parser_pos != len(s:input) && c =~ /^[0-9]+[Ee]$/ && (s:input[s:parser_pos] == "-" || s:input[s:parser_pos] == "+") + "let sign = s:input[s:parser_pos] + "let s:parser_pos += 1 + + "let t = get_next_token(s:parser_pos) + "let c .= sign . t[0] + "return [c, "TK_WORD"] + " endif + + if c == "in" + return [c, "TK_OPERATOR"] + endif + if wanted_newline && s:last_type != "TK_OPERATOR" && !s:if_line_flag + call s:print_newline(1) + endif + return [c, "TK_WORD"] + endif + if c == "(" || c == "[" + return [c, "TK_START_EXPR"] + endif + + if c == ")" || c == "]" + return [c, "TK_END_EXPR"] + endif + + if c == "{" + return [c, "TK_START_BLOCK"] + endif + + if c == "}" + return [c, "TK_END_BLOCK"] + endif + + if c == ";" + return [c, "TK_SEMICOLON"] + endif + + if c == "/" + let comment = "" + if s:input[s:parser_pos] == "*" + let s:parser_pos += 1 + if s:parser_pos < len(s:input) + while !(s:input[s:parser_pos] == "*" && s:parser_pos + 1 < len(s:input) && s:input[s:parser_pos + 1] == "/" && s:parser_pos < len(s:input)) + let comment .= s:input[s:parser_pos] + let s:parser_pos += 1 + if s:parser_pos >= len(s:input) + break + endif + endwhile + endif + let s:parser_pos += 2 + return ['/*' . comment . '*/', 'TK_BLOCK_COMMENT'] + endif + + " peek for comment // ... + if s:input[s:parser_pos] == "/" + let comment = c + while s:input[s:parser_pos] != "\r" && s:input[s:parser_pos] != "\n" + let comment .= s:input[s:parser_pos] + let s:parser_pos += 1 + if s:parser_pos >= len(s:input) + break + endif + endwhile + let s:parser_pos += 1 + if wanted_newline + call s:print_newline(1) + endif + return [comment, "TK_COMMENT"] + endif + endif + + if c == "'" || c =='"' || (c == "/" && ((s:last_type == "TK_WORD" && s:last_text == "return") || (s:last_type == "TK_START_EXPR" || s:last_type == "TK_START_BLOCK" || s:last_type == "TK_END_BLOCK" || s:last_type == "TK_OPERATOR" || s:last_type == "TK_EOF" || s:last_type == "TK_SEMICOLON"))) + let sep = c + let esc = 0 + let resulting_string = c + + if s:parser_pos < len(s:input) + while esc || s:input[s:parser_pos] != sep + let resulting_string .= s:input[s:parser_pos] + if !esc + let esc = s:input[s:parser_pos] == "\\" + else + let esc = 0 + endif + let s:parser_pos += 1 + if s:parser_pos >= len(s:input) + return [resulting_string, "TK_STRING"] + endif + endwhile + endif + + let s:parser_pos += 1 + + let resulting_string .= sep + + if sep == "/" + + while s:parser_pos < len(s:input) && s:in_array(s:input[s:parser_pos], s:wordchar) + let resulting_string .= s:input[s:parser_pos] + let s:parser_pos += 1 + endwhile + endif + return [resulting_string, "TK_STRING"] + endif + + if c == "#" + let sharp = "#" + if s:parser_pos < len(s:input) && s:in_array(s:input[s:parser_pos], s:digits) + let c = s:input[s:parser_pos] + let sharp .= c + let s:parser_pos += 1 + + while s:parser_pos < len(s:input) && c != "#" && c !="=" + let c = s:input[s:parser_pos] + let sharp .= c + let s:parser_pos += 1 + endwhile + + if c == "#" + return [sharp, "TK_WORD"] + else + return [sharp, "TK_OPERATOR"] + endif + endif + endif + + if c == "<" && s:input[s:parser_pos-1 : s:parser_pos+3] == "<!--" + let s:parser_pos += 3 + return ["<!--", "TK_COMMENT"] + endif + + if c == "-" && s:input[s:parser_pos-1 : s:parser_pos+2] == "-->" + let s:parser_pos += 2 + if wanted_newline + call s:print_newline(1) + endif + return ["-->", "TK_COMMENT"] + endif + + if s:in_array(c, s:punct) + while s:parser_pos < len(s:input) && s:in_array(c . s:input[s:parser_pos], s:punct) + let c .= s:input[s:parser_pos] + let s:parser_pos += 1 + if s:parser_pos >= len(s:input) + break + endif + endwhile + + return [c, "TK_OPERATOR"] + endif + + return [c, "TK_UNKNOWN"] + endif + + + +endfunction + +function! s:is_js() + return expand("%:e") == "js" +endfunction + +"function! g:Jsbeautify(js_source_text, options) +function! g:Jsbeautify() + if !s:is_js() + echo "Not a JS file." + return + endif + + "let a:options = {} + let s:opt_indent_size = 1 + let s:opt_indent_char = "\t" + let s:opt_preserve_newlines = 1 + let s:opt_indent_level = 0 + + let s:if_line_flag = 0 + "-------------------------------- + + let s:indent_string = "" + while s:opt_indent_size > 0 + let s:indent_string .= s:opt_indent_char + let s:opt_indent_size -= 1 + endwhile + + let s:indent_level = s:opt_indent_level + + let lines = getline(1, "$") + let s:input = join(lines, "\n") + "let s:input = a:js_source_text + + let s:last_word = "" "last 'TK_WORD' passed + let s:last_type = "TK_START_EXPR" "last token type + let s:last_text = "" "last token text + let s:output = [] + + let s:do_block_just_closed = 0 + let s:var_line = 0 + let s:var_line_tainted = 0 + + let s:whitespace = ["\n", "\r", "\t", " "] + let s:wordchar = split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$", '\zs') + let s:digits = split("0123456789", '\zs') + + "<!-- is a special case (ok, it"s a minor hack actually) + let s:punct = split("+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::", " ") + + let s:line_starters = split("continue,try,throw,return,var,if,switch,case,default,for,while,break", ",") + + let s:current_mode = "BLOCK" + let s:modes = [s:current_mode] + + let s:parser_pos = 0 + let s:in_case = 0 + while 1 + let t = s:get_next_token() + let s:token_text = t[0] + let s:token_type = t[1] + if s:token_type == "TK_EOF" + break + endif + + try + if s:token_type == "TK_START_EXPR" + let s:var_line = 0 + call s:set_mode("EXPRESSION") + if s:last_text == ";" + call s:print_newline(1) + elseif s:last_type == "TK_END_EXPR" || s:last_type == "TK_START_EXPR" + " do nothing on (( and )( and ][ and ]( .. + elseif s:last_type != "TK_WORD" && s:last_type != "TK_OPERATOR" + call s:print_space() + elseif s:in_array(s:last_word, s:line_starters) + call s:print_space() + endif + + call s:print_token() + + elseif s:token_type == "TK_END_EXPR" + call s:print_token() + call s:restore_mode() + elseif s:token_type == "TK_START_BLOCK" + + if s:last_word == "do" + call s:set_mode("DO_BLOCK") + else + call s:set_mode("BLOCK") + endif + if s:last_type != "TK_OPERATOR" && s:last_type != "TK_START_EXPR" + if s:last_type == "TK_START_BLOCK" + call s:print_newline(1) + else + call s:print_space() + endif + endif + call s:print_token() + call s:indent() + elseif s:token_type == "TK_END_BLOCK" + if s:last_type == "TK_START_BLOCK" + call s:remove_indent() + call s:unindent() + else + call s:unindent() + call s:print_newline(1) + endif + call s:print_token() + call s:restore_mode() + + elseif s:token_type == "TK_WORD" + if s:do_block_just_closed + " do {} ## while () + call s:print_space() + call s:print_token() + call s:print_space() + let s:do_block_just_closed = 0 + throw "jump out" + endif + if s:token_text == "case" || s:token_text == "default" + if s:last_text == ":" + "switch cases following one another + call s:remove_indent() + else + " case statement starts in the same line where switch + call s:unindent() + call s:print_newline(1) + call s:indent() + endif + call s:print_token() + let s:in_case = 1 + throw "jump out" + endif + + let s:prefix = "NONE" + + if s:last_type == "TK_END_BLOCK" + if !s:in_array(tolower(s:token_text), ["else", "catch", "finally"]) + let s:prefix = "NEWLINE" + else + let s:prefix = "SPACE" + call s:print_space() + endif + elseif s:last_type == "TK_SEMICOLON" && (s:current_mode == "BLOCK" || s:current_mode == "DO_BLOCK") + let s:prefix = "NEWLINE" + elseif s:last_type == "TK_SEMICOLON" && s:current_mode == "EXPRESSION" + let s:prefix = "SPACE" + elseif s:last_type == "TK_STRING" + let s:prefix = "NEWLINE" + elseif s:last_type == "TK_WORD" + let s:prefix = "SPACE" + elseif s:last_type == "TK_START_BLOCK" + let s:prefix = "NEWLINE" + elseif s:last_type == "TK_END_EXPR" + call s:print_space() + let s:prefix = "NEWLINE" + endif + + if s:last_type != "TK_END_BLOCK" && s:in_array(tolower(s:token_text), ["else", "catch", "finally"]) + call s:print_newline(1) + elseif s:in_array(s:token_text, s:line_starters) || s:prefix == "NEWLINE" + if s:last_text == "else" + call s:print_space() + elseif (s:last_type == "TK_START_EXPR" || s:last_text == "=" || s:last_text == ",") && s:token_text == "function" + " no need to force newline on "function": + " DONOTHINT + elseif s:last_type == "TK_WORD" && (s:last_text == "return" || s:last_text == "throw") + " no newline between "return nnn" + call s:print_space() + elseif s:last_type != "TK_END_EXPR" + if (s:last_type != "TK_START_EXPR" || s:token_text != "var") && s:last_text != ":" + " no need to force newline on "var": for (var + " x = 0...) + if s:token_text == "if" && s:last_type == "TK_WORD" && s:last_word == "else" + " no newline for } else if { + call s:print_space() + else + call s:print_newline(1) + endif + endif + else + if s:in_array(s:token_text, s:line_starters) && s:last_text != ")" + call s:print_newline(1) + endif + endif + elseif s:prefix == "SPACE" + call s:print_space() + endif + call s:print_token() + let s:last_word = s:token_text + + if s:token_text == "var" + let s:var_line = 1 + let s:var_line_tainted = 0 + endif + + if s:token_text == "if" || s:token_text == "else" + let s:if_line_flag = 1 + endif + + elseif s:token_type == "TK_SEMICOLON" + call s:print_token() + let s:var_line = 0 + + elseif s:token_type == "TK_STRING" + if s:last_type == "TK_START_BLOCK" || s:last_type == "TK_END_BLOCK" || s:last_type == "TK_SEMICOLON" + call s:print_newline(1) + elseif s:last_type == "TK_WORD" + call s:print_space() + endif + call s:print_token() + + elseif s:token_type == "TK_OPERATOR" + + let start_delim = 1 + let end_delim = 1 + if s:var_line && s:token_text != "," + let s:var_line_tainted = 1 + if s:token_text == ":" + let s:var_line = 0 + endif + endif + if s:var_line && s:token_text=="," && s:current_mode == "EXPRESSION" + " do not break on comma, for(var a = 1, b = 2) + let s:var_line_tainted = 0 + endif + + if s:token_text == ":" && s:in_case + call s:print_token() + call s:print_newline(1) + throw "jump out" + endif + + if s:token_text == "::" + " no spaces around exotic namespacing syntax operator + call s:print_token() + throw "jump out" + endif + + let s:in_case = 0 + + if s:token_text == "," + if s:var_line + if s:var_line_tainted + call s:print_token() + call s:print_newline(1) + let s:var_line_tainted = 0 + else + call s:print_token() + call s:print_space() + endif + elseif s:last_type == "TK_END_BLOCK" + call s:print_token() + call s:print_newline(1) + else + if s:current_mode == "BLOCK" + call s:print_token() + call s:print_newline(1) + else + " EXPR od DO_BLOCK + call s:print_token() + call s:print_space() + endif + endif + throw "jump out" + elseif s:token_text == "--" || s:token_text == "++" " unary operators special case + if s:last_text == ";" + " space for (;; ++i) + let start_delim = 1 + let end_delim = 0 + else + let start_delim = 0 + let end_delim = 0 + endif + elseif s:token_text == "!" && s:last_type == "TK_START_EXPR" + " special case handling: if (!a) + let start_delim = 0 + let end_delim = 0 + elseif s:last_type == "TK_OPERATOR" + let s:start_delim = 0 + let s:end_delim = 0 + elseif s:last_type == "TK_END_EXPR" + let s:start_delim = 1 + let s:end_delim = 1 + elseif s:token_text == "." + " decimal digits or object.property + let start_delim = 0 + let end_delim = 0 + elseif s:token_text == ":" + " zz: xx + " can"t differentiate ternary op, so for now it"s a ? b: + " c;without space before colon + if s:last_text =~ '/^\d+$/' + " a little help for ternary a ? 1 : 0 + let start_delim = 1 + else + let start_delim = 0 + endif + endif + if start_delim + call s:print_space() + endif + + call s:print_token() + + if end_delim + call s:print_space() + endif + throw "jump out" + + elseif s:token_type == "TK_BLOCK_COMMENT" + call s:print_newline(1) + call s:print_token() + call s:print_newline(1) + + elseif s:token_type == "TK_COMMENT" + + "call s:print_newline(1) + call s:print_space() + call s:print_token() + call s:print_newline(1) + + elseif s:token_type == "TK_UNKNOWN" + call s:print_token() + throw "jump out" + endif + catch /.*/ + if v:exception != 'jump out' + echo "exception caught: " v:exception + endif + endtry + + let s:last_type = s:token_type + let s:last_text = s:token_text + endwhile + + let ret = join(s:output, "") + :g/.*/d + let @0 = ret + :put!0 +endfunction + +nnoremap <silent> <leader>ff :call g:Jsbeautify()<cr> diff --git a/plugin/mark.vim b/plugin/mark.vim new file mode 100644 index 0000000..4f7fa9b --- /dev/null +++ b/plugin/mark.vim @@ -0,0 +1,209 @@ +" Script Name: mark.vim +" Description: Highlight several words in different colors simultaneously. +" +" Copyright: (C) 2005-2008 by Yuheng Xie +" (C) 2008-2009 by Ingo Karkat +" The VIM LICENSE applies to this script; see ':help copyright'. +" +" Maintainer: Ingo Karkat <ingo@karkat.de> +" Orig Author: Yuheng Xie <elephant@linux.net.cn> +" Contributors:Luc Hermitte, Ingo Karkat +" +" Dependencies: +" - Requires Vim 7.1 with "matchadd()", or Vim 7.2 or higher. +" - mark.vim autoload script. +" +" Version: 2.3.2 +" Changes: +" 17-Nov-2009, Ingo Karkat +" - Replaced the (overly) generic mark#GetVisualSelectionEscaped() with +" mark#GetVisualSelectionAsRegexp() and +" mark#GetVisualSelectionAsLiteralPattern(). +" +" 04-Jul-2009, Ingo Karkat +" - A [count] before any mapping either caused "No range allowed" error or just +" repeated the :call [count] times, resulting in the current search pattern +" echoed [count] times and a hit-enter prompt. Now suppressing [count] via +" <C-u> and handling it inside the implementation. +" - Now passing isBackward (0/1) instead of optional 'b' flag into functions. +" Also passing empty regexp to mark#MarkRegex() to avoid any optional +" arguments. +" +" 02-Jul-2009, Ingo Karkat +" - Split off functions into autoload script. +" - Removed g:force_reload_mark. +" - Initialization of global variables and autocommands is now done lazily on +" the first use, not during loading of the plugin. This reduces Vim startup +" time and footprint as long as the functionality isn't yet used. +" +" 6-Jun-2009, Ingo Karkat +" 1. Somehow s:WrapMessage() needs a redraw before the :echo to avoid that a +" later Vim redraw clears the wrap message. This happened when there's no +" statusline and thus :echo'ing into the ruler. +" 2. Removed line-continuations and ':set cpo=...'. Upper-cased <SID> and <CR>. +" 3. Added default highlighting for the special search type. +" +" 2-Jun-2009, Ingo Karkat +" 1. Replaced highlighting via :syntax with matchadd() / matchdelete(). This +" requires Vim 7.2 / 7.1 with patches. This method is faster, there are no +" more clashes with syntax highlighting (:match always has preference), and +" the background highlighting does not disappear under 'cursorline'. +" 2. Factored :windo application out into s:MarkScope(). +" 3. Using winrestcmd() to fix effects of :windo: By entering a window, its +" height is potentially increased from 0 to 1. +" 4. Handling multiple tabs by calling s:UpdateScope() on the TabEnter event. +" +" 1-Jun-2009, Ingo Karkat +" 1. Now using Vim List for g:mwWord and thus requiring Vim 7. g:mwCycle is now +" zero-based, but the syntax groups "MarkWordx" are still one-based. +" 2. Added missing setter for re-inclusion guard. +" 3. Factored :syntax operations out of s:DoMark() and s:UpdateMark() so that +" they can all be done in a single :windo. +" 4. Normal mode <Plug>MarkSet now has the same semantics as its visual mode +" cousin: If the cursor is on an existing mark, the mark is removed. +" Beforehand, one could only remove a visually selected mark via again +" selecting it. Now, one simply can invoke the mapping when on such a mark. +" 5. Highlighting can now actually be overridden in the vimrc (anywhere +" _before_ sourcing this script) by using ':hi def'. +" +" 31-May-2009, Ingo Karkat +" 1. Refactored s:Search() to optionally take advantage of SearchSpecial.vim +" autoload functionality for echoing of search pattern, wrap and error +" messages. +" 2. Now prepending search type ("any-mark", "same-mark", "new-mark") for +" better identification. +" 3. Retired the algorithm in s:PrevWord in favor of simply using <cword>, +" which makes mark.vim work like the * command. At the end of a line, +" non-keyword characters may now be marked; the previous algorithm prefered +" any preceding word. +" 4. BF: If 'iskeyword' contains characters that have a special meaning in a +" regex (e.g. [.*]), these are now escaped properly. +" +" 01-Sep-2008, Ingo Karkat: bugfixes and enhancements +" 1. Added <Plug>MarkAllClear (without a default mapping), which clears all +" marks, even when the cursor is on a mark. +" 2. Added <Plug>... mappings for hard-coded \*, \#, \/, \?, * and #, to allow +" re-mapping and disabling. Beforehand, there were some <Plug>... mappings +" and hard-coded ones; now, everything can be customized. +" 3. Bugfix: Using :autocmd without <bang> to avoid removing _all_ autocmds for +" the BufWinEnter event. (Using a custom :augroup would be even better.) +" 4. Bugfix: Explicitly defining s:current_mark_position; some execution paths +" left it undefined, causing errors. +" 5. Refactoring: Instead of calling s:InitMarkVariables() at the beginning of +" several functions, just calling it once when sourcing the script. +" 6. Refactoring: Moved multiple 'let lastwinnr = winnr()' to a single one at the +" top of DoMark(). +" 7. ENH: Make the match according to the 'ignorecase' setting, like the star +" command. +" 8. The jumps to the next/prev occurrence now print 'search hit BOTTOM, +" continuing at TOP" and "Pattern not found:..." messages, like the * and +" n/N Vim search commands. +" 9. Jumps now open folds if the occurrence is inside a closed fold, just like n/N +" do. +" +" 10th Mar 2006, Yuheng Xie: jump to ANY mark +" (*) added \* \# \/ \? for the ability of jumping to ANY mark, even when the +" cursor is not currently over any mark +" +" 20th Sep 2005, Yuheng Xie: minor modifications +" (*) merged MarkRegexVisual into MarkRegex +" (*) added GetVisualSelectionEscaped for multi-lines visual selection and +" visual selection contains ^, $, etc. +" (*) changed the name ThisMark to CurrentMark +" (*) added SearchCurrentMark and re-used raw map (instead of Vim function) to +" implement * and # +" +" 14th Sep 2005, Luc Hermitte: modifications done on v1.1.4 +" (*) anti-reinclusion guards. They do not guard colors definitions in case +" this script must be reloaded after .gvimrc +" (*) Protection against disabled |line-continuation|s. +" (*) Script-local functions +" (*) Default keybindings +" (*) \r for visual mode +" (*) uses <Leader> instead of "\" +" (*) do not mess with global variable g:w +" (*) regex simplified -> double quotes changed into simple quotes. +" (*) strpart(str, idx, 1) -> str[idx] +" (*) command :Mark +" -> e.g. :Mark Mark.\{-}\ze( + +" Avoid installing twice or when in unsupported Vim version. +if exists('g:loaded_mark') || (v:version == 701 && ! exists('*matchadd')) || (v:version < 702) + finish +endif +let g:loaded_mark = 1 + +"- default highlightings ------------------------------------------------------ +" You may define your own colors in your vimrc file, in the form as below: +highlight def MarkWord1 ctermbg=Cyan ctermfg=Black guibg=#8CCBEA guifg=Black +highlight def MarkWord2 ctermbg=Green ctermfg=Black guibg=#A4E57E guifg=Black +highlight def MarkWord3 ctermbg=Yellow ctermfg=Black guibg=#FFDB72 guifg=Black +highlight def MarkWord4 ctermbg=Red ctermfg=Black guibg=#FF7272 guifg=Black +highlight def MarkWord5 ctermbg=Magenta ctermfg=Black guibg=#FFB3FF guifg=Black +highlight def MarkWord6 ctermbg=Blue ctermfg=Black guibg=#9999FF guifg=Black + +" Default highlighting for the special search type. +" You can override this by defining / linking the 'SearchSpecialSearchType' +" highlight group before this script is sourced. +highlight def link SearchSpecialSearchType MoreMsg + + +"- mappings ------------------------------------------------------------------- +nnoremap <silent> <Plug>MarkSet :<C-u>call mark#MarkCurrentWord()<CR> +vnoremap <silent> <Plug>MarkSet <C-\><C-n>:call mark#DoMark(mark#GetVisualSelectionAsLiteralPattern())<CR> +nnoremap <silent> <Plug>MarkRegex :<C-u>call mark#MarkRegex('')<CR> +vnoremap <silent> <Plug>MarkRegex <C-\><C-n>:call mark#MarkRegex(mark#GetVisualSelectionAsRegexp())<CR> +nnoremap <silent> <Plug>MarkClear :<C-u>call mark#DoMark(mark#CurrentMark()[0])<CR> +nnoremap <silent> <Plug>MarkAllClear :<C-u>call mark#DoMark()<CR> + +nnoremap <silent> <Plug>MarkSearchCurrentNext :<C-u>call mark#SearchCurrentMark(0)<CR> +nnoremap <silent> <Plug>MarkSearchCurrentPrev :<C-u>call mark#SearchCurrentMark(1)<CR> +nnoremap <silent> <Plug>MarkSearchAnyNext :<C-u>call mark#SearchAnyMark(0)<CR> +nnoremap <silent> <Plug>MarkSearchAnyPrev :<C-u>call mark#SearchAnyMark(1)<CR> +nnoremap <silent> <Plug>MarkSearchNext :<C-u>if !mark#SearchNext(0)<Bar>execute 'normal! *zv'<Bar>endif<CR> +nnoremap <silent> <Plug>MarkSearchPrev :<C-u>if !mark#SearchNext(1)<Bar>execute 'normal! #zv'<Bar>endif<CR> +" When typed, [*#nN] open the fold at the search result, but inside a mapping or +" :normal this must be done explicitly via 'zv'. + + +if !hasmapto('<Plug>MarkSet', 'n') + nmap <unique> <silent> <Leader>m <Plug>MarkSet +endif +if !hasmapto('<Plug>MarkSet', 'v') + vmap <unique> <silent> <Leader>m <Plug>MarkSet +endif +if !hasmapto('<Plug>MarkRegex', 'n') + nmap <unique> <silent> <Leader>r <Plug>MarkRegex +endif +if !hasmapto('<Plug>MarkRegex', 'v') + vmap <unique> <silent> <Leader>r <Plug>MarkRegex +endif +if !hasmapto('<Plug>MarkClear', 'n') + nmap <unique> <silent> <Leader>n <Plug>MarkClear +endif +" No default mapping for <Plug>MarkAllClear. + +if !hasmapto('<Plug>MarkSearchCurrentNext', 'n') + nmap <unique> <silent> <Leader>* <Plug>MarkSearchCurrentNext +endif +if !hasmapto('<Plug>MarkSearchCurrentPrev', 'n') + nmap <unique> <silent> <Leader># <Plug>MarkSearchCurrentPrev +endif +if !hasmapto('<Plug>MarkSearchAnyNext', 'n') + nmap <unique> <silent> <Leader>/ <Plug>MarkSearchAnyNext +endif +if !hasmapto('<Plug>MarkSearchAnyPrev', 'n') + nmap <unique> <silent> <Leader>? <Plug>MarkSearchAnyPrev +endif +if !hasmapto('<Plug>MarkSearchNext', 'n') + nmap <unique> <silent> * <Plug>MarkSearchNext +endif +if !hasmapto('<Plug>MarkSearchPrev', 'n') + nmap <unique> <silent> # <Plug>MarkSearchPrev +endif + + +"- commands ------------------------------------------------------------------- +command! -nargs=? Mark call mark#DoMark(<f-args>) + +" vim: ts=2 sw=2 diff --git a/plugin/occur.vim b/plugin/occur.vim new file mode 100644 index 0000000..33952c7 --- /dev/null +++ b/plugin/occur.vim @@ -0,0 +1,84 @@ +"============================================================================= +" File: occur.vim +" Author: FURUSAWA, Noriyoshi (noriyosi xxx gmail dot com) xxx=@,dot=. +" Last Change: 2008/7/13 +" Version: 0.03 +"============================================================================= + +if exists('loaded_occur') || &cp + finish +endif +let loaded_occur=1 + +if v:version < 700 + echo "Sorry, occur ONLY runs with Vim 7.0 and greater." + finish +endif + +if !exists("g:occur_no_quickfix_map") + let g:occur_no_quickfix_map = 0 +endif + +" Key bind +nnoremap <silent> <unique> <Leader>oc :Occur<CR> +nnoremap <silent> <unique> <Leader>om :Moccur<CR> +nnoremap <silent> <unique> <Leader>8 *<C-o>:Moccur<CR> + +" Create commands +command! Occur silent call s:SetupAndGo('s:Occur') +command! Moccur silent call s:SetupAndGo('s:Moccur') +command! StarOccur exec "normal! *<C-o>" <Bar> Moccur + +function! s:Occur() + let expr = 'caddexpr expand("%") . ":" . line(".") . ":" . getline(".")' + exec 'silent keepjumps g/' . @/ . '/' . expr +endfunction + +function! s:Moccur() + " Create the buffer list + redir => command_out + ls + redir END + + let buffers = [] + for line in split(command_out, '\n') + call add(buffers, split(line, ' ')[0]) + endfor + + " Search the pattern in all buffers + for buf_number in buffers + exec 'keepjumps buffer ' . buf_number + call s:Occur() + endfor +endfunction + +function! s:SetupAndGo(func) + let org_efm = &errorformat + let &errorformat = '%f:%l:%m' + + " Clear the results window + cexpr "================= occur result =================" + cclose + + " Log the current cursor position + normal! H + + " Do Occur + call function(a:func)() + + " Open the results window (and restore cursor position) + keepjumps cfirst 1 + exec "normal! \<C-o>" + copen + + " Map the key sequence on the QuickFix + if !g:occur_no_quickfix_map + nnoremap <buffer> <silent> <Space> <C-w><C-_> + nnoremap <buffer> <silent> x 10<C-w>_<CR>zxzz:copen<CR> + nnoremap <buffer> <silent> <CR> <CR>zxzz:cclose<CR> + nnoremap <buffer> <silent> q :cclose<CR> + endif + + let &errorformat = org_efm +endfunction + diff --git a/plugin/pysmell.vim b/plugin/pysmell.vim new file mode 100644 index 0000000..e8a079c --- /dev/null +++ b/plugin/pysmell.vim @@ -0,0 +1,102 @@ +" pysmell.vim +" Omnicompletions provider for Python, using PYSMELLTAGS files +" Copyright (C) 2008 Orestis Markou +" All rights reserved +" E-mail: orestis@orestis.gr + +" pysmell v0.7.2 +" http://orestis.gr + +" Released subject to the BSD License + +" Options: +" g:pysmell_debug : set to 1 and create a PYSMELL_DEBUG buffer. Info will get appended there. +" g:pysmell_matcher : one of the following, listed from stricter to fuzzier: +" 'case-sensitive' +" 'case-insensitive' "default +" 'camel-case' +" 'camel-case-sensitive' +" 'smartass' +" 'fuzzy-ci' +" 'fuzzy-cs' + + +if !has('python') + echo "Error: Required vim compiled with +python" + finish +endif + +if !exists('g:pysmell_debug') + let g:pysmell_debug = 0 +endif +if !exists('g:pysmell_matcher') + let g:pysmell_matcher='case-insensitive' +endif + +python << eopython +from pysmell import vimhelper, idehelper +import vim +import string +TRANSLATEQUOTES = string.maketrans("\'\"", "\"\'") +eopython + +function! pysmell#Complete(findstart, base) + "findstart = 1 when we need to get the text length + if a:findstart == 1 +python << eopython +row, col = vim.current.window.cursor +line = vim.current.buffer[row-1] +index = idehelper.findBase(line, col) +vim.command('let g:pysmell_origCol = %d' % col) +vim.command('let g:pysmell_origLine = %r' % line) +vim.command('return %d' % index) +eopython + "findstart = 0 when we need to return the list of completions + else + let g:pysmell_args = 0 + let g:pysmell_completions = [] +python << eopython +origCol = int(vim.eval('g:pysmell_origCol')) +origLine = vim.eval('g:pysmell_origLine') +origSourceLines = vim.current.buffer[:] +lineno = vim.current.window.cursor[0] +origSourceLines[lineno - 1] = origLine +origSource = '\n'.join(origSourceLines) +vimcompletePYSMELL(origSource, lineno, origCol, vim.eval("a:base")) + +eopython + return g:pysmell_completions + endif +endfunction + +python << eopython +def vimcompletePYSMELL(origSource, origLineNo, origCol, base): + fullPath = vim.current.buffer.name + PYSMELLDICT = idehelper.findPYSMELLDICT(fullPath) + if not PYSMELLDICT: + vim.command("echoerr 'No PYSMELLTAGS found. You have to generate one.'") + return + + try: + options = idehelper.detectCompletionType(fullPath, origSource, origLineNo, origCol, base, PYSMELLDICT) + except: + f = file('pysmell_exc.txt', 'wb') + import traceback + f.write(traceback.format_exc()) + f.close() + vim.command("echoerr 'Exception written out at pysmell_exc.txt'") + return + + if int(vim.eval('g:pysmell_debug')): + for b in vim.buffers: + if b.name.endswith('PYSMELL_DEBUG'): + b.append("%s %s %s %s" % (fullPath, origSource[origLineNo], origCol, base)) + b.append("%r" % options) + break + + completions = idehelper.findCompletions(base, PYSMELLDICT, options, vim.eval('g:pysmell_matcher')) + output = repr(completions) + translated = output.translate(TRANSLATEQUOTES) + vim.command('let g:pysmell_completions = %s' % (translated, )) + +eopython diff --git a/plugin/showmarks.vim b/plugin/showmarks.vim new file mode 100644 index 0000000..c6931c2 --- /dev/null +++ b/plugin/showmarks.vim @@ -0,0 +1,507 @@ +" ============================================================================== +" Name: ShowMarks +" Description: Visually displays the location of marks. +" Authors: Anthony Kruize <trandor@labyrinth.net.au> +" Michael Geddes <michaelrgeddes@optushome.com.au> +" Version: 2.2 +" Modified: 17 August 2004 +" License: Released into the public domain. +" ChangeLog: See :help showmarks-changelog +" +" Usage: Copy this file into the plugins directory so it will be +" automatically sourced. +" +" Default keymappings are: +" <Leader>mt - Toggles ShowMarks on and off. +" <Leader>mo - Turns ShowMarks on, and displays marks. +" <Leader>mh - Clears a mark. +" <Leader>ma - Clears all marks. +" <Leader>mm - Places the next available mark. +" +" Hiding a mark doesn't actually remove it, it simply moves it +" to line 1 and hides it visually. +" +" Configuration: *********************************************************** +" * PLEASE read the included help file(showmarks.txt) for a * +" * more thorough explanation of how to use ShowMarks. * +" *********************************************************** +" The following options can be used to customize the behavior +" of ShowMarks. Simply include them in your vimrc file with +" the desired settings. +" +" showmarks_enable (Default: 1) +" Defines whether ShowMarks is enabled by default. +" Example: let g:showmarks_enable=0 +" showmarks_include (Default: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.'`^<>[]{}()\"") +" Defines all marks, in precedence order (only the highest +" precence will show on lines having more than one mark). +" Can be buffer-specific (set b:showmarks_include) +" showmarks_ignore_type (Default: "hq") +" Defines the buffer types to be ignored. +" Valid types are: +" h - Help p - preview +" q - quickfix r - readonly +" m - non-modifiable +" showmarks_textlower (Default: ">") +" Defines how the mark is to be displayed. +" A maximum of two characters can be displayed. To include +" the mark in the text use a tab(\t) character. A single +" character will display as the mark with the character +" suffixed (same as "\t<character>") +" Examples: +" To display the mark with a > suffixed: +" let g:showmarks_textlower="\t>" +" or +" let g:showmarks_textlower=">" +" To display the mark with a ( prefixed: +" let g:showmarks_textlower="(\t" +" To display two > characters: +" let g:showmarks_textlower=">>" +" showmarks_textupper (Default: ">") +" Same as above but for the marks A-Z. +" Example: let g:showmarks_textupper="**" +" showmarks_textother (Default: ">") +" Same as above but for all other marks. +" Example: let g:showmarks_textother="--" +" showmarks_hlline_lower (Default: 0) +" showmarks_hlline_upper (Default: 0) +" showmarks_hlline_other (Default: 0) +" Defines whether the entire line for a particular mark +" should be highlighted. +" Example: let g:showmarks_hlline_lower=1 +" +" Setting Highlighting Colours +" ShowMarks uses the following highlighting groups: +" ShowMarksHLl - For marks a-z +" ShowMarksHLu - For marks A-Z +" ShowMarksHLo - For all other marks +" ShowMarksHLm - For multiple marks on the same line. +" (Highest precendece mark is shown) +" +" By default they are set to a bold blue on light blue. +" Defining a highlight for each of these groups will +" override the default highlighting. +" See the VIM help for more information about highlighting. +" ============================================================================== + +" Check if we should continue loading +if exists( "loaded_showmarks" ) + finish +endif +let loaded_showmarks = 1 + +" Bail if Vim isn't compiled with signs support. +if has( "signs" ) == 0 + echohl ErrorMsg + echo "ShowMarks requires Vim to have +signs support." + echohl None + finish +endif + +" Options: Set up some nice defaults +if !exists('g:showmarks_enable' ) | let g:showmarks_enable = 1 | endif +if !exists('g:showmarks_textlower' ) | let g:showmarks_textlower = ">" | endif +if !exists('g:showmarks_textupper' ) | let g:showmarks_textupper = ">" | endif +if !exists('g:showmarks_textother' ) | let g:showmarks_textother = ">" | endif +if !exists('g:showmarks_ignore_type' ) | let g:showmarks_ignore_type = "hq" | endif +if !exists('g:showmarks_ignore_name' ) | let g:showmarks_ignore_name = "" | endif +if !exists('g:showmarks_hlline_lower') | let g:showmarks_hlline_lower = "0" | endif +if !exists('g:showmarks_hlline_upper') | let g:showmarks_hlline_upper = "0" | endif +if !exists('g:showmarks_hlline_other') | let g:showmarks_hlline_other = "0" | endif + +" This is the default, and used in ShowMarksSetup to set up info for any +" possible mark (not just those specified in the possibly user-supplied list +" of marks to show -- it can be changed on-the-fly). +let s:all_marks = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.'`^<>[]{}()\"" + +" Commands +com! -nargs=0 ShowMarksToggle :call <sid>ShowMarksToggle() +com! -nargs=0 ShowMarksOn :call <sid>ShowMarksOn() +com! -nargs=0 ShowMarksClearMark :call <sid>ShowMarksClearMark() +com! -nargs=0 ShowMarksClearAll :call <sid>ShowMarksClearAll() +com! -nargs=0 ShowMarksPlaceMark :call <sid>ShowMarksPlaceMark() + +" Mappings (NOTE: Leave the '|'s immediately following the '<cr>' so the mapping does not contain any trailing spaces!) +if !hasmapto( '<Plug>ShowmarksShowMarksToggle' ) | map <silent> <unique> <leader>mt :ShowMarksToggle<cr>| endif +if !hasmapto( '<Plug>ShowmarksShowMarksOn' ) | map <silent> <unique> <leader>mo :ShowMarksOn<cr>| endif +if !hasmapto( '<Plug>ShowmarksClearMark' ) | map <silent> <unique> <leader>mh :ShowMarksClearMark<cr>| endif +if !hasmapto( '<Plug>ShowmarksClearAll' ) | map <silent> <unique> <leader>ma :ShowMarksClearAll<cr>| endif +if !hasmapto( '<Plug>ShowmarksPlaceMark' ) | map <silent> <unique> <leader>mm :ShowMarksPlaceMark<cr>| endif +noremap <unique> <script> \sm m +noremap <silent> m :exe 'norm \sm'.nr2char(getchar())<bar>call <sid>ShowMarks()<CR> + +" AutoCommands: Only if ShowMarks is enabled +if g:showmarks_enable == 1 + aug ShowMarks + au! + autocmd CursorHold * call s:ShowMarks() + aug END +endif + +" Highlighting: Setup some nice colours to show the mark positions. +hi default ShowMarksHLl ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold +hi default ShowMarksHLu ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold +hi default ShowMarksHLo ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold +hi default ShowMarksHLm ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold + +" Function: IncludeMarks() +" Description: This function returns the list of marks (in priority order) to +" show in this buffer. Each buffer, if not already set, inherits the global +" setting; if the global include marks have not been set; that is set to the +" default value. +fun! s:IncludeMarks() + if exists('b:showmarks_include') && exists('b:showmarks_previous_include') && b:showmarks_include != b:showmarks_previous_include + " The user changed the marks to include; hide all marks; change the + " included mark list, then show all marks. Prevent infinite + " recursion during this switch. + if exists('s:use_previous_include') + " Recursive call from ShowMarksHideAll() + return b:showmarks_previous_include + elseif exists('s:use_new_include') + " Recursive call from ShowMarks() + return b:showmarks_include + else + let s:use_previous_include = 1 + call <sid>ShowMarksHideAll() + unlet s:use_previous_include + let s:use_new_include = 1 + call <sid>ShowMarks() + unlet s:use_new_include + endif + endif + + if !exists('g:showmarks_include') + let g:showmarks_include = s:all_marks + endif + if !exists('b:showmarks_include') + let b:showmarks_include = g:showmarks_include + endif + + " Save this include setting so we can detect if it was changed. + let b:showmarks_previous_include = b:showmarks_include + + return b:showmarks_include +endf + +" Function: NameOfMark() +" Paramaters: mark - Specifies the mark to find the name of. +" Description: Convert marks that cannot be used as part of a variable name to +" something that can be. i.e. We cannot use [ as a variable-name suffix (as +" in 'placed_['; this function will return something like 63, so the variable +" will be something like 'placed_63'). +" 10 is added to the mark's index to avoid colliding with the numeric marks +" 0-9 (since a non-word mark could be listed in showmarks_include in the +" first 10 characters if the user overrides the default). +" Returns: The name of the requested mark. +fun! s:NameOfMark(mark) + let name = a:mark + if a:mark =~# '\W' + let name = stridx(s:all_marks, a:mark) + 10 + endif + return name +endf + +" Function: VerifyText() +" Paramaters: which - Specifies the variable to verify. +" Description: Verify the validity of a showmarks_text{upper,lower,other} setup variable. +" Default to ">" if it is found to be invalid. +fun! s:VerifyText(which) + if strlen(g:showmarks_text{a:which}) == 0 || strlen(g:showmarks_text{a:which}) > 2 + echohl ErrorMsg + echo "ShowMarks: text".a:which." must contain only 1 or 2 characters." + echohl None + let g:showmarks_text{a:which}=">" + endif +endf + +" Function: ShowMarksSetup() +" Description: This function sets up the sign definitions for each mark. +" It uses the showmarks_textlower, showmarks_textupper and showmarks_textother +" variables to determine how to draw the mark. +fun! s:ShowMarksSetup() + " Make sure the textlower, textupper, and textother options are valid. + call s:VerifyText('lower') + call s:VerifyText('upper') + call s:VerifyText('other') + + let n = 0 + let s:maxmarks = strlen(s:all_marks) + while n < s:maxmarks + let c = strpart(s:all_marks, n, 1) + let nm = s:NameOfMark(c) + let text = '>'.c + let lhltext = '' + if c =~# '[a-z]' + if strlen(g:showmarks_textlower) == 1 + let text=c.g:showmarks_textlower + elseif strlen(g:showmarks_textlower) == 2 + let t1 = strpart(g:showmarks_textlower,0,1) + let t2 = strpart(g:showmarks_textlower,1,1) + if t1 == "\t" + let text=c.t2 + elseif t2 == "\t" + let text=t1.c + else + let text=g:showmarks_textlower + endif + endif + let s:ShowMarksDLink{nm} = 'ShowMarksHLl' + if g:showmarks_hlline_lower == 1 + let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm + endif + elseif c =~# '[A-Z]' + if strlen(g:showmarks_textupper) == 1 + let text=c.g:showmarks_textupper + elseif strlen(g:showmarks_textupper) == 2 + let t1 = strpart(g:showmarks_textupper,0,1) + let t2 = strpart(g:showmarks_textupper,1,1) + if t1 == "\t" + let text=c.t2 + elseif t2 == "\t" + let text=t1.c + else + let text=g:showmarks_textupper + endif + endif + let s:ShowMarksDLink{nm} = 'ShowMarksHLu' + if g:showmarks_hlline_upper == 1 + let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm + endif + else " Other signs, like ', ., etc. + if strlen(g:showmarks_textother) == 1 + let text=c.g:showmarks_textother + elseif strlen(g:showmarks_textother) == 2 + let t1 = strpart(g:showmarks_textother,0,1) + let t2 = strpart(g:showmarks_textother,1,1) + if t1 == "\t" + let text=c.t2 + elseif t2 == "\t" + let text=t1.c + else + let text=g:showmarks_textother + endif + endif + let s:ShowMarksDLink{nm} = 'ShowMarksHLo' + if g:showmarks_hlline_other == 1 + let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm + endif + endif + + " Define the sign with a unique highlight which will be linked when placed. + exe 'sign define ShowMark'.nm.' '.lhltext.' text='.text.' texthl='.s:ShowMarksDLink{nm}.nm + let b:ShowMarksLink{nm} = '' + let n = n + 1 + endw +endf + +" Set things up +call s:ShowMarksSetup() + +" Function: ShowMarksOn +" Description: Enable showmarks, and show them now. +fun! s:ShowMarksOn() + if g:showmarks_enable == 0 + call <sid>ShowMarksToggle() + else + call <sid>ShowMarks() + endif +endf + +" Function: ShowMarksToggle() +" Description: This function toggles whether marks are displayed or not. +fun! s:ShowMarksToggle() + if g:showmarks_enable == 0 + let g:showmarks_enable = 1 + call <sid>ShowMarks() + aug ShowMarks + au! + autocmd CursorHold * call s:ShowMarks() + aug END + else + let g:showmarks_enable = 0 + call <sid>ShowMarksHideAll() + aug ShowMarks + au! + autocmd BufEnter * call s:ShowMarksHideAll() + aug END + endif +endf + +" Function: ShowMarks() +" Description: This function runs through all the marks and displays or +" removes signs as appropriate. It is called on the CursorHold autocommand. +" We use the marked_{ln} variables (containing a timestamp) to track what marks +" we've shown (placed) in this call to ShowMarks; to only actually place the +" first mark on any particular line -- this forces only the first mark +" (according to the order of showmarks_include) to be shown (i.e., letters +" take precedence over marks like paragraph and sentence.) +fun! s:ShowMarks() + if g:showmarks_enable == 0 + return + endif + + if ((match(g:showmarks_ignore_type, "[Hh]") > -1) && (&buftype == "help" )) + \ || ((match(g:showmarks_ignore_type, "[Qq]") > -1) && (&buftype == "quickfix")) + \ || ((match(g:showmarks_ignore_type, "[Pp]") > -1) && (&pvw == 1 )) + \ || ((match(g:showmarks_ignore_type, "[Rr]") > -1) && (&readonly == 1 )) + \ || ((match(g:showmarks_ignore_type, "[Mm]") > -1) && (&modifiable == 0 )) + return + endif + + let n = 0 + let s:maxmarks = strlen(s:IncludeMarks()) + while n < s:maxmarks + let c = strpart(s:IncludeMarks(), n, 1) + let nm = s:NameOfMark(c) + let id = n + (s:maxmarks * winbufnr(0)) + let ln = line("'".c) + + if ln == 0 && (exists('b:placed_'.nm) && b:placed_{nm} != ln) + exe 'sign unplace '.id.' buffer='.winbufnr(0) + elseif ln > 1 || c !~ '[a-zA-Z]' + " Have we already placed a mark here in this call to ShowMarks? + if exists('mark_at'.ln) + " Already placed a mark, set the highlight to multiple + if c =~# '[a-zA-Z]' && b:ShowMarksLink{mark_at{ln}} != 'ShowMarksHLm' + let b:ShowMarksLink{mark_at{ln}} = 'ShowMarksHLm' + exe 'hi link '.s:ShowMarksDLink{mark_at{ln}}.mark_at{ln}.' '.b:ShowMarksLink{mark_at{ln}} + endif + else + if !exists('b:ShowMarksLink'.nm) || b:ShowMarksLink{nm} != s:ShowMarksDLink{nm} + let b:ShowMarksLink{nm} = s:ShowMarksDLink{nm} + exe 'hi link '.s:ShowMarksDLink{nm}.nm.' '.b:ShowMarksLink{nm} + endif + let mark_at{ln} = nm + if !exists('b:placed_'.nm) || b:placed_{nm} != ln + exe 'sign unplace '.id.' buffer='.winbufnr(0) + exe 'sign place '.id.' name=ShowMark'.nm.' line='.ln.' buffer='.winbufnr(0) + let b:placed_{nm} = ln + endif + endif + endif + let n = n + 1 + endw +endf + +" Function: ShowMarksClearMark() +" Description: This function hides the mark at the current line. +" It simply moves the mark to line 1 and removes the sign. +" Only marks a-z and A-Z are supported. +fun! s:ShowMarksClearMark() + let ln = line(".") + let n = 0 + let s:maxmarks = strlen(s:IncludeMarks()) + while n < s:maxmarks + let c = strpart(s:IncludeMarks(), n, 1) + if c =~# '[a-zA-Z]' && ln == line("'".c) + let nm = s:NameOfMark(c) + let id = n + (s:maxmarks * winbufnr(0)) + exe 'sign unplace '.id.' buffer='.winbufnr(0) + exe '1 mark '.c + let b:placed_{nm} = 1 + endif + let n = n + 1 + endw +endf + +" Function: ShowMarksClearAll() +" Description: This function clears all marks in the buffer. +" It simply moves the marks to line 1 and removes the signs. +" Only marks a-z and A-Z are supported. +fun! s:ShowMarksClearAll() + let n = 0 + let s:maxmarks = strlen(s:IncludeMarks()) + while n < s:maxmarks + let c = strpart(s:IncludeMarks(), n, 1) + if c =~# '[a-zA-Z]' + let nm = s:NameOfMark(c) + let id = n + (s:maxmarks * winbufnr(0)) + exe 'sign unplace '.id.' buffer='.winbufnr(0) + exe '1 mark '.c + let b:placed_{nm} = 1 + endif + let n = n + 1 + endw +endf + +" Function: ShowMarksHideAll() +" Description: This function hides all marks in the buffer. +" It simply removes the signs. +fun! s:ShowMarksHideAll() + let n = 0 + let s:maxmarks = strlen(s:IncludeMarks()) + while n < s:maxmarks + let c = strpart(s:IncludeMarks(), n, 1) + let nm = s:NameOfMark(c) + if exists('b:placed_'.nm) + let id = n + (s:maxmarks * winbufnr(0)) + exe 'sign unplace '.id.' buffer='.winbufnr(0) + unlet b:placed_{nm} + endif + let n = n + 1 + endw +endf + +" Function: ShowMarksPlaceMark() +" Description: This function will place the next unplaced mark (in priority +" order) to the current location. The idea here is to automate the placement +" of marks so the user doesn't have to remember which marks are placed or not. +" Hidden marks are considered to be unplaced. +" Only marks a-z are supported. +fun! s:ShowMarksPlaceMark() + " Find the first, next, and last [a-z] mark in showmarks_include (i.e. + " priority order), so we know where to "wrap". + let first_alpha_mark = -1 + let last_alpha_mark = -1 + let next_mark = -1 + + if !exists('b:previous_auto_mark') + let b:previous_auto_mark = -1 + endif + + " Find the next unused [a-z] mark (in priority order); if they're all + " used, find the next one after the previously auto-assigned mark. + let n = 0 + let s:maxmarks = strlen(s:IncludeMarks()) + while n < s:maxmarks + let c = strpart(s:IncludeMarks(), n, 1) + if c =~# '[a-z]' + if line("'".c) <= 1 + " Found an unused [a-z] mark; we're done. + let next_mark = n + break + endif + + if first_alpha_mark < 0 + let first_alpha_mark = n + endif + let last_alpha_mark = n + if n > b:previous_auto_mark && next_mark == -1 + let next_mark = n + endif + endif + let n = n + 1 + endw + + if next_mark == -1 && (b:previous_auto_mark == -1 || b:previous_auto_mark == last_alpha_mark) + " Didn't find an unused mark, and haven't placed any auto-chosen marks yet, + " or the previously placed auto-chosen mark was the last alpha mark -- + " use the first alpha mark this time. + let next_mark = first_alpha_mark + endif + + if (next_mark == -1) + echohl WarningMsg + echo 'No marks in [a-z] included! (No "next mark" to choose from)' + echohl None + return + endif + + let c = strpart(s:IncludeMarks(), next_mark, 1) + let b:previous_auto_mark = next_mark + exe 'mark '.c + call <sid>ShowMarks() +endf + +" ----------------------------------------------------------------------------- +" vim:ts=4:sw=4:noet diff --git a/plugin/snipMate.vim b/plugin/snipMate.vim new file mode 100644 index 0000000..3efee2a --- /dev/null +++ b/plugin/snipMate.vim @@ -0,0 +1,247 @@ +" File: snipMate.vim +" Author: Michael Sanders +" Last Updated: July 13, 2009 +" Version: 0.83 +" Description: snipMate.vim implements some of TextMate's snippets features in +" Vim. A snippet is a piece of often-typed text that you can +" insert into your document using a trigger word followed by a "<tab>". +" +" For more help see snipMate.txt; you can do this by using: +" :helptags ~/.vim/doc +" :h snipMate.txt + +if exists('loaded_snips') || &cp || version < 700 + finish +endif +let loaded_snips = 1 +if !exists('snips_author') | let snips_author = 'Me' | endif + +au BufRead,BufNewFile *.snippets\= set ft=snippet +au FileType snippet setl noet fdm=indent + +let s:snippets = {} | let s:multi_snips = {} + +if !exists('snippets_dir') + let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g') +endif + +fun! MakeSnip(scope, trigger, content, ...) + let multisnip = a:0 && a:1 != '' + let var = multisnip ? 's:multi_snips' : 's:snippets' + if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif + if !has_key({var}[a:scope], a:trigger) + let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content + elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]] + else + echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.' + \ .' See :h multi_snip for help on snippets with multiple matches.' + endif +endf + +fun! ExtractSnips(dir, ft) + for path in split(globpath(a:dir, '*'), "\n") + if isdirectory(path) + let pathname = fnamemodify(path, ':t') + for snipFile in split(globpath(path, '*.snippet'), "\n") + call s:ProcessFile(snipFile, a:ft, pathname) + endfor + elseif fnamemodify(path, ':e') == 'snippet' + call s:ProcessFile(path, a:ft) + endif + endfor +endf + +" Processes a single-snippet file; optionally add the name of the parent +" directory for a snippet with multiple matches. +fun s:ProcessFile(file, ft, ...) + let keyword = fnamemodify(a:file, ':t:r') + if keyword == '' | return | endif + try + let text = join(readfile(a:file), "\n") + catch /E484/ + echom "Error in snipMate.vim: couldn't read file: ".a:file + endtry + return a:0 ? MakeSnip(a:ft, a:1, text, keyword) + \ : MakeSnip(a:ft, keyword, text) +endf + +fun! ExtractSnipsFile(file, ft) + if !filereadable(a:file) | return | endif + let text = readfile(a:file) + let inSnip = 0 + for line in text + ["\n"] + if inSnip && (line[0] == "\t" || line == '') + let content .= strpart(line, 1)."\n" + continue + elseif inSnip + call MakeSnip(a:ft, trigger, content[:-2], name) + let inSnip = 0 + endif + + if line[:6] == 'snippet' + let inSnip = 1 + let trigger = strpart(line, 8) + let name = '' + let space = stridx(trigger, ' ') + 1 + if space " Process multi snip + let name = strpart(trigger, space) + let trigger = strpart(trigger, 0, space - 1) + endif + let content = '' + endif + endfor +endf + +fun! ResetSnippets() + let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {} +endf + +let g:did_ft = {} +fun! GetSnippets(dir, filetypes) + for ft in split(a:filetypes, '\.') + if has_key(g:did_ft, ft) | continue | endif + call s:DefineSnips(a:dir, ft, ft) + if ft == 'objc' || ft == 'cpp' || ft == 'cs' + call s:DefineSnips(a:dir, 'c', ft) + elseif ft == 'xhtml' + call s:DefineSnips(a:dir, 'html', 'xhtml') + endif + let g:did_ft[ft] = 1 + endfor +endf + +" Define "aliasft" snippets for the filetype "realft". +fun s:DefineSnips(dir, aliasft, realft) + for path in split(globpath(a:dir, a:aliasft.'/')."\n". + \ globpath(a:dir, a:aliasft.'-*/'), "\n") + call ExtractSnips(path, a:realft) + endfor + for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n". + \ globpath(a:dir, a:aliasft.'-*.snippets'), "\n") + call ExtractSnipsFile(path, a:realft) + endfor +endf + +fun! TriggerSnippet() + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingForward == "<tab>" + let SuperTabKey = "\<c-n>" + elseif g:SuperTabMappingBackward == "<tab>" + let SuperTabKey = "\<c-p>" + endif + endif + + if pumvisible() " Update snippet if completion is used, or deal with supertab + if exists('SuperTabKey') + call feedkeys(SuperTabKey) | return '' + endif + call feedkeys("\<esc>a", 'n') " Close completion menu + call feedkeys("\<tab>") | return '' + endif + + if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif + + let word = matchstr(getline('.'), '\S\+\%'.col('.').'c') + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let [trigger, snippet] = s:GetSnippet(word, scope) + " If word is a trigger for a snippet, delete the trigger & expand + " the snippet. + if snippet != '' + let col = col('.') - len(trigger) + sil exe 's/\V'.escape(trigger, '/.').'\%#//' + return snipMate#expandSnip(snippet, col) + endif + endfor + + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\<tab>" +endf + +fun! BackwardsSnippet() + if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif + + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingBackward == "<s-tab>" + let SuperTabKey = "\<c-p>" + elseif g:SuperTabMappingForward == "<s-tab>" + let SuperTabKey = "\<c-n>" + endif + endif + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\<s-tab>" +endf + +" Check if word under cursor is snippet trigger; if it isn't, try checking if +" the text after non-word characters is (e.g. check for "foo" in "bar.foo") +fun s:GetSnippet(word, scope) + let word = a:word | let snippet = '' + while snippet == '' + if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:snippets[a:scope][word] + elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:ChooseSnippet(a:scope, word) + if snippet == '' | break | endif + else + if match(word, '\W') == -1 | break | endif + let word = substitute(word, '.\{-}\W', '', '') + endif + endw + if word == '' && a:word != '.' && stridx(a:word, '.') != -1 + let [word, snippet] = s:GetSnippet('.', a:scope) + endif + return [word, snippet] +endf + +fun s:ChooseSnippet(scope, trigger) + let snippet = [] + let i = 1 + for snip in s:multi_snips[a:scope][a:trigger] + let snippet += [i.'. '.snip[0]] + let i += 1 + endfor + if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif + let num = inputlist(snippet) - 1 + return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1] +endf + +fun! ShowAvailableSnips() + let line = getline('.') + let col = col('.') + let word = matchstr(getline('.'), '\S\+\%'.col.'c') + let words = [word] + if stridx(word, '.') + let words += split(word, '\.', 1) + endif + let matchlen = 0 + let matches = [] + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : [] + if has_key(s:multi_snips, scope) + let triggers += keys(s:multi_snips[scope]) + endif + for trigger in triggers + for word in words + if word == '' + let matches += [trigger] " Show all matches if word is empty + elseif trigger =~ '^'.word + let matches += [trigger] + let len = len(word) + if len > matchlen | let matchlen = len | endif + endif + endfor + endfor + endfor + + " This is to avoid a bug with Vim when using complete(col - matchlen, matches) + " (Issue#46 on the Google Code snipMate issue tracker). + call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', '')) + call complete(col, matches) + return '' +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/plugin/taglist.vim b/plugin/taglist.vim new file mode 100644 index 0000000..59901f6 --- /dev/null +++ b/plugin/taglist.vim @@ -0,0 +1,4546 @@ +" File: taglist.vim +" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +" Version: 4.5 +" Last Modified: September 21, 2007 +" Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan +" Permission is hereby granted to use and distribute this code, +" with or without modifications, provided that this copyright +" notice is copied with it. Like anything else that's free, +" taglist.vim is provided *as is* and comes with no warranty of any +" kind, either expressed or implied. In no event will the copyright +" holder be liable for any damamges resulting from the use of this +" software. +" +" The "Tag List" plugin is a source code browser plugin for Vim and provides +" an overview of the structure of the programming language files and allows +" you to efficiently browse through source code files for different +" programming languages. You can visit the taglist plugin home page for more +" information: +" +" http://vim-taglist.sourceforge.net +" +" You can subscribe to the taglist mailing list to post your questions +" or suggestions for improvement or to report bugs. Visit the following +" page for subscribing to the mailing list: +" +" http://groups.yahoo.com/group/taglist/ +" +" For more information about using this plugin, after installing the +" taglist plugin, use the ":help taglist" command. +" +" Installation +" ------------ +" 1. Download the taglist.zip file and unzip the files to the $HOME/.vim +" or the $HOME/vimfiles or the $VIM/vimfiles directory. This should +" unzip the following two files (the directory structure should be +" preserved): +" +" plugin/taglist.vim - main taglist plugin file +" doc/taglist.txt - documentation (help) file +" +" Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath' +" Vim help pages for more details about installing Vim plugins. +" 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or +" $VIM/vimfiles/doc directory, start Vim and run the ":helptags ." +" command to process the taglist help file. +" 3. If the exuberant ctags utility is not present in your PATH, then set the +" Tlist_Ctags_Cmd variable to point to the location of the exuberant ctags +" utility (not to the directory) in the .vimrc file. +" 4. If you are running a terminal/console version of Vim and the +" terminal doesn't support changing the window width then set the +" 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file. +" 5. Restart Vim. +" 6. You can now use the ":TlistToggle" command to open/close the taglist +" window. You can use the ":help taglist" command to get more +" information about using the taglist plugin. +" +" ****************** Do not modify after this line ************************ + +" Line continuation used here +let s:cpo_save = &cpo +set cpo&vim + +if !exists('loaded_taglist') + " First time loading the taglist plugin + " + " To speed up the loading of Vim, the taglist plugin uses autoload + " mechanism to load the taglist functions. + " Only define the configuration variables, user commands and some + " auto-commands and finish sourcing the file + + " The taglist plugin requires the built-in Vim system() function. If this + " function is not available, then don't load the plugin. + if !exists('*system') + echomsg 'Taglist: Vim system() built-in function is not available. ' . + \ 'Plugin is not loaded.' + let loaded_taglist = 'no' + let &cpo = s:cpo_save + finish + endif + + " Location of the exuberant ctags tool + if !exists('Tlist_Ctags_Cmd') + if executable('exuberant-ctags') + " On Debian Linux, exuberant ctags is installed + " as exuberant-ctags + let Tlist_Ctags_Cmd = 'exuberant-ctags' + elseif executable('exctags') + " On Free-BSD, exuberant ctags is installed as exctags + let Tlist_Ctags_Cmd = 'exctags' + elseif executable('ctags') + let Tlist_Ctags_Cmd = 'ctags' + elseif executable('ctags.exe') + let Tlist_Ctags_Cmd = 'ctags.exe' + elseif executable('tags') + let Tlist_Ctags_Cmd = 'tags' + else + echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' . + \ 'not found in PATH. Plugin is not loaded.' + " Skip loading the plugin + let loaded_taglist = 'no' + let &cpo = s:cpo_save + finish + endif + endif + + + " Automatically open the taglist window on Vim startup + if !exists('Tlist_Auto_Open') + let Tlist_Auto_Open = 0 + endif + + " When the taglist window is toggle opened, move the cursor to the + " taglist window + if !exists('Tlist_GainFocus_On_ToggleOpen') + let Tlist_GainFocus_On_ToggleOpen = 0 + endif + + " Process files even when the taglist window is not open + if !exists('Tlist_Process_File_Always') + let Tlist_Process_File_Always = 0 + endif + + if !exists('Tlist_Show_Menu') + let Tlist_Show_Menu = 0 + endif + + " Tag listing sort type - 'name' or 'order' + if !exists('Tlist_Sort_Type') + let Tlist_Sort_Type = 'order' + endif + + " Tag listing window split (horizontal/vertical) control + if !exists('Tlist_Use_Horiz_Window') + let Tlist_Use_Horiz_Window = 0 + endif + + " Open the vertically split taglist window on the left or on the right + " side. This setting is relevant only if Tlist_Use_Horiz_Window is set to + " zero (i.e. only for vertically split windows) + if !exists('Tlist_Use_Right_Window') + let Tlist_Use_Right_Window = 0 + endif + + " Increase Vim window width to display vertically split taglist window. + " For MS-Windows version of Vim running in a MS-DOS window, this must be + " set to 0 otherwise the system may hang due to a Vim limitation. + if !exists('Tlist_Inc_Winwidth') + if (has('win16') || has('win95')) && !has('gui_running') + let Tlist_Inc_Winwidth = 0 + else + let Tlist_Inc_Winwidth = 1 + endif + endif + + " Vertically split taglist window width setting + if !exists('Tlist_WinWidth') + let Tlist_WinWidth = 30 + endif + + " Horizontally split taglist window height setting + if !exists('Tlist_WinHeight') + let Tlist_WinHeight = 10 + endif + + " Display tag prototypes or tag names in the taglist window + if !exists('Tlist_Display_Prototype') + let Tlist_Display_Prototype = 0 + endif + + " Display tag scopes in the taglist window + if !exists('Tlist_Display_Tag_Scope') + let Tlist_Display_Tag_Scope = 1 + endif + + " Use single left mouse click to jump to a tag. By default this is disabled. + " Only double click using the mouse will be processed. + if !exists('Tlist_Use_SingleClick') + let Tlist_Use_SingleClick = 0 + endif + + " Control whether additional help is displayed as part of the taglist or + " not. Also, controls whether empty lines are used to separate the tag + " tree. + if !exists('Tlist_Compact_Format') + let Tlist_Compact_Format = 0 + endif + + " Exit Vim if only the taglist window is currently open. By default, this is + " set to zero. + if !exists('Tlist_Exit_OnlyWindow') + let Tlist_Exit_OnlyWindow = 0 + endif + + " Automatically close the folds for the non-active files in the taglist + " window + if !exists('Tlist_File_Fold_Auto_Close') + let Tlist_File_Fold_Auto_Close = 0 + endif + + " Close the taglist window when a tag is selected + if !exists('Tlist_Close_On_Select') + let Tlist_Close_On_Select = 0 + endif + + " Automatically update the taglist window to display tags for newly + " edited files + if !exists('Tlist_Auto_Update') + let Tlist_Auto_Update = 1 + endif + + " Automatically highlight the current tag + if !exists('Tlist_Auto_Highlight_Tag') + let Tlist_Auto_Highlight_Tag = 1 + endif + + " Automatically highlight the current tag on entering a buffer + if !exists('Tlist_Highlight_Tag_On_BufEnter') + let Tlist_Highlight_Tag_On_BufEnter = 1 + endif + + " Enable fold column to display the folding for the tag tree + if !exists('Tlist_Enable_Fold_Column') + let Tlist_Enable_Fold_Column = 1 + endif + + " Display the tags for only one file in the taglist window + if !exists('Tlist_Show_One_File') + let Tlist_Show_One_File = 0 + endif + + if !exists('Tlist_Max_Submenu_Items') + let Tlist_Max_Submenu_Items = 20 + endif + + if !exists('Tlist_Max_Tag_Length') + let Tlist_Max_Tag_Length = 10 + endif + + " Do not change the name of the taglist title variable. The winmanager + " plugin relies on this name to determine the title for the taglist + " plugin. + let TagList_title = "__Tag_List__" + + " Taglist debug messages + let s:tlist_msg = '' + + " Define the taglist autocommand to automatically open the taglist window + " on Vim startup + if g:Tlist_Auto_Open + autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open() + endif + + " Refresh the taglist + if g:Tlist_Process_File_Always + autocmd BufEnter * call s:Tlist_Refresh() + endif + + if g:Tlist_Show_Menu + autocmd GUIEnter * call s:Tlist_Menu_Init() + endif + + " When the taglist buffer is created when loading a Vim session file, + " the taglist buffer needs to be initialized. The BufFilePost event + " is used to handle this case. + autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load() + + " Define the user commands to manage the taglist window + command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle() + command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open() + " For backwards compatiblity define the Tlist command + command! -nargs=0 -bar Tlist TlistToggle + command! -nargs=+ -complete=file TlistAddFiles + \ call s:Tlist_Add_Files(<f-args>) + command! -nargs=+ -complete=dir TlistAddFilesRecursive + \ call s:Tlist_Add_Files_Recursive(<f-args>) + command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close() + command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File() + command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag( + \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1) + " For backwards compatiblity define the TlistSync command + command! -nargs=0 -bar TlistSync TlistHighlightTag + command! -nargs=* -complete=buffer TlistShowPrototype + \ echo Tlist_Get_Tag_Prototype_By_Line(<f-args>) + command! -nargs=* -complete=buffer TlistShowTag + \ echo Tlist_Get_Tagname_By_Line(<f-args>) + command! -nargs=* -complete=file TlistSessionLoad + \ call s:Tlist_Session_Load(<q-args>) + command! -nargs=* -complete=file TlistSessionSave + \ call s:Tlist_Session_Save(<q-args>) + command! -bar TlistLock let Tlist_Auto_Update=0 + command! -bar TlistUnlock let Tlist_Auto_Update=1 + + " Commands for enabling/disabling debug and to display debug messages + command! -nargs=? -complete=file -bar TlistDebug + \ call s:Tlist_Debug_Enable(<q-args>) + command! -nargs=0 -bar TlistUndebug call s:Tlist_Debug_Disable() + command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show() + + " Define autocommands to autoload the taglist plugin when needed. + + " Trick to get the current script ID + map <SID>xx <SID>xx + let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$', + \ '\1', '') + unmap <SID>xx + + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' . + \ escape(expand('<sfile>'), ' ') + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' . + \ escape(expand('<sfile>'), ' ') + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' . + \ escape(expand('<sfile>'), ' ') + exe 'autocmd FuncUndefined Tlist_* source ' . + \ escape(expand('<sfile>'), ' ') + exe 'autocmd FuncUndefined TagList_* source ' . + \ escape(expand('<sfile>'), ' ') + + let loaded_taglist = 'fast_load_done' + + if g:Tlist_Show_Menu && has('gui_running') + call s:Tlist_Menu_Init() + endif + + " restore 'cpo' + let &cpo = s:cpo_save + finish +endif + +if !exists('s:tlist_sid') + " Two or more versions of taglist plugin are installed. Don't + " load this version of the plugin. + finish +endif + +unlet! s:tlist_sid + +if loaded_taglist != 'fast_load_done' + " restore 'cpo' + let &cpo = s:cpo_save + finish +endif + +" Taglist plugin functionality is available +let loaded_taglist = 'available' + +"------------------- end of user configurable options -------------------- + +" Default language specific settings for supported file types and tag types +" +" Variable name format: +" +" s:tlist_def_{vim_ftype}_settings +" +" vim_ftype - Filetype detected by Vim +" +" Value format: +" +" <ctags_ftype>;<flag>:<name>;<flag>:<name>;... +" +" ctags_ftype - File type supported by exuberant ctags +" flag - Flag supported by exuberant ctags to generate a tag type +" name - Name of the tag type used in the taglist window to display the +" tags of this type +" + +" assembly language +let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type' + +" aspperl language +let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable' + +" aspvbs language +let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable' + +" awk language +let s:tlist_def_awk_settings = 'awk;f:function' + +" beta language +let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern' + +" c language +let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' . + \ 'v:variable;f:function' + +" c++ language +let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' . + \ 'c:class;g:enum;s:struct;u:union;f:function' + +" c# language +let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' . + \ 'E:event;g:enum;s:struct;i:interface;' . + \ 'p:properties;m:method' + +" cobol language +let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' . + \ 'P:program;s:section' + +" eiffel language +let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature' + +" erlang language +let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function' + +" expect (same as tcl) language +let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure' + +" fortran language +let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' . + \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' . + \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine' + +" HTML language +let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function' + +" java language +let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' . + \ 'f:field;m:method' + +" javascript language +let s:tlist_def_javascript_settings = 'javascript;f:function' + +" lisp language +let s:tlist_def_lisp_settings = 'lisp;f:function' + +" lua language +let s:tlist_def_lua_settings = 'lua;f:function' + +" makefiles +let s:tlist_def_make_settings = 'make;m:macro' + +" pascal language +let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure' + +" perl language +let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine' + +" php language +let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function' + +" python language +let s:tlist_def_python_settings = 'python;c:class;m:member;f:function' + +" rexx language +let s:tlist_def_rexx_settings = 'rexx;s:subroutine' + +" ruby language +let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' . + \ 'm:singleton method' + +" scheme language +let s:tlist_def_scheme_settings = 'scheme;s:set;f:function' + +" shell language +let s:tlist_def_sh_settings = 'sh;f:function' + +" C shell language +let s:tlist_def_csh_settings = 'sh;f:function' + +" Z shell language +let s:tlist_def_zsh_settings = 'sh;f:function' + +" slang language +let s:tlist_def_slang_settings = 'slang;n:namespace;f:function' + +" sml language +let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' . + \ 'r:structure;t:type;v:value;f:function' + +" sql language +let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' . + \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure' + +" tcl language +let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure' + +" vera language +let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' . + \ 'f:function;g:enum;m:member;p:program;' . + \ 'P:prototype;t:task;T:typedef;v:variable;' . + \ 'x:externvar' + +"verilog language +let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' . + \ 'e:event;r:register;t:task;w:write;p:port;v:variable;f:function' + +" vim language +let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function' + +" yacc language +let s:tlist_def_yacc_settings = 'yacc;l:label' + +"------------------- end of language specific options -------------------- + +" Vim window size is changed by the taglist plugin or not +let s:tlist_winsize_chgd = -1 +" Taglist window is maximized or not +let s:tlist_win_maximized = 0 +" Name of files in the taglist +let s:tlist_file_names='' +" Number of files in the taglist +let s:tlist_file_count = 0 +" Number of filetypes supported by taglist +let s:tlist_ftype_count = 0 +" Is taglist part of other plugins like winmanager or cream? +let s:tlist_app_name = "none" +" Are we displaying brief help text +let s:tlist_brief_help = 1 +" List of files removed on user request +let s:tlist_removed_flist = "" +" Index of current file displayed in the taglist window +let s:tlist_cur_file_idx = -1 +" Taglist menu is empty or not +let s:tlist_menu_empty = 1 + +" An autocommand is used to refresh the taglist window when entering any +" buffer. We don't want to refresh the taglist window if we are entering the +" file window from one of the taglist functions. The 'Tlist_Skip_Refresh' +" variable is used to skip the refresh of the taglist window and is set +" and cleared appropriately. +let s:Tlist_Skip_Refresh = 0 + +" Tlist_Window_Display_Help() +function! s:Tlist_Window_Display_Help() + if s:tlist_app_name == "winmanager" + " To handle a bug in the winmanager plugin, add a space at the + " last line + call setline('$', ' ') + endif + + if s:tlist_brief_help + " Add the brief help + call append(0, '" Press <F1> to display help text') + else + " Add the extensive help + call append(0, '" <enter> : Jump to tag definition') + call append(1, '" o : Jump to tag definition in new window') + call append(2, '" p : Preview the tag definition') + call append(3, '" <space> : Display tag prototype') + call append(4, '" u : Update tag list') + call append(5, '" s : Select sort field') + call append(6, '" d : Remove file from taglist') + call append(7, '" x : Zoom-out/Zoom-in taglist window') + call append(8, '" + : Open a fold') + call append(9, '" - : Close a fold') + call append(10, '" * : Open all folds') + call append(11, '" = : Close all folds') + call append(12, '" [[ : Move to the start of previous file') + call append(13, '" ]] : Move to the start of next file') + call append(14, '" q : Close the taglist window') + call append(15, '" <F1> : Remove help text') + endif +endfunction + +" Tlist_Window_Toggle_Help_Text() +" Toggle taglist plugin help text between the full version and the brief +" version +function! s:Tlist_Window_Toggle_Help_Text() + if g:Tlist_Compact_Format + " In compact display mode, do not display help + return + endif + + " Include the empty line displayed after the help text + let brief_help_size = 1 + let full_help_size = 16 + + setlocal modifiable + + " Set report option to a huge value to prevent informational messages + " while deleting the lines + let old_report = &report + set report=99999 + + " Remove the currently highlighted tag. Otherwise, the help text + " might be highlighted by mistake + match none + + " Toggle between brief and full help text + if s:tlist_brief_help + let s:tlist_brief_help = 0 + + " Remove the previous help + exe '1,' . brief_help_size . ' delete _' + + " Adjust the start/end line numbers for the files + call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size) + else + let s:tlist_brief_help = 1 + + " Remove the previous help + exe '1,' . full_help_size . ' delete _' + + " Adjust the start/end line numbers for the files + call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size) + endif + + call s:Tlist_Window_Display_Help() + + " Restore the report option + let &report = old_report + + setlocal nomodifiable +endfunction + +" Taglist debug support +let s:tlist_debug = 0 + +" File for storing the debug messages +let s:tlist_debug_file = '' + +" Tlist_Debug_Enable +" Enable logging of taglist debug messages. +function! s:Tlist_Debug_Enable(...) + let s:tlist_debug = 1 + + " Check whether a valid file name is supplied. + if a:1 != '' + let s:tlist_debug_file = fnamemodify(a:1, ':p') + + " Empty the log file + exe 'redir! > ' . s:tlist_debug_file + redir END + + " Check whether the log file is present/created + if !filewritable(s:tlist_debug_file) + call s:Tlist_Warning_Msg('Taglist: Unable to create log file ' + \ . s:tlist_debug_file) + let s:tlist_debug_file = '' + endif + endif +endfunction + +" Tlist_Debug_Disable +" Disable logging of taglist debug messages. +function! s:Tlist_Debug_Disable(...) + let s:tlist_debug = 0 + let s:tlist_debug_file = '' +endfunction + +" Tlist_Debug_Show +" Display the taglist debug messages in a new window +function! s:Tlist_Debug_Show() + if s:tlist_msg == '' + call s:Tlist_Warning_Msg('Taglist: No debug messages') + return + endif + + " Open a new window to display the taglist debug messages + new taglist_debug.txt + " Delete all the lines (if the buffer already exists) + silent! %delete _ + " Add the messages + silent! put =s:tlist_msg + " Move the cursor to the first line + normal! gg +endfunction + +" Tlist_Log_Msg +" Log the supplied debug message along with the time +function! s:Tlist_Log_Msg(msg) + if s:tlist_debug + if s:tlist_debug_file != '' + exe 'redir >> ' . s:tlist_debug_file + silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n" + redir END + else + " Log the message into a variable + " Retain only the last 3000 characters + let len = strlen(s:tlist_msg) + if len > 3000 + let s:tlist_msg = strpart(s:tlist_msg, len - 3000) + endif + let s:tlist_msg = s:tlist_msg . strftime('%H:%M:%S') . ': ' . + \ a:msg . "\n" + endif + endif +endfunction + +" Tlist_Warning_Msg() +" Display a message using WarningMsg highlight group +function! s:Tlist_Warning_Msg(msg) + echohl WarningMsg + echomsg a:msg + echohl None +endfunction + +" Last returned file index for file name lookup. +" Used to speed up file lookup +let s:tlist_file_name_idx_cache = -1 + +" Tlist_Get_File_Index() +" Return the index of the specified filename +function! s:Tlist_Get_File_Index(fname) + if s:tlist_file_count == 0 || a:fname == '' + return -1 + endif + + " If the new filename is same as the last accessed filename, then + " return that index + if s:tlist_file_name_idx_cache != -1 && + \ s:tlist_file_name_idx_cache < s:tlist_file_count + if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname + " Same as the last accessed file + return s:tlist_file_name_idx_cache + endif + endif + + " First, check whether the filename is present + let s_fname = a:fname . "\n" + let i = stridx(s:tlist_file_names, s_fname) + if i == -1 + let s:tlist_file_name_idx_cache = -1 + return -1 + endif + + " Second, compute the file name index + let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g') + let s:tlist_file_name_idx_cache = strlen(nl_txt) + return s:tlist_file_name_idx_cache +endfunction + +" Last returned file index for line number lookup. +" Used to speed up file lookup +let s:tlist_file_lnum_idx_cache = -1 + +" Tlist_Window_Get_File_Index_By_Linenum() +" Return the index of the filename present in the specified line number +" Line number refers to the line number in the taglist window +function! s:Tlist_Window_Get_File_Index_By_Linenum(lnum) + call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')') + + " First try to see whether the new line number is within the range + " of the last returned file + if s:tlist_file_lnum_idx_cache != -1 && + \ s:tlist_file_lnum_idx_cache < s:tlist_file_count + if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start && + \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end + return s:tlist_file_lnum_idx_cache + endif + endif + + let fidx = -1 + + if g:Tlist_Show_One_File + " Displaying only one file in the taglist window. Check whether + " the line is within the tags displayed for that file + if s:tlist_cur_file_idx != -1 + if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start + \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end + let fidx = s:tlist_cur_file_idx + endif + + endif + else + " Do a binary search in the taglist + let left = 0 + let right = s:tlist_file_count - 1 + + while left < right + let mid = (left + right) / 2 + + if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end + let s:tlist_file_lnum_idx_cache = mid + return mid + endif + + if a:lnum < s:tlist_{mid}_start + let right = mid - 1 + else + let left = mid + 1 + endif + endwhile + + if left >= 0 && left < s:tlist_file_count + \ && a:lnum >= s:tlist_{left}_start + \ && a:lnum <= s:tlist_{left}_end + let fidx = left + endif + endif + + let s:tlist_file_lnum_idx_cache = fidx + + return fidx +endfunction + +" Tlist_Exe_Cmd_No_Acmds +" Execute the specified Ex command after disabling autocommands +function! s:Tlist_Exe_Cmd_No_Acmds(cmd) + let old_eventignore = &eventignore + set eventignore=all + exe a:cmd + let &eventignore = old_eventignore +endfunction + +" Tlist_Skip_File() +" Check whether tag listing is supported for the specified file +function! s:Tlist_Skip_File(filename, ftype) + " Skip buffers with no names and buffers with filetype not set + if a:filename == '' || a:ftype == '' + return 1 + endif + + " Skip files which are not supported by exuberant ctags + " First check whether default settings for this filetype are available. + " If it is not available, then check whether user specified settings are + " available. If both are not available, then don't list the tags for this + " filetype + let var = 's:tlist_def_' . a:ftype . '_settings' + if !exists(var) + let var = 'g:tlist_' . a:ftype . '_settings' + if !exists(var) + return 1 + endif + endif + + " Skip files which are not readable or files which are not yet stored + " to the disk + if !filereadable(a:filename) + return 1 + endif + + return 0 +endfunction + +" Tlist_User_Removed_File +" Returns 1 if a file is removed by a user from the taglist +function! s:Tlist_User_Removed_File(filename) + return stridx(s:tlist_removed_flist, a:filename . "\n") != -1 +endfunction + +" Tlist_Update_Remove_List +" Update the list of user removed files from the taglist +" add == 1, add the file to the removed list +" add == 0, delete the file from the removed list +function! s:Tlist_Update_Remove_List(filename, add) + if a:add + let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n" + else + let idx = stridx(s:tlist_removed_flist, a:filename . "\n") + let text_before = strpart(s:tlist_removed_flist, 0, idx) + let rem_text = strpart(s:tlist_removed_flist, idx) + let next_idx = stridx(rem_text, "\n") + let text_after = strpart(rem_text, next_idx + 1) + + let s:tlist_removed_flist = text_before . text_after + endif +endfunction + +" Tlist_FileType_Init +" Initialize the ctags arguments and tag variable for the specified +" file type +function! s:Tlist_FileType_Init(ftype) + call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a:ftype . ')') + " If the user didn't specify any settings, then use the default + " ctags args. Otherwise, use the settings specified by the user + let var = 'g:tlist_' . a:ftype . '_settings' + if exists(var) + " User specified ctags arguments + let settings = {var} . ';' + else + " Default ctags arguments + let var = 's:tlist_def_' . a:ftype . '_settings' + if !exists(var) + " No default settings for this file type. This filetype is + " not supported + return 0 + endif + let settings = s:tlist_def_{a:ftype}_settings . ';' + endif + + let msg = 'Taglist: Invalid ctags option setting - ' . settings + + " Format of the option that specifies the filetype and ctags arugments: + " + " <language_name>;flag1:name1;flag2:name2;flag3:name3 + " + + " Extract the file type to pass to ctags. This may be different from the + " file type detected by Vim + let pos = stridx(settings, ';') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let ctags_ftype = strpart(settings, 0, pos) + if ctags_ftype == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + " Make sure a valid filetype is supplied. If the user didn't specify a + " valid filetype, then the ctags option settings may be treated as the + " filetype + if ctags_ftype =~ ':' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + + " Remove the file type from settings + let settings = strpart(settings, pos + 1) + if settings == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + + " Process all the specified ctags flags. The format is + " flag1:name1;flag2:name2;flag3:name3 + let ctags_flags = '' + let cnt = 0 + while settings != '' + " Extract the flag + let pos = stridx(settings, ':') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let flag = strpart(settings, 0, pos) + if flag == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + " Remove the flag from settings + let settings = strpart(settings, pos + 1) + + " Extract the tag type name + let pos = stridx(settings, ';') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let name = strpart(settings, 0, pos) + if name == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let settings = strpart(settings, pos + 1) + + let cnt = cnt + 1 + + let s:tlist_{a:ftype}_{cnt}_name = flag + let s:tlist_{a:ftype}_{cnt}_fullname = name + let ctags_flags = ctags_flags . flag + endwhile + + let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype . + \ ' --' . ctags_ftype . '-types=' . ctags_flags + let s:tlist_{a:ftype}_count = cnt + let s:tlist_{a:ftype}_ctags_flags = ctags_flags + + " Save the filetype name + let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype + let s:tlist_ftype_count = s:tlist_ftype_count + 1 + + return 1 +endfunction + +" Tlist_Detect_Filetype +" Determine the filetype for the specified file using the filetypedetect +" autocmd. +function! s:Tlist_Detect_Filetype(fname) + " Ignore the filetype autocommands + let old_eventignore = &eventignore + set eventignore=FileType + + " Save the 'filetype', as this will be changed temporarily + let old_filetype = &filetype + + " Run the filetypedetect group of autocommands to determine + " the filetype + exe 'doautocmd filetypedetect BufRead ' . a:fname + + " Save the detected filetype + let ftype = &filetype + + " Restore the previous state + let &filetype = old_filetype + let &eventignore = old_eventignore + + return ftype +endfunction + +" Tlist_Get_Buffer_Filetype +" Get the filetype for the specified buffer +function! s:Tlist_Get_Buffer_Filetype(bnum) + let buf_ft = getbufvar(a:bnum, '&filetype') + + if bufloaded(a:bnum) + " For loaded buffers, the 'filetype' is already determined + return buf_ft + endif + + " For unloaded buffers, if the 'filetype' option is set, return it + if buf_ft != '' + return buf_ft + endif + + " Skip non-existent buffers + if !bufexists(a:bnum) + return '' + endif + + " For buffers whose filetype is not yet determined, try to determine + " the filetype + let bname = bufname(a:bnum) + + return s:Tlist_Detect_Filetype(bname) +endfunction + +" Tlist_Discard_TagInfo +" Discard the stored tag information for a file +function! s:Tlist_Discard_TagInfo(fidx) + call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' . + \ s:tlist_{a:fidx}_filename . ')') + let ftype = s:tlist_{a:fidx}_filetype + + " Discard information about the tags defined in the file + let i = 1 + while i <= s:tlist_{a:fidx}_tag_count + let fidx_i = 's:tlist_' . a:fidx . '_' . i + unlet! {fidx_i}_tag + unlet! {fidx_i}_tag_name + unlet! {fidx_i}_tag_type + unlet! {fidx_i}_ttype_idx + unlet! {fidx_i}_tag_proto + unlet! {fidx_i}_tag_searchpat + unlet! {fidx_i}_tag_linenum + let i = i + 1 + endwhile + + let s:tlist_{a:fidx}_tag_count = 0 + + " Discard information about tag type groups + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + if s:tlist_{a:fidx}_{ttype} != '' + let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype + let {fidx_ttype} = '' + let {fidx_ttype}_offset = 0 + let cnt = {fidx_ttype}_count + let {fidx_ttype}_count = 0 + let j = 1 + while j <= cnt + unlet! {fidx_ttype}_{j} + let j = j + 1 + endwhile + endif + let i = i + 1 + endwhile + + " Discard the stored menu command also + let s:tlist_{a:fidx}_menu_cmd = '' +endfunction + +" Tlist_Window_Update_Line_Offsets +" Update the line offsets for tags for files starting from start_idx +" and displayed in the taglist window by the specified offset +function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset) + let i = a:start_idx + + while i < s:tlist_file_count + if s:tlist_{i}_visible + " Update the start/end line number only if the file is visible + if a:increment + let s:tlist_{i}_start = s:tlist_{i}_start + a:offset + let s:tlist_{i}_end = s:tlist_{i}_end + a:offset + else + let s:tlist_{i}_start = s:tlist_{i}_start - a:offset + let s:tlist_{i}_end = s:tlist_{i}_end - a:offset + endif + endif + let i = i + 1 + endwhile +endfunction + +" Tlist_Discard_FileInfo +" Discard the stored information for a file +function! s:Tlist_Discard_FileInfo(fidx) + call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' . + \ s:tlist_{a:fidx}_filename . ')') + call s:Tlist_Discard_TagInfo(a:fidx) + + let ftype = s:tlist_{a:fidx}_filetype + + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + unlet! s:tlist_{a:fidx}_{ttype} + unlet! s:tlist_{a:fidx}_{ttype}_offset + unlet! s:tlist_{a:fidx}_{ttype}_count + let i = i + 1 + endwhile + + unlet! s:tlist_{a:fidx}_filename + unlet! s:tlist_{a:fidx}_sort_type + unlet! s:tlist_{a:fidx}_filetype + unlet! s:tlist_{a:fidx}_mtime + unlet! s:tlist_{a:fidx}_start + unlet! s:tlist_{a:fidx}_end + unlet! s:tlist_{a:fidx}_valid + unlet! s:tlist_{a:fidx}_visible + unlet! s:tlist_{a:fidx}_tag_count + unlet! s:tlist_{a:fidx}_menu_cmd +endfunction + +" Tlist_Window_Remove_File_From_Display +" Remove the specified file from display +function! s:Tlist_Window_Remove_File_From_Display(fidx) + call s:Tlist_Log_Msg('Tlist_Window_Remove_File_From_Display (' . + \ s:tlist_{a:fidx}_filename . ')') + " If the file is not visible then no need to remove it + if !s:tlist_{a:fidx}_visible + return + endif + + " Remove the tags displayed for the specified file from the window + let start = s:tlist_{a:fidx}_start + " Include the empty line after the last line also + if g:Tlist_Compact_Format + let end = s:tlist_{a:fidx}_end + else + let end = s:tlist_{a:fidx}_end + 1 + endif + + setlocal modifiable + exe 'silent! ' . start . ',' . end . 'delete _' + setlocal nomodifiable + + " Correct the start and end line offsets for all the files following + " this file, as the tags for this file are removed + call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1) +endfunction + +" Tlist_Remove_File +" Remove the file under the cursor or the specified file index +" user_request - User requested to remove the file from taglist +function! s:Tlist_Remove_File(file_idx, user_request) + let fidx = a:file_idx + + if fidx == -1 + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + endif + call s:Tlist_Log_Msg('Tlist_Remove_File (' . + \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')') + + let save_winnr = winnr() + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Taglist window is open, remove the file from display + + if save_winnr != winnum + let old_eventignore = &eventignore + set eventignore=all + exe winnum . 'wincmd w' + endif + + call s:Tlist_Window_Remove_File_From_Display(fidx) + + if save_winnr != winnum + exe save_winnr . 'wincmd w' + let &eventignore = old_eventignore + endif + endif + + let fname = s:tlist_{fidx}_filename + + if a:user_request + " As the user requested to remove the file from taglist, + " add it to the removed list + call s:Tlist_Update_Remove_List(fname, 1) + endif + + " Remove the file name from the taglist list of filenames + let idx = stridx(s:tlist_file_names, fname . "\n") + let text_before = strpart(s:tlist_file_names, 0, idx) + let rem_text = strpart(s:tlist_file_names, idx) + let next_idx = stridx(rem_text, "\n") + let text_after = strpart(rem_text, next_idx + 1) + let s:tlist_file_names = text_before . text_after + + call s:Tlist_Discard_FileInfo(fidx) + + " Shift all the file variables by one index + let i = fidx + 1 + + while i < s:tlist_file_count + let j = i - 1 + + let s:tlist_{j}_filename = s:tlist_{i}_filename + let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type + let s:tlist_{j}_filetype = s:tlist_{i}_filetype + let s:tlist_{j}_mtime = s:tlist_{i}_mtime + let s:tlist_{j}_start = s:tlist_{i}_start + let s:tlist_{j}_end = s:tlist_{i}_end + let s:tlist_{j}_valid = s:tlist_{i}_valid + let s:tlist_{j}_visible = s:tlist_{i}_visible + let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count + let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd + + let k = 1 + while k <= s:tlist_{j}_tag_count + let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag + let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name + let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type_By_Tag(i, k) + let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx + let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k) + let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k) + let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k) + let k = k + 1 + endwhile + + let ftype = s:tlist_{i}_filetype + + let k = 1 + while k <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{k}_name + let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype} + let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset + let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count + if s:tlist_{j}_{ttype} != '' + let l = 1 + while l <= s:tlist_{j}_{ttype}_count + let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l} + let l = l + 1 + endwhile + endif + let k = k + 1 + endwhile + + " As the file and tag information is copied to the new index, + " discard the previous information + call s:Tlist_Discard_FileInfo(i) + + let i = i + 1 + endwhile + + " Reduce the number of files displayed + let s:tlist_file_count = s:tlist_file_count - 1 + + if g:Tlist_Show_One_File + " If the tags for only one file is displayed and if we just + " now removed that file, then invalidate the current file idx + if s:tlist_cur_file_idx == fidx + let s:tlist_cur_file_idx = -1 + endif + endif +endfunction + +" Tlist_Window_Goto_Window +" Goto the taglist window +function! s:Tlist_Window_Goto_Window() + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + if winnr() != winnum + call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w') + endif + endif +endfunction + +" Tlist_Window_Create +" Create a new taglist window. If it is already open, jump to it +function! s:Tlist_Window_Create() + call s:Tlist_Log_Msg('Tlist_Window_Create()') + " If the window is open, jump to it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Jump to the existing window + if winnr() != winnum + exe winnum . 'wincmd w' + endif + return + endif + + " If used with winmanager don't open windows. Winmanager will handle + " the window/buffer management + if s:tlist_app_name == "winmanager" + return + endif + + " Create a new window. If user prefers a horizontal window, then open + " a horizontally split window. Otherwise open a vertically split + " window + if g:Tlist_Use_Horiz_Window + " Open a horizontally split window + let win_dir = 'botright' + " Horizontal window height + let win_size = g:Tlist_WinHeight + else + if s:tlist_winsize_chgd == -1 + " Open a vertically split window. Increase the window size, if + " needed, to accomodate the new window + if g:Tlist_Inc_Winwidth && + \ &columns < (80 + g:Tlist_WinWidth) + " Save the original window position + let s:tlist_pre_winx = getwinposx() + let s:tlist_pre_winy = getwinposy() + + " one extra column is needed to include the vertical split + let &columns= &columns + g:Tlist_WinWidth + 1 + + let s:tlist_winsize_chgd = 1 + else + let s:tlist_winsize_chgd = 0 + endif + endif + + if g:Tlist_Use_Right_Window + " Open the window at the rightmost place + let win_dir = 'botright vertical' + else + " Open the window at the leftmost place + let win_dir = 'topleft vertical' + endif + let win_size = g:Tlist_WinWidth + endif + + " If the tag listing temporary buffer already exists, then reuse it. + " Otherwise create a new buffer + let bufnum = bufnr(g:TagList_title) + if bufnum == -1 + " Create a new buffer + let wcmd = g:TagList_title + else + " Edit the existing buffer + let wcmd = '+buffer' . bufnum + endif + + " Create the taglist window + exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd + + " Save the new window position + let s:tlist_winx = getwinposx() + let s:tlist_winy = getwinposy() + + " Initialize the taglist window + call s:Tlist_Window_Init() +endfunction + +" Tlist_Window_Zoom +" Zoom (maximize/minimize) the taglist window +function! s:Tlist_Window_Zoom() + if s:tlist_win_maximized + " Restore the window back to the previous size + if g:Tlist_Use_Horiz_Window + exe 'resize ' . g:Tlist_WinHeight + else + exe 'vert resize ' . g:Tlist_WinWidth + endif + let s:tlist_win_maximized = 0 + else + " Set the window size to the maximum possible without closing other + " windows + if g:Tlist_Use_Horiz_Window + resize + else + vert resize + endif + let s:tlist_win_maximized = 1 + endif +endfunction + +" Tlist_Ballon_Expr +" When the mouse cursor is over a tag in the taglist window, display the +" tag prototype (balloon) +function! Tlist_Ballon_Expr() + " Get the file index + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum) + if fidx == -1 + return '' + endif + + " Get the tag output line for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum) + if tidx == 0 + return '' + endif + + " Get the tag search pattern and display it + return s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" Tlist_Window_Check_Width +" Check the width of the taglist window. For horizontally split windows, the +" 'winfixheight' option is used to fix the height of the window. For +" vertically split windows, Vim doesn't support the 'winfixwidth' option. So +" need to handle window width changes from this function. +function! s:Tlist_Window_Check_Width() + let tlist_winnr = bufwinnr(g:TagList_title) + if tlist_winnr == -1 + return + endif + + let width = winwidth(tlist_winnr) + if width != g:Tlist_WinWidth + call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " . + \ "width from " . width . " to " . g:Tlist_WinWidth) + let save_winnr = winnr() + if save_winnr != tlist_winnr + call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w') + endif + exe 'vert resize ' . g:Tlist_WinWidth + if save_winnr != tlist_winnr + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + endif +endfunction + +" Tlist_Window_Exit_Only_Window +" If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the +" taglist window is present. +function! s:Tlist_Window_Exit_Only_Window() + " Before quitting Vim, delete the taglist buffer so that + " the '0 mark is correctly set to the previous buffer. + if v:version < 700 + if winbufnr(2) == -1 + bdelete + quit + endif + else + if winbufnr(2) == -1 + if tabpagenr('$') == 1 + " Only one tag page is present + bdelete + quit + else + " More than one tab page is present. Close only the current + " tab page + close + endif + endif + endif +endfunction + +" Tlist_Window_Init +" Set the default options for the taglist window +function! s:Tlist_Window_Init() + call s:Tlist_Log_Msg('Tlist_Window_Init()') + + " The 'readonly' option should not be set for the taglist buffer. + " If Vim is started as "view/gview" or if the ":view" command is + " used, then the 'readonly' option is set for all the buffers. + " Unset it for the taglist buffer + setlocal noreadonly + + " Set the taglist buffer filetype to taglist + setlocal filetype=taglist + + " Define taglist window element highlighting + syntax match TagListComment '^" .*' + syntax match TagListFileName '^[^" ].*$' + syntax match TagListTitle '^ \S.*$' + syntax match TagListTagScope '\s\[.\{-\}\]$' + + " Define the highlighting only if colors are supported + if has('gui_running') || &t_Co > 2 + " Colors to highlight various taglist window elements + " If user defined highlighting group exists, then use them. + " Otherwise, use default highlight groups. + if hlexists('MyTagListTagName') + highlight link TagListTagName MyTagListTagName + else + highlight default link TagListTagName Search + endif + " Colors to highlight comments and titles + if hlexists('MyTagListComment') + highlight link TagListComment MyTagListComment + else + highlight clear TagListComment + highlight default link TagListComment Comment + endif + if hlexists('MyTagListTitle') + highlight link TagListTitle MyTagListTitle + else + highlight clear TagListTitle + highlight default link TagListTitle Title + endif + if hlexists('MyTagListFileName') + highlight link TagListFileName MyTagListFileName + else + highlight clear TagListFileName + highlight default TagListFileName guibg=Grey ctermbg=darkgray + \ guifg=white ctermfg=white + endif + if hlexists('MyTagListTagScope') + highlight link TagListTagScope MyTagListTagScope + else + highlight clear TagListTagScope + highlight default link TagListTagScope Identifier + endif + else + highlight default TagListTagName term=reverse cterm=reverse + endif + + " Folding related settings + setlocal foldenable + setlocal foldminlines=0 + setlocal foldmethod=manual + setlocal foldlevel=9999 + if g:Tlist_Enable_Fold_Column + setlocal foldcolumn=3 + else + setlocal foldcolumn=0 + endif + setlocal foldtext=v:folddashes.getline(v:foldstart) + + if s:tlist_app_name != "winmanager" + " Mark buffer as scratch + silent! setlocal buftype=nofile + if s:tlist_app_name == "none" + silent! setlocal bufhidden=delete + endif + silent! setlocal noswapfile + " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted + " buffers. So if the taglist buffer is unlisted, multiple taglist + " windows will be opened. This bug is fixed in Vim 6.1 and above + if v:version >= 601 + silent! setlocal nobuflisted + endif + endif + + silent! setlocal nowrap + + " If the 'number' option is set in the source window, it will affect the + " taglist window. So forcefully disable 'number' option for the taglist + " window + silent! setlocal nonumber + + " Use fixed height when horizontally split window is used + if g:Tlist_Use_Horiz_Window + if v:version >= 602 + set winfixheight + endif + endif + if !g:Tlist_Use_Horiz_Window && v:version >= 700 + set winfixwidth + endif + + " Setup balloon evaluation to display tag prototype + if v:version >= 700 && has('balloon_eval') + setlocal balloonexpr=Tlist_Ballon_Expr() + set ballooneval + endif + + " Setup the cpoptions properly for the maps to work + let old_cpoptions = &cpoptions + set cpoptions&vim + + " Create buffer local mappings for jumping to the tags and sorting the list + nnoremap <buffer> <silent> <CR> + \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> + nnoremap <buffer> <silent> o + \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR> + nnoremap <buffer> <silent> p + \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR> + nnoremap <buffer> <silent> P + \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR> + if v:version >= 700 + nnoremap <buffer> <silent> t + \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR> + nnoremap <buffer> <silent> <C-t> + \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR> + endif + nnoremap <buffer> <silent> <2-LeftMouse> + \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> + nnoremap <buffer> <silent> s + \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR> + nnoremap <buffer> <silent> + :silent! foldopen<CR> + nnoremap <buffer> <silent> - :silent! foldclose<CR> + nnoremap <buffer> <silent> * :silent! %foldopen!<CR> + nnoremap <buffer> <silent> = :silent! %foldclose<CR> + nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR> + nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR> + nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR> + nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR> + nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR> + nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR> + nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR> + nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR> + nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR> + nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR> + nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR> + nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR> + nnoremap <buffer> <silent> q :close<CR> + + " Insert mode mappings + inoremap <buffer> <silent> <CR> + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> + " Windows needs return + inoremap <buffer> <silent> <Return> + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> + inoremap <buffer> <silent> o + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR> + inoremap <buffer> <silent> p + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR> + inoremap <buffer> <silent> P + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR> + if v:version >= 700 + inoremap <buffer> <silent> t + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR> + inoremap <buffer> <silent> <C-t> + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR> + endif + inoremap <buffer> <silent> <2-LeftMouse> + \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> + inoremap <buffer> <silent> s + \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR> + inoremap <buffer> <silent> + <C-o>:silent! foldopen<CR> + inoremap <buffer> <silent> - <C-o>:silent! foldclose<CR> + inoremap <buffer> <silent> * <C-o>:silent! %foldopen!<CR> + inoremap <buffer> <silent> = <C-o>:silent! %foldclose<CR> + inoremap <buffer> <silent> <kPlus> <C-o>:silent! foldopen<CR> + inoremap <buffer> <silent> <kMinus> <C-o>:silent! foldclose<CR> + inoremap <buffer> <silent> <kMultiply> <C-o>:silent! %foldopen!<CR> + inoremap <buffer> <silent> <Space> <C-o>:call + \ <SID>Tlist_Window_Show_Info()<CR> + inoremap <buffer> <silent> u + \ <C-o>:call <SID>Tlist_Window_Update_File()<CR> + inoremap <buffer> <silent> d <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR> + inoremap <buffer> <silent> x <C-o>:call <SID>Tlist_Window_Zoom()<CR> + inoremap <buffer> <silent> [[ <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR> + inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR> + inoremap <buffer> <silent> ]] <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR> + inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR> + inoremap <buffer> <silent> <F1> <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR> + inoremap <buffer> <silent> q <C-o>:close<CR> + + " Map single left mouse click if the user wants this functionality + if g:Tlist_Use_SingleClick == 1 + " Contributed by Bindu Wavell + " attempt to perform single click mapping, it would be much + " nicer if we could nnoremap <buffer> ... however vim does + " not fire the <buffer> <leftmouse> when you use the mouse + " to enter a buffer. + let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' . + \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' . + \ '<bar> endif <CR>' + if maparg('<leftmouse>', 'n') == '' + " no mapping for leftmouse + exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap + else + " we have a mapping + let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>' + let mapcmd = mapcmd . substitute(substitute( + \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'), + \ '\c^<leftmouse>', '', '') + let mapcmd = mapcmd . clickmap + exe mapcmd + endif + endif + + " Define the taglist autocommands + augroup TagListAutoCmds + autocmd! + " Display the tag prototype for the tag under the cursor. + autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info() + " Highlight the current tag periodically + autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag( + \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0) + + " Adjust the Vim window width when taglist window is closed + autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup() + " Close the fold for this buffer when leaving the buffer + if g:Tlist_File_Fold_Auto_Close + autocmd BufEnter * silent + \ call s:Tlist_Window_Open_File_Fold(expand('<abuf>')) + endif + " Exit Vim itself if only the taglist window is present (optional) + if g:Tlist_Exit_OnlyWindow + autocmd BufEnter __Tag_List__ nested + \ call s:Tlist_Window_Exit_Only_Window() + endif + if s:tlist_app_name != "winmanager" && + \ !g:Tlist_Process_File_Always && + \ (!has('gui_running') || !g:Tlist_Show_Menu) + " Auto refresh the taglist window + autocmd BufEnter * call s:Tlist_Refresh() + endif + + if !g:Tlist_Use_Horiz_Window + if v:version < 700 + autocmd WinEnter * call s:Tlist_Window_Check_Width() + endif + endif + if v:version >= 700 + autocmd TabEnter * silent call s:Tlist_Refresh_Folds() + endif + augroup end + + " Restore the previous cpoptions settings + let &cpoptions = old_cpoptions +endfunction + +" Tlist_Window_Refresh +" Display the tags for all the files in the taglist window +function! s:Tlist_Window_Refresh() + call s:Tlist_Log_Msg('Tlist_Window_Refresh()') + " Set report option to a huge value to prevent informational messages + " while deleting the lines + let old_report = &report + set report=99999 + + " Mark the buffer as modifiable + setlocal modifiable + + " Delete the contents of the buffer to the black-hole register + silent! %delete _ + + " As we have cleared the taglist window, mark all the files + " as not visible + let i = 0 + while i < s:tlist_file_count + let s:tlist_{i}_visible = 0 + let i = i + 1 + endwhile + + if g:Tlist_Compact_Format == 0 + " Display help in non-compact mode + call s:Tlist_Window_Display_Help() + endif + + " Mark the buffer as not modifiable + setlocal nomodifiable + + " Restore the report option + let &report = old_report + + " If the tags for only one file should be displayed in the taglist + " window, then no need to add the tags here. The bufenter autocommand + " will add the tags for that file. + if g:Tlist_Show_One_File + return + endif + + " List all the tags for the previously processed files + " Do this only if taglist is configured to display tags for more than + " one file. Otherwise, when Tlist_Show_One_File is configured, + " tags for the wrong file will be displayed. + let i = 0 + while i < s:tlist_file_count + call s:Tlist_Window_Refresh_File(s:tlist_{i}_filename, + \ s:tlist_{i}_filetype) + let i = i + 1 + endwhile + + if g:Tlist_Auto_Update + " Add and list the tags for all buffers in the Vim buffer list + let i = 1 + let last_bufnum = bufnr('$') + while i <= last_bufnum + if buflisted(i) + let fname = fnamemodify(bufname(i), ':p') + let ftype = s:Tlist_Get_Buffer_Filetype(i) + " If the file doesn't support tag listing, skip it + if !s:Tlist_Skip_File(fname, ftype) + call s:Tlist_Window_Refresh_File(fname, ftype) + endif + endif + let i = i + 1 + endwhile + endif + + " If Tlist_File_Fold_Auto_Close option is set, then close all the folds + if g:Tlist_File_Fold_Auto_Close + " Close all the folds + silent! %foldclose + endif + + " Move the cursor to the top of the taglist window + normal! gg +endfunction + +" Tlist_Post_Close_Cleanup() +" Close the taglist window and adjust the Vim window width +function! s:Tlist_Post_Close_Cleanup() + call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()') + " Mark all the files as not visible + let i = 0 + while i < s:tlist_file_count + let s:tlist_{i}_visible = 0 + let i = i + 1 + endwhile + + " Remove the taglist autocommands + silent! autocmd! TagListAutoCmds + + " Clear all the highlights + match none + + silent! syntax clear TagListTitle + silent! syntax clear TagListComment + silent! syntax clear TagListTagScope + + " Remove the left mouse click mapping if it was setup initially + if g:Tlist_Use_SingleClick + if hasmapto('<LeftMouse>') + nunmap <LeftMouse> + endif + endif + + if s:tlist_app_name != "winmanager" + if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 || + \ s:tlist_winsize_chgd != 1 || + \ &columns < (80 + g:Tlist_WinWidth) + " No need to adjust window width if using horizontally split taglist + " window or if columns is less than 101 or if the user chose not to + " adjust the window width + else + " If the user didn't manually move the window, then restore the window + " position to the pre-taglist position + if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 && + \ getwinposx() == s:tlist_winx && + \ getwinposy() == s:tlist_winy + exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy + endif + + " Adjust the Vim window width + let &columns= &columns - (g:Tlist_WinWidth + 1) + endif + endif + + let s:tlist_winsize_chgd = -1 + + " Reset taglist state variables + if s:tlist_app_name == "winmanager" + let s:tlist_app_name = "none" + endif + let s:tlist_window_initialized = 0 +endfunction + +" Tlist_Window_Refresh_File() +" List the tags defined in the specified file in a Vim window +function! s:Tlist_Window_Refresh_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')') + " First check whether the file already exists + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx != -1 + let file_listed = 1 + else + let file_listed = 0 + endif + + if !file_listed + " Check whether this file is removed based on user request + " If it is, then don't display the tags for this file + if s:Tlist_User_Removed_File(a:filename) + return + endif + endif + + if file_listed && s:tlist_{fidx}_visible + " Check whether the file tags are currently valid + if s:tlist_{fidx}_valid + " Goto the first line in the file + exe s:tlist_{fidx}_start + + " If the line is inside a fold, open the fold + if foldclosed('.') != -1 + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + endif + return + endif + + " Discard and remove the tags for this file from display + call s:Tlist_Discard_TagInfo(fidx) + call s:Tlist_Window_Remove_File_From_Display(fidx) + endif + + " Process and generate a list of tags defined in the file + if !file_listed || !s:tlist_{fidx}_valid + let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype) + if ret_fidx == -1 + return + endif + let fidx = ret_fidx + endif + + " Set report option to a huge value to prevent informational messages + " while adding lines to the taglist window + let old_report = &report + set report=99999 + + if g:Tlist_Show_One_File + " Remove the previous file + if s:tlist_cur_file_idx != -1 + call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx) + let s:tlist_{s:tlist_cur_file_idx}_visible = 0 + let s:tlist_{s:tlist_cur_file_idx}_start = 0 + let s:tlist_{s:tlist_cur_file_idx}_end = 0 + endif + let s:tlist_cur_file_idx = fidx + endif + + " Mark the buffer as modifiable + setlocal modifiable + + " Add new files to the end of the window. For existing files, add them at + " the same line where they were previously present. If the file is not + " visible, then add it at the end + if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible + if g:Tlist_Compact_Format + let s:tlist_{fidx}_start = line('$') + else + let s:tlist_{fidx}_start = line('$') + 1 + endif + endif + + let s:tlist_{fidx}_visible = 1 + + " Goto the line where this file should be placed + if g:Tlist_Compact_Format + exe s:tlist_{fidx}_start + else + exe s:tlist_{fidx}_start - 1 + endif + + let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' . + \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')' + if g:Tlist_Compact_Format == 0 + silent! put =txt + else + silent! put! =txt + " Move to the next line + exe line('.') + 1 + endif + let file_start = s:tlist_{fidx}_start + + " Add the tag names grouped by tag type to the buffer with a title + let i = 1 + let ttype_cnt = s:tlist_{a:ftype}_count + while i <= ttype_cnt + let ttype = s:tlist_{a:ftype}_{i}_name + " Add the tag type only if there are tags for that type + let fidx_ttype = 's:tlist_' . fidx . '_' . ttype + let ttype_txt = {fidx_ttype} + if ttype_txt != '' + let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname + if g:Tlist_Compact_Format == 0 + let ttype_start_lnum = line('.') + 1 + silent! put =txt + else + let ttype_start_lnum = line('.') + silent! put! =txt + endif + silent! put =ttype_txt + + let {fidx_ttype}_offset = ttype_start_lnum - file_start + + " create a fold for this tag type + let fold_start = ttype_start_lnum + let fold_end = fold_start + {fidx_ttype}_count + exe fold_start . ',' . fold_end . 'fold' + + " Adjust the cursor position + if g:Tlist_Compact_Format == 0 + exe ttype_start_lnum + {fidx_ttype}_count + else + exe ttype_start_lnum + {fidx_ttype}_count + 1 + endif + + if g:Tlist_Compact_Format == 0 + " Separate the tag types by a empty line + silent! put ='' + endif + endif + let i = i + 1 + endwhile + + if s:tlist_{fidx}_tag_count == 0 + if g:Tlist_Compact_Format == 0 + silent! put ='' + endif + endif + + let s:tlist_{fidx}_end = line('.') - 1 + + " Create a fold for the entire file + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold' + exe 'silent! ' . s:tlist_{fidx}_start . ',' . + \ s:tlist_{fidx}_end . 'foldopen!' + + " Goto the starting line for this file, + exe s:tlist_{fidx}_start + + if s:tlist_app_name == "winmanager" + " To handle a bug in the winmanager plugin, add a space at the + " last line + call setline('$', ' ') + endif + + " Mark the buffer as not modifiable + setlocal nomodifiable + + " Restore the report option + let &report = old_report + + " Update the start and end line numbers for all the files following this + " file + let start = s:tlist_{fidx}_start + " include the empty line after the last line + if g:Tlist_Compact_Format + let end = s:tlist_{fidx}_end + else + let end = s:tlist_{fidx}_end + 1 + endif + call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1) + + " Now that we have updated the taglist window, update the tags + " menu (if present) + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(1) + endif +endfunction + +" Tlist_Init_File +" Initialize the variables for a new file +function! s:Tlist_Init_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')') + " Add new files at the end of the list + let fidx = s:tlist_file_count + let s:tlist_file_count = s:tlist_file_count + 1 + " Add the new file name to the taglist list of file names + let s:tlist_file_names = s:tlist_file_names . a:filename . "\n" + + " Initialize the file variables + let s:tlist_{fidx}_filename = a:filename + let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type + let s:tlist_{fidx}_filetype = a:ftype + let s:tlist_{fidx}_mtime = -1 + let s:tlist_{fidx}_start = 0 + let s:tlist_{fidx}_end = 0 + let s:tlist_{fidx}_valid = 0 + let s:tlist_{fidx}_visible = 0 + let s:tlist_{fidx}_tag_count = 0 + let s:tlist_{fidx}_menu_cmd = '' + + " Initialize the tag type variables + let i = 1 + while i <= s:tlist_{a:ftype}_count + let ttype = s:tlist_{a:ftype}_{i}_name + let s:tlist_{fidx}_{ttype} = '' + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = 0 + let i = i + 1 + endwhile + + return fidx +endfunction + +" Tlist_Get_Tag_Type_By_Tag +" Return the tag type for the specified tag index +function! s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx) + let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type' + + " Already parsed and have the tag name + if exists(ttype_var) + return {ttype_var} + endif + + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line) + + return {ttype_var} +endfunction + +" Tlist_Get_Tag_Prototype +function! s:Tlist_Get_Tag_Prototype(fidx, tidx) + let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto' + + " Already parsed and have the tag prototype + if exists(tproto_var) + return {tproto_var} + endif + + " Parse and extract the tag prototype + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = stridx(tag_line, '/^') + 2 + let end = stridx(tag_line, '/;"' . "\t") + if tag_line[end - 1] == '$' + let end = end -1 + endif + let tag_proto = strpart(tag_line, start, end - start) + let {tproto_var} = substitute(tag_proto, '\s*', '', '') + + return {tproto_var} +endfunction + +" Tlist_Get_Tag_SearchPat +function! s:Tlist_Get_Tag_SearchPat(fidx, tidx) + let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat' + + " Already parsed and have the tag search pattern + if exists(tpat_var) + return {tpat_var} + endif + + " Parse and extract the tag search pattern + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = stridx(tag_line, '/^') + 2 + let end = stridx(tag_line, '/;"' . "\t") + if tag_line[end - 1] == '$' + let end = end -1 + endif + let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) . + \ (tag_line[end] == '$' ? '\$' : '') + + return {tpat_var} +endfunction + +" Tlist_Get_Tag_Linenum +" Return the tag line number, given the tag index +function! s:Tlist_Get_Tag_Linenum(fidx, tidx) + let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum' + + " Already parsed and have the tag line number + if exists(tline_var) + return {tline_var} + endif + + " Parse and extract the tag line number + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = strridx(tag_line, 'line:') + 5 + let end = strridx(tag_line, "\t") + if end < start + let {tline_var} = strpart(tag_line, start) + 0 + else + let {tline_var} = strpart(tag_line, start, end - start) + 0 + endif + + return {tline_var} +endfunction + +" Tlist_Parse_Tagline +" Parse a tag line from the ctags output. Separate the tag output based on the +" tag type and store it in the tag type variable. +" The format of each line in the ctags output is: +" +" tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields +" +function! s:Tlist_Parse_Tagline(tag_line) + if a:tag_line == '' + " Skip empty lines + return + endif + + " Extract the tag type + let ttype = s:Tlist_Extract_Tagtype(a:tag_line) + + " Make sure the tag type is a valid and supported one + if ttype == '' || stridx(s:ctags_flags, ttype) == -1 + " Line is not in proper tags format or Tag type is not supported + return + endif + + " Update the total tag count + let s:tidx = s:tidx + 1 + + " The following variables are used to optimize this code. Vim is slow in + " using curly brace names. To reduce the amount of processing needed, the + " curly brace variables are pre-processed here + let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx + let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype + + " Update the count of this tag type + let ttype_idx = {fidx_ttype}_count + 1 + let {fidx_ttype}_count = ttype_idx + + " Store the ctags output for this tag + let {fidx_tidx}_tag = a:tag_line + + " Store the tag index and the tag type index (back pointers) + let {fidx_ttype}_{ttype_idx} = s:tidx + let {fidx_tidx}_ttype_idx = ttype_idx + + " Extract the tag name + let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t")) + + " Extract the tag scope/prototype + if g:Tlist_Display_Prototype + let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx) + else + let ttxt = ' ' . tag_name + + " Add the tag scope, if it is available and is configured. Tag + " scope is the last field after the 'line:<num>\t' field + if g:Tlist_Display_Tag_Scope + let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line) + if tag_scope != '' + let ttxt = ttxt . ' [' . tag_scope . ']' + endif + endif + endif + + " Add this tag to the tag type variable + let {fidx_ttype} = {fidx_ttype} . ttxt . "\n" + + " Save the tag name + let {fidx_tidx}_tag_name = tag_name +endfunction + +" Tlist_Process_File +" Get the list of tags defined in the specified file and store them +" in Vim variables. Returns the file index where the tags are stored. +function! s:Tlist_Process_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' . + \ a:ftype . ')') + " Check whether this file is supported + if s:Tlist_Skip_File(a:filename, a:ftype) + return -1 + endif + + " If the tag types for this filetype are not yet created, then create + " them now + let var = 's:tlist_' . a:ftype . '_count' + if !exists(var) + if s:Tlist_FileType_Init(a:ftype) == 0 + return -1 + endif + endif + + " If this file is already processed, then use the cached values + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + " First time, this file is loaded + let fidx = s:Tlist_Init_File(a:filename, a:ftype) + else + " File was previously processed. Discard the tag information + call s:Tlist_Discard_TagInfo(fidx) + endif + + let s:tlist_{fidx}_valid = 1 + + " Exuberant ctags arguments to generate a tag list + let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks ' + + " Form the ctags argument depending on the sort type + if s:tlist_{fidx}_sort_type == 'name' + let ctags_args = ctags_args . '--sort=yes' + else + let ctags_args = ctags_args . '--sort=no' + endif + + " Add the filetype specific arguments + let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args + + " Ctags command to produce output with regexp for locating the tags + let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args + let ctags_cmd = ctags_cmd . ' "' . a:filename . '"' + + if &shellxquote == '"' + " Double-quotes within double-quotes will not work in the + " command-line.If the 'shellxquote' option is set to double-quotes, + " then escape the double-quotes in the ctags command-line. + let ctags_cmd = escape(ctags_cmd, '"') + endif + + " In Windows 95, if not using cygwin, disable the 'shellslash' + " option. Otherwise, this will cause problems when running the + " ctags command. + if has('win95') && !has('win32unix') + let old_shellslash = &shellslash + set noshellslash + endif + + if has('win32') && !has('win32unix') && !has('win95') + \ && (&shell =~ 'cmd.exe') + " Windows does not correctly deal with commands that have more than 1 + " set of double quotes. It will strip them all resulting in: + " 'C:\Program' is not recognized as an internal or external command + " operable program or batch file. To work around this, place the + " command inside a batch file and call the batch file. + " Do this only on Win2K, WinXP and above. + " Contributed by: David Fishburn. + let s:taglist_tempfile = fnamemodify(tempname(), ':h') . + \ '\taglist.cmd' + exe 'redir! > ' . s:taglist_tempfile + silent echo ctags_cmd + redir END + + call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd) + let ctags_cmd = '"' . s:taglist_tempfile . '"' + endif + + call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd) + + " Run ctags and get the tag list + let cmd_output = system(ctags_cmd) + + " Restore the value of the 'shellslash' option. + if has('win95') && !has('win32unix') + let &shellslash = old_shellslash + endif + + if exists('s:taglist_tempfile') + " Delete the temporary cmd file created on MS-Windows + call delete(s:taglist_tempfile) + endif + + " Handle errors + if v:shell_error + let msg = "Taglist: Failed to generate tags for " . a:filename + call s:Tlist_Warning_Msg(msg) + if cmd_output != '' + call s:Tlist_Warning_Msg(cmd_output) + endif + return fidx + endif + + " Store the modification time for the file + let s:tlist_{fidx}_mtime = getftime(a:filename) + + " No tags for current file + if cmd_output == '' + call s:Tlist_Log_Msg('No tags defined in ' . a:filename) + return fidx + endif + + call s:Tlist_Log_Msg('Generated tags information for ' . a:filename) + + if v:version > 601 + " The following script local variables are used by the + " Tlist_Parse_Tagline() function. + let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags + let s:fidx = fidx + let s:tidx = 0 + + " Process the ctags output one line at a time. The substitute() + " command is used to parse the tag lines instead of using the + " matchstr()/stridx()/strpart() functions for performance reason + call substitute(cmd_output, "\\([^\n]\\+\\)\n", + \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g') + + " Save the number of tags for this file + let s:tlist_{fidx}_tag_count = s:tidx + + " The following script local variables are no longer needed + unlet! s:ctags_flags + unlet! s:tidx + unlet! s:fidx + else + " Due to a bug in Vim earlier than version 6.1, + " we cannot use substitute() to parse the ctags output. + " Instead the slow str*() functions are used + let ctags_flags = s:tlist_{a:ftype}_ctags_flags + let tidx = 0 + + while cmd_output != '' + " Extract one line at a time + let idx = stridx(cmd_output, "\n") + let one_line = strpart(cmd_output, 0, idx) + " Remove the line from the tags output + let cmd_output = strpart(cmd_output, idx + 1) + + if one_line == '' + " Line is not in proper tags format + continue + endif + + " Extract the tag type + let ttype = s:Tlist_Extract_Tagtype(one_line) + + " Make sure the tag type is a valid and supported one + if ttype == '' || stridx(ctags_flags, ttype) == -1 + " Line is not in proper tags format or Tag type is not + " supported + continue + endif + + " Update the total tag count + let tidx = tidx + 1 + + " The following variables are used to optimize this code. Vim is + " slow in using curly brace names. To reduce the amount of + " processing needed, the curly brace variables are pre-processed + " here + let fidx_tidx = 's:tlist_' . fidx . '_' . tidx + let fidx_ttype = 's:tlist_' . fidx . '_' . ttype + + " Update the count of this tag type + let ttype_idx = {fidx_ttype}_count + 1 + let {fidx_ttype}_count = ttype_idx + + " Store the ctags output for this tag + let {fidx_tidx}_tag = one_line + + " Store the tag index and the tag type index (back pointers) + let {fidx_ttype}_{ttype_idx} = tidx + let {fidx_tidx}_ttype_idx = ttype_idx + + " Extract the tag name + let tag_name = strpart(one_line, 0, stridx(one_line, "\t")) + + " Extract the tag scope/prototype + if g:Tlist_Display_Prototype + let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(fidx, tidx) + else + let ttxt = ' ' . tag_name + + " Add the tag scope, if it is available and is configured. Tag + " scope is the last field after the 'line:<num>\t' field + if g:Tlist_Display_Tag_Scope + let tag_scope = s:Tlist_Extract_Tag_Scope(one_line) + if tag_scope != '' + let ttxt = ttxt . ' [' . tag_scope . ']' + endif + endif + endif + + " Add this tag to the tag type variable + let {fidx_ttype} = {fidx_ttype} . ttxt . "\n" + + " Save the tag name + let {fidx_tidx}_tag_name = tag_name + endwhile + + " Save the number of tags for this file + let s:tlist_{fidx}_tag_count = tidx + endif + + call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count . + \ ' tags in ' . a:filename) + + return fidx +endfunction + +" Tlist_Update_File +" Update the tags for a file (if needed) +function! Tlist_Update_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Update_File (' . a:filename . ')') + " If the file doesn't support tag listing, skip it + if s:Tlist_Skip_File(a:filename, a:ftype) + return + endif + + " Convert the file name to a full path + let fname = fnamemodify(a:filename, ':p') + + " First check whether the file already exists + let fidx = s:Tlist_Get_File_Index(fname) + + if fidx != -1 && s:tlist_{fidx}_valid + " File exists and the tags are valid + " Check whether the file was modified after the last tags update + " If it is modified, then update the tags + if s:tlist_{fidx}_mtime == getftime(fname) + return + endif + else + " If the tags were removed previously based on a user request, + " as we are going to update the tags (based on the user request), + " remove the filename from the deleted list + call s:Tlist_Update_Remove_List(fname, 0) + endif + + " If the taglist window is opened, update it + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + " Taglist window is not present. Just update the taglist + " and return + call s:Tlist_Process_File(fname, a:ftype) + else + if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1 + " If tags for only one file are displayed and we are not + " updating the tags for that file, then no need to + " refresh the taglist window. Otherwise, the taglist + " window should be updated. + if s:tlist_{s:tlist_cur_file_idx}_filename != fname + call s:Tlist_Process_File(fname, a:ftype) + return + endif + endif + + " Save the current window number + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + " Save the cursor position + let save_line = line('.') + let save_col = col('.') + + " Update the taglist window + call s:Tlist_Window_Refresh_File(fname, a:ftype) + + " Restore the cursor position + if v:version >= 601 + call cursor(save_line, save_col) + else + exe save_line + exe 'normal! ' . save_col . '|' + endif + + if winnr() != save_winnr + " Go back to the original window + call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w') + endif + endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(1) + endif +endfunction + +" Tlist_Window_Close +" Close the taglist window +function! s:Tlist_Window_Close() + call s:Tlist_Log_Msg('Tlist_Window_Close()') + " Make sure the taglist window exists + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Error: Taglist window is not open') + return + endif + + if winnr() == winnum + " Already in the taglist window. Close it and return + if winbufnr(2) != -1 + " If a window other than the taglist window is open, + " then only close the taglist window. + close + endif + else + " Goto the taglist window, close it and then come back to the + " original window + let curbufnr = bufnr('%') + exe winnum . 'wincmd w' + close + " Need to jump back to the original window only if we are not + " already in that window + let winnum = bufwinnr(curbufnr) + if winnr() != winnum + exe winnum . 'wincmd w' + endif + endif +endfunction + +" Tlist_Window_Mark_File_Window +" Mark the current window as the file window to use when jumping to a tag. +" Only if the current window is a non-plugin, non-preview and non-taglist +" window +function! s:Tlist_Window_Mark_File_Window() + if getbufvar('%', '&buftype') == '' && !&previewwindow + let w:tlist_file_window = "yes" + endif +endfunction + +" Tlist_Window_Open +" Open and refresh the taglist window +function! s:Tlist_Window_Open() + call s:Tlist_Log_Msg('Tlist_Window_Open()') + " If the window is open, jump to it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Jump to the existing window + if winnr() != winnum + exe winnum . 'wincmd w' + endif + return + endif + + if s:tlist_app_name == "winmanager" + " Taglist plugin is no longer part of the winmanager app + let s:tlist_app_name = "none" + endif + + " Get the filename and filetype for the specified buffer + let curbuf_name = fnamemodify(bufname('%'), ':p') + let curbuf_ftype = s:Tlist_Get_Buffer_Filetype('%') + let cur_lnum = line('.') + + " Mark the current window as the desired window to open a file when a tag + " is selected. + call s:Tlist_Window_Mark_File_Window() + + " Open the taglist window + call s:Tlist_Window_Create() + + call s:Tlist_Window_Refresh() + + if g:Tlist_Show_One_File + " Add only the current buffer and file + " + " If the file doesn't support tag listing, skip it + if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype) + call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype) + endif + endif + + if g:Tlist_File_Fold_Auto_Close + " Open the fold for the current file, as all the folds in + " the taglist window are closed + let fidx = s:Tlist_Get_File_Index(curbuf_name) + if fidx != -1 + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + endif + endif + + " Highlight the current tag + call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1) +endfunction + +" Tlist_Window_Toggle() +" Open or close a taglist window +function! s:Tlist_Window_Toggle() + call s:Tlist_Log_Msg('Tlist_Window_Toggle()') + " If taglist window is open then close it. + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + call s:Tlist_Window_Close() + return + endif + + call s:Tlist_Window_Open() + + " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not + " set + if !g:Tlist_GainFocus_On_ToggleOpen + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif +endfunction + +" Tlist_Process_Filelist +" Process multiple files. Each filename is separated by "\n" +" Returns the number of processed files +function! s:Tlist_Process_Filelist(file_names) + let flist = a:file_names + + " Enable lazy screen updates + let old_lazyredraw = &lazyredraw + set lazyredraw + + " Keep track of the number of processed files + let fcnt = 0 + + " Process one file at a time + while flist != '' + let nl_idx = stridx(flist, "\n") + let one_file = strpart(flist, 0, nl_idx) + + " Remove the filename from the list + let flist = strpart(flist, nl_idx + 1) + + if one_file == '' + continue + endif + + " Skip directories + if isdirectory(one_file) + continue + endif + + let ftype = s:Tlist_Detect_Filetype(one_file) + + echon "\r " + echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t') + + let fcnt = fcnt + 1 + + call Tlist_Update_File(one_file, ftype) + endwhile + + " Clear the displayed informational messages + echon "\r " + + " Restore the previous state + let &lazyredraw = old_lazyredraw + + return fcnt +endfunction + +" Tlist_Process_Dir +" Process the files in a directory matching the specified pattern +function! s:Tlist_Process_Dir(dir_name, pat) + let flist = glob(a:dir_name . '/' . a:pat) . "\n" + + let fcnt = s:Tlist_Process_Filelist(flist) + + let len = strlen(a:dir_name) + if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/' + let glob_expr = a:dir_name . '*' + else + let glob_expr = a:dir_name . '/*' + endif + let all_files = glob(glob_expr) . "\n" + + while all_files != '' + let nl_idx = stridx(all_files, "\n") + let one_file = strpart(all_files, 0, nl_idx) + + let all_files = strpart(all_files, nl_idx + 1) + if one_file == '' + continue + endif + + " Skip non-directory names + if !isdirectory(one_file) + continue + endif + + echon "\r " + echon "\rProcessing files in directory " . fnamemodify(one_file, ':t') + let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat) + endwhile + + return fcnt +endfunction + +" Tlist_Add_Files_Recursive +" Add files recursively from a directory +function! s:Tlist_Add_Files_Recursive(dir, ...) + let dir_name = fnamemodify(a:dir, ':p') + if !isdirectory(dir_name) + call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory') + return + endif + + if a:0 == 1 + " User specified file pattern + let pat = a:1 + else + " Default file pattern + let pat = '*' + endif + + echon "\r " + echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t') + let fcnt = s:Tlist_Process_Dir(dir_name, pat) + + echon "\rAdded " . fcnt . " files to the taglist" +endfunction + +" Tlist_Add_Files +" Add the specified list of files to the taglist +function! s:Tlist_Add_Files(...) + let flist = '' + let i = 1 + + " Get all the files matching the file patterns supplied as argument + while i <= a:0 + let flist = flist . glob(a:{i}) . "\n" + let i = i + 1 + endwhile + + if flist == '' + call s:Tlist_Warning_Msg('Error: No matching files are found') + return + endif + + let fcnt = s:Tlist_Process_Filelist(flist) + echon "\rAdded " . fcnt . " files to the taglist" +endfunction + +" Tlist_Extract_Tagtype +" Extract the tag type from the tag text +function! s:Tlist_Extract_Tagtype(tag_line) + " The tag type is after the tag prototype field. The prototype field + " ends with the /;"\t string. We add 4 at the end to skip the characters + " in this special string.. + let start = strridx(a:tag_line, '/;"' . "\t") + 4 + let end = strridx(a:tag_line, 'line:') - 1 + let ttype = strpart(a:tag_line, start, end - start) + + return ttype +endfunction + +" Tlist_Extract_Tag_Scope +" Extract the tag scope from the tag text +function! s:Tlist_Extract_Tag_Scope(tag_line) + let start = strridx(a:tag_line, 'line:') + let end = strridx(a:tag_line, "\t") + if end <= start + return '' + endif + + let tag_scope = strpart(a:tag_line, end + 1) + let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1) + + return tag_scope +endfunction + +" Tlist_Refresh() +" Refresh the taglist +function! s:Tlist_Refresh() + call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' . + \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')') + " If we are entering the buffer from one of the taglist functions, then + " no need to refresh the taglist window again. + if s:Tlist_Skip_Refresh + " We still need to update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif + return + endif + + " If part of the winmanager plugin and not configured to process + " tags always and not configured to display the tags menu, then return + if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always + \ && !g:Tlist_Show_Menu + return + endif + + " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help + if &buftype != '' + return + endif + + let filename = fnamemodify(bufname('%'), ':p') + let ftype = s:Tlist_Get_Buffer_Filetype('%') + + " If the file doesn't support tag listing, skip it + if s:Tlist_Skip_File(filename, ftype) + return + endif + + let tlist_win = bufwinnr(g:TagList_title) + + " If the taglist window is not opened and not configured to process + " tags always and not displaying the tags menu, then return + if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu + return + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 + " Check whether this file is removed based on user request + " If it is, then don't display the tags for this file + if s:Tlist_User_Removed_File(filename) + return + endif + + " If the taglist should not be auto updated, then return + if !g:Tlist_Auto_Update + return + endif + endif + + let cur_lnum = line('.') + + if fidx == -1 + " Update the tags for the file + let fidx = s:Tlist_Process_File(filename, ftype) + else + let mtime = getftime(filename) + if s:tlist_{fidx}_mtime != mtime + " Invalidate the tags listed for this file + let s:tlist_{fidx}_valid = 0 + + " Update the taglist and the window + call Tlist_Update_File(filename, ftype) + + " Store the new file modification time + let s:tlist_{fidx}_mtime = mtime + endif + endif + + " Update the taglist window + if tlist_win != -1 + " Disable screen updates + let old_lazyredraw = &lazyredraw + set nolazyredraw + + " Save the current window number + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter + " Save the cursor position + let save_line = line('.') + let save_col = col('.') + endif + + " Update the taglist window + call s:Tlist_Window_Refresh_File(filename, ftype) + + " Open the fold for the file + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + + if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag + if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx + " If displaying tags for only one file in the taglist + " window and about to display the tags for a new file, + " then center the current tag line for the new file + let center_tag_line = 1 + else + let center_tag_line = 0 + endif + + " Highlight the current tag + call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line) + else + " Restore the cursor position + if v:version >= 601 + call cursor(save_line, save_col) + else + exe save_line + exe 'normal! ' . save_col . '|' + endif + endif + + " Jump back to the original window + if save_winnr != winnr() + call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w') + endif + + " Restore screen updates + let &lazyredraw = old_lazyredraw + endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif +endfunction + +" Tlist_Change_Sort() +" Change the sort order of the tag listing +" caller == 'cmd', command used in the taglist window +" caller == 'menu', taglist menu +" action == 'toggle', toggle sort from name to order and vice versa +" action == 'set', set the sort order to sort_type +function! s:Tlist_Change_Sort(caller, action, sort_type) + call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller . + \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')') + if a:caller == 'cmd' + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + " Remove the previous highlighting + match none + elseif a:caller == 'menu' + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx == -1 + return + endif + endif + + if a:action == 'toggle' + let sort_type = s:tlist_{fidx}_sort_type + + " Toggle the sort order from 'name' to 'order' and vice versa + if sort_type == 'name' + let s:tlist_{fidx}_sort_type = 'order' + else + let s:tlist_{fidx}_sort_type = 'name' + endif + else + let s:tlist_{fidx}_sort_type = a:sort_type + endif + + " Invalidate the tags listed for this file + let s:tlist_{fidx}_valid = 0 + + if a:caller == 'cmd' + " Save the current line for later restoration + let curline = '\V\^' . getline('.') . '\$' + + call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename, + \ s:tlist_{fidx}_filetype) + + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!' + + " Go back to the cursor line before the tag list is sorted + call search(curline, 'w') + + call s:Tlist_Menu_Update_File(1) + else + call s:Tlist_Menu_Remove_File() + + call s:Tlist_Refresh() + endif +endfunction + +" Tlist_Update_Current_File() +" Update taglist for the current buffer by regenerating the tag list +" Contributed by WEN Guopeng. +function! s:Tlist_Update_Current_File() + call s:Tlist_Log_Msg('Tlist_Update_Current_File()') + if winnr() == bufwinnr(g:TagList_title) + " In the taglist window. Update the current file + call s:Tlist_Window_Update_File() + else + " Not in the taglist window. Update the current buffer + let filename = fnamemodify(bufname('%'), ':p') + let fidx = s:Tlist_Get_File_Index(filename) + if fidx != -1 + let s:tlist_{fidx}_valid = 0 + endif + let ft = s:Tlist_Get_Buffer_Filetype('%') + call Tlist_Update_File(filename, ft) + endif +endfunction + +" Tlist_Window_Update_File() +" Update the tags displayed in the taglist window +function! s:Tlist_Window_Update_File() + call s:Tlist_Log_Msg('Tlist_Window_Update_File()') + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + " Remove the previous highlighting + match none + + " Save the current line for later restoration + let curline = '\V\^' . getline('.') . '\$' + + let s:tlist_{fidx}_valid = 0 + + " Update the taglist window + call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename, + \ s:tlist_{fidx}_filetype) + + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!' + + " Go back to the tag line before the list is updated + call search(curline, 'w') +endfunction + +" Tlist_Window_Get_Tag_Type_By_Linenum() +" Return the tag type index for the specified line in the taglist window +function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum) + let ftype = s:tlist_{a:fidx}_filetype + + " Determine to which tag type the current line number belongs to using the + " tag type start line number and the number of tags in a tag type + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + let start_lnum = + \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset + let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count + if a:lnum >= start_lnum && a:lnum <= end + break + endif + let i = i + 1 + endwhile + + " Current line doesn't belong to any of the displayed tag types + if i > s:tlist_{ftype}_count + return '' + endif + + return ttype +endfunction + +" Tlist_Window_Get_Tag_Index() +" Return the tag index for the specified line in the taglist window +function! s:Tlist_Window_Get_Tag_Index(fidx, lnum) + let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum) + + " Current line doesn't belong to any of the displayed tag types + if ttype == '' + return 0 + endif + + " Compute the index into the displayed tags for the tag type + let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset + let tidx = a:lnum - ttype_lnum + if tidx == 0 + return 0 + endif + + " Get the corresponding tag line and return it + return s:tlist_{a:fidx}_{ttype}_{tidx} +endfunction + +" Tlist_Window_Highlight_Line +" Highlight the current line +function! s:Tlist_Window_Highlight_Line() + " Clear previously selected name + match none + + " Highlight the current line + if g:Tlist_Display_Prototype == 0 + let pat = '/\%' . line('.') . 'l\s\+\zs.*/' + else + let pat = '/\%' . line('.') . 'l.*/' + endif + + exe 'match TagListTagName ' . pat +endfunction + +" Tlist_Window_Open_File +" Open the specified file in either a new window or an existing window +" and place the cursor at the specified tag pattern +function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat) + call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' . + \ a:win_ctrl . ')') + let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh + let s:Tlist_Skip_Refresh = 1 + + if s:tlist_app_name == "winmanager" + " Let the winmanager edit the file + call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin') + else + + if a:win_ctrl == 'newtab' + " Create a new tab + exe 'tabnew ' . escape(a:filename, ' ') + " Open the taglist window in the new tab + call s:Tlist_Window_Open() + endif + + if a:win_ctrl == 'checktab' + " Check whether the file is present in any of the tabs. + " If the file is present in the current tab, then use the + " current tab. + if bufwinnr(a:filename) != -1 + let file_present_in_tab = 1 + let i = tabpagenr() + else + let i = 1 + let bnum = bufnr(a:filename) + let file_present_in_tab = 0 + while i <= tabpagenr('$') + if index(tabpagebuflist(i), bnum) != -1 + let file_present_in_tab = 1 + break + endif + let i += 1 + endwhile + endif + + if file_present_in_tab + " Goto the tab containing the file + exe 'tabnext ' . i + else + " Open a new tab + exe 'tabnew ' . escape(a:filename, ' ') + + " Open the taglist window + call s:Tlist_Window_Open() + endif + endif + + let winnum = -1 + if a:win_ctrl == 'prevwin' + " Open the file in the previous window, if it is usable + let cur_win = winnr() + wincmd p + if &buftype == '' && !&previewwindow + exe "edit " . escape(a:filename, ' ') + let winnum = winnr() + else + " Previous window is not usable + exe cur_win . 'wincmd w' + endif + endif + + " Goto the window containing the file. If the window is not there, open a + " new window + if winnum == -1 + let winnum = bufwinnr(a:filename) + endif + + if winnum == -1 + " Locate the previously used window for opening a file + let fwin_num = 0 + let first_usable_win = 0 + + let i = 1 + let bnum = winbufnr(i) + while bnum != -1 + if getwinvar(i, 'tlist_file_window') == 'yes' + let fwin_num = i + break + endif + if first_usable_win == 0 && + \ getbufvar(bnum, '&buftype') == '' && + \ !getwinvar(i, '&previewwindow') + " First non-taglist, non-plugin and non-preview window + let first_usable_win = i + endif + let i = i + 1 + let bnum = winbufnr(i) + endwhile + + " If a previously used window is not found, then use the first + " non-taglist window + if fwin_num == 0 + let fwin_num = first_usable_win + endif + + if fwin_num != 0 + " Jump to the file window + exe fwin_num . "wincmd w" + + " If the user asked to jump to the tag in a new window, then split + " the existing window into two. + if a:win_ctrl == 'newwin' + split + endif + exe "edit " . escape(a:filename, ' ') + else + " Open a new window + if g:Tlist_Use_Horiz_Window + exe 'leftabove split ' . escape(a:filename, ' ') + else + if winbufnr(2) == -1 + " Only the taglist window is present + if g:Tlist_Use_Right_Window + exe 'leftabove vertical split ' . + \ escape(a:filename, ' ') + else + exe 'rightbelow vertical split ' . + \ escape(a:filename, ' ') + endif + + " Go to the taglist window to change the window size to + " the user configured value + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + if g:Tlist_Use_Horiz_Window + exe 'resize ' . g:Tlist_WinHeight + else + exe 'vertical resize ' . g:Tlist_WinWidth + endif + " Go back to the file window + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + else + " A plugin or help window is also present + wincmd w + exe 'leftabove split ' . escape(a:filename, ' ') + endif + endif + endif + " Mark the window, so that it can be reused. + call s:Tlist_Window_Mark_File_Window() + else + if v:version >= 700 + " If the file is opened in more than one window, then check + " whether the last accessed window has the selected file. + " If it does, then use that window. + let lastwin_bufnum = winbufnr(winnr('#')) + if bufnr(a:filename) == lastwin_bufnum + let winnum = winnr('#') + endif + endif + exe winnum . 'wincmd w' + + " If the user asked to jump to the tag in a new window, then split the + " existing window into two. + if a:win_ctrl == 'newwin' + split + endif + endif + endif + + " Jump to the tag + if a:tagpat != '' + " Add the current cursor position to the jump list, so that user can + " jump back using the ' and ` marks. + mark ' + silent call search(a:tagpat, 'w') + + " Bring the line to the middle of the window + normal! z. + + " If the line is inside a fold, open the fold + if foldclosed('.') != -1 + .foldopen + endif + endif + + " If the user selects to preview the tag then jump back to the + " taglist window + if a:win_ctrl == 'preview' + " Go back to the taglist window + let winnum = bufwinnr(g:TagList_title) + exe winnum . 'wincmd w' + else + " If the user has selected to close the taglist window, when a + " tag is selected, close the taglist window + if g:Tlist_Close_On_Select + call s:Tlist_Window_Goto_Window() + close + + " Go back to the window displaying the selected file + let wnum = bufwinnr(a:filename) + if wnum != -1 && wnum != winnr() + call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w') + endif + endif + endif + + let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh +endfunction + +" Tlist_Window_Jump_To_Tag() +" Jump to the location of the current tag +" win_ctrl == useopen - Reuse the existing file window +" win_ctrl == newwin - Open a new window +" win_ctrl == preview - Preview the tag +" win_ctrl == prevwin - Open in previous window +" win_ctrl == newtab - Open in new tab +function! s:Tlist_Window_Jump_To_Tag(win_ctrl) + call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')') + " Do not process comment lines and empty lines + let curline = getline('.') + if curline =~ '^\s*$' || curline[0] == '"' + return + endif + + " If inside a closed fold, then use the first line of the fold + " and jump to the file. + let lnum = foldclosed('.') + if lnum == -1 + " Jump to the selected tag or file + let lnum = line('.') + else + " Open the closed fold + .foldopen! + endif + + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum) + if fidx == -1 + return + endif + + " Get the tag output for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum) + if tidx != 0 + let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx) + + " Highlight the tagline + call s:Tlist_Window_Highlight_Line() + else + " Selected a line which is not a tag name. Just edit the file + let tagpat = '' + endif + + call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat) +endfunction + +" Tlist_Window_Show_Info() +" Display information about the entry under the cursor +function! s:Tlist_Window_Show_Info() + call s:Tlist_Log_Msg('Tlist_Window_Show_Info()') + + " Clear the previously displayed line + echo + + " Do not process comment lines and empty lines + let curline = getline('.') + if curline =~ '^\s*$' || curline[0] == '"' + return + endif + + " If inside a fold, then don't display the prototype + if foldclosed('.') != -1 + return + endif + + let lnum = line('.') + + " Get the file index + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum) + if fidx == -1 + return + endif + + if lnum == s:tlist_{fidx}_start + " Cursor is on a file name + let fname = s:tlist_{fidx}_filename + if strlen(fname) > 50 + let fname = fnamemodify(fname, ':t') + endif + echo fname . ', Filetype=' . s:tlist_{fidx}_filetype . + \ ', Tag count=' . s:tlist_{fidx}_tag_count + return + endif + + " Get the tag output line for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum) + if tidx == 0 + " Cursor is on a tag type + let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum) + if ttype == '' + return + endif + + let ttype_name = '' + + let ftype = s:tlist_{fidx}_filetype + let i = 1 + while i <= s:tlist_{ftype}_count + if ttype == s:tlist_{ftype}_{i}_name + let ttype_name = s:tlist_{ftype}_{i}_fullname + break + endif + let i = i + 1 + endwhile + + echo 'Tag type=' . ttype_name . + \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count + return + endif + + " Get the tag search pattern and display it + echo s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" Tlist_Find_Nearest_Tag_Idx +" Find the tag idx nearest to the supplied line number +" Returns -1, if a tag couldn't be found for the specified line number +function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum) + let sort_type = s:tlist_{a:fidx}_sort_type + + let left = 1 + let right = s:tlist_{a:fidx}_tag_count + + if sort_type == 'order' + " Tags sorted by order, use a binary search. + " The idea behind this function is taken from the ctags.vim script (by + " Alexey Marinichev) available at the Vim online website. + + " If the current line is the less than the first tag, then no need to + " search + let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1) + + if a:linenum < first_lnum + return -1 + endif + + while left < right + let middle = (right + left + 1) / 2 + let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle) + + if middle_lnum == a:linenum + let left = middle + break + endif + + if middle_lnum > a:linenum + let right = middle - 1 + else + let left = middle + endif + endwhile + else + " Tags sorted by name, use a linear search. (contributed by Dave + " Eggum). + " Look for a tag with a line number less than or equal to the supplied + " line number. If multiple tags are found, then use the tag with the + " line number closest to the supplied line number. IOW, use the tag + " with the highest line number. + let closest_lnum = 0 + let final_left = 0 + while left <= right + let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left) + + if lnum < a:linenum && lnum > closest_lnum + let closest_lnum = lnum + let final_left = left + elseif lnum == a:linenum + let closest_lnum = lnum + let final_left = left + break + else + let left = left + 1 + endif + endwhile + if closest_lnum == 0 + return -1 + endif + if left >= right + let left = final_left + endif + endif + + return left +endfunction + +" Tlist_Window_Highlight_Tag() +" Highlight the current tag +" cntx == 1, Called by the taglist plugin itself +" cntx == 2, Forced by the user through the TlistHighlightTag command +" center = 1, move the tag line to the center of the taglist window +function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center) + " Highlight the current tag only if the user configured the + " taglist plugin to do so or if the user explictly invoked the + " command to highlight the current tag. + if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1 + return + endif + + if a:filename == '' + return + endif + + " Make sure the taglist window is present + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Error: Taglist window is not open') + return + endif + + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + return + endif + + " If the file is currently not displayed in the taglist window, then retrn + if !s:tlist_{fidx}_visible + return + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return + endif + + " Ignore all autocommands + let old_ei = &eventignore + set eventignore=all + + " Save the original window number + let org_winnr = winnr() + + if org_winnr == winnum + let in_taglist_window = 1 + else + let in_taglist_window = 0 + endif + + " Go to the taglist window + if !in_taglist_window + exe winnum . 'wincmd w' + endif + + " Clear previously selected name + match none + + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum) + if tidx == -1 + " Make sure the current tag line is visible in the taglist window. + " Calling the winline() function makes the line visible. Don't know + " of a better way to achieve this. + let lnum = line('.') + + if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end + " Move the cursor to the beginning of the file + exe s:tlist_{fidx}_start + endif + + if foldclosed('.') != -1 + .foldopen + endif + + call winline() + + if !in_taglist_window + exe org_winnr . 'wincmd w' + endif + + " Restore the autocommands + let &eventignore = old_ei + return + endif + + " Extract the tag type + let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx) + + " Compute the line number + " Start of file + Start of tag type + offset + let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset + + \ s:tlist_{fidx}_{tidx}_ttype_idx + + " Goto the line containing the tag + exe lnum + + " Open the fold + if foldclosed('.') != -1 + .foldopen + endif + + if a:center + " Move the tag line to the center of the taglist window + normal! z. + else + " Make sure the current tag line is visible in the taglist window. + " Calling the winline() function makes the line visible. Don't know + " of a better way to achieve this. + call winline() + endif + + " Highlight the tag name + call s:Tlist_Window_Highlight_Line() + + " Go back to the original window + if !in_taglist_window + exe org_winnr . 'wincmd w' + endif + + " Restore the autocommands + let &eventignore = old_ei + return +endfunction + +" Tlist_Get_Tag_Prototype_By_Line +" Get the prototype for the tag on or before the specified line number in the +" current buffer +function! Tlist_Get_Tag_Prototype_By_Line(...) + if a:0 == 0 + " Arguments are not supplied. Use the current buffer name + " and line number + let filename = bufname('%') + let linenr = line('.') + elseif a:0 == 2 + " Filename and line number are specified + let filename = a:1 + let linenr = a:2 + if linenr !~ '\d\+' + " Invalid line number + return "" + endif + else + " Sufficient arguments are not supplied + let msg = 'Usage: Tlist_Get_Tag_Prototype_By_Line <filename> ' . + \ '<line_number>' + call s:Tlist_Warning_Msg(msg) + return "" + endif + + " Expand the file to a fully qualified name + let filename = fnamemodify(filename, ':p') + if filename == '' + return "" + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 + return "" + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return "" + endif + + " Get the tag text using the line number + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 + return "" + endif + + return s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" Tlist_Get_Tagname_By_Line +" Get the tag name on or before the specified line number in the +" current buffer +function! Tlist_Get_Tagname_By_Line(...) + if a:0 == 0 + " Arguments are not supplied. Use the current buffer name + " and line number + let filename = bufname('%') + let linenr = line('.') + elseif a:0 == 2 + " Filename and line number are specified + let filename = a:1 + let linenr = a:2 + if linenr !~ '\d\+' + " Invalid line number + return "" + endif + else + " Sufficient arguments are not supplied + let msg = 'Usage: Tlist_Get_Tagname_By_Line <filename> <line_number>' + call s:Tlist_Warning_Msg(msg) + return "" + endif + + " Make sure the current file has a name + let filename = fnamemodify(filename, ':p') + if filename == '' + return "" + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 + return "" + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return "" + endif + + " Get the tag name using the line number + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 + return "" + endif + + return s:tlist_{fidx}_{tidx}_tag_name +endfunction + +" Tlist_Window_Move_To_File +" Move the cursor to the beginning of the current file or the next file +" or the previous file in the taglist window +" dir == -1, move to start of current or previous function +" dir == 1, move to start of next function +function! s:Tlist_Window_Move_To_File(dir) + if foldlevel('.') == 0 + " Cursor is on a non-folded line (it is not in any of the files) + " Move it to a folded line + if a:dir == -1 + normal! zk + else + " While moving down to the start of the next fold, + " no need to do go to the start of the next file. + normal! zj + return + endif + endif + + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + let cur_lnum = line('.') + + if a:dir == -1 + if cur_lnum > s:tlist_{fidx}_start + " Move to the beginning of the current file + exe s:tlist_{fidx}_start + return + endif + + if fidx != 0 + " Move to the beginning of the previous file + let fidx = fidx - 1 + else + " Cursor is at the first file, wrap around to the last file + let fidx = s:tlist_file_count - 1 + endif + + exe s:tlist_{fidx}_start + return + else + " Move to the beginning of the next file + let fidx = fidx + 1 + + if fidx >= s:tlist_file_count + " Cursor is at the last file, wrap around to the first file + let fidx = 0 + endif + + if s:tlist_{fidx}_start != 0 + exe s:tlist_{fidx}_start + endif + return + endif +endfunction + +" Tlist_Session_Load +" Load a taglist session (information about all the displayed files +" and the tags) from the specified file +function! s:Tlist_Session_Load(...) + if a:0 == 0 || a:1 == '' + call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>') + return + endif + + let sessionfile = a:1 + + if !filereadable(sessionfile) + let msg = 'Taglist: Error - Unable to open file ' . sessionfile + call s:Tlist_Warning_Msg(msg) + return + endif + + " Mark the current window as the file window + call s:Tlist_Window_Mark_File_Window() + + " Source the session file + exe 'source ' . sessionfile + + let new_file_count = g:tlist_file_count + unlet! g:tlist_file_count + + let i = 0 + while i < new_file_count + let ftype = g:tlist_{i}_filetype + unlet! g:tlist_{i}_filetype + + if !exists('s:tlist_' . ftype . '_count') + if s:Tlist_FileType_Init(ftype) == 0 + let i = i + 1 + continue + endif + endif + + let fname = g:tlist_{i}_filename + unlet! g:tlist_{i}_filename + + let fidx = s:Tlist_Get_File_Index(fname) + if fidx != -1 + let s:tlist_{fidx}_visible = 0 + let i = i + 1 + continue + else + " As we are loading the tags from the session file, if this + " file was previously deleted by the user, now we need to + " add it back. So remove the file from the deleted list. + call s:Tlist_Update_Remove_List(fname, 0) + endif + + let fidx = s:Tlist_Init_File(fname, ftype) + + let s:tlist_{fidx}_filename = fname + + let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type + unlet! g:tlist_{i}_sort_type + + let s:tlist_{fidx}_filetype = ftype + let s:tlist_{fidx}_mtime = getftime(fname) + + let s:tlist_{fidx}_start = 0 + let s:tlist_{fidx}_end = 0 + + let s:tlist_{fidx}_valid = 1 + + let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count + unlet! g:tlist_{i}_tag_count + + let j = 1 + while j <= s:tlist_{fidx}_tag_count + let s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag + let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name + let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx + unlet! g:tlist_{i}_{j}_tag + unlet! g:tlist_{i}_{j}_tag_name + unlet! g:tlist_{i}_{j}_ttype_idx + let j = j + 1 + endwhile + + let j = 1 + while j <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{j}_name + + if exists('g:tlist_' . i . '_' . ttype) + let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype} + unlet! g:tlist_{i}_{ttype} + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count + unlet! g:tlist_{i}_{ttype}_count + + let k = 1 + while k <= s:tlist_{fidx}_{ttype}_count + let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k} + unlet! g:tlist_{i}_{ttype}_{k} + let k = k + 1 + endwhile + else + let s:tlist_{fidx}_{ttype} = '' + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = 0 + endif + + let j = j + 1 + endwhile + + let i = i + 1 + endwhile + + " If the taglist window is open, then update it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + " Refresh the taglist window + call s:Tlist_Window_Refresh() + + " Go back to the original window + if save_winnr != winnr() + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + endif +endfunction + +" Tlist_Session_Save +" Save a taglist session (information about all the displayed files +" and the tags) into the specified file +function! s:Tlist_Session_Save(...) + if a:0 == 0 || a:1 == '' + call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>') + return + endif + + let sessionfile = a:1 + + if s:tlist_file_count == 0 + " There is nothing to save + call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.') + return + endif + + if filereadable(sessionfile) + let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?') + if ans !=? 'y' + return + endif + + echo "\n" + endif + + let old_verbose = &verbose + set verbose&vim + + exe 'redir! > ' . sessionfile + + silent! echo '" Taglist session file. This file is auto-generated.' + silent! echo '" File information' + silent! echo 'let tlist_file_count = ' . s:tlist_file_count + + let i = 0 + + while i < s:tlist_file_count + " Store information about the file + silent! echo 'let tlist_' . i . "_filename = '" . + \ s:tlist_{i}_filename . "'" + silent! echo 'let tlist_' . i . '_sort_type = "' . + \ s:tlist_{i}_sort_type . '"' + silent! echo 'let tlist_' . i . '_filetype = "' . + \ s:tlist_{i}_filetype . '"' + silent! echo 'let tlist_' . i . '_tag_count = ' . + \ s:tlist_{i}_tag_count + " Store information about all the tags + let j = 1 + while j <= s:tlist_{i}_tag_count + let txt = escape(s:tlist_{i}_{j}_tag, '"\\') + silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"' + silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' . + \ s:tlist_{i}_{j}_tag_name . '"' + silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' . + \ s:tlist_{i}_{j}_ttype_idx + let j = j + 1 + endwhile + + " Store information about all the tags grouped by their type + let ftype = s:tlist_{i}_filetype + let j = 1 + while j <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{j}_name + if s:tlist_{i}_{ttype}_count != 0 + let txt = escape(s:tlist_{i}_{ttype}, '"\') + let txt = substitute(txt, "\n", "\\\\n", 'g') + silent! echo 'let tlist_' . i . '_' . ttype . ' = "' . + \ txt . '"' + silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' . + \ s:tlist_{i}_{ttype}_count + let k = 1 + while k <= s:tlist_{i}_{ttype}_count + silent! echo 'let tlist_' . i . '_' . ttype . '_' . k . + \ ' = ' . s:tlist_{i}_{ttype}_{k} + let k = k + 1 + endwhile + endif + let j = j + 1 + endwhile + + silent! echo + + let i = i + 1 + endwhile + + redir END + + let &verbose = old_verbose +endfunction + +" Tlist_Buffer_Removed +" A buffer is removed from the Vim buffer list. Remove the tags defined +" for that file +function! s:Tlist_Buffer_Removed(filename) + call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename . ')') + + " Make sure a valid filename is supplied + if a:filename == '' + return + endif + + " Get tag list index of the specified file + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + " File not present in the taglist + return + endif + + " Remove the file from the list + call s:Tlist_Remove_File(fidx, 0) +endfunction + +" When a buffer is deleted, remove the file from the taglist +autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand('<afile>:p')) + +" Tlist_Window_Open_File_Fold +" Open the fold for the specified file and close the fold for all the +" other files +function! s:Tlist_Window_Open_File_Fold(acmd_bufnr) + call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')') + + " Make sure the taglist window is present + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open') + return + endif + + " Save the original window number + let org_winnr = winnr() + if org_winnr == winnum + let in_taglist_window = 1 + else + let in_taglist_window = 0 + endif + + if in_taglist_window + " When entering the taglist window, no need to update the folds + return + endif + + " Go to the taglist window + if !in_taglist_window + call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w') + endif + + " Close all the folds + silent! %foldclose + + " Get tag list index of the specified file + let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p') + if filereadable(fname) + let fidx = s:Tlist_Get_File_Index(fname) + if fidx != -1 + " Open the fold for the file + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen" + endif + endif + + " Go back to the original window + if !in_taglist_window + call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w') + endif +endfunction + +" Tlist_Window_Check_Auto_Open +" Open the taglist window automatically on Vim startup. +" Open the window only when files present in any of the Vim windows support +" tags. +function! s:Tlist_Window_Check_Auto_Open() + let open_window = 0 + + let i = 1 + let buf_num = winbufnr(i) + while buf_num != -1 + let filename = fnamemodify(bufname(buf_num), ':p') + let ft = s:Tlist_Get_Buffer_Filetype(buf_num) + if !s:Tlist_Skip_File(filename, ft) + let open_window = 1 + break + endif + let i = i + 1 + let buf_num = winbufnr(i) + endwhile + + if open_window + call s:Tlist_Window_Toggle() + endif +endfunction + +" Tlist_Refresh_Folds +" Remove and create the folds for all the files displayed in the taglist +" window. Used after entering a tab. If this is not done, then the folds +" are not properly created for taglist windows displayed in multiple tabs. +function! s:Tlist_Refresh_Folds() + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + return + endif + + let save_wnum = winnr() + exe winnum . 'wincmd w' + + " First remove all the existing folds + normal! zE + + " Create the folds for each in the tag list + let fidx = 0 + while fidx < s:tlist_file_count + let ftype = s:tlist_{fidx}_filetype + + " Create the folds for each tag type in a file + let j = 1 + while j <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{j}_name + if s:tlist_{fidx}_{ttype}_count + let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset + let e = s + s:tlist_{fidx}_{ttype}_count + exe s . ',' . e . 'fold' + endif + let j = j + 1 + endwhile + + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold' + exe 'silent! ' . s:tlist_{fidx}_start . ',' . + \ s:tlist_{fidx}_end . 'foldopen!' + let fidx = fidx + 1 + endwhile + + exe save_wnum . 'wincmd w' +endfunction + +function! s:Tlist_Menu_Add_Base_Menu() + call s:Tlist_Log_Msg('Adding the base menu') + + " Add the menu + anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR> + anoremenu <silent> T&ags.Sort\ menu\ by.Name + \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR> + anoremenu <silent> T&ags.Sort\ menu\ by.Order + \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR> + anoremenu T&ags.-SEP1- : + + if &mousemodel =~ 'popup' + anoremenu <silent> PopUp.T&ags.Refresh\ menu + \ :call <SID>Tlist_Menu_Refresh()<CR> + anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name + \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR> + anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order + \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR> + anoremenu PopUp.T&ags.-SEP1- : + endif +endfunction + +let s:menu_char_prefix = + \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + +" Tlist_Menu_Get_Tag_Type_Cmd +" Get the menu command for the specified tag type +" fidx - File type index +" ftype - File Type +" add_ttype_name - To add or not to add the tag type name to the menu entries +" ttype_idx - Tag type index +function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, ttype_idx) + " Curly brace variable name optimization + let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx + + let ttype = s:tlist_{ftype_ttype_idx}_name + if a:add_ttype_name + " If the tag type name contains space characters, escape it. This + " will be used to create the menu entries. + let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ') + endif + + " Curly brace variable name optimization + let fidx_ttype = a:fidx . '_' . ttype + + " Number of tag entries for this tag type + let tcnt = s:tlist_{fidx_ttype}_count + if tcnt == 0 " No entries for this tag type + return '' + endif + + let mcmd = '' + + " Create the menu items for the tags. + " Depending on the number of tags of this type, split the menu into + " multiple sub-menus, if needed. + if tcnt > g:Tlist_Max_Submenu_Items + let j = 1 + while j <= tcnt + let final_index = j + g:Tlist_Max_Submenu_Items - 1 + if final_index > tcnt + let final_index = tcnt + endif + + " Extract the first and last tag name and form the + " sub-menu name + let tidx = s:tlist_{fidx_ttype}_{j} + let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name + + let tidx = s:tlist_{fidx_ttype}_{final_index} + let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name + + " Truncate the names, if they are greater than the + " max length + let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length) + let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length) + + " Form the menu command prefix + let m_prefix = 'anoremenu <silent> T\&ags.' + if a:add_ttype_name + let m_prefix = m_prefix . ttype_fullname . '.' + endif + let m_prefix = m_prefix . first_tag . '\.\.\.' . last_tag . '.' + + " Character prefix used to number the menu items (hotkey) + let m_prefix_idx = 0 + + while j <= final_index + let tidx = s:tlist_{fidx_ttype}_{j} + + let tname = s:tlist_{a:fidx}_{tidx}_tag_name + + let mcmd = mcmd . m_prefix . '\&' . + \ s:menu_char_prefix[m_prefix_idx] . '\.' . + \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . + \ tidx . ')<CR>|' + + let m_prefix_idx = m_prefix_idx + 1 + let j = j + 1 + endwhile + endwhile + else + " Character prefix used to number the menu items (hotkey) + let m_prefix_idx = 0 + + let m_prefix = 'anoremenu <silent> T\&ags.' + if a:add_ttype_name + let m_prefix = m_prefix . ttype_fullname . '.' + endif + let j = 1 + while j <= tcnt + let tidx = s:tlist_{fidx_ttype}_{j} + + let tname = s:tlist_{a:fidx}_{tidx}_tag_name + + let mcmd = mcmd . m_prefix . '\&' . + \ s:menu_char_prefix[m_prefix_idx] . '\.' . + \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . tidx + \ . ')<CR>|' + + let m_prefix_idx = m_prefix_idx + 1 + let j = j + 1 + endwhile + endif + + return mcmd +endfunction + +" Update the taglist menu with the tags for the specified file +function! s:Tlist_Menu_File_Refresh(fidx) + call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename) + " The 'B' flag is needed in the 'cpoptions' option + let old_cpoptions = &cpoptions + set cpoptions&vim + + exe s:tlist_{a:fidx}_menu_cmd + + " Update the popup menu (if enabled) + if &mousemodel =~ 'popup' + let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.', + \ ' PopUp.T\\\&ags.', "g") + exe cmd + endif + + " The taglist menu is not empty now + let s:tlist_menu_empty = 0 + + " Restore the 'cpoptions' settings + let &cpoptions = old_cpoptions +endfunction + +" Tlist_Menu_Update_File +" Add the taglist menu +function! s:Tlist_Menu_Update_File(clear_menu) + if !has('gui_running') + " Not running in GUI mode + return + endif + + call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu) + + " Remove the tags menu + if a:clear_menu + call s:Tlist_Menu_Remove_File() + + endif + + " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help + if &buftype != '' + return + endif + + let filename = fnamemodify(bufname('%'), ':p') + let ftype = s:Tlist_Get_Buffer_Filetype('%') + + " If the file doesn't support tag listing, skip it + if s:Tlist_Skip_File(filename, ftype) + return + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 || !s:tlist_{fidx}_valid + " Check whether this file is removed based on user request + " If it is, then don't display the tags for this file + if s:Tlist_User_Removed_File(filename) + return + endif + + " Process the tags for the file + let fidx = s:Tlist_Process_File(filename, ftype) + if fidx == -1 + return + endif + endif + + let fname = escape(fnamemodify(bufname('%'), ':t'), '.') + if fname != '' + exe 'anoremenu T&ags.' . fname . ' <Nop>' + anoremenu T&ags.-SEP2- : + endif + + if !s:tlist_{fidx}_tag_count + return + endif + + if s:tlist_{fidx}_menu_cmd != '' + " Update the menu with the cached command + call s:Tlist_Menu_File_Refresh(fidx) + + return + endif + + " We are going to add entries to the tags menu, so the menu won't be + " empty + let s:tlist_menu_empty = 0 + + let cmd = '' + + " Determine whether the tag type name needs to be added to the menu + " If more than one tag type is present in the taglisting for a file, + " then the tag type name needs to be present + let add_ttype_name = -1 + let i = 1 + while i <= s:tlist_{ftype}_count && add_ttype_name < 1 + let ttype = s:tlist_{ftype}_{i}_name + if s:tlist_{fidx}_{ttype}_count + let add_ttype_name = add_ttype_name + 1 + endif + let i = i + 1 + endwhile + + " Process the tags by the tag type and get the menu command + let i = 1 + while i <= s:tlist_{ftype}_count + let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, i) + if mcmd != '' + let cmd = cmd . mcmd + endif + + let i = i + 1 + endwhile + + " Cache the menu command for reuse + let s:tlist_{fidx}_menu_cmd = cmd + + " Update the menu + call s:Tlist_Menu_File_Refresh(fidx) +endfunction + +" Tlist_Menu_Remove_File +" Remove the tags displayed in the tags menu +function! s:Tlist_Menu_Remove_File() + if !has('gui_running') || s:tlist_menu_empty + return + endif + + call s:Tlist_Log_Msg('Removing the tags menu for a file') + + " Cleanup the Tags menu + silent! unmenu T&ags + if &mousemodel =~ 'popup' + silent! unmenu PopUp.T&ags + endif + + " Add a dummy menu item to retain teared off menu + noremenu T&ags.Dummy l + + silent! unmenu! T&ags + if &mousemodel =~ 'popup' + silent! unmenu! PopUp.T&ags + endif + + call s:Tlist_Menu_Add_Base_Menu() + + " Remove the dummy menu item + unmenu T&ags.Dummy + + let s:tlist_menu_empty = 1 +endfunction + +" Tlist_Menu_Refresh +" Refresh the taglist menu +function! s:Tlist_Menu_Refresh() + call s:Tlist_Log_Msg('Refreshing the tags menu') + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx != -1 + " Invalidate the cached menu command + let s:tlist_{fidx}_menu_cmd = '' + endif + + " Update the taglist, menu and window + call s:Tlist_Update_Current_File() +endfunction + +" Tlist_Menu_Jump_To_Tag +" Jump to the selected tag +function! s:Tlist_Menu_Jump_To_Tag(tidx) + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx == -1 + return + endif + + let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx) + if tagpat == '' + return + endif + + " Add the current cursor position to the jump list, so that user can + " jump back using the ' and ` marks. + mark ' + + silent call search(tagpat, 'w') + + " Bring the line to the middle of the window + normal! z. + + " If the line is inside a fold, open the fold + if foldclosed('.') != -1 + .foldopen + endif +endfunction + +" Tlist_Menu_Init +" Initialize the taglist menu +function! s:Tlist_Menu_Init() + call s:Tlist_Menu_Add_Base_Menu() + + " Automatically add the tags defined in the current file to the menu + augroup TagListMenuCmds + autocmd! + + if !g:Tlist_Process_File_Always + autocmd BufEnter * call s:Tlist_Refresh() + endif + autocmd BufLeave * call s:Tlist_Menu_Remove_File() + augroup end + + call s:Tlist_Menu_Update_File(0) +endfunction + +" Tlist_Vim_Session_Load +" Initialize the taglist window/buffer, which is created when loading +" a Vim session file. +function! s:Tlist_Vim_Session_Load() + call s:Tlist_Log_Msg('Tlist_Vim_Session_Load') + + " Initialize the taglist window + call s:Tlist_Window_Init() + + " Refresh the taglist window + call s:Tlist_Window_Refresh() +endfunction + +" Tlist_Set_App +" Set the name of the external plugin/application to which taglist +" belongs. +" Taglist plugin is part of another plugin like cream or winmanager. +function! Tlist_Set_App(name) + if a:name == "" + return + endif + + let s:tlist_app_name = a:name +endfunction + +" Winmanager integration + +" Initialization required for integration with winmanager +function! TagList_Start() + " If current buffer is not taglist buffer, then don't proceed + if bufname('%') != '__Tag_List__' + return + endif + + call Tlist_Set_App('winmanager') + + " Get the current filename from the winmanager plugin + let bufnum = WinManagerGetLastEditedFile() + if bufnum != -1 + let filename = fnamemodify(bufname(bufnum), ':p') + let ftype = s:Tlist_Get_Buffer_Filetype(bufnum) + endif + + " Initialize the taglist window, if it is not already initialized + if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized + call s:Tlist_Window_Init() + call s:Tlist_Window_Refresh() + let s:tlist_window_initialized = 1 + endif + + " Update the taglist window + if bufnum != -1 + if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update + call s:Tlist_Window_Refresh_File(filename, ftype) + endif + endif +endfunction + +function! TagList_IsValid() + return 0 +endfunction + +function! TagList_WrapUp() + return 0 +endfunction + +" restore 'cpo' +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/plugin/tasklist.vim b/plugin/tasklist.vim new file mode 100644 index 0000000..a241533 --- /dev/null +++ b/plugin/tasklist.vim @@ -0,0 +1,375 @@ +"------------------------------------------------------------------------------ +" Name Of File: tasklist.vim +" +" Description: Vim plugin to search for a list of tokens and display a +" window with matches. +" +" Author: Juan Frias (juandfrias at gmail.com) +" +" Last Change: 2009 Apr 11 +" Version: 1.0.1 +" +" Copyright: Permission is hereby granted to use and distribute this code, +" with or without modifications, provided that this header +" is included with it. +" +" This script is to be distributed freely in the hope that it +" will be useful, but is provided 'as is' and without warranties +" as to performance of merchantability or any other warranties +" whether expressed or implied. Because of the various hardware +" and software environments into which this script may be put, +" no warranty of fitness for a particular purpose is offered. +" +" GOOD DATA PROCESSING PROCEDURE DICTATES THAT ANY SCRIPT BE +" THOROUGHLY TESTED WITH NON-CRITICAL DATA BEFORE RELYING ON IT. +" +" THE USER MUST ASSUME THE ENTIRE RISK OF USING THE SCRIPT. +" +" The author does not retain any liability on any damage caused +" through the use of this script. +" +" Install: 1. Read the section titled 'Options' +" 2. Setup any variables need in your vimrc file +" 3. Copy 'tasklist.vim' to your plugin directory. +" +" Mapped Keys: <Leader>t Display list. +" +" Usage: Start the script with the mapped key, a new window appears +" with the matches found, moving around the window will also +" update the position of the current document. +" +" The following keys are mapped to the results window: +" +" q - Quit, and restore original cursor position. +" +" e - Exit, and keep results window open note that +" movements on the result window will no longer be +" updated. +" +" <cr> - Quit and place the cursor on the selected line. +" +" Aknowledgments: Many thanks to Zhang Shuhan for taking the time to beta +" test and suggest many of the improvements and features +" found in the script. I don't think I would have +" implemented it wihout his help. Thanks! +" +"------------------------------------------------------------------------------ +" Please send me any bugs you find, so I can keep the script up to date. +"------------------------------------------------------------------------------ + +" History: {{{1 +"------------------------------------------------------------------------------ +" +" 1.00 Initial version. +" +" User Options: {{{1 +"------------------------------------------------------------------------------ +" +" <Leader>t +" This is the default key map to view the task list. +" to overwrite use something like: +" map <leader>v <Plug>TaskList +" in your vimrc file +" +" g:tlWindowPosition +" This is specifies the position of the window to be opened. By +" default it will open at on top. To overwrite use: +" let g:tlWindowPosition = 1 +" in your vimrc file, options are as follows: +" 0 = Open on top +" 1 = Open on the bottom +" +" g:tlTokenList +" This is the list of tokens to search for default is +" 'FIXME TODO XXX'. The results are groupped and displayed in the +" order that they appear. to overwrite use: +" let g:tlTokenList = ['TOKEN1', 'TOKEN2', 'TOKEN3'] +" in your vimrc file +" +" g:tlRememberPosition +" If this is set to 1 then the script will try to get back to the +" position where it last was closed. By default it will find the line +" closest to the current cursor position. +" to overwrite use: +" let g:tlRememberPosition = 1 +" in your vimrc file +" + +" Global variables: {{{1 +"------------------------------------------------------------------------------ + +" Load script once +"------------------------------------------------------------------------------ +if exists("g:loaded_tasklist") || &cp + finish +endif +let g:loaded_tasklist = 1 + +" Set where the window opens +"------------------------------------------------------------------------------ +if !exists('g:tlWindowPosition') +" 0 = Open at top + let g:tlWindowPosition = 0 +endif + +" Set the token list +"------------------------------------------------------------------------------ +if !exists('g:tlTokenList') +" default list of tokens + let g:tlTokenList = ["FIXME", "TODO", "XXX"] +endif + +" Remember position +"------------------------------------------------------------------------------ +if !exists('g:tlRememberPosition') +" 0 = Donot remember, find closest match + let g:tlRememberPosition = 0 +endif + +" Script variables: {{{1 +"------------------------------------------------------------------------------ + +" Function: Open Window {{{1 +"-------------------------------------------------------------------------- +function! s:OpenWindow(buffnr, lineno) + " Open results window and place items there. + if g:tlWindowPosition == 0 + execute 'sp -TaskList_'.a:buffnr.'-' + else + execute 'botright sp -TaskList_'.a:buffnr.'-' + endif + + let b:original_buffnr = a:buffnr + let b:original_line = a:lineno + + set noswapfile + set modifiable + normal! "zPGddgg + set fde=getline(v:lnum)[0]=='L' + set foldmethod=expr + set foldlevel=0 + normal! zR + + " Resize line if too big. + let l:hits = line("$") + if l:hits < winheight(0) + sil! exe "resize ".l:hits + endif + + " Clean up. + let @z = "" + set nomodified +endfunction + +" Function: Search file {{{1 +"-------------------------------------------------------------------------- +function! s:SearchFile(hits, word) + " Search at the beginning and keep adding them to the register + let l:match_count = 0 + normal! gg0 + let l:max = strlen(line('$')) + let l:last_match = -1 + let l:div = 0 + while search(a:word, "Wc") > 0 + let l:curr_line = line('.') + if l:last_match == l:curr_line + if l:curr_line == line('$') + break + endif + normal! j0 + continue + endif + let l:last_match = l:curr_line + if foldlevel(l:curr_line) != 0 + normal! 99zo + endif + if l:div == 0 + if a:hits != 0 + let @z = @z."\n" + endif + let l:div = 1 + endif + normal! 0 + let l:lineno = ' '.l:curr_line + let @z = @z.'Ln '.strpart(l:lineno, strlen(l:lineno) - l:max).': ' + let l:text = getline(".") + let @z = @z.strpart(l:text, stridx(l:text, a:word)) + let @z = @z."\n" + normal! $ + let l:match_count = l:match_count + 1 + endwhile + return l:match_count +endfunction + +" Function: Get line number {{{1 +"-------------------------------------------------------------------------- +function! s:LineNumber() + let l:text = getline(".") + if strpart(l:text, 0, 5) == "File:" + return 0 + endif + if strlen(l:text) == 0 + return -1 + endif + let l:num = matchstr(l:text, '[0-9]\+') + if l:num == '' + return -1 + endif + return l:num +endfunction + +" Function: Update document position {{{1 +"-------------------------------------------------------------------------- +function! s:UpdateDoc() + let l:line_hit = <sid>LineNumber() + + match none + if l:line_hit == -1 + redraw + return + endif + + let l:buffnr = b:original_buffnr + exe 'match Search /\%'.line(".").'l.*/' + if line(".") < (line("$") - (winheight(0) / 2)) + 1 + normal! zz + endif + execute bufwinnr(l:buffnr)." wincmd w" + match none + if l:line_hit == 0 + normal! 1G + else + exe "normal! ".l:line_hit."Gzz" + exe 'match Search /\%'.line(".").'l.*/' + endif + execute bufwinnr('-TaskList_'.l:buffnr.'-')." wincmd w" + redraw +endfunction + +" Function: Clean up on exit {{{1 +"-------------------------------------------------------------------------- +function! s:Exit(key) + + call <sid>UpdateDoc() + match none + + let l:original_line = b:original_line + let l:last_position = line('.') + + if a:key == -1 + nunmap <buffer> e + nunmap <buffer> q + nunmap <buffer> <cr> + execute bufwinnr(b:original_buffnr)." wincmd w" + else + bd! + endif + + let b:last_position = l:last_position + + if a:key == 0 + exe "normal! ".l:original_line."G" + endif + + match none + normal! zz + + execute "set updatetime=".s:old_updatetime +endfunction + +" Function: Check for screen update {{{1 +"-------------------------------------------------------------------------- +function! s:CheckForUpdate() + if stridx(expand("%:t"), '-TaskList_') == -1 + return + endif + if b:selected_line != line(".") + call <sid>UpdateDoc() + let b:selected_line = line(".") + endif +endfunction + +" Function: Start the search. {{{1 +"-------------------------------------------------------------------------- +function! s:TaskList() + let l:original_buffnr = bufnr('%') + let l:original_line = line(".") + + " last position + if !exists('b:last_position') + let b:last_position = 1 + endif + let l:last_position = b:last_position + + + " get file name + let @z = "File:".expand("%:p")."\n\n" + + " search file + let l:index = 0 + let l:count = 0 + let l:hits = 0 + while l:index < len(g:tlTokenList) + let l:search_word = g:tlTokenList[l:index] + let l:hits = s:SearchFile(l:hits, l:search_word) + let l:count = l:count + l:hits + let l:index = l:index + 1 + endwhile + + " Make sure we at least have one hit. + if l:count == 0 + echohl Search + echo "tasklist.vim: No task information found." + echohl None + execute 'normal! '.l:original_line.'G' + return + endif + + " display window + call s:OpenWindow(l:original_buffnr, l:original_line) + + " restore the cursor position + if g:tlRememberPosition != 0 + exec 'normal! '.l:last_position.'G' + else + normal! gg + endif + + " Map exit keys + nnoremap <buffer> <silent> q :call <sid>Exit(0)<cr> + nnoremap <buffer> <silent> <cr> :call <sid>Exit(1)<cr> + nnoremap <buffer> <silent> e :call <sid>Exit(-1)<cr> + + " Setup syntax highlight {{{ + syntax match tasklistFileDivider /^File:.*$/ + syntax match tasklistLineNumber /^Ln\s\+\d\+:/ + + highlight def link tasklistFileDivider Title + highlight def link tasklistLineNumber LineNr + highlight def link tasklistSearchWord Search + " }}} + + " Save globals and change updatetime + let b:selected_line = line(".") + let s:old_updatetime = &updatetime + set updatetime=350 + + " update the doc and hook the CheckForUpdate function. + call <sid>UpdateDoc() + au! CursorHold <buffer> nested call <sid>CheckForUpdate() + +endfunction +"}}} + +" Command +command! TaskList call s:TaskList() + +" Default key map +if !hasmapto('<Plug>TaskList') + map <unique> <Leader>T <Plug>TaskList +endif + +" Key map to Command +nnoremap <unique> <script> <Plug>TaskList :TaskList<CR> + +" vim:fdm=marker:tw=75:ff=unix: diff --git a/plugin/vcsbzr.vim b/plugin/vcsbzr.vim new file mode 100644 index 0000000..cebba31 --- /dev/null +++ b/plugin/vcsbzr.vim @@ -0,0 +1,263 @@ +" vim600: set foldmethod=marker: +" +" BZR extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2009 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandBZRExec +" This variable specifies the BZR executable. If not set, it defaults to +" 'bzr' executed from the user's executable path. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandBZRExec', 'bzr')) + " BZR is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:bzrFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke bzr suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandBZRExec', 'bzr')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the BZR executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'BZR' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'BZR VCSCommand plugin called on non-BZR item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:bzrFunctions.Identify(buffer) {{{2 +function! s:bzrFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + let l:save_bzr_log=$BZR_LOG + try + let $BZR_LOG=has("win32") || has("win95") || has("win64") || has("win16") ? "nul" : "/dev/null" + let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . fileName . '"') + finally + let $BZR_LOG=l:save_bzr_log + endtry + if(v:shell_error) + return 0 + else + return 1 + endif +endfunction + +" Function: s:bzrFunctions.Add() {{{2 +function! s:bzrFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Annotate(argList) {{{2 +function! s:bzrFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'BZRannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + normal 1G2dd + endif + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Commit(argList) {{{2 +function! s:bzrFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:bzrFunctions.Delete() {{{2 +function! s:bzrFunctions.Delete(argList) + return s:DoCommand(join(['rm'] + a:argList, ' '), 'rm', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Diff(argList) {{{2 +function! s:bzrFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, '..')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) +endfunction + +" Function: s:bzrFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository] + +function! s:bzrFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = resolve(bufname(originalBuffer)) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -S -- "' . fileName . '"') + let revision = s:VCSCommandUtility.system(s:Executable() . ' revno -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under BZR control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)')[1:2] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:bzrFunctions.Info(argList) {{{2 +function! s:bzrFunctions.Info(argList) + return s:DoCommand(join(['version-info'] + a:argList, ' '), 'version-info', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Lock(argList) {{{2 +function! s:bzrFunctions.Lock(argList) + echomsg 'bzr lock is not necessary' +endfunction + +" Function: s:bzrFunctions.Log() {{{2 +function! s:bzrFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Revert(argList) {{{2 +function! s:bzrFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:bzrFunctions.Review(argList) {{{2 +function! s:bzrFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:bzrFunctions.Status(argList) {{{2 +function! s:bzrFunctions.Status(argList) + let options = ['-S'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Unlock(argList) {{{2 +function! s:bzrFunctions.Unlock(argList) + echomsg 'bzr unlock is not necessary' +endfunction +" Function: s:bzrFunctions.Update(argList) {{{2 +function! s:bzrFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Annotate setting {{{2 +let s:bzrFunctions.AnnotateSplitRegex = '^[^|]\+ | ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('BZR', expand('<sfile>'), s:bzrFunctions, []) + +let &cpo = s:save_cpo diff --git a/plugin/vcscommand.vim b/plugin/vcscommand.vim new file mode 100644 index 0000000..f505d9e --- /dev/null +++ b/plugin/vcscommand.vim @@ -0,0 +1,1397 @@ +" vim600: set foldmethod=marker: +" +" Vim plugin to assist in working with files under control of various Version +" Control Systems, such as CVS, SVN, SVK, and git. +" +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2008 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Provides functions to invoke various source control commands on the current +" file (either the current buffer, or, in the case of an directory buffer, the +" directory and all subdirectories associated with the current buffer). The +" output of the commands is captured in a new scratch window. +" +" This plugin needs additional extension plugins, each specific to a source +" control system, to function. Several options include the name of the +" version control system in the option name. Such options use the placeholder +" text '{VCSType}', which would be replaced in actual usage with 'CVS' or +" 'SVN', for instance. +" +" Command documentation {{{2 +" +" VCSAdd Adds the current file to source control. +" +" VCSAnnotate[!] Displays the current file with each line annotated with the +" version in which it was most recently changed. If an +" argument is given, the argument is used as a revision +" number to display. If not given an argument, it uses the +" most recent version of the file on the current branch. +" Additionally, if the current buffer is a VCSAnnotate buffer +" already, the version number on the current line is used. +" +" If '!' is used, the view of the annotated buffer is split +" so that the annotation is in a separate window from the +" content, and each is highlighted separately. +" +" VCSBlame Alias for 'VCSAnnotate'. +" +" VCSCommit[!] Commits changes to the current file to source control. +" +" If called with arguments, the arguments are the log message. +" +" If '!' is used, an empty log message is committed. +" +" If called with no arguments, this is a two-step command. +" The first step opens a buffer to accept a log message. +" When that buffer is written, it is automatically closed and +" the file is committed using the information from that log +" message. The commit can be abandoned if the log message +" buffer is deleted or wiped before being written. +" +" VCSDelete Deletes the current file and removes it from source control. +" +" VCSDiff With no arguments, this displays the differences between +" the current file and its parent version under source +" control in a new scratch buffer. +" +" With one argument, the diff is performed on the +" current file against the specified revision. +" +" With two arguments, the diff is performed between the +" specified revisions of the current file. +" +" This command uses the 'VCSCommand{VCSType}DiffOpt' variable +" to specify diff options. If that variable does not exist, +" a plugin-specific default is used. If you wish to have no +" options, then set it to the empty string. +" +" VCSGotoOriginal Jumps to the source buffer if the current buffer is a VCS +" scratch buffer. If VCSGotoOriginal[!] is used, remove all +" VCS scratch buffers associated with the original file. +" +" VCSInfo Displays extended information about the current file in a +" new scratch buffer. +" +" VCSLock Locks the current file in order to prevent other users from +" concurrently modifying it. The exact semantics of this +" command depend on the underlying VCS. +" +" VCSLog Displays the version history of the current file in a new +" scratch buffer. +" +" VCSRemove Alias for 'VCSDelete'. +" +" VCSRevert Replaces the modified version of the current file with the +" most recent version from the repository. +" +" VCSReview Displays a particular version of the current file in a new +" scratch buffer. If no argument is given, the most recent +" version of the file on the current branch is retrieved. +" +" VCSStatus Displays versioning information about the current file in a +" new scratch buffer. +" +" VCSUnlock Unlocks the current file in order to allow other users from +" concurrently modifying it. The exact semantics of this +" command depend on the underlying VCS. +" +" VCSUpdate Updates the current file with any relevant changes from the +" repository. +" +" VCSVimDiff Uses vimdiff to display differences between versions of the +" current file. +" +" If no revision is specified, the most recent version of the +" file on the current branch is used. With one argument, +" that argument is used as the revision as above. With two +" arguments, the differences between the two revisions is +" displayed using vimdiff. +" +" With either zero or one argument, the original buffer is +" used to perform the vimdiff. When the scratch buffer is +" closed, the original buffer will be returned to normal +" mode. +" +" Once vimdiff mode is started using the above methods, +" additional vimdiff buffers may be added by passing a single +" version argument to the command. There may be up to 4 +" vimdiff buffers total. +" +" Using the 2-argument form of the command resets the vimdiff +" to only those 2 versions. Additionally, invoking the +" command on a different file will close the previous vimdiff +" buffers. +" +" Mapping documentation: {{{2 +" +" By default, a mapping is defined for each command. User-provided mappings +" can be used instead by mapping to <Plug>CommandName, for instance: +" +" nmap ,ca <Plug>VCSAdd +" +" The default mappings are as follow: +" +" <Leader>ca VCSAdd +" <Leader>cn VCSAnnotate +" <Leader>cN VCSAnnotate! +" <Leader>cc VCSCommit +" <Leader>cD VCSDelete +" <Leader>cd VCSDiff +" <Leader>cg VCSGotoOriginal +" <Leader>cG VCSGotoOriginal! +" <Leader>ci VCSInfo +" <Leader>cl VCSLog +" <Leader>cL VCSLock +" <Leader>cr VCSReview +" <Leader>cs VCSStatus +" <Leader>cu VCSUpdate +" <Leader>cU VCSUnlock +" <Leader>cv VCSVimDiff +" +" Options documentation: {{{2 +" +" Several variables are checked by the script to determine behavior as follow: +" +" VCSCommandCommitOnWrite +" This variable, if set to a non-zero value, causes the pending commit to +" take place immediately as soon as the log message buffer is written. If +" set to zero, only the VCSCommit mapping will cause the pending commit to +" occur. If not set, it defaults to 1. +" +" VCSCommandDeleteOnHide +" This variable, if set to a non-zero value, causes the temporary VCS result +" buffers to automatically delete themselves when hidden. +" +" VCSCommand{VCSType}DiffOpt +" This variable, if set, determines the options passed to the diff command +" of the underlying VCS. Each VCS plugin defines a default value. +" +" VCSCommandDiffSplit +" This variable overrides the VCSCommandSplit variable, but only for buffers +" created with VCSVimDiff. +" +" VCSCommandDisableAll +" This variable, if set, prevents the plugin or any extensions from loading +" at all. This is useful when a single runtime distribution is used on +" multiple systems with varying versions. +" +" VCSCommandDisableMappings +" This variable, if set to a non-zero value, prevents the default command +" mappings from being set. +" +" VCSCommandDisableExtensionMappings +" This variable, if set to a non-zero value, prevents the default command +" mappings from being set for commands specific to an individual VCS. +" +" VCSCommandEdit +" This variable controls whether to split the current window to display a +" scratch buffer ('split'), or to display it in the current buffer ('edit'). +" If not set, it defaults to 'split'. +" +" VCSCommandEnableBufferSetup +" This variable, if set to a non-zero value, activates VCS buffer management +" mode. This mode means that the buffer variable 'VCSRevision' is set if +" the file is VCS-controlled. This is useful for displaying version +" information in the status bar. Additional options may be set by +" individual VCS plugins. +" +" VCSCommandMappings +" This variable, if set, overrides the default mappings used for shortcuts. +" It should be a List of 2-element Lists, each containing a shortcut and +" function name pair. +" +" VCSCommandMapPrefix +" This variable, if set, overrides the default mapping prefix ('<Leader>c'). +" This allows customization of the mapping space used by the vcscommand +" shortcuts. +" +" VCSCommandResultBufferNameExtension +" This variable, if set to a non-blank value, is appended to the name of the +" VCS command output buffers. For example, '.vcs'. Using this option may +" help avoid problems caused by autocommands dependent on file extension. +" +" VCSCommandResultBufferNameFunction +" This variable, if set, specifies a custom function for naming VCS command +" output buffers. This function will be passed the following arguments: +" +" command - name of the VCS command being executed (such as 'Log' or +" 'Diff'). +" +" originalBuffer - buffer number of the source file. +" +" vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN'). +" +" statusText - extra text associated with the VCS action (such as version +" numbers). +" +" VCSCommandSplit +" This variable controls the orientation of the various window splits that +" may occur (such as with VCSVimDiff, when using a VCS command on a VCS +" command buffer, or when the 'VCSCommandEdit' variable is set to 'split'. +" If set to 'horizontal', the resulting windows will be on stacked on top of +" one another. If set to 'vertical', the resulting windows will be +" side-by-side. If not set, it defaults to 'horizontal' for all but +" VCSVimDiff windows. +" +" VCSCommandVCSTypeOverride +" This variable allows the VCS type detection to be overridden on a +" path-by-path basis. The value of this variable is expected to be a List +" of Lists. Each high-level List item is a List containing two elements. +" The first element is a regular expression that will be matched against the +" full file name of a given buffer. If it matches, the second element will +" be used as the VCS type. +" +" Event documentation {{{2 +" For additional customization, VCSCommand.vim uses User event autocommand +" hooks. Each event is in the VCSCommand group, and different patterns +" match the various hooks. +" +" For instance, the following could be added to the vimrc to provide a 'q' +" mapping to quit a VCS scratch buffer: +" +" augroup VCSCommand +" au VCSCommand User VCSBufferCreated silent! nmap <unique> <buffer> q :bwipeout<cr> +" augroup END +" +" The following hooks are available: +" +" VCSBufferCreated This event is fired just after a VCS command +" output buffer is created. It is executed +" within the context of the new buffer. +" +" VCSBufferSetup This event is fired just after VCS buffer setup +" occurs, if enabled. +" +" VCSPluginInit This event is fired when the VCSCommand plugin +" first loads. +" +" VCSPluginFinish This event is fired just after the VCSCommand +" plugin loads. +" +" VCSVimDiffFinish This event is fired just after the VCSVimDiff +" command executes to allow customization of, +" for instance, window placement and focus. +" +" Section: Plugin header {{{1 + +" loaded_VCSCommand is set to 1 when the initialization begins, and 2 when it +" completes. This allows various actions to only be taken by functions after +" system initialization. + +if exists('VCSCommandDisableAll') + finish +endif + +if exists('loaded_VCSCommand') + finish +endif +let loaded_VCSCommand = 1 + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Event group setup {{{1 + +augroup VCSCommand +augroup END + +augroup VCSCommandCommit +augroup END + +" Section: Plugin initialization {{{1 +silent do VCSCommand User VCSPluginInit + +" Section: Constants declaration {{{1 + +let g:VCSCOMMAND_IDENTIFY_EXACT = 1 +let g:VCSCOMMAND_IDENTIFY_INEXACT = -1 + +" Section: Script variable initialization {{{1 + +" Hidden functions for use by extensions +let s:VCSCommandUtility = {} + +" plugin-specific information: {vcs -> [script, {command -> function}, {key -> mapping}]} +let s:plugins = {} + +" temporary values of overridden configuration variables +let s:optionOverrides = {} + +" state flag used to vary behavior of certain automated actions +let s:isEditFileRunning = 0 + +" commands needed to restore diff buffers to their original state +unlet! s:vimDiffRestoreCmd + +" original buffer currently reflected in vimdiff windows +unlet! s:vimDiffSourceBuffer + +" +unlet! s:vimDiffScratchList + +" Section: Utility functions {{{1 + +" Function: s:ReportError(mapping) {{{2 +" Displays the given error in a consistent faction. This is intended to be +" invoked from a catch statement. + +function! s:ReportError(error) + echohl WarningMsg|echomsg 'VCSCommand: ' . a:error|echohl None +endfunction + +" Function s:VCSCommandUtility.system(...) {{{2 +" Replacement for system() function. This version protects the quoting in the +" command line on Windows systems. + +function! s:VCSCommandUtility.system(...) + if (has("win32") || has("win64")) && &sxq !~ '"' + let save_sxq = &sxq + set sxq=\" + endif + try + return call('system', a:000) + finally + if exists("save_sxq") + let &sxq = save_sxq + endif + endtry +endfunction + +" Function: s:CreateMapping(shortcut, expansion, display) {{{2 +" Creates the given mapping by prepending the contents of +" 'VCSCommandMapPrefix' (by default '<Leader>c') to the given shortcut and +" mapping it to the given plugin function. If a mapping exists for the +" specified shortcut + prefix, emit an error but continue. If a mapping +" exists for the specified function, do nothing. + +function! s:CreateMapping(shortcut, expansion, display) + let lhs = VCSCommandGetOption('VCSCommandMapPrefix', '<Leader>c') . a:shortcut + if !hasmapto(a:expansion) + try + execute 'nmap <silent> <unique>' lhs a:expansion + catch /^Vim(.*):E227:/ + if(&verbose != 0) + echohl WarningMsg|echomsg 'VCSCommand: mapping ''' . lhs . ''' already exists, refusing to overwrite. The mapping for ' . a:display . ' will not be available.'|echohl None + endif + endtry + endif +endfunction + +" Function: s:ExecuteExtensionMapping(mapping) {{{2 +" Invokes the appropriate extension mapping depending on the type of the +" current buffer. + +function! s:ExecuteExtensionMapping(mapping) + let buffer = bufnr('%') + let vcsType = VCSCommandGetVCSType(buffer) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + if !has_key(s:plugins[vcsType][2], a:mapping) + throw 'This extended mapping is not defined for ' . vcsType + endif + silent execute 'normal' ':' . s:plugins[vcsType][2][a:mapping] . "\<CR>" +endfunction + +" Function: s:ExecuteVCSCommand(command, argList) {{{2 +" Calls the indicated plugin-specific VCS command on the current buffer. +" Returns: buffer number of resulting output scratch buffer, or -1 if an error +" occurs. + +function! s:ExecuteVCSCommand(command, argList) + try + let buffer = bufnr('%') + + let vcsType = VCSCommandGetVCSType(buffer) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(buffer) + let bufferName = bufname(originalBuffer) + + " It is already known that the directory is under VCS control. No further + " checks are needed. Otherwise, perform some basic sanity checks to avoid + " VCS-specific error messages from confusing things. + if !isdirectory(bufferName) + if !filereadable(bufferName) + throw 'No such file ' . bufferName + endif + endif + + let functionMap = s:plugins[vcsType][1] + if !has_key(functionMap, a:command) + throw 'Command ''' . a:command . ''' not implemented for ' . vcsType + endif + return functionMap[a:command](a:argList) + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Function: s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText) {{{2 +" Default method of generating the name for VCS result buffers. This can be +" overridden with the VCSResultBufferNameFunction variable. + +function! s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText) + let fileName = bufname(a:originalBuffer) + let bufferName = a:vcsType . ' ' . a:command + if strlen(a:statusText) > 0 + let bufferName .= ' ' . a:statusText + endif + let bufferName .= ' ' . fileName + let counter = 0 + let versionedBufferName = bufferName + while buflisted(versionedBufferName) + let counter += 1 + let versionedBufferName = bufferName . ' (' . counter . ')' + endwhile + return versionedBufferName +endfunction + +" Function: s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText) {{{2 +" Method of generating the name for VCS result buffers that uses the original +" file name with the VCS type and command appended as extensions. + +function! s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText) + let fileName = bufname(a:originalBuffer) + let bufferName = a:vcsType . ' ' . a:command + if strlen(a:statusText) > 0 + let bufferName .= ' ' . a:statusText + endif + let bufferName .= ' ' . fileName . VCSCommandGetOption('VCSCommandResultBufferNameExtension', '.vcs') + let counter = 0 + let versionedBufferName = bufferName + while buflisted(versionedBufferName) + let counter += 1 + let versionedBufferName = '(' . counter . ') ' . bufferName + endwhile + return versionedBufferName +endfunction + +" Function: s:EditFile(command, originalBuffer, statusText) {{{2 +" Creates a new buffer of the given name and associates it with the given +" original buffer. + +function! s:EditFile(command, originalBuffer, statusText) + let vcsType = getbufvar(a:originalBuffer, 'VCSCommandVCSType') + + " Protect against useless buffer set-up + let s:isEditFileRunning += 1 + try + let editCommand = VCSCommandGetOption('VCSCommandEdit', 'split') + if editCommand == 'split' + if VCSCommandGetOption('VCSCommandSplit', 'horizontal') == 'horizontal' + rightbelow split + else + vert rightbelow split + endif + endif + + enew + + call s:SetupScratchBuffer(a:command, vcsType, a:originalBuffer, a:statusText) + + finally + let s:isEditFileRunning -= 1 + endtry +endfunction + +" Function: s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) {{{2 +" Creates convenience buffer variables and the name of a vcscommand result +" buffer. + +function! s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) + let nameExtension = VCSCommandGetOption('VCSCommandResultBufferNameExtension', '') + if nameExtension == '' + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferName') + else + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferNameWithExtension') + endif + + let name = call(nameFunction, [a:command, a:originalBuffer, a:vcsType, a:statusText]) + + let b:VCSCommandCommand = a:command + let b:VCSCommandOriginalBuffer = a:originalBuffer + let b:VCSCommandSourceFile = bufname(a:originalBuffer) + let b:VCSCommandVCSType = a:vcsType + if a:statusText != '' + let b:VCSCommandStatusText = a:statusText + endif + + setlocal buftype=nofile + setlocal noswapfile + let &filetype = tolower(a:vcsType . a:command) + + if VCSCommandGetOption('VCSCommandDeleteOnHide', 0) + setlocal bufhidden=delete + endif + silent noautocmd file `=name` +endfunction + +" Function: s:SetupBuffer() {{{2 +" Attempts to set the b:VCSCommandBufferInfo variable + +function! s:SetupBuffer() + if (exists('b:VCSCommandBufferSetup') && b:VCSCommandBufferSetup) + " This buffer is already set up. + return + endif + + if !isdirectory(@%) && (strlen(&buftype) > 0 || !filereadable(@%)) + " No special status for special buffers other than directory buffers. + return + endif + + if !VCSCommandGetOption('VCSCommandEnableBufferSetup', 0) || s:isEditFileRunning > 0 + unlet! b:VCSCommandBufferSetup + return + endif + + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + let b:VCSCommandBufferInfo = s:plugins[vcsType][1].GetBufferInfo() + silent do VCSCommand User VCSBufferSetup + catch /No suitable plugin/ + " This is not a VCS-controlled file. + let b:VCSCommandBufferInfo = [] + endtry + + let b:VCSCommandBufferSetup = 1 +endfunction + +" Function: s:MarkOrigBufferForSetup(buffer) {{{2 +" Resets the buffer setup state of the original buffer for a given VCS scratch +" buffer. +" Returns: The VCS buffer number in a passthrough mode. + +function! s:MarkOrigBufferForSetup(buffer) + checktime + if a:buffer > 0 + let origBuffer = VCSCommandGetOriginalBuffer(a:buffer) + " This should never not work, but I'm paranoid + if origBuffer != a:buffer + call setbufvar(origBuffer, 'VCSCommandBufferSetup', 0) + endif + endif + return a:buffer +endfunction + +" Function: s:OverrideOption(option, [value]) {{{2 +" Provides a temporary override for the given VCS option. If no value is +" passed, the override is disabled. + +function! s:OverrideOption(option, ...) + if a:0 == 0 + call remove(s:optionOverrides[a:option], -1) + else + if !has_key(s:optionOverrides, a:option) + let s:optionOverrides[a:option] = [] + endif + call add(s:optionOverrides[a:option], a:1) + endif +endfunction + +" Function: s:WipeoutCommandBuffers() {{{2 +" Clears all current VCS output buffers of the specified type for a given source. + +function! s:WipeoutCommandBuffers(originalBuffer, VCSCommand) + let buffer = 1 + while buffer <= bufnr('$') + if getbufvar(buffer, 'VCSCommandOriginalBuffer') == a:originalBuffer + if getbufvar(buffer, 'VCSCommandCommand') == a:VCSCommand + execute 'bw' buffer + endif + endif + let buffer = buffer + 1 + endwhile +endfunction + +" Function: s:VimDiffRestore(vimDiffBuff) {{{2 +" Checks whether the given buffer is one whose deletion should trigger +" restoration of an original buffer after it was diffed. If so, it executes +" the appropriate setting command stored with that original buffer. + +function! s:VimDiffRestore(vimDiffBuff) + let s:isEditFileRunning += 1 + try + if exists('s:vimDiffSourceBuffer') + if a:vimDiffBuff == s:vimDiffSourceBuffer + " Original file is being removed. + unlet! s:vimDiffSourceBuffer + unlet! s:vimDiffRestoreCmd + unlet! s:vimDiffScratchList + else + let index = index(s:vimDiffScratchList, a:vimDiffBuff) + if index >= 0 + call remove(s:vimDiffScratchList, index) + if len(s:vimDiffScratchList) == 0 + if exists('s:vimDiffRestoreCmd') + " All scratch buffers are gone, reset the original. + " Only restore if the source buffer is still in Diff mode + + let sourceWinNR = bufwinnr(s:vimDiffSourceBuffer) + if sourceWinNR != -1 + " The buffer is visible in at least one window + let currentWinNR = winnr() + while winbufnr(sourceWinNR) != -1 + if winbufnr(sourceWinNR) == s:vimDiffSourceBuffer + execute sourceWinNR . 'wincmd w' + if getwinvar(0, '&diff') + execute s:vimDiffRestoreCmd + endif + endif + let sourceWinNR = sourceWinNR + 1 + endwhile + execute currentWinNR . 'wincmd w' + else + " The buffer is hidden. It must be visible in order to set the + " diff option. + let currentBufNR = bufnr('') + execute 'hide buffer' s:vimDiffSourceBuffer + if getwinvar(0, '&diff') + execute s:vimDiffRestoreCmd + endif + execute 'hide buffer' currentBufNR + endif + + unlet s:vimDiffRestoreCmd + endif + " All buffers are gone. + unlet s:vimDiffSourceBuffer + unlet s:vimDiffScratchList + endif + endif + endif + endif + finally + let s:isEditFileRunning -= 1 + endtry +endfunction + +" Section: Generic VCS command functions {{{1 + +" Function: s:VCSAnnotate(...) {{{2 +function! s:VCSAnnotate(bang, ...) + try + let line = line('.') + let currentBuffer = bufnr('%') + let originalBuffer = VCSCommandGetOriginalBuffer(currentBuffer) + + let annotateBuffer = s:ExecuteVCSCommand('Annotate', a:000) + if annotateBuffer == -1 + return -1 + endif + if a:bang == '!' && VCSCommandGetOption('VCSCommandDisableSplitAnnotate', 0) == 0 + let vcsType = VCSCommandGetVCSType(annotateBuffer) + let functionMap = s:plugins[vcsType][1] + let splitRegex = '' + if has_key(s:plugins[vcsType][1], 'AnnotateSplitRegex') + let splitRegex = s:plugins[vcsType][1]['AnnotateSplitRegex'] + endif + let splitRegex = VCSCommandGetOption('VCSCommand' . vcsType . 'AnnotateSplitRegex', splitRegex) + if splitRegex == '' + return annotateBuffer + endif + let originalFileType = getbufvar(originalBuffer, '&ft') + let annotateFileType = getbufvar(annotateBuffer, '&ft') + execute "normal 0zR\<c-v>G/" . splitRegex . "/e\<cr>d" + call setbufvar('%', '&filetype', getbufvar(originalBuffer, '&filetype')) + set scrollbind + leftabove vert new + normal 0P + execute "normal" . col('$') . "\<c-w>|" + call s:SetupScratchBuffer('annotate', vcsType, originalBuffer, 'header') + wincmd l + endif + + if currentBuffer == originalBuffer + " Starting from the original source buffer, so the + " current line is relevant. + if a:0 == 0 + " No argument list means that we're annotating + " the current version, so jumping to the same + " line is the expected action. + execute "normal" line . 'G' + if has('folding') + " The execution of the buffer created autocommand + " re-folds the buffer. Display the current line + " unfolded. + normal zv + endif + endif + endif + + return annotateBuffer + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Function: s:VCSCommit() {{{2 +function! s:VCSCommit(bang, message) + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + + " Handle the commit message being specified. If a message is supplied, it + " is used; if bang is supplied, an empty message is used; otherwise, the + " user is provided a buffer from which to edit the commit message. + + if strlen(a:message) > 0 || a:bang == '!' + return s:VCSFinishCommit([a:message], originalBuffer) + endif + + call s:EditFile('commitlog', originalBuffer, '') + setlocal ft=vcscommit + + " Create a commit mapping. + + nnoremap <silent> <buffer> <Plug>VCSCommit :call <SID>VCSFinishCommitWithBuffer()<CR> + + silent 0put ='VCS: ----------------------------------------------------------------------' + silent put ='VCS: Please enter log message. Lines beginning with ''VCS:'' are removed automatically.' + silent put ='VCS: To finish the commit, Type <leader>cc (or your own <Plug>VCSCommit mapping)' + + if VCSCommandGetOption('VCSCommandCommitOnWrite', 1) == 1 + setlocal buftype=acwrite + au VCSCommandCommit BufWriteCmd <buffer> call s:VCSFinishCommitWithBuffer() + silent put ='VCS: or write this buffer' + endif + + silent put ='VCS: ----------------------------------------------------------------------' + $ + setlocal nomodified + silent do VCSCommand User VCSBufferCreated + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Function: s:VCSFinishCommitWithBuffer() {{{2 +" Wrapper for s:VCSFinishCommit which is called only from a commit log buffer +" which removes all lines starting with 'VCS:'. + +function! s:VCSFinishCommitWithBuffer() + setlocal nomodified + let currentBuffer = bufnr('%') + let logMessageList = getbufline('%', 1, '$') + call filter(logMessageList, 'v:val !~ ''^\s*VCS:''') + let resultBuffer = s:VCSFinishCommit(logMessageList, b:VCSCommandOriginalBuffer) + if resultBuffer >= 0 + execute 'bw' currentBuffer + endif + return resultBuffer +endfunction + +" Function: s:VCSFinishCommit(logMessageList, originalBuffer) {{{2 +function! s:VCSFinishCommit(logMessageList, originalBuffer) + let messageFileName = tempname() + call writefile(a:logMessageList, messageFileName) + try + let resultBuffer = s:ExecuteVCSCommand('Commit', [messageFileName]) + if resultBuffer < 0 + return resultBuffer + endif + return s:MarkOrigBufferForSetup(resultBuffer) + finally + call delete(messageFileName) + endtry +endfunction + +" Function: s:VCSGotoOriginal(bang) {{{2 +function! s:VCSGotoOriginal(bang) + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + if originalBuffer > 0 + let origWinNR = bufwinnr(originalBuffer) + if origWinNR == -1 + execute 'buffer' originalBuffer + else + execute origWinNR . 'wincmd w' + endif + if a:bang == '!' + let buffnr = 1 + let buffmaxnr = bufnr('$') + while buffnr <= buffmaxnr + if getbufvar(buffnr, 'VCSCommandOriginalBuffer') == originalBuffer + execute 'bw' buffnr + endif + let buffnr = buffnr + 1 + endwhile + endif + endif +endfunction + +function! s:VCSDiff(...) "{{{2 + let resultBuffer = s:ExecuteVCSCommand('Diff', a:000) + if resultBuffer > 0 + let &filetype = 'diff' + elseif resultBuffer == 0 + echomsg 'No differences found' + endif + return resultBuffer +endfunction + +function! s:VCSReview(...) "{{{2 + let resultBuffer = s:ExecuteVCSCommand('Review', a:000) + if resultBuffer > 0 + let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:VCSVimDiff(...) {{{2 +function! s:VCSVimDiff(...) + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let s:isEditFileRunning = s:isEditFileRunning + 1 + try + " If there's already a VimDiff'ed window, restore it. + " There may only be one VCSVimDiff original window at a time. + + if exists('s:vimDiffSourceBuffer') && s:vimDiffSourceBuffer != originalBuffer + " Clear the existing vimdiff setup by removing the result buffers. + call s:WipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') + endif + + let orientation = &diffopt =~ 'horizontal' ? 'horizontal' : 'vertical' + let orientation = VCSCommandGetOption('VCSCommandSplit', orientation) + let orientation = VCSCommandGetOption('VCSCommandDiffSplit', orientation) + + " Split and diff + if(a:0 == 2) + " Reset the vimdiff system, as 2 explicit versions were provided. + if exists('s:vimDiffSourceBuffer') + call s:WipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') + endif + let resultBuffer = s:VCSReview(a:1) + if resultBuffer < 0 + echomsg 'Can''t open revision ' . a:1 + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + let s:vimDiffScratchList = [resultBuffer] + " If no split method is defined, cheat, and set it to vertical. + try + call s:OverrideOption('VCSCommandSplit', orientation) + let resultBuffer = s:VCSReview(a:2) + finally + call s:OverrideOption('VCSCommandSplit') + endtry + if resultBuffer < 0 + echomsg 'Can''t open revision ' . a:1 + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + let s:vimDiffScratchList += [resultBuffer] + else + " Add new buffer + call s:OverrideOption('VCSCommandEdit', 'split') + try + " Force splitting behavior, otherwise why use vimdiff? + call s:OverrideOption('VCSCommandSplit', orientation) + try + if(a:0 == 0) + let resultBuffer = s:VCSReview() + else + let resultBuffer = s:VCSReview(a:1) + endif + finally + call s:OverrideOption('VCSCommandSplit') + endtry + finally + call s:OverrideOption('VCSCommandEdit') + endtry + if resultBuffer < 0 + echomsg 'Can''t open current revision' + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + + if !exists('s:vimDiffSourceBuffer') + " New instance of vimdiff. + let s:vimDiffScratchList = [resultBuffer] + + " This could have been invoked on a VCS result buffer, not the + " original buffer. + wincmd W + execute 'buffer' originalBuffer + " Store info for later original buffer restore + let s:vimDiffRestoreCmd = + \ 'call setbufvar('.originalBuffer.', ''&diff'', '.getbufvar(originalBuffer, '&diff').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldcolumn'', '.getbufvar(originalBuffer, '&foldcolumn').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldenable'', '.getbufvar(originalBuffer, '&foldenable').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldmethod'', '''.getbufvar(originalBuffer, '&foldmethod').''')' + \ . '|call setbufvar('.originalBuffer.', ''&foldlevel'', '''.getbufvar(originalBuffer, '&foldlevel').''')' + \ . '|call setbufvar('.originalBuffer.', ''&scrollbind'', '.getbufvar(originalBuffer, '&scrollbind').')' + \ . '|call setbufvar('.originalBuffer.', ''&wrap'', '.getbufvar(originalBuffer, '&wrap').')' + \ . '|if &foldmethod==''manual''|execute ''normal zE''|endif' + diffthis + wincmd w + else + " Adding a window to an existing vimdiff + let s:vimDiffScratchList += [resultBuffer] + endif + endif + + let s:vimDiffSourceBuffer = originalBuffer + + " Avoid executing the modeline in the current buffer after the autocommand. + + let currentBuffer = bufnr('%') + let saveModeline = getbufvar(currentBuffer, '&modeline') + try + call setbufvar(currentBuffer, '&modeline', 0) + silent do VCSCommand User VCSVimDiffFinish + finally + call setbufvar(currentBuffer, '&modeline', saveModeline) + endtry + return resultBuffer + finally + let s:isEditFileRunning = s:isEditFileRunning - 1 + endtry + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Section: Public functions {{{1 + +" Function: VCSCommandGetVCSType() {{{2 +" Sets the b:VCSCommandVCSType variable in the given buffer to the +" appropriate source control system name. +" +" This uses the Identify extension function to test the buffer. If the +" Identify function returns VCSCOMMAND_IDENTIFY_EXACT, the match is considered +" exact. If the Identify function returns VCSCOMMAND_IDENTIFY_INEXACT, the +" match is considered inexact, and is only applied if no exact match is found. +" Multiple inexact matches is currently considered an error. + +function! VCSCommandGetVCSType(buffer) + let vcsType = getbufvar(a:buffer, 'VCSCommandVCSType') + if strlen(vcsType) > 0 + return vcsType + endif + if exists("g:VCSCommandVCSTypeOverride") + let fullpath = fnamemodify(bufname(a:buffer), ':p') + for [path, vcsType] in g:VCSCommandVCSTypeOverride + if match(fullpath, path) > -1 + call setbufvar(a:buffer, 'VCSCommandVCSType', vcsType) + return vcsType + endif + endfor + endif + let matches = [] + for vcsType in keys(s:plugins) + let identified = s:plugins[vcsType][1].Identify(a:buffer) + if identified + if identified == g:VCSCOMMAND_IDENTIFY_EXACT + let matches = [vcsType] + break + else + let matches += [vcsType] + endif + endif + endfor + if len(matches) == 1 + call setbufvar(a:buffer, 'VCSCommandVCSType', matches[0]) + return matches[0] + elseif len(matches) == 0 + throw 'No suitable plugin' + else + throw 'Too many matching VCS: ' . join(matches) + endif +endfunction + +" Function: VCSCommandChdir(directory) {{{2 +" Changes the current directory, respecting :lcd changes. + +function! VCSCommandChdir(directory) + let command = 'cd' + if exists("*haslocaldir") && haslocaldir() + let command = 'lcd' + endif + execute command escape(a:directory, ' ') +endfunction + +" Function: VCSCommandChangeToCurrentFileDir() {{{2 +" Go to the directory in which the given file is located. + +function! VCSCommandChangeToCurrentFileDir(fileName) + let oldCwd = getcwd() + let newCwd = fnamemodify(resolve(a:fileName), ':p:h') + if strlen(newCwd) > 0 + call VCSCommandChdir(newCwd) + endif + return oldCwd +endfunction + +" Function: VCSCommandGetOriginalBuffer(vcsBuffer) {{{2 +" Attempts to locate the original file to which VCS operations were applied +" for a given buffer. + +function! VCSCommandGetOriginalBuffer(vcsBuffer) + let origBuffer = getbufvar(a:vcsBuffer, 'VCSCommandOriginalBuffer') + if origBuffer + if bufexists(origBuffer) + return origBuffer + else + " Original buffer no longer exists. + throw 'Original buffer for this VCS buffer no longer exists.' + endif + else + " No original buffer + return a:vcsBuffer + endif +endfunction + +" Function: VCSCommandRegisterModule(name, file, commandMap) {{{2 +" Allows VCS modules to register themselves. + +function! VCSCommandRegisterModule(name, path, commandMap, mappingMap) + let s:plugins[a:name] = [a:path, a:commandMap, a:mappingMap] + if !empty(a:mappingMap) + \ && !VCSCommandGetOption('VCSCommandDisableMappings', 0) + \ && !VCSCommandGetOption('VCSCommandDisableExtensionMappings', 0) + for shortcut in keys(a:mappingMap) + let expansion = ":call <SID>ExecuteExtensionMapping('" . shortcut . "')<CR>" + call s:CreateMapping(shortcut, expansion, a:name . " extension mapping " . shortcut) + endfor + endif + return s:VCSCommandUtility +endfunction + +" Function: VCSCommandDoCommand(cmd, cmdName, statusText, [options]) {{{2 +" General skeleton for VCS function execution. The given command is executed +" after appending the current buffer name (or substituting it for +" <VCSCOMMANDFILE>, if such a token is present). The output is captured in a +" new buffer. +" +" The optional 'options' Dictionary may contain the following options: +" allowNonZeroExit: if non-zero, if the underlying VCS command has a +" non-zero exit status, the command is still considered +" successfuly. This defaults to zero. +" Returns: name of the new command buffer containing the command results + +function! VCSCommandDoCommand(cmd, cmdName, statusText, options) + let allowNonZeroExit = 0 + if has_key(a:options, 'allowNonZeroExit') + let allowNonZeroExit = a:options.allowNonZeroExit + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + if originalBuffer == -1 + throw 'Original buffer no longer exists, aborting.' + endif + + let path = resolve(bufname(originalBuffer)) + + " Work with netrw or other systems where a directory listing is displayed in + " a buffer. + + if isdirectory(path) + let fileName = '.' + else + let fileName = fnamemodify(path, ':t') + endif + + if match(a:cmd, '<VCSCOMMANDFILE>') > 0 + let fullCmd = substitute(a:cmd, '<VCSCOMMANDFILE>', fileName, 'g') + else + let fullCmd = a:cmd . ' -- "' . fileName . '"' + endif + + " Change to the directory of the current buffer. This is done for CVS, but + " is left in for other systems as it does not affect them negatively. + + let oldCwd = VCSCommandChangeToCurrentFileDir(path) + try + let output = s:VCSCommandUtility.system(fullCmd) + finally + call VCSCommandChdir(oldCwd) + endtry + + " HACK: if line endings in the repository have been corrupted, the output + " of the command will be confused. + let output = substitute(output, "\r", '', 'g') + + if v:shell_error && !allowNonZeroExit + if strlen(output) == 0 + throw 'Version control command failed' + else + let output = substitute(output, '\n', ' ', 'g') + throw 'Version control command failed: ' . output + endif + endif + + if strlen(output) == 0 + " Handle case of no output. In this case, it is important to check the + " file status, especially since cvs edit/unedit may change the attributes + " of the file with no visible output. + + checktime + return 0 + endif + + call s:EditFile(a:cmdName, originalBuffer, a:statusText) + + silent 0put=output + + " The last command left a blank line at the end of the buffer. If the + " last line is folded (a side effect of the 'put') then the attempt to + " remove the blank line will kill the last fold. + " + " This could be fixed by explicitly detecting whether the last line is + " within a fold, but I prefer to simply unfold the result buffer altogether. + + if has('folding') + normal zR + endif + + $d + 1 + + " Define the environment and execute user-defined hooks. + + silent do VCSCommand User VCSBufferCreated + return bufnr('%') +endfunction + +" Function: VCSCommandGetOption(name, default) {{{2 +" Grab a user-specified option to override the default provided. Options are +" searched in the window, buffer, then global spaces. + +function! VCSCommandGetOption(name, default) + if has_key(s:optionOverrides, a:name) && len(s:optionOverrides[a:name]) > 0 + return s:optionOverrides[a:name][-1] + elseif exists('w:' . a:name) + return w:{a:name} + elseif exists('b:' . a:name) + return b:{a:name} + elseif exists('g:' . a:name) + return g:{a:name} + else + return a:default + endif +endfunction + +" Function: VCSCommandDisableBufferSetup() {{{2 +" Global function for deactivating the buffer autovariables. + +function! VCSCommandDisableBufferSetup() + let g:VCSCommandEnableBufferSetup = 0 + silent! augroup! VCSCommandPlugin +endfunction + +" Function: VCSCommandEnableBufferSetup() {{{2 +" Global function for activating the buffer autovariables. + +function! VCSCommandEnableBufferSetup() + let g:VCSCommandEnableBufferSetup = 1 + augroup VCSCommandPlugin + au! + au BufEnter * call s:SetupBuffer() + augroup END + + " Only auto-load if the plugin is fully loaded. This gives other plugins a + " chance to run. + if g:loaded_VCSCommand == 2 + call s:SetupBuffer() + endif +endfunction + +" Function: VCSCommandGetStatusLine() {{{2 +" Default (sample) status line entry for VCS-controlled files. This is only +" useful if VCS-managed buffer mode is on (see the VCSCommandEnableBufferSetup +" variable for how to do this). + +function! VCSCommandGetStatusLine() + if exists('b:VCSCommandCommand') + " This is a result buffer. Return nothing because the buffer name + " contains information already. + return '' + endif + + if exists('b:VCSCommandVCSType') + \ && exists('g:VCSCommandEnableBufferSetup') + \ && g:VCSCommandEnableBufferSetup + \ && exists('b:VCSCommandBufferInfo') + return '[' . join(extend([b:VCSCommandVCSType], b:VCSCommandBufferInfo), ' ') . ']' + else + return '' + endif +endfunction + +" Section: Command definitions {{{1 +" Section: Primary commands {{{2 +com! -nargs=* VCSAdd call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Add', [<f-args>])) +com! -nargs=* -bang VCSAnnotate call s:VCSAnnotate(<q-bang>, <f-args>) +com! -nargs=* -bang VCSBlame call s:VCSAnnotate(<q-bang>, <f-args>) +com! -nargs=? -bang VCSCommit call s:VCSCommit(<q-bang>, <q-args>) +com! -nargs=* VCSDelete call s:ExecuteVCSCommand('Delete', [<f-args>]) +com! -nargs=* VCSDiff call s:VCSDiff(<f-args>) +com! -nargs=0 -bang VCSGotoOriginal call s:VCSGotoOriginal(<q-bang>) +com! -nargs=* VCSInfo call s:ExecuteVCSCommand('Info', [<f-args>]) +com! -nargs=* VCSLock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Lock', [<f-args>])) +com! -nargs=* VCSLog call s:ExecuteVCSCommand('Log', [<f-args>]) +com! -nargs=* VCSRemove call s:ExecuteVCSCommand('Delete', [<f-args>]) +com! -nargs=0 VCSRevert call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Revert', [])) +com! -nargs=? VCSReview call s:VCSReview(<f-args>) +com! -nargs=* VCSStatus call s:ExecuteVCSCommand('Status', [<f-args>]) +com! -nargs=* VCSUnlock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Unlock', [<f-args>])) +com! -nargs=0 VCSUpdate call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Update', [])) +com! -nargs=* VCSVimDiff call s:VCSVimDiff(<f-args>) + +" Section: VCS buffer management commands {{{2 +com! VCSCommandDisableBufferSetup call VCSCommandDisableBufferSetup() +com! VCSCommandEnableBufferSetup call VCSCommandEnableBufferSetup() + +" Allow reloading VCSCommand.vim +com! VCSReload let savedPlugins = s:plugins|let s:plugins = {}|aunmenu Plugin.VCS|unlet! g:loaded_VCSCommand|runtime plugin/vcscommand.vim|for plugin in values(savedPlugins)|execute 'source' plugin[0]|endfor|unlet savedPlugins + +" Section: Plugin command mappings {{{1 +nnoremap <silent> <Plug>VCSAdd :VCSAdd<CR> +nnoremap <silent> <Plug>VCSAnnotate :VCSAnnotate<CR> +nnoremap <silent> <Plug>VCSCommit :VCSCommit<CR> +nnoremap <silent> <Plug>VCSDelete :VCSDelete<CR> +nnoremap <silent> <Plug>VCSDiff :VCSDiff<CR> +nnoremap <silent> <Plug>VCSGotoOriginal :VCSGotoOriginal<CR> +nnoremap <silent> <Plug>VCSClearAndGotoOriginal :VCSGotoOriginal!<CR> +nnoremap <silent> <Plug>VCSInfo :VCSInfo<CR> +nnoremap <silent> <Plug>VCSLock :VCSLock<CR> +nnoremap <silent> <Plug>VCSLog :VCSLog<CR> +nnoremap <silent> <Plug>VCSRevert :VCSRevert<CR> +nnoremap <silent> <Plug>VCSReview :VCSReview<CR> +nnoremap <silent> <Plug>VCSSplitAnnotate :VCSAnnotate!<CR> +nnoremap <silent> <Plug>VCSStatus :VCSStatus<CR> +nnoremap <silent> <Plug>VCSUnlock :VCSUnlock<CR> +nnoremap <silent> <Plug>VCSUpdate :VCSUpdate<CR> +nnoremap <silent> <Plug>VCSVimDiff :VCSVimDiff<CR> + +" Section: Default mappings {{{1 + +let s:defaultMappings = [ + \['a', 'VCSAdd'], + \['c', 'VCSCommit'], + \['D', 'VCSDelete'], + \['d', 'VCSDiff'], + \['G', 'VCSClearAndGotoOriginal'], + \['g', 'VCSGotoOriginal'], + \['i', 'VCSInfo'], + \['L', 'VCSLock'], + \['l', 'VCSLog'], + \['N', 'VCSSplitAnnotate'], + \['n', 'VCSAnnotate'], + \['q', 'VCSRevert'], + \['r', 'VCSReview'], + \['s', 'VCSStatus'], + \['U', 'VCSUnlock'], + \['u', 'VCSUpdate'], + \['v', 'VCSVimDiff'], + \] + +if !VCSCommandGetOption('VCSCommandDisableMappings', 0) + for [shortcut, vcsFunction] in VCSCommandGetOption('VCSCommandMappings', s:defaultMappings) + call s:CreateMapping(shortcut, '<Plug>' . vcsFunction, '''' . vcsFunction . '''') + endfor +endif + +" Section: Menu items {{{1 +amenu <silent> &Plugin.VCS.&Add <Plug>VCSAdd +amenu <silent> &Plugin.VCS.A&nnotate <Plug>VCSAnnotate +amenu <silent> &Plugin.VCS.&Commit <Plug>VCSCommit +amenu <silent> &Plugin.VCS.Delete <Plug>VCSDelete +amenu <silent> &Plugin.VCS.&Diff <Plug>VCSDiff +amenu <silent> &Plugin.VCS.&Info <Plug>VCSInfo +amenu <silent> &Plugin.VCS.&Log <Plug>VCSLog +amenu <silent> &Plugin.VCS.Revert <Plug>VCSRevert +amenu <silent> &Plugin.VCS.&Review <Plug>VCSReview +amenu <silent> &Plugin.VCS.&Status <Plug>VCSStatus +amenu <silent> &Plugin.VCS.&Update <Plug>VCSUpdate +amenu <silent> &Plugin.VCS.&VimDiff <Plug>VCSVimDiff + +" Section: Autocommands to restore vimdiff state {{{1 +augroup VimDiffRestore + au! + au BufUnload * call s:VimDiffRestore(str2nr(expand('<abuf>'))) +augroup END + +" Section: Optional activation of buffer management {{{1 + +if VCSCommandGetOption('VCSCommandEnableBufferSetup', 0) + call VCSCommandEnableBufferSetup() +endif + +" Section: VIM shutdown hook {{{1 + +" Close all result buffers when VIM exits, to prevent them from being restored +" via viminfo. + +" Function: s:CloseAllResultBuffers() {{{2 +" Closes all vcscommand result buffers. +function! s:CloseAllResultBuffers() + " This avoids using bufdo as that may load buffers already loaded in another + " vim process, resulting in an error. + let buffnr = 1 + let buffmaxnr = bufnr('$') + while buffnr <= buffmaxnr + if getbufvar(buffnr, 'VCSCommandOriginalBuffer') != "" + execute 'bw' buffnr + endif + let buffnr = buffnr + 1 + endwhile +endfunction + +augroup VCSCommandVIMShutdown + au! + au VimLeavePre * call s:CloseAllResultBuffers() +augroup END + +" Section: Plugin completion {{{1 + +let loaded_VCSCommand = 2 + +silent do VCSCommand User VCSPluginFinish + +let &cpo = s:save_cpo diff --git a/plugin/vcscvs.vim b/plugin/vcscvs.vim new file mode 100644 index 0000000..2766348 --- /dev/null +++ b/plugin/vcscvs.vim @@ -0,0 +1,445 @@ +" vim600: set foldmethod=marker: +" +" CVS extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Command documentation {{{2 +" +" The following commands only apply to files under CVS source control. +" +" CVSEdit Performs "cvs edit" on the current file. +" +" CVSEditors Performs "cvs editors" on the current file. +" +" CVSUnedit Performs "cvs unedit" on the current file. +" +" CVSWatch Takes an argument which must be one of [on|off|add|remove]. +" Performs "cvs watch" with the given argument on the current +" file. +" +" CVSWatchers Performs "cvs watchers" on the current file. +" +" CVSWatchAdd Alias for "CVSWatch add" +" +" CVSWatchOn Alias for "CVSWatch on" +" +" CVSWatchOff Alias for "CVSWatch off" +" +" CVSWatchRemove Alias for "CVSWatch remove" +" +" Mapping documentation: {{{2 +" +" By default, a mapping is defined for each command. User-provided mappings +" can be used instead by mapping to <Plug>CommandName, for instance: +" +" nnoremap ,ce <Plug>CVSEdit +" +" The default mappings are as follow: +" +" <Leader>ce CVSEdit +" <Leader>cE CVSEditors +" <Leader>ct CVSUnedit +" <Leader>cwv CVSWatchers +" <Leader>cwa CVSWatchAdd +" <Leader>cwn CVSWatchOn +" <Leader>cwf CVSWatchOff +" <Leader>cwr CVSWatchRemove +" +" Options documentation: {{{2 +" +" VCSCommandCVSExec +" This variable specifies the CVS executable. If not set, it defaults to +" 'cvs' executed from the user's executable path. +" +" VCSCommandCVSDiffOpt +" This variable, if set, determines the options passed to the cvs diff +" command. If not set, it defaults to 'u'. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandCVSExec', 'cvs')) + " CVS is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:cvsFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke cvs suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandCVSExec', 'cvs')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the CVS executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'CVS' + let fullCmd = s:Executable() . ' ' . a:cmd + let ret = VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + + if ret > 0 + if getline(line('$')) =~ '^cvs \w\+: closing down connection' + $d + 1 + endif + + endif + + return ret + else + throw 'CVS VCSCommand plugin called on non-CVS item.' + endif +endfunction + +" Function: s:GetRevision() {{{2 +" Function for retrieving the current buffer's revision number. +" Returns: Revision number or an empty string if an error occurs. + +function! s:GetRevision() + if !exists('b:VCSCommandBufferInfo') + let b:VCSCommandBufferInfo = s:cvsFunctions.GetBufferInfo() + endif + + if len(b:VCSCommandBufferInfo) > 0 + return b:VCSCommandBufferInfo[0] + else + return '' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:cvsFunctions.Identify(buffer) {{{2 +function! s:cvsFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + if isdirectory(fileName) + let directoryName = fileName + else + let directoryName = fnamemodify(fileName, ':h') + endif + if strlen(directoryName) > 0 + let CVSRoot = directoryName . '/CVS/Root' + else + let CVSRoot = 'CVS/Root' + endif + if filereadable(CVSRoot) + return 1 + else + return 0 + endif +endfunction + +" Function: s:cvsFunctions.Add(argList) {{{2 +function! s:cvsFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:cvsFunctions.Annotate(argList) {{{2 +function! s:cvsFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'CVSannotate' + " This is a CVSAnnotate buffer. Perform annotation of the version + " indicated by the current line. + let caption = matchstr(getline('.'),'\v^[0-9.]+') + + if VCSCommandGetOption('VCSCommandCVSAnnotateParent', 0) != 0 + if caption != '1.1' + let revmaj = matchstr(caption,'\v[0-9.]+\ze\.[0-9]+') + let revmin = matchstr(caption,'\v[0-9.]+\.\zs[0-9]+') - 1 + if revmin == 0 + " Jump to ancestor branch + let caption = matchstr(revmaj,'\v[0-9.]+\ze\.[0-9]+') + else + let caption = revmaj . "." . revmin + endif + endif + endif + + let options = ['-r' . caption] + else + " CVS defaults to pulling HEAD, regardless of current branch. + " Therefore, always pass desired revision. + let caption = '' + let options = ['-r' . s:GetRevision()] + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ['-r' . caption] + else + let caption = join(a:argList) + let options = a:argList + endif + + let resultBuffer = s:DoCommand(join(['-q', 'annotate'] + options), 'annotate', caption, {}) + if resultBuffer > 0 + " Remove header lines from standard error + silent v/^\d\+\%(\.\d\+\)\+/d + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.Commit(argList) {{{2 +function! s:cvsFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.Delete() {{{2 +" By default, use the -f option to remove the file first. If options are +" passed in, use those instead. +function! s:cvsFunctions.Delete(argList) + let options = ['-f'] + let caption = '' + if len(a:argList) > 0 + let options = a:argList + let caption = join(a:argList, ' ') + endif + return s:DoCommand(join(['remove'] + options, ' '), 'delete', caption, {}) +endfunction + +" Function: s:cvsFunctions.Diff(argList) {{{2 +function! s:cvsFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ' -r')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let cvsDiffOpt = VCSCommandGetOption('VCSCommandCVSDiffOpt', 'u') + if cvsDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-' . cvsDiffOpt] + endif + + return s:DoCommand(join(['diff'] + diffOptions + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) +endfunction + +" Function: s:cvsFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. This CVS extension adds branch name to the return +" list as well. +" Returns: List of results: [revision, repository, branch] + +function! s:cvsFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + if isdirectory(fileName) + let tag = '' + if filereadable(fileName . '/CVS/Tag') + let tagFile = readfile(fileName . '/CVS/Tag') + if len(tagFile) == 1 + let tag = substitute(tagFile[0], '^T', '', '') + endif + endif + return [tag] + endif + let realFileName = fnamemodify(resolve(fileName), ':t') + if !filereadable(fileName) + return ['Unknown'] + endif + let oldCwd = VCSCommandChangeToCurrentFileDir(fileName) + try + let statusText=s:VCSCommandUtility.system(s:Executable() . ' status -- "' . realFileName . '"') + if(v:shell_error) + return [] + endif + let revision=substitute(statusText, '^\_.*Working revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\)\_.*$', '\1', '') + + " We can still be in a CVS-controlled directory without this being a CVS + " file + if match(revision, '^New file!$') >= 0 + let revision='New' + elseif match(revision, '^\d\+\.\d\+\%(\.\d\+\.\d\+\)*$') <0 + return ['Unknown'] + endif + + let branch=substitute(statusText, '^\_.*Sticky Tag:\s\+\(\d\+\%(\.\d\+\)\+\|\a[A-Za-z0-9-_]*\|(none)\).*$', '\1', '') + let repository=substitute(statusText, '^\_.*Repository revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\|No revision control file\)\_.*$', '\1', '') + let repository=substitute(repository, '^New file!\|No revision control file$', 'New', '') + return [revision, repository, branch] + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:cvsFunctions.Log() {{{2 +function! s:cvsFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + return s:DoCommand(join(['log'] + options), 'log', caption, {}) +endfunction + +" Function: s:cvsFunctions.Revert(argList) {{{2 +function! s:cvsFunctions.Revert(argList) + return s:DoCommand('update -C', 'revert', '', {}) +endfunction + +" Function: s:cvsFunctions.Review(argList) {{{2 +function! s:cvsFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('-q update -p' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:cvsFunctions.Status(argList) {{{2 +function! s:cvsFunctions.Status(argList) + return s:DoCommand(join(['status'] + a:argList, ' '), 'status', join(a:argList, ' '), {}) +endfunction + +" Function: s:cvsFunctions.Update(argList) {{{2 +function! s:cvsFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: CVS-specific functions {{{1 + +" Function: s:CVSEdit() {{{2 +function! s:CVSEdit() + return s:DoCommand('edit', 'cvsedit', '', {}) +endfunction + +" Function: s:CVSEditors() {{{2 +function! s:CVSEditors() + return s:DoCommand('editors', 'cvseditors', '', {}) +endfunction + +" Function: s:CVSUnedit() {{{2 +function! s:CVSUnedit() + return s:DoCommand('unedit', 'cvsunedit', '', {}) +endfunction + +" Function: s:CVSWatch(onoff) {{{2 +function! s:CVSWatch(onoff) + if a:onoff !~ '^\c\%(on\|off\|add\|remove\)$' + echoerr 'Argument to CVSWatch must be one of [on|off|add|remove]' + return -1 + end + return s:DoCommand('watch ' . tolower(a:onoff), 'cvswatch', '', {}) +endfunction + +" Function: s:CVSWatchers() {{{2 +function! s:CVSWatchers() + return s:DoCommand('watchers', 'cvswatchers', '', {}) +endfunction + +" Annotate setting {{{2 +let s:cvsFunctions.AnnotateSplitRegex = '): ' + +" Section: Command definitions {{{1 +" Section: Primary commands {{{2 +com! CVSEdit call s:CVSEdit() +com! CVSEditors call s:CVSEditors() +com! CVSUnedit call s:CVSUnedit() +com! -nargs=1 CVSWatch call s:CVSWatch(<f-args>) +com! CVSWatchAdd call s:CVSWatch('add') +com! CVSWatchOn call s:CVSWatch('on') +com! CVSWatchOff call s:CVSWatch('off') +com! CVSWatchRemove call s:CVSWatch('remove') +com! CVSWatchers call s:CVSWatchers() + +" Section: Plugin command mappings {{{1 + +let s:cvsExtensionMappings = {} +let mappingInfo = [ + \['CVSEdit', 'CVSEdit', 'e'], + \['CVSEditors', 'CVSEditors', 'E'], + \['CVSUnedit', 'CVSUnedit', 't'], + \['CVSWatchers', 'CVSWatchers', 'wv'], + \['CVSWatchAdd', 'CVSWatch add', 'wa'], + \['CVSWatchOff', 'CVSWatch off', 'wf'], + \['CVSWatchOn', 'CVSWatch on', 'wn'], + \['CVSWatchRemove', 'CVSWatch remove', 'wr'] + \] + +for [pluginName, commandText, shortCut] in mappingInfo + execute 'nnoremap <silent> <Plug>' . pluginName . ' :' . commandText . '<CR>' + if !hasmapto('<Plug>' . pluginName) + let s:cvsExtensionMappings[shortCut] = commandText + endif +endfor + +" Section: Menu items {{{1 +amenu <silent> &Plugin.VCS.CVS.&Edit <Plug>CVSEdit +amenu <silent> &Plugin.VCS.CVS.Ed&itors <Plug>CVSEditors +amenu <silent> &Plugin.VCS.CVS.Unedi&t <Plug>CVSUnedit +amenu <silent> &Plugin.VCS.CVS.&Watchers <Plug>CVSWatchers +amenu <silent> &Plugin.VCS.CVS.WatchAdd <Plug>CVSWatchAdd +amenu <silent> &Plugin.VCS.CVS.WatchOn <Plug>CVSWatchOn +amenu <silent> &Plugin.VCS.CVS.WatchOff <Plug>CVSWatchOff +amenu <silent> &Plugin.VCS.CVS.WatchRemove <Plug>CVSWatchRemove + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('CVS', expand('<sfile>'), s:cvsFunctions, s:cvsExtensionMappings) + +let &cpo = s:save_cpo diff --git a/plugin/vcsgit.vim b/plugin/vcsgit.vim new file mode 100644 index 0000000..8ecbcf2 --- /dev/null +++ b/plugin/vcsgit.vim @@ -0,0 +1,248 @@ +" vim600: set foldmethod=marker: +" +" git extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2008 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandGitExec +" This variable specifies the git executable. If not set, it defaults to +" 'git' executed from the user's executable path. +" +" VCSCommandGitDiffOpt +" This variable, if set, determines the default options passed to the +" VCSDiff command. If any options (starting with '-') are passed to the +" command, this variable is not used. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandGitExec', 'git')) + " git is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:gitFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke git suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandGitExec', 'git')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the git executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'git' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'git VCSCommand plugin called on non-git item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:gitFunctions.Identify(buffer) {{{2 +" This function only returns an inexact match due to the detection method used +" by git, which simply traverses the directory structure upward. +function! s:gitFunctions.Identify(buffer) + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) + try + call s:VCSCommandUtility.system(s:Executable() . ' rev-parse --is-inside-work-tree') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_INEXACT + endif + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:gitFunctions.Add(argList) {{{2 +function! s:gitFunctions.Add(argList) + return s:DoCommand(join(['add'] + ['-v'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:gitFunctions.Annotate(argList) {{{2 +function! s:gitFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'gitannotate' + " Perform annotation of the version indicated by the current line. + let options = matchstr(getline('.'),'^\x\+') + else + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let options = a:argList[0] + else + let options = join(a:argList, ' ') + endif + + return s:DoCommand('blame ' . options, 'annotate', options, {}) +endfunction + +" Function: s:gitFunctions.Commit(argList) {{{2 +function! s:gitFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif + return resultBuffer +endfunction + +" Function: s:gitFunctions.Delete() {{{2 +" All options are passed through. +function! s:gitFunctions.Delete(argList) + let options = a:argList + let caption = join(a:argList, ' ') + return s:DoCommand(join(['rm'] + options, ' '), 'delete', caption, {}) +endfunction + +" Function: s:gitFunctions.Diff(argList) {{{2 +" Pass-through call to git-diff. If no options (starting with '-') are found, +" then the options in the 'VCSCommandGitDiffOpt' variable are added. +function! s:gitFunctions.Diff(argList) + let gitDiffOpt = VCSCommandGetOption('VCSCommandGitDiffOpt', '') + if gitDiffOpt == '' + let diffOptions = [] + else + let diffOptions = [gitDiffOpt] + for arg in a:argList + if arg =~ '^-' + let diffOptions = [] + break + endif + endfor + endif + + return s:DoCommand(join(['diff'] + diffOptions + a:argList), 'diff', join(a:argList), {}) +endfunction + +" Function: s:gitFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. This CVS extension adds branch name to the return +" list as well. +" Returns: List of results: [revision, repository, branch] + +function! s:gitFunctions.GetBufferInfo() + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname('%'))) + try + let branch = substitute(s:VCSCommandUtility.system(s:Executable() . ' symbolic-ref -q HEAD'), '\n$', '', '') + if v:shell_error + let branch = 'DETACHED' + else + let branch = substitute(branch, '^refs/heads/', '', '') + endif + + let info = [branch] + + for method in split(VCSCommandGetOption('VCSCommandGitDescribeArgList', (',tags,all,always')), ',', 1) + if method != '' + let method = ' --' . method + endif + let tag = substitute(s:VCSCommandUtility.system(s:Executable() . ' describe' . method), '\n$', '', '') + if !v:shell_error + call add(info, tag) + break + endif + endfor + + return info + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:gitFunctions.Log() {{{2 +function! s:gitFunctions.Log(argList) + return s:DoCommand(join(['log'] + a:argList), 'log', join(a:argList, ' '), {}) +endfunction + +" Function: s:gitFunctions.Revert(argList) {{{2 +function! s:gitFunctions.Revert(argList) + return s:DoCommand('checkout', 'revert', '', {}) +endfunction + +" Function: s:gitFunctions.Review(argList) {{{2 +function! s:gitFunctions.Review(argList) + if len(a:argList) == 0 + let revision = 'HEAD' + else + let revision = a:argList[0] + endif + + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(VCSCommandGetOriginalBuffer('%')))) + try + let prefix = s:VCSCommandUtility.system(s:Executable() . ' rev-parse --show-prefix') + finally + call VCSCommandChdir(oldCwd) + endtry + + let prefix = substitute(prefix, '\n$', '', '') + let blob = '"' . revision . ':' . prefix . '<VCSCOMMANDFILE>"' + return s:DoCommand('show ' . blob, 'review', revision, {}) +endfunction + +" Function: s:gitFunctions.Status(argList) {{{2 +function! s:gitFunctions.Status(argList) + return s:DoCommand(join(['status'] + a:argList), 'status', join(a:argList), {'allowNonZeroExit': 1}) +endfunction + +" Function: s:gitFunctions.Update(argList) {{{2 +function! s:gitFunctions.Update(argList) + throw "This command is not implemented for git because file-by-file update doesn't make much sense in that context. If you have an idea for what it should do, please let me know." +endfunction + +" Annotate setting {{{2 +let s:gitFunctions.AnnotateSplitRegex = ') ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('git', expand('<sfile>'), s:gitFunctions, []) + +let &cpo = s:save_cpo diff --git a/plugin/vcshg.vim b/plugin/vcshg.vim new file mode 100644 index 0000000..a520172 --- /dev/null +++ b/plugin/vcshg.vim @@ -0,0 +1,273 @@ +" vim600: set foldmethod=marker: +" +" Mercurial extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2009 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandHGExec +" This variable specifies the mercurial executable. If not set, it defaults +" to 'hg' executed from the user's executable path. +" +" VCSCommandHGDiffExt +" This variable, if set, sets the external diff program used by Subversion. +" +" VCSCommandHGDiffOpt +" This variable, if set, determines the options passed to the hg diff +" command (such as 'u', 'w', or 'b'). + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandHGExec', 'hg')) + " HG is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:hgFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke hg suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandHGExec', 'hg')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the HG executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'HG' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'HG VCSCommand plugin called on non-HG item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:hgFunctions.Identify(buffer) {{{2 +function! s:hgFunctions.Identify(buffer) + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) + try + call s:VCSCommandUtility.system(s:Executable() . ' root') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_INEXACT + endif + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:hgFunctions.Add() {{{2 +function! s:hgFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Annotate(argList) {{{2 +function! s:hgFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'HGannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = ' -un' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -un -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + return s:DoCommand('blame' . options, 'annotate', caption, {}) +endfunction + +" Function: s:hgFunctions.Commit(argList) {{{2 +function! s:hgFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -l "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:hgFunctions.Delete() {{{2 +function! s:hgFunctions.Delete(argList) + return s:DoCommand(join(['remove'] + a:argList, ' '), 'remove', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Diff(argList) {{{2 +function! s:hgFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ':')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let hgDiffExt = VCSCommandGetOption('VCSCommandHGDiffExt', '') + if hgDiffExt == '' + let diffExt = [] + else + let diffExt = ['--diff-cmd ' . hgDiffExt] + endif + + let hgDiffOpt = VCSCommandGetOption('VCSCommandHGDiffOpt', '') + if hgDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-x -' . hgDiffOpt] + endif + + return s:DoCommand(join(['diff'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) +endfunction + +" Function: s:hgFunctions.Info(argList) {{{2 +function! s:hgFunctions.Info(argList) + return s:DoCommand(join(['log --limit 1'] + a:argList, ' '), 'log', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository, branch] + +function! s:hgFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under HG control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let parentsText = s:VCSCommandUtility.system(s:Executable() . ' parents -- "' . fileName . '"') + let revision = matchlist(parentsText, '^changeset:\s\+\(\S\+\)\n')[1] + + let logText = s:VCSCommandUtility.system(s:Executable() . ' log -- "' . fileName . '"') + let repository = matchlist(logText, '^changeset:\s\+\(\S\+\)\n')[1] + + if revision == '' + " Error + return ['Unknown'] + elseif statusText =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:hgFunctions.Log(argList) {{{2 +function! s:hgFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:hgFunctions.Revert(argList) {{{2 +function! s:hgFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:hgFunctions.Review(argList) {{{2 +function! s:hgFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:hgFunctions.Status(argList) {{{2 +function! s:hgFunctions.Status(argList) + let options = ['-u', '-v'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:hgFunctions.Update(argList) {{{2 +function! s:hgFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Annotate setting {{{2 +let s:hgFunctions.AnnotateSplitRegex = '\d\+: ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('HG', expand('<sfile>'), s:hgFunctions, []) + +let &cpo = s:save_cpo diff --git a/plugin/vcssvk.vim b/plugin/vcssvk.vim new file mode 100644 index 0000000..15e1c1e --- /dev/null +++ b/plugin/vcssvk.vim @@ -0,0 +1,258 @@ +" vim600: set foldmethod=marker: +" +" SVK extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandSVKExec +" This variable specifies the SVK executable. If not set, it defaults to +" 'svk' executed from the user's executable path. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandSVKExec', 'svk')) + " SVK is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:svkFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke SVK suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandSVKExec', 'svk')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the SVK executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'SVK' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'SVK VCSCommand plugin called on non-SVK item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:svkFunctions.Identify(buffer) {{{2 +function! s:svkFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + if isdirectory(fileName) + let directoryName = fileName + else + let directoryName = fnamemodify(fileName, ':p:h') + endif + let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . directoryName . '"', "no") + if(v:shell_error) + return 0 + else + return 1 + endif +endfunction + +" Function: s:svkFunctions.Add() {{{2 +function! s:svkFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Annotate(argList) {{{2 +function! s:svkFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'SVKannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + normal 1G2dd + endif + return resultBuffer +endfunction + +" Function: s:svkFunctions.Commit(argList) {{{2 +function! s:svkFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:svkFunctions.Delete() {{{2 +function! s:svkFunctions.Delete(argList) + return s:DoCommand(join(['delete'] + a:argList, ' '), 'delete', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Diff(argList) {{{2 +function! s:svkFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ':')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {}) +endfunction + +" Function: s:svkFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository] + +function! s:svkFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = resolve(bufname(originalBuffer)) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -v -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under SVK control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, revision, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)\s')[1:3] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:svkFunctions.Info(argList) {{{2 +function! s:svkFunctions.Info(argList) + return s:DoCommand(join(['info'] + a:argList, ' '), 'info', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Lock(argList) {{{2 +function! s:svkFunctions.Lock(argList) + return s:DoCommand(join(['lock'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Log() {{{2 +function! s:svkFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:svkFunctions.Revert(argList) {{{2 +function! s:svkFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:svkFunctions.Review(argList) {{{2 +function! s:svkFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:svkFunctions.Status(argList) {{{2 +function! s:svkFunctions.Status(argList) + let options = ['-v'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:svkFunctions.Unlock(argList) {{{2 +function! s:svkFunctions.Unlock(argList) + return s:DoCommand(join(['unlock'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) +endfunction +" Function: s:svkFunctions.Update(argList) {{{2 +function! s:svkFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('SVK', expand('<sfile>'), s:svkFunctions, []) + +let &cpo = s:save_cpo diff --git a/plugin/vcssvn.vim b/plugin/vcssvn.vim new file mode 100644 index 0000000..c9d120f --- /dev/null +++ b/plugin/vcssvn.vim @@ -0,0 +1,285 @@ +" vim600: set foldmethod=marker: +" +" SVN extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandSVNExec +" This variable specifies the SVN executable. If not set, it defaults to +" 'svn' executed from the user's executable path. +" +" VCSCommandSVNDiffExt +" This variable, if set, sets the external diff program used by Subversion. +" +" VCSCommandSVNDiffOpt +" This variable, if set, determines the options passed to the svn diff +" command (such as 'u', 'w', or 'b'). + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandSVNExec', 'svn')) + " SVN is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:svnFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke git suitable for use in a shell +" command. +function! s:Executable() + return shellescape(VCSCommandGetOption('VCSCommandSVNExec', 'svn')) +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the SVN executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'SVN' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'SVN VCSCommand plugin called on non-SVN item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:svnFunctions.Identify(buffer) {{{2 +function! s:svnFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + if isdirectory(fileName) + let directoryName = fileName + else + let directoryName = fnamemodify(fileName, ':h') + endif + if strlen(directoryName) > 0 + let svnDir = directoryName . '/.svn' + else + let svnDir = '.svn' + endif + if isdirectory(svnDir) + return 1 + else + return 0 + endif +endfunction + +" Function: s:svnFunctions.Add() {{{2 +function! s:svnFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Annotate(argList) {{{2 +function! s:svnFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'SVNannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + return s:DoCommand('blame --non-interactive' . options, 'annotate', caption, {}) +endfunction + +" Function: s:svnFunctions.Commit(argList) {{{2 +function! s:svnFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit --non-interactive -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:svnFunctions.Delete() {{{2 +function! s:svnFunctions.Delete(argList) + return s:DoCommand(join(['delete --non-interactive'] + a:argList, ' '), 'delete', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Diff(argList) {{{2 +function! s:svnFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ':')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let svnDiffExt = VCSCommandGetOption('VCSCommandSVNDiffExt', '') + if svnDiffExt == '' + let diffExt = [] + else + let diffExt = ['--diff-cmd ' . svnDiffExt] + endif + + let svnDiffOpt = VCSCommandGetOption('VCSCommandSVNDiffOpt', '') + if svnDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-x -' . svnDiffOpt] + endif + + return s:DoCommand(join(['diff --non-interactive'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) +endfunction + +" Function: s:svnFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository, branch] + +function! s:svnFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status --non-interactive -vu -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under SVN control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, revision, repository] = matchlist(statusText, '^\(.\{9}\)\s*\(\d\+\)\s\+\(\d\+\)')[1:3] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + elseif flags =~ '*' + return [revision, repository, '*'] + else + return [revision, repository] + endif +endfunction + +" Function: s:svnFunctions.Info(argList) {{{2 +function! s:svnFunctions.Info(argList) + return s:DoCommand(join(['info --non-interactive'] + a:argList, ' '), 'info', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Lock(argList) {{{2 +function! s:svnFunctions.Lock(argList) + return s:DoCommand(join(['lock --non-interactive'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Log(argList) {{{2 +function! s:svnFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log --non-interactive', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:svnFunctions.Revert(argList) {{{2 +function! s:svnFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:svnFunctions.Review(argList) {{{2 +function! s:svnFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat --non-interactive' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:svnFunctions.Status(argList) {{{2 +function! s:svnFunctions.Status(argList) + let options = ['-u', '-v'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status --non-interactive'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:svnFunctions.Unlock(argList) {{{2 +function! s:svnFunctions.Unlock(argList) + return s:DoCommand(join(['unlock --non-interactive'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Update(argList) {{{2 +function! s:svnFunctions.Update(argList) + return s:DoCommand('update --non-interactive', 'update', '', {}) +endfunction + +" Annotate setting {{{2 +let s:svnFunctions.AnnotateSplitRegex = '\s\+\S\+\s\+\S\+ ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('SVN', expand('<sfile>'), s:svnFunctions, []) + +let &cpo = s:save_cpo diff --git a/plugin/vimwiki.vim b/plugin/vimwiki.vim new file mode 100644 index 0000000..72f0483 --- /dev/null +++ b/plugin/vimwiki.vim @@ -0,0 +1,405 @@ +" Vimwiki plugin file +" Author: Maxim Kim <habamax@gmail.com> +" Home: http://code.google.com/p/vimwiki/ +" GetLatestVimScripts: 2226 1 :AutoInstall: vimwiki + +if exists("loaded_vimwiki") || &cp + finish +endif +let loaded_vimwiki = 1 + +let s:old_cpo = &cpo +set cpo&vim + +" HELPER functions {{{ +function! s:default(varname, value) "{{{ + if !exists('g:vimwiki_'.a:varname) + let g:vimwiki_{a:varname} = a:value + endif +endfunction "}}} + +function! Str_common_part(str1, str2)"{{{ + let idx = 0 + let minlen = min([len(a:str1), len(a:str2)]) + while (idx < minlen) && (a:str1[idx] == a:str2[idx]) + let idx = idx + 1 + endwhile + + return strpart(a:str1, 0, idx) +endfunction"}}} + +function! s:chomp_slash(str)"{{{ + return substitute(a:str, '[/\\]\+$', '', '') +endfunction"}}} + +function! s:find_wiki(path) "{{{ + let idx = 0 + while idx < len(g:vimwiki_list) + let path = s:chomp_slash(expand(VimwikiGet('path', idx))) + if Str_common_part(path, a:path) == path + return idx + endif + let idx += 1 + endwhile + return -1 +endfunction "}}} + +function! s:setup_buffer_leave()"{{{ + if &filetype == 'vimwiki' && !exists("b:vimwiki_idx") + let b:vimwiki_idx = g:vimwiki_current_idx + endif + + " Set up menu + if g:vimwiki_menu != "" + exe 'nmenu disable '.g:vimwiki_menu.'.Table' + endif +endfunction"}}} + +function! s:setup_buffer_enter() "{{{ + if exists("b:vimwiki_idx") + let g:vimwiki_current_idx = b:vimwiki_idx + else + " Find what wiki current buffer belongs to. + " If wiki does not exist in g:vimwiki_list -- add new wiki there with + " buffer's path and ext. + " Else set g:vimwiki_current_idx to that wiki index. + let path = expand('%:p:h') + let ext = '.'.expand('%:e') + let idx = s:find_wiki(path) + + " The buffer's file is not in the path and user do not want his wiki + " extension to be global -- do not add new wiki. + if idx == -1 && g:vimwiki_global_ext == 0 + return + endif + + if idx == -1 + call add(g:vimwiki_list, {'path': path, 'ext': ext}) + let g:vimwiki_current_idx = len(g:vimwiki_list) - 1 + else + let g:vimwiki_current_idx = idx + endif + + let b:vimwiki_idx = g:vimwiki_current_idx + endif + + call s:setup_colors() + + if &filetype != 'vimwiki' + setlocal ft=vimwiki + else + setlocal syntax=vimwiki + endif + + " Settings foldmethod, foldexpr and foldtext are local to window. Thus in a + " new tab with the same buffer folding is reset to vim defaults. So we + " insist vimwiki folding here. + " TODO: remove the same from ftplugin. + if g:vimwiki_folding == 1 && &fdm != 'expr' + setlocal fdm=expr + setlocal foldexpr=VimwikiFoldLevel(v:lnum) + setlocal foldtext=VimwikiFoldText() + endif + + " Set up menu + if g:vimwiki_menu != "" + exe 'nmenu enable '.g:vimwiki_menu.'.Table' + endif +endfunction "}}} + +function! s:setup_colors()"{{{ + if g:vimwiki_hl_headers == 0 + return + endif + + if &background == 'light' + hi def VimwikiHeader1 guibg=bg guifg=#aa5858 gui=bold ctermfg=DarkRed + hi def VimwikiHeader2 guibg=bg guifg=#309010 gui=bold ctermfg=DarkGreen + hi def VimwikiHeader3 guibg=bg guifg=#1030a0 gui=bold ctermfg=DarkBlue + hi def VimwikiHeader4 guibg=bg guifg=#103040 gui=bold ctermfg=Black + hi def VimwikiHeader5 guibg=bg guifg=#001020 gui=bold ctermfg=Black + hi def VimwikiHeader6 guibg=bg guifg=#000000 gui=bold ctermfg=Black + else + hi def VimwikiHeader1 guibg=bg guifg=#e08090 gui=bold ctermfg=Red + hi def VimwikiHeader2 guibg=bg guifg=#80e090 gui=bold ctermfg=Green + hi def VimwikiHeader3 guibg=bg guifg=#6090e0 gui=bold ctermfg=Blue + hi def VimwikiHeader4 guibg=bg guifg=#c0c0f0 gui=bold ctermfg=White + hi def VimwikiHeader5 guibg=bg guifg=#e0e0f0 gui=bold ctermfg=White + hi def VimwikiHeader6 guibg=bg guifg=#f0f0f0 gui=bold ctermfg=White + endif +endfunction"}}} + +" OPTION get/set functions {{{ +" return value of option for current wiki or if second parameter exists for +" wiki with a given index. +function! VimwikiGet(option, ...) "{{{ + if a:0 == 0 + let idx = g:vimwiki_current_idx + else + let idx = a:1 + endif + if !has_key(g:vimwiki_list[idx], a:option) && + \ has_key(s:vimwiki_defaults, a:option) + if a:option == 'path_html' + let g:vimwiki_list[idx][a:option] = + \VimwikiGet('path', idx)[:-2].'_html/' + else + let g:vimwiki_list[idx][a:option] = + \s:vimwiki_defaults[a:option] + endif + endif + + " if path's ending is not a / or \ + " then add it + if a:option == 'path' || a:option == 'path_html' + let p = g:vimwiki_list[idx][a:option] + " resolve doesn't work quite right with symlinks ended with / or \ + let p = substitute(p, '[/\\]\+$', '', '') + let p = resolve(expand(p)) + let g:vimwiki_list[idx][a:option] = p.'/' + endif + + return g:vimwiki_list[idx][a:option] +endfunction "}}} + +" set option for current wiki or if third parameter exists for +" wiki with a given index. +function! VimwikiSet(option, value, ...) "{{{ + if a:0 == 0 + let idx = g:vimwiki_current_idx + else + let idx = a:1 + endif + let g:vimwiki_list[idx][a:option] = a:value +endfunction "}}} +" }}} + +" }}} + +" CALLBACK function "{{{ +" User can redefine it. +if !exists("*VimwikiWeblinkHandler") "{{{ + function VimwikiWeblinkHandler(weblink) + for browser in g:vimwiki_browsers + if executable(browser) + if has("win32") + execute '!start "'.browser.'" ' . a:weblink + else + execute '!'.browser.' ' . a:weblink + endif + return + endif + endfor + endfunction +endif "}}} +" CALLBACK }}} + +" DEFAULT wiki {{{ +let s:vimwiki_defaults = {} +let s:vimwiki_defaults.path = '~/vimwiki/' +let s:vimwiki_defaults.path_html = '~/vimwiki_html/' +let s:vimwiki_defaults.css_name = 'style.css' +let s:vimwiki_defaults.index = 'index' +let s:vimwiki_defaults.ext = '.wiki' +let s:vimwiki_defaults.maxhi = 1 +let s:vimwiki_defaults.syntax = 'default' +let s:vimwiki_defaults.gohome = 'split' +let s:vimwiki_defaults.html_header = '' +let s:vimwiki_defaults.html_footer = '' +let s:vimwiki_defaults.nested_syntaxes = {} +let s:vimwiki_defaults.auto_export = 0 + +" diary +let s:vimwiki_defaults.diary_rel_path = 'diary/' +let s:vimwiki_defaults.diary_index = 'diary' +let s:vimwiki_defaults.diary_header = 'Diary' + +" Do not change this! Will wait till vim would be more datetime awareable. +let s:vimwiki_defaults.diary_link_fmt = '%Y-%m-%d' + +let s:vimwiki_defaults.diary_link_count = 4 + +"}}} + +" DEFAULT options {{{ +call s:default('list', [s:vimwiki_defaults]) +if &encoding == 'utf-8' + call s:default('upper', 'A-Z\u0410-\u042f') + call s:default('lower', 'a-z\u0430-\u044f') +else + call s:default('upper', 'A-Z') + call s:default('lower', 'a-z') +endif +call s:default('other', '0-9') +call s:default('stripsym', '_') +call s:default('badsyms', '') +call s:default('auto_checkbox', 1) +call s:default('use_mouse', 0) +call s:default('folding', 0) +call s:default('fold_trailing_empty_lines', 0) +call s:default('fold_lists', 0) +call s:default('menu', 'Vimwiki') +call s:default('global_ext', 1) +call s:default('hl_headers', 1) +call s:default('hl_cb_checked', 0) +call s:default('camel_case', 1) +call s:default('list_ignore_newline', 1) +call s:default('listsyms', ' .oOX') +if has("win32") + call s:default('browsers', + \ [ + \ expand('~').'\Local Settings\Application Data\Google\Chrome\Application\chrome.exe', + \ 'C:\Program Files\Opera\opera.exe', + \ 'C:\Program Files\Mozilla Firefox\firefox.exe', + \ 'C:\Program Files\Internet Explorer\iexplore.exe', + \ ]) +else + call s:default('browsers', + \ [ + \ 'opera', + \ 'firefox', + \ 'konqueror', + \ ]) +endif + +call s:default('use_calendar', 1) +call s:default('table_auto_fmt', 1) +call s:default('w32_dir_enc', '') + +call s:default('current_idx', 0) + +let upp = g:vimwiki_upper +let low = g:vimwiki_lower +let oth = g:vimwiki_other +let nup = low.oth +let nlo = upp.oth +let any = upp.nup + +let g:vimwiki_word1 = '\C\<['.upp.']['.nlo.']*['. + \ low.']['.nup.']*['.upp.']['.any.']*\>' +let g:vimwiki_word2 = '\[\[[^\]]\+\]\]' +let g:vimwiki_word3 = '\[\[[^\]]\+\]\[[^\]]\+\]\]' +if g:vimwiki_camel_case + let g:vimwiki_rxWikiWord = g:vimwiki_word1.'\|'.g:vimwiki_word2.'\|'.g:vimwiki_word3 +else + let g:vimwiki_rxWikiWord = g:vimwiki_word2.'\|'.g:vimwiki_word3 +endif +let g:vimwiki_rxWeblink = '\%("[^"(]\+\((\([^)]\+\))\)\?":\)\?'. + \'\%(https\?\|ftp\|gopher\|telnet\|file\|notes\|ms-help\):'. + \'\%(\%(\%(//\)\|\%(\\\\\)\)\+[A-Za-z0-9:#@%/;,$~()_?+=.&\\\-]*\)' +"}}} + +" AUTOCOMMANDS for all known wiki extensions {{{ +" Getting all extensions that different wikies could have +let extensions = {} +for wiki in g:vimwiki_list + if has_key(wiki, 'ext') + let extensions[wiki.ext] = 1 + else + let extensions['.wiki'] = 1 + endif +endfor + +augroup filetypedetect + " clear FlexWiki's stuff + au! * *.wiki +augroup end + +augroup vimwiki + autocmd! + for ext in keys(extensions) + exe 'autocmd BufEnter *'.ext.' call s:setup_buffer_enter()' + exe 'autocmd BufLeave,BufHidden *'.ext.' call s:setup_buffer_leave()' + + " ColorScheme could have or could have not a + " VimwikiHeader1..VimwikiHeader6 highlight groups. We need to refresh + " syntax after colorscheme change. + exe 'autocmd ColorScheme *'.ext.' call s:setup_colors()'. + \ ' | set syntax=vimwiki' + + " Format tables when exit from insert mode. Do not use textwidth to + " autowrap tables. + if g:vimwiki_table_auto_fmt + exe 'autocmd InsertLeave *'.ext.' call vimwiki_tbl#format(line("."))' + exe 'autocmd InsertEnter *'.ext.' call vimwiki_tbl#reset_tw(line("."))' + endif + endfor +augroup END +"}}} + +" COMMANDS {{{ +command! VimwikiUISelect call vimwiki#WikiUISelect() +command! -count VimwikiGoHome + \ call vimwiki#WikiGoHome(v:count1) +command! -count VimwikiTabGoHome tabedit <bar> + \ call vimwiki#WikiGoHome(v:count1) + +command! -count VimwikiMakeDiaryNote + \ call vimwiki_diary#make_note(v:count1) +command! -count VimwikiTabMakeDiaryNote tabedit <bar> + \ call vimwiki_diary#make_note(v:count1) +"}}} + +" MAPPINGS {{{ +if !hasmapto('<Plug>VimwikiGoHome') + map <silent><unique> <Leader>ww <Plug>VimwikiGoHome +endif +noremap <unique><script> <Plug>VimwikiGoHome :VimwikiGoHome<CR> + +if !hasmapto('<Plug>VimwikiTabGoHome') + map <silent><unique> <Leader>wt <Plug>VimwikiTabGoHome +endif +noremap <unique><script> <Plug>VimwikiTabGoHome :VimwikiTabGoHome<CR> + +if !hasmapto('<Plug>VimwikiUISelect') + map <silent><unique> <Leader>ws <Plug>VimwikiUISelect +endif +noremap <unique><script> <Plug>VimwikiUISelect :VimwikiUISelect<CR> + +if !hasmapto('<Plug>VimwikiMakeDiaryNote') + map <silent><unique> <Leader>w<Leader>w <Plug>VimwikiMakeDiaryNote +endif +noremap <unique><script> <Plug>VimwikiMakeDiaryNote :VimwikiMakeDiaryNote<CR> + +if !hasmapto('<Plug>VimwikiTabMakeDiaryNote') + map <silent><unique> <Leader>w<Leader>t <Plug>VimwikiTabMakeDiaryNote +endif +noremap <unique><script> <Plug>VimwikiTabMakeDiaryNote + \ :VimwikiTabMakeDiaryNote<CR> + +"}}} + +" MENU {{{ +function! s:build_menu(topmenu) + let idx = 0 + while idx < len(g:vimwiki_list) + let norm_path = fnamemodify(VimwikiGet('path', idx), ':h:t') + let norm_path = escape(norm_path, '\ ') + execute 'menu '.a:topmenu.'.Open\ index.'.norm_path. + \ ' :call vimwiki#WikiGoHome('.(idx + 1).')<CR>' + execute 'menu '.a:topmenu.'.Open/Create\ diary\ note.'.norm_path. + \ ' :call vimwiki_diary#make_note('.(idx + 1).')<CR>' + let idx += 1 + endwhile +endfunction + +function! s:build_table_menu(topmenu) + exe 'menu '.a:topmenu.'.-Sep- :' + exe 'menu '.a:topmenu.'.Table.Create\ (enter\ cols\ rows) :VimwikiTable ' + exe 'nmenu '.a:topmenu.'.Table.Format<tab>gqq gqq' + exe 'nmenu disable '.a:topmenu.'.Table' +endfunction + +if !empty(g:vimwiki_menu) + call s:build_menu(g:vimwiki_menu) + call s:build_table_menu(g:vimwiki_menu) +endif +" }}} + +" CALENDAR Hook "{{{ +if g:vimwiki_use_calendar + let g:calendar_action = 'vimwiki_diary#calendar_action' +endif +"}}} + +let &cpo = s:old_cpo diff --git a/plugin/vstplugin.vim b/plugin/vstplugin.vim new file mode 100644 index 0000000..5890535 --- /dev/null +++ b/plugin/vstplugin.vim @@ -0,0 +1,68 @@ +" Vim reStructured Text +" (c) Mikolaj Machowski 2006 +" Author: Mikolaj Machowski ( mikmach AT wp DOT pl ) +" Last Change: 4 Nov 2006 +" Version: 1.4 +" License: +" Copyright (C) 2006 Mikolaj Machowski <mikmach@wp.pl> +" +" This script is free software; you can redistribute it and/or +" modify it under the terms of the GNU Library General Public +" License as published by the Free Software Foundation; either +" version 2 of the License, or (at your option) any later version. +" +" This library is distributed in the hope that it will be useful, +" but WITHOUT ANY WARRANTY; without even the implied warranty of +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +" Library General Public License for more details. +" +" You should have received a copy of the GNU Library General Public License +" along with this library; see the file COPYING.LIB. If not, write to +" the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +" Boston, MA 02110-1301, USA. +" +" VST requires Vim7 +if v:version < 700 + finish +endif + +" Command :Vst +command! -range=% -nargs=? -complete=custom,VST_Args Vst call vst#vst#VST_Export(<line1>, <line2>, <q-args>) +command! -range=% -nargs=? -complete=custom,VST_Args Vsti call vst#vst#VST_InstantWrapper(<line1>, <line2>, <q-args>) +command! -range=% -nargs=? -complete=custom,VST_Args Vstm call VST_Menus() + +" VST_Args: Command line completion for :Vst command {{{ +function! VST_Args(A, C, P) + let args = "html,tex,latex,pdf,toc,head,fold,link,slink,rep,srep,preproc,help,rest" + return substitute(args, ',', '\n', 'g') +endfunction +" }}} +" Menus {{{ +function! VST_Menus() + if has("gui_running") + menu VreST.Export\ to\ HTML :Vst html<cr> + menu VreST.Export\ to\ LaTeX :Vst tex<cr> + menu VreST.Export\ to\ PDF :Vst pdf<cr> + menu VreST.Export\ to\ reST :Vst rest<cr> + menu VreST.Fold :Vst fold<cr> + menu VreST.Headers :Vst head<cr> + menu VreST.TOC :Vst toc<cr> + menu VreST.Help :Vst help<cr> + inoremenu VreST.Export\ to\ HTML <c-o>:Vst html<cr> + inoremenu VreST.Export\ to\ LaTeX <c-o>:Vst tex<cr> + inoremenu VreST.Export\ to\ PDF <c-o>:Vst pdf<cr> + inoremenu VreST.Export\ to\ reST <c-o>:Vst rest<cr> + inoremenu VreST.Fold <c-o>:Vst fold<cr> + inoremenu VreST.Headers <c-o>:Vst head<cr> + inoremenu VreST.TOC <c-o>:Vst toc<cr> + inoremenu VreST.Help <c-o>:Vst help<cr> + endif +endfunction +if exists("g:vst_showmenu") && g:vst_load_menus != 0 + call VST_Menus() +endif +" }}} +" Load auxiliary mappings: +call vst#vst#VST_AuxiliaryMappings() + +" vim:fdm=marker:ff=unix:noet:ts=4:sw=4:nowrap diff --git a/pol.utf8.add b/pol.utf8.add new file mode 100644 index 0000000..1b81e89 --- /dev/null +++ b/pol.utf8.add @@ -0,0 +1,3 @@ +Cohenie +oddziaÅ‚ywuje +Czterooki diff --git a/pol.utf8.add.spl b/pol.utf8.add.spl new file mode 100644 index 0000000..8db08aa Binary files /dev/null and b/pol.utf8.add.spl differ diff --git a/snippets/_.snippets b/snippets/_.snippets new file mode 100644 index 0000000..68a5a58 --- /dev/null +++ b/snippets/_.snippets @@ -0,0 +1,24 @@ +# Global snippets + +# (c) holds no legal value ;) +snippet c) + `&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2} +snippet date + `strftime("%Y-%m-%d")` +snippet datetime + `strftime("%Y-%m-%d %H:%M:%S")` +snippet ,, + „ +snippet '' + †+# pause sign. Long dash +snippet -- + — +# simple dash (shorter then minus, used for concatenating words, like thirty-nine) +snippet - + †+# this is for hyphenation hints (SHY) +snippet ~ + ­ +snippet ... + … diff --git a/snippets/autoit.snippets b/snippets/autoit.snippets new file mode 100644 index 0000000..690018c --- /dev/null +++ b/snippets/autoit.snippets @@ -0,0 +1,66 @@ +snippet if + If ${1:condition} Then + ${2:; True code} + EndIf +snippet el + Else + ${1} +snippet elif + ElseIf ${1:condition} Then + ${2:; True code} +# If/Else block +snippet ifel + If ${1:condition} Then + ${2:; True code} + Else + ${3:; Else code} + EndIf +# If/ElseIf/Else block +snippet ifelif + If ${1:condition 1} Then + ${2:; True code} + ElseIf ${3:condition 2} Then + ${4:; True code} + Else + ${5:; Else code} + EndIf +# Switch block +snippet switch + Switch (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSwitch +# Select block +snippet select + Select (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSelect +# While loop +snippet while + While (${1:condition}) + ${2:; code...} + WEnd +# For loop +snippet for + For ${1:n} = ${3:1} to ${2:count} + ${4:; code...} + Next +# New Function +snippet func + Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${4:Return} + EndFunc +# Message box +snippet msg + MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"}) +# Debug Message +snippet debug + MsgBox(0, "Debug", ${1:"Debug Message"}) +# Show Variable Debug Message +snippet showvar + MsgBox(0, "${1:VarName}", $1) diff --git a/snippets/c.snippets b/snippets/c.snippets new file mode 100644 index 0000000..89b81ba --- /dev/null +++ b/snippets/c.snippets @@ -0,0 +1,110 @@ +# main() +snippet main + int main(int argc, const char *argv[]) + { + ${1} + return 0; + } +# #include <...> +snippet inc + #include <${1:stdio}.h>${2} +# #include "..." +snippet Inc + #include "${1:`Filename("$1.h")`}"${2} +# #ifndef ... #define ... #endif +snippet Def + #ifndef $1 + #define ${1:SYMBOL} ${2:value} + #endif${3} +snippet def + #define +snippet ifdef + #ifdef ${1:FOO} + ${2:#define } + #endif +snippet #if + #if ${1:FOO} + ${2} + #endif +# Header Include-Guard +# (the randomizer code is taken directly from TextMate; it could probably be +# cleaner, I don't know how to do it in vim script) +snippet once + #ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`} + + #define $1 + + ${2} + + #endif /* end of include guard: $1 */ +# If Condition +snippet if + if (${1:/* condition */}) { + ${2:/* code */} + } +snippet el + else { + ${1} + } +# Tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# Do While Loop +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# While Loop +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# For Loop +snippet for + for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) { + ${4:/* code */} + } +# Custom For Loop +snippet forr + for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) { + ${5:/* code */} + } +# Function +snippet fun + ${1:void} ${2:function_name}(${3}) + { + ${4:/* code */} + } +# Function Declaration +snippet fund + ${1:void} ${2:function_name}(${3});${4} +# Typedef +snippet td + typedef ${1:int} ${2:MyCustomType};${3} +# Struct +snippet st + struct ${1:`Filename('$1_t', 'name')`} { + ${2:/* data */} + }${3: /* optional variable list */};${4} +# Typedef struct +snippet tds + typedef struct ${2:_$1 }{ + ${3:/* data */} + } ${1:`Filename('$1_t', 'name')`}; +# Typdef enum +snippet tde + typedef enum { + ${1:/* data */} + } ${2:foo}; +# printf +# unfortunately version this isn't as nice as TextMates's, given the lack of a +# dynamic `...` +snippet pr + printf("${1:%s}\n"${2});${3} +# fprintf (again, this isn't as nice as TextMate's version, but it works) +snippet fpr + fprintf(${1:stderr}, "${2:%s}\n"${3});${4} +snippet . + [${1}]${2} +snippet un + unsigned diff --git a/snippets/cpp.snippets b/snippets/cpp.snippets new file mode 100644 index 0000000..e4850cd --- /dev/null +++ b/snippets/cpp.snippets @@ -0,0 +1,30 @@ +# Read File Into Vector +snippet readfile + std::vector<char> v; + if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) { + char buf[1024]; + while (size_t len = fread(buf, 1, sizeof(buf), $2)) + v.insert(v.end(), buf, buf + len); + fclose($2); + }${3} +# std::map +snippet map + std::map<${1:key}, ${2:value}> map${3}; +# std::vector +snippet vector + std::vector<${1:char}> v${2}; +# Namespace +snippet ns + namespace ${1:`Filename('', 'my')`} { + ${2} + } /* $1 */ +# Class +snippet cl + class ${1:`Filename('$1_t', 'name')`} { + public: + $1 (${2:arguments}); + virtual ~$1 (); + + private: + ${3:/* data */} + }; diff --git a/snippets/html.snippets b/snippets/html.snippets new file mode 100644 index 0000000..f1adb68 --- /dev/null +++ b/snippets/html.snippets @@ -0,0 +1,211 @@ +# Some useful Unicode entities +# Non-Breaking Space +snippet nbs +   +# ↠+snippet left + ← +# → +snippet right + → +# ↑ +snippet up + ↑ +# ↓ +snippet down + ↓ +# ↩ +snippet return + ↩ +# ⇤ +snippet backtab + ⇤ +# ⇥ +snippet tab + ⇥ +# ⇧ +snippet shift + ⇧ +# ⌃ +snippet control + ⌃ +# ⌅ +snippet enter + ⌅ +# ⌘ +snippet command + ⌘ +# ⌥ +snippet option + ⌥ +# ⌦ +snippet delete + ⌦ +# ⌫ +snippet backspace + ⌫ +# ⎋ +snippet escape + ⎋ +# Generic Doctype +snippet doctype HTML 4.01 Strict + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"" + "http://www.w3.org/TR/html4/strict.dtd"> +snippet doctype HTML 4.01 Transitional + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"" + "http://www.w3.org/TR/html4/loose.dtd"> +snippet doctype HTML 5 + <!DOCTYPE HTML> +snippet doctype XHTML 1.0 Frameset + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +snippet doctype XHTML 1.0 Strict + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +snippet doctype XHTML 1.0 Transitional + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +snippet doctype XHTML 1.1 + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +# HTML Doctype 4.01 Strict +snippet docts + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"" + "http://www.w3.org/TR/html4/strict.dtd"> +# HTML Doctype 4.01 Transitional +snippet doct + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"" + "http://www.w3.org/TR/html4/loose.dtd"> +# HTML Doctype 5 +snippet doct5 + <!DOCTYPE HTML> +# XHTML Doctype 1.0 Frameset +snippet docxf + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> +# XHTML Doctype 1.0 Strict +snippet docxs + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +# XHTML Doctype 1.0 Transitional +snippet docxt + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +# XHTML Doctype 1.1 +snippet docx + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +snippet html + <html> + ${1} + </html> +snippet xhtml + <html xmlns="http://www.w3.org/1999/xhtml"> + ${1} + </html> +snippet body + <body> + ${1} + </body> +snippet head + <head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`> + + <title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`} + ${2} + +snippet title + ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}${2} +snippet script + ${2} +snippet scriptsrc + ${2} +snippet style + ${3} +snippet base + +snippet r + +snippet div +
+ ${2} +
+# Embed QT Movie +snippet movie + + + + + + ${6} +snippet fieldset +
+ ${1:name} + + ${3} +
+snippet form +
+ ${3} + + +

+
+snippet h1 +

${2:$1}

+snippet input + ${4} +snippet label + ${7} +snippet link + ${4} +snippet mailto + ${3:email me} +snippet meta + ${3} +snippet opt + ${3} +snippet optt + ${2} +snippet select + ${5} +snippet table + + + + + + + + + + + + + + + + + + + + +
${1:caption}
${2:header}
${3:footer}
+ ${4:row1} +
+ ${4:row2} +
+snippet textarea + ${5} diff --git a/snippets/java.snippets b/snippets/java.snippets new file mode 100644 index 0000000..fd705cb --- /dev/null +++ b/snippets/java.snippets @@ -0,0 +1,78 @@ +snippet main + public static void main (String [] args) + { + ${1:/* code */} + } +snippet pu + public +snippet po + protected +snippet pr + private +snippet st + static +snippet fi + final +snippet ab + abstract +snippet re + return +snippet br + break; +snippet de + default: + ${1} +snippet ca + catch(${1:Exception} ${2:e}) ${3} +snippet th + throw +snippet sy + synchronized +snippet im + import +snippet j.u + java.util +snippet j.i + java.io. +snippet j.b + java.beans. +snippet j.n + java.net. +snippet j.m + java.math. +snippet if + if (${1}) ${2} +snippet el + else +snippet elif + else if (${1}) ${2} +snippet wh + while (${1}) ${2} +snippet for + for (${1}; ${2}; ${3}) ${4} +snippet fore + for (${1} : ${2}) ${3} +snippet sw + switch (${1}) ${2} +snippet cs + case ${1}: + ${2} + ${3} +snippet tc + public class ${1:`Filename()`} extends ${2:TestCase} +snippet t + public void test${1:Name}() throws Exception ${2} +snippet cl + class ${1:`Filename("", "untitled")`} ${2} +snippet in + interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3} +snippet m + ${1:void} ${2:method}(${3}) ${4:throws }${5} +snippet v + ${1:String} ${2:var}${3: = null}${4};${5} +snippet co + static public final ${1:String} ${2:var} = ${3};${4} +snippet cos + static public final String ${1:var} = "${2}";${3} +snippet as + assert ${1:test} : "${2:Failure message}";${3} diff --git a/snippets/javascript.snippets b/snippets/javascript.snippets new file mode 100644 index 0000000..51f5e05 --- /dev/null +++ b/snippets/javascript.snippets @@ -0,0 +1,74 @@ +# Prototype +snippet proto + ${1:class_name}.prototype.${2:method_name} = + function(${3:first_argument}) { + ${4:// body...} + }; +# Function +snippet fun + function ${1:function_name} (${2:argument}) { + ${3:// body...} + } +# Anonymous Function +snippet f + function(${1}) {${2}}; +# if +snippet if + if (${1:true}) {${2}}; +# if ... else +snippet ife + if (${1:true}) {${2}} + else{${3}}; +# tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# switch +snippet switch + switch(${1:expression}) { + case '${3:case}': + ${4:// code} + break; + ${5} + default: + ${2:// code} + } +# case +snippet case + case '${1:case}': + ${2:// code} + break; + ${3} +# for (...) {...} +snippet for + for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) { + ${4:$1[$2]} + }; +# for (...) {...} (Improved Native For-Loop) +snippet forr + for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) { + ${4:$1[$2]} + }; +# while (...) {...} +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# do...while +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# Object Method +snippet :f + ${1:method_name}: function(${2:attribute}) { + ${4} + }${3:,} +# setTimeout function +snippet timeout + setTimeout(function() {${3}}${2}, ${1:10}; +# Get Elements +snippet get + getElementsBy${1:TagName}('${2}')${3} +# Get Element +snippet gett + getElementBy${1:Id}('${2}')${3} diff --git a/snippets/mako.snippets b/snippets/mako.snippets new file mode 100644 index 0000000..2a0aef9 --- /dev/null +++ b/snippets/mako.snippets @@ -0,0 +1,54 @@ +snippet def + <%def name="${1:name}"> + ${2:} + +snippet call + <%call expr="${1:name}"> + ${2:} + +snippet doc + <%doc> + ${1:} + +snippet text + <%text> + ${1:} + +snippet for + % for ${1:i} in ${2:iter}: + ${3:} + % endfor +snippet if if + % if ${1:condition}: + ${2:} + % endif +snippet if if/else + % if ${1:condition}: + ${2:} + % else: + ${3:} + % endif +snippet try + % try: + ${1:} + % except${2:}: + ${3:pass} + % endtry +snippet wh + % while ${1:}: + ${2:} + % endwhile +snippet $ + ${ ${1:} } +snippet <% + <% ${1:} %> +snippet +snippet inherit + <%inherit file="${1:filename}" /> +snippet include + <%include file="${1:filename}" /> +snippet namespace + <%namespace file="${1:name}" /> +snippet page + <%page args="${1:}" /> diff --git a/snippets/mkd.snippets b/snippets/mkd.snippets new file mode 100644 index 0000000..05b737a --- /dev/null +++ b/snippets/mkd.snippets @@ -0,0 +1,37 @@ +snippet pgbreak +

 

+snippet brk +

 

+snippet head + + + +snippet toc + ///Table of Contents/// +snippet title + # ${1:title} +snippet author + # ${1: author} +snippet autor + # ${1: author} +snippet chapter + ## ${1: chapter} +snippet bold + **${1: bold}** +snippet italic + *${1:italic}* +snippet img + !${1:[Alt text]}(${2:/path/to/img.jpg}${3: "Optional title"}) +snippet table + | |* Col 1 *|* Col 2 *| + |* Row 1 *| (1, 1) | (1, 2) | + |* Row 2 *| (2, 1) | (2, 2) | diff --git a/snippets/objc.snippets b/snippets/objc.snippets new file mode 100644 index 0000000..4749bb7 --- /dev/null +++ b/snippets/objc.snippets @@ -0,0 +1,184 @@ +# #import <...> +snippet Imp + #import <${1:Cocoa/Cocoa.h}>${2} +# #import "..." +snippet imp + #import "${1:`Filename()`.h}"${2} +# @selector(...) +snippet sel + @selector(${1:method}:)${3} +# @"..." string +snippet s + @"${1}"${2} +# Object +snippet o + ${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5} +# NSLog(...) +snippet log + NSLog(@"${1:%@}"${2});${3} +# Class +snippet objc + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + { + } + @end + + @implementation $1 + ${3} + @end +# Class Interface +snippet int + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + {${3} + } + ${4} + @end +# Class Implementation +snippet impl + @implementation ${1:`Filename('', 'someClass')`} + ${2} + @end +snippet init + - (id)init + { + [super init]; + return self; + } +snippet ifself + if (self = [super init]) { + ${1:/* code */} + } + return self; +snippet ibo + IBOutlet ${1:NSSomeClass} *${2:$1};${3} +# Category +snippet cat + @interface ${1:NSObject} (${2:Category}) + @end + + @implementation $1 ($2) + ${3} + @end +# Category Interface +snippet cath + @interface ${1:NSObject} (${2:Category}) + ${3} + @end +# NSArray +snippet array + NSMutableArray *${1:array} = [NSMutable array];${2} +# NSDictionary +snippet dict + NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2} +# NSBezierPath +snippet bez + NSBezierPath *${1:path} = [NSBezierPath bezierPath];${2} +# Method +snippet m + - (${1:id})${2:method} + { + ${3} + } +# Method declaration +snippet md + - (${1:id})${2:method};${3} +# IBAction declaration +snippet ibad + - (IBAction)${1:method}:(${2:id})sender;${3} +# IBAction method +snippet iba + - (IBAction)${1:method}:(${2:id})sender + { + ${3} + } +# awakeFromNib method +snippet wake + - (void)awakeFromNib + { + ${1} + } +# Class Method +snippet M + + (${1:id})${2:method} + {${3} + return nil; + } +# Sub-method (Call super) +snippet sm + - (${1:id})${2:method} + { + [super $2];${3} + return self; + } +# Method: Initialize +snippet I + + (void) initialize + { + [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWIthObjectsAndKeys: + ${1}@"value", @"key", + nil]]; + } +# Accessor Methods For: +# Object +snippet objacc + - (${1:id})${2:thing} + { + return $2; + } + + - (void)set$2:($1)${3:new$2} + { + [$3 retain]; + [$2 release]; + $2 = $3; + }${4} +# for (object in array) +snippet forin + for (${1:Class} *${2:some$1} in ${3:array}) { + ${4} + } +snippet forarray + unsigned int ${1:object}Count = [${2:array} count]; + + for (unsigned int index = 0; index < $1Count; index++) { + ${3:id} $1 = [$2 $1AtIndex:index]; + ${4} + } +# IBOutlet +# @property (Objective-C 2.0) +snippet prop + @property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4} +# @synthesize (Objective-C 2.0) +snippet syn + @synthesize ${1:property};${2} +# [[ alloc] init] +snippet alloc + [[${1:foo} alloc] init${2}];${3} +# retain +snippet ret + [${1:foo} retain];${2} +# release +snippet rel + [${1:foo} release]; + ${2:$1 = nil;} +# autorelease +snippet arel + [${1:foo} autorelease]; +# autorelease pool +snippet pool + NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init]; + ${2:/* code */} + [$1 drain]; +# Throw an exception +snippet except + NSException *${1:badness}; + $1 = [NSException exceptionWithName:@"${2:$1Name}" + reason:@"${3}" + userInfo:nil]; + [$1 raise]; +snippet prag + #pragma mark ${1:foo} +snippet cl + @class ${1:Foo};${2} +snippet color + [[NSColor ${1:blackColor}] set]; diff --git a/snippets/perl.snippets b/snippets/perl.snippets new file mode 100644 index 0000000..cf8f9fc --- /dev/null +++ b/snippets/perl.snippets @@ -0,0 +1,91 @@ +# #!/usr/bin/perl +snippet #! + #!/usr/bin/perl + +# Hash Pointer +snippet . + => +# Function +snippet sub + sub ${1:function_name} { + ${2:#body ...} + } +# Conditional +snippet if + if (${1}) { + ${2:# body...} + } +# Conditional if..else +snippet ife + if (${1}) { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if (${1}) { + ${2:# body...} + } elsif (${3}) { + ${4:# elsif...} + } else { + ${5:# else...} + } +# Conditional One-line +snippet xif + ${1:expression} if ${2:condition};${3} +# Unless conditional +snippet unless + unless (${1}) { + ${2:# body...} + } +# Unless conditional One-line +snippet xunless + ${1:expression} unless ${2:condition};${3} +# Try/Except +snippet eval + eval { + ${1:# do something risky...} + }; + if ($@) { + ${2:# handle failure...} + } +# While Loop +snippet wh + while (${1}) { + ${2:# body...} + } +# While Loop One-line +snippet xwh + ${1:expression} while ${2:condition};${3} +# For Loop +snippet for + for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach my $${1:x} (@${2:array}) { + ${3:# body...} + } +# Foreach Loop One-line +snippet xfore + ${1:expression} foreach @${2:array};${3} +# Package +snippet cl + package ${1:ClassName}; + + use base qw(${2:ParentClass}); + + sub new { + my $class = shift; + $class = ref $class if ref $class; + my $self = bless {}, $class; + $self; + } + + 1;${3} +# Read File +snippet slurp + my $${1:var}; + { local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = ; close FILE }${3} diff --git a/snippets/php.snippets b/snippets/php.snippets new file mode 100644 index 0000000..3ce9e26 --- /dev/null +++ b/snippets/php.snippets @@ -0,0 +1,216 @@ +snippet php + +snippet ec + echo "${1:string}"${2}; +snippet inc + include '${1:file}';${2} +snippet inc1 + include_once '${1:file}';${2} +snippet req + require '${1:file}';${2} +snippet req1 + require_once '${1:file}';${2} +# $GLOBALS['...'] +snippet globals + $GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5} +snippet $_ COOKIE['...'] + $_COOKIE['${1:variable}']${2} +snippet $_ ENV['...'] + $_ENV['${1:variable}']${2} +snippet $_ FILES['...'] + $_FILES['${1:variable}']${2} +snippet $_ Get['...'] + $_GET['${1:variable}']${2} +snippet $_ POST['...'] + $_POST['${1:variable}']${2} +snippet $_ REQUEST['...'] + $_REQUEST['${1:variable}']${2} +snippet $_ SERVER['...'] + $_SERVER['${1:variable}']${2} +snippet $_ SESSION['...'] + $_SESSION['${1:variable}']${2} +# Start Docblock +snippet /* + /** + * ${1} + **/ +# Class - post doc +snippet doc_cp + /** + * ${1:undocumented class} + * + * @package ${2:default} + * @author ${3:`g:snips_author`} + **/${4} +# Class Variable - post doc +snippet doc_vp + /** + * ${1:undocumented class variable} + * + * @var ${2:string} + **/${3} +# Class Variable +snippet doc_v + /** + * ${3:undocumented class variable} + * + * @var ${4:string} + **/ + ${1:var} $${2};${5} +# Class +snippet doc_c + /** + * ${3:undocumented class} + * + * @packaged ${4:default} + * @author ${5:`g:snips_author`} + **/ + ${1:}class ${2:} + {${6} + } // END $1class $2 +# Constant Definition - post doc +snippet doc_dp + /** + * ${1:undocumented constant} + **/${2} +# Constant Definition +snippet doc_d + /** + * ${3:undocumented constant} + **/ + define(${1}, ${2});${4} +# Function - post doc +snippet doc_fp + /** + * ${1:undocumented function} + * + * @return ${2:void} + * @author ${3:`g:snips_author`} + **/${4} +# Function signature +snippet doc_s + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3});${7} +# Function +snippet doc_f + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3}) + {${7} + } +# Header +snippet doc_h + /** + * ${1} + * + * @author ${2:`g:snips_author`} + * @version ${3:$Id$} + * @copyright ${4:$2}, `strftime('%d %B, %Y')` + * @package ${5:default} + **/ + + /** + * Define DocBlock + *// +# Interface +snippet doc_i + /** + * ${2:undocumented class} + * + * @package ${3:default} + * @author ${4:`g:snips_author`} + **/ + interface ${1:} + {${5} + } // END interface $1 +# class ... +snippet class + /** + * ${1} + **/ + class ${2:ClassName} + { + ${3} + function ${4:__construct}(${5:argument}) + { + ${6:// code...} + } + } +# define(...) +snippet def + define('${1}'${2});${3} +# defined(...) +snippet def? + ${1}defined('${2}')${3} +snippet wh + while (${1:/* condition */}) { + ${2:// code...} + } +# do ... while +snippet do + do { + ${2:// code... } + } while (${1:/* condition */}); +snippet if + if (${1:/* condition */}) { + ${2:// code...} + } +snippet ife + if (${1:/* condition */}) { + ${2:// code...} + } else { + ${3:// code...} + } + ${4} +snippet else + else { + ${1:// code...} + } +snippet elseif + elseif (${1:/* condition */}) { + ${2:// code...} + } +# Tertiary conditional +snippet t + $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5} +snippet switch + switch ($${1:variable}) { + case '${2:value}': + ${3:// code...} + break; + ${5} + default: + ${4:// code...} + break; + } +snippet case + case '${1:value}': + ${2:// code...} + break;${3} +snippet for + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4: // code...} + } +snippet foreach + foreach ($${1:variable} as $${2:key}) { + ${3:// code...} + } +snippet fun + ${1:public }function ${2:FunctionName}(${3}) + { + ${4:// code...} + } +# $... = array (...) +snippet array + $${1:arrayName} = array('${2}' => ${3});${4} diff --git a/snippets/python.snippets b/snippets/python.snippets new file mode 100644 index 0000000..9454a0d --- /dev/null +++ b/snippets/python.snippets @@ -0,0 +1,108 @@ +snippet #! + #!/usr/bin/python + +snippet imp + import ${1:module} +# Module Docstring +snippet docs + ''' + File: ${1:`Filename('$1.py', 'foo.py')`} + Author: ${2:`g:snips_author`} + Description: ${3} + ''' +snippet wh + while ${1:condition}: + ${2:# code...} +snippet for + for ${1:needle} in ${2:haystack}: + ${3:# code...} +# New Class +snippet cl + class ${1:ClassName}(${2:object}): + """${3:docstring for $1}""" + def __init__(self, ${4:arg}): + ${5:super($1, self).__init__()} + self.$4 = $4 + ${6} +# New Function +snippet def + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + """${3:docstring for $1}""" + ${4:pass} +snippet deff + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${3} +# New Method +snippet defs + def ${1:mname}(self, ${2:arg}): + ${3:pass} +# New Property +snippet property + def ${1:foo}(): + doc = "${2:The $1 property.}" + def fget(self): + ${3:return self._$1} + def fset(self, value): + ${4:self._$1 = value} +# Lambda +snippet ld + ${1:var} = lambda ${2:vars} : ${3:action} +snippet . + self. +snippet try Try/Except + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} +snippet try Try/Except/Else + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} +snippet try Try/Except/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + finally: + ${5:pass} +snippet try Try/Except/Else/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} + finally: + ${6:pass} +# if __name__ == '__main__': +snippet ifmain + if __name__ == '__main__': + ${1:main()} +# __magic__ +snippet _ + __${1:init}__${2} + +# gryf stuff. Debuggers +snippet dbg + import ipdb; ipdb.set_trace() +snippet pdb + import pdb; pdb.set_trace() +snippet winpdb + import rpdb2; rpdb2.start_embedded_debugger('password') +snippet pupdb + from pudb import set_trace; set_trace() +snippet vimpdb + import vimpdb; vimpdb.set_trace() +snippet docmodule + """ + Project: ${1:pyGTKtalog} + Description: ${2:Tests for DataBase class.} + Type: ${3:test} + Author: ${4:Roman 'gryf' Dobosz, gryf73@gmail.com} + Created: ${5:`strftime("%Y-%m-%d %H:%M:%S")`} + """ +snippet dupa + dwie dupy diff --git a/snippets/ruby.snippets b/snippets/ruby.snippets new file mode 100644 index 0000000..bf1d7f1 --- /dev/null +++ b/snippets/ruby.snippets @@ -0,0 +1,420 @@ +# #!/usr/bin/ruby +snippet #! + #!/usr/bin/ruby + +# New Block +snippet =b + =begin rdoc + ${1} + =end +snippet y + :yields: ${1:arguments} +snippet rb + #!/usr/bin/env ruby -wKU + +snippet req + require "${1}"${2} +snippet # + # => +snippet end + __END__ +snippet case + case ${1:object} + when ${2:condition} + ${3} + end +snippet when + when ${1:condition} + ${2} +snippet def + def ${1:method_name} + ${2} + end +snippet deft + def test_${1:case_name} + ${2} + end +snippet if + if ${1:condition} + ${2} + end +snippet ife + if ${1:condition} + ${2} + else + ${3} + end +snippet elsif + elsif ${1:condition} + ${2} +snippet unless + unless ${1:condition} + ${2} + end +snippet while + while ${1:condition} + ${2} + end +snippet until + until ${1:condition} + ${2} + end +snippet cla class .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet cla class .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + def initialize(${2:args}) + ${3} + end + + + end +snippet cla class .. < ParentClass .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass} + def initialize(${3:args}) + ${4} + end + + + end +snippet cla ClassName = Struct .. do .. end + ${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do + def ${3:method_name} + ${4} + end + + + end +snippet cla class BlankSlate .. initialize .. end + class ${1:BlankSlate} + instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ } +snippet cla class << self .. end + class << ${1:self} + ${2} + end +# class .. < DelegateClass .. initialize .. end +snippet cla- + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass}) + def initialize(${3:args}) + super(${4:del_obj}) + + ${5} + end + + + end +snippet mod module .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet mod module .. module_function .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module_function + + ${2} + end +snippet mod module .. ClassMethods .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module ClassMethods + ${2} + end + + module InstanceMethods + + end + + def self.included(receiver) + receiver.extend ClassMethods + receiver.send :include, InstanceMethods + end + end +# attr_reader +snippet r + attr_reader :${1:attr_names} +# attr_writer +snippet w + attr_writer :${1:attr_names} +# attr_accessor +snippet rw + attr_accessor :${1:attr_names} +# include Enumerable +snippet Enum + include Enumerable + + def each(&block) + ${1} + end +# include Comparable +snippet Comp + include Comparable + + def <=>(other) + ${1} + end +# extend Forwardable +snippet Forw- + extend Forwardable +# def self +snippet defs + def self.${1:class_method_name} + ${2} + end +# def method_missing +snippet defmm + def method_missing(meth, *args, &blk) + ${1} + end +snippet defd + def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name} +snippet defds + def_delegators :${1:@del_obj}, :${2:del_methods} +snippet am + alias_method :${1:new_name}, :${2:old_name} +snippet app + if __FILE__ == $PROGRAM_NAME + ${1} + end +# usage_if() +snippet usai + if ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +# usage_unless() +snippet usau + unless ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +snippet array + Array.new(${1:10}) { |${2:i}| ${3} } +snippet hash + Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} } +snippet file File.foreach() { |line| .. } + File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} } +snippet file File.read() + File.read(${1:"path/to/file"})${2} +snippet Dir Dir.global() { |file| .. } + Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} } +snippet Dir Dir[".."] + Dir[${1:"glob/**/*.rb"}]${2} +snippet dir + Filename.dirname(__FILE__) +snippet deli + delete_if { |${1:e}| ${2} } +snippet fil + fill(${1:range}) { |${2:i}| ${3} } +# flatten_once() +snippet flao + inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3} +snippet zip + zip(${1:enums}) { |${2:row}| ${3} } +# downto(0) { |n| .. } +snippet dow + downto(${1:0}) { |${2:n}| ${3} } +snippet ste + step(${1:2}) { |${2:n}| ${3} } +snippet tim + times { |${1:n}| ${2} } +snippet upt + upto(${1:1.0/0.0}) { |${2:n}| ${3} } +snippet loo + loop { ${1} } +snippet ea + each { |${1:e}| ${2} } +snippet eab + each_byte { |${1:byte}| ${2} } +snippet eac- each_char { |chr| .. } + each_char { |${1:chr}| ${2} } +snippet eac- each_cons(..) { |group| .. } + each_cons(${1:2}) { |${2:group}| ${3} } +snippet eai + each_index { |${1:i}| ${2} } +snippet eak + each_key { |${1:key}| ${2} } +snippet eal + each_line { |${1:line}| ${2} } +snippet eap + each_pair { |${1:name}, ${2:val}| ${3} } +snippet eas- + each_slice(${1:2}) { |${2:group}| ${3} } +snippet eav + each_value { |${1:val}| ${2} } +snippet eawi + each_with_index { |${1:e}, ${2:i}| ${3} } +snippet reve + reverse_each { |${1:e}| ${2} } +snippet inj + inject(${1:init}) { |${2:mem}, ${3:var}| ${4} } +snippet map + map { |${1:e}| ${2} } +snippet mapwi- + enum_with_index.map { |${1:e}, ${2:i}| ${3} } +snippet sor + sort { |a, b| ${1} } +snippet sorb + sort_by { |${1:e}| ${2} } +snippet ran + sort_by { rand } +snippet all + all? { |${1:e}| ${2} } +snippet any + any? { |${1:e}| ${2} } +snippet cl + classify { |${1:e}| ${2} } +snippet col + collect { |${1:e}| ${2} } +snippet det + detect { |${1:e}| ${2} } +snippet fet + fetch(${1:name}) { |${2:key}| ${3} } +snippet fin + find { |${1:e}| ${2} } +snippet fina + find_all { |${1:e}| ${2} } +snippet gre + grep(${1:/pattern/}) { |${2:match}| ${3} } +snippet sub + ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} } +snippet sca + scan(${1:/pattern/}) { |${2:match}| ${3} } +snippet max + max { |a, b|, ${1} } +snippet min + min { |a, b|, ${1} } +snippet par + partition { |${1:e}|, ${2} } +snippet rej + reject { |${1:e}|, ${2} } +snippet sel + select { |${1:e}|, ${2} } +snippet lam + lambda { |${1:args}| ${2} } +snippet do + do |${1:variable}| + ${2} + end +snippet : + :${1:key} => ${2:"value"}${3} +snippet ope + open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} } +# path_from_here() +snippet patfh + File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2} +# unix_filter {} +snippet unif + ARGF.each_line${1} do |${2:line}| + ${3} + end +# option_parse {} +snippet optp + require "optparse" + + options = {${1:default => "args"}} + + ARGV.options do |opts| + opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} +snippet opt + opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String}, + "${4:Option description.}") do |${5:opt}| + ${6} + end +snippet tc + require "test/unit" + + require "${1:library_file_name}" + + class Test${2:$1} < Test::Unit::TestCase + def test_${3:case_name} + ${4} + end + end +snippet ts + require "test/unit" + + require "tc_${1:test_case_file}" + require "tc_${2:test_case_file}"${3} +snippet as + assert(${1:test}, "${2:Failure message.}")${3} +snippet ase + assert_equal(${1:expected}, ${2:actual})${3} +snippet asne + assert_not_equal(${1:unexpected}, ${2:actual})${3} +snippet asid + assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4} +snippet asio + assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3} +snippet asko + assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3} +snippet asn + assert_nil(${1:instance})${2} +snippet asnn + assert_not_nil(${1:instance})${2} +snippet asm + assert_match(/${1:expected_pattern}/, ${2:actual_string})${3} +snippet asnm + assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3} +snippet aso + assert_operator(${1:left}, :${2:operator}, ${3:right})${4} +snippet asr + assert_raise(${1:Exception}) { ${2} } +snippet asnr + assert_nothing_raised(${1:Exception}) { ${2} } +snippet asrt + assert_respond_to(${1:object}, :${2:method})${3} +snippet ass assert_same(..) + assert_same(${1:expected}, ${2:actual})${3} +snippet ass assert_send(..) + assert_send([${1:object}, :${2:message}, ${3:args}])${4} +snippet asns + assert_not_same(${1:unexpected}, ${2:actual})${3} +snippet ast + assert_throws(:${1:expected}) { ${2} } +snippet asnt + assert_nothing_thrown { ${1} } +snippet fl + flunk("${1:Failure message.}")${2} +# Benchmark.bmbm do .. end +snippet bm- + TESTS = ${1:10_000} + Benchmark.bmbm do |results| + ${2} + end +snippet rep + results.report("${1:name}:") { TESTS.times { ${2} }} +# Marshal.dump(.., file) +snippet Md + File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4} +# Mashal.load(obj) +snippet Ml + File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3} +# deep_copy(..) +snippet deec + Marshal.load(Marshal.dump(${1:obj_to_copy}))${2} +snippet Pn- + PStore.new(${1:"file_name.pstore"})${2} +snippet tra + transaction(${1:true}) { ${2} } +# xmlread(..) +snippet xml- + REXML::Document.new(File.read(${1:"path/to/file"}))${2} +# xpath(..) { .. } +snippet xpa + elements.each(${1:"//Xpath"}) do |${2:node}| + ${3} + end +# class_from_name() +snippet clafn + split("::").inject(Object) { |par, const| par.const_get(const) } +# singleton_class() +snippet sinc + class << self; self end +snippet nam + namespace :${1:`Filename()`} do + ${2} + end +snippet tas + desc "${1:Task description\}" + task :${2:task_name => [:dependent, :tasks]} do + ${3} + end diff --git a/snippets/sh.snippets b/snippets/sh.snippets new file mode 100644 index 0000000..f035126 --- /dev/null +++ b/snippets/sh.snippets @@ -0,0 +1,28 @@ +# #!/bin/bash +snippet #! + #!/bin/bash + +snippet if + if [[ ${1:condition} ]]; then + ${2:#statements} + fi +snippet elif + elif [[ ${1:condition} ]]; then + ${2:#statements} +snippet for + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do + ${3:#statements} + done +snippet wh + while [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet until + until [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet case + case ${1:word} in + ${2:pattern}) + ${3};; + esac diff --git a/snippets/snippet.snippets b/snippets/snippet.snippets new file mode 100644 index 0000000..854c058 --- /dev/null +++ b/snippets/snippet.snippets @@ -0,0 +1,7 @@ +# snippets for making snippets :) +snippet snip + snippet ${1:trigger} + ${2} +snippet msnip + snippet ${1:trigger} ${2:description} + ${3} diff --git a/snippets/tcl.snippets b/snippets/tcl.snippets new file mode 100644 index 0000000..bee2ef8 --- /dev/null +++ b/snippets/tcl.snippets @@ -0,0 +1,92 @@ +# #!/usr/bin/tclsh +snippet #! + #!/usr/bin/tclsh + +# Process +snippet pro + proc ${1:function_name} {${2:args}} { + ${3:#body ...} + } +#xif +snippet xif + ${1:expr}? ${2:true} : ${3:false} +# Conditional +snippet if + if {${1}} { + ${2:# body...} + } +# Conditional if..else +snippet ife + if {${1}} { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if {${1}} { + ${2:# body...} + } elseif {${3}} { + ${4:# elsif...} + } else { + ${5:# else...} + } +# If catch then +snippet ifc + if { [catch {${1:#do something...}} ${2:err}] } { + ${3:# handle failure...} + } +# Catch +snippet catch + catch {${1}} ${2:err} ${3:options} +# While Loop +snippet wh + while {${1}} { + ${2:# body...} + } +# For Loop +snippet for + for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach ${1:x} {${2:#list}} { + ${3:# body...} + } +# after ms script... +snippet af + after ${1:ms} ${2:#do something} +# after cancel id +snippet afc + after cancel ${1:id or script} +# after idle +snippet afi + after idle ${1:script} +# after info id +snippet afin + after info ${1:id} +# Expr +snippet exp + expr {${1:#expression here}} +# Switch +snippet sw + switch ${1:var} { + ${3:pattern 1} { + ${4:#do something} + } + default { + ${2:#do something} + } + } +# Case +snippet ca + ${1:pattern} { + ${2:#do something} + }${3} +# Namespace eval +snippet ns + namespace eval ${1:path} {${2:#script...}} +# Namespace current +snippet nsc + namespace current diff --git a/snippets/tex.snippets b/snippets/tex.snippets new file mode 100644 index 0000000..22f7316 --- /dev/null +++ b/snippets/tex.snippets @@ -0,0 +1,115 @@ +# \begin{}...\end{} +snippet begin + \begin{${1:env}} + ${2} + \end{$1} +# Tabular +snippet tab + \begin{${1:tabular}}{${2:c}} + ${3} + \end{$1} +# Align(ed) +snippet ali + \begin{align${1:ed}} + ${2} + \end{align$1} +# Gather(ed) +snippet gat + \begin{gather${1:ed}} + ${2} + \end{gather$1} +# Equation +snippet eq + \begin{equation} + ${1} + \end{equation} +# Unnumbered Equation +snippet \ + \\[ + ${1} + \\] +# Enumerate +snippet enum + \begin{enumerate} + \item ${1} + \end{enumerate} +# Itemize +snippet item + \begin{itemize} + \item ${1} + \end{itemize} +# Description +snippet desc + \begin{description} + \item[${1}] ${2} + \end{description} +# Matrix +snippet mat + \begin{${1:p/b/v/V/B/small}matrix} + ${2} + \end{$1matrix} +# Cases +snippet cas + \begin{cases} + ${1:equation}, &\text{ if }${2:case}\\ + ${3} + \end{cases} +# Split +snippet spl + \begin{split} + ${1} + \end{split} +# Part +snippet part + \part{${1:part name}} % (fold) + \label{prt:${2:$1}} + ${3} + % part $2 (end) +# Chapter +snippet cha + \chapter{${1:chapter name}} % (fold) + \label{cha:${2:$1}} + ${3} + % chapter $2 (end) +# Section +snippet sec + \section{${1:section name}} % (fold) + \label{sec:${2:$1}} + ${3} + % section $2 (end) +# Sub Section +snippet sub + \subsection{${1:subsection name}} % (fold) + \label{sub:${2:$1}} + ${3} + % subsection $2 (end) +# Sub Sub Section +snippet subs + \subsubsection{${1:subsubsection name}} % (fold) + \label{ssub:${2:$1}} + ${3} + % subsubsection $2 (end) +# Paragraph +snippet par + \paragraph{${1:paragraph name}} % (fold) + \label{par:${2:$1}} + ${3} + % paragraph $2 (end) +# Sub Paragraph +snippet subp + \subparagraph{${1:subparagraph name}} % (fold) + \label{subp:${2:$1}} + ${3} + % subparagraph $2 (end) +snippet itd + \item[${1:description}] ${2:item} +snippet figure + ${1:Figure}~\ref{${2:fig:}}${3} +snippet table + ${1:Table}~\ref{${2:tab:}}${3} +snippet listing + ${1:Listing}~\ref{${2:list}}${3} +snippet section + ${1:Section}~\ref{${2:sec:}}${3} +snippet page + ${1:page}~\pageref{${2}}${3} diff --git a/snippets/vim.snippets b/snippets/vim.snippets new file mode 100644 index 0000000..64e7807 --- /dev/null +++ b/snippets/vim.snippets @@ -0,0 +1,32 @@ +snippet header + " File: ${1:`expand('%:t')`} + " Author: ${2:`g:snips_author`} + " Description: ${3} + ${4:" Last Modified: `strftime("%B %d, %Y")`} +snippet guard + if exists('${1:did_`Filename()`}') || &cp${2: || version < 700} + finish + endif + let $1 = 1${3} +snippet f + fun ${1:function_name}(${2}) + ${3:" code} + endf +snippet for + for ${1:needle} in ${2:haystack} + ${3:" code} + endfor +snippet wh + while ${1:condition} + ${2:" code} + endw +snippet if + if ${1:condition} + ${2:" code} + endif +snippet ife + if ${1:condition} + ${2} + else + ${3} + endif diff --git a/snippets/xhtml.snippets b/snippets/xhtml.snippets new file mode 100644 index 0000000..90a62b2 --- /dev/null +++ b/snippets/xhtml.snippets @@ -0,0 +1,12 @@ +snippet xhtml + + + + + ${1:title} + + + + ${2:end} + + diff --git a/snippets/zsh.snippets b/snippets/zsh.snippets new file mode 100644 index 0000000..7aee05b --- /dev/null +++ b/snippets/zsh.snippets @@ -0,0 +1,58 @@ +# #!/bin/zsh +snippet #! + #!/bin/zsh + +snippet if + if ${1:condition}; then + ${2:# statements} + fi +snippet ife + if ${1:condition}; then + ${2:# statements} + else + ${3:# statements} + fi +snippet elif + elif ${1:condition} ; then + ${2:# statements} +snippet for + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do + ${3:# statements} + done +snippet fore + for ${1:item} in ${2:list}; do + ${3:# statements} + done +snippet wh + while ${1:condition}; do + ${2:# statements} + done +snippet until + until ${1:condition}; do + ${2:# statements} + done +snippet repeat + repeat ${1:integer}; do + ${2:# statements} + done +snippet case + case ${1:word} in + ${2:pattern}) + ${3};; + esac +snippet select + select ${1:answer} in ${2:choices}; do + ${3:# statements} + done +snippet ( + ( ${1:#statements} ) +snippet { + { ${1:#statements} } +snippet [ + [[ ${1:test} ]] +snippet always + { ${1:try} } always { ${2:always} } +snippet fun + function ${1:name} (${2:args}) { + ${3:# body} + } diff --git a/spell/pl.utf-8.add b/spell/pl.utf-8.add new file mode 100644 index 0000000..da9d23e --- /dev/null +++ b/spell/pl.utf-8.add @@ -0,0 +1,20 @@ +asteroidów +Astropsychologia +astrozoologowie +ciemnolubnego +salamandrowym +czasoprzestrzennie +Arcymag +czarnobrody +poliwymiarowych +Szronowej +pięciogłowych +zawibrował +subrzeczywistości +meduzowego +dryń +zewnętrze +zbalansowany +smartindent +autoindenting +filetype/! diff --git a/spell/pl.utf-8.add.spl b/spell/pl.utf-8.add.spl new file mode 100644 index 0000000..fe88773 Binary files /dev/null and b/spell/pl.utf-8.add.spl differ diff --git a/syntax/c.vim b/syntax/c.vim new file mode 100644 index 0000000..07df36b --- /dev/null +++ b/syntax/c.vim @@ -0,0 +1,368 @@ +" Vim syntax file +" Language: C +" Maintainer: Bram Moolenaar +" Last Change: 2008 Mar 19 + +" Quit when a (custom) syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +" A bunch of useful C keywords +syn keyword cStatement goto break return continue asm +syn keyword cLabel case default +syn keyword cConditional if else switch +syn keyword cRepeat while for do + +syn keyword cTodo contained TODO FIXME XXX + +" cCommentGroup allows adding matches for special things in comments +syn cluster cCommentGroup contains=cTodo + +" String and Character constants +" Highlight special characters (those which have a backslash) differently +syn match cSpecial display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)" +if !exists("c_no_utf") + syn match cSpecial display contained "\\\(u\x\{4}\|U\x\{8}\)" +endif +if exists("c_no_cformat") + syn region cString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell + " cCppString: same as cString, but ends at end of line + syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,@Spell +else + if !exists("c_no_c99") " ISO C99 + syn match cFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained + else + syn match cFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([bdiuoxXDOUfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained + endif + syn match cFormat display "%%" contained + syn region cString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell + " cCppString: same as cString, but ends at end of line + syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell +endif + +syn match cCharacter "L\='[^\\]'" +syn match cCharacter "L'[^']*'" contains=cSpecial +if exists("c_gnu") + syn match cSpecialError "L\='\\[^'\"?\\abefnrtv]'" + syn match cSpecialCharacter "L\='\\['\"?\\abefnrtv]'" +else + syn match cSpecialError "L\='\\[^'\"?\\abfnrtv]'" + syn match cSpecialCharacter "L\='\\['\"?\\abfnrtv]'" +endif +syn match cSpecialCharacter display "L\='\\\o\{1,3}'" +syn match cSpecialCharacter display "'\\x\x\{1,2}'" +syn match cSpecialCharacter display "L'\\x\x\+'" + +"when wanted, highlight trailing white space +if exists("c_space_errors") + if !exists("c_no_trail_space_error") + syn match cSpaceError display excludenl "\s\+$" + endif + if !exists("c_no_tab_space_error") + syn match cSpaceError display " \+\t"me=e-1 + endif +endif + +" This should be before cErrInParen to avoid problems with #define ({ xxx }) +if exists("c_curly_error") + syntax match cCurlyError "}" + syntax region cBlock start="{" end="}" contains=ALLBUT,cCurlyError,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell fold +else + syntax region cBlock start="{" end="}" transparent fold +endif + +"catch errors caused by wrong parenthesis and brackets +" also accept <% for {, %> for }, <: for [ and :> for ] (C99) +" But avoid matching <::. +syn cluster cParenGroup contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom +if exists("c_no_curly_error") + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell + syn match cParenError display ")" + syn match cErrInParen display contained "^[{}]\|^<%\|^%>" +elseif exists("c_no_bracket_error") + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell + syn match cParenError display ")" + syn match cErrInParen display contained "[{}]\|<%\|%>" +else + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString,@Spell + syn match cParenError display "[\])]" + syn match cErrInParen display contained "[\]{}]\|<%\|%>" + syn region cBracket transparent start='\[\|<::\@!' end=']\|:>' contains=ALLBUT,@cParenGroup,cErrInParen,cCppParen,cCppBracket,cCppString,@Spell + " cCppBracket: same as cParen but ends at end-of-line; used in cDefine + syn region cCppBracket transparent start='\[\|<::\@!' skip='\\$' excludenl end=']\|:>' end='$' contained contains=ALLBUT,@cParenGroup,cErrInParen,cParen,cBracket,cString,@Spell + syn match cErrInBracket display contained "[);{}]\|<%\|%>" +endif + +"integer number, or floating point number without a dot and with "f". +syn case ignore +syn match cNumbers display transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctalError,cOctal +" Same, but without octal error (for comments) +syn match cNumbersCom display contained transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctal +syn match cNumber display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>" +"hex number +syn match cNumber display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>" +" Flag the first zero of an octal number as something special +syn match cOctal display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=cOctalZero +syn match cOctalZero display contained "\<0" +syn match cFloat display contained "\d\+f" +"floating point number, with dot, optional exponent +syn match cFloat display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\=" +"floating point number, starting with a dot, optional exponent +syn match cFloat display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>" +"floating point number, without dot, with exponent +syn match cFloat display contained "\d\+e[-+]\=\d\+[fl]\=\>" +if !exists("c_no_c99") + "hexadecimal floating point number, optional leading digits, with dot, with exponent + syn match cFloat display contained "0x\x*\.\x\+p[-+]\=\d\+[fl]\=\>" + "hexadecimal floating point number, with leading digits, optional dot, with exponent + syn match cFloat display contained "0x\x\+\.\=p[-+]\=\d\+[fl]\=\>" +endif + +" flag an octal number with wrong digits +syn match cOctalError display contained "0\o*[89]\d*" +syn case match + +if exists("c_comment_strings") + " A comment can contain cString, cCharacter and cNumber. + " But a "*/" inside a cString in a cComment DOES end the comment! So we + " need to use a special type of cString: cCommentString, which also ends on + " "*/", and sees a "*" at the start of the line as comment again. + " Unfortunately this doesn't very well work for // type of comments :-( + syntax match cCommentSkip contained "^\s*\*\($\|\s\+\)" + syntax region cCommentString contained start=+L\=\\\@" skip="\\$" end="$" end="//"me=s-1 contains=cComment,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError +syn match cPreCondit display "^\s*\(%:\|#\)\s*\(else\|endif\)\>" +if !exists("c_no_if0") + if !exists("c_no_if0_fold") + syn region cCppOut start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2 fold + else + syn region cCppOut start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2 + endif + syn region cCppOut2 contained start="0" end="^\s*\(%:\|#\)\s*\(endif\>\|else\>\|elif\>\)" contains=cSpaceError,cCppSkip + syn region cCppSkip contained start="^\s*\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppSkip +endif +syn region cIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+ +syn match cIncluded display contained "<[^>]*>" +syn match cInclude display "^\s*\(%:\|#\)\s*include\>\s*["<]" contains=cIncluded +"syn match cLineSkip "\\$" +syn cluster cPreProcGroup contains=cPreCondit,cIncluded,cInclude,cDefine,cErrInParen,cErrInBracket,cUserLabel,cSpecial,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cString,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cParen,cBracket,cMulti +syn region cDefine start="^\s*\(%:\|#\)\s*\(define\|undef\)\>" skip="\\$" end="$" end="//"me=s-1 keepend contains=ALLBUT,@cPreProcGroup,@Spell +syn region cPreProc start="^\s*\(%:\|#\)\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell + +" Highlight User Labels +syn cluster cMultiGroup contains=cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cCppParen,cCppBracket,cCppString +syn region cMulti transparent start='?' skip='::' end=':' contains=ALLBUT,@cMultiGroup,@Spell +" Avoid matching foo::bar() in C++ by requiring that the next char is not ':' +syn cluster cLabelGroup contains=cUserLabel +syn match cUserCont display "^\s*\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display ";\s*\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup +syn match cUserCont display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + +syn match cUserLabel display "\I\i*" contained + +" Avoid recognizing most bitfields as labels +syn match cBitField display "^\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType +syn match cBitField display ";\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType + +if exists("c_minlines") + let b:c_minlines = c_minlines +else + if !exists("c_no_if0") + let b:c_minlines = 50 " #if 0 constructs can be long + else + let b:c_minlines = 15 " mostly for () constructs + endif +endif +if exists("c_curly_error") + syn sync fromstart +else + exec "syn sync ccomment cComment minlines=" . b:c_minlines +endif + +" Define the default highlighting. +" Only used when an item doesn't have highlighting yet +hi def link cFormat cSpecial +hi def link cCppString cString +hi def link cCommentL cComment +hi def link cCommentStart cComment +hi def link cLabel Label +hi def link cUserLabel Label +hi def link cConditional Conditional +hi def link cRepeat Repeat +hi def link cCharacter Character +hi def link cSpecialCharacter cSpecial +hi def link cNumber Number +hi def link cOctal Number +hi def link cOctalZero PreProc " link this to Error if you want +hi def link cFloat Float +hi def link cOctalError cError +hi def link cParenError cError +hi def link cErrInParen cError +hi def link cErrInBracket cError +hi def link cCommentError cError +hi def link cCommentStartError cError +hi def link cSpaceError cError +hi def link cSpecialError cError +hi def link cCurlyError cError +hi def link cOperator Operator +hi def link cStructure Structure +hi def link cStorageClass StorageClass +hi def link cInclude Include +hi def link cPreProc PreProc +hi def link cDefine Macro +hi def link cIncluded cString +hi def link cError Error +hi def link cStatement Statement +hi def link cPreCondit PreCondit +hi def link cType Type +hi def link cConstant Constant +hi def link cCommentString cString +hi def link cComment2String cString +hi def link cCommentSkip cComment +hi def link cString String +hi def link cComment Comment +hi def link cSpecial SpecialChar +hi def link cTodo Todo +hi def link cCppSkip cCppOut +hi def link cCppOut2 cCppOut +hi def link cCppOut Comment + +let b:current_syntax = "c" + +" vim: ts=8 diff --git a/syntax/cvsannotate.vim b/syntax/cvsannotate.vim new file mode 100644 index 0000000..4af5809 --- /dev/null +++ b/syntax/cvsannotate.vim @@ -0,0 +1,45 @@ +" Vim syntax file +" Language: CVS annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the cvscommand plugin. Originally written by Mathieu +" Clabaut +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +syn match cvsDate /\d\d-...-\d\d/ contained +syn match cvsName /(\S* /hs=s+1,he=e-1 contained nextgroup=cvsDate +syn match cvsVer /^\d\+\(\.\d\+\)\+/ contained nextgroup=cvsName +syn region cvsHead start="^\d\+\.\d\+" end="):" contains=cvsVer,cvsName,cvsDate + +if !exists("did_cvsannotate_syntax_inits") + let did_cvsannotate_syntax_inits = 1 + hi link cvsDate Comment + hi link cvsName Type + hi link cvsVer Statement +endif + +let b:current_syntax="CVSAnnotate" diff --git a/syntax/gitAnnotate.vim b/syntax/gitAnnotate.vim new file mode 100644 index 0000000..932342d --- /dev/null +++ b/syntax/gitAnnotate.vim @@ -0,0 +1,44 @@ +" Vim syntax file +" Language: git annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) 2009 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn region gitName start="(\@<=" end="\( \d\d\d\d-\)\@=" contained +syn match gitCommit /^\^\?\x\+/ contained +syn match gitDate /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d/ contained +syn match gitLineNumber /\d\+)\@=/ contained +syn region gitAnnotation start="^" end=") " oneline keepend contains=gitCommit,gitLineNumber,gitDate,gitName + +if !exists("did_gitannotate_syntax_inits") + let did_gitannotate_syntax_inits = 1 + hi link gitName Type + hi link gitCommit Statement + hi link gitDate Comment + hi link gitLineNumber Label +endif + +let b:current_syntax="gitAnnotate" diff --git a/syntax/gitannotate.vim b/syntax/gitannotate.vim new file mode 100644 index 0000000..932342d --- /dev/null +++ b/syntax/gitannotate.vim @@ -0,0 +1,44 @@ +" Vim syntax file +" Language: git annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) 2009 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn region gitName start="(\@<=" end="\( \d\d\d\d-\)\@=" contained +syn match gitCommit /^\^\?\x\+/ contained +syn match gitDate /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d/ contained +syn match gitLineNumber /\d\+)\@=/ contained +syn region gitAnnotation start="^" end=") " oneline keepend contains=gitCommit,gitLineNumber,gitDate,gitName + +if !exists("did_gitannotate_syntax_inits") + let did_gitannotate_syntax_inits = 1 + hi link gitName Type + hi link gitCommit Statement + hi link gitDate Comment + hi link gitLineNumber Label +endif + +let b:current_syntax="gitAnnotate" diff --git a/syntax/hgannotate.vim b/syntax/hgannotate.vim new file mode 100755 index 0000000..cee9a23 --- /dev/null +++ b/syntax/hgannotate.vim @@ -0,0 +1,40 @@ +" Vim syntax file +" Language: HG annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) 2010 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match hgVer /\d\+/ contained +syn match hgName /^\s*\S\+/ contained +syn match hgHead /^\s*\S\+\s\+\d\+:/ contains=hgVer,hgName + +if !exists("did_hgannotate_syntax_inits") + let did_hgannotate_syntax_inits = 1 + hi link hgName Type + hi link hgVer Statement +endif + +let b:current_syntax="hgAnnotate" diff --git a/syntax/mkd.vim b/syntax/mkd.vim new file mode 100644 index 0000000..ee22365 --- /dev/null +++ b/syntax/mkd.vim @@ -0,0 +1,104 @@ +" Vim syntax file +" Language: Markdown +" Maintainer: Ben Williams +" URL: http://plasticboy.com/markdown-vim-mode/ +" Version: 9 +" Last Change: 2009 May 18 +" Remark: Uses HTML syntax file +" Remark: I don't do anything with angle brackets (<>) because that would too easily +" easily conflict with HTML syntax +" TODO: Handle stuff contained within stuff (e.g. headings within blockquotes) + + +" Read the HTML syntax to start with +if version < 600 + so :p:h/html.vim +else + runtime! syntax/html.vim + unlet b:current_syntax +endif + +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +" don't use standard HiLink, it will not work with included syntax files +if version < 508 + command! -nargs=+ HtmlHiLink hi link +else + command! -nargs=+ HtmlHiLink hi def link +endif + +syn spell toplevel +syn case ignore +syn sync linebreaks=1 + +"additions to HTML groups +syn region htmlBold start=/\\\@) +syn region mkdLinkDef matchgroup=mkdDelimiter start="^ \{,3}\zs\[" end="]:" oneline nextgroup=mkdLinkDefTarget skipwhite +syn region mkdLinkDefTarget start="<\?\zs\S" excludenl end="\ze[>[:space:]\n]" contained nextgroup=mkdLinkTitle,mkdLinkDef skipwhite skipnl oneline +syn region mkdLinkTitle matchgroup=mkdDelimiter start=+"+ end=+"+ contained +syn region mkdLinkTitle matchgroup=mkdDelimiter start=+'+ end=+'+ contained +syn region mkdLinkTitle matchgroup=mkdDelimiter start=+(+ end=+)+ contained + +"define Markdown groups +syn match mkdLineContinue ".$" contained +syn match mkdRule /^\s*\*\s\{0,1}\*\s\{0,1}\*$/ +syn match mkdRule /^\s*-\s\{0,1}-\s\{0,1}-$/ +syn match mkdRule /^\s*_\s\{0,1}_\s\{0,1}_$/ +syn match mkdRule /^\s*-\{3,}$/ +syn match mkdRule /^\s*\*\{3,5}$/ +syn match mkdListItem "^\s*[-*+]\s\+" +syn match mkdListItem "^\s*\d\+\.\s\+" +syn match mkdCode /^\s*\n\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/ +syn match mkdLineBreak / \+$/ +syn region mkdCode start=/\\\@/ end=/$/ contains=mkdLineBreak,mkdLineContinue,@Spell +syn region mkdCode start="]*>" end="
" +syn region mkdCode start="]*>" end="" + +"HTML headings +syn region htmlH1 start="^\s*#" end="\($\|#\+\)" contains=@Spell +syn region htmlH2 start="^\s*##" end="\($\|#\+\)" contains=@Spell +syn region htmlH3 start="^\s*###" end="\($\|#\+\)" contains=@Spell +syn region htmlH4 start="^\s*####" end="\($\|#\+\)" contains=@Spell +syn region htmlH5 start="^\s*#####" end="\($\|#\+\)" contains=@Spell +syn region htmlH6 start="^\s*######" end="\($\|#\+\)" contains=@Spell +syn match htmlH1 /^.\+\n=\+$/ contains=@Spell +syn match htmlH2 /^.\+\n-\+$/ contains=@Spell + +"highlighting for Markdown groups +HtmlHiLink mkdString String +HtmlHiLink mkdCode String +HtmlHiLink mkdBlockquote Comment +HtmlHiLink mkdLineContinue Comment +HtmlHiLink mkdListItem Identifier +HtmlHiLink mkdRule Identifier +HtmlHiLink mkdLineBreak Todo +HtmlHiLink mkdLink htmlLink +HtmlHiLink mkdURL htmlString +HtmlHiLink mkdID Identifier +HtmlHiLink mkdLinkDef mkdID +HtmlHiLink mkdLinkDefTarget mkdURL +HtmlHiLink mkdLinkTitle htmlString + +HtmlHiLink mkdDelimiter Delimiter + +let b:current_syntax = "mkd" + +delcommand HtmlHiLink +" vim: ts=8 diff --git a/syntax/opl.vim b/syntax/opl.vim new file mode 100644 index 0000000..42318d0 --- /dev/null +++ b/syntax/opl.vim @@ -0,0 +1,162 @@ +" Vim syntax file +" Language: OpenUI +" Maintainer: None +" $Id: opl.vim,v 1.1 2004/06/13 17:34:11 vimboss Exp $ + +" Open UI Language + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +" case is not significant +syn case ignore + +" A bunch of useful OPL keywords +syn keyword OPLStatement proc endp abs acos addr adjustalloc alert alloc app +syn keyword OPLStatement append appendsprite asc asin at atan back beep +syn keyword OPLStatement begintrans bookmark break busy byref cache +syn keyword OPLStatement cachehdr cacherec cachetidy call cancel caption +syn keyword OPLStatement changesprite chr$ clearflags close closesprite cls +syn keyword OPLStatement cmd$ committrans compact compress const continue +syn keyword OPLStatement copy cos count create createsprite cursor +syn keyword OPLStatement datetosecs datim$ day dayname$ days daystodate +syn keyword OPLStatement dbuttons dcheckbox dchoice ddate declare dedit +syn keyword OPLStatement deditmulti defaultwin deg delete dfile dfloat +syn keyword OPLStatement dialog diaminit diampos dinit dir$ dlong dow +syn keyword OPLStatement dposition drawsprite dtext dtime dxinput edit else +syn keyword OPLStatement elseif enda endif endv endwh entersend entersend0 +syn keyword OPLStatement eof erase err err$ errx$ escape eval exist exp ext +syn keyword OPLStatement external find findfield findlib first fix$ flags +syn keyword OPLStatement flt font freealloc gat gborder gbox gbutton +syn keyword OPLStatement gcircle gclock gclose gcls gcolor gcopy gcreate +syn keyword OPLStatement gcreatebit gdrawobject gellipse gen$ get get$ +syn keyword OPLStatement getcmd$ getdoc$ getevent getevent32 geteventa32 +syn keyword OPLStatement geteventc getlibh gfill gfont ggmode ggrey gheight +syn keyword OPLStatement gidentity ginfo ginfo32 ginvert giprint glineby +syn keyword OPLStatement glineto gloadbit gloadfont global gmove gorder +syn keyword OPLStatement goriginx goriginy goto gotomark gpatt gpeekline +syn keyword OPLStatement gpoly gprint gprintb gprintclip grank gsavebit +syn keyword OPLStatement gscroll gsetpenwidth gsetwin gstyle gtmode gtwidth +syn keyword OPLStatement gunloadfont gupdate guse gvisible gwidth gx +syn keyword OPLStatement gxborder gxprint gy hex$ hour iabs icon if include +syn keyword OPLStatement input insert int intf intrans key key$ keya keyc +syn keyword OPLStatement killmark kmod last lclose left$ len lenalloc +syn keyword OPLStatement linklib ln loadlib loadm loc local lock log lopen +syn keyword OPLStatement lower$ lprint max mcard mcasc mean menu mid$ min +syn keyword OPLStatement minit minute mkdir modify month month$ mpopup +syn keyword OPLStatement newobj newobjh next notes num$ odbinfo off onerr +syn keyword OPLStatement open openr opx os parse$ path pause peek pi +syn keyword OPLStatement pointerfilter poke pos position possprite print +syn keyword OPLStatement put rad raise randomize realloc recsize rename +syn keyword OPLStatement rept$ return right$ rmdir rnd rollback sci$ screen +syn keyword OPLStatement screeninfo second secstodate send setdoc setflags +syn keyword OPLStatement setname setpath sin space sqr statuswin +syn keyword OPLStatement statwininfo std stop style sum tan testevent trap +syn keyword OPLStatement type uadd unloadlib unloadm until update upper$ +syn keyword OPLStatement use usr usr$ usub val var vector week year + + +syn keyword OPLRepeat while do for +syn keyword OPLConstant NULL TRUE +syn keyword OPLType OuiBooleanT OuiCharT OuiDecimalT OuiFloatT OuiIntegerT +syn keyword OPLType OuiLongT OuiPointerT bool char class + +"syn keyword attr +"syn keyword attribute +"syn keyword begin +"syn keyword class +"syn keyword const +"syn keyword constant +"syn keyword declid +"syn keyword div +"syn keyword doobrie +"syn keyword div +"syn keyword not +"syn keyword else +"syn keyword end +"syn keyword enum +"syn keyword export +"syn keyword extern +"syn keyword false +"syn keyword float +"syn keyword func +"syn keyword function +"syn keyword goto +"syn keyword if +"syn keyword in +"syn keyword init +"syn keyword FALSE + +"syn keyword initially +"syn keyword inst +"syn keyword instance +"syn keyword int +"syn keyword local +"syn keyword long +"syn keyword message +"syn keyword mnemonic +"syn keyword not +"syn keyword of +"syn keyword on +"syn keyword or +"syn keyword priv +"syn keyword OuiShortT +"syn keyword OuiStringT +"syn keyword OuiZonedT +"syn keyword TRUE +"syn keyword accelerator +"syn keyword action +"syn keyword alias +"syn keyword and +"syn keyword array +"syn keyword private +"syn keyword pub +"syn keyword public +"syn keyword readonly +"syn keyword record +"syn keyword rem +"syn keyword repeat +"syn keyword return +"syn keyword short +"syn keyword slot +"syn keyword slotno +"syn keyword string +"syn keyword to +"syn keyword true +"syn keyword type +"syn keyword until +"syn keyword var +"syn keyword variable +"syn keyword virtual +"syn keyword when +"syn keyword while +"syn keyword zoned + +" syn keyword OPLStatement rem + + +syn match OPLNumber "\<\d\+\>" +syn match OPLNumber "\<\d\+\.\d*\>" +syn match OPLNumber "\.\d\+\>" + +syn region OPLString start=+"+ end=+"+ +syn region OPLComment start="REM[\t ]" end="$" +syn match OPLMathsOperator "-\|=\|[:<>+\*^/\\]" + + +" Define the default highliting +hi def link OPLStatement Statement +hi def link OPLConstant Constant +hi def link OPLNumber Number +hi def link OPLString String +hi def link OPLComment Comment +hi def link OPLMathsOperator Conditional +hi def link OPLType Type +hi def link OPLError Error + +let b:current_syntax = "opl" + +" vim: ts=8 diff --git a/syntax/opl.xml b/syntax/opl.xml new file mode 100644 index 0000000..824dd99 --- /dev/null +++ b/syntax/opl.xml @@ -0,0 +1,816 @@ + + + + + + + + + + + + + + + + + + + + + + " + " + + + ' + ' + + + // + ) + = + : + ! + >= + <= + + + - + / + + * + > + < + % + & + | + ^ + ~ + + . + , + ; + ] + [ + ? + + + + KeyAltBack + KeyAltBackTab + KeyAltCancel + KeyAltClrDisp + KeyAltClrLine + KeyAltCopy + KeyAltCut + KeyAltDelChar + KeyAltDelLine + KeyAltDo + KeyAltDown + KeyAltEof + KeyAltExtend + KeyAltForm + KeyAltHelp + KeyAltHome + KeyAltHomeD + KeyAltInsChar + KeyAltInsLine + KeyAltKeys + KeyAltLeft + KeyAltLocal + KeyAltLocalTab + KeyAltMenu + KeyAltMenuBar + KeyAltNext + KeyAltNull + KeyAltPaste + KeyAltPoint + KeyAltPrev + KeyAltPrint + KeyAltReplace + KeyAltReturn + KeyAltRight + KeyAltRollDn + KeyAltRollUp + KeyAltSelect + KeyAltSoft1 + KeyAltSoft10 + KeyAltSoft11 + KeyAltSoft12 + KeyAltSoft13 + KeyAltSoft14 + KeyAltSoft15 + KeyAltSoft16 + KeyAltSoft17 + KeyAltSoft18 + KeyAltSoft19 + KeyAltSoft2 + KeyAltSoft20 + KeyAltSoft21 + KeyAltSoft22 + KeyAltSoft23 + KeyAltSoft24 + KeyAltSoft25 + KeyAltSoft26 + KeyAltSoft27 + KeyAltSoft28 + KeyAltSoft29 + KeyAltSoft3 + KeyAltSoft30 + KeyAltSoft31 + KeyAltSoft32 + KeyAltSoft4 + KeyAltSoft5 + KeyAltSoft6 + KeyAltSoft7 + KeyAltSoft8 + KeyAltSoft9 + KeyAltTab + KeyAltTimer + KeyAltUp + KeyAltWindowList + KeyAltWindowMenu + KeyBack + KeyBackTab + KeyCancel + KeyClrDisp + KeyClrLine + KeyCopy + KeyCut + KeyDelChar + KeyDelLine + KeyDo + KeyDown + KeyEof + KeyExtend + KeyForm + KeyHelp + KeyHome + KeyHomeD + KeyInsChar + KeyInsLine + KeyKeys + KeyLeft + KeyLocal + KeyLocalTab + KeyMenu + KeyMenuBar + KeyNext + KeyNull + KeyPaste + KeyPoint + KeyPrev + KeyPrint + KeyReplace + KeyReturn + KeyRight + KeyRollDn + KeyRollUp + KeySelect + KeySoft1 + KeySoft10 + KeySoft11 + KeySoft12 + KeySoft13 + KeySoft14 + KeySoft15 + KeySoft16 + KeySoft17 + KeySoft18 + KeySoft19 + KeySoft2 + KeySoft20 + KeySoft21 + KeySoft22 + KeySoft23 + KeySoft24 + KeySoft25 + KeySoft26 + KeySoft27 + KeySoft28 + KeySoft29 + KeySoft3 + KeySoft30 + KeySoft31 + KeySoft32 + KeySoft4 + KeySoft5 + KeySoft6 + KeySoft7 + KeySoft8 + KeySoft9 + KeyTab + KeyTimer + KeyUp + KeyWindowList + KeyWindowMenu + OuiDestroy + OuiGetTime + OuiInstantiate + OuiListAppend + OuiListDeleteItem + OuiListFind + OuiListInsertItem + OuiListItems + OuiListNumItems + OuiListReFind + OuiListSort + OuiLookup + OuiPrefsClose + OuiPrefsGetBoolean + OuiPrefsGetEnum + OuiPrefsGetLong + OuiMessageHelponHelp + OuiMsgAbout + OuiMsgClose + OuiMsgCreationAborted + OuiMsgDbCommit + OuiMsgAny + OuiMsgKeyAny + OuiMsgKeyAnyPrintable + OuiMsgMouseAny + OuiMsgMouseAnyDbl + OuiMsgB1Down + OuiMsgB1Drag + OuiMsgB1Up + OuiMsgB2Down + OuiMsgB2Drag + OuiMsgB2Up + OuiMsgB3Down + OuiMsgB3Drag + OuiMsgB3Up + OuiMsgB4Down + OuiMsgB4Drag + OuiMsgB4Up + OuiMsgB5Down + OuiMsgB5Drag + OuiMsgB5Up + OuiMsgMouseB1 + OuiMsgMouseB1Dbl + OuiMsgMouseB1Down + OuiMsgDbCommit + OuiMsgDbCommitResult + OuiMsgDbCommitResult + OuiMsgDbConnect + OuiMsgDbConnectResult + OuiMsgDbDisconnect + OuiMsgDbDisconnectResult + OuiMsgDbExecuteSQL + OuiMsgDbExecuteSQLResult + OuiMsgDefocus + OuiMsgDmDeleteMajor + OuiMsgDmDeleteMinor + OuiMsgDmInsertMajor + OuiMsgDmInsertMinor + OuiMsgDmInvalidateArea + OuiMsgDmNotify + OuiMsgDoublePick + OuiMsgDrag + OuiMsgDragCancel + OuiMsgDragDone + OuiMsgDragHelp + OuiMsgDragMotion + OuiMsgDragStart + OuiMsgDrop + OuiMsgEvaluatorChanged + OuiMsgEvaluatorDrag + OuiMsgExitApplication + OuiMsgFocus + OuiMsgFocusIn + OuiMsgFocusOut + OuiMsgFormStateChanged + OuiMsgGridDragged + OuiMsgHelp + OuiMsgHelpClearStatus + OuiMsgHelpClose + OuiMsgHelpContext + OuiMsgHelpHideHint + OuiMsgHelpIndex + OuiMsgHelpKey + OuiMsgHelpPick + OuiMsgHelpShowHint + OuiMsgHelpShowStatus + OuiMsgInvisible + OuiMsgLockClear + OuiMsgLockException + OuiMsgLockId + OuiMsgLockRelease + OuiMsgLockRequest + OuiMsgLowResources + OuiMsgMDIArrangeIcons + OuiMsgMDICascade + OuiMsgMDIClose + OuiMsgMDITile + OuiMsgMove + OuiMsgNewRadioButton + OuiMsgMouseAnyDown + OuiMsgMouseAnyDrag + OuiMsgMouseAnyUp + OuiMsgMouseB1Down + OuiMsgMouseB1Drag + OuiMsgMouseB1Up + OuiMsgMouseB2Dbl + OuiMsgMouseB2Down + OuiMsgMouseB2Down + OuiMsgMouseB2Drag + OuiMsgMouseB2Up + OuiMsgMouseB2Up + OuiMsgMouseB3Dbl + OuiMsgMouseB3Down + OuiMsgMouseB3Down + OuiMsgMouseB3Drag + OuiMsgMouseB3Up + OuiMsgMouseB3Up + OuiMsgMouseB4Dbl + OuiMsgMouseB4Down + OuiMsgMouseB4Drag + OuiMsgMouseB4Up + OuiMsgMouseB5Dbl + OuiMsgMouseB5Dowkn + OuiMsgMouseB5Drag + OuiMsgMouseB5Up + OuiMsgNoResources + OuiMsgNothingCanHappen + OuiMsgPick + OuiMsgPlace + OuiMsgQueryExecute + OuiMsgQueryExecuteResult + OuiMsgQueryFetchRows + OuiMsgQueryFetchRowsResult + OuiMsgRubberLine + OuiMsgRubberRect + OuiMsgSelect + OuiMsgSelectionChange + OuiMsgSelectionDefocus + OuiMsgSelectionDoubleClick + OuiMsgSessionAborted + OuiMsgSize + OuiMsgTableDataArrived + OuiMsgTimer + OuiMsgTimerCancel + OuiMsgTnfData<Type> + OuiMsgTnfException + OuiMsgTnfInitiateRequest + OuiMsgTnfInitiateSupply + OuiMsgTopLeftChanged + OuiMsgTxnCancel + OuiMsgTxnCommit + OuiMsgTxnData<Type> + OuiMsgTxnException + OuiMsgTxnId + OuiMsgTxnIdRequest + OuiMsgTxnInitiateRequest + OuiMsgTxnInitiateSupply + OuiMsgVisible + OuiMsgWMFocusIn + OuiPrefsGetMask + OuiPrefsGetString + OuiPrefsItemEnumerate + OuiPrefsMerge + OuiPrefsOpen + OuiPrefsSave + OuiPrefsSectionEnumerate + OuiPrefsSetBoolean + OuiPrefsSetEnum + OuiPrefsSetLong + OuiPrefsSetMask + OuiPrefsSetString + OuiPrint + OuiQueueMessage + OuiReCmp + OuiReDestroy + OuiReExtract + OuiReMatch + OuiStrChr + OuiStrIsAlnum + OuiStrIsAlpha + OuiStrIsDigit + OuiStrIsLower + OuiStrIsPunct + OuiStrIsSpace + OuiStrIsUpper + OuiStrLen + OuiStrPad + OuiStrRChr + OuiStrStr + OuiStrToLower + OuiStrToUpper + OuiStrTrim + OuiSubStr + OuiSynchronize + OuiTrace + OuiWebBrowserLoadURL + + AccelLabel + Active + ActiveCell + ActiveCellBackground + ActiveCellForeground + ActivePrefix + ActiveQuery + AlignHoriz + AlignVert + Alignment + AllowClose + AllowMaximize + AllowMinimize + AllowMove + AllowResize + AspectLock + AspectRatio + AutoCommit + AutoFlow + AutoResizePolicy + Background + BaseHeight + BaseWidth + BeepOnDiscard + BorderStyle + BorderStyle + BorderWidth + Bounds + ButtonModifiers + ButtonNumber + Bytes + CatName + CatSetNum + Changed + Class + Closed + ColumnCount + ColumnLengths + ColumnNames + ColumnTypes + ComboBoxStyle + CommitDirection + Connected + CursorName + DataDemandPolicy + DataOrigin + DataPendingPolicy + DatasourceName + DateInputFormat + DecimalPoints + Depth + Direction + DiscardInput + DrawGridColor + DrawGridStyle + DynamicGrid + EdgeStyle + EdgeWidth + Editable + Editable + ErrorText + ExtendClassLibrary + FastDraw + FillAlternate + FillAngle + FocusItem + Font + Font + Font + Font + Font + Foreground + FormState + GUIType + GrabInput + Height + HeightInc + HelpId + IconImage + IconX + Image + ImageData + ImageTileName + Increment + IncrementMulti + IndexMajor + IndexMinor + InputEdit + InputMode + InsensColor + InsensColor + InsertMode + IsDefault + ItemCount + Items + JumpScroll + Label + LabelDisplayPolicy + LastNativeError + Length + LineStyle + LineWidth + LockedColumns + LockedRows + MajorCount + MajorIncrement + MarginHeight + MarginHeight + MarginWidth + MarginWidth + MaxAspectX + MaxAspectY + MaxBytes + MaxBytes + MaxHeight + MaxOffsetHoriz + MaxOffsetVert + MaxWidth + Maximized + MinAspectX + MinAspectY + MinChars + MinChars + MinColumns + MinHeight + MinLines + MinRows + MinWidth + Mnemonic + Modal + Mode + NPoints + NPoints + Name + NativeHandle + NativeHandle + NativeHandle + NavigateLocked + Offset + OffsetHoriz + OffsetVert + OnDesktop + Orientation + OutputEdit + OutputFormat + OverrideRedirect + PageSize + PagesLocked + PagesMemory + PagingPolicy + Parent + PassivePrefix + PasswordChar + Pattern + Placement + PlacementDetail + PlacementPolicy + Points + PositionX + PositionY + PrimarySource + PrimarySource + QueryType + Radio + RadiusMajor + RadiusMinor + RangeHoriz + RangeMajor + RangeMinor + RangeVert + RealizePolicy + RotateAngle + RowMajor + RowMajor + SaveUnder + ScaleX + ScaleY + ScreenHeight, + ScreenWidth + ScrollBarPlacement + ScrollBarTroughColor + ScrollHoriz + ScrollVert + Sector + SelectedAreas + SelectedItemBG + SelectedItemCount + SelectedItemFG + SelectedItemList + SelectedItemMap + SelectedItems + SelectedText + SelectionBackground + SelectionForeground + SelectionLength + SelectionPolicy + SelectionPolicy + SelectionStart + Self + Sensitive + Sensitive + ShortHelpText + ShowButtons + ShowIndicator + ShowMinimize + ShowResizeHandles + ShowSysMenu + ShowTitle + ShowValue + SizeVisible + SoftKey + SpaceColumns + SpaceItems + SpaceRows + SpanX + SpanY + StartAngle + StretchHoriz + StretchVert + Style + Suffix + Template + Thickness + ThumbSize + Title + Title + TitleFont + TitlePlacement + Toggle + TopLeft + Trace + Transient + Traversable + TroughColor + UniformColumns + UniformRows + Units + Updatable + Valid + Value + Value + ValueMax + ValueMin + Visible + VisibleColumns + VisibleItems + VisibleRows + Width + WidthInc + WorldCoords + WrapMode + WrapNavigation + X + Y + + + attr + attribute + begin + bool + char + class + const + constant + declid + div + doobrie + div + not + else + end + enum + export + extern + false + float + for + func + function + goto + if + in + init + FALSE + NULL + TRUE + OuiBooleanT + OuiCharT + OuiDecimalT + OuiFloatT + OuiIntegerT + OuiLongT + OuiPointerT + initially + inst + instance + int + local + long + message + mnemonic + not + of + on + or + priv + OuiShortT + OuiStringT + OuiZonedT + TRUE + accelerator + action + alias + and + array + private + pub + public + readonly + record + rem + repeat + return + short + slot + slotno + string + to + true + type + until + var + variable + virtual + when + while + zoned + + Application + Button + Evaluator + Filledge + Graphic + Menu + OuiObj + Region + Scrollable + dataManager + database + devFontDialog + dialogb + diversion + editText + fontDialog + form + graphicCompound + groupBox + horizontalSep + interactor + label + list + mdiFrameForm + menuBar + menuBarButton + menuButton + menuCascadeButton + menuPushButton + menuRadioButton + menuToggleButton + messageBox + module + multiTextL + multiTextW + openSaveDialog + optionMenu + panel + popupMenu + pulldown + pushButton + query + radioButton + radioPushButton + scene + scrollbar + session + slider + spline + statusText + table + timer + toggleButton + Separator + StandardDialog + Visual + arc + cascade + colorDialog + comboBox + controlBar + togglePushButton + tpMenuBar + tpSpreadSheet + tpStatusBar + tpTable + tpToolBar + verticalSep + + + + + diff --git a/syntax/pd_opl.syn b/syntax/pd_opl.syn new file mode 100644 index 0000000..c865640 --- /dev/null +++ b/syntax/pd_opl.syn @@ -0,0 +1,234 @@ +#=========================================================== +# +# MED file mode definition file +# Last updated: 02.12.2004 11:42 +# +#=========================================================== + +files: *.opl +title: Open UI's OPL + +default: no +caseSensitive: yes +checkCommentInString: yes +shiftDistance: 1 +tabWidth: 8 +tabLoadExpand: 0 +tabInsAsBlank: 1 + +sectionRegexp: (^[ ]*)(class|function)[ ]+([a-zA-Z0-9_\$]+) +sectionDisplayRegexp: (^[ ]*)(class|function)[ ]+([a-zA-Z0-9_\$]+) *[:\(] *([^\(\)/]*)[\): ]*([^/\(\){}]*) +sectionBrowserOrder: 2, 3, 4, 5 +sectionDisplayOrder: 2, 3 +sectionBrowserMainKey: 3 +sectionDisplay: 5000, 1000 + +wordWrap: disabled 70 >!:~# + +wordSep:'&()[]{}\<>.,;-+*:?!=-|"/~ + +# 3rd party online help +inf: cmd.exe|/C|internet|%h http://info.propack-data.de/Doku/Programmierung/OpenUI/htmlindx.htm * http://info.propack-data.de/Doku/Programmierung/OpenUI/htmlindx.htm + + +# brackets +bracket: ( ) 1 +bracket: { } 1 +bracket: [ ] 0 + + +# Color definitions +defineColor: myGreen 0 100 10 +defineColor: myDarkYellow 150 150 0 +defineColor: myDarkBlue 0 0 150 +defineColor: myDarkRed 200 0 0 +defineColor: myDarkestRed 150 0 0 +defineColor: myLightGray 220 220 220 + + +foregroundColor: black +backgroundColor: white +blockColor: myLightGray + +# Reserved words + +color: blue, normal, blue, bold +token: FALSE OuiBooleanT OuiCharT OuiDecimalT OuiFloatT OuiIntegerT OuiLongT OuiPointerT +token: OuiShortT OuiStringT OuiZonedT TRUE accelerator action alias and array +token: attr attribute begin bool char class const constant declid div doobrie +token: else end enum export extern false float for func function goto if in init +token: initially inst instance int local long message mnemonic not of on or priv +token: private pub public readonly record rem repeat return short slot slotno +token: string to true type until var variable virtual when while zoned + +color: myDarkRed, normal, myDarkRed, normal +token: Application Button Evaluator Filledge Graphic Menu OuiObj Region Scrollable +token: Separator StandardDialog Visual arc cascade colorDialog comboBox controlBar +token: dataManager database devFontDialog dialogb diversion editText fontDialog +token: form graphicCompound groupBox horizontalSep interactor label list mdiFrameForm +token: menuBar menuBarButton menuButton menuCascadeButton menuPushButton menuRadioButton +token: menuToggleButton messageBox module multiTextL multiTextW openSaveDialog +token: optionMenu panel popupMenu pulldown pushButton query radioButton radioPushButton +token: scene scrollbar session slider spline statusText table timer toggleButton +token: togglePushButton tpMenuBar tpSpreadSheet tpStatusBar tpTable tpToolBar +token: verticalSep + +color: myGreen, normal, myGreen, normal +token: AccelLabel Active ActiveCell ActiveCellBackground ActiveCellForeground +token: ActivePrefix ActiveQuery AlignHoriz AlignVert Alignment AllowClose AllowMaximize +token: AllowMinimize AllowMove AllowResize AspectLock AspectRatio AutoCommit AutoFlow +token: AutoResizePolicy BaseHeight BaseWidth BeepOnDiscard BorderStyle BorderStyle +token: BorderWidth Bounds ButtonModifiers ButtonNumber Bytes CatName CatSetNum +token: Changed Class Closed ColumnCount ColumnLengths ColumnNames ColumnTypes +token: ComboBoxStyle CommitDirection Connected CursorName DataDemandPolicy DataOrigin +token: DataPendingPolicy DatasourceName DateInputFormat DecimalPoints Depth Direction +token: DiscardInput DrawGridColor DrawGridStyle DynamicGrid EdgeStyle EdgeWidth +token: Editable Editable ErrorText ExtendClassLibrary FastDraw FillAlternate FillAngle +token: FocusItem Font Font Font Font Font Foreground FormState GUIType GrabInput +token: Height HeightInc HelpId IconImage IconX Image ImageData ImageTileName Increment +token: IncrementMulti IndexMajor IndexMinor InputEdit InputMode InsensColor InsensColor +token: InsertMode IsDefault ItemCount Items JumpScroll Label LabelDisplayPolicy +token: LastNativeError Length LineStyle LineWidth LockedColumns LockedRows MajorCount +token: MajorIncrement MarginHeight MarginHeight MarginWidth MarginWidth MaxAspectX +token: MaxAspectY MaxBytes MaxBytes MaxHeight MaxOffsetHoriz MaxOffsetVert MaxWidth +token: Maximized MinAspectX MinAspectY MinChars MinChars MinColumns MinHeight +token: MinLines MinRows MinWidth Mnemonic Modal Mode NPoints NPoints Name NativeHandle +token: NativeHandle NativeHandle NavigateLocked Offset OffsetHoriz OffsetVert +token: OnDesktop Orientation OutputEdit OutputFormat OverrideRedirect PageSize +token: PagesLocked PagesMemory PagingPolicy Parent PassivePrefix PasswordChar +token: Pattern Placement PlacementDetail PlacementPolicy Points PositionX PositionY +token: PrimarySource PrimarySource QueryType Radio RadiusMajor RadiusMinor RangeHoriz +token: RangeMajor RangeMinor RangeVert RealizePolicy RotateAngle RowMajor RowMajor +token: SaveUnder ScaleX ScaleY ScreenHeight, ScreenWidth ScrollBarPlacement ScrollBarTroughColor +token: ScrollHoriz ScrollVert Sector SelectedAreas SelectedItemBG SelectedItemCount +token: SelectedItemFG SelectedItemList SelectedItemMap SelectedItems SelectedText +token: SelectionBackground SelectionForeground SelectionLength SelectionPolicy +token: SelectionPolicy SelectionStart Self Sensitive Sensitive ShortHelpText ShowButtons +token: ShowIndicator ShowMinimize ShowResizeHandles ShowSysMenu ShowTitle ShowValue +token: SizeVisible SoftKey SpaceColumns SpaceItems SpaceRows SpanX SpanY StartAngle +token: StretchHoriz StretchVert Style Suffix Template Thickness ThumbSize Title +token: Title TitleFont TitlePlacement Toggle TopLeft Trace Transient Traversable +token: TroughColor UniformColumns UniformRows Units Updatable Valid Value Value +token: ValueMax ValueMin Visible VisibleColumns VisibleItems VisibleRows Width +token: WidthInc WorldCoords WrapMode WrapNavigation X Y + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiDestroy OuiGetTime OuiInstantiate OuiListAppend OuiListDeleteItem OuiListFind +token: OuiListInsertItem OuiListItems OuiListNumItems OuiListReFind OuiListSort +token: OuiLookup OuiPrefsClose OuiPrefsGetBoolean OuiPrefsGetEnum OuiPrefsGetLong +token: OuiPrefsGetMask OuiPrefsGetString OuiPrefsItemEnumerate OuiPrefsMerge OuiPrefsOpen +token: OuiPrefsSave OuiPrefsSectionEnumerate OuiPrefsSetBoolean OuiPrefsSetEnum +token: OuiPrefsSetLong OuiPrefsSetMask OuiPrefsSetString OuiPrint OuiQueueMessage +token: OuiReCmp OuiReDestroy OuiReExtract OuiReMatch OuiStrChr OuiStrIsAlnum OuiStrIsAlpha +token: OuiStrIsDigit OuiStrIsLower OuiStrIsPunct OuiStrIsSpace OuiStrIsUpper OuiStrLen +token: OuiStrPad OuiStrRChr OuiStrStr OuiStrToLower OuiStrToUpper OuiStrTrim OuiSubStr +token: OuiSynchronize OuiTrace OuiWebBrowserLoadURL + +color: myDarkestRed, normal, myDarkestRed, normal +token: KeyAltBack KeyAltBackTab KeyAltCancel KeyAltClrDisp KeyAltClrLine KeyAltCopy +token: KeyAltCut KeyAltDelChar KeyAltDelLine KeyAltDo KeyAltDown KeyAltEof KeyAltExtend +token: KeyAltForm KeyAltHelp KeyAltHome KeyAltHomeD KeyAltInsChar KeyAltInsLine +token: KeyAltKeys KeyAltLeft KeyAltLocal KeyAltLocalTab KeyAltMenu KeyAltMenuBar +token: KeyAltNext KeyAltNull KeyAltPaste KeyAltPoint KeyAltPrev KeyAltPrint KeyAltReplace +token: KeyAltReturn KeyAltRight KeyAltRollDn KeyAltRollUp KeyAltSelect KeyAltSoft1 +token: KeyAltSoft10 KeyAltSoft11 KeyAltSoft12 KeyAltSoft13 KeyAltSoft14 KeyAltSoft15 +token: KeyAltSoft16 KeyAltSoft17 KeyAltSoft18 KeyAltSoft19 KeyAltSoft2 KeyAltSoft20 +token: KeyAltSoft21 KeyAltSoft22 KeyAltSoft23 KeyAltSoft24 KeyAltSoft25 KeyAltSoft26 +token: KeyAltSoft27 KeyAltSoft28 KeyAltSoft29 KeyAltSoft3 KeyAltSoft30 KeyAltSoft31 +token: KeyAltSoft32 KeyAltSoft4 KeyAltSoft5 KeyAltSoft6 KeyAltSoft7 KeyAltSoft8 +token: KeyAltSoft9 KeyAltTab KeyAltTimer KeyAltUp KeyAltWindowList KeyAltWindowMenu +token: KeyBack KeyBackTab KeyCancel KeyClrDisp KeyClrLine KeyCopy KeyCut KeyDelChar +token: KeyDelLine KeyDo KeyDown KeyEof KeyExtend KeyForm KeyHelp KeyHome KeyHomeD +token: KeyInsChar KeyInsLine KeyKeys KeyLeft KeyLocal KeyLocalTab KeyMenu KeyMenuBar +token: KeyNext KeyNull KeyPaste KeyPoint KeyPrev KeyPrint KeyReplace KeyReturn +token: KeyRight KeyRollDn KeyRollUp KeySelect KeySoft1 KeySoft10 KeySoft11 KeySoft12 +token: KeySoft13 KeySoft14 KeySoft15 KeySoft16 KeySoft17 KeySoft18 KeySoft19 KeySoft2 +token: KeySoft20 KeySoft21 KeySoft22 KeySoft23 KeySoft24 KeySoft25 KeySoft26 KeySoft27 +token: KeySoft28 KeySoft29 KeySoft3 KeySoft30 KeySoft31 KeySoft32 KeySoft4 KeySoft5 +token: KeySoft6 KeySoft7 KeySoft8 KeySoft9 KeyTab KeyTimer KeyUp KeyWindowList +token: KeyWindowMenu + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMsgAny OuiMsgKeyAny OuiMsgKeyAnyPrintable OuiMsgMouseAny OuiMsgMouseAnyDbl +token: OuiMsgMouseAnyDown OuiMsgMouseAnyDrag OuiMsgMouseAnyUp + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMsgB1Down OuiMsgB1Drag OuiMsgB1Up OuiMsgB2Down OuiMsgB2Drag OuiMsgB2Up +token: OuiMsgB3Down OuiMsgB3Drag OuiMsgB3Up OuiMsgB4Down OuiMsgB4Drag OuiMsgB4Up +token: OuiMsgB5Down OuiMsgB5Drag OuiMsgB5Up OuiMsgMouseB1 OuiMsgMouseB1Dbl OuiMsgMouseB1Down +token: OuiMsgMouseB1Down OuiMsgMouseB1Drag OuiMsgMouseB1Up OuiMsgMouseB2Dbl OuiMsgMouseB2Down +token: OuiMsgMouseB2Down OuiMsgMouseB2Drag OuiMsgMouseB2Up OuiMsgMouseB2Up OuiMsgMouseB3Dbl +token: OuiMsgMouseB3Down OuiMsgMouseB3Down OuiMsgMouseB3Drag OuiMsgMouseB3Up OuiMsgMouseB3Up +token: OuiMsgMouseB4Dbl OuiMsgMouseB4Down OuiMsgMouseB4Drag OuiMsgMouseB4Up OuiMsgMouseB5Dbl +token: OuiMsgMouseB5Dowkn OuiMsgMouseB5Drag OuiMsgMouseB5Up + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMessageHelponHelp OuiMsgAbout OuiMsgClose OuiMsgCreationAborted OuiMsgDbCommit +token: OuiMsgDbCommit OuiMsgDbCommitResult OuiMsgDbCommitResult OuiMsgDbConnect +token: OuiMsgDbConnectResult OuiMsgDbDisconnect OuiMsgDbDisconnectResult OuiMsgDbExecuteSQL +token: OuiMsgDbExecuteSQLResult OuiMsgDefocus OuiMsgDmDeleteMajor OuiMsgDmDeleteMinor +token: OuiMsgDmInsertMajor OuiMsgDmInsertMinor OuiMsgDmInvalidateArea OuiMsgDmNotify +token: OuiMsgDoublePick OuiMsgDrag OuiMsgDragCancel OuiMsgDragDone OuiMsgDragHelp +token: OuiMsgDragMotion OuiMsgDragStart OuiMsgDrop OuiMsgEvaluatorChanged OuiMsgEvaluatorDrag +token: OuiMsgExitApplication OuiMsgFocus OuiMsgFocusIn OuiMsgFocusOut OuiMsgFormStateChanged +token: OuiMsgGridDragged OuiMsgHelp OuiMsgHelpClearStatus OuiMsgHelpClose OuiMsgHelpContext +token: OuiMsgHelpHideHint OuiMsgHelpIndex OuiMsgHelpKey OuiMsgHelpPick OuiMsgHelpShowHint +token: OuiMsgHelpShowStatus OuiMsgInvisible OuiMsgLockClear OuiMsgLockException +token: OuiMsgLockId OuiMsgLockRelease OuiMsgLockRequest OuiMsgLowResources OuiMsgMDIArrangeIcons +token: OuiMsgMDICascade OuiMsgMDIClose OuiMsgMDITile OuiMsgMove OuiMsgNewRadioButton +token: OuiMsgNoResources OuiMsgNothingCanHappen OuiMsgPick OuiMsgPlace OuiMsgQueryExecute +token: OuiMsgQueryExecuteResult OuiMsgQueryFetchRows OuiMsgQueryFetchRowsResult +token: OuiMsgRubberLine OuiMsgRubberRect OuiMsgSelect OuiMsgSelectionChange OuiMsgSelectionDefocus +token: OuiMsgSelectionDoubleClick OuiMsgSessionAborted OuiMsgSize OuiMsgTableDataArrived +token: OuiMsgTimer OuiMsgTimerCancel OuiMsgTnfData OuiMsgTnfException OuiMsgTnfInitiateRequest +token: OuiMsgTnfInitiateSupply OuiMsgTopLeftChanged OuiMsgTxnCancel OuiMsgTxnCommit +token: OuiMsgTxnData OuiMsgTxnException OuiMsgTxnId OuiMsgTxnIdRequest OuiMsgTxnInitiateRequest +token: OuiMsgTxnInitiateSupply OuiMsgVisible OuiMsgWMFocusIn + +color: red, normal, red, bold +token: FALSE NULL TRUE + +color: darkred, normal, darkred, normal +token: div not + +# Comments +color: darkcyan, normal, darkcyan, outline +eolCom: // +comCol: 0 + +openCom: /* +closeCom: */ + +# Symbols + +color: darkpink, normal, darkpink, italic +string: " + +color: darkpink, normal, darkpink, italic +char: ' + +color: red, normal, red, normal +literal: \ + +color: myDarkBlue, normal, myDarkBlue, bold +funcParml: ( + +color: myDarkYellow, normal, myDarkYellow, normal +decPrefix: + +color: darkgreen, normal, darkgreen, normal +hexPrefix: 0X + +color: darkgray, normal, darkgray, normal +octalPrefix: 0 + +numPostfix: L + +color: red, normal, red, normal +symbol: ><{}()+-:&!|=~?.;,^/* +color: red, normal, red, normal +symbol: [] + + +#=========================================================== + diff --git a/syntax/pd_opl.syn2 b/syntax/pd_opl.syn2 new file mode 100644 index 0000000..54048df --- /dev/null +++ b/syntax/pd_opl.syn2 @@ -0,0 +1,234 @@ +#=========================================================== +# +# MED file mode definition file +# Last updated: 12.07.2002 20:10 +# +#=========================================================== + +files: *.opl +title: Open UI's OPL + +default: no +caseSensitive: yes +checkCommentInString: yes +shiftDistance: 1 +tabWidth: 2 +tabLoadExpand: 0 +tabInsAsBlank: 1 + +sectionRegexp: (^[ ]*)(class|function)[ ]+([a-zA-Z0-9_\$]+) +sectionDisplayRegexp: (^[ ]*)(class|function)[ ]+([a-zA-Z0-9_\$]+) +sectionBrowserOrder: 2, 3 +sectionDisplayOrder: 2, 3 +sectionBrowserMainKey: 3 +sectionDisplay: 5000, 1000 + +wordWrap: disabled 70 >!:~# + +wordSep:'&()[]{}\<>.,;-+*:?!=-|"/~ + +# 3rd party online help +inf: netscape.cmd|%h http://info.propack-data.de/Doku/Programmierung/OpenUI/htmlindx.htm * http://info.propack-data.de/Doku/Programmierung/OpenUI/htmlindx.htm + + +# brackets +bracket: ( ) 1 +bracket: { } 1 +bracket: [ ] 0 + + +# Color definitions +defineColor: myGreen 0 100 10 +defineColor: myDarkYellow 150 150 0 +defineColor: myDarkBlue 0 0 150 +defineColor: myDarkRed 200 0 0 +defineColor: myDarkestRed 150 0 0 +defineColor: myLightGray 220 220 220 + + +foregroundColor: black +backgroundColor: white +blockColor: myLightGray + +# Reserved words + +color: blue, normal, blue, bold +token: FALSE OuiBooleanT OuiCharT OuiDecimalT OuiFloatT OuiIntegerT OuiLongT OuiPointerT +token: OuiShortT OuiStringT OuiZonedT TRUE accelerator action alias and array +token: attr attribute begin bool char class const constant declid div doobrie +token: else end enum export extern false float for func function goto if in init +token: initially inst instance int local long message mnemonic not of on or priv +token: private pub public readonly record rem repeat return short slot slotno +token: string to true type until var variable virtual when while zoned + +color: myDarkRed, normal, myDarkRed, normal +token: Application Button Evaluator Filledge Graphic Menu OuiObj Region Scrollable +token: Separator StandardDialog Visual arc cascade colorDialog comboBox controlBar +token: dataManager database devFontDialog dialogb diversion editText fontDialog +token: form graphicCompound groupBox horizontalSep interactor label list mdiFrameForm +token: menuBar menuBarButton menuButton menuCascadeButton menuPushButton menuRadioButton +token: menuToggleButton messageBox module multiTextL multiTextW openSaveDialog +token: optionMenu panel popupMenu pulldown pushButton query radioButton radioPushButton +token: scene scrollbar session slider spline statusText table timer toggleButton +token: togglePushButton tpMenuBar tpSpreadSheet tpStatusBar tpTable tpToolBar +token: verticalSep + +color: myGreen, normal, myGreen, normal +token: AccelLabel Active ActiveCell ActiveCellBackground ActiveCellForeground +token: ActivePrefix ActiveQuery AlignHoriz AlignVert Alignment AllowClose AllowMaximize +token: AllowMinimize AllowMove AllowResize AspectLock AspectRatio AutoCommit AutoFlow +token: AutoResizePolicy BaseHeight BaseWidth BeepOnDiscard BorderStyle BorderStyle +token: BorderWidth Bounds ButtonModifiers ButtonNumber Bytes CatName CatSetNum +token: Changed Class Closed ColumnCount ColumnLengths ColumnNames ColumnTypes +token: ComboBoxStyle CommitDirection Connected CursorName DataDemandPolicy DataOrigin +token: DataPendingPolicy DatasourceName DateInputFormat DecimalPoints Depth Direction +token: DiscardInput DrawGridColor DrawGridStyle DynamicGrid EdgeStyle EdgeWidth +token: Editable Editable ErrorText ExtendClassLibrary FastDraw FillAlternate FillAngle +token: FocusItem Font Font Font Font Font Foreground FormState GUIType GrabInput +token: Height HeightInc HelpId IconImage IconX Image ImageData ImageTileName Increment +token: IncrementMulti IndexMajor IndexMinor InputEdit InputMode InsensColor InsensColor +token: InsertMode IsDefault ItemCount Items JumpScroll Label LabelDisplayPolicy +token: LastNativeError Length LineStyle LineWidth LockedColumns LockedRows MajorCount +token: MajorIncrement MarginHeight MarginHeight MarginWidth MarginWidth MaxAspectX +token: MaxAspectY MaxBytes MaxBytes MaxHeight MaxOffsetHoriz MaxOffsetVert MaxWidth +token: Maximized MinAspectX MinAspectY MinChars MinChars MinColumns MinHeight +token: MinLines MinRows MinWidth Mnemonic Modal Mode NPoints NPoints Name NativeHandle +token: NativeHandle NativeHandle NavigateLocked Offset OffsetHoriz OffsetVert +token: OnDesktop Orientation OutputEdit OutputFormat OverrideRedirect PageSize +token: PagesLocked PagesMemory PagingPolicy Parent PassivePrefix PasswordChar +token: Pattern Placement PlacementDetail PlacementPolicy Points PositionX PositionY +token: PrimarySource PrimarySource QueryType Radio RadiusMajor RadiusMinor RangeHoriz +token: RangeMajor RangeMinor RangeVert RealizePolicy RotateAngle RowMajor RowMajor +token: SaveUnder ScaleX ScaleY ScreenHeight, ScreenWidth ScrollBarPlacement ScrollBarTroughColor +token: ScrollHoriz ScrollVert Sector SelectedAreas SelectedItemBG SelectedItemCount +token: SelectedItemFG SelectedItemList SelectedItemMap SelectedItems SelectedText +token: SelectionBackground SelectionForeground SelectionLength SelectionPolicy +token: SelectionPolicy SelectionStart Self Sensitive Sensitive ShortHelpText ShowButtons +token: ShowIndicator ShowMinimize ShowResizeHandles ShowSysMenu ShowTitle ShowValue +token: SizeVisible SoftKey SpaceColumns SpaceItems SpaceRows SpanX SpanY StartAngle +token: StretchHoriz StretchVert Style Suffix Template Thickness ThumbSize Title +token: Title TitleFont TitlePlacement Toggle TopLeft Trace Transient Traversable +token: TroughColor UniformColumns UniformRows Units Updatable Valid Value Value +token: ValueMax ValueMin Visible VisibleColumns VisibleItems VisibleRows Width +token: WidthInc WorldCoords WrapMode WrapNavigation X Y + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiDestroy OuiGetTime OuiInstantiate OuiListAppend OuiListDeleteItem OuiListFind +token: OuiListInsertItem OuiListItems OuiListNumItems OuiListReFind OuiListSort +token: OuiLookup OuiPrefsClose OuiPrefsGetBoolean OuiPrefsGetEnum OuiPrefsGetLong +token: OuiPrefsGetMask OuiPrefsGetString OuiPrefsItemEnumerate OuiPrefsMerge OuiPrefsOpen +token: OuiPrefsSave OuiPrefsSectionEnumerate OuiPrefsSetBoolean OuiPrefsSetEnum +token: OuiPrefsSetLong OuiPrefsSetMask OuiPrefsSetString OuiPrint OuiQueueMessage +token: OuiReCmp OuiReDestroy OuiReExtract OuiReMatch OuiStrChr OuiStrIsAlnum OuiStrIsAlpha +token: OuiStrIsDigit OuiStrIsLower OuiStrIsPunct OuiStrIsSpace OuiStrIsUpper OuiStrLen +token: OuiStrPad OuiStrRChr OuiStrStr OuiStrToLower OuiStrToUpper OuiStrTrim OuiSubStr +token: OuiSynchronize OuiTrace OuiWebBrowserLoadURL + +color: myDarkestRed, normal, myDarkestRed, normal +token: KeyAltBack KeyAltBackTab KeyAltCancel KeyAltClrDisp KeyAltClrLine KeyAltCopy +token: KeyAltCut KeyAltDelChar KeyAltDelLine KeyAltDo KeyAltDown KeyAltEof KeyAltExtend +token: KeyAltForm KeyAltHelp KeyAltHome KeyAltHomeD KeyAltInsChar KeyAltInsLine +token: KeyAltKeys KeyAltLeft KeyAltLocal KeyAltLocalTab KeyAltMenu KeyAltMenuBar +token: KeyAltNext KeyAltNull KeyAltPaste KeyAltPoint KeyAltPrev KeyAltPrint KeyAltReplace +token: KeyAltReturn KeyAltRight KeyAltRollDn KeyAltRollUp KeyAltSelect KeyAltSoft1 +token: KeyAltSoft10 KeyAltSoft11 KeyAltSoft12 KeyAltSoft13 KeyAltSoft14 KeyAltSoft15 +token: KeyAltSoft16 KeyAltSoft17 KeyAltSoft18 KeyAltSoft19 KeyAltSoft2 KeyAltSoft20 +token: KeyAltSoft21 KeyAltSoft22 KeyAltSoft23 KeyAltSoft24 KeyAltSoft25 KeyAltSoft26 +token: KeyAltSoft27 KeyAltSoft28 KeyAltSoft29 KeyAltSoft3 KeyAltSoft30 KeyAltSoft31 +token: KeyAltSoft32 KeyAltSoft4 KeyAltSoft5 KeyAltSoft6 KeyAltSoft7 KeyAltSoft8 +token: KeyAltSoft9 KeyAltTab KeyAltTimer KeyAltUp KeyAltWindowList KeyAltWindowMenu +token: KeyBack KeyBackTab KeyCancel KeyClrDisp KeyClrLine KeyCopy KeyCut KeyDelChar +token: KeyDelLine KeyDo KeyDown KeyEof KeyExtend KeyForm KeyHelp KeyHome KeyHomeD +token: KeyInsChar KeyInsLine KeyKeys KeyLeft KeyLocal KeyLocalTab KeyMenu KeyMenuBar +token: KeyNext KeyNull KeyPaste KeyPoint KeyPrev KeyPrint KeyReplace KeyReturn +token: KeyRight KeyRollDn KeyRollUp KeySelect KeySoft1 KeySoft10 KeySoft11 KeySoft12 +token: KeySoft13 KeySoft14 KeySoft15 KeySoft16 KeySoft17 KeySoft18 KeySoft19 KeySoft2 +token: KeySoft20 KeySoft21 KeySoft22 KeySoft23 KeySoft24 KeySoft25 KeySoft26 KeySoft27 +token: KeySoft28 KeySoft29 KeySoft3 KeySoft30 KeySoft31 KeySoft32 KeySoft4 KeySoft5 +token: KeySoft6 KeySoft7 KeySoft8 KeySoft9 KeyTab KeyTimer KeyUp KeyWindowList +token: KeyWindowMenu + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMsgAny OuiMsgKeyAny OuiMsgKeyAnyPrintable OuiMsgMouseAny OuiMsgMouseAnyDbl +token: OuiMsgMouseAnyDown OuiMsgMouseAnyDrag OuiMsgMouseAnyUp + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMsgB1Down OuiMsgB1Drag OuiMsgB1Up OuiMsgB2Down OuiMsgB2Drag OuiMsgB2Up +token: OuiMsgB3Down OuiMsgB3Drag OuiMsgB3Up OuiMsgB4Down OuiMsgB4Drag OuiMsgB4Up +token: OuiMsgB5Down OuiMsgB5Drag OuiMsgB5Up OuiMsgMouseB1 OuiMsgMouseB1Dbl OuiMsgMouseB1Down +token: OuiMsgMouseB1Down OuiMsgMouseB1Drag OuiMsgMouseB1Up OuiMsgMouseB2Dbl OuiMsgMouseB2Down +token: OuiMsgMouseB2Down OuiMsgMouseB2Drag OuiMsgMouseB2Up OuiMsgMouseB2Up OuiMsgMouseB3Dbl +token: OuiMsgMouseB3Down OuiMsgMouseB3Down OuiMsgMouseB3Drag OuiMsgMouseB3Up OuiMsgMouseB3Up +token: OuiMsgMouseB4Dbl OuiMsgMouseB4Down OuiMsgMouseB4Drag OuiMsgMouseB4Up OuiMsgMouseB5Dbl +token: OuiMsgMouseB5Dowkn OuiMsgMouseB5Drag OuiMsgMouseB5Up + +color: myDarkestRed, normal, myDarkestRed, normal +token: OuiMessageHelponHelp OuiMsgAbout OuiMsgClose OuiMsgCreationAborted OuiMsgDbCommit +token: OuiMsgDbCommit OuiMsgDbCommitResult OuiMsgDbCommitResult OuiMsgDbConnect +token: OuiMsgDbConnectResult OuiMsgDbDisconnect OuiMsgDbDisconnectResult OuiMsgDbExecuteSQL +token: OuiMsgDbExecuteSQLResult OuiMsgDefocus OuiMsgDmDeleteMajor OuiMsgDmDeleteMinor +token: OuiMsgDmInsertMajor OuiMsgDmInsertMinor OuiMsgDmInvalidateArea OuiMsgDmNotify +token: OuiMsgDoublePick OuiMsgDrag OuiMsgDragCancel OuiMsgDragDone OuiMsgDragHelp +token: OuiMsgDragMotion OuiMsgDragStart OuiMsgDrop OuiMsgEvaluatorChanged OuiMsgEvaluatorDrag +token: OuiMsgExitApplication OuiMsgFocus OuiMsgFocusIn OuiMsgFocusOut OuiMsgFormStateChanged +token: OuiMsgGridDragged OuiMsgHelp OuiMsgHelpClearStatus OuiMsgHelpClose OuiMsgHelpContext +token: OuiMsgHelpHideHint OuiMsgHelpIndex OuiMsgHelpKey OuiMsgHelpPick OuiMsgHelpShowHint +token: OuiMsgHelpShowStatus OuiMsgInvisible OuiMsgLockClear OuiMsgLockException +token: OuiMsgLockId OuiMsgLockRelease OuiMsgLockRequest OuiMsgLowResources OuiMsgMDIArrangeIcons +token: OuiMsgMDICascade OuiMsgMDIClose OuiMsgMDITile OuiMsgMove OuiMsgNewRadioButton +token: OuiMsgNoResources OuiMsgNothingCanHappen OuiMsgPick OuiMsgPlace OuiMsgQueryExecute +token: OuiMsgQueryExecuteResult OuiMsgQueryFetchRows OuiMsgQueryFetchRowsResult +token: OuiMsgRubberLine OuiMsgRubberRect OuiMsgSelect OuiMsgSelectionChange OuiMsgSelectionDefocus +token: OuiMsgSelectionDoubleClick OuiMsgSessionAborted OuiMsgSize OuiMsgTableDataArrived +token: OuiMsgTimer OuiMsgTimerCancel OuiMsgTnfData OuiMsgTnfException OuiMsgTnfInitiateRequest +token: OuiMsgTnfInitiateSupply OuiMsgTopLeftChanged OuiMsgTxnCancel OuiMsgTxnCommit +token: OuiMsgTxnData OuiMsgTxnException OuiMsgTxnId OuiMsgTxnIdRequest OuiMsgTxnInitiateRequest +token: OuiMsgTxnInitiateSupply OuiMsgVisible OuiMsgWMFocusIn + +color: red, normal, red, bold +token: FALSE NULL TRUE + +color: darkred, normal, darkred, normal +token: div not + +# Comments +color: darkcyan, normal, darkcyan, outline +eolCom: // +comCol: 0 + +openCom: /* +closeCom: */ + +# Symbols + +color: darkpink, normal, darkpink, italic +string: " + +color: darkpink, normal, darkpink, italic +char: ' + +color: red, normal, red, normal +literal: \ + +color: myDarkBlue, normal, myDarkBlue, bold +funcParml: ( + +color: myDarkYellow, normal, myDarkYellow, normal +decPrefix: + +color: darkgreen, normal, darkgreen, normal +hexPrefix: 0X + +color: darkgray, normal, darkgray, normal +octalPrefix: 0 + +numPostfix: L + +color: red, normal, red, normal +symbol: ><{}()+-:&!|=~?.;,^/* +color: red, normal, red, normal +symbol: [] + + +#=========================================================== + diff --git a/syntax/python.vim b/syntax/python.vim new file mode 100644 index 0000000..b766869 --- /dev/null +++ b/syntax/python.vim @@ -0,0 +1,376 @@ +" Vim syntax file +" Language: Python +" Maintainer: Dmitry Vasiliev +" URL: http://www.hlabs.spb.ru/vim/python.vim +" Last Change: 2010-04-09 +" Filenames: *.py +" Version: 2.6.6 +" +" Based on python.vim (from Vim 6.1 distribution) +" by Neil Schemenauer +" +" Thanks: +" +" Jeroen Ruigrok van der Werven +" for the idea to highlight erroneous operators +" Pedro Algarvio +" for the patch to enable spell checking only for the right spots +" (strings and comments) +" John Eikenberry +" for the patch fixing small typo +" Caleb Adamantine +" for the patch fixing highlighting for decorators +" Andrea Riciputi +" for the patch with new configuration options + +" +" Options: +" +" For set option do: let OPTION_NAME = 1 +" For clear option do: let OPTION_NAME = 0 +" +" Option names: +" +" For highlight builtin functions and objects: +" python_highlight_builtins +" +" For highlight builtin objects: +" python_highlight_builtin_objs +" +" For highlight builtin funtions: +" python_highlight_builtin_funcs +" +" For highlight standard exceptions: +" python_highlight_exceptions +" +" For highlight string formatting: +" python_highlight_string_formatting +" +" For highlight str.format syntax: +" python_highlight_string_format +" +" For highlight string.Template syntax: +" python_highlight_string_templates +" +" For highlight indentation errors: +" python_highlight_indent_errors +" +" For highlight trailing spaces: +" python_highlight_space_errors +" +" For highlight doc-tests: +" python_highlight_doctests +" +" If you want all Python highlightings above: +" python_highlight_all +" (This option not override previously set options) +" +" For fast machines: +" python_slow_sync +" +" For "print" builtin as function: +" python_print_as_function + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +if exists("python_highlight_all") && python_highlight_all != 0 + " Not override previously set options + if !exists("python_highlight_builtins") + if !exists("python_highlight_builtin_objs") + let python_highlight_builtin_objs = 1 + endif + if !exists("python_highlight_builtin_funcs") + let python_highlight_builtin_funcs = 1 + endif + endif + if !exists("python_highlight_exceptions") + let python_highlight_exceptions = 1 + endif + if !exists("python_highlight_string_formatting") + let python_highlight_string_formatting = 1 + endif + if !exists("python_highlight_string_format") + let python_highlight_string_format = 1 + endif + if !exists("python_highlight_string_templates") + let python_highlight_string_templates = 1 + endif + if !exists("python_highlight_indent_errors") + let python_highlight_indent_errors = 1 + endif + if !exists("python_highlight_space_errors") + let python_highlight_space_errors = 1 + endif + if !exists("python_highlight_doctests") + let python_highlight_doctests = 1 + endif +endif + +" Keywords +syn keyword pythonStatement break continue del +syn keyword pythonStatement exec return +syn keyword pythonStatement pass raise +syn keyword pythonStatement global assert +syn keyword pythonStatement lambda yield +syn keyword pythonStatement with +syn keyword pythonStatement def class nextgroup=pythonFunction skipwhite +syn match pythonFunction "[a-zA-Z_][a-zA-Z0-9_]*" display contained +syn keyword pythonRepeat for while +syn keyword pythonConditional if elif else +syn keyword pythonPreCondit import from as +syn keyword pythonException try except finally +syn keyword pythonOperator and in is not or + +if !exists("python_print_as_function") || python_print_as_function == 0 + syn keyword pythonStatement print +endif + +" Decorators (new in Python 2.4) +" gryf: match also name of the decorator not only at sign. +syn match pythonDecorator "@[a-zA-Z_][a-zA-Z0-9_]*" display nextgroup=pythonDottedName skipwhite +"syn match pythonDecorator "@" display nextgroup=pythonDottedName skipwhite +syn match pythonDottedName "[a-zA-Z_][a-zA-Z0-9_]*\(\.[a-zA-Z_][a-zA-Z0-9_]*\)*" display contained +syn match pythonDot "\." display containedin=pythonDottedName + +" Comments +syn match pythonComment "#.*$" display contains=pythonTodo,@Spell +syn match pythonRun "\%^#!.*$" +syn match pythonCoding "\%^.*\(\n.*\)\?#.*coding[:=]\s*[0-9A-Za-z-_.]\+.*$" +syn keyword pythonTodo TODO FIXME XXX contained + +" Errors +syn match pythonError "\<\d\+\D\+\>" display +syn match pythonError "[$?]" display +syn match pythonError "[&|]\{2,}" display +syn match pythonError "[=]\{3,}" display + +" TODO: Mixing spaces and tabs also may be used for pretty formatting multiline +" statements. For now I don't know how to work around this. +if exists("python_highlight_indent_errors") && python_highlight_indent_errors != 0 + syn match pythonIndentError "^\s*\( \t\|\t \)\s*\S"me=e-1 display +endif + +" Trailing space errors +if exists("python_highlight_space_errors") && python_highlight_space_errors != 0 + syn match pythonSpaceError "\s\+$" display +endif + +" Strings +syn region pythonString start=+[bB]\='+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell +syn region pythonString start=+[bB]\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell +syn region pythonString start=+[bB]\="""+ end=+"""+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonString start=+[bB]\='''+ end=+'''+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonEscape +\\[abfnrtv'"\\]+ display contained +syn match pythonEscape "\\\o\o\=\o\=" display contained +syn match pythonEscapeError "\\\o\{,2}[89]" display contained +syn match pythonEscape "\\x\x\{2}" display contained +syn match pythonEscapeError "\\x\x\=\X" display contained +syn match pythonEscape "\\$" + +" Unicode strings +syn region pythonUniString start=+[uU]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell +syn region pythonUniString start=+[uU]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell +syn region pythonUniString start=+[uU]"""+ end=+"""+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonUniString start=+[uU]'''+ end=+'''+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonUniEscape "\\u\x\{4}" display contained +syn match pythonUniEscapeError "\\u\x\{,3}\X" display contained +syn match pythonUniEscape "\\U\x\{8}" display contained +syn match pythonUniEscapeError "\\U\x\{,7}\X" display contained +syn match pythonUniEscape "\\N{[A-Z ]\+}" display contained +syn match pythonUniEscapeError "\\N{[^A-Z ]\+}" display contained + +" Raw strings +syn region pythonRawString start=+[rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,@Spell +syn region pythonRawString start=+[rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,@Spell +syn region pythonRawString start=+[rR]"""+ end=+"""+ keepend contains=pythonDocTest2,pythonSpaceError,@Spell +syn region pythonRawString start=+[rR]'''+ end=+'''+ keepend contains=pythonDocTest,pythonSpaceError,@Spell + +syn match pythonRawEscape +\\['"]+ display transparent contained + +" Unicode raw strings +syn region pythonUniRawString start=+[uU][rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell +syn region pythonUniRawString start=+[uU][rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell +syn region pythonUniRawString start=+[uU][rR]"""+ end=+"""+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonUniRawString start=+[uU][rR]'''+ end=+'''+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonUniRawEscape "\([^\\]\(\\\\\)*\)\@<=\\u\x\{4}" display contained +syn match pythonUniRawEscapeError "\([^\\]\(\\\\\)*\)\@<=\\u\x\{,3}\X" display contained + +if exists("python_highlight_string_formatting") && python_highlight_string_formatting != 0 + " String formatting + syn match pythonStrFormatting "%\(([^)]\+)\)\=[-#0 +]*\d*\(\.\d\+\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrFormatting "%[-#0 +]*\(\*\|\d\+\)\=\(\.\(\*\|\d\+\)\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_string_format") && python_highlight_string_format != 0 + " str.format syntax + syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrFormat "{\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)\(\.[a-zA-Z_][a-zA-Z0-9_]*\|\[\(\d\+\|[^!:\}]\+\)\]\)*\(![rs]\)\=\(:\({\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)}\|\([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*\(\.\d\+\)\=[bcdeEfFgGnoxX%]\=\)\=\)\=}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_string_templates") && python_highlight_string_templates != 0 + " String templates + syn match pythonStrTemplate "\$\$" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrTemplate "\${[a-zA-Z_][a-zA-Z0-9_]*}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrTemplate "\$[a-zA-Z_][a-zA-Z0-9_]*" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_doctests") && python_highlight_doctests != 0 + " DocTests + syn region pythonDocTest start="^\s*>>>" end=+'''+he=s-1 end="^\s*$" contained + syn region pythonDocTest2 start="^\s*>>>" end=+"""+he=s-1 end="^\s*$" contained +endif + +" Numbers (ints, longs, floats, complex) +syn match pythonHexError "\<0[xX]\x*[g-zG-Z]\x*[lL]\=\>" display + +syn match pythonHexNumber "\<0[xX]\x\+[lL]\=\>" display +syn match pythonOctNumber "\<0[oO]\o\+[lL]\=\>" display +syn match pythonBinNumber "\<0[bB][01]\+[lL]\=\>" display + +syn match pythonNumber "\<\d\+[lLjJ]\=\>" display + +syn match pythonFloat "\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" display +syn match pythonFloat "\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display +syn match pythonFloat "\<\d\+\.\d*\([eE][+-]\=\d\+\)\=[jJ]\=" display + +syn match pythonOctError "\<0[oO]\=\o*[8-9]\d*[lL]\=\>" display +syn match pythonBinError "\<0[bB][01]*[2-9]\d*[lL]\=\>" display + +if exists("python_highlight_builtin_objs") && python_highlight_builtin_objs != 0 + " Builtin objects and types + syn keyword pythonBuiltinObj True False Ellipsis None NotImplemented + syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ +endif + +if exists("python_highlight_builtin_funcs") && python_highlight_builtin_funcs != 0 + " Builtin functions + syn keyword pythonBuiltinFunc __import__ abs all any apply + syn keyword pythonBuiltinFunc basestring bin bool buffer bytearray bytes callable + syn keyword pythonBuiltinFunc chr classmethod cmp coerce compile complex + syn keyword pythonBuiltinFunc delattr dict dir divmod enumerate eval + syn keyword pythonBuiltinFunc execfile file filter float format frozenset getattr + syn keyword pythonBuiltinFunc globals hasattr hash help hex id + syn keyword pythonBuiltinFunc input int intern isinstance + syn keyword pythonBuiltinFunc issubclass iter len list locals long map max + syn keyword pythonBuiltinFunc min next object oct open ord + syn keyword pythonBuiltinFunc pow property range + syn keyword pythonBuiltinFunc raw_input reduce reload repr + syn keyword pythonBuiltinFunc reversed round set setattr + syn keyword pythonBuiltinFunc slice sorted staticmethod str sum super tuple + syn keyword pythonBuiltinFunc type unichr unicode vars xrange zip + + if exists("python_print_as_function") && python_print_as_function != 0 + syn keyword pythonBuiltinFunc print + endif +endif + +if exists("python_highlight_exceptions") && python_highlight_exceptions != 0 + " Builtin exceptions and warnings + syn keyword pythonExClass BaseException + syn keyword pythonExClass Exception StandardError ArithmeticError + syn keyword pythonExClass LookupError EnvironmentError + + syn keyword pythonExClass AssertionError AttributeError BufferError EOFError + syn keyword pythonExClass FloatingPointError GeneratorExit IOError + syn keyword pythonExClass ImportError IndexError KeyError + syn keyword pythonExClass KeyboardInterrupt MemoryError NameError + syn keyword pythonExClass NotImplementedError OSError OverflowError + syn keyword pythonExClass ReferenceError RuntimeError StopIteration + syn keyword pythonExClass SyntaxError IndentationError TabError + syn keyword pythonExClass SystemError SystemExit TypeError + syn keyword pythonExClass UnboundLocalError UnicodeError + syn keyword pythonExClass UnicodeEncodeError UnicodeDecodeError + syn keyword pythonExClass UnicodeTranslateError ValueError VMSError + syn keyword pythonExClass WindowsError ZeroDivisionError + + syn keyword pythonExClass Warning UserWarning BytesWarning DeprecationWarning + syn keyword pythonExClass PendingDepricationWarning SyntaxWarning + syn keyword pythonExClass RuntimeWarning FutureWarning + syn keyword pythonExClass ImportWarning UnicodeWarning +endif + +if exists("python_slow_sync") && python_slow_sync != 0 + syn sync minlines=2000 +else + " This is fast but code inside triple quoted strings screws it up. It + " is impossible to fix because the only way to know if you are inside a + " triple quoted string is to start from the beginning of the file. + syn sync match pythonSync grouphere NONE "):$" + syn sync maxlines=200 +endif + +if version >= 508 || !exists("did_python_syn_inits") + if version <= 508 + let did_python_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + + HiLink pythonStatement Statement + HiLink pythonPreCondit Statement + HiLink pythonFunction Function + HiLink pythonConditional Conditional + HiLink pythonRepeat Repeat + HiLink pythonException Exception + HiLink pythonOperator Operator + + HiLink pythonDecorator Define + HiLink pythonDottedName Function + HiLink pythonDot Normal + + HiLink pythonComment Comment + HiLink pythonCoding Special + HiLink pythonRun Special + HiLink pythonTodo Todo + + HiLink pythonError Error + HiLink pythonIndentError Error + HiLink pythonSpaceError Error + + HiLink pythonString String + HiLink pythonUniString String + HiLink pythonRawString String + HiLink pythonUniRawString String + + HiLink pythonEscape Special + HiLink pythonEscapeError Error + HiLink pythonUniEscape Special + HiLink pythonUniEscapeError Error + HiLink pythonUniRawEscape Special + HiLink pythonUniRawEscapeError Error + + HiLink pythonStrFormatting Special + HiLink pythonStrFormat Special + HiLink pythonStrTemplate Special + + HiLink pythonDocTest Special + HiLink pythonDocTest2 Special + + HiLink pythonNumber Number + HiLink pythonHexNumber Number + HiLink pythonOctNumber Number + HiLink pythonBinNumber Number + HiLink pythonFloat Float + HiLink pythonOctError Error + HiLink pythonHexError Error + HiLink pythonBinError Error + + HiLink pythonBuiltinObj Structure + HiLink pythonBuiltinFunc Function + + HiLink pythonExClass Structure + + delcommand HiLink +endif + +let b:current_syntax = "python" diff --git a/syntax/snippet.vim b/syntax/snippet.vim new file mode 100644 index 0000000..5e919e7 --- /dev/null +++ b/syntax/snippet.vim @@ -0,0 +1,19 @@ +" Syntax highlighting for snippet files (used for snipMate.vim) +" Hopefully this should make snippets a bit nicer to write! +syn match snipComment '^#.*' +syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand +syn match tabStop '\$\d\+' +syn match snipCommand '`.\{-}`' +syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword +syn match multiSnipText '\S\+ \zs.*' contained +syn match snipKeyword '^snippet'me=s+8 contained +syn match snipError "^[^#s\t].*$" + +hi link snipComment Comment +hi link multiSnipText String +hi link snipKeyword Keyword +hi link snipComment Comment +hi link placeHolder Special +hi link tabStop Special +hi link snipCommand String +hi link snipError Error diff --git a/syntax/svkannotate.vim b/syntax/svkannotate.vim new file mode 100644 index 0000000..3c53c3c --- /dev/null +++ b/syntax/svkannotate.vim @@ -0,0 +1,42 @@ +" Vim syntax file +" Language: SVK annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match svkDate /\d\{4}-\d\{1,2}-\d\{1,2}/ skipwhite contained +syn match svkName /(\s*\zs\S\+/ contained nextgroup=svkDate skipwhite +syn match svkVer /^\s*\d\+/ contained nextgroup=svkName skipwhite +syn region svkHead start=/^/ end="):" contains=svkVer,svkName,svkDate oneline + +if !exists("did_svkannotate_syntax_inits") + let did_svkannotate_syntax_inits = 1 + hi link svkName Type + hi link svkDate Comment + hi link svkVer Statement +endif + +let b:current_syntax="svkAnnotate" diff --git a/syntax/svnannotate.vim b/syntax/svnannotate.vim new file mode 100644 index 0000000..d46f771 --- /dev/null +++ b/syntax/svnannotate.vim @@ -0,0 +1,40 @@ +" Vim syntax file +" Language: SVN annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match svnName /\S\+/ contained +syn match svnVer /^\s\+\zs\d\+/ contained nextgroup=svnName skipwhite +syn match svnHead /^\s\+\d\+\s\+\S\+/ contains=svnVer,svnName + +if !exists("did_svnannotate_syntax_inits") + let did_svnannotate_syntax_inits = 1 + hi link svnName Type + hi link svnVer Statement +endif + +let b:current_syntax="svnAnnotate" diff --git a/syntax/vcscommit.vim b/syntax/vcscommit.vim new file mode 100644 index 0000000..0cd4c5e --- /dev/null +++ b/syntax/vcscommit.vim @@ -0,0 +1,31 @@ +" Vim syntax file +" Language: VCS commit file +" Maintainer: Bob Hiestand (bob.hiestand@gmail.com) +" License: +" Copyright (c) 2007 Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syntax region vcsComment start="^VCS: " end="$" +highlight link vcsComment Comment +let b:current_syntax = "vcscommit" diff --git a/syntax/vimwiki.vim b/syntax/vimwiki.vim new file mode 100644 index 0000000..610a5bc --- /dev/null +++ b/syntax/vimwiki.vim @@ -0,0 +1,149 @@ +" Vimwiki syntax file +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ +" vim:tw=79: + +" Quit if syntax file is already loaded +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +"" use max highlighting - could be quite slow if there are too many wikifiles +if VimwikiGet('maxhi') + " Every WikiWord is nonexistent + if g:vimwiki_camel_case + execute 'syntax match VimwikiNoExistsWord /\%(^\|[^!]\)\@<='.g:vimwiki_word1.'/' + endif + execute 'syntax match VimwikiNoExistsWord /'.g:vimwiki_word2.'/' + execute 'syntax match VimwikiNoExistsWord /'.g:vimwiki_word3.'/' + " till we find them in vimwiki's path + call vimwiki#WikiHighlightWords() +else + " A WikiWord (unqualifiedWikiName) + execute 'syntax match VimwikiWord /\%(^\|[^!]\)\@<=\<'.g:vimwiki_word1.'\>/' + " A [[bracketed wiki word]] + execute 'syntax match VimwikiWord /'.g:vimwiki_word2.'/' +endif + +execute 'syntax match VimwikiLink `'.g:vimwiki_rxWeblink.'`' + +" Emoticons +syntax match VimwikiEmoticons /\%((.)\|:[()|$@]\|:-[DOPS()\]|$@]\|;)\|:'(\)/ + +let g:vimwiki_rxTodo = '\C\%(TODO:\|DONE:\|STARTED:\|FIXME:\|FIXED:\|XXX:\)' +execute 'syntax match VimwikiTodo /'. g:vimwiki_rxTodo .'/' + +" Load concrete Wiki syntax +execute 'runtime! syntax/vimwiki_'.VimwikiGet('syntax').'.vim' + +" Tables +" execute 'syntax match VimwikiTable /'.g:vimwiki_rxTable.'/' +syntax match VimwikiTableRow /\s*|.\+|\s*/ + \ transparent contains=VimwikiCellSeparator,VimwikiWord, + \ VimwikiNoExistsWord,VimwikiEmoticons,VimwikiTodo, + \ VimwikiBold,VimwikiItalic,VimwikiBoldItalic,VimwikiItalicBold, + \ VimwikiDelText,VimwikiSuperScript,VimwikiSubScript,VimwikiCode +syntax match VimwikiCellSeparator + \ /\%(|\)\|\%(-\@<=+\-\@=\)\|\%([|+]\@<=-\+\)/ contained + +" List items +execute 'syntax match VimwikiList /'.g:vimwiki_rxListBullet.'/' +execute 'syntax match VimwikiList /'.g:vimwiki_rxListNumber.'/' +execute 'syntax match VimwikiList /'.g:vimwiki_rxListDefine.'/' + +execute 'syntax match VimwikiBold /'.g:vimwiki_rxBold.'/' + +execute 'syntax match VimwikiItalic /'.g:vimwiki_rxItalic.'/' + +execute 'syntax match VimwikiBoldItalic /'.g:vimwiki_rxBoldItalic.'/' + +execute 'syntax match VimwikiItalicBold /'.g:vimwiki_rxItalicBold.'/' + +execute 'syntax match VimwikiDelText /'.g:vimwiki_rxDelText.'/' + +execute 'syntax match VimwikiSuperScript /'.g:vimwiki_rxSuperScript.'/' + +execute 'syntax match VimwikiSubScript /'.g:vimwiki_rxSubScript.'/' + +execute 'syntax match VimwikiCode /'.g:vimwiki_rxCode.'/' + +"
horizontal rule +execute 'syntax match VimwikiHR /'.g:vimwiki_rxHR.'/' + +execute 'syntax region VimwikiPre start=/'.g:vimwiki_rxPreStart. + \ '/ end=/'.g:vimwiki_rxPreEnd.'/ contains=VimwikiComment' + +" List item checkbox +syntax match VimwikiCheckBox /\[.\?\]/ +if g:vimwiki_hl_cb_checked + execute 'syntax match VimwikiCheckBoxDone /'. + \ g:vimwiki_rxListBullet.'\s*\['.g:vimwiki_listsyms[4].'\].*$/' + execute 'syntax match VimwikiCheckBoxDone /'. + \ g:vimwiki_rxListNumber.'\s*\['.g:vimwiki_listsyms[4].'\].*$/' +endif + +syntax region VimwikiComment start='' + +if !vimwiki#hl_exists("VimwikiHeader1") + execute 'syntax match VimwikiHeader /'.g:vimwiki_rxHeader.'/ contains=VimwikiTodo' +else + " Header levels, 1-6 + execute 'syntax match VimwikiHeader1 /'.g:vimwiki_rxH1.'/ contains=VimwikiTodo' + execute 'syntax match VimwikiHeader2 /'.g:vimwiki_rxH2.'/ contains=VimwikiTodo' + execute 'syntax match VimwikiHeader3 /'.g:vimwiki_rxH3.'/ contains=VimwikiTodo' + execute 'syntax match VimwikiHeader4 /'.g:vimwiki_rxH4.'/ contains=VimwikiTodo' + execute 'syntax match VimwikiHeader5 /'.g:vimwiki_rxH5.'/ contains=VimwikiTodo' + execute 'syntax match VimwikiHeader6 /'.g:vimwiki_rxH6.'/ contains=VimwikiTodo' +endif + +" group names "{{{ +if !vimwiki#hl_exists("VimwikiHeader1") + hi def link VimwikiHeader Title +else + hi def link VimwikiHeader1 Title + hi def link VimwikiHeader2 Title + hi def link VimwikiHeader3 Title + hi def link VimwikiHeader4 Title + hi def link VimwikiHeader5 Title + hi def link VimwikiHeader6 Title +endif + +hi def VimwikiBold term=bold cterm=bold gui=bold +hi def VimwikiItalic term=italic cterm=italic gui=italic +hi def VimwikiBoldItalic term=bold cterm=bold gui=bold,italic +hi def link VimwikiItalicBold VimwikiBoldItalic + +hi def link VimwikiCode PreProc +hi def link VimwikiWord Underlined +hi def link VimwikiNoExistsWord Error + +hi def link VimwikiPre SpecialComment +hi def link VimwikiLink Underlined +hi def link VimwikiList Function +hi def link VimwikiCheckBox VimwikiList +hi def link VimwikiCheckBoxDone Comment +hi def link VimwikiEmoticons Character +hi def link VimwikiDelText Constant +hi def link VimwikiSuperScript Number +hi def link VimwikiSubScript Number +hi def link VimwikiTodo Todo +hi def link VimwikiComment Comment + +hi def link VimwikiCellSeparator SpecialKey +"}}} + +let b:current_syntax="vimwiki" + +" EMBEDDED syntax setup "{{{ +let nested = VimwikiGet('nested_syntaxes') +if !empty(nested) + for [hl_syntax, vim_syntax] in items(nested) + call vimwiki#nested_syntax(vim_syntax, + \ '^{{{\%(.*[[:blank:][:punct:]]\)\?'. + \ hl_syntax.'\%([[:blank:][:punct:]].*\)\?', + \ '^}}}', 'VimwikiPre') + endfor +endif +"}}} diff --git a/syntax/vimwiki_default.vim b/syntax/vimwiki_default.vim new file mode 100644 index 0000000..d6c8d60 --- /dev/null +++ b/syntax/vimwiki_default.vim @@ -0,0 +1,76 @@ +" Vimwiki syntax file +" Default syntax +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ +" vim:tw=78: + +" text: *strong* +" let g:vimwiki_rxBold = '\*[^*]\+\*' +let g:vimwiki_rxBold = '\%(^\|\s\|[[:punct:]]\)\@<='. + \'\*'. + \'\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`]\)'. + \'\*'. + \'\%([[:punct:]]\|\s\|$\)\@=' + +" text: _emphasis_ +" let g:vimwiki_rxItalic = '_[^_]\+_' +let g:vimwiki_rxItalic = '\%(^\|\s\|[[:punct:]]\)\@<='. + \'_'. + \'\%([^_`[:space:]][^_`]*[^_`[:space:]]\|[^_`]\)'. + \'_'. + \'\%([[:punct:]]\|\s\|$\)\@=' + +" text: *_bold italic_* or _*italic bold*_ +let g:vimwiki_rxBoldItalic = '\%(^\|\s\|[[:punct:]]\)\@<='. + \'\*_'. + \'\%([^*_`[:space:]][^*_`]*[^*_`[:space:]]\|[^*_`]\)'. + \'_\*'. + \'\%([[:punct:]]\|\s\|$\)\@=' + +let g:vimwiki_rxItalicBold = '\%(^\|\s\|[[:punct:]]\)\@<='. + \'_\*'. + \'\%([^*_`[:space:]][^*_`]*[^*_`[:space:]]\|[^*_`]\)'. + \'\*_'. + \'\%([[:punct:]]\|\s\|$\)\@=' + +" text: `code` +let g:vimwiki_rxCode = '`[^`]\+`' + +" text: ~~deleted text~~ +let g:vimwiki_rxDelText = '\~\~[^~`]\+\~\~' + +" text: ^superscript^ +let g:vimwiki_rxSuperScript = '\^[^^`]\+\^' + +" text: ,,subscript,, +let g:vimwiki_rxSubScript = ',,[^,`]\+,,' + +" Header levels, 1-6 +let g:vimwiki_rxH1 = '^\s*=\{1}[^=]\+.*[^=]\+=\{1}\s*$' +let g:vimwiki_rxH2 = '^\s*=\{2}[^=]\+.*[^=]\+=\{2}\s*$' +let g:vimwiki_rxH3 = '^\s*=\{3}[^=]\+.*[^=]\+=\{3}\s*$' +let g:vimwiki_rxH4 = '^\s*=\{4}[^=]\+.*[^=]\+=\{4}\s*$' +let g:vimwiki_rxH5 = '^\s*=\{5}[^=]\+.*[^=]\+=\{5}\s*$' +let g:vimwiki_rxH6 = '^\s*=\{6}[^=]\+.*[^=]\+=\{6}\s*$' +let g:vimwiki_rxHeader = '\%('.g:vimwiki_rxH1.'\)\|'. + \ '\%('.g:vimwiki_rxH2.'\)\|'. + \ '\%('.g:vimwiki_rxH3.'\)\|'. + \ '\%('.g:vimwiki_rxH4.'\)\|'. + \ '\%('.g:vimwiki_rxH5.'\)\|'. + \ '\%('.g:vimwiki_rxH6.'\)' + +"
, horizontal rule +let g:vimwiki_rxHR = '^----.*$' + +" Tables. Each line starts and ends with '||'; each cell is separated by '||' +let g:vimwiki_rxTable = '||' + +" List items start with optional whitespace(s) then '* ' or '# ' +let g:vimwiki_rxListBullet = '^\s*\%(\*\|-\)\s' +let g:vimwiki_rxListNumber = '^\s*#\s' + +let g:vimwiki_rxListDefine = '::\(\s\|$\)' + +" Preformatted text +let g:vimwiki_rxPreStart = '{{{' +let g:vimwiki_rxPreEnd = '}}}' diff --git a/syntax/vimwiki_media.vim b/syntax/vimwiki_media.vim new file mode 100644 index 0000000..6f4b7dd --- /dev/null +++ b/syntax/vimwiki_media.vim @@ -0,0 +1,58 @@ +" Vimwiki syntax file +" MediaWiki syntax +" Author: Maxim Kim +" Home: http://code.google.com/p/vimwiki/ +" vim:tw=78: + +" text: '''strong''' +let g:vimwiki_rxBold = "'''[^']\\+'''" + +" text: ''emphasis'' +let g:vimwiki_rxItalic = "''[^']\\+''" + +" text: '''''strong italic''''' +let g:vimwiki_rxBoldItalic = "'''''[^']\\+'''''" +let g:vimwiki_rxItalicBold = g:vimwiki_rxBoldItalic + +" text: `code` +let g:vimwiki_rxCode = '`[^`]\+`' + +" text: ~~deleted text~~ +let g:vimwiki_rxDelText = '\~\~[^~]\+\~\~' + +" text: ^superscript^ +let g:vimwiki_rxSuperScript = '\^[^^]\+\^' + +" text: ,,subscript,, +let g:vimwiki_rxSubScript = ',,[^,]\+,,' + +" Header levels, 1-6 +let g:vimwiki_rxH1 = '^\s*=\{1}[^=]\+.*[^=]\+=\{1}\s*$' +let g:vimwiki_rxH2 = '^\s*=\{2}[^=]\+.*[^=]\+=\{2}\s*$' +let g:vimwiki_rxH3 = '^\s*=\{3}[^=]\+.*[^=]\+=\{3}\s*$' +let g:vimwiki_rxH4 = '^\s*=\{4}[^=]\+.*[^=]\+=\{4}\s*$' +let g:vimwiki_rxH5 = '^\s*=\{5}[^=]\+.*[^=]\+=\{5}\s*$' +let g:vimwiki_rxH6 = '^\s*=\{6}[^=]\+.*[^=]\+=\{6}\s*$' +let g:vimwiki_rxHeader = '\%('.g:vimwiki_rxH1.'\)\|'. + \ '\%('.g:vimwiki_rxH2.'\)\|'. + \ '\%('.g:vimwiki_rxH3.'\)\|'. + \ '\%('.g:vimwiki_rxH4.'\)\|'. + \ '\%('.g:vimwiki_rxH5.'\)\|'. + \ '\%('.g:vimwiki_rxH6.'\)' + +"
, horizontal rule +let g:vimwiki_rxHR = '^----.*$' + +" Tables. Each line starts and ends with '||'; each cell is separated by '||' +let g:vimwiki_rxTable = '||' + +" Bulleted list items start with whitespace(s), then '*' +" highlight only bullets and digits. +let g:vimwiki_rxListBullet = '^\s*\*\+\([^*]*$\)\@=' +let g:vimwiki_rxListNumber = '^\s*#\+' + +let g:vimwiki_rxListDefine = '^\%(;\|:\)\s' + +" Preformatted text +let g:vimwiki_rxPreStart = '
'
+let g:vimwiki_rxPreEnd = '<\/pre>'