From fb0350983f9c0e53d76c3d428fb8ea0c03f23842 Mon Sep 17 00:00:00 2001 From: Ian Date: Fri, 1 Jun 2012 15:49:20 -0400 Subject: [PATCH] Added some plugins and made some shortcuts in vimrc --- vim/dot_vim/autoload/tcomment.vim | 1073 +++++ vim/dot_vim/doc/NERD_tree.txt | 1291 ++++++ vim/dot_vim/doc/tags | 115 +- vim/dot_vim/doc/tcomment.txt | 359 ++ vim/dot_vim/nerdtree_plugin/exec_menuitem.vim | 41 + vim/dot_vim/nerdtree_plugin/fs_menu.vim | 224 + vim/dot_vim/plugin/NERD_tree.vim | 4017 +++++++++++++++++ vim/dot_vim/plugin/buffet.vim | 524 +++ vim/dot_vim/plugin/tcomment.vim | 142 + vim/dot_vim/syntax/nerdtree.vim | 88 + vim/dot_vimrc | 17 +- 11 files changed, 7809 insertions(+), 82 deletions(-) create mode 100644 vim/dot_vim/autoload/tcomment.vim create mode 100644 vim/dot_vim/doc/NERD_tree.txt create mode 100644 vim/dot_vim/doc/tcomment.txt create mode 100644 vim/dot_vim/nerdtree_plugin/exec_menuitem.vim create mode 100644 vim/dot_vim/nerdtree_plugin/fs_menu.vim create mode 100644 vim/dot_vim/plugin/NERD_tree.vim create mode 100644 vim/dot_vim/plugin/buffet.vim create mode 100644 vim/dot_vim/plugin/tcomment.vim create mode 100644 vim/dot_vim/syntax/nerdtree.vim diff --git a/vim/dot_vim/autoload/tcomment.vim b/vim/dot_vim/autoload/tcomment.vim new file mode 100644 index 0000000..092e0e1 --- /dev/null +++ b/vim/dot_vim/autoload/tcomment.vim @@ -0,0 +1,1073 @@ +" tcomment.vim +" @Author: Tom Link (mailto:micathom AT gmail com?subject=[vim]) +" @Website: http://www.vim.org/account/profile.php?user_id=4037 +" @License: GPL (see http://www.gnu.org/licenses/gpl.txt) +" @Created: 2007-09-17. +" @Last Change: 2011-04-12. +" @Revision: 0.0.407 + +" call tlog#Log('Load: '. expand('')) " vimtlib-sfile + +if !exists("g:tcommentBlankLines") + " If true, comment blank lines too + let g:tcommentBlankLines = 1 "{{{2 +endif + +if !exists("g:tcommentOpModeExtra") + " Modifies how the operator works. + " > ... Move the cursor to the end of the comment + let g:tcommentOpModeExtra = '' "{{{2 +endif + +if !exists('g:tcommentOptions') + " Other key-value options used by |tcomment#Comment()|. + " + " Example: If you want to put the opening comment marker always in + " the first column regardless of the block's indentation, put this + " into your |vimrc| file: > + " let g:tcommentOptions = {'col': 1} + let g:tcommentOptions = {} "{{{2 +endif + +if !exists('g:tcomment#ignore_char_type') + " |text-objects| for use with |tcomment#Operator| can have different + " types: line, block, char etc. Text objects like aB, it, at etc. + " have type char but this may not work reliably. By default, + " tcomment handles those text objects most often as if they were of + " type line. Set this variable to 0 in order to change this + " behaviour. Be prepared that the result may not always match your + " intentions. + let g:tcomment#ignore_char_type = 1 "{{{2 +endif + +if !exists("g:tcommentGuessFileType") + " Guess the file type based on syntax names always or for some fileformat only + " If non-zero, try to guess filetypes. + " tcomment also checks g:tcommentGuessFileType_{&filetype} for + " filetype specific values. + " + " Values: + " 0 ... don't guess + " 1 ... guess + " FILETYPE ... assume this filetype + let g:tcommentGuessFileType = 0 "{{{2 +endif +if !exists("g:tcommentGuessFileType_dsl") + " For dsl documents, assumet filetype = xml. + let g:tcommentGuessFileType_dsl = 'xml' "{{{2 +endif +if !exists("g:tcommentGuessFileType_php") + " In php documents, the php part is usually marked as phpRegion. We + " thus assume that the buffers default comment style isn't php but + " html. + let g:tcommentGuessFileType_php = 'html' "{{{2 +endif +if !exists("g:tcommentGuessFileType_html") + let g:tcommentGuessFileType_html = 1 "{{{2 +endif +if !exists("g:tcommentGuessFileType_tskeleton") + let g:tcommentGuessFileType_tskeleton = 1 "{{{2 +endif +if !exists("g:tcommentGuessFileType_vim") + let g:tcommentGuessFileType_vim = 1 "{{{2 +endif +if !exists("g:tcommentGuessFileType_django") + let g:tcommentGuessFileType_django = 1 "{{{2 +endif + +if !exists("g:tcommentIgnoreTypes_php") + " In php files, some syntax regions are wongly highlighted as sql + " markup. We thus ignore sql syntax when guessing the filetype in + " php files. + let g:tcommentIgnoreTypes_php = 'sql' "{{{2 +endif + +if !exists('g:tcomment#syntax_substitute') + " :read: let g:tcomment#syntax_substitute = {...} "{{{2 + " Perform replacements on the syntax name. + let g:tcomment#syntax_substitute = { + \ '\C^javaScript': {'sub': 'javascript'} + \ } +endif + +if !exists('g:tcommentSyntaxMap') + " tcomment guesses filetypes based on the name of the current syntax + " region. This works well if the syntax names match + " /filetypeSomeName/. Other syntax names have to be explicitly + " mapped onto the corresponding filetype. + " :read: let g:tcommentSyntaxMap = {...} "{{{2 + let g:tcommentSyntaxMap = { + \ 'vimMzSchemeRegion': 'scheme', + \ 'vimPerlRegion': 'perl', + \ 'vimPythonRegion': 'python', + \ 'vimRubyRegion': 'ruby', + \ 'vimTclRegion': 'tcl', + \ } +endif + +if !exists("g:tcommentBlockC") + " Generic c-like block comments. + " :read: let g:tcommentBlockC = {...} "{{{2 + let g:tcommentBlockC = { + \ 'commentstring': '/*%s */', + \ 'middle': ' * ', + \ 'rxbeg': '\*\+', + \ 'rxend': '\*\+', + \ 'rxmid': '\*\+', + \ } +endif +if !exists("g:tcommentBlockC2") + " Generic c-like block comments (alternative markup). + " :read: let g:tcommentBlockC2 = {...} "{{{2 + let g:tcommentBlockC2 = { + \ 'commentstring': '/**%s */', + \ 'middle': ' * ', + \ 'rxbeg': '\*\+', + \ 'rxend': '\*\+', + \ 'rxmid': '\*\+', + \ } +endif +if !exists("g:tcommentInlineC") + " Generic c-like comments. + let g:tcommentInlineC = "/* %s */" "{{{2 +endif + +if !exists("g:tcommentBlockXML") + " Generic xml-like block comments. + let g:tcommentBlockXML = "\n " "{{{2 +endif +if !exists("g:tcommentInlineXML") + " Generic xml-like comments. + let g:tcommentInlineXML = "" "{{{2 +endif + +let s:typesDirty = 1 + +let s:definitions = {} + +" If you don't explicitly define a comment style, |:TComment| will use +" 'commentstring' instead. We override the default values here in order +" to have a blank after the comment marker. Block comments work only if +" we explicitly define the markup. +" +" The comment definition can be either a string or a dictionary. +" +" If it is a string: +" The format for block comments is similar to 'commentstrings' with the +" exception that the format strings for blocks can contain a second line +" that defines how "middle lines" (see :h format-comments) should be +" displayed. +" +" If it is a dictionary: +" See the help on the args argument of |tcomment#Comment|. +function! tcomment#DefineType(name, commentdef) + if !has_key(s:definitions, a:name) + if type(a:commentdef) == 4 + let cdef = copy(a:commentdef) + else + let cdef = a:0 >= 1 ? a:1 : {} + let cdef.commentstring = a:commentdef + endif + let s:definitions[a:name] = cdef + endif + let s:typesDirty = 1 +endf + +" :nodoc: +" Return 1 if a comment type is defined. +function! tcomment#TypeExists(name) + return has_key(s:definitions, a:name) +endf + +call tcomment#DefineType('aap', '# %s' ) +call tcomment#DefineType('ada', '-- %s' ) +call tcomment#DefineType('apache', '# %s' ) +call tcomment#DefineType('autoit', '; %s' ) +call tcomment#DefineType('asm', '; %s' ) +call tcomment#DefineType('awk', '# %s' ) +call tcomment#DefineType('catalog', '-- %s --' ) +call tcomment#DefineType('catalog_block', "--%s--\n " ) +call tcomment#DefineType('cpp', '// %s' ) +call tcomment#DefineType('cpp_inline', g:tcommentInlineC ) +call tcomment#DefineType('cpp_block', g:tcommentBlockC ) +call tcomment#DefineType('css', '/* %s */' ) +call tcomment#DefineType('css_inline', g:tcommentInlineC ) +call tcomment#DefineType('css_block', g:tcommentBlockC ) +call tcomment#DefineType('c', '/* %s */' ) +call tcomment#DefineType('c_inline', g:tcommentInlineC ) +call tcomment#DefineType('c_block', g:tcommentBlockC ) +call tcomment#DefineType('cfg', '# %s' ) +call tcomment#DefineType('conf', '# %s' ) +call tcomment#DefineType('crontab', '# %s' ) +call tcomment#DefineType('cs', '// %s' ) +call tcomment#DefineType('cs_inline', g:tcommentInlineC ) +call tcomment#DefineType('cs_block', g:tcommentBlockC ) +call tcomment#DefineType('debsources', '# %s' ) +call tcomment#DefineType('debcontrol', '# %s' ) +call tcomment#DefineType('desktop', '# %s' ) +call tcomment#DefineType('django', '{# %s #}' ) +call tcomment#DefineType('django_block', "{%% comment %%}%s{%% endcomment %%}\n ") +call tcomment#DefineType('docbk', '' ) +call tcomment#DefineType('docbk_inline', g:tcommentInlineXML) +call tcomment#DefineType('docbk_block', g:tcommentBlockXML ) +call tcomment#DefineType('dosbatch', 'rem %s' ) +call tcomment#DefineType('dosini', '; %s' ) +call tcomment#DefineType('dsl', '; %s' ) +call tcomment#DefineType('dylan', '// %s' ) +call tcomment#DefineType('eiffel', '-- %s' ) +call tcomment#DefineType('erlang', '%%%% %s' ) +call tcomment#DefineType('eruby', '<%%# %s' ) +call tcomment#DefineType('fstab', '# %s' ) +call tcomment#DefineType('gitcommit', '# %s' ) +call tcomment#DefineType('gtkrc', '# %s' ) +call tcomment#DefineType('go', '// %s' ) +call tcomment#DefineType('go_inline', g:tcommentInlineC ) +call tcomment#DefineType('go_block', g:tcommentBlockC ) +call tcomment#DefineType('groovy', '// %s' ) +call tcomment#DefineType('groovy_inline', g:tcommentInlineC ) +call tcomment#DefineType('groovy_block', g:tcommentBlockC ) +call tcomment#DefineType('groovy_doc_block', g:tcommentBlockC2 ) +call tcomment#DefineType('haskell', '-- %s' ) +call tcomment#DefineType('haskell_block', "{-%s-}\n " ) +call tcomment#DefineType('haskell_inline', '{- %s -}' ) +call tcomment#DefineType('html', '' ) +call tcomment#DefineType('html_inline', g:tcommentInlineXML) +call tcomment#DefineType('html_block', g:tcommentBlockXML ) +call tcomment#DefineType('io', '// %s' ) +call tcomment#DefineType('javaScript', '// %s' ) +call tcomment#DefineType('javaScript_inline', g:tcommentInlineC ) +call tcomment#DefineType('javaScript_block', g:tcommentBlockC ) +call tcomment#DefineType('javascript', '// %s' ) +call tcomment#DefineType('javascript_inline', g:tcommentInlineC ) +call tcomment#DefineType('javascript_block', g:tcommentBlockC ) +call tcomment#DefineType('java', '/* %s */' ) +call tcomment#DefineType('java_inline', g:tcommentInlineC ) +call tcomment#DefineType('java_block', g:tcommentBlockC ) +call tcomment#DefineType('java_doc_block', g:tcommentBlockC2 ) +call tcomment#DefineType('jproperties', '# %s' ) +call tcomment#DefineType('lisp', '; %s' ) +call tcomment#DefineType('lynx', '# %s' ) +call tcomment#DefineType('matlab', '%% %s' ) +call tcomment#DefineType('m4', 'dnl %s' ) +call tcomment#DefineType('mail', '> %s' ) +call tcomment#DefineType('msidl', '// %s' ) +call tcomment#DefineType('msidl_block', g:tcommentBlockC ) +call tcomment#DefineType('nginx', '# %s' ) +call tcomment#DefineType('nroff', '.\\" %s' ) +call tcomment#DefineType('nsis', '# %s' ) +call tcomment#DefineType('objc', '/* %s */' ) +call tcomment#DefineType('objc_inline', g:tcommentInlineC ) +call tcomment#DefineType('objc_block', g:tcommentBlockC ) +call tcomment#DefineType('ocaml', '(* %s *)' ) +call tcomment#DefineType('ocaml_inline', '(* %s *)' ) +call tcomment#DefineType('ocaml_block', "(*%s*)\n " ) +call tcomment#DefineType('pascal', '(* %s *)' ) +call tcomment#DefineType('pascal_inline', '(* %s *)' ) +call tcomment#DefineType('pascal_block', "(*%s*)\n " ) +call tcomment#DefineType('perl', '# %s' ) +call tcomment#DefineType('perl_block', "=cut%s=cut" ) +call tcomment#DefineType('php', {'commentstring_rx': '\%%(//\|#\) %s', 'commentstring': '// %s'}) +call tcomment#DefineType('php_inline', g:tcommentInlineC ) +call tcomment#DefineType('php_block', g:tcommentBlockC ) +call tcomment#DefineType('php_2_block', g:tcommentBlockC2 ) +call tcomment#DefineType('po', '# %s' ) +call tcomment#DefineType('prolog', '%% %s' ) +call tcomment#DefineType('python', '# %s' ) +call tcomment#DefineType('rc', '// %s' ) +call tcomment#DefineType('readline', '# %s' ) +call tcomment#DefineType('ruby', '# %s' ) +call tcomment#DefineType('ruby_3', '### %s' ) +call tcomment#DefineType('ruby_block', "=begin rdoc%s=end") +call tcomment#DefineType('ruby_nodoc_block', "=begin%s=end" ) +call tcomment#DefineType('r', '# %s' ) +call tcomment#DefineType('samba', '# %s' ) +call tcomment#DefineType('sbs', "' %s" ) +call tcomment#DefineType('scheme', '; %s' ) +call tcomment#DefineType('scss', '// %s' ) +call tcomment#DefineType('scss_inline', g:tcommentInlineC ) +call tcomment#DefineType('scss_block', g:tcommentBlockC ) +call tcomment#DefineType('sed', '# %s' ) +call tcomment#DefineType('sgml', '' ) +call tcomment#DefineType('sgml_inline', g:tcommentInlineXML) +call tcomment#DefineType('sgml_block', g:tcommentBlockXML ) +call tcomment#DefineType('sh', '# %s' ) +call tcomment#DefineType('sql', '-- %s' ) +call tcomment#DefineType('spec', '# %s' ) +call tcomment#DefineType('sps', '* %s.' ) +call tcomment#DefineType('sps_block', "* %s." ) +call tcomment#DefineType('spss', '* %s.' ) +call tcomment#DefineType('spss_block', "* %s." ) +call tcomment#DefineType('tcl', '# %s' ) +call tcomment#DefineType('tex', '%% %s' ) +call tcomment#DefineType('tpl', '' ) +call tcomment#DefineType('typoscript', '# %s' ) +call tcomment#DefineType('viki', '%% %s' ) +call tcomment#DefineType('viki_3', '%%%%%% %s' ) +call tcomment#DefineType('viki_inline', '{cmt: %s}' ) +call tcomment#DefineType('vim', '" %s' ) +call tcomment#DefineType('vim_3', '""" %s' ) +call tcomment#DefineType('websec', '# %s' ) +call tcomment#DefineType('x86conf', '# %s' ) +call tcomment#DefineType('xml', '' ) +call tcomment#DefineType('xml_inline', g:tcommentInlineXML) +call tcomment#DefineType('xml_block', g:tcommentBlockXML ) +call tcomment#DefineType('xs', '// %s' ) +call tcomment#DefineType('xs_block', g:tcommentBlockC ) +call tcomment#DefineType('xslt', '' ) +call tcomment#DefineType('xslt_inline', g:tcommentInlineXML) +call tcomment#DefineType('xslt_block', g:tcommentBlockXML ) +call tcomment#DefineType('yaml', '# %s' ) + + +function! s:DefaultValue(option) + exec 'let '. a:option .' = &'. a:option + exec 'set '. a:option .'&' + exec 'let default = &'. a:option + exec 'let &'. a:option .' = '. a:option + return default +endf + +let s:defaultComments = s:DefaultValue('comments') +let s:defaultCommentString = s:DefaultValue('commentstring') +let s:nullCommentString = '%s' + +" tcomment#Comment(line1, line2, ?commentMode, ?commentAnyway, ?args...) +" args... are either: +" 1. a list of key=value pairs where known keys are (see also +" |g:tcommentOptions|): +" as=STRING ... Use a specific comment definition +" col=N ... Start the comment at column N (in block +" mode; must be smaller than |indent()|) +" mode=STRING ... See the notes below on the "commentMode" argument +" begin=STRING ... Comment prefix +" end=STRING ... Comment postfix +" middle=STRING ... Middle line comments in block mode +" rxbeg=N ... Regexp to find the substring of "begin" +" that should be multipied by "count" +" rxend=N ... The above for "end" +" rxmid=N ... The above for "middle" +" commentstring_rx ... A regexp format string that matches +" commented lines (no new groups may be +" introduced, the |regexp| is |\V|; % have +" to be doubled); "commentstring", "begin" +" and optionally "end" must be defined or +" deducible. +" 2. 1-2 values for: ?commentPrefix, ?commentPostfix +" 3. a dictionary (internal use only) +" +" commentMode: +" G ... guess the value of commentMode +" B ... block (use extra lines for the comment markers) +" i ... maybe inline, guess +" I ... inline +" R ... right (comment the line right of the cursor) +" v ... visual +" o ... operator +" By default, each line in range will be commented by adding the comment +" prefix and postfix. +function! tcomment#Comment(beg, end, ...) + let commentMode = a:0 >= 1 ? a:1 : 'G' + let commentAnyway = a:0 >= 2 ? (a:2 == '!') : 0 + " TLogVAR a:beg, a:end, a:1, commentMode, commentAnyway + " save the cursor position + let pos = getpos('.') + let s:pos_end = getpos("'>") + if commentMode =~# 'i' + let commentMode = substitute(commentMode, '\Ci', line("'<") == line("'>") ? 'I' : 'G', 'g') + endif + let [lbeg, cbeg, lend, cend] = s:GetStartEnd(a:beg, a:end, commentMode) + " TLogVAR commentMode, lbeg, cbeg, lend, cend + " get the correct commentstring + let cdef = copy(g:tcommentOptions) + if a:0 >= 3 && type(a:3) == 4 + call extend(cdef, a:3) + else + call extend(cdef, s:GetCommentDefinition(lbeg, lend, commentMode)) + let ax = 3 + if a:0 >= 3 && a:3 != '' && stridx(a:3, '=') == -1 + let ax = 4 + let cdef.begin = a:3 + if a:0 >= 4 && a:4 != '' && stridx(a:4, '=') == -1 + let ax = 5 + let cdef.end = a:4 + endif + endif + if a:0 >= ax + call extend(cdef, s:ParseArgs(lbeg, lend, commentMode, a:000[ax - 1 : -1])) + endif + if !empty(get(cdef, 'begin', '')) || !empty(get(cdef, 'end', '')) + let cdef.commentstring = s:EncodeCommentPart(get(cdef, 'begin', '')) + \ . '%s' + \ . s:EncodeCommentPart(get(cdef, 'end', '')) + endif + let commentMode = cdef.mode + endif + if !empty(filter(['count', 'cbeg', 'cend', 'cmid'], 'has_key(cdef, v:val)')) + call s:RepeatCommentstring(cdef) + endif + " echom "DBG" string(cdef) string(a:000) + let cms0 = s:BlockGetCommentRx(cdef) + " make whitespace optional; this conflicts with comments that require some + " whitespace + let cmtCheck = substitute(cms0, '\([ ]\)', '\1\\?', 'g') + " turn commentstring into a search pattern + let cmtCheck = printf(cmtCheck, '\(\_.\{-}\)') + " set commentMode and indentStr + let [indentStr, uncomment] = s:CommentDef(lbeg, lend, cmtCheck, commentMode, cbeg, cend) + " TLogVAR indentStr, uncomment + let col = get(cdef, 'col', -1) + if col >= 0 + let col -= 1 + let indent = len(indentStr) + if col > indent + let cms0 = repeat(' ', col - indent) . cms0 + else + let indentStr = repeat(' ', col) + endif + endif + if commentAnyway + let uncomment = 0 + endif + " go + if commentMode =~# 'B' + " We want a comment block + call s:CommentBlock(lbeg, lend, uncomment, cmtCheck, cdef, indentStr) + else + " call s:CommentLines(lbeg, lend, cbeg, cend, uncomment, cmtCheck, cms0, indentStr) + " We want commented lines + " final search pattern for uncommenting + let cmtCheck = escape('\V\^\(\s\{-}\)'. cmtCheck .'\$', '"/\') + " final pattern for commenting + let cmtReplace = s:GetCommentReplace(cdef, cms0) + " echom "DBG tcomment#Comment" lbeg .','. lend .'s/\V'. + " \ s:StartPosRx(commentMode, lbeg, cbeg) . indentStr .'\zs\(\_.\{-}\)'. s:EndPosRx(commentMode, lend, cend) .'/'. + " \ '\=s:ProcessedLine('. uncomment .', submatch(0), "'. cmtCheck .'", "'. cmtReplace .'")/ge' + exec lbeg .','. lend .'s/\V'. + \ s:StartPosRx(commentMode, lbeg, cbeg) . indentStr .'\zs\(\_.\{-}\)'. s:EndPosRx(commentMode, lend, cend) .'/'. + \ '\=s:ProcessedLine('. uncomment .', submatch(0), "'. cmtCheck .'", "'. cmtReplace .'")/ge' + endif + " reposition cursor + " TLogVAR commentMode + if commentMode =~ '>' + call setpos('.', s:pos_end) + else + " TLogVAR pos + call setpos('.', pos) + endif +endf + + +function! s:GetStartEnd(beg, end, commentMode) "{{{3 + if type(a:beg) == 3 + let [lbeg, cbeg] = a:beg + let [lend, cend] = a:end + else + let lbeg = a:beg + let lend = a:end + let commentMode = a:commentMode + if commentMode =~# 'R' || commentMode =~# 'I' + let cbeg = col("'<") + if cbeg == 0 + let cbeg = col('.') + endif + if commentMode =~# 'R' + let commentMode = substitute(commentMode, '\CR', 'G', 'g') + let cend = 0 + else + let cend = col("'>") + if commentMode =~# 'o' + let cend += 1 + endif + endif + else + let cbeg = 0 + let cend = 0 + endif + endif + return [lbeg, cbeg, lend, cend] +endf + + +function! s:RepeatCommentstring(cdef) "{{{3 + " TLogVAR a:cdef + let cms = s:BlockGetCommentString(a:cdef) + let mid = s:BlockGetMiddleString(a:cdef) + let cms_fbeg = match(cms, '\s*%\@= 1 ? a:1 : '' + let bang = a:0 >= 2 ? a:2 : '' + if !exists('w:tcommentPos') + let w:tcommentPos = getpos(".") + endif + let sel_save = &selection + set selection=inclusive + let reg_save = @@ + " let pos = getpos('.') + " TLogVAR a:type + try + if a:type == 'line' + silent exe "normal! '[V']" + let commentMode1 = 'G' + elseif a:type == 'block' + silent exe "normal! `[\`]" + let commentMode1 = 'I' + elseif a:type == 'char' && !g:tcomment#ignore_char_type + silent exe "normal! `[v`]" + let commentMode1 = 'I' + else + silent exe "normal! `[v`]" + let commentMode1 = 'i' + endif + if empty(commentMode) + let commentMode = commentMode1 + endif + let lbeg = line("'[") + let lend = line("']") + let cbeg = col("'[") + let cend = col("']") + " echom "DBG tcomment#Operator" lbeg col("'[") col("'<") lend col("']") col("'>") + norm!  + let commentMode .= g:tcommentOpModeExtra + if a:type =~ 'line\|block' || g:tcomment#ignore_char_type + call tcomment#Comment(lbeg, lend, commentMode.'o', bang) + else + call tcomment#Comment([lbeg, cbeg], [lend, cend], commentMode.'o', bang) + endif + finally + let &selection = sel_save + let @@ = reg_save + if g:tcommentOpModeExtra !~ '>' + " TLogVAR pos + " call setpos('.', pos) + if exists('w:tcommentPos') + call setpos('.', w:tcommentPos) + unlet! w:tcommentPos + else + echohl WarningMsg + echom "TComment: w:tcommentPos wasn't set. Please report this to the plugin author" + echohl NONE + endif + endif + endtry +endf + + +function! tcomment#OperatorLine(type) "{{{3 + call tcomment#Operator(a:type, 'G') +endf + + +function! tcomment#OperatorAnyway(type) "{{{3 + call tcomment#Operator(a:type, '', '!') +endf + + +function! tcomment#OperatorLineAnyway(type) "{{{3 + call tcomment#Operator(a:type, 'G', '!') +endf + + +" :display: tcomment#CommentAs(beg, end, commentAnyway, filetype, ?args...) +" Where args is either: +" 1. A count NUMBER +" 2. An args list (see the notes on the "args" argument of +" |tcomment#Comment()|) +" comment text as if it were of a specific filetype +function! tcomment#CommentAs(beg, end, commentAnyway, filetype, ...) + if a:filetype =~ '_block$' + let commentMode = 'B' + let ft = substitute(a:filetype, '_block$', '', '') + elseif a:filetype =~ '_inline$' + let commentMode = 'I' + let ft = substitute(a:filetype, '_inline$', '', '') + else + let commentMode = 'G' + let ft = a:filetype + endif + if a:0 >= 1 + if type(a:1) == 0 + let cdef = {'count': a:0 >= 1 ? a:1 : 1} + else + let cdef = s:ParseArgs(a:beg, a:end, commentMode, a:000) + endif + else + let cdef = {} + endif + " echom "DBG" string(cdef) + call extend(cdef, s:GetCommentDefinitionForType(a:beg, a:end, commentMode, ft)) + keepjumps call tcomment#Comment(a:beg, a:end, commentMode, a:commentAnyway, cdef) +endf + + +" collect all known comment types +" :nodoc: +function! tcomment#CollectFileTypes() + if s:typesDirty + let s:types = keys(s:definitions) + let s:typesRx = '\V\^\('. join(s:types, '\|') .'\)\(\u\.\*\)\?\$' + let s:typesDirty = 0 + endif +endf + +call tcomment#CollectFileTypes() + + +" return a list of filetypes for which a tcomment_{&ft} is defined +" :nodoc: +function! tcomment#Complete(ArgLead, CmdLine, CursorPos) "{{{3 + call tcomment#CollectFileTypes() + let completions = copy(s:types) + let filetype = s:Filetype() + if index(completions, filetype) != -1 + " TLogVAR filetype + call insert(completions, filetype) + endif + if !empty(a:ArgLead) + call filter(completions, 'v:val =~ ''\V\^''.a:ArgLead') + endif + let completions += tcomment#CompleteArgs(a:ArgLead, a:CmdLine, a:CursorPos) + return completions +endf + + +" :nodoc: +function! tcomment#CompleteArgs(ArgLead, CmdLine, CursorPos) "{{{3 + let completions = ['as=', 'col=', 'count=', 'mode=', 'begin=', 'end='] + if !empty(a:ArgLead) + if a:ArgLead =~ '^as=' + call tcomment#CollectFileTypes() + let completions += map(copy(s:types), '"as=". v:val') + endif + call filter(completions, 'v:val =~ ''\V\^''.a:ArgLead') + endif + return completions +endf + + +function! s:EncodeCommentPart(string) + return substitute(a:string, '%', '%%', 'g') +endf + + +function! s:GetCommentDefinitionForType(beg, end, commentMode, filetype) "{{{3 + let cdef = s:GetCommentDefinition(a:beg, a:end, a:commentMode, a:filetype) + let cms = cdef.commentstring + let commentMode = cdef.mode + let pre = substitute(cms, '%s.*$', '', '') + let pre = substitute(pre, '%%', '%', 'g') + let post = substitute(cms, '^.\{-}%s', '', '') + let post = substitute(post, '%%', '%', 'g') + let cdef.begin = pre + let cdef.end = post + return cdef +endf + + +" s:GetCommentDefinition(beg, end, commentMode, ?filetype="") +function! s:GetCommentDefinition(beg, end, commentMode, ...) + let ft = a:0 >= 1 ? a:1 : '' + if ft != '' + let cdef = s:GetCustomCommentString(ft, a:commentMode) + else + let cdef = {'mode': a:commentMode} + endif + let cms = get(cdef, 'commentstring', '') + if empty(cms) + let filetype = s:Filetype() + if exists('b:commentstring') + let cms = b:commentstring + return s:GetCustomCommentString(filetype, a:commentMode, cms) + elseif exists('b:commentStart') && b:commentStart != '' + let cms = s:EncodeCommentPart(b:commentStart) .' %s' + if exists('b:commentEnd') && b:commentEnd != '' + let cms = cms .' '. s:EncodeCommentPart(b:commentEnd) + endif + return s:GetCustomCommentString(filetype, a:commentMode, cms) + elseif g:tcommentGuessFileType || (exists('g:tcommentGuessFileType_'. filetype) + \ && g:tcommentGuessFileType_{filetype} =~ '[^0]') + if g:tcommentGuessFileType_{filetype} == 1 + let altFiletype = '' + else + let altFiletype = g:tcommentGuessFileType_{filetype} + endif + return s:GuessFileType(a:beg, a:end, a:commentMode, filetype, altFiletype) + else + return s:GetCustomCommentString(filetype, a:commentMode, s:GuessCurrentCommentString(a:commentMode)) + endif + let cdef.commentstring = cms + endif + return cdef +endf + +function! s:StartPosRx(mode, line, col) + if a:mode =~# 'I' + return s:StartLineRx(a:line) . s:StartColRx(a:col) + else + return s:StartColRx(a:col) + endif +endf + +function! s:EndPosRx(mode, line, col) + if a:mode =~# 'I' + return s:EndLineRx(a:line) . s:EndColRx(a:col) + else + return s:EndColRx(a:col) + endif +endf + +function! s:StartLineRx(pos) + return '\%'. a:pos .'l' +endf + +function! s:EndLineRx(pos) + return '\%'. a:pos .'l' +endf + +function! s:StartColRx(pos) + if a:pos == 0 + return '\^' + else + return '\%'. a:pos .'c' + endif +endf + +function! s:EndColRx(pos) + if a:pos == 0 + return '\$' + else + return '\%'. a:pos .'c' + endif +endf + +function! s:GetIndentString(line, start) + let start = a:start > 0 ? a:start - 1 : 0 + return substitute(strpart(getline(a:line), start), '\V\^\s\*\zs\.\*\$', '', '') +endf + +function! s:CommentDef(beg, end, checkRx, commentMode, cstart, cend) + let mdrx = '\V'. s:StartColRx(a:cstart) .'\s\*'. a:checkRx .'\s\*'. s:EndColRx(0) + " let mdrx = '\V'. s:StartPosRx(a:commentMode, a:beg, a:cstart) .'\s\*'. a:checkRx .'\s\*'. s:EndPosRx(a:commentMode, a:end, 0) + let line = getline(a:beg) + if a:cstart != 0 && a:cend != 0 + let line = strpart(line, 0, a:cend - 1) + endif + let uncomment = (line =~ mdrx) + let indentStr = s:GetIndentString(a:beg, a:cstart) + let il = indent(a:beg) + let n = a:beg + 1 + while n <= a:end + if getline(n) =~ '\S' + let jl = indent(n) + if jl < il + let indentStr = s:GetIndentString(n, a:cstart) + let il = jl + endif + if a:commentMode =~# 'G' + if !(getline(n) =~ mdrx) + let uncomment = 0 + endif + endif + endif + let n = n + 1 + endwh + if a:commentMode =~# 'B' + let t = @t + try + silent exec 'norm! '. a:beg.'G1|v'.a:end.'G$"ty' + let uncomment = (@t =~ mdrx) + finally + let @t = t + endtry + endif + return [indentStr, uncomment] +endf + +function! s:ProcessedLine(uncomment, match, checkRx, replace) + " TLogVAR a:uncomment, a:match, a:checkRx, a:replace + if !(a:match =~ '\S' || g:tcommentBlankLines) + return a:match + endif + let ml = len(a:match) + if a:uncomment + let rv = substitute(a:match, a:checkRx, '\1\2', '') + else + let rv = printf(a:replace, a:match) + endif + " TLogVAR rv + " let md = len(rv) - ml + let s:pos_end = getpos('.') + let s:pos_end[2] += len(rv) + " TLogVAR pe, md, a:match + " TLogVAR rv + if v:version > 702 || (v:version == 702 && has('patch407')) + let rv = escape(rv, ' ') + else + let rv = escape(rv, '\ ') + endif + " TLogVAR rv + " let rv = substitute(rv, '\n', '\\\n', 'g') + " TLogVAR rv + return rv +endf + +" function! s:CommentLines(beg, end, cstart, cend, uncomment, cmtCheck, cms0, indentStr) "{{{3 +" " We want commented lines +" " final search pattern for uncommenting +" let cmtCheck = escape('\V\^\(\s\{-}\)'. a:cmtCheck .'\$', '"/\') +" " final pattern for commenting +" let cmtReplace = escape(a:cms0, '"/') +" silent exec a:beg .','. a:end .'s/\V'. +" \ s:StartColRx(a:cstart) . a:indentStr .'\zs\(\.\{-}\)'. s:EndColRx(a:cend) .'/'. +" \ '\=s:ProcessedLine('. a:uncomment .', submatch(0), "'. a:cmtCheck .'", "'. cmtReplace .'")/ge' +" endf + +function! s:CommentBlock(beg, end, uncomment, checkRx, cdef, indentStr) + let t = @t + try + silent exec 'norm! '. a:beg.'G1|v'.a:end.'G$"td' + let ms = s:BlockGetMiddleString(a:cdef) + let mx = escape(ms, '\') + if a:uncomment + let @t = substitute(@t, '\V\^\s\*'. a:checkRx .'\$', '\1', '') + if ms != '' + let @t = substitute(@t, '\V\n'. a:indentStr . mx, '\n'. a:indentStr, 'g') + endif + let @t = substitute(@t, '^\n', '', '') + let @t = substitute(@t, '\n\s*$', '', '') + else + let cs = s:BlockGetCommentString(a:cdef) + let cs = a:indentStr . substitute(cs, '%s', '%s'. a:indentStr, '') + if ms != '' + let ms = a:indentStr . ms + let mx = a:indentStr . mx + let @t = substitute(@t, '^'. a:indentStr, '', 'g') + let @t = ms . substitute(@t, '\n'. a:indentStr, '\n'. mx, 'g') + endif + let @t = printf(cs, "\n". @t ."\n") + endif + silent norm! "tP + finally + let @t = t + endtry +endf + + +function! s:Filetype(...) "{{{3 + let ft = a:0 >= 1 ? a:1 : &filetype + let ft = substitute(ft, '\..*$', '', '') + return ft +endf + + +" inspired by Meikel Brandmeyer's EnhancedCommentify.vim +" this requires that a syntax names are prefixed by the filetype name +" s:GuessFileType(beg, end, commentMode, filetype, ?fallbackFiletype) +function! s:GuessFileType(beg, end, commentMode, filetype, ...) + if a:0 >= 1 && a:1 != '' + let cdef = s:GetCustomCommentString(a:1, a:commentMode) + if empty(get(cdef, 'commentstring', '')) + let cdef.commentstring = s:GuessCurrentCommentString(a:commentMode) + endif + else + let cdef = {'commentstring': s:GuessCurrentCommentString(0), 'mode': s:CommentMode(a:commentMode, 'G')} + endif + let n = a:beg + " TLogVAR n, a:beg, a:end + while n <= a:end + let m = indent(n) + 1 + let le = len(getline(n)) + " TLogVAR m, le + while m < le + let syntaxName = s:GetSyntaxName(n, m) + " TLogVAR syntaxName, n, m + let ftypeMap = get(g:tcommentSyntaxMap, syntaxName) + if !empty(ftypeMap) + " TLogVAR ftypeMap + return s:GetCustomCommentString(ftypeMap, a:commentMode, cdef.commentstring) + elseif syntaxName =~ s:typesRx + let ft = substitute(syntaxName, s:typesRx, '\1', '') + " TLogVAR ft + if exists('g:tcommentIgnoreTypes_'. a:filetype) && g:tcommentIgnoreTypes_{a:filetype} =~ '\<'.ft.'\>' + let m += 1 + else + return s:GetCustomCommentString(ft, a:commentMode, cdef.commentstring) + endif + elseif syntaxName == '' || syntaxName == 'None' || syntaxName =~ '^\u\+$' || syntaxName =~ '^\u\U*$' + let m += 1 + else + break + endif + endwh + let n += 1 + endwh + return cdef +endf + + +function! s:GetSyntaxName(lnum, col) "{{{3 + let syntaxName = synIDattr(synID(a:lnum, a:col, 1), 'name') + if !empty(g:tcomment#syntax_substitute) + for [rx, subdef] in items(g:tcomment#syntax_substitute) + if !has_key(subdef, 'if') || eval(subdef.if) + let syntaxName = substitute(syntaxName, rx, subdef.sub, 'g') + endif + endfor + endif + " TLogVAR syntaxName + return syntaxName +endf + + +function! s:CommentMode(commentMode, newmode) "{{{3 + return substitute(a:commentMode, '\w\+', a:newmode, 'g') +endf + +function! s:GuessCurrentCommentString(commentMode) + let valid_cms = (stridx(&commentstring, '%s') != -1) + if &commentstring != s:defaultCommentString && valid_cms + " The &commentstring appears to have been set and to be valid + return &commentstring + endif + if &comments != s:defaultComments + " the commentstring is the default one, so we assume that it wasn't + " explicitly set; we then try to reconstruct &cms from &comments + let cms = s:ConstructFromComments(a:commentMode) + if cms != s:nullCommentString + return cms + endif + endif + if valid_cms + " Before &commentstring appeared not to be set. As we don't know + " better we return it anyway if it is valid + return &commentstring + else + " &commentstring is invalid. So we return the identity string. + return s:nullCommentString + endif +endf + +function! s:ConstructFromComments(commentMode) + exec s:ExtractCommentsPart('') + if a:commentMode =~# 'G' && line != '' + return line .' %s' + endif + exec s:ExtractCommentsPart('s') + if s != '' + exec s:ExtractCommentsPart('e') + return s.' %s '.e + endif + if line != '' + return line .' %s' + else + return s:nullCommentString + endif +endf + +function! s:ExtractCommentsPart(key) + " let key = a:key != "" ? a:key .'[^:]*' : "" + let key = a:key . '[bnflrxO0-9-]*' + let val = substitute(&comments, '^\(.\{-},\)\{-}'. key .':\([^,]\+\).*$', '\2', '') + if val == &comments + let val = '' + else + let val = substitute(val, '%', '%%', 'g') + endif + let var = a:key == '' ? 'line' : a:key + return 'let '. var .'="'. escape(val, '"') .'"' +endf + +" s:GetCustomCommentString(ft, commentMode, ?default="") +function! s:GetCustomCommentString(ft, commentMode, ...) + let commentMode = a:commentMode + let customComment = tcomment#TypeExists(a:ft) + if commentMode =~# 'B' && tcomment#TypeExists(a:ft .'_block') + let def = s:definitions[a:ft .'_block'] + elseif commentMode =~? 'I' && tcomment#TypeExists(a:ft .'_inline') + let def = s:definitions[a:ft .'_inline'] + elseif customComment + let def = s:definitions[a:ft] + let commentMode = s:CommentMode(commentMode, 'G') + elseif a:0 >= 1 + let def = {'commentstring': a:1} + let commentMode = s:CommentMode(commentMode, 'G') + else + let def = {} + let commentMode = s:CommentMode(commentMode, 'G') + endif + let cdef = copy(def) + let cdef.mode = commentMode + return cdef +endf + +function! s:GetCommentReplace(cdef, cms0) + if has_key(a:cdef, 'commentstring_rx') + let rs = s:BlockGetCommentString(a:cdef) + else + let rs = a:cms0 + endif + return escape(rs, '"/') +endf + +function! s:BlockGetCommentRx(cdef) + if has_key(a:cdef, 'commentstring_rx') + return a:cdef.commentstring_rx + else + let cms0 = s:BlockGetCommentString(a:cdef) + let cms0 = escape(cms0, '\') + return cms0 + endif +endf + +function! s:BlockGetCommentString(cdef) + if has_key(a:cdef, 'middle') + return a:cdef.commentstring + else + return matchstr(a:cdef.commentstring, '^.\{-}\ze\(\n\|$\)') + endif +endf + +function! s:BlockGetMiddleString(cdef) + if has_key(a:cdef, 'middle') + return a:cdef.middle + else + return matchstr(a:cdef.commentstring, '\n\zs.*') + endif +endf + + +redraw + diff --git a/vim/dot_vim/doc/NERD_tree.txt b/vim/dot_vim/doc/NERD_tree.txt new file mode 100644 index 0000000..174229d --- /dev/null +++ b/vim/dot_vim/doc/NERD_tree.txt @@ -0,0 +1,1291 @@ +*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 not tree exists and the current file is under vim's CWD, then init a + tree at the CWD and reveal the file. Otherwise init a tree in the current + file's directory. + + In any case, the current file is revealed and the cursor is placed on it. + +------------------------------------------------------------------------------ +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. + If is not provided, it defaults to the file or directory name. + For directories, a trailing slash is present. + +: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. + +|'NERDTreeMinimalUI'| Disables display of the 'Bookmarks' label and + 'Press ? for help' text. + +|'NERDTreeDirArrows'| Tells the NERD tree to use arrows instead of + + ~ chars when displaying directories. + +------------------------------------------------------------------------------ +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. + +------------------------------------------------------------------------------ + *'NERDTreeMinimalUI'* +Values: 0 or 1 +Default: 0 + +This options disables the 'Bookmarks' label 'Press ? for help' text. Use one +of the following lines to set this option: > + let NERDTreeMinimalUI=0 + let NERDTreeMinimalUI=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeDirArrows'* +Values: 0 or 1 +Default: 0. + +This option is used to change the default look of directory nodes displayed in +the tree. When set to 0 it shows old-school bars (|), + and ~ chars. If set to +1 it shows right and down arrows. Use one of the follow lines to set this +option: > + let NERDTreeDirArrows=0 + let NERDTreeDirArrows=1 +< + +============================================================================== +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.2.0 + - Add NERDTreeDirArrows option to make the UI use pretty arrow chars + instead of the old +~| chars to define the tree structure (sickill) + - shift the syntax highlighting out into its own syntax file (gnap) + - add some mac specific options to the filesystem menu - for macvim + only (andersonfreitas) + - Add NERDTreeMinimalUI option to remove some non functional parts of the + nerdtree ui (camthompson) + - tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the + new behaviour (benjamingeiger) + - if no name is given to :Bookmark, make it default to the name of the + target file/dir (minyoung) + - use 'file' completion when doing copying, create, and move + operations (EvanDotPro) + - lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly + Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!) + +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 + Vitaly Bogdanov + Patrick O'Loughlin (paddyoloughlin) + Cam Thompson (camthompson) + Marcin Kulik (sickill) + Steve DeWald (sdewald) + Ivan Necas (iNecas) + George Ang (gnap) + Evan Coury (EvanDotPro) + Andrew Radev (AndrewRadev) + Matt Gauger (mathias) + Scott Stevenson (scottstvnsn) + Anderson Freitas (andersonfreitas) + Kamil K. Lemański (kml) + Yehuda Katz (wycats) + Min-Young Wu (minyoung) + Benjamin Geiger (benjamingeiger) + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. diff --git a/vim/dot_vim/doc/tags b/vim/dot_vim/doc/tags index ea7b3bc..ac86352 100644 --- a/vim/dot_vim/doc/tags +++ b/vim/dot_vim/doc/tags @@ -1,79 +1,36 @@ -'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'* -: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* -AN alternate.txt /*AN* -AS alternate.txt /*AS* -AT alternate.txt /*AT* -AV alternate.txt /*AV* -IH alternate.txt /*IH* -IHN alternate.txt /*IHN* -IHS alternate.txt /*IHS* -IHT alternate.txt /*IHT* -IHV alternate.txt /*IHV* -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()* -alternate alternate.txt /*alternate* -alternate-acknowledgments alternate.txt /*alternate-acknowledgments* -alternate-commands alternate.txt /*alternate-commands* -alternate-config alternate.txt /*alternate-config* -alternate-installation alternate.txt /*alternate-installation* -alternate-purpose alternate.txt /*alternate-purpose* -alternate-support alternate.txt /*alternate-support* -alternate.txt alternate.txt /*alternate.txt* -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* +:TComment tcomment.txt /*:TComment* +:TCommentAs tcomment.txt /*:TCommentAs* +:TCommentBlock tcomment.txt /*:TCommentBlock* +:TCommentInline tcomment.txt /*:TCommentInline* +:TCommentMaybeInline tcomment.txt /*:TCommentMaybeInline* +:TCommentRight tcomment.txt /*:TCommentRight* +g:tcomment#ignore_char_type tcomment.txt /*g:tcomment#ignore_char_type* +g:tcomment#syntax_substitute tcomment.txt /*g:tcomment#syntax_substitute* +g:tcommentBlankLines tcomment.txt /*g:tcommentBlankLines* +g:tcommentBlockC tcomment.txt /*g:tcommentBlockC* +g:tcommentBlockC2 tcomment.txt /*g:tcommentBlockC2* +g:tcommentBlockXML tcomment.txt /*g:tcommentBlockXML* +g:tcommentGuessFileType tcomment.txt /*g:tcommentGuessFileType* +g:tcommentGuessFileType_django tcomment.txt /*g:tcommentGuessFileType_django* +g:tcommentGuessFileType_dsl tcomment.txt /*g:tcommentGuessFileType_dsl* +g:tcommentGuessFileType_html tcomment.txt /*g:tcommentGuessFileType_html* +g:tcommentGuessFileType_php tcomment.txt /*g:tcommentGuessFileType_php* +g:tcommentGuessFileType_tskeleton tcomment.txt /*g:tcommentGuessFileType_tskeleton* +g:tcommentGuessFileType_vim tcomment.txt /*g:tcommentGuessFileType_vim* +g:tcommentIgnoreTypes_php tcomment.txt /*g:tcommentIgnoreTypes_php* +g:tcommentInlineC tcomment.txt /*g:tcommentInlineC* +g:tcommentInlineXML tcomment.txt /*g:tcommentInlineXML* +g:tcommentMapLeaderOp1 tcomment.txt /*g:tcommentMapLeaderOp1* +g:tcommentMapLeaderOp2 tcomment.txt /*g:tcommentMapLeaderOp2* +g:tcommentOpModeExtra tcomment.txt /*g:tcommentOpModeExtra* +g:tcommentOptions tcomment.txt /*g:tcommentOptions* +g:tcommentSyntaxMap tcomment.txt /*g:tcommentSyntaxMap* +tcomment#Comment() tcomment.txt /*tcomment#Comment()* +tcomment#CommentAs() tcomment.txt /*tcomment#CommentAs()* +tcomment#DefineType() tcomment.txt /*tcomment#DefineType()* +tcomment#Operator() tcomment.txt /*tcomment#Operator()* +tcomment#OperatorAnyway() tcomment.txt /*tcomment#OperatorAnyway()* +tcomment#OperatorLine() tcomment.txt /*tcomment#OperatorLine()* +tcomment#OperatorLineAnyway() tcomment.txt /*tcomment#OperatorLineAnyway()* +tcomment-maps tcomment.txt /*tcomment-maps* +tcomment.txt tcomment.txt /*tcomment.txt* diff --git a/vim/dot_vim/doc/tcomment.txt b/vim/dot_vim/doc/tcomment.txt new file mode 100644 index 0000000..34a9fc4 --- /dev/null +++ b/vim/dot_vim/doc/tcomment.txt @@ -0,0 +1,359 @@ +*tcomment.txt* An easily extensible & universal comment plugin + Author: Thomas Link, micathom AT gmail com?subject=vim + +tcomment provides easy to use, file-type sensible comments for Vim. It +can handle embedded syntax. + +TComment works like a toggle, i.e., it will comment out text that +contains uncommented lines, and it will remove comment markup for +already commented text (i.e. text that contains no uncommented lines). + +If the file-type is properly defined, TComment will figure out which +comment string to use. Otherwise you use |tcomment#DefineType()| to +override the default choice. + +TComment can properly handle an embedded syntax, e.g., ruby/python/perl +regions in vim scripts, HTML or JavaScript in php code etc. + +Demo: +http://vimsomnia.blogspot.com/2010/11/tcomment-vim-plugin.html + + + *tcomment-maps* +Key bindings~ + +Most of the time the default toggle keys will do what you want (or to be +more precise: what I think you want it to do ;-). + + *g:tcommentMapLeaderOp1* + *g:tcommentMapLeaderOp2* +As operator (the prefix can be customized via g:tcommentMapLeaderOp1 +and g:tcommentMapLeaderOp2): + + gc{motion} :: Toggle comments (for small comments within one line + the &filetype_inline style will be used, if + defined) + gcc :: Toggle comment for the current line + gC{motion} :: Comment region + gCc :: Comment the current line + +By default the cursor stays put. If you want the cursor to the end of +the commented text, set |g:tcommentOpModeExtra| to '>' (but this may not +work properly with exclusive motions). + +Primary key maps: + + :: :TComment + :: :TComment + b :: :TCommentBlock + a :: :TCommentAs + n :: :TCommentAs &filetype + s :: :TCommentAs &filetype_ + i :: :TCommentInline + r :: :TCommentRight + p :: Comment the current inner paragraph + +A secondary set of key maps is defined for normal mode. + + __ :: :TComment + _p :: Comment the current inner paragraph + _ :: :TComment + _i :: :TCommentInline + _r :: :TCommentRight + _b :: :TCommentBlock + _a :: :TCommentAs + _n :: :TCommentAs &filetype + _s :: :TCommentAs &filetype_ + + +----------------------------------------------------------------------- +Install~ + +Edit the vba file and type: > + + :so % + +See :help vimball for details. If you have difficulties or use vim 7.0, +please make sure, you have the current version of vimball (vimscript +#1502) installed or update your runtime. + + +======================================================================== +Contents~ + + :TComment ........................... |:TComment| + :TCommentAs ......................... |:TCommentAs| + :TCommentRight ...................... |:TCommentRight| + :TCommentBlock ...................... |:TCommentBlock| + :TCommentInline ..................... |:TCommentInline| + :TCommentMaybeInline ................ |:TCommentMaybeInline| + g:tcommentBlankLines ................ |g:tcommentBlankLines| + g:tcommentOpModeExtra ............... |g:tcommentOpModeExtra| + g:tcommentOptions ................... |g:tcommentOptions| + g:tcomment#ignore_char_type ......... |g:tcomment#ignore_char_type| + g:tcommentGuessFileType ............. |g:tcommentGuessFileType| + g:tcommentGuessFileType_dsl ......... |g:tcommentGuessFileType_dsl| + g:tcommentGuessFileType_php ......... |g:tcommentGuessFileType_php| + g:tcommentGuessFileType_html ........ |g:tcommentGuessFileType_html| + g:tcommentGuessFileType_tskeleton ... |g:tcommentGuessFileType_tskeleton| + g:tcommentGuessFileType_vim ......... |g:tcommentGuessFileType_vim| + g:tcommentGuessFileType_django ...... |g:tcommentGuessFileType_django| + g:tcommentIgnoreTypes_php ........... |g:tcommentIgnoreTypes_php| + g:tcomment#syntax_substitute ........ |g:tcomment#syntax_substitute| + g:tcommentSyntaxMap ................. |g:tcommentSyntaxMap| + g:tcommentBlockC .................... |g:tcommentBlockC| + g:tcommentBlockC2 ................... |g:tcommentBlockC2| + g:tcommentInlineC ................... |g:tcommentInlineC| + g:tcommentBlockXML .................. |g:tcommentBlockXML| + g:tcommentInlineXML ................. |g:tcommentInlineXML| + tcomment#DefineType ................. |tcomment#DefineType()| + tcomment#Comment .................... |tcomment#Comment()| + tcomment#Operator ................... |tcomment#Operator()| + tcomment#OperatorLine ............... |tcomment#OperatorLine()| + tcomment#OperatorAnyway ............. |tcomment#OperatorAnyway()| + tcomment#OperatorLineAnyway ......... |tcomment#OperatorLineAnyway()| + tcomment#CommentAs .................. |tcomment#CommentAs()| + + +======================================================================== +plugin/tcomment.vim~ + + *:TComment* +:[range]TComment[!] ?ARGS... + If there is a visual selection that begins and ends in the same line, + then |:TCommentInline| is used instead. + The optional range defaults to the current line. With a bang '!', + always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + *:TCommentAs* +:[range]TCommentAs[!] commenttype ?ARGS... + TCommentAs requires g:tcomment_{filetype} to be defined. + With a bang '!', always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + *:TCommentRight* +:[range]TCommentRight[!] ?ARGS... + Comment the text to the right of the cursor. If a visual selection was + made (be it block-wise or not), all lines are commented out at from + the current cursor position downwards. + With a bang '!', always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + *:TCommentBlock* +:[range]TCommentBlock[!] ?ARGS... + Comment as "block", e.g. use the {&ft}_block comment style. The + commented text isn't indented or reformated. + With a bang '!', always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + *:TCommentInline* +:[range]TCommentInline[!] ?ARGS... + Use the {&ft}_inline comment style. + With a bang '!', always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + *:TCommentMaybeInline* +:[range]TCommentMaybeInline[!] ?ARGS... + With a bang '!', always comment the line. + + ARGS... are either (see also |tcomment#Comment()|): + 1. a list of key=value pairs + 2. 1-2 values for: ?commentBegin, ?commentEnd + + +======================================================================== +autoload/tcomment.vim~ + + *g:tcommentBlankLines* +g:tcommentBlankLines (default: 1) + If true, comment blank lines too + + *g:tcommentOpModeExtra* +g:tcommentOpModeExtra (default: '') + Modifies how the operator works. + > ... Move the cursor to the end of the comment + + *g:tcommentOptions* +g:tcommentOptions (default: {}) + Other key-value options used by |tcomment#Comment()|. + + Example: If you want to put the opening comment marker always in + the first column regardless of the block's indentation, put this + into your |vimrc| file: > + let g:tcommentOptions = {'col': 1} +< + + *g:tcomment#ignore_char_type* +g:tcomment#ignore_char_type (default: 1) + |text-objects| for use with |tcomment#Operator| can have different + types: line, block, char etc. Text objects like aB, it, at etc. + have type char but this may not work reliably. By default, + tcomment handles those text objects most often as if they were of + type line. Set this variable to 0 in order to change this + behaviour. Be prepared that the result may not always match your + intentions. + + *g:tcommentGuessFileType* +g:tcommentGuessFileType (default: 0) + Guess the file type based on syntax names always or for some fileformat only + If non-zero, try to guess filetypes. + tcomment also checks g:tcommentGuessFileType_{&filetype} for + filetype specific values. + + Values: + 0 ... don't guess + 1 ... guess + FILETYPE ... assume this filetype + + *g:tcommentGuessFileType_dsl* +g:tcommentGuessFileType_dsl (default: 'xml') + For dsl documents, assumet filetype = xml. + + *g:tcommentGuessFileType_php* +g:tcommentGuessFileType_php (default: 'html') + In php documents, the php part is usually marked as phpRegion. We + thus assume that the buffers default comment style isn't php but + html. + + *g:tcommentGuessFileType_html* +g:tcommentGuessFileType_html (default: 1) + + *g:tcommentGuessFileType_tskeleton* +g:tcommentGuessFileType_tskeleton (default: 1) + + *g:tcommentGuessFileType_vim* +g:tcommentGuessFileType_vim (default: 1) + + *g:tcommentGuessFileType_django* +g:tcommentGuessFileType_django (default: 1) + + *g:tcommentIgnoreTypes_php* +g:tcommentIgnoreTypes_php (default: 'sql') + In php files, some syntax regions are wongly highlighted as sql + markup. We thus ignore sql syntax when guessing the filetype in + php files. + + *g:tcomment#syntax_substitute* +g:tcomment#syntax_substitute (default: {...}) + + *g:tcommentSyntaxMap* +g:tcommentSyntaxMap (default: {...}) + tcomment guesses filetypes based on the name of the current syntax + region. This works well if the syntax names match + /filetypeSomeName/. Other syntax names have to be explicitly + mapped onto the corresponding filetype. + + *g:tcommentBlockC* +g:tcommentBlockC (default: {...}) + Generic c-like block comments. + + *g:tcommentBlockC2* +g:tcommentBlockC2 (default: {...}) + Generic c-like block comments (alternative markup). + + *g:tcommentInlineC* +g:tcommentInlineC (default: "/* %s */") + Generic c-like comments. + + *g:tcommentBlockXML* +g:tcommentBlockXML (default: "\n ") + Generic xml-like block comments. + + *g:tcommentInlineXML* +g:tcommentInlineXML (default: "") + Generic xml-like comments. + + *tcomment#DefineType()* +tcomment#DefineType(name, commentdef) + If you don't explicitly define a comment style, |:TComment| will use + 'commentstring' instead. We override the default values here in order + to have a blank after the comment marker. Block comments work only if + we explicitly define the markup. + + The comment definition can be either a string or a dictionary. + + If it is a string: + The format for block comments is similar to 'commentstrings' with the + exception that the format strings for blocks can contain a second line + that defines how "middle lines" (see :h format-comments) should be + displayed. + + If it is a dictionary: + See the help on the args argument of |tcomment#Comment|. + + *tcomment#Comment()* +tcomment#Comment(beg, end, ...) + tcomment#Comment(line1, line2, ?commentMode, ?commentAnyway, ?args...) + args... are either: + 1. a list of key=value pairs where known keys are (see also + |g:tcommentOptions|): + as=STRING ... Use a specific comment definition + col=N ... Start the comment at column N (in block + mode; must be smaller than |indent()|) + mode=STRING ... See the notes below on the "commentMode" argument + begin=STRING ... Comment prefix + end=STRING ... Comment postfix + middle=STRING ... Middle line comments in block mode + rxbeg=N ... Regexp to find the substring of "begin" + that should be multipied by "count" + rxend=N ... The above for "end" + rxmid=N ... The above for "middle" + commentstring_rx ... A regexp format string that matches + commented lines (no new groups may be + introduced, the |regexp| is |\V|; % have + to be doubled); "commentstring", "begin" + and optionally "end" must be defined or + deducible. + 2. 1-2 values for: ?commentPrefix, ?commentPostfix + 3. a dictionary (internal use only) + + commentMode: + G ... guess the value of commentMode + B ... block (use extra lines for the comment markers) + i ... maybe inline, guess + I ... inline + R ... right (comment the line right of the cursor) + v ... visual + o ... operator + By default, each line in range will be commented by adding the comment + prefix and postfix. + + *tcomment#Operator()* +tcomment#Operator(type, ...) + + *tcomment#OperatorLine()* +tcomment#OperatorLine(type) + + *tcomment#OperatorAnyway()* +tcomment#OperatorAnyway(type) + + *tcomment#OperatorLineAnyway()* +tcomment#OperatorLineAnyway(type) + + *tcomment#CommentAs()* +tcomment#CommentAs(beg, end, commentAnyway, filetype, ?args...) + Where args is either: + 1. A count NUMBER + 2. An args list (see the notes on the "args" argument of + |tcomment#Comment()|) + comment text as if it were of a specific filetype + + + +vim:tw=78:fo=tcq2:isk=!-~,^*,^|,^":ts=8:ft=help:norl: diff --git a/vim/dot_vim/nerdtree_plugin/exec_menuitem.vim b/vim/dot_vim/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..e7a7c53 --- /dev/null +++ b/vim/dot_vim/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 +" 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/vim/dot_vim/nerdtree_plugin/fs_menu.vim b/vim/dot_vim/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..0e2f728 --- /dev/null +++ b/vim/dot_vim/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,224 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell +" 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 current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) + +if has("gui_mac") || has("gui_macvim") + call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'}) + call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'}) + call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'}) +endif + +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() . g:NERDTreePath.Slash(), "file") + + 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(), "file") + + 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(), "file") + + 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) + if !empty(newNode) + call NERDTreeRender() + call newNode.putCursorHere(0, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Could not copy node") + endtry + endif + else + call s:echo("Copy aborted.") + endif + redraw +endfunction + +function! NERDTreeQuickLook() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'") + endif +endfunction + +function! NERDTreeRevealInFinder() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + let x = system("open -R '" . treenode.path.str() . "'") + endif +endfunction + +function! NERDTreeExecuteFile() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + let x = system("open '" . treenode.path.str() . "'") + endif +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/vim/dot_vim/plugin/NERD_tree.vim b/vim/dot_vim/plugin/NERD_tree.vim new file mode 100644 index 0000000..bc34775 --- /dev/null +++ b/vim/dot_vim/plugin/NERD_tree.vim @@ -0,0 +1,4017 @@ +" ============================================================================ +" File: NERD_tree.vim +" Description: vim global plugin that provides a nice tree explorer +" Maintainer: Martin Grenfell +" Last Change: 28 December, 2011 +" 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.2.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 + +let s:running_windows = has("win16") || has("win32") || has("win64") + +"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 . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'" + 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) +call s:initVariable("g:NERDTreeMinimalUI", 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) +call s:initVariable("g:NERDTreeDirArrows", !s:running_windows) + +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) + +"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", "") +call s:initVariable("g:NERDTreeMapJumpParent", "p") +call s:initVariable("g:NERDTreeMapJumpPrevSibling", "") +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('') +command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('') +command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen() +command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('') +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 saveScreenState()" + + "disallow insert mode in the NERDTree + exec "autocmd BufEnter ". s:NERDTreeBufName ."* stopinsert" + + "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("")) + 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() + call s:closeTreeIfQuitOnOpen() + 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 " . self.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 ". self.key ." :call ". self.callback ."()" +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 currently 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) + + "if a bookmark exists with the same name and the node is cached then save + "it so we can update its display string + let oldMarkedNode = {} + try + let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1) + catch /^NERDTree.BookmarkNotFoundError/ + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + + call s:Bookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call s:Bookmark.Write() + + if !empty(oldMarkedNode) + call oldMarkedNode.path.cacheDisplayString() + endif +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() + return parent.findNode(newPath) + else + return {} + endif +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 g:NERDTreeDirArrows + let treeParts = treeParts . ' ' + else + if j ==# 1 + let treeParts = treeParts . '| ' + else + let treeParts = treeParts . ' ' + endif + 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 !g:NERDTreeDirArrows + if a:isLastChild + let treeParts = treeParts . '`' + else + let treeParts = treeParts . '|' + endif + endif + + "smack the appropriate dir/file symbol on the line before the file/dir + "name itself + if self.path.isDirectory + if self.isOpen + if g:NERDTreeDirArrows + let treeParts = treeParts . '▾ ' + else + let treeParts = treeParts . '~' + endif + else + if g:NERDTreeDirArrows + let treeParts = treeParts . '▸ ' + else + let treeParts = treeParts . '+' + endif + endif + else + if g:NERDTreeDirArrows + let treeParts = treeParts . ' ' + else + let treeParts = treeParts . '-' + endif + 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 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("%:p")) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("no file for the current buffer") + return + endtry + + if !s:treeExistsForTab() + try + let cwd = s:Path.New(getcwd()) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("current directory does not exist.") + let cwd = p.getParent() + endtry + + if p.isUnder(cwd) + call s:initNerdTree(cwd.str()) + else + call s:initNerdTree(p.getParent().str()) + endif + 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() + + call s:setCommonBufOptions() + let b:NERDTreeType = "secondary" + + 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 + if winnr() == s:getTreeWinNum() + wincmd p + let bufnr = bufnr("") + wincmd p + else + let bufnr = bufnr("") + endif + + call s:exec(s:getTreeWinNum() . " wincmd w") + close + call s:exec(bufwinnr(bufnr) . " wincmd w") + 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 + call s:setCommonBufOptions() +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."\" ,\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 \n" + let @h=@h."\" :BookmarkToRoot \n" + let @h=@h."\" :RevealBookmark \n" + let @h=@h."\" :OpenBookmark \n" + let @h=@h."\" :ClearBookmarks []\n" + let @h=@h."\" :ClearAllBookmarks\n" + silent! put h + elseif g:NERDTreeMinimalUI == 0 + let @h="\" Press ". g:NERDTreeMapHelp ." for help\n" + silent! put h + endif + + 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 + + if !g:NERDTreeDirArrows + " in case called from outside the tree + if line !~# '^ *[|`▸▾ ]' || line =~# '^$' + return {} + endif + 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) + let level = match(a:line, '[^ \-+~▸▾`|]') / s:tree_wid + " check if line includes arrows + if match(a:line, '[▸▾]') > -1 + " decrement level as arrow uses 3 ascii chars + let level = level - 1 + endif + return level +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 + + if g:NERDTreeMinimalUI + return cursor(1, 2) + 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, 2) +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() + + if g:NERDTreeMinimalUI == 0 + call setline(line(".")+1, ">----------Bookmarks----------") + call cursor(line(".")+1, col(".")) + endif + + 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 + if g:NERDTreeMinimalUI == 0 + call setline(line(".")+1, "") + call cursor(line(".")+1, col(".")) + endif + + if b:NERDTreeShowBookmarks + call s:renderBookmarks() + endif + + "add the 'up a dir' line + if !g:NERDTreeMinimalUI + call setline(line(".")+1, s:tree_up_dir_line) + call cursor(line(".")+1, col(".")) + endif + + "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:setCommonBufOptions() {{{2 +function! s:setCommonBufOptions() + "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 + if v:version >= 703 + setlocal nornu + endif + endif + + iabc + + 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 + setfiletype nerdtree + call s:bindMappings() +endfunction + +"FUNCTION: s:setupStatusline() {{{2 +function! s:setupStatusline() + if g:NERDTreeStatusline != -1 + let &l:statusline = g:NERDTreeStatusline + endif +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 :call handleMiddleMouse() + nnoremap :call checkForActivate() + nnoremap <2-leftmouse> :call activateNode(0) + + exec "nnoremap ". g:NERDTreeMapActivateNode . " :call activateNode(0)" + exec "nnoremap ". g:NERDTreeMapOpenSplit ." :call openEntrySplit(0,0)" + exec "nnoremap :call activateNode(0)" + + exec "nnoremap ". g:NERDTreeMapPreview ." :call previewNode(0)" + exec "nnoremap ". g:NERDTreeMapPreviewSplit ." :call previewNode(1)" + + exec "nnoremap ". g:NERDTreeMapOpenVSplit ." :call openEntrySplit(1,0)" + exec "nnoremap ". g:NERDTreeMapPreviewVSplit ." :call previewNode(2)" + + exec "nnoremap ". g:NERDTreeMapOpenRecursively ." :call openNodeRecursively()" + + exec "nnoremap ". g:NERDTreeMapUpdirKeepOpen ." :call upDir(1)" + exec "nnoremap ". g:NERDTreeMapUpdir ." :call upDir(0)" + exec "nnoremap ". g:NERDTreeMapChangeRoot ." :call chRoot()" + + exec "nnoremap ". g:NERDTreeMapChdir ." :call chCwd()" + + exec "nnoremap ". g:NERDTreeMapQuit ." :call closeTreeWindow()" + + exec "nnoremap ". g:NERDTreeMapRefreshRoot ." :call refreshRoot()" + exec "nnoremap ". g:NERDTreeMapRefresh ." :call refreshCurrent()" + + exec "nnoremap ". g:NERDTreeMapHelp ." :call displayHelp()" + exec "nnoremap ". g:NERDTreeMapToggleZoom ." :call toggleZoom()" + exec "nnoremap ". g:NERDTreeMapToggleHidden ." :call toggleShowHidden()" + exec "nnoremap ". g:NERDTreeMapToggleFilters ." :call toggleIgnoreFilter()" + exec "nnoremap ". g:NERDTreeMapToggleFiles ." :call toggleShowFiles()" + exec "nnoremap ". g:NERDTreeMapToggleBookmarks ." :call toggleShowBookmarks()" + + exec "nnoremap ". g:NERDTreeMapCloseDir ." :call closeCurrentDir()" + exec "nnoremap ". g:NERDTreeMapCloseChildren ." :call closeChildren()" + + exec "nnoremap ". g:NERDTreeMapMenu ." :call showMenu()" + + exec "nnoremap ". g:NERDTreeMapJumpParent ." :call jumpToParent()" + exec "nnoremap ". g:NERDTreeMapJumpNextSibling ." :call jumpToSibling(1)" + exec "nnoremap ". g:NERDTreeMapJumpPrevSibling ." :call jumpToSibling(0)" + exec "nnoremap ". g:NERDTreeMapJumpFirstChild ." :call jumpToFirstChild()" + exec "nnoremap ". g:NERDTreeMapJumpLastChild ." :call jumpToLastChild()" + exec "nnoremap ". g:NERDTreeMapJumpRoot ." :call jumpToRoot()" + + exec "nnoremap ". g:NERDTreeMapOpenInTab ." :call openInNewTab(0)" + exec "nnoremap ". g:NERDTreeMapOpenInTabSilent ." :call openInNewTab(1)" + + exec "nnoremap ". g:NERDTreeMapOpenExpl ." :call openExplorer()" + + exec "nnoremap ". g:NERDTreeMapDeleteBookmark ." :call deleteBookmark()" + + "bind all the user custom maps + call s:KeyMap.BindAll() + + command! -buffer -nargs=? Bookmark :call bookmarkNode('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call revealBookmark('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call openBookmark('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call clearBookmarks('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('') + command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() call renderView() + command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) call 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(...) + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + let name = a:1 + if empty(name) + let name = currentNode.path.getLastPathComponent(0) + endif + try + call currentNode.bookmark(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(".")) + + if currentNode.path.isDirectory + if startToCur =~# s:tree_markup_reg . '$' && startToCur =~# '[+~▾▸]$' + call s:activateNode(0) + return + endif + endif + + if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3 + let char = strpart(startToCur, strlen(startToCur)-1, 1) + if char !~# s:tree_markup_reg + 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/vim/dot_vim/plugin/buffet.vim b/vim/dot_vim/plugin/buffet.vim new file mode 100644 index 0000000..9fb93fd --- /dev/null +++ b/vim/dot_vim/plugin/buffet.vim @@ -0,0 +1,524 @@ +" Buffet Plugin for VIM > 7.3 version 2.10 +" +" A fast, simple and easy to use pluggin for switching and managing buffers. +" +" Usage: +" +" Copy the file buffet.vim to the plugins directory. +" The command to open the buffer list is +" :Bufferlist +" +" A horizontal window is opened with a list of buffer. the buffer numbers are +" also displayed along side. The user select a buffer by +" +" 1.Entering the buffer number using keyboard. Just start typing the number using keyboard. +" The plugin will search for the buffer with that number and will keep going to the matching +" buffers. Entered number will be shown at the top you can use backspace to edit it.When you +" are in the desired buffer, press enter or any control keys that are +" displayed at the bottom to execute any command available, on that buffer +" +" Available commands +" +" Enter(Replace current buffer) +" o - make window fill with selected buffer +" hh - (Horizontal Split) +" v - (Vertical Split) +" - - (Vertical Diff Split) +" g - (Go to buffer window if it is visible in any tab) +" d - (Delete selected buffer) +" x - (Close window) +" c - (Clear diff flags for all windows) +" +" 2.Move up or down using the navigation keys to reach the buffer line. +" +" 3.Doubleclick on a buffer line using the mouse. Will immediatly switch to +" that buffer +" +" To make this plugin really useful you have to assign a shortcut key for it, +" say you want F2 key to open the buffer list. you can add the following line in your .vimrc file. +" +" map :Bufferlist +" +" Last Change: 2012 Jan +" Maintainer: Sandeep.c.r +" +" +function! s:open_new_window(dim) + exe s:currentposition. ' '.a:dim . 'new buflisttempbuffer412393' + set nonu + setlocal bt=nofile + setlocal modifiable + setlocal bt=nowrite + setlocal bufhidden=hide + setlocal noswapfile + setlocal nowrap + setlocal ft=buffet + return bufnr('%') +endfunction +function! s:open_new_vertical_window(dim) + exe a:dim . 'vnew' + set nonu + setlocal bt=nofile + setlocal bt=nowrite + setlocal bufhidden=hide + setlocal noswapfile + return bufnr('%') +endfunction +function! s:cursormove() + let s:lineonclose = line('.') + if(s:lineonclose >len(s:displayed)+1) + call cursor(2,3) + elseif(s:lineonclose ==1 ) + call cursor(len(s:displayed)+1,3) + endif +endfunction +function! s:buffet_pathshorten(str) + if(s:detail == 1) + return a:str + else + return pathshorten(a:str) + endif +endfunction +function! s:display_buffer_list(gotolastbuffer) + let l:line = 2 + let l:fg = synIDattr(hlID('Statement'),'fg','gui') + let l:bg = synIDattr(hlID('CursorLine'),'bg','gui') + call filter(s:bufrecent,'exists("s:bufferlistlite[v:val]") && v:val!=t:tlistbuf' ) + let l:maxlen = 0 + let l:headmaxlen = 0 + for l:i in keys(s:bufferlistlite) + if(index(s:bufrecent,l:i)==-1) + call add(s:bufrecent,l:i) + endif + let l:temp = strlen(fnamemodify(s:bufferlistlite[l:i],':t')) + let l:headtemp = strlen(s:buffet_pathshorten(fnamemodify(s:bufferlistlite[l:i],':h'))) + if(l:headtemp > l:headmaxlen) + let l:headmaxlen = l:headtemp + endif + if(l:temp > l:maxlen) + let l:maxlen = l:temp + endif + endfor + call setline(1,"Buffet-2.10 ( Enter Number to search for a buffer number )") + let s:displayed = [] + let s:last_buffer_line = 0 + for l:i in s:bufrecent + let l:thisbufno = str2nr(l:i) + let l:bufname = s:bufferlistlite[l:i] + let l:buftailname =fnamemodify(l:bufname,':t') + let l:bufheadlname =s:buffet_pathshorten(fnamemodify(l:bufname,':h')) + if(getbufvar(l:thisbufno,'&modified')) + let l:modifiedflag = " (+) " + else + let l:modifiedflag = " " + endif + let l:padlength = l:maxlen - strlen(l:buftailname) + 2 + let l:padlengthhead= l:headmaxlen - strlen(l:bufheadlname) + 2 + let l:short_file_name = repeat(' ',2-strlen(l:i)).l:i .' '. l:buftailname.repeat(' ',l:padlength) .l:modifiedflag. l:bufheadlname .repeat(' ',l:padlengthhead) + let l:padstring = repeat(' ',len(l:short_file_name)) + if(exists("s:buftotabwindow[l:thisbufno]")) + let l:thistab = s:buftotabwindow[l:thisbufno][0][0] + let l:thiswindow = s:buftotabwindow[l:thisbufno][0][1] + let l:short_file_name = l:short_file_name ." Tab:".l:thistab." Window:".l:thiswindow + call add(s:displayed,[l:thisbufno,l:thistab,l:thiswindow]) + if(l:thistab == s:sourcetab && l:thiswindow == s:sourcewindow) + let l:short_file_name = '>'.l:short_file_name ." <" + else + let l:short_file_name = ' '.l:short_file_name + endif + else + let l:short_file_name = ' '.l:short_file_name + call add(s:displayed,[l:thisbufno]) + endif + call setline(l:line,l:short_file_name) + let l:subwindow = 1 + while(exists("s:buftotabwindow[l:thisbufno][l:subwindow]")) + let l:thistab = s:buftotabwindow[l:thisbufno][l:subwindow][0] + let l:thiswindow = s:buftotabwindow[l:thisbufno][l:subwindow][1] + let l:line += 1 + if(l:thistab == s:sourcetab && l:thiswindow == s:sourcewindow) + call setline(l:line,'> '.l:padstring."Tab:".l:thistab." window:".l:thiswindow." <") + else + call setline(l:line,' '.l:padstring."Tab:".l:thistab." window:".l:thiswindow) + endif + call add(s:displayed,[l:thisbufno,l:thistab,l:thiswindow]) + let l:subwindow += 1 + endwhile + if(s:last_buffer_line == 0) + let s:last_buffer_line = l:line+1 + endif + let l:line += 1 + endfor + exe "resize ".(len(s:displayed)+4) + call setline(l:line,"") + let l:line+=1 + call setline(l:line,"Enter(Load buffer) | hh/v/-/c (Horizontal/Vertical/Vertical Diff Split/Clear Diff) | o(Maximize) | t(New tab) | m(Toggle detail) | g(Go to window) | d(Delete buffer) | x(Close window) ") + let l:fg = synIDattr(hlID('Statement'),'fg','Question') + exe 'highlight buffethelpline guibg=black' + exe 'highlight buffethelpline guifg=orange' + exe '2match buffethelpline /\%1l\|\%'.l:line.'l.\%>1c/' + if(a:gotolastbuffer==1) + call cursor(s:last_buffer_line,3) + else + if(s:lineonclose >len(s:displayed)+1) + let s:lineonclose -=1 + endif + call cursor(s:lineonclose,3) + endif +endfunction + +function! s:close() + if(exists("t:tlistbuf")) + unlet t:tlistbuf + let s:lineonclose = line('.') + :bdelete buflisttempbuffer412393 + echo '' + exe s:sourcewindow. ' wincmd w' + endif +endfunction + +function! s:place_sign() + setlocal cursorline + return + exec "sign unplace *" + exec "sign define lineh linehl=Search texthl=Search" + exec "sign place 10 name=lineh line=".line('.')." buffer=" . t:tlistbuf +endfunction + +function! s:getallbuffers() + let l:buffers = filter(range(1,bufnr('$')), 'buflisted(v:val)') + let l:return = {} + for i in l:buffers + let l:bufname = bufname(i) + if(strlen(l:bufname)==0) + let l:bufname = "[No Name]" + endif + let l:return[i] = l:bufname + endfor + return l:return +endfunction + +function! s:printmessage(msg) + setlocal modifiable + call setline(len(s:displayed)+2,a:msg) + setlocal nomodifiable +endfunction + +function! s:press(num) + if(a:num==-1) + let s:keybuf = strpart(s:keybuf,0,len(s:keybuf)-1) + else + let s:keybuf = s:keybuf . a:num + endif + setlocal modifiable + call setline(1 ,'Buffet-2.10 - Searching for buffer:'.s:keybuf.' (Use backspace to edit)') + let l:index = 0 + for l:i in s:displayed + if(l:i[0] == s:keybuf) + let l:index += 2 + exe "normal "+l:index+ "gg" + break + endif + let l:index += 1 + endfor + setlocal nomodifiable +endfunction + +function! s:togglesw() + let s:currentposition = '' + call s:toggle(1) +endfunction + +function! s:toggletop() + let s:currentposition = 'topleft' + call s:toggle(1) +endfunction +function! s:toggle(gotolastbuffer) + + let s:keybuf = '' + if(exists("t:tlistbuf")) + call s:close() + return 0 + endif + + let s:bufferlistlite = s:getallbuffers() + let s:sourcebuffer = bufnr('%') + let s:sourcewindow = winnr() + let s:sourcetab = tabpagenr() + let s:buftotabwindow = {} + for l:i in range(tabpagenr('$')) + let l:windowno = 1 + for l:bufno in tabpagebuflist(l:i + 1) + if(!exists("s:buftotabwindow[l:bufno]")) + let s:buftotabwindow[l:bufno] = [] + endif + call add(s:buftotabwindow[l:bufno], [l:i+1,l:windowno]) + let l:windowno += 1 + endfor + endfor + let t:tlistbuf = s:open_new_window(len(s:bufrecent)+4) + set nodiff + set noscrollbind + let s:buflistwindow = winnr() + setlocal cursorline + call s:display_buffer_list(a:gotolastbuffer) + "call matchadd('String','[\/\\][^\/\\]*$') + setlocal nomodifiable + map <2-leftrelease> :call loadbuffer(0) + nnoremap :call loadbuffer(0) + nnoremap :call loadbuffer(0) + nnoremap x :call closewindow(0) + nnoremap X :call closewindow(1) + nnoremap c :call cleardiff() + nnoremap C :call cleardiff() + nnoremap d :call deletebuffer(0) + nnoremap D :call deletebuffer(1) + nnoremap o :call loadbuffer(1) + nnoremap O :call loadbuffer(1) + nnoremap g :call gotowindow() + nnoremap G :call gotowindow() + nnoremap s :call split('h') + nnoremap S :call split('h') + nnoremap t :call openintab() + nnoremap T :call openintab() + nnoremap hh :call split('h') + nnoremap HH :call split('h') + nnoremap v :call split('v') + nnoremap V :call split('v') + nnoremap r :call refresh() + nnoremap 0 :call press(0) + nnoremap 1 :call press(1) + nnoremap 2 :call press(2) + nnoremap 3 :call press(3) + nnoremap 4 :call press(4) + nnoremap 5 :call press(5) + nnoremap 6 :call press(6) + nnoremap 7 :call press(7) + nnoremap 8 :call press(8) + nnoremap 9 :call press(9) + nnoremap - :call diff_split('v') + nnoremap m :call toggle_detail() + nnoremap M :call toggle_detail() + nnoremap :call press(-1) + nnoremap :call close() + augroup Tlistaco1 + autocmd! + au BufLeave call close() + au CursorMoved call cursormove() + augroup END +endfunction +function! s:toggle_detail() + let s:detail = !s:detail + setlocal modifiable + call s:display_buffer_list(0) + setlocal nomodifiable +endfunction +function! s:cleardiff() + for i in range(1,winnr('$')) + call setwinvar(i,"&diff",0) + call setwinvar(i,"&scrollbind",0) + endfor +endfunction +function! s:deletebuffer(force) + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]") ) + let l:selectedbuffer = str2nr(s:displayed[l:llindex][0]) + if(getbufvar(str2nr(l:selectedbuffer),'&modified') && a:force == 0 ) + call s:printmessage("Buffer contents modified. Use 'D' to force delete.") + else + call s:toggle(0) + exe "bdelete! ".l:selectedbuffer + call s:toggle(0) + endif + else + call s:close() + endif +endfunction + +function! s:openintab() + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + exe s:buflistwindow . ' wincmd w' + let l:target = s:displayed[l:llindex][0] + call s:close() + exe "tabnew" + exe l:target. ' buf!' + else + call s:close() + endif +endfunction + +function! s:closewindow(force) + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + if(exists("s:displayed[l:llindex][1]")) + if(getbufvar(str2nr(s:displayed[l:llindex][0]),'&modified') && a:force == 0 ) + call s:printmessage("Buffer contents modified. Use 'X' to force close.") + else + if(tabpagenr('$')==1 && winnr('$')==2) + call s:printmessage("Not closing last window of the last tab.") + else + exe s:buflistwindow . ' wincmd w' + call s:close() + exe "tabn" .s:displayed[l:llindex][1] + exe s:displayed[l:llindex][2]. ' wincmd w' + :q! + exe "tabn". s:sourcetab + call s:toggle(0) + endif + endif + else + call s:printmessage("Buffer not showing in any tab.") + endif + else + call s:close() + endif +endfunction + + +function! s:gotowindow() + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + if(exists("s:displayed[l:llindex][1]")) + exe s:buflistwindow . ' wincmd w' + call s:close() + exe "tabn" .s:displayed[l:llindex][1] + exe s:displayed[l:llindex][2]. ' wincmd w' + else + call s:printmessage("Buffer not showing in any tab. Use Enter,v,hh,t or o to open buffer in a window.") + endif + else + call s:close() + endif +endfunction + +function! s:loadbuffer(isonly) + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + exe s:buflistwindow . ' wincmd w' + let l:target = s:displayed[l:llindex][0] + call s:close() + call s:switch_buffer(l:target) + if(a:isonly == 1 && winnr('$')>1) + exe 'only!' + endif + else + call s:close() + endif +endfunction + +function! s:diff_split(mode) + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + exe s:buflistwindow . ' wincmd w' + let l:target = s:displayed[l:llindex][0] + call s:close() + call s:diff_split_buffer(l:target,a:mode) + else + call s:close() + endif +endfunction + + +function! s:split(mode) + let l:llindex= line('.') - 2 + if(exists("s:displayed[l:llindex]")) + exe s:buflistwindow . ' wincmd w' + let l:target = s:displayed[l:llindex][0] + call s:close() + call s:split_buffer(l:target,a:mode) + else + call s:close() + endif +endfunction + +function! s:goto_buffer(bufferno) + if(exists("s:buftotabwindow[a:bufferno]")) + let l:tabno = s:buftotabwindow[a:bufferno][0] + let l:winno = s:buftotabwindow[a:bufferno][1] + exe "tabn" .l:tabno + exe l:winno. ' wincmd w' + endif +endfunction +function! s:removedifforsource() + if(exists("b:buffet_sourcewindowfordiff")) + call setwinvar(b:buffet_sourcewindowfordiff,"&diff",0) + call setwinvar(b:buffet_sourcewindowfordiff,"&scrollbind",0) + endif +endfunction + +function! s:diff_split_buffer(bufferno,mode) + if(a:mode == 'v') + exe 'belowright vert '.a:bufferno. ' sbuf' + elseif(a:mode == 'h') + exe 'belowright ' .a:bufferno. ' sbuf' + endif + if(exists("s:buflinenos[a:bufferno]")) + exe "normal "+s:buflinenos[a:bufferno] + "gg" + endif + call setwinvar(s:sourcewindow,"&diff",1) + call setwinvar(s:sourcewindow,"&scrollbind",1) + let b:buffet_sourcewindowfordiff = s:sourcewindow + augroup Tlistaco2 + autocmd! + au BufWinLeave call removedifforsource() + augroup END + + setlocal diff + setlocal scrollbind +endfunction + + +function! s:split_buffer(bufferno,mode) + if(a:mode == 'v') + exe 'belowright vert '.a:bufferno. ' sbuf' + elseif(a:mode == 'h') + exe 'belowright ' .a:bufferno. ' sbuf' + endif + if(exists("s:buflinenos[a:bufferno]")) + exe "normal "+s:buflinenos[a:bufferno] + "gg" + endif + set nodiff + set noscrollbind +endfunction + +function! s:switch_buffer(bufferno) + exe a:bufferno. ' buf!' + set nodiff + set noscrollbind + if(exists("s:buflinenos[a:bufferno]")) + exe "normal "+s:buflinenos[a:bufferno] + "gg" + endif +endfunction + +function! s:updaterecent() + let l:bufname = bufname("%") + let l:j = bufnr('%') + if(strlen(l:bufname) > 0 && getbufvar(l:j,'&modifiable') ) + call filter(s:bufrecent, 'v:val !='. l:j) + call insert(s:bufrecent,l:j.'') + endif +endfunction + +function! s:savelineno() + let s:buflinenos[bufnr('%')] = line('.') +endfunction + +let s:bufrecent = [] +let s:buflinenos = {} +let s:bufferlistlite = {} +let s:bufliststatus = 0 +let s:keybuf = '' +let s:lineonclose = 3 +let s:currentposition = '' +let s:firstrun = 1 +let s:detail = 0 +augroup Tlistacom + autocmd! + au BufEnter * call updaterecent() + au BufLeave * call savelineno() +augroup END + +command! Bufferlist :call toggletop() +command! Bufferlistsw :call togglesw() + diff --git a/vim/dot_vim/plugin/tcomment.vim b/vim/dot_vim/plugin/tcomment.vim new file mode 100644 index 0000000..6eda6f4 --- /dev/null +++ b/vim/dot_vim/plugin/tcomment.vim @@ -0,0 +1,142 @@ +" tComment.vim -- An easily extensible & universal comment plugin +" @Author: Tom Link (micathom AT gmail com) +" @License: GPL (see http://www.gnu.org/licenses/gpl.txt) +" @Created: 27-Dez-2004. +" @Last Change: 2011-05-26. +" @Revision: 720 +" GetLatestVimScripts: 1173 1 tcomment.vim + +if &cp || exists('loaded_tcomment') + finish +endif +let loaded_tcomment = 205 + +if !exists("g:tcommentMapLeader1") + " g:tcommentMapLeader1 should be a shortcut that can be used with + " map, imap, vmap. + let g:tcommentMapLeader1 = '' +endif +if !exists("g:tcommentMapLeader2") + " g:tcommentMapLeader2 should be a shortcut that can be used with + " map, xmap. + let g:tcommentMapLeader2 = '_' +endif +if !exists("g:tcommentMapLeaderOp1") + let g:tcommentMapLeaderOp1 = 'gc' +endif +if !exists("g:tcommentMapLeaderOp2") + let g:tcommentMapLeaderOp2 = 'gC' +endif + + +" :display: :[range]TComment[!] ?ARGS... +" If there is a visual selection that begins and ends in the same line, +" then |:TCommentInline| is used instead. +" The optional range defaults to the current line. With a bang '!', +" always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TComment + \ keepjumps call tcomment#Comment(, , 'G', "", ) + +" :display: :[range]TCommentAs[!] commenttype ?ARGS... +" TCommentAs requires g:tcomment_{filetype} to be defined. +" With a bang '!', always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -complete=customlist,tcomment#Complete -range -nargs=+ TCommentAs + \ call tcomment#CommentAs(, , "", ) + +" :display: :[range]TCommentRight[!] ?ARGS... +" Comment the text to the right of the cursor. If a visual selection was +" made (be it block-wise or not), all lines are commented out at from +" the current cursor position downwards. +" With a bang '!', always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentRight + \ keepjumps call tcomment#Comment(, , 'R', "", ) + +" :display: :[range]TCommentBlock[!] ?ARGS... +" Comment as "block", e.g. use the {&ft}_block comment style. The +" commented text isn't indented or reformated. +" With a bang '!', always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentBlock + \ keepjumps call tcomment#Comment(, , 'B', "", ) + +" :display: :[range]TCommentInline[!] ?ARGS... +" Use the {&ft}_inline comment style. +" With a bang '!', always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentInline + \ keepjumps call tcomment#Comment(, , 'I', "", ) + +" :display: :[range]TCommentMaybeInline[!] ?ARGS... +" With a bang '!', always comment the line. +" +" ARGS... are either (see also |tcomment#Comment()|): +" 1. a list of key=value pairs +" 2. 1-2 values for: ?commentBegin, ?commentEnd +command! -bang -range -nargs=* -complete=customlist,tcomment#CompleteArgs TCommentMaybeInline + \ keepjumps call tcomment#Comment(, , 'i', "", ) + + + +if (g:tcommentMapLeader1 != '') + exec 'noremap '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' :TComment' + exec 'vnoremap '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' :TCommentMaybeInline' + exec 'inoremap '. g:tcommentMapLeader1 . g:tcommentMapLeader1 .' :TComment' + exec 'noremap '. g:tcommentMapLeader1 .'p m`vip:TComment``' + exec 'inoremap '. g:tcommentMapLeader1 .'p :norm! m`vip:TComment``' + exec 'noremap '. g:tcommentMapLeader1 .' :TComment ' + exec 'inoremap '. g:tcommentMapLeader1 .' :TComment ' + exec 'inoremap '. g:tcommentMapLeader1 .'r :TCommentRight' + exec 'noremap '. g:tcommentMapLeader1 .'r :TCommentRight' + exec 'vnoremap '. g:tcommentMapLeader1 .'i :TCommentInline' + exec 'vnoremap '. g:tcommentMapLeader1 .'r :TCommentRight' + exec 'noremap '. g:tcommentMapLeader1 .'b :TCommentBlock' + exec 'inoremap '. g:tcommentMapLeader1 .'b :TCommentBlock' + exec 'noremap '. g:tcommentMapLeader1 .'a :TCommentAs ' + exec 'inoremap '. g:tcommentMapLeader1 .'a :TCommentAs ' + exec 'noremap '. g:tcommentMapLeader1 .'n :TCommentAs =&ft ' + exec 'inoremap '. g:tcommentMapLeader1 .'n :TCommentAs =&ft ' + exec 'noremap '. g:tcommentMapLeader1 .'s :TCommentAs =&ft_' + exec 'inoremap '. g:tcommentMapLeader1 .'s :TCommentAs =&ft_' +endif +if (g:tcommentMapLeader2 != '') + exec 'noremap '. g:tcommentMapLeader2 .'_ :TComment' + exec 'xnoremap '. g:tcommentMapLeader2 .'_ :TCommentMaybeInline' + exec 'noremap '. g:tcommentMapLeader2 .'p vip:TComment' + exec 'noremap '. g:tcommentMapLeader2 .' :TComment ' + exec 'xnoremap '. g:tcommentMapLeader2 .'i :TCommentInline' + exec 'noremap '. g:tcommentMapLeader2 .'r :TCommentRight' + exec 'xnoremap '. g:tcommentMapLeader2 .'r :TCommentRight' + exec 'noremap '. g:tcommentMapLeader2 .'b :TCommentBlock' + exec 'noremap '. g:tcommentMapLeader2 .'a :TCommentAs ' + exec 'noremap '. g:tcommentMapLeader2 .'n :TCommentAs =&ft ' + exec 'noremap '. g:tcommentMapLeader2 .'s :TCommentAs =&ft_' +endif +if (g:tcommentMapLeaderOp1 != '') + exec 'nnoremap '. g:tcommentMapLeaderOp1 .' :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#Operatorg@' + exec 'nnoremap '. g:tcommentMapLeaderOp1 .'c :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLineg@$' + exec 'xnoremap '. g:tcommentMapLeaderOp1 .' :TCommentMaybeInline' +endif +if (g:tcommentMapLeaderOp2 != '') + exec 'nnoremap '. g:tcommentMapLeaderOp2 .' :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorAnywayg@' + exec 'nnoremap '. g:tcommentMapLeaderOp2 .'c :let w:tcommentPos = getpos(".") \| set opfunc=tcomment#OperatorLineAnywayg@$' + exec 'xnoremap '. g:tcommentMapLeaderOp2 .' :TCommentMaybeInline' +endif + diff --git a/vim/dot_vim/syntax/nerdtree.vim b/vim/dot_vim/syntax/nerdtree.vim new file mode 100644 index 0000000..636d2af --- /dev/null +++ b/vim/dot_vim/syntax/nerdtree.vim @@ -0,0 +1,88 @@ +let s:tree_up_dir_line = '.. (up a dir)' +"NERDTreeFlags are syntax items that should be invisible, but give clues as to +"how things should be highlighted +syn match NERDTreeFlag #\~# +syn match NERDTreeFlag #\[RO\]# + +"highlighting for the .. (up dir) line at the top of the tree +execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#" + +"highlighting for the ~/+ symbols for the directory nodes +syn match NERDTreeClosable #\~\<# +syn match NERDTreeClosable #\~\.# +syn match NERDTreeOpenable #+\<# +syn match NERDTreeOpenable #+\.#he=e-1 + +"highlighting for the tree structural parts +syn match NERDTreePart #|# +syn match NERDTreePart #`# +syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart + +"quickhelp syntax elements +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1 +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1 +syn match NERDTreeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=NERDTreeFlag +syn match NERDTreeToggleOn #".*(on)#hs=e-2,he=e-1 contains=NERDTreeHelpKey +syn match NERDTreeToggleOff #".*(off)#hs=e-3,he=e-1 contains=NERDTreeHelpKey +syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3 +syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeFlag,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand + +"highlighting for readonly files +syn match NERDTreeRO #.*\[RO\]#hs=s+2 contains=NERDTreeFlag,NERDTreeBookmark,NERDTreePart,NERDTreePartFile + +"highlighting for sym links +syn match NERDTreeLink #[^-| `].* -> # contains=NERDTreeBookmark,NERDTreeOpenable,NERDTreeClosable,NERDTreeDirSlash + +"highlighing for directory nodes and file nodes +syn match NERDTreeDirSlash #/# +syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeDirSlash,NERDTreeOpenable,NERDTreeClosable +syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark +syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile +syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile +syn match NERDTreeCWD #^[# +syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader + +if exists("g:NERDChristmasTree") && g:NERDChristmasTree + hi def link NERDTreePart Special + hi def link NERDTreePartFile Type + hi def link NERDTreeFile Normal + hi def link NERDTreeExecFile Title + hi def link NERDTreeDirSlash Identifier + hi def link NERDTreeClosable Type +else + hi def link NERDTreePart Normal + hi def link NERDTreePartFile Normal + hi def link NERDTreeFile Normal + hi def link NERDTreeClosable Title +endif + +hi def link NERDTreeBookmarksHeader statement +hi def link NERDTreeBookmarksLeader ignore +hi def link NERDTreeBookmarkName Identifier +hi def link NERDTreeBookmark normal + +hi def link NERDTreeHelp String +hi def link NERDTreeHelpKey Identifier +hi def link NERDTreeHelpCommand Identifier +hi def link NERDTreeHelpTitle Macro +hi def link NERDTreeToggleOn Question +hi def link NERDTreeToggleOff WarningMsg + +hi def link NERDTreeDir Directory +hi def link NERDTreeUp Directory +hi def link NERDTreeCWD Statement +hi def link NERDTreeLink Macro +hi def link NERDTreeOpenable Title +hi def link NERDTreeFlag ignore +hi def link NERDTreeRO WarningMsg +hi def link NERDTreeBookmark Statement + +hi def link NERDTreeCurrentNode Search diff --git a/vim/dot_vimrc b/vim/dot_vimrc index 31b672d..6bf6ada 100644 --- a/vim/dot_vimrc +++ b/vim/dot_vimrc @@ -21,15 +21,20 @@ set hls "Highlights the line the cursor is on set cursorline +:hi CursorLine cterm=NONE ctermbg=darkred guibg=darkred guifg=white +"Toggle highlighting with \hr (highlight row) +nnoremap hr :set cursorline! "enable line numbers set nu "Toggle Line numbers with Ctrl+N double tap nmap :set invnumber +nmap ln :set invnumber "Toggle line wrap with Ctrl+L double tap nmap :set wrap! +nmap lw :set wrap! "Allows filetype detection filetype on @@ -48,6 +53,12 @@ map j map l map h +" map Shift+U to redo +map + +" Buffet shortcut +nnoremap :Bufferlist + "CTags List nnoremap :TlistToggle let Tlist_Exit_OnlyWindow=1 @@ -64,10 +75,10 @@ inoremap inoremap " Stupid shift key fixes -cmap W w +"cmap W w cmap WQ wq -cmap wQ wq -cmap Q q +cmap Wq wq +"cmap Q q "clearing highlighted search nmap / :nohlsearch