--- a/vim/bundle/nerdcommenter/plugin/NERD_commenter.vim Mon Nov 22 14:44:00 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3146 +0,0 @@
-" ============================================================================
-" File: NERD_commenter.vim
-" Description: vim global plugin that provides easy code commenting
-" Maintainer: Martin Grenfell <martin_grenfell at msn dot com>
-" Version: 2.2.2
-" Last Change: 30th March, 2008
-" 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.
-"
-" ============================================================================
-
-" Section: script init stuff {{{1
-if exists("loaded_nerd_comments")
- finish
-endif
-if v:version < 700
- echoerr "NERDCommenter: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
- finish
-endif
-let loaded_nerd_comments = 1
-
-" Function: s:InitVariable() function {{{2
-" This function is used to initialise a given variable to a given value. The
-" variable is only initialised if it does not exist prior
-"
-" Args:
-" -var: the name of the var to be initialised
-" -value: the value to initialise var to
-"
-" Returns:
-" 1 if the var is set, 0 otherwise
-function s:InitVariable(var, value)
- if !exists(a:var)
- exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
- return 1
- endif
- return 0
-endfunction
-
-" Section: space string init{{{2
-" When putting spaces after the left delim and before the right we use
-" s:spaceStr for the space char. This way we can make it add anything after
-" the left and before the right by modifying this variable
-let s:spaceStr = ' '
-let s:lenSpaceStr = strlen(s:spaceStr)
-
-" Section: variable init calls {{{2
-call s:InitVariable("g:NERDAllowAnyVisualDelims", 1)
-call s:InitVariable("g:NERDBlockComIgnoreEmpty", 0)
-call s:InitVariable("g:NERDCommentWholeLinesInVMode", 0)
-call s:InitVariable("g:NERDCompactSexyComs", 0)
-call s:InitVariable("g:NERDCreateDefaultMappings", 1)
-call s:InitVariable("g:NERDDefaultNesting", 1)
-call s:InitVariable("g:NERDMenuMode", 3)
-call s:InitVariable("g:NERDLPlace", "[>")
-call s:InitVariable("g:NERDUsePlaceHolders", 1)
-call s:InitVariable("g:NERDRemoveAltComs", 1)
-call s:InitVariable("g:NERDRemoveExtraSpaces", 1)
-call s:InitVariable("g:NERDRPlace", "<]")
-call s:InitVariable("g:NERDSpaceDelims", 0)
-call s:InitVariable("g:NERDDelimiterRequests", 1)
-
-
-
-let s:NERDFileNameEscape="[]#*$%'\" ?`!&();<>\\"
-
-" Section: Comment mapping functions, autocommands and commands {{{1
-" ============================================================================
-" Section: Comment enabler autocommands {{{2
-" ============================================================================
-
-augroup commentEnablers
-
- "if the user enters a buffer or reads a buffer then we gotta set up
- "the comment delimiters for that new filetype
- autocmd BufEnter,BufRead * :call s:SetUpForNewFiletype(&filetype, 0)
-
- "if the filetype of a buffer changes, force the script to reset the
- "delims for the buffer
- autocmd Filetype * :call s:SetUpForNewFiletype(&filetype, 1)
-augroup END
-
-
-" Function: s:SetUpForNewFiletype(filetype) function {{{2
-" This function is responsible for setting up buffer scoped variables for the
-" given filetype.
-"
-" These variables include the comment delimiters for the given filetype and calls
-" MapDelimiters or MapDelimitersWithAlternative passing in these delimiters.
-"
-" Args:
-" -filetype: the filetype to set delimiters for
-" -forceReset: 1 if the delimiters should be reset if they have already be
-" set for this buffer.
-"
-function s:SetUpForNewFiletype(filetype, forceReset)
- "if we have already set the delimiters for this buffer then dont go thru
- "it again
- if !a:forceReset && exists("b:NERDLeft") && b:NERDLeft != ''
- return
- endif
-
- let b:NERDSexyComMarker = ''
-
- "check the filetype against all known filetypes to see if we have
- "hardcoded the comment delimiters to use
- if a:filetype ==? ""
- call s:MapDelimiters('', '')
- elseif a:filetype ==? "aap"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "abc"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "acedb"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "actionscript"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "ada"
- call s:MapDelimitersWithAlternative('--','', '-- ', '')
- elseif a:filetype ==? "ahdl"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "ahk"
- call s:MapDelimitersWithAlternative(';', '', '/*', '*/')
- elseif a:filetype ==? "amiga"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "aml"
- call s:MapDelimiters('/*', '')
- elseif a:filetype ==? "ampl"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "apache"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "apachestyle"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "asciidoc"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "applescript"
- call s:MapDelimitersWithAlternative('--', '', '(*', '*)')
- elseif a:filetype ==? "asm68k"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "asm"
- call s:MapDelimitersWithAlternative(';', '', '#', '')
- elseif a:filetype ==? "asn"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "aspvbs"
- call s:MapDelimiters('''', '')
- elseif a:filetype ==? "asterisk"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "asy"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "atlas"
- call s:MapDelimiters('C','$')
- elseif a:filetype ==? "autohotkey"
- call s:MapDelimiters(';','')
- elseif a:filetype ==? "autoit"
- call s:MapDelimiters(';','')
- elseif a:filetype ==? "ave"
- call s:MapDelimiters("'",'')
- elseif a:filetype ==? "awk"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "basic"
- call s:MapDelimitersWithAlternative("'",'', 'REM ', '')
- elseif a:filetype ==? "bbx"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "bc"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "bib"
- call s:MapDelimiters('%','')
- elseif a:filetype ==? "bindzone"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "bst"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "btm"
- call s:MapDelimiters('::', '')
- elseif a:filetype ==? "caos"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "calibre"
- call s:MapDelimiters('//','')
- elseif a:filetype ==? "catalog"
- call s:MapDelimiters('--','--')
- elseif a:filetype ==? "c"
- call s:MapDelimitersWithAlternative('/*','*/', '//', '')
- elseif a:filetype ==? "cfg"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "cg"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "ch"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "cl"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "clean"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "clipper"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "clojure"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "cmake"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "conkyrc"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "cpp"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "crontab"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "cs"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "csp"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "cterm"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "cucumber"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "cvs"
- call s:MapDelimiters('CVS:','')
- elseif a:filetype ==? "d"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "dcl"
- call s:MapDelimiters('$!', '')
- elseif a:filetype ==? "dakota"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "debcontrol"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "debsources"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "def"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "desktop"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "dhcpd"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "diff"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "django"
- call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
- elseif a:filetype ==? "docbk"
- call s:MapDelimiters('<!--', '-->')
- elseif a:filetype ==? "dns"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "dosbatch"
- call s:MapDelimitersWithAlternative('REM ','', '::', '')
- elseif a:filetype ==? "dosini"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "dot"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "dracula"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "dsl"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "dtml"
- call s:MapDelimiters('<dtml-comment>','</dtml-comment>')
- elseif a:filetype ==? "dylan"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? 'ebuild'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ecd"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'eclass'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "eiffel"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "elf"
- call s:MapDelimiters("'", '')
- elseif a:filetype ==? "elmfilt"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "erlang"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "eruby"
- call s:MapDelimitersWithAlternative('<%#', '%>', '<!--', '-->')
- elseif a:filetype ==? "expect"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "exports"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "factor"
- call s:MapDelimitersWithAlternative('! ', '', '!# ', '')
- elseif a:filetype ==? "fgl"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "focexec"
- call s:MapDelimiters('-*', '')
- elseif a:filetype ==? "form"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "foxpro"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "fstab"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "fvwm"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "fx"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "gams"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "gdb"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "gdmo"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "geek"
- call s:MapDelimiters('GEEK_COMMENT:', '')
- elseif a:filetype ==? "genshi"
- call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
- elseif a:filetype ==? "gentoo-conf-d"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "gentoo-env-d"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "gentoo-init-d"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "gentoo-make-conf"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'gentoo-package-keywords'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'gentoo-package-mask'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'gentoo-package-use'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'gitcommit'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? 'gitconfig'
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? 'gitrebase'
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "gnuplot"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "groovy"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "gtkrc"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "haskell"
- call s:MapDelimitersWithAlternative('{-','-}', '--', '')
- elseif a:filetype ==? "hb"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "h"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "haml"
- call s:MapDelimitersWithAlternative('-#', '', '/', '')
- elseif a:filetype ==? "hercules"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "hog"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "hostsaccess"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "htmlcheetah"
- call s:MapDelimiters('##','')
- elseif a:filetype ==? "htmldjango"
- call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
- elseif a:filetype ==? "htmlos"
- call s:MapDelimiters('#','/#')
- elseif a:filetype ==? "ia64"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "icon"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "idlang"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "idl"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "inform"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "inittab"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ishd"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "iss"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "ist"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "java"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "javacc"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "javascript"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype == "javascript.jquery"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "jess"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "jgraph"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "jproperties"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "jsp"
- call s:MapDelimiters('<%--', '--%>')
- elseif a:filetype ==? "kix"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "kscript"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "lace"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "ldif"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "lilo"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "lilypond"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "liquid"
- call s:MapDelimiters('{%', '%}')
- elseif a:filetype ==? "lisp"
- call s:MapDelimitersWithAlternative(';','', '#|', '|#')
- elseif a:filetype ==? "llvm"
- call s:MapDelimiters(';','')
- elseif a:filetype ==? "lotos"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "lout"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "lprolog"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "lscript"
- call s:MapDelimiters("'", '')
- elseif a:filetype ==? "lss"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "lua"
- call s:MapDelimitersWithAlternative('--','', '--[[', ']]')
- elseif a:filetype ==? "lynx"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "lytex"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "mail"
- call s:MapDelimiters('> ','')
- elseif a:filetype ==? "mako"
- call s:MapDelimiters('##', '')
- elseif a:filetype ==? "man"
- call s:MapDelimiters('."', '')
- elseif a:filetype ==? "map"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "maple"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "markdown"
- call s:MapDelimiters('<!--', '-->')
- elseif a:filetype ==? "masm"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "mason"
- call s:MapDelimiters('<% #', '%>')
- elseif a:filetype ==? "master"
- call s:MapDelimiters('$', '')
- elseif a:filetype ==? "matlab"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "mel"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "mib"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "mkd"
- call s:MapDelimiters('>', '')
- elseif a:filetype ==? "mma"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "model"
- call s:MapDelimiters('$','$')
- elseif a:filetype =~ "moduala."
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "modula2"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "modula3"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "monk"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "mush"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "named"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "nasm"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "nastran"
- call s:MapDelimiters('$', '')
- elseif a:filetype ==? "natural"
- call s:MapDelimiters('/*', '')
- elseif a:filetype ==? "ncf"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "newlisp"
- call s:MapDelimiters(';','')
- elseif a:filetype ==? "nroff"
- call s:MapDelimiters('\"', '')
- elseif a:filetype ==? "nsis"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ntp"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "objc"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "objcpp"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "objj"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "ocaml"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "occam"
- call s:MapDelimiters('--','')
- elseif a:filetype ==? "omlet"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "omnimark"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "openroad"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "opl"
- call s:MapDelimiters("REM", "")
- elseif a:filetype ==? "ora"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ox"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "pascal"
- call s:MapDelimitersWithAlternative('{','}', '(*', '*)')
- elseif a:filetype ==? "patran"
- call s:MapDelimitersWithAlternative('$','','/*', '*/')
- elseif a:filetype ==? "pcap"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "pccts"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "pdf"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "pfmain"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "php"
- call s:MapDelimitersWithAlternative('//','','/*', '*/')
- elseif a:filetype ==? "pic"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "pike"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "pilrc"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "pine"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "plm"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "plsql"
- call s:MapDelimitersWithAlternative('--', '', '/*', '*/')
- elseif a:filetype ==? "po"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "postscr"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "pov"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "povini"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "ppd"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "ppwiz"
- call s:MapDelimiters(';;', '')
- elseif a:filetype ==? "processing"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "prolog"
- call s:MapDelimitersWithAlternative('%','','/*','*/')
- elseif a:filetype ==? "ps1"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "psf"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ptcap"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "python"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "radiance"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "ratpoison"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "r"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "rc"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "rebol"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "registry"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "remind"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "resolv"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "rgb"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "rib"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "robots"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "sa"
- call s:MapDelimiters('--','')
- elseif a:filetype ==? "samba"
- call s:MapDelimitersWithAlternative(';','', '#', '')
- elseif a:filetype ==? "sass"
- call s:MapDelimitersWithAlternative('//','', '/*', '')
- elseif a:filetype ==? "sather"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "scala"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "scilab"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "scsh"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "sed"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "sgmldecl"
- call s:MapDelimiters('--','--')
- elseif a:filetype ==? "sgmllnx"
- call s:MapDelimiters('<!--','-->')
- elseif a:filetype ==? "sicad"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "simula"
- call s:MapDelimitersWithAlternative('%', '', '--', '')
- elseif a:filetype ==? "sinda"
- call s:MapDelimiters('$', '')
- elseif a:filetype ==? "skill"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "slang"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "slice"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "slrnrc"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "sm"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "smarty"
- call s:MapDelimiters('{*', '*}')
- elseif a:filetype ==? "smil"
- call s:MapDelimiters('<!','>')
- elseif a:filetype ==? "smith"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "sml"
- call s:MapDelimiters('(*','*)')
- elseif a:filetype ==? "snnsnet"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "snnspat"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "snnsres"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "snobol4"
- call s:MapDelimiters('*', '')
- elseif a:filetype ==? "spec"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "specman"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "spectre"
- call s:MapDelimitersWithAlternative('//', '', '*', '')
- elseif a:filetype ==? "spice"
- call s:MapDelimiters('$', '')
- elseif a:filetype ==? "sql"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "sqlforms"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "sqlj"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "sqr"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "squid"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "st"
- call s:MapDelimiters('"','')
- elseif a:filetype ==? "stp"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "systemverilog"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "tads"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "tags"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "tak"
- call s:MapDelimiters('$', '')
- elseif a:filetype ==? "tasm"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "tcl"
- call s:MapDelimiters('#','')
- elseif a:filetype ==? "texinfo"
- call s:MapDelimiters("@c ", "")
- elseif a:filetype ==? "texmf"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "tf"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "tidy"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "tli"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "trasys"
- call s:MapDelimiters("$", "")
- elseif a:filetype ==? "tsalt"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "tsscl"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "tssgm"
- call s:MapDelimiters("comment = '","'")
- elseif a:filetype ==? "txt2tags"
- call s:MapDelimiters('%','')
- elseif a:filetype ==? "uc"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "uil"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "vb"
- call s:MapDelimiters("'","")
- elseif a:filetype ==? "velocity"
- call s:MapDelimitersWithAlternative("##","", '#*', '*#')
- elseif a:filetype ==? "vera"
- call s:MapDelimitersWithAlternative('/*','*/','//','')
- elseif a:filetype ==? "verilog"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "verilog_systemverilog"
- call s:MapDelimitersWithAlternative('//','', '/*','*/')
- elseif a:filetype ==? "vgrindefs"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "vhdl"
- call s:MapDelimiters('--', '')
- elseif a:filetype ==? "vimperator"
- call s:MapDelimiters('"','')
- elseif a:filetype ==? "virata"
- call s:MapDelimiters('%', '')
- elseif a:filetype ==? "vrml"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "vsejcl"
- call s:MapDelimiters('/*', '')
- elseif a:filetype ==? "webmacro"
- call s:MapDelimiters('##', '')
- elseif a:filetype ==? "wget"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "Wikipedia"
- call s:MapDelimiters('<!--','-->')
- elseif a:filetype ==? "winbatch"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "wml"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "wvdial"
- call s:MapDelimiters(';', '')
- elseif a:filetype ==? "xdefaults"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "xkb"
- call s:MapDelimiters('//', '')
- elseif a:filetype ==? "xmath"
- call s:MapDelimiters('#', '')
- elseif a:filetype ==? "xpm2"
- call s:MapDelimiters('!', '')
- elseif a:filetype ==? "xquery"
- call s:MapDelimiters('(:',':)')
- elseif a:filetype ==? "z8a"
- call s:MapDelimiters(';', '')
-
- else
-
- "extract the delims from &commentstring
- let left= substitute(&commentstring, '\([^ \t]*\)\s*%s.*', '\1', '')
- let right= substitute(&commentstring, '.*%s\s*\(.*\)', '\1', 'g')
- call s:MapDelimiters(left,right)
-
- endif
-endfunction
-
-" Function: s:MapDelimiters(left, right) function {{{2
-" This function is a wrapper for s:MapDelimiters(left, right, leftAlt, rightAlt, useAlt) and is called when there
-" is no alternative comment delimiters for the current filetype
-"
-" Args:
-" -left: the left comment delimiter
-" -right: the right comment delimiter
-function s:MapDelimiters(left, right)
- call s:MapDelimitersWithAlternative(a:left, a:right, "", "")
-endfunction
-
-" Function: s:MapDelimitersWithAlternative(left, right, leftAlt, rightAlt) function {{{2
-" this function sets up the comment delimiter buffer variables
-"
-" Args:
-" -left: the string defining the comment start delimiter
-" -right: the string defining the comment end delimiter
-" -leftAlt: the string for the alternative comment style defining the comment start delimiter
-" -rightAlt: the string for the alternative comment style defining the comment end delimiter
-function s:MapDelimitersWithAlternative(left, right, leftAlt, rightAlt)
- if !exists('g:NERD_' . &filetype . '_alt_style')
- let b:NERDLeft = a:left
- let b:NERDRight = a:right
- let b:NERDLeftAlt = a:leftAlt
- let b:NERDRightAlt = a:rightAlt
- else
- let b:NERDLeft = a:leftAlt
- let b:NERDRight = a:rightAlt
- let b:NERDLeftAlt = a:left
- let b:NERDRightAlt = a:right
- endif
-endfunction
-
-" Function: s:SwitchToAlternativeDelimiters(printMsgs) function {{{2
-" This function is used to swap the delimiters that are being used to the
-" alternative delimiters for that filetype. For example, if a c++ file is
-" being edited and // comments are being used, after this function is called
-" /**/ comments will be used.
-"
-" Args:
-" -printMsgs: if this is 1 then a message is echoed to the user telling them
-" if this function changed the delimiters or not
-function s:SwitchToAlternativeDelimiters(printMsgs)
- "if both of the alternative delimiters are empty then there is no
- "alternative comment style so bail out
- if b:NERDLeftAlt == "" && b:NERDRightAlt == ""
- if a:printMsgs
- call s:NerdEcho("Cannot use alternative delimiters, none are specified", 0)
- endif
- return 0
- endif
-
- "save the current delimiters
- let tempLeft = b:NERDLeft
- let tempRight = b:NERDRight
-
- "swap current delimiters for alternative
- let b:NERDLeft = b:NERDLeftAlt
- let b:NERDRight = b:NERDRightAlt
-
- "set the previously current delimiters to be the new alternative ones
- let b:NERDLeftAlt = tempLeft
- let b:NERDRightAlt = tempRight
-
- "tell the user what comment delimiters they are now using
- if a:printMsgs
- let leftNoEsc = b:NERDLeft
- let rightNoEsc = b:NERDRight
- call s:NerdEcho("Now using " . leftNoEsc . " " . rightNoEsc . " to delimit comments", 1)
- endif
-
- return 1
-endfunction
-
-" Section: Comment delimiter add/removal functions {{{1
-" ============================================================================
-" Function: s:AppendCommentToLine(){{{2
-" This function appends comment delimiters at the EOL and places the cursor in
-" position to start typing the comment
-function s:AppendCommentToLine()
- let left = s:GetLeft(0,1,0)
- let right = s:GetRight(0,1,0)
-
- " get the len of the right delim
- let lenRight = strlen(right)
-
- let isLineEmpty = strlen(getline(".")) == 0
- let insOrApp = (isLineEmpty==1 ? 'i' : 'A')
-
- "stick the delimiters down at the end of the line. We have to format the
- "comment with spaces as appropriate
- execute ":normal! " . insOrApp . (isLineEmpty ? '' : ' ') . left . right . " "
-
- " if there is a right delimiter then we gotta move the cursor left
- " by the len of the right delimiter so we insert between the delimiters
- if lenRight > 0
- let leftMoveAmount = lenRight
- execute ":normal! " . leftMoveAmount . "h"
- endif
- startinsert
-endfunction
-
-" Function: s:CommentBlock(top, bottom, lSide, rSide, forceNested ) {{{2
-" This function is used to comment out a region of code. This region is
-" specified as a bounding box by arguments to the function.
-"
-" Args:
-" -top: the line number for the top line of code in the region
-" -bottom: the line number for the bottom line of code in the region
-" -lSide: the column number for the left most column in the region
-" -rSide: the column number for the right most column in the region
-" -forceNested: a flag indicating whether comments should be nested
-function s:CommentBlock(top, bottom, lSide, rSide, forceNested )
- " we need to create local copies of these arguments so we can modify them
- let top = a:top
- let bottom = a:bottom
- let lSide = a:lSide
- let rSide = a:rSide
-
- "if the top or bottom line starts with tabs we have to adjust the left and
- "right boundaries so that they are set as though the tabs were spaces
- let topline = getline(top)
- let bottomline = getline(bottom)
- if s:HasLeadingTabs(topline, bottomline)
-
- "find out how many tabs are in the top line and adjust the left
- "boundary accordingly
- let numTabs = s:NumberOfLeadingTabs(topline)
- if lSide < numTabs
- let lSide = &ts * lSide
- else
- let lSide = (lSide - numTabs) + (&ts * numTabs)
- endif
-
- "find out how many tabs are in the bottom line and adjust the right
- "boundary accordingly
- let numTabs = s:NumberOfLeadingTabs(bottomline)
- let rSide = (rSide - numTabs) + (&ts * numTabs)
- endif
-
- "we must check that bottom IS actually below top, if it is not then we
- "swap top and bottom. Similarly for left and right.
- if bottom < top
- let temp = top
- let top = bottom
- let bottom = top
- endif
- if rSide < lSide
- let temp = lSide
- let lSide = rSide
- let rSide = temp
- endif
-
- "if the current delimiters arent multipart then we will switch to the
- "alternative delims (if THEY are) as the comment will be better and more
- "accurate with multipart delims
- let switchedDelims = 0
- if !s:Multipart() && g:NERDAllowAnyVisualDelims && s:AltMultipart()
- let switchedDelims = 1
- call s:SwitchToAlternativeDelimiters(0)
- endif
-
- "start the commenting from the top and keep commenting till we reach the
- "bottom
- let currentLine=top
- while currentLine <= bottom
-
- "check if we are allowed to comment this line
- if s:CanCommentLine(a:forceNested, currentLine)
-
- "convert the leading tabs into spaces
- let theLine = getline(currentLine)
- let lineHasLeadTabs = s:HasLeadingTabs(theLine)
- if lineHasLeadTabs
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- endif
-
- "dont comment lines that begin after the right boundary of the
- "block unless the user has specified to do so
- if theLine !~ '^ \{' . rSide . '\}' || !g:NERDBlockComIgnoreEmpty
-
- "attempt to place the cursor in on the left of the boundary box,
- "then check if we were successful, if not then we cant comment this
- "line
- call setline(currentLine, theLine)
- if s:CanPlaceCursor(currentLine, lSide)
-
- let leftSpaced = s:GetLeft(0,1,0)
- let rightSpaced = s:GetRight(0,1,0)
-
- "stick the left delimiter down
- let theLine = strpart(theLine, 0, lSide-1) . leftSpaced . strpart(theLine, lSide-1)
-
- if s:Multipart()
- "stick the right delimiter down
- let theLine = strpart(theLine, 0, rSide+strlen(leftSpaced)) . rightSpaced . strpart(theLine, rSide+strlen(leftSpaced))
-
- let firstLeftDelim = s:FindDelimiterIndex(b:NERDLeft, theLine)
- let lastRightDelim = s:LastIndexOfDelim(b:NERDRight, theLine)
-
- if firstLeftDelim != -1 && lastRightDelim != -1
- let searchStr = strpart(theLine, 0, lastRightDelim)
- let searchStr = strpart(searchStr, firstLeftDelim+strlen(b:NERDLeft))
-
- "replace the outter most delims in searchStr with
- "place-holders
- let theLineWithPlaceHolders = s:ReplaceDelims(b:NERDLeft, b:NERDRight, g:NERDLPlace, g:NERDRPlace, searchStr)
-
- "add the right delimiter onto the line
- let theLine = strpart(theLine, 0, firstLeftDelim+strlen(b:NERDLeft)) . theLineWithPlaceHolders . strpart(theLine, lastRightDelim)
- endif
- endif
- endif
- endif
-
- "restore tabs if needed
- if lineHasLeadTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
-
- call setline(currentLine, theLine)
- endif
-
- let currentLine = currentLine + 1
- endwhile
-
- "if we switched delims then we gotta go back to what they were before
- if switchedDelims == 1
- call s:SwitchToAlternativeDelimiters(0)
- endif
-endfunction
-
-" Function: s:CommentLines(forceNested, alignLeft, alignRight, firstLine, lastLine) {{{2
-" This function comments a range of lines.
-"
-" Args:
-" -forceNested: a flag indicating whether the called is requesting the comment
-" to be nested if need be
-" -align: should be "left" or "both" or "none"
-" -firstLine/lastLine: the top and bottom lines to comment
-function s:CommentLines(forceNested, align, firstLine, lastLine)
- " we need to get the left and right indexes of the leftmost char in the
- " block of of lines and the right most char so that we can do alignment of
- " the delimiters if the user has specified
- let leftAlignIndx = s:LeftMostIndx(a:forceNested, 0, a:firstLine, a:lastLine)
- let rightAlignIndx = s:RightMostIndx(a:forceNested, 0, a:firstLine, a:lastLine)
-
- " gotta add the length of the left delimiter onto the rightAlignIndx cos
- " we'll be adding a left delim to the line
- let rightAlignIndx = rightAlignIndx + strlen(s:GetLeft(0,1,0))
-
- " now we actually comment the lines. Do it line by line
- let currentLine = a:firstLine
- while currentLine <= a:lastLine
-
- " get the next line, check commentability and convert spaces to tabs
- let theLine = getline(currentLine)
- let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- if s:CanCommentLine(a:forceNested, currentLine)
- "if the user has specified forceNesting then we check to see if we
- "need to switch delimiters for place-holders
- if a:forceNested && g:NERDUsePlaceHolders
- let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
- endif
-
- " find out if the line is commented using normal delims and/or
- " alternate ones
- let isCommented = s:IsCommented(b:NERDLeft, b:NERDRight, theLine) || s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine)
-
- " check if we can comment this line
- if !isCommented || g:NERDUsePlaceHolders || s:Multipart()
- if a:align == "left" || a:align == "both"
- let theLine = s:AddLeftDelimAligned(s:GetLeft(0,1,0), theLine, leftAlignIndx)
- else
- let theLine = s:AddLeftDelim(s:GetLeft(0,1,0), theLine)
- endif
- if a:align == "both"
- let theLine = s:AddRightDelimAligned(s:GetRight(0,1,0), theLine, rightAlignIndx)
- else
- let theLine = s:AddRightDelim(s:GetRight(0,1,0), theLine)
- endif
- endif
- endif
-
- " restore leading tabs if appropriate
- if lineHasLeadingTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
-
- " we are done with this line
- call setline(currentLine, theLine)
- let currentLine = currentLine + 1
- endwhile
-
-endfunction
-
-" Function: s:CommentLinesMinimal(firstLine, lastLine) {{{2
-" This function comments a range of lines in a minimal style. I
-"
-" Args:
-" -firstLine/lastLine: the top and bottom lines to comment
-function s:CommentLinesMinimal(firstLine, lastLine)
- "check that minimal comments can be done on this filetype
- if !s:HasMultipartDelims()
- throw 'NERDCommenter.Delimiters exception: Minimal comments can only be used for filetypes that have multipart delimiters'
- endif
-
- "if we need to use place holders for the comment, make sure they are
- "enabled for this filetype
- if !g:NERDUsePlaceHolders && s:DoesBlockHaveMultipartDelim(a:firstLine, a:lastLine)
- throw 'NERDCommenter.Settings exception: Placeoholders are required but disabled.'
- endif
-
- "get the left and right delims to smack on
- let left = s:GetSexyComLeft(g:NERDSpaceDelims,0)
- let right = s:GetSexyComRight(g:NERDSpaceDelims,0)
-
- "make sure all multipart delims on the lines are replaced with
- "placeholders to prevent illegal syntax
- let currentLine = a:firstLine
- while(currentLine <= a:lastLine)
- let theLine = getline(currentLine)
- let theLine = s:ReplaceDelims(left, right, g:NERDLPlace, g:NERDRPlace, theLine)
- call setline(currentLine, theLine)
- let currentLine = currentLine + 1
- endwhile
-
- "add the delim to the top line
- let theLine = getline(a:firstLine)
- let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- let theLine = s:AddLeftDelim(left, theLine)
- if lineHasLeadingTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:firstLine, theLine)
-
- "add the delim to the bottom line
- let theLine = getline(a:lastLine)
- let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- let theLine = s:AddRightDelim(right, theLine)
- if lineHasLeadingTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:lastLine, theLine)
-endfunction
-
-" Function: s:CommentLinesSexy(topline, bottomline) function {{{2
-" This function is used to comment lines in the 'Sexy' style. eg in c:
-" /*
-" * This is a sexy comment
-" */
-" Args:
-" -topline: the line num of the top line in the sexy comment
-" -bottomline: the line num of the bottom line in the sexy comment
-function s:CommentLinesSexy(topline, bottomline)
- let left = s:GetSexyComLeft(0, 0)
- let right = s:GetSexyComRight(0, 0)
-
- "check if we can do a sexy comment with the available delimiters
- if left == -1 || right == -1
- throw 'NERDCommenter.Delimiters exception: cannot perform sexy comments with available delimiters.'
- endif
-
- "make sure the lines arent already commented sexually
- if !s:CanSexyCommentLines(a:topline, a:bottomline)
- throw 'NERDCommenter.Nesting exception: cannot nest sexy comments'
- endif
-
-
- let sexyComMarker = s:GetSexyComMarker(0,0)
- let sexyComMarkerSpaced = s:GetSexyComMarker(1,0)
-
-
- " we jam the comment as far to the right as possible
- let leftAlignIndx = s:LeftMostIndx(1, 1, a:topline, a:bottomline)
-
- "check if we should use the compact style i.e that the left/right
- "delimiters should appear on the first and last lines of the code and not
- "on separate lines above/below the first/last lines of code
- if g:NERDCompactSexyComs
- let spaceString = (g:NERDSpaceDelims ? s:spaceStr : '')
-
- "comment the top line
- let theLine = getline(a:topline)
- let lineHasTabs = s:HasLeadingTabs(theLine)
- if lineHasTabs
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- endif
- let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
- let theLine = s:AddLeftDelimAligned(left . spaceString, theLine, leftAlignIndx)
- if lineHasTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:topline, theLine)
-
- "comment the bottom line
- if a:bottomline != a:topline
- let theLine = getline(a:bottomline)
- let lineHasTabs = s:HasLeadingTabs(theLine)
- if lineHasTabs
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- endif
- let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
- endif
- let theLine = s:AddRightDelim(spaceString . right, theLine)
- if lineHasTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:bottomline, theLine)
- else
-
- " add the left delimiter one line above the lines that are to be commented
- call cursor(a:topline, 1)
- execute 'normal! O'
- let theLine = repeat(' ', leftAlignIndx) . left
-
- " Make sure tabs are respected
- if !&expandtab
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:topline, theLine)
-
- " add the right delimiter after bottom line (we have to add 1 cos we moved
- " the lines down when we added the left delim
- call cursor(a:bottomline+1, 1)
- execute 'normal! o'
- let theLine = repeat(' ', leftAlignIndx) . repeat(' ', strlen(left)-strlen(sexyComMarker)) . right
-
- " Make sure tabs are respected
- if !&expandtab
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
- call setline(a:bottomline+2, theLine)
-
- endif
-
- " go thru each line adding the sexyComMarker marker to the start of each
- " line in the appropriate place to align them with the comment delims
- let currentLine = a:topline+1
- while currentLine <= a:bottomline + !g:NERDCompactSexyComs
- " get the line and convert the tabs to spaces
- let theLine = getline(currentLine)
- let lineHasTabs = s:HasLeadingTabs(theLine)
- if lineHasTabs
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- endif
-
- let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
-
- " add the sexyComMarker
- let theLine = repeat(' ', leftAlignIndx) . repeat(' ', strlen(left)-strlen(sexyComMarker)) . sexyComMarkerSpaced . strpart(theLine, leftAlignIndx)
-
- if lineHasTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
-
-
- " set the line and move onto the next one
- call setline(currentLine, theLine)
- let currentLine = currentLine + 1
- endwhile
-
-endfunction
-
-" Function: s:CommentLinesToggle(forceNested, firstLine, lastLine) {{{2
-" Applies "toggle" commenting to the given range of lines
-"
-" Args:
-" -forceNested: a flag indicating whether the called is requesting the comment
-" to be nested if need be
-" -firstLine/lastLine: the top and bottom lines to comment
-function s:CommentLinesToggle(forceNested, firstLine, lastLine)
- let currentLine = a:firstLine
- while currentLine <= a:lastLine
-
- " get the next line, check commentability and convert spaces to tabs
- let theLine = getline(currentLine)
- let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- if s:CanToggleCommentLine(a:forceNested, currentLine)
-
- "if the user has specified forceNesting then we check to see if we
- "need to switch delimiters for place-holders
- if g:NERDUsePlaceHolders
- let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
- endif
-
- let theLine = s:AddLeftDelim(s:GetLeft(0, 1, 0), theLine)
- let theLine = s:AddRightDelim(s:GetRight(0, 1, 0), theLine)
- endif
-
- " restore leading tabs if appropriate
- if lineHasLeadingTabs
- let theLine = s:ConvertLeadingSpacesToTabs(theLine)
- endif
-
- " we are done with this line
- call setline(currentLine, theLine)
- let currentLine = currentLine + 1
- endwhile
-
-endfunction
-
-" Function: s:CommentRegion(topline, topCol, bottomLine, bottomCol) function {{{2
-" This function comments chunks of text selected in visual mode.
-" It will comment exactly the text that they have selected.
-" Args:
-" -topLine: the line num of the top line in the sexy comment
-" -topCol: top left col for this comment
-" -bottomline: the line num of the bottom line in the sexy comment
-" -bottomCol: the bottom right col for this comment
-" -forceNested: whether the caller wants comments to be nested if the
-" line(s) are already commented
-function s:CommentRegion(topLine, topCol, bottomLine, bottomCol, forceNested)
-
- "switch delims (if we can) if the current set isnt multipart
- let switchedDelims = 0
- if !s:Multipart() && s:AltMultipart() && !g:NERDAllowAnyVisualDelims
- let switchedDelims = 1
- call s:SwitchToAlternativeDelimiters(0)
- endif
-
- "if there is only one line in the comment then just do it
- if a:topLine == a:bottomLine
- call s:CommentBlock(a:topLine, a:bottomLine, a:topCol, a:bottomCol, a:forceNested)
-
- "there are multiple lines in the comment
- else
- "comment the top line
- call s:CommentBlock(a:topLine, a:topLine, a:topCol, strlen(getline(a:topLine)), a:forceNested)
-
- "comment out all the lines in the middle of the comment
- let topOfRange = a:topLine+1
- let bottomOfRange = a:bottomLine-1
- if topOfRange <= bottomOfRange
- call s:CommentLines(a:forceNested, "none", topOfRange, bottomOfRange)
- endif
-
- "comment the bottom line
- let bottom = getline(a:bottomLine)
- let numLeadingSpacesTabs = strlen(substitute(bottom, '^\([ \t]*\).*$', '\1', ''))
- call s:CommentBlock(a:bottomLine, a:bottomLine, numLeadingSpacesTabs+1, a:bottomCol, a:forceNested)
-
- endif
-
- "stick the cursor back on the char it was on before the comment
- call cursor(a:topLine, a:topCol + strlen(b:NERDLeft) + g:NERDSpaceDelims)
-
- "if we switched delims then we gotta go back to what they were before
- if switchedDelims == 1
- call s:SwitchToAlternativeDelimiters(0)
- endif
-
-endfunction
-
-" Function: s:InvertComment(firstLine, lastLine) function {{{2
-" Inverts the comments on the lines between and including the given line
-" numbers i.e all commented lines are uncommented and vice versa
-" Args:
-" -firstLine: the top of the range of lines to be inverted
-" -lastLine: the bottom of the range of lines to be inverted
-function s:InvertComment(firstLine, lastLine)
-
- " go thru all lines in the given range
- let currentLine = a:firstLine
- while currentLine <= a:lastLine
- let theLine = getline(currentLine)
-
- let sexyComBounds = s:FindBoundingLinesOfSexyCom(currentLine)
-
- " if the line is commented normally, uncomment it
- if s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)
- call s:UncommentLines(currentLine, currentLine)
- let currentLine = currentLine + 1
-
- " check if the line is commented sexually
- elseif !empty(sexyComBounds)
- let numLinesBeforeSexyComRemoved = s:NumLinesInBuf()
- call s:UncommentLinesSexy(sexyComBounds[0], sexyComBounds[1])
-
- "move to the line after last line of the sexy comment
- let numLinesAfterSexyComRemoved = s:NumLinesInBuf()
- let currentLine = bottomBound - (numLinesBeforeSexyComRemoved - numLinesAfterSexyComRemoved) + 1
-
- " the line isnt commented
- else
- call s:CommentLinesToggle(1, currentLine, currentLine)
- let currentLine = currentLine + 1
- endif
-
- endwhile
-endfunction
-
-" Function: NERDComment(isVisual, type) function {{{2
-" This function is a Wrapper for the main commenting functions
-"
-" Args:
-" -isVisual: a flag indicating whether the comment is requested in visual
-" mode or not
-" -type: the type of commenting requested. Can be 'sexy', 'invert',
-" 'minimal', 'toggle', 'alignLeft', 'alignBoth', 'norm',
-" 'nested', 'toEOL', 'append', 'insert', 'uncomment', 'yank'
-function! NERDComment(isVisual, type) range
- " we want case sensitivity when commenting
- let oldIgnoreCase = &ignorecase
- set noignorecase
-
- if a:isVisual
- let firstLine = line("'<")
- let lastLine = line("'>")
- let firstCol = col("'<")
- let lastCol = col("'>") - (&selection == 'exclusive' ? 1 : 0)
- else
- let firstLine = a:firstline
- let lastLine = a:lastline
- endif
-
- let countWasGiven = (a:isVisual == 0 && firstLine != lastLine)
-
- let forceNested = (a:type == 'nested' || g:NERDDefaultNesting)
-
- if a:type == 'norm' || a:type == 'nested'
- if a:isVisual && visualmode() == ""
- call s:CommentBlock(firstLine, lastLine, firstCol, lastCol, forceNested)
- elseif a:isVisual && visualmode() == "v" && (g:NERDCommentWholeLinesInVMode==0 || (g:NERDCommentWholeLinesInVMode==2 && s:HasMultipartDelims()))
- call s:CommentRegion(firstLine, firstCol, lastLine, lastCol, forceNested)
- else
- call s:CommentLines(forceNested, "none", firstLine, lastLine)
- endif
-
- elseif a:type == 'alignLeft' || a:type == 'alignBoth'
- let align = "none"
- if a:type == "alignLeft"
- let align = "left"
- elseif a:type == "alignBoth"
- let align = "both"
- endif
- call s:CommentLines(forceNested, align, firstLine, lastLine)
-
- elseif a:type == 'invert'
- call s:InvertComment(firstLine, lastLine)
-
- elseif a:type == 'sexy'
- try
- call s:CommentLinesSexy(firstLine, lastLine)
- catch /NERDCommenter.Delimiters/
- call s:CommentLines(forceNested, "none", firstLine, lastLine)
- catch /NERDCommenter.Nesting/
- call s:NerdEcho("Sexy comment aborted. Nested sexy cannot be nested", 0)
- endtry
-
- elseif a:type == 'toggle'
- let theLine = getline(firstLine)
-
- if s:IsInSexyComment(firstLine) || s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)
- call s:UncommentLines(firstLine, lastLine)
- else
- call s:CommentLinesToggle(forceNested, firstLine, lastLine)
- endif
-
- elseif a:type == 'minimal'
- try
- call s:CommentLinesMinimal(firstLine, lastLine)
- catch /NERDCommenter.Delimiters/
- call s:NerdEcho("Minimal comments can only be used for filetypes that have multipart delimiters.", 0)
- catch /NERDCommenter.Settings/
- call s:NerdEcho("Place holders are required but disabled.", 0)
- endtry
-
- elseif a:type == 'toEOL'
- call s:SaveScreenState()
- call s:CommentBlock(firstLine, firstLine, col("."), col("$")-1, 1)
- call s:RestoreScreenState()
-
- elseif a:type == 'append'
- call s:AppendCommentToLine()
-
- elseif a:type == 'insert'
- call s:PlaceDelimitersAndInsBetween()
-
- elseif a:type == 'uncomment'
- call s:UncommentLines(firstLine, lastLine)
-
- elseif a:type == 'yank'
- if a:isVisual
- normal! gvy
- elseif countWasGiven
- execute firstLine .','. lastLine .'yank'
- else
- normal! yy
- endif
- execute firstLine .','. lastLine .'call NERDComment('. a:isVisual .', "norm")'
- endif
-
- let &ignorecase = oldIgnoreCase
-endfunction
-
-" Function: s:PlaceDelimitersAndInsBetween() function {{{2
-" This is function is called to place comment delimiters down and place the
-" cursor between them
-function s:PlaceDelimitersAndInsBetween()
- " get the left and right delimiters without any escape chars in them
- let left = s:GetLeft(0, 1, 0)
- let right = s:GetRight(0, 1, 0)
-
- let theLine = getline(".")
- let lineHasLeadTabs = s:HasLeadingTabs(theLine) || (theLine =~ '^ *$' && !&expandtab)
-
- "convert tabs to spaces and adjust the cursors column to take this into
- "account
- let untabbedCol = s:UntabbedCol(theLine, col("."))
- call setline(line("."), s:ConvertLeadingTabsToSpaces(theLine))
- call cursor(line("."), untabbedCol)
-
- " get the len of the right delim
- let lenRight = strlen(right)
-
- let isDelimOnEOL = col(".") >= strlen(getline("."))
-
- " if the cursor is in the first col then we gotta insert rather than
- " append the comment delimiters here
- let insOrApp = (col(".")==1 ? 'i' : 'a')
-
- " place the delimiters down. We do it differently depending on whether
- " there is a left AND right delimiter
- if lenRight > 0
- execute ":normal! " . insOrApp . left . right
- execute ":normal! " . lenRight . "h"
- else
- execute ":normal! " . insOrApp . left
-
- " if we are tacking the delim on the EOL then we gotta add a space
- " after it cos when we go out of insert mode the cursor will move back
- " one and the user wont be in position to type the comment.
- if isDelimOnEOL
- execute 'normal! a '
- endif
- endif
- normal! l
-
- "if needed convert spaces back to tabs and adjust the cursors col
- "accordingly
- if lineHasLeadTabs
- let tabbedCol = s:TabbedCol(getline("."), col("."))
- call setline(line("."), s:ConvertLeadingSpacesToTabs(getline(".")))
- call cursor(line("."), tabbedCol)
- endif
-
- startinsert
-endfunction
-
-" Function: s:RemoveDelimiters(left, right, line) {{{2
-" this function is called to remove the first left comment delimiter and the
-" last right delimiter of the given line.
-"
-" The args left and right must be strings. If there is no right delimiter (as
-" is the case for e.g vim file comments) them the arg right should be ""
-"
-" Args:
-" -left: the left comment delimiter
-" -right: the right comment delimiter
-" -line: the line to remove the delimiters from
-function s:RemoveDelimiters(left, right, line)
-
- let l:left = a:left
- let l:right = a:right
- let lenLeft = strlen(left)
- let lenRight = strlen(right)
-
- let delimsSpaced = (g:NERDSpaceDelims || g:NERDRemoveExtraSpaces)
-
- let line = a:line
-
- "look for the left delimiter, if we find it, remove it.
- let leftIndx = s:FindDelimiterIndex(a:left, line)
- if leftIndx != -1
- let line = strpart(line, 0, leftIndx) . strpart(line, leftIndx+lenLeft)
-
- "if the user has specified that there is a space after the left delim
- "then check for the space and remove it if it is there
- if delimsSpaced && strpart(line, leftIndx, s:lenSpaceStr) == s:spaceStr
- let line = strpart(line, 0, leftIndx) . strpart(line, leftIndx+s:lenSpaceStr)
- endif
- endif
-
- "look for the right delimiter, if we find it, remove it
- let rightIndx = s:FindDelimiterIndex(a:right, line)
- if rightIndx != -1
- let line = strpart(line, 0, rightIndx) . strpart(line, rightIndx+lenRight)
-
- "if the user has specified that there is a space before the right delim
- "then check for the space and remove it if it is there
- if delimsSpaced && strpart(line, rightIndx-s:lenSpaceStr, s:lenSpaceStr) == s:spaceStr && s:Multipart()
- let line = strpart(line, 0, rightIndx-s:lenSpaceStr) . strpart(line, rightIndx)
- endif
- endif
-
- return line
-endfunction
-
-" Function: s:UncommentLines(topLine, bottomLine) {{{2
-" This function uncomments the given lines
-"
-" Args:
-" topLine: the top line of the visual selection to uncomment
-" bottomLine: the bottom line of the visual selection to uncomment
-function s:UncommentLines(topLine, bottomLine)
- "make local copies of a:firstline and a:lastline and, if need be, swap
- "them around if the top line is below the bottom
- let l:firstline = a:topLine
- let l:lastline = a:bottomLine
- if firstline > lastline
- let firstline = lastline
- let lastline = a:topLine
- endif
-
- "go thru each line uncommenting each line removing sexy comments
- let currentLine = firstline
- while currentLine <= lastline
-
- "check the current line to see if it is part of a sexy comment
- let sexyComBounds = s:FindBoundingLinesOfSexyCom(currentLine)
- if !empty(sexyComBounds)
-
- "we need to store the num lines in the buf before the comment is
- "removed so we know how many lines were removed when the sexy com
- "was removed
- let numLinesBeforeSexyComRemoved = s:NumLinesInBuf()
-
- call s:UncommentLinesSexy(sexyComBounds[0], sexyComBounds[1])
-
- "move to the line after last line of the sexy comment
- let numLinesAfterSexyComRemoved = s:NumLinesInBuf()
- let numLinesRemoved = numLinesBeforeSexyComRemoved - numLinesAfterSexyComRemoved
- let currentLine = sexyComBounds[1] - numLinesRemoved + 1
- let lastline = lastline - numLinesRemoved
-
- "no sexy com was detected so uncomment the line as normal
- else
- call s:UncommentLinesNormal(currentLine, currentLine)
- let currentLine = currentLine + 1
- endif
- endwhile
-
-endfunction
-
-" Function: s:UncommentLinesSexy(topline, bottomline) {{{2
-" This function removes all the comment characters associated with the sexy
-" comment spanning the given lines
-" Args:
-" -topline/bottomline: the top/bottom lines of the sexy comment
-function s:UncommentLinesSexy(topline, bottomline)
- let left = s:GetSexyComLeft(0,1)
- let right = s:GetSexyComRight(0,1)
-
-
- "check if it is even possible for sexy comments to exist with the
- "available delimiters
- if left == -1 || right == -1
- throw 'NERDCommenter.Delimiters exception: cannot uncomment sexy comments with available delimiters.'
- endif
-
- let leftUnEsc = s:GetSexyComLeft(0,0)
- let rightUnEsc = s:GetSexyComRight(0,0)
-
- let sexyComMarker = s:GetSexyComMarker(0, 1)
- let sexyComMarkerUnEsc = s:GetSexyComMarker(0, 0)
-
- "the markerOffset is how far right we need to move the sexyComMarker to
- "line it up with the end of the left delim
- let markerOffset = strlen(leftUnEsc)-strlen(sexyComMarkerUnEsc)
-
- " go thru the intermediate lines of the sexy comment and remove the
- " sexy comment markers (eg the '*'s on the start of line in a c sexy
- " comment)
- let currentLine = a:topline+1
- while currentLine < a:bottomline
- let theLine = getline(currentLine)
-
- " remove the sexy comment marker from the line. We also remove the
- " space after it if there is one and if appropriate options are set
- let sexyComMarkerIndx = stridx(theLine, sexyComMarkerUnEsc)
- if strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc), s:lenSpaceStr) == s:spaceStr && g:NERDSpaceDelims
- let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc)+s:lenSpaceStr)
- else
- let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc))
- endif
-
- let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
-
- let theLine = s:ConvertLeadingWhiteSpace(theLine)
-
- " move onto the next line
- call setline(currentLine, theLine)
- let currentLine = currentLine + 1
- endwhile
-
- " gotta make a copy of a:bottomline cos we modify the position of the
- " last line it if we remove the topline
- let bottomline = a:bottomline
-
- " get the first line so we can remove the left delim from it
- let theLine = getline(a:topline)
-
- " if the first line contains only the left delim then just delete it
- if theLine =~ '^[ \t]*' . left . '[ \t]*$' && !g:NERDCompactSexyComs
- call cursor(a:topline, 1)
- normal! dd
- let bottomline = bottomline - 1
-
- " topline contains more than just the left delim
- else
-
- " remove the delim. If there is a space after it
- " then remove this too if appropriate
- let delimIndx = stridx(theLine, leftUnEsc)
- if strpart(theLine, delimIndx+strlen(leftUnEsc), s:lenSpaceStr) == s:spaceStr && g:NERDSpaceDelims
- let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(leftUnEsc)+s:lenSpaceStr)
- else
- let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(leftUnEsc))
- endif
- let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
- call setline(a:topline, theLine)
- endif
-
- " get the last line so we can remove the right delim
- let theLine = getline(bottomline)
-
- " if the bottomline contains only the right delim then just delete it
- if theLine =~ '^[ \t]*' . right . '[ \t]*$'
- call cursor(bottomline, 1)
- normal! dd
-
- " the last line contains more than the right delim
- else
- " remove the right delim. If there is a space after it and
- " if the appropriate options are set then remove this too.
- let delimIndx = s:LastIndexOfDelim(rightUnEsc, theLine)
- if strpart(theLine, delimIndx+strlen(leftUnEsc), s:lenSpaceStr) == s:spaceStr && g:NERDSpaceDelims
- let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(rightUnEsc)+s:lenSpaceStr)
- else
- let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(rightUnEsc))
- endif
-
- " if the last line also starts with a sexy comment marker then we
- " remove this as well
- if theLine =~ '^[ \t]*' . sexyComMarker
-
- " remove the sexyComMarker. If there is a space after it then
- " remove that too
- let sexyComMarkerIndx = stridx(theLine, sexyComMarkerUnEsc)
- if strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc), s:lenSpaceStr) == s:spaceStr && g:NERDSpaceDelims
- let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset ) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc)+s:lenSpaceStr)
- else
- let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset ) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc))
- endif
- endif
-
- let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
- call setline(bottomline, theLine)
- endif
-endfunction
-
-" Function: s:UncommentLineNormal(line) {{{2
-" uncomments the given line and returns the result
-" Args:
-" -line: the line to uncomment
-function s:UncommentLineNormal(line)
- let line = a:line
-
- "get the comment status on the line so we know how it is commented
- let lineCommentStatus = s:IsCommentedOuttermost(b:NERDLeft, b:NERDRight, b:NERDLeftAlt, b:NERDRightAlt, line)
-
- "it is commented with b:NERDLeft and b:NERDRight so remove these delims
- if lineCommentStatus == 1
- let line = s:RemoveDelimiters(b:NERDLeft, b:NERDRight, line)
-
- "it is commented with b:NERDLeftAlt and b:NERDRightAlt so remove these delims
- elseif lineCommentStatus == 2 && g:NERDRemoveAltComs
- let line = s:RemoveDelimiters(b:NERDLeftAlt, b:NERDRightAlt, line)
-
- "it is not properly commented with any delims so we check if it has
- "any random left or right delims on it and remove the outtermost ones
- else
- "get the positions of all delim types on the line
- let indxLeft = s:FindDelimiterIndex(b:NERDLeft, line)
- let indxLeftAlt = s:FindDelimiterIndex(b:NERDLeftAlt, line)
- let indxRight = s:FindDelimiterIndex(b:NERDRight, line)
- let indxRightAlt = s:FindDelimiterIndex(b:NERDRightAlt, line)
-
- "remove the outter most left comment delim
- if indxLeft != -1 && (indxLeft < indxLeftAlt || indxLeftAlt == -1)
- let line = s:RemoveDelimiters(b:NERDLeft, '', line)
- elseif indxLeftAlt != -1
- let line = s:RemoveDelimiters(b:NERDLeftAlt, '', line)
- endif
-
- "remove the outter most right comment delim
- if indxRight != -1 && (indxRight < indxRightAlt || indxRightAlt == -1)
- let line = s:RemoveDelimiters('', b:NERDRight, line)
- elseif indxRightAlt != -1
- let line = s:RemoveDelimiters('', b:NERDRightAlt, line)
- endif
- endif
-
-
- let indxLeft = s:FindDelimiterIndex(b:NERDLeft, line)
- let indxLeftAlt = s:FindDelimiterIndex(b:NERDLeftAlt, line)
- let indxLeftPlace = s:FindDelimiterIndex(g:NERDLPlace, line)
-
- let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
- let indxRightAlt = s:FindDelimiterIndex(b:NERDRightAlt, line)
- let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
-
- let right = b:NERDRight
- let left = b:NERDLeft
- if !s:Multipart()
- let right = b:NERDRightAlt
- let left = b:NERDLeftAlt
- endif
-
-
- "if there are place-holders on the line then we check to see if they are
- "the outtermost delimiters on the line. If so then we replace them with
- "real delimiters
- if indxLeftPlace != -1
- if (indxLeftPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
- let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
- endif
- elseif indxRightPlace != -1
- if (indxRightPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
- let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
- endif
-
- endif
-
- let line = s:ConvertLeadingWhiteSpace(line)
-
- return line
-endfunction
-
-" Function: s:UncommentLinesNormal(topline, bottomline) {{{2
-" This function is called to uncomment lines that arent a sexy comment
-" Args:
-" -topline/bottomline: the top/bottom line numbers of the comment
-function s:UncommentLinesNormal(topline, bottomline)
- let currentLine = a:topline
- while currentLine <= a:bottomline
- let line = getline(currentLine)
- call setline(currentLine, s:UncommentLineNormal(line))
- let currentLine = currentLine + 1
- endwhile
-endfunction
-
-
-" Section: Other helper functions {{{1
-" ============================================================================
-
-" Function: s:AddLeftDelim(delim, theLine) {{{2
-" Args:
-function s:AddLeftDelim(delim, theLine)
- return substitute(a:theLine, '^\([ \t]*\)', '\1' . a:delim, '')
-endfunction
-
-" Function: s:AddLeftDelimAligned(delim, theLine) {{{2
-" Args:
-function s:AddLeftDelimAligned(delim, theLine, alignIndx)
-
- "if the line is not long enough then bung some extra spaces on the front
- "so we can align the delim properly
- let theLine = a:theLine
- if strlen(theLine) < a:alignIndx
- let theLine = repeat(' ', a:alignIndx - strlen(theLine))
- endif
-
- return strpart(theLine, 0, a:alignIndx) . a:delim . strpart(theLine, a:alignIndx)
-endfunction
-
-" Function: s:AddRightDelim(delim, theLine) {{{2
-" Args:
-function s:AddRightDelim(delim, theLine)
- if a:delim == ''
- return a:theLine
- else
- return substitute(a:theLine, '$', a:delim, '')
- endif
-endfunction
-
-" Function: s:AddRightDelimAligned(delim, theLine, alignIndx) {{{2
-" Args:
-function s:AddRightDelimAligned(delim, theLine, alignIndx)
- if a:delim == ""
- return a:theLine
- else
-
- " when we align the right delim we are just adding spaces
- " so we get a string containing the needed spaces (it
- " could be empty)
- let extraSpaces = ''
- let extraSpaces = repeat(' ', a:alignIndx-strlen(a:theLine))
-
- " add the right delim
- return substitute(a:theLine, '$', extraSpaces . a:delim, '')
- endif
-endfunction
-
-" Function: s:AltMultipart() {{{2
-" returns 1 if the alternative delims are multipart
-function s:AltMultipart()
- return b:NERDRightAlt != ''
-endfunction
-
-" Function: s:CanCommentLine(forceNested, line) {{{2
-"This function is used to determine whether the given line can be commented.
-"It returns 1 if it can be and 0 otherwise
-"
-" Args:
-" -forceNested: a flag indicating whether the caller wants comments to be nested
-" if the current line is already commented
-" -lineNum: the line num of the line to check for commentability
-function s:CanCommentLine(forceNested, lineNum)
- let theLine = getline(a:lineNum)
-
- " make sure we don't comment lines that are just spaces or tabs or empty.
- if theLine =~ "^[ \t]*$"
- return 0
- endif
-
- "if the line is part of a sexy comment then just flag it...
- if s:IsInSexyComment(a:lineNum)
- return 0
- endif
-
- let isCommented = s:IsCommentedNormOrSexy(a:lineNum)
-
- "if the line isnt commented return true
- if !isCommented
- return 1
- endif
-
- "if the line is commented but nesting is allowed then return true
- if a:forceNested && (!s:Multipart() || g:NERDUsePlaceHolders)
- return 1
- endif
-
- return 0
-endfunction
-
-" Function: s:CanPlaceCursor(line, col) {{{2
-" returns 1 if the cursor can be placed exactly in the given position
-function s:CanPlaceCursor(line, col)
- let c = col(".")
- let l = line(".")
- call cursor(a:line, a:col)
- let success = (line(".") == a:line && col(".") == a:col)
- call cursor(l,c)
- return success
-endfunction
-
-" Function: s:CanSexyCommentLines(topline, bottomline) {{{2
-" Return: 1 if the given lines can be commented sexually, 0 otherwise
-function s:CanSexyCommentLines(topline, bottomline)
- " see if the selected regions have any sexy comments
- let currentLine = a:topline
- while(currentLine <= a:bottomline)
- if s:IsInSexyComment(currentLine)
- return 0
- endif
- let currentLine = currentLine + 1
- endwhile
- return 1
-endfunction
-" Function: s:CanToggleCommentLine(forceNested, line) {{{2
-"This function is used to determine whether the given line can be toggle commented.
-"It returns 1 if it can be and 0 otherwise
-"
-" Args:
-" -lineNum: the line num of the line to check for commentability
-function s:CanToggleCommentLine(forceNested, lineNum)
- let theLine = getline(a:lineNum)
- if (s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)) && !a:forceNested
- return 0
- endif
-
- " make sure we don't comment lines that are just spaces or tabs or empty.
- if theLine =~ "^[ \t]*$"
- return 0
- endif
-
- "if the line is part of a sexy comment then just flag it...
- if s:IsInSexyComment(a:lineNum)
- return 0
- endif
-
- return 1
-endfunction
-
-" Function: s:ConvertLeadingSpacesToTabs(line) {{{2
-" This function takes a line and converts all leading tabs on that line into
-" spaces
-"
-" Args:
-" -line: the line whose leading tabs will be converted
-function s:ConvertLeadingSpacesToTabs(line)
- let toReturn = a:line
- while toReturn =~ '^\t*' . s:TabSpace() . '\(.*\)$'
- let toReturn = substitute(toReturn, '^\(\t*\)' . s:TabSpace() . '\(.*\)$' , '\1\t\2' , "")
- endwhile
-
- return toReturn
-endfunction
-
-
-" Function: s:ConvertLeadingTabsToSpaces(line) {{{2
-" This function takes a line and converts all leading spaces on that line into
-" tabs
-"
-" Args:
-" -line: the line whose leading spaces will be converted
-function s:ConvertLeadingTabsToSpaces(line)
- let toReturn = a:line
- while toReturn =~ '^\( *\)\t'
- let toReturn = substitute(toReturn, '^\( *\)\t', '\1' . s:TabSpace() , "")
- endwhile
-
- return toReturn
-endfunction
-
-" Function: s:ConvertLeadingWhiteSpace(line) {{{2
-" Converts the leading white space to tabs/spaces depending on &ts
-"
-" Args:
-" -line: the line to convert
-function s:ConvertLeadingWhiteSpace(line)
- let toReturn = a:line
- while toReturn =~ '^ *\t'
- let toReturn = substitute(toReturn, '^ *\zs\t\ze', s:TabSpace(), "g")
- endwhile
-
- if !&expandtab
- let toReturn = s:ConvertLeadingSpacesToTabs(toReturn)
- endif
-
- return toReturn
-endfunction
-
-
-" Function: s:CountNonESCedOccurances(str, searchstr, escChar) {{{2
-" This function counts the number of substrings contained in another string.
-" These substrings are only counted if they are not escaped with escChar
-" Args:
-" -str: the string to look for searchstr in
-" -searchstr: the substring to search for in str
-" -escChar: the escape character which, when preceding an instance of
-" searchstr, will cause it not to be counted
-function s:CountNonESCedOccurances(str, searchstr, escChar)
- "get the index of the first occurrence of searchstr
- let indx = stridx(a:str, a:searchstr)
-
- "if there is an instance of searchstr in str process it
- if indx != -1
- "get the remainder of str after this instance of searchstr is removed
- let lensearchstr = strlen(a:searchstr)
- let strLeft = strpart(a:str, indx+lensearchstr)
-
- "if this instance of searchstr is not escaped, add one to the count
- "and recurse. If it is escaped, just recurse
- if !s:IsEscaped(a:str, indx, a:escChar)
- return 1 + s:CountNonESCedOccurances(strLeft, a:searchstr, a:escChar)
- else
- return s:CountNonESCedOccurances(strLeft, a:searchstr, a:escChar)
- endif
- endif
-endfunction
-" Function: s:DoesBlockHaveDelim(delim, top, bottom) {{{2
-" Returns 1 if the given block of lines has a delimiter (a:delim) in it
-" Args:
-" -delim: the comment delimiter to check the block for
-" -top: the top line number of the block
-" -bottom: the bottom line number of the block
-function s:DoesBlockHaveDelim(delim, top, bottom)
- let currentLine = a:top
- while currentLine < a:bottom
- let theline = getline(currentLine)
- if s:FindDelimiterIndex(a:delim, theline) != -1
- return 1
- endif
- let currentLine = currentLine + 1
- endwhile
- return 0
-endfunction
-
-" Function: s:DoesBlockHaveMultipartDelim(top, bottom) {{{2
-" Returns 1 if the given block has a >= 1 multipart delimiter in it
-" Args:
-" -top: the top line number of the block
-" -bottom: the bottom line number of the block
-function s:DoesBlockHaveMultipartDelim(top, bottom)
- if s:HasMultipartDelims()
- if s:Multipart()
- return s:DoesBlockHaveDelim(b:NERDLeft, a:top, a:bottom) || s:DoesBlockHaveDelim(b:NERDRight, a:top, a:bottom)
- else
- return s:DoesBlockHaveDelim(b:NERDLeftAlt, a:top, a:bottom) || s:DoesBlockHaveDelim(b:NERDRightAlt, a:top, a:bottom)
- endif
- endif
- return 0
-endfunction
-
-
-" Function: s:Esc(str) {{{2
-" Escapes all the tricky chars in the given string
-function s:Esc(str)
- let charsToEsc = '*/\."&$+'
- return escape(a:str, charsToEsc)
-endfunction
-
-" Function: s:FindDelimiterIndex(delimiter, line) {{{2
-" This function is used to get the string index of the input comment delimiter
-" on the input line. If no valid comment delimiter is found in the line then
-" -1 is returned
-" Args:
-" -delimiter: the delimiter we are looking to find the index of
-" -line: the line we are looking for delimiter on
-function s:FindDelimiterIndex(delimiter, line)
-
- "make sure the delimiter isnt empty otherwise we go into an infinite loop.
- if a:delimiter == ""
- return -1
- endif
-
-
- let l:delimiter = a:delimiter
- let lenDel = strlen(l:delimiter)
-
- "get the index of the first occurrence of the delimiter
- let delIndx = stridx(a:line, l:delimiter)
-
- "keep looping thru the line till we either find a real comment delimiter
- "or run off the EOL
- while delIndx != -1
-
- "if we are not off the EOL get the str before the possible delimiter
- "in question and check if it really is a delimiter. If it is, return
- "its position
- if delIndx != -1
- if s:IsDelimValid(l:delimiter, delIndx, a:line)
- return delIndx
- endif
- endif
-
- "we have not yet found a real comment delimiter so move past the
- "current one we are lookin at
- let restOfLine = strpart(a:line, delIndx + lenDel)
- let distToNextDelim = stridx(restOfLine , l:delimiter)
-
- "if distToNextDelim is -1 then there is no more potential delimiters
- "on the line so set delIndx to -1. Otherwise, move along the line by
- "distToNextDelim
- if distToNextDelim == -1
- let delIndx = -1
- else
- let delIndx = delIndx + lenDel + distToNextDelim
- endif
- endwhile
-
- "there is no comment delimiter on this line
- return -1
-endfunction
-
-" Function: s:FindBoundingLinesOfSexyCom(lineNum) {{{2
-" This function takes in a line number and tests whether this line number is
-" the top/bottom/middle line of a sexy comment. If it is then the top/bottom
-" lines of the sexy comment are returned
-" Args:
-" -lineNum: the line number that is to be tested whether it is the
-" top/bottom/middle line of a sexy com
-" Returns:
-" A string that has the top/bottom lines of the sexy comment encoded in it.
-" The format is 'topline,bottomline'. If a:lineNum turns out not to be the
-" top/bottom/middle of a sexy comment then -1 is returned
-function s:FindBoundingLinesOfSexyCom(lineNum)
-
- "find which delimiters to look for as the start/end delims of the comment
- let left = ''
- let right = ''
- if s:Multipart()
- let left = s:GetLeft(0,0,1)
- let right = s:GetRight(0,0,1)
- elseif s:AltMultipart()
- let left = s:GetLeft(1,0,1)
- let right = s:GetRight(1,0,1)
- else
- return []
- endif
-
- let sexyComMarker = s:GetSexyComMarker(0, 1)
-
- "initialise the top/bottom line numbers of the sexy comment to -1
- let top = -1
- let bottom = -1
-
- let currentLine = a:lineNum
- while top == -1 || bottom == -1
- let theLine = getline(currentLine)
-
- "check if the current line is the top of the sexy comment
- if currentLine <= a:lineNum && theLine =~ '^[ \t]*' . left && theLine !~ '.*' . right && currentLine < s:NumLinesInBuf()
- let top = currentLine
- let currentLine = a:lineNum
-
- "check if the current line is the bottom of the sexy comment
- elseif theLine =~ '^[ \t]*' . right && theLine !~ '.*' . left && currentLine > 1
- let bottom = currentLine
-
- "the right delimiter is on the same line as the last sexyComMarker
- elseif theLine =~ '^[ \t]*' . sexyComMarker . '.*' . right
- let bottom = currentLine
-
- "we have not found the top or bottom line so we assume currentLine is an
- "intermediate line and look to prove otherwise
- else
-
- "if the line doesnt start with a sexyComMarker then it is not a sexy
- "comment
- if theLine !~ '^[ \t]*' . sexyComMarker
- return []
- endif
-
- endif
-
- "if top is -1 then we havent found the top yet so keep looking up
- if top == -1
- let currentLine = currentLine - 1
- "if we have found the top line then go down looking for the bottom
- else
- let currentLine = currentLine + 1
- endif
-
- endwhile
-
- return [top, bottom]
-endfunction
-
-
-" Function: s:GetLeft(alt, space, esc) {{{2
-" returns the left/left-alternative delimiter
-" Args:
-" -alt: specifies whether to get left or left-alternative delim
-" -space: specifies whether the delim should be spaced or not
-" (the space string will only be added if NERDSpaceDelims is set)
-" -esc: specifies whether the tricky chars in the delim should be ESCed
-function s:GetLeft(alt, space, esc)
- let delim = b:NERDLeft
-
- if a:alt
- if b:NERDLeftAlt == ''
- return ''
- else
- let delim = b:NERDLeftAlt
- endif
- endif
- if delim == ''
- return ''
- endif
-
- if a:space && g:NERDSpaceDelims
- let delim = delim . s:spaceStr
- endif
-
- if a:esc
- let delim = s:Esc(delim)
- endif
-
- return delim
-endfunction
-
-" Function: s:GetRight(alt, space, esc) {{{2
-" returns the right/right-alternative delimiter
-" Args:
-" -alt: specifies whether to get right or right-alternative delim
-" -space: specifies whether the delim should be spaced or not
-" (the space string will only be added if NERDSpaceDelims is set)
-" -esc: specifies whether the tricky chars in the delim should be ESCed
-function s:GetRight(alt, space, esc)
- let delim = b:NERDRight
-
- if a:alt
- if !s:AltMultipart()
- return ''
- else
- let delim = b:NERDRightAlt
- endif
- endif
- if delim == ''
- return ''
- endif
-
- if a:space && g:NERDSpaceDelims
- let delim = s:spaceStr . delim
- endif
-
- if a:esc
- let delim = s:Esc(delim)
- endif
-
- return delim
-endfunction
-
-
-" Function: s:GetSexyComMarker() {{{2
-" Returns the sexy comment marker for the current filetype.
-"
-" C style sexy comments are assumed if possible. If not then the sexy comment
-" marker is the last char of the delimiter pair that has both left and right
-" delims and has the longest left delim
-"
-" Args:
-" -space: specifies whether the marker is to have a space string after it
-" (the space string will only be added if NERDSpaceDelims is set)
-" -esc: specifies whether the tricky chars in the marker are to be ESCed
-function s:GetSexyComMarker(space, esc)
- let sexyComMarker = b:NERDSexyComMarker
-
- "if there is no hardcoded marker then we find one
- if sexyComMarker == ''
-
- "if the filetype has c style comments then use standard c sexy
- "comments
- if s:HasCStyleComments()
- let sexyComMarker = '*'
- else
- "find a comment marker by getting the longest available left delim
- "(that has a corresponding right delim) and taking the last char
- let lenLeft = strlen(b:NERDLeft)
- let lenLeftAlt = strlen(b:NERDLeftAlt)
- let left = ''
- let right = ''
- if s:Multipart() && lenLeft >= lenLeftAlt
- let left = b:NERDLeft
- elseif s:AltMultipart()
- let left = b:NERDLeftAlt
- else
- return -1
- endif
-
- "get the last char of left
- let sexyComMarker = strpart(left, strlen(left)-1)
- endif
- endif
-
- if a:space && g:NERDSpaceDelims
- let sexyComMarker = sexyComMarker . s:spaceStr
- endif
-
- if a:esc
- let sexyComMarker = s:Esc(sexyComMarker)
- endif
-
- return sexyComMarker
-endfunction
-
-" Function: s:GetSexyComLeft(space, esc) {{{2
-" Returns the left delimiter for sexy comments for this filetype or -1 if
-" there is none. C style sexy comments are used if possible
-" Args:
-" -space: specifies if the delim has a space string on the end
-" (the space string will only be added if NERDSpaceDelims is set)
-" -esc: specifies whether the tricky chars in the string are ESCed
-function s:GetSexyComLeft(space, esc)
- let lenLeft = strlen(b:NERDLeft)
- let lenLeftAlt = strlen(b:NERDLeftAlt)
- let left = ''
-
- "assume c style sexy comments if possible
- if s:HasCStyleComments()
- let left = '/*'
- else
- "grab the longest left delim that has a right
- if s:Multipart() && lenLeft >= lenLeftAlt
- let left = b:NERDLeft
- elseif s:AltMultipart()
- let left = b:NERDLeftAlt
- else
- return -1
- endif
- endif
-
- if a:space && g:NERDSpaceDelims
- let left = left . s:spaceStr
- endif
-
- if a:esc
- let left = s:Esc(left)
- endif
-
- return left
-endfunction
-
-" Function: s:GetSexyComRight(space, esc) {{{2
-" Returns the right delimiter for sexy comments for this filetype or -1 if
-" there is none. C style sexy comments are used if possible.
-" Args:
-" -space: specifies if the delim has a space string on the start
-" (the space string will only be added if NERDSpaceDelims
-" is specified for the current filetype)
-" -esc: specifies whether the tricky chars in the string are ESCed
-function s:GetSexyComRight(space, esc)
- let lenLeft = strlen(b:NERDLeft)
- let lenLeftAlt = strlen(b:NERDLeftAlt)
- let right = ''
-
- "assume c style sexy comments if possible
- if s:HasCStyleComments()
- let right = '*/'
- else
- "grab the right delim that pairs with the longest left delim
- if s:Multipart() && lenLeft >= lenLeftAlt
- let right = b:NERDRight
- elseif s:AltMultipart()
- let right = b:NERDRightAlt
- else
- return -1
- endif
- endif
-
- if a:space && g:NERDSpaceDelims
- let right = s:spaceStr . right
- endif
-
- if a:esc
- let right = s:Esc(right)
- endif
-
- return right
-endfunction
-
-" Function: s:HasMultipartDelims() {{{2
-" Returns 1 iff the current filetype has at least one set of multipart delims
-function s:HasMultipartDelims()
- return s:Multipart() || s:AltMultipart()
-endfunction
-
-" Function: s:HasLeadingTabs(...) {{{2
-" Returns 1 if any of the given strings have leading tabs
-function s:HasLeadingTabs(...)
- for s in a:000
- if s =~ '^\t.*'
- return 1
- end
- endfor
- return 0
-endfunction
-" Function: s:HasCStyleComments() {{{2
-" Returns 1 iff the current filetype has c style comment delimiters
-function s:HasCStyleComments()
- return (b:NERDLeft == '/*' && b:NERDRight == '*/') || (b:NERDLeftAlt == '/*' && b:NERDRightAlt == '*/')
-endfunction
-
-" Function: s:IsCommentedNormOrSexy(lineNum) {{{2
-"This function is used to determine whether the given line is commented with
-"either set of delimiters or if it is part of a sexy comment
-"
-" Args:
-" -lineNum: the line number of the line to check
-function s:IsCommentedNormOrSexy(lineNum)
- let theLine = getline(a:lineNum)
-
- "if the line is commented normally return 1
- if s:IsCommented(b:NERDLeft, b:NERDRight, theLine) || s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine)
- return 1
- endif
-
- "if the line is part of a sexy comment return 1
- if s:IsInSexyComment(a:lineNum)
- return 1
- endif
- return 0
-endfunction
-
-" Function: s:IsCommented(left, right, line) {{{2
-"This function is used to determine whether the given line is commented with
-"the given delimiters
-"
-" Args:
-" -line: the line that to check if commented
-" -left/right: the left and right delimiters to check for
-function s:IsCommented(left, right, line)
- "if the line isnt commented return true
- if s:FindDelimiterIndex(a:left, a:line) != -1 && (s:FindDelimiterIndex(a:right, a:line) != -1 || !s:Multipart())
- return 1
- endif
- return 0
-endfunction
-
-" Function: s:IsCommentedFromStartOfLine(left, line) {{{2
-"This function is used to determine whether the given line is commented with
-"the given delimiters at the start of the line i.e the left delimiter is the
-"first thing on the line (apart from spaces\tabs)
-"
-" Args:
-" -line: the line that to check if commented
-" -left: the left delimiter to check for
-function s:IsCommentedFromStartOfLine(left, line)
- let theLine = s:ConvertLeadingTabsToSpaces(a:line)
- let numSpaces = strlen(substitute(theLine, '^\( *\).*$', '\1', ''))
- let delimIndx = s:FindDelimiterIndex(a:left, theLine)
- return delimIndx == numSpaces
-endfunction
-
-" Function: s:IsCommentedOuttermost(left, right, leftAlt, rightAlt, line) {{{2
-" Finds the type of the outtermost delims on the line
-"
-" Args:
-" -line: the line that to check if the outtermost comments on it are
-" left/right
-" -left/right: the left and right delimiters to check for
-" -leftAlt/rightAlt: the left and right alternative delimiters to check for
-"
-" Returns:
-" 0 if the line is not commented with either set of delims
-" 1 if the line is commented with the left/right delim set
-" 2 if the line is commented with the leftAlt/rightAlt delim set
-function s:IsCommentedOuttermost(left, right, leftAlt, rightAlt, line)
- "get the first positions of the left delims and the last positions of the
- "right delims
- let indxLeft = s:FindDelimiterIndex(a:left, a:line)
- let indxLeftAlt = s:FindDelimiterIndex(a:leftAlt, a:line)
- let indxRight = s:LastIndexOfDelim(a:right, a:line)
- let indxRightAlt = s:LastIndexOfDelim(a:rightAlt, a:line)
-
- "check if the line has a left delim before a leftAlt delim
- if (indxLeft <= indxLeftAlt || indxLeftAlt == -1) && indxLeft != -1
- "check if the line has a right delim after any rightAlt delim
- if (indxRight > indxRightAlt && indxRight > indxLeft) || !s:Multipart()
- return 1
- endif
-
- "check if the line has a leftAlt delim before a left delim
- elseif (indxLeftAlt <= indxLeft || indxLeft == -1) && indxLeftAlt != -1
- "check if the line has a rightAlt delim after any right delim
- if (indxRightAlt > indxRight && indxRightAlt > indxLeftAlt) || !s:AltMultipart()
- return 2
- endif
- else
- return 0
- endif
-
- return 0
-
-endfunction
-
-
-" Function: s:IsDelimValid(delimiter, delIndx, line) {{{2
-" This function is responsible for determining whether a given instance of a
-" comment delimiter is a real delimiter or not. For example, in java the
-" // string is a comment delimiter but in the line:
-" System.out.println("//");
-" it does not count as a comment delimiter. This function is responsible for
-" distinguishing between such cases. It does so by applying a set of
-" heuristics that are not fool proof but should work most of the time.
-"
-" Args:
-" -delimiter: the delimiter we are validating
-" -delIndx: the position of delimiter in line
-" -line: the line that delimiter occurs in
-"
-" Returns:
-" 0 if the given delimiter is not a real delimiter (as far as we can tell) ,
-" 1 otherwise
-function s:IsDelimValid(delimiter, delIndx, line)
- "get the delimiter without the escchars
- let l:delimiter = a:delimiter
-
- "get the strings before and after the delimiter
- let preComStr = strpart(a:line, 0, a:delIndx)
- let postComStr = strpart(a:line, a:delIndx+strlen(delimiter))
-
- "to check if the delimiter is real, make sure it isnt preceded by
- "an odd number of quotes and followed by the same (which would indicate
- "that it is part of a string and therefore is not a comment)
- if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, '"', "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, '"', "\\"))
- return 0
- endif
- if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, "'", "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, "'", "\\"))
- return 0
- endif
- if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, "`", "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, "`", "\\"))
- return 0
- endif
-
-
- "if the comment delimiter is escaped, assume it isnt a real delimiter
- if s:IsEscaped(a:line, a:delIndx, "\\")
- return 0
- endif
-
- "vim comments are so fuckin stupid!! Why the hell do they have comment
- "delimiters that are used elsewhere in the syntax?!?! We need to check
- "some conditions especially for vim
- if &filetype == "vim"
- if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, '"', "\\"))
- return 0
- endif
-
- "if the delimiter is on the very first char of the line or is the
- "first non-tab/space char on the line then it is a valid comment delimiter
- if a:delIndx == 0 || a:line =~ "^[ \t]\\{" . a:delIndx . "\\}\".*$"
- return 1
- endif
-
- let numLeftParen =s:CountNonESCedOccurances(preComStr, "(", "\\")
- let numRightParen =s:CountNonESCedOccurances(preComStr, ")", "\\")
-
- "if the quote is inside brackets then assume it isnt a comment
- if numLeftParen > numRightParen
- return 0
- endif
-
- "if the line has an even num of unescaped "'s then we can assume that
- "any given " is not a comment delimiter
- if s:IsNumEven(s:CountNonESCedOccurances(a:line, "\"", "\\"))
- return 0
- endif
- endif
-
- return 1
-
-endfunction
-
-" Function: s:IsNumEven(num) {{{2
-" A small function the returns 1 if the input number is even and 0 otherwise
-" Args:
-" -num: the number to check
-function s:IsNumEven(num)
- return (a:num % 2) == 0
-endfunction
-
-" Function: s:IsEscaped(str, indx, escChar) {{{2
-" This function takes a string, an index into that string and an esc char and
-" returns 1 if the char at the index is escaped (i.e if it is preceded by an
-" odd number of esc chars)
-" Args:
-" -str: the string to check
-" -indx: the index into str that we want to check
-" -escChar: the escape char the char at indx may be ESCed with
-function s:IsEscaped(str, indx, escChar)
- "initialise numEscChars to 0 and look at the char before indx
- let numEscChars = 0
- let curIndx = a:indx-1
-
- "keep going back thru str until we either reach the start of the str or
- "run out of esc chars
- while curIndx >= 0 && strpart(a:str, curIndx, 1) == a:escChar
-
- "we have found another esc char so add one to the count and move left
- "one char
- let numEscChars = numEscChars + 1
- let curIndx = curIndx - 1
-
- endwhile
-
- "if there is an odd num of esc chars directly before the char at indx then
- "the char at indx is escaped
- return !s:IsNumEven(numEscChars)
-endfunction
-
-" Function: s:IsInSexyComment(line) {{{2
-" returns 1 if the given line number is part of a sexy comment
-function s:IsInSexyComment(line)
- return !empty(s:FindBoundingLinesOfSexyCom(a:line))
-endfunction
-
-" Function: s:IsSexyComment(topline, bottomline) {{{2
-" This function takes in 2 line numbers and returns 1 if the lines between and
-" including the given line numbers are a sexy comment. It returns 0 otherwise.
-" Args:
-" -topline: the line that the possible sexy comment starts on
-" -bottomline: the line that the possible sexy comment stops on
-function s:IsSexyComment(topline, bottomline)
-
- "get the delim set that would be used for a sexy comment
- let left = ''
- let right = ''
- if s:Multipart()
- let left = b:NERDLeft
- let right = b:NERDRight
- elseif s:AltMultipart()
- let left = b:NERDLeftAlt
- let right = b:NERDRightAlt
- else
- return 0
- endif
-
- "swap the top and bottom line numbers around if need be
- let topline = a:topline
- let bottomline = a:bottomline
- if bottomline < topline
- topline = bottomline
- bottomline = a:topline
- endif
-
- "if there is < 2 lines in the comment it cannot be sexy
- if (bottomline - topline) <= 0
- return 0
- endif
-
- "if the top line doesnt begin with a left delim then the comment isnt sexy
- if getline(a:topline) !~ '^[ \t]*' . left
- return 0
- endif
-
- "if there is a right delim on the top line then this isnt a sexy comment
- if s:FindDelimiterIndex(right, getline(a:topline)) != -1
- return 0
- endif
-
- "if there is a left delim on the bottom line then this isnt a sexy comment
- if s:FindDelimiterIndex(left, getline(a:bottomline)) != -1
- return 0
- endif
-
- "if the bottom line doesnt begin with a right delim then the comment isnt
- "sexy
- if getline(a:bottomline) !~ '^.*' . right . '$'
- return 0
- endif
-
- let sexyComMarker = s:GetSexyComMarker(0, 1)
-
- "check each of the intermediate lines to make sure they start with a
- "sexyComMarker
- let currentLine = a:topline+1
- while currentLine < a:bottomline
- let theLine = getline(currentLine)
-
- if theLine !~ '^[ \t]*' . sexyComMarker
- return 0
- endif
-
- "if there is a right delim in an intermediate line then the block isnt
- "a sexy comment
- if s:FindDelimiterIndex(right, theLine) != -1
- return 0
- endif
-
- let currentLine = currentLine + 1
- endwhile
-
- "we have not found anything to suggest that this isnt a sexy comment so
- return 1
-
-endfunction
-
-" Function: s:LastIndexOfDelim(delim, str) {{{2
-" This function takes a string and a delimiter and returns the last index of
-" that delimiter in string
-" Args:
-" -delim: the delimiter to look for
-" -str: the string to look for delim in
-function s:LastIndexOfDelim(delim, str)
- let delim = a:delim
- let lenDelim = strlen(delim)
-
- "set index to the first occurrence of delim. If there is no occurrence then
- "bail
- let indx = s:FindDelimiterIndex(delim, a:str)
- if indx == -1
- return -1
- endif
-
- "keep moving to the next instance of delim in str till there is none left
- while 1
-
- "search for the next delim after the previous one
- let searchStr = strpart(a:str, indx+lenDelim)
- let indx2 = s:FindDelimiterIndex(delim, searchStr)
-
- "if we find a delim update indx to record the position of it, if we
- "dont find another delim then indx is the last one so break out of
- "this loop
- if indx2 != -1
- let indx = indx + indx2 + lenDelim
- else
- break
- endif
- endwhile
-
- return indx
-
-endfunction
-
-" Function: s:LeftMostIndx(countCommentedLines, countEmptyLines, topline, bottomline) {{{2
-" This function takes in 2 line numbers and returns the index of the left most
-" char (that is not a space or a tab) on all of these lines.
-" Args:
-" -countCommentedLines: 1 if lines that are commented are to be checked as
-" well. 0 otherwise
-" -countEmptyLines: 1 if empty lines are to be counted in the search
-" -topline: the top line to be checked
-" -bottomline: the bottom line to be checked
-function s:LeftMostIndx(countCommentedLines, countEmptyLines, topline, bottomline)
-
- " declare the left most index as an extreme value
- let leftMostIndx = 1000
-
- " go thru the block line by line updating leftMostIndx
- let currentLine = a:topline
- while currentLine <= a:bottomline
-
- " get the next line and if it is allowed to be commented, or is not
- " commented, check it
- let theLine = getline(currentLine)
- if a:countEmptyLines || theLine !~ '^[ \t]*$'
- if a:countCommentedLines || (!s:IsCommented(b:NERDLeft, b:NERDRight, theLine) && !s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine))
- " convert spaces to tabs and get the number of leading spaces for
- " this line and update leftMostIndx if need be
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- let leadSpaceOfLine = strlen( substitute(theLine, '\(^[ \t]*\).*$','\1','') )
- if leadSpaceOfLine < leftMostIndx
- let leftMostIndx = leadSpaceOfLine
- endif
- endif
- endif
-
- " move on to the next line
- let currentLine = currentLine + 1
- endwhile
-
- if leftMostIndx == 1000
- return 0
- else
- return leftMostIndx
- endif
-endfunction
-
-" Function: s:Multipart() {{{2
-" returns 1 if the current delims are multipart
-function s:Multipart()
- return b:NERDRight != ''
-endfunction
-
-" Function: s:NerdEcho(msg, typeOfMsg) {{{2
-" Args:
-" -msg: the message to echo
-" -typeOfMsg: 0 = warning message
-" 1 = normal message
-function s:NerdEcho(msg, typeOfMsg)
- if a:typeOfMsg == 0
- echohl WarningMsg
- echo 'NERDCommenter:' . a:msg
- echohl None
- elseif a:typeOfMsg == 1
- echo 'NERDCommenter:' . a:msg
- endif
-endfunction
-
-" Function: s:NumberOfLeadingTabs(s) {{{2
-" returns the number of leading tabs in the given string
-function s:NumberOfLeadingTabs(s)
- return strlen(substitute(a:s, '^\(\t*\).*$', '\1', ""))
-endfunction
-
-" Function: s:NumLinesInBuf() {{{2
-" Returns the number of lines in the current buffer
-function s:NumLinesInBuf()
- return line('$')
-endfunction
-
-" Function: s:ReplaceDelims(toReplace1, toReplace2, replacor1, replacor2, str) {{{2
-" This function takes in a string, 2 delimiters in that string and 2 strings
-" to replace these delimiters with.
-"
-" Args:
-" -toReplace1: the first delimiter to replace
-" -toReplace2: the second delimiter to replace
-" -replacor1: the string to replace toReplace1 with
-" -replacor2: the string to replace toReplace2 with
-" -str: the string that the delimiters to be replaced are in
-function s:ReplaceDelims(toReplace1, toReplace2, replacor1, replacor2, str)
- let line = s:ReplaceLeftMostDelim(a:toReplace1, a:replacor1, a:str)
- let line = s:ReplaceRightMostDelim(a:toReplace2, a:replacor2, line)
- return line
-endfunction
-
-" Function: s:ReplaceLeftMostDelim(toReplace, replacor, str) {{{2
-" This function takes a string and a delimiter and replaces the left most
-" occurrence of this delimiter in the string with a given string
-"
-" Args:
-" -toReplace: the delimiter in str that is to be replaced
-" -replacor: the string to replace toReplace with
-" -str: the string that contains toReplace
-function s:ReplaceLeftMostDelim(toReplace, replacor, str)
- let toReplace = a:toReplace
- let replacor = a:replacor
- "get the left most occurrence of toReplace
- let indxToReplace = s:FindDelimiterIndex(toReplace, a:str)
-
- "if there IS an occurrence of toReplace in str then replace it and return
- "the resulting string
- if indxToReplace != -1
- let line = strpart(a:str, 0, indxToReplace) . replacor . strpart(a:str, indxToReplace+strlen(toReplace))
- return line
- endif
-
- return a:str
-endfunction
-
-" Function: s:ReplaceRightMostDelim(toReplace, replacor, str) {{{2
-" This function takes a string and a delimiter and replaces the right most
-" occurrence of this delimiter in the string with a given string
-"
-" Args:
-" -toReplace: the delimiter in str that is to be replaced
-" -replacor: the string to replace toReplace with
-" -str: the string that contains toReplace
-"
-function s:ReplaceRightMostDelim(toReplace, replacor, str)
- let toReplace = a:toReplace
- let replacor = a:replacor
- let lenToReplace = strlen(toReplace)
-
- "get the index of the last delim in str
- let indxToReplace = s:LastIndexOfDelim(toReplace, a:str)
-
- "if there IS a delimiter in str, replace it and return the result
- let line = a:str
- if indxToReplace != -1
- let line = strpart(a:str, 0, indxToReplace) . replacor . strpart(a:str, indxToReplace+strlen(toReplace))
- endif
- return line
-endfunction
-
-"FUNCTION: s:RestoreScreenState() {{{2
-"
-"Sets the screen state back to what it was when s:SaveScreenState was last
-"called.
-"
-function s:RestoreScreenState()
- if !exists("t:NERDComOldTopLine") || !exists("t:NERDComOldPos")
- throw 'NERDCommenter exception: cannot restore screen'
- endif
-
- call cursor(t:NERDComOldTopLine, 0)
- normal! zt
- call setpos(".", t:NERDComOldPos)
-endfunction
-
-" Function: s:RightMostIndx(countCommentedLines, countEmptyLines, topline, bottomline) {{{2
-" This function takes in 2 line numbers and returns the index of the right most
-" char on all of these lines.
-" Args:
-" -countCommentedLines: 1 if lines that are commented are to be checked as
-" well. 0 otherwise
-" -countEmptyLines: 1 if empty lines are to be counted in the search
-" -topline: the top line to be checked
-" -bottomline: the bottom line to be checked
-function s:RightMostIndx(countCommentedLines, countEmptyLines, topline, bottomline)
- let rightMostIndx = -1
-
- " go thru the block line by line updating rightMostIndx
- let currentLine = a:topline
- while currentLine <= a:bottomline
-
- " get the next line and see if it is commentable, otherwise it doesnt
- " count
- let theLine = getline(currentLine)
- if a:countEmptyLines || theLine !~ '^[ \t]*$'
-
- if a:countCommentedLines || (!s:IsCommented(b:NERDLeft, b:NERDRight, theLine) && !s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine))
-
- " update rightMostIndx if need be
- let theLine = s:ConvertLeadingTabsToSpaces(theLine)
- let lineLen = strlen(theLine)
- if lineLen > rightMostIndx
- let rightMostIndx = lineLen
- endif
- endif
- endif
-
- " move on to the next line
- let currentLine = currentLine + 1
- endwhile
-
- return rightMostIndx
-endfunction
-
-"FUNCTION: s:SaveScreenState() {{{2
-"Saves the current cursor position in the current buffer and the window
-"scroll position
-function s:SaveScreenState()
- let t:NERDComOldPos = getpos(".")
- let t:NERDComOldTopLine = line("w0")
-endfunction
-
-" Function: s:SwapOutterMultiPartDelimsForPlaceHolders(line) {{{2
-" This function takes a line and swaps the outter most multi-part delims for
-" place holders
-" Args:
-" -line: the line to swap the delims in
-"
-function s:SwapOutterMultiPartDelimsForPlaceHolders(line)
- " find out if the line is commented using normal delims and/or
- " alternate ones
- let isCommented = s:IsCommented(b:NERDLeft, b:NERDRight, a:line)
- let isCommentedAlt = s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, a:line)
-
- let line2 = a:line
-
- "if the line is commented and there is a right delimiter, replace
- "the delims with place-holders
- if isCommented && s:Multipart()
- let line2 = s:ReplaceDelims(b:NERDLeft, b:NERDRight, g:NERDLPlace, g:NERDRPlace, a:line)
-
- "similarly if the line is commented with the alternative
- "delimiters
- elseif isCommentedAlt && s:AltMultipart()
- let line2 = s:ReplaceDelims(b:NERDLeftAlt, b:NERDRightAlt, g:NERDLPlace, g:NERDRPlace, a:line)
- endif
-
- return line2
-endfunction
-
-" Function: s:SwapOutterPlaceHoldersForMultiPartDelims(line) {{{2
-" This function takes a line and swaps the outtermost place holders for
-" multi-part delims
-" Args:
-" -line: the line to swap the delims in
-"
-function s:SwapOutterPlaceHoldersForMultiPartDelims(line)
- let left = ''
- let right = ''
- if s:Multipart()
- let left = b:NERDLeft
- let right = b:NERDRight
- elseif s:AltMultipart()
- let left = b:NERDLeftAlt
- let right = b:NERDRightAlt
- endif
-
- let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, a:line)
- return line
-endfunction
-" Function: s:TabbedCol(line, col) {{{2
-" Gets the col number for given line and existing col number. The new col
-" number is the col number when all leading spaces are converted to tabs
-" Args:
-" -line:the line to get the rel col for
-" -col: the abs col
-function s:TabbedCol(line, col)
- let lineTruncated = strpart(a:line, 0, a:col)
- let lineSpacesToTabs = substitute(lineTruncated, s:TabSpace(), '\t', 'g')
- return strlen(lineSpacesToTabs)
-endfunction
-"FUNCTION: s:TabSpace() {{{2
-"returns a string of spaces equal in length to &tabstop
-function s:TabSpace()
- let tabSpace = ""
- let spacesPerTab = &tabstop
- while spacesPerTab > 0
- let tabSpace = tabSpace . " "
- let spacesPerTab = spacesPerTab - 1
- endwhile
- return tabSpace
-endfunction
-
-" Function: s:UnEsc(str, escChar) {{{2
-" This function removes all the escape chars from a string
-" Args:
-" -str: the string to remove esc chars from
-" -escChar: the escape char to be removed
-function s:UnEsc(str, escChar)
- return substitute(a:str, a:escChar, "", "g")
-endfunction
-
-" Function: s:UntabbedCol(line, col) {{{2
-" Takes a line and a col and returns the absolute column of col taking into
-" account that a tab is worth 3 or 4 (or whatever) spaces.
-" Args:
-" -line:the line to get the abs col for
-" -col: the col that doesnt take into account tabs
-function s:UntabbedCol(line, col)
- let lineTruncated = strpart(a:line, 0, a:col)
- let lineTabsToSpaces = substitute(lineTruncated, '\t', s:TabSpace(), 'g')
- return strlen(lineTabsToSpaces)
-endfunction
-" Section: Comment mapping setup {{{1
-" ===========================================================================
-
-" switch to/from alternative delimiters
-nnoremap <plug>NERDCommenterAltDelims :call <SID>SwitchToAlternativeDelimiters(1)<cr>
-
-" comment out lines
-nnoremap <silent> <plug>NERDCommenterComment :call NERDComment(0, "norm")<cr>
-vnoremap <silent> <plug>NERDCommenterComment <ESC>:call NERDComment(1, "norm")<cr>
-
-" toggle comments
-nnoremap <silent> <plug>NERDCommenterToggle :call NERDComment(0, "toggle")<cr>
-vnoremap <silent> <plug>NERDCommenterToggle <ESC>:call NERDComment(1, "toggle")<cr>
-
-" minimal comments
-nnoremap <silent> <plug>NERDCommenterMinimal :call NERDComment(0, "minimal")<cr>
-vnoremap <silent> <plug>NERDCommenterMinimal <ESC>:call NERDComment(1, "minimal")<cr>
-
-" sexy comments
-nnoremap <silent> <plug>NERDCommenterSexy :call NERDComment(0, "sexy")<CR>
-vnoremap <silent> <plug>NERDCommenterSexy <ESC>:call NERDComment(1, "sexy")<CR>
-
-" invert comments
-nnoremap <silent> <plug>NERDCommenterInvert :call NERDComment(0, "invert")<CR>
-vnoremap <silent> <plug>NERDCommenterInvert <ESC>:call NERDComment(1, "invert")<CR>
-
-" yank then comment
-nmap <silent> <plug>NERDCommenterYank :call NERDComment(0, "yank")<CR>
-vmap <silent> <plug>NERDCommenterYank <ESC>:call NERDComment(1, "yank")<CR>
-
-" left aligned comments
-nnoremap <silent> <plug>NERDCommenterAlignLeft :call NERDComment(0, "alignLeft")<cr>
-vnoremap <silent> <plug>NERDCommenterAlignLeft <ESC>:call NERDComment(1, "alignLeft")<cr>
-
-" left and right aligned comments
-nnoremap <silent> <plug>NERDCommenterAlignBoth :call NERDComment(0, "alignBoth")<cr>
-vnoremap <silent> <plug>NERDCommenterAlignBoth <ESC>:call NERDComment(1, "alignBoth")<cr>
-
-" nested comments
-nnoremap <silent> <plug>NERDCommenterNest :call NERDComment(0, "nested")<cr>
-vnoremap <silent> <plug>NERDCommenterNest <ESC>:call NERDComment(1, "nested")<cr>
-
-" uncomment
-nnoremap <silent> <plug>NERDCommenterUncomment :call NERDComment(0, "uncomment")<cr>
-vnoremap <silent> <plug>NERDCommenterUncomment :call NERDComment(1, "uncomment")<cr>
-
-" comment till the end of the line
-nnoremap <silent> <plug>NERDCommenterToEOL :call NERDComment(0, "toEOL")<cr>
-
-" append comments
-nmap <silent> <plug>NERDCommenterAppend :call NERDComment(0, "append")<cr>
-
-" insert comments
-inoremap <silent> <plug>NERDCommenterInInsert <SPACE><BS><ESC>:call NERDComment(0, "insert")<CR>
-
-
-function! s:CreateMaps(target, combo)
- if !hasmapto(a:target, 'n')
- exec 'nmap ' . a:combo . ' ' . a:target
- endif
-
- if !hasmapto(a:target, 'v')
- exec 'vmap ' . a:combo . ' ' . a:target
- endif
-endfunction
-
-if g:NERDCreateDefaultMappings
- call s:CreateMaps('<plug>NERDCommenterComment', ',cc')
- call s:CreateMaps('<plug>NERDCommenterToggle', ',c<space>')
- call s:CreateMaps('<plug>NERDCommenterMinimal', ',cm')
- call s:CreateMaps('<plug>NERDCommenterSexy', ',cs')
- call s:CreateMaps('<plug>NERDCommenterInvert', ',ci')
- call s:CreateMaps('<plug>NERDCommenterYank', ',cy')
- call s:CreateMaps('<plug>NERDCommenterAlignLeft', ',cl')
- call s:CreateMaps('<plug>NERDCommenterAlignBoth', ',cb')
- call s:CreateMaps('<plug>NERDCommenterNest', ',cn')
- call s:CreateMaps('<plug>NERDCommenterUncomment', ',cu')
- call s:CreateMaps('<plug>NERDCommenterToEOL', ',c$')
- call s:CreateMaps('<plug>NERDCommenterAppend', ',cA')
-
- if !hasmapto('<plug>NERDCommenterAltDelims', 'n')
- nmap ,ca <plug>NERDCommenterAltDelims
- endif
-endif
-
-
-
-" Section: Menu item setup {{{1
-" ===========================================================================
-"check if the user wants the menu to be displayed
-if g:NERDMenuMode != 0
-
- let menuRoot = ""
- if g:NERDMenuMode == 1
- let menuRoot = 'comment'
- elseif g:NERDMenuMode == 2
- let menuRoot = '&comment'
- elseif g:NERDMenuMode == 3
- let menuRoot = '&Plugin.&comment'
- endif
-
- function! s:CreateMenuItems(target, desc, root)
- exec 'nmenu <silent> ' . a:root . '.' . a:desc . ' ' . a:target
- exec 'vmenu <silent> ' . a:root . '.' . a:desc . ' ' . a:target
- endfunction
- call s:CreateMenuItems("<plug>NERDCommenterComment", 'Comment', menuRoot)
- call s:CreateMenuItems("<plug>NERDCommenterToggle", 'Toggle', menuRoot)
- call s:CreateMenuItems('<plug>NERDCommenterMinimal', 'Minimal', menuRoot)
- call s:CreateMenuItems('<plug>NERDCommenterNest', 'Nested', menuRoot)
- exec 'nmenu <silent> '. menuRoot .'.To\ EOL <plug>NERDCommenterToEOL'
- call s:CreateMenuItems('<plug>NERDCommenterInvert', 'Invert', menuRoot)
- call s:CreateMenuItems('<plug>NERDCommenterSexy', 'Sexy', menuRoot)
- call s:CreateMenuItems('<plug>NERDCommenterYank', 'Yank\ then\ comment', menuRoot)
- exec 'nmenu <silent> '. menuRoot .'.Append <plug>NERDCommenterAppend'
- exec 'menu <silent> '. menuRoot .'.-Sep- :'
- call s:CreateMenuItems('<plug>NERDCommenterAlignLeft', 'Left\ aligned', menuRoot)
- call s:CreateMenuItems('<plug>NERDCommenterAlignBoth', 'Left\ and\ right\ aligned', menuRoot)
- exec 'menu <silent> '. menuRoot .'.-Sep2- :'
- call s:CreateMenuItems('<plug>NERDCommenterUncomment', 'Uncomment', menuRoot)
- exec 'nmenu <silent> '. menuRoot .'.Switch\ Delimiters <plug>NERDCommenterAltDelims'
- exec 'imenu <silent> '. menuRoot .'.Insert\ Comment\ Here <plug>NERDCommenterInInsert'
- exec 'menu <silent> '. menuRoot .'.-Sep3- :'
- exec 'menu <silent>'. menuRoot .'.Help :help NERDCommenterContents<CR>'
-endif
-" vim: set foldmethod=marker :
--- a/vim/bundle/nerdtree/plugin/NERD_tree.vim Mon Nov 22 14:44:00 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4059 +0,0 @@
-" ============================================================================
-" File: NERD_tree.vim
-" Description: vim global plugin that provides a nice tree explorer
-" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
-" Last Change: 1 December, 2009
-" License: This program is free software. It comes without any warranty,
-" to the extent permitted by applicable law. You can redistribute
-" it and/or modify it under the terms of the Do What The Fuck You
-" Want To Public License, Version 2, as published by Sam Hocevar.
-" See http://sam.zoy.org/wtfpl/COPYING for more details.
-"
-" ============================================================================
-let s:NERD_tree_version = '4.1.0'
-
-" SECTION: Script init stuff {{{1
-"============================================================
-if exists("loaded_nerd_tree")
- finish
-endif
-if v:version < 700
- echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
- finish
-endif
-let loaded_nerd_tree = 1
-
-"for line continuation - i.e dont want C in &cpo
-let s:old_cpo = &cpo
-set cpo&vim
-
-"Function: s:initVariable() function {{{2
-"This function is used to initialise a given variable to a given value. The
-"variable is only initialised if it does not exist prior
-"
-"Args:
-"var: the name of the var to be initialised
-"value: the value to initialise var to
-"
-"Returns:
-"1 if the var is set, 0 otherwise
-function! s:initVariable(var, value)
- if !exists(a:var)
- exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
- return 1
- endif
- return 0
-endfunction
-
-"SECTION: Init variable calls and other random constants {{{2
-call s:initVariable("g:NERDChristmasTree", 1)
-call s:initVariable("g:NERDTreeAutoCenter", 1)
-call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
-call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
-call s:initVariable("g:NERDTreeChDirMode", 0)
-if !exists("g:NERDTreeIgnore")
- let g:NERDTreeIgnore = ['\~$']
-endif
-call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
-call s:initVariable("g:NERDTreeHighlightCursorline", 1)
-call s:initVariable("g:NERDTreeHijackNetrw", 1)
-call s:initVariable("g:NERDTreeMouseMode", 1)
-call s:initVariable("g:NERDTreeNotificationThreshold", 100)
-call s:initVariable("g:NERDTreeQuitOnOpen", 0)
-call s:initVariable("g:NERDTreeShowBookmarks", 0)
-call s:initVariable("g:NERDTreeShowFiles", 1)
-call s:initVariable("g:NERDTreeShowHidden", 0)
-call s:initVariable("g:NERDTreeShowLineNumbers", 0)
-call s:initVariable("g:NERDTreeSortDirs", 1)
-
-if !exists("g:NERDTreeSortOrder")
- let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
-else
- "if there isnt a * in the sort sequence then add one
- if count(g:NERDTreeSortOrder, '*') < 1
- call add(g:NERDTreeSortOrder, '*')
- endif
-endif
-
-"we need to use this number many times for sorting... so we calculate it only
-"once here
-let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
-
-if !exists('g:NERDTreeStatusline')
-
- "the exists() crap here is a hack to stop vim spazzing out when
- "loading a session that was created with an open nerd tree. It spazzes
- "because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash)
- let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}"
-
-endif
-call s:initVariable("g:NERDTreeWinPos", "left")
-call s:initVariable("g:NERDTreeWinSize", 31)
-
-let s:running_windows = has("win16") || has("win32") || has("win64")
-
-"init the shell commands that will be used to copy nodes, and remove dir trees
-"
-"Note: the space after the command is important
-if s:running_windows
- call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
-else
- call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
- call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
-endif
-
-
-"SECTION: Init variable calls for key mappings {{{2
-call s:initVariable("g:NERDTreeMapActivateNode", "o")
-call s:initVariable("g:NERDTreeMapChangeRoot", "C")
-call s:initVariable("g:NERDTreeMapChdir", "cd")
-call s:initVariable("g:NERDTreeMapCloseChildren", "X")
-call s:initVariable("g:NERDTreeMapCloseDir", "x")
-call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
-call s:initVariable("g:NERDTreeMapMenu", "m")
-call s:initVariable("g:NERDTreeMapHelp", "?")
-call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
-call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
-call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
-call s:initVariable("g:NERDTreeMapJumpParent", "p")
-call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
-call s:initVariable("g:NERDTreeMapJumpRoot", "P")
-call s:initVariable("g:NERDTreeMapOpenExpl", "e")
-call s:initVariable("g:NERDTreeMapOpenInTab", "t")
-call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
-call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
-call s:initVariable("g:NERDTreeMapOpenSplit", "i")
-call s:initVariable("g:NERDTreeMapOpenVSplit", "s")
-call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
-call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
-call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit)
-call s:initVariable("g:NERDTreeMapQuit", "q")
-call s:initVariable("g:NERDTreeMapRefresh", "r")
-call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
-call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
-call s:initVariable("g:NERDTreeMapToggleFiles", "F")
-call s:initVariable("g:NERDTreeMapToggleFilters", "f")
-call s:initVariable("g:NERDTreeMapToggleHidden", "I")
-call s:initVariable("g:NERDTreeMapToggleZoom", "A")
-call s:initVariable("g:NERDTreeMapUpdir", "u")
-call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
-
-"SECTION: Script level variable declaration{{{2
-if s:running_windows
- let s:escape_chars = " `\|\"#%&,?()\*^<>"
-else
- let s:escape_chars = " \\`\|\"#%&,?()\*^<>"
-endif
-let s:NERDTreeBufName = 'NERD_tree_'
-
-let s:tree_wid = 2
-let s:tree_markup_reg = '^[ `|]*[\-+~]'
-let s:tree_up_dir_line = '.. (up a dir)'
-
-"the number to add to the nerd tree buffer name to make the buf name unique
-let s:next_buffer_number = 1
-
-" SECTION: Commands {{{1
-"============================================================
-"init the command that users start the nerd tree with
-command! -n=? -complete=dir -bar NERDTree :call s:initNerdTree('<args>')
-command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('<args>')
-command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen()
-command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('<args>')
-command! -n=0 -bar NERDTreeMirror call s:initNerdTreeMirror()
-command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
-" SECTION: Auto commands {{{1
-"============================================================
-augroup NERDTree
- "Save the cursor position whenever we close the nerd tree
- exec "autocmd BufWinLeave ". s:NERDTreeBufName ."* call <SID>saveScreenState()"
- "cache bookmarks when vim loads
- autocmd VimEnter * call s:Bookmark.CacheBookmarks(0)
-
- "load all nerdtree plugins after vim starts
- autocmd VimEnter * runtime! nerdtree_plugin/**/*.vim
-augroup END
-
-if g:NERDTreeHijackNetrw
- augroup NERDTreeHijackNetrw
- autocmd VimEnter * silent! autocmd! FileExplorer
- au BufEnter,VimEnter * call s:checkForBrowse(expand("<amatch>"))
- augroup END
-endif
-
-"SECTION: Classes {{{1
-"============================================================
-"CLASS: Bookmark {{{2
-"============================================================
-let s:Bookmark = {}
-" FUNCTION: Bookmark.activate() {{{3
-function! s:Bookmark.activate()
- if self.path.isDirectory
- call self.toRoot()
- else
- if self.validate()
- let n = s:TreeFileNode.New(self.path)
- call n.open()
- endif
- endif
-endfunction
-" FUNCTION: Bookmark.AddBookmark(name, path) {{{3
-" Class method to add a new bookmark to the list, if a previous bookmark exists
-" with the same name, just update the path for that bookmark
-function! s:Bookmark.AddBookmark(name, path)
- for i in s:Bookmark.Bookmarks()
- if i.name ==# a:name
- let i.path = a:path
- return
- endif
- endfor
- call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
- call s:Bookmark.Sort()
-endfunction
-" Function: Bookmark.Bookmarks() {{{3
-" Class method to get all bookmarks. Lazily initializes the bookmarks global
-" variable
-function! s:Bookmark.Bookmarks()
- if !exists("g:NERDTreeBookmarks")
- let g:NERDTreeBookmarks = []
- endif
- return g:NERDTreeBookmarks
-endfunction
-" Function: Bookmark.BookmarkExistsFor(name) {{{3
-" class method that returns 1 if a bookmark with the given name is found, 0
-" otherwise
-function! s:Bookmark.BookmarkExistsFor(name)
- try
- call s:Bookmark.BookmarkFor(a:name)
- return 1
- catch /^NERDTree.BookmarkNotFoundError/
- return 0
- endtry
-endfunction
-" Function: Bookmark.BookmarkFor(name) {{{3
-" Class method to get the bookmark that has the given name. {} is return if no
-" bookmark is found
-function! s:Bookmark.BookmarkFor(name)
- for i in s:Bookmark.Bookmarks()
- if i.name ==# a:name
- return i
- endif
- endfor
- throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
-endfunction
-" Function: Bookmark.BookmarkNames() {{{3
-" Class method to return an array of all bookmark names
-function! s:Bookmark.BookmarkNames()
- let names = []
- for i in s:Bookmark.Bookmarks()
- call add(names, i.name)
- endfor
- return names
-endfunction
-" FUNCTION: Bookmark.CacheBookmarks(silent) {{{3
-" Class method to read all bookmarks from the bookmarks file intialize
-" bookmark objects for each one.
-"
-" Args:
-" silent - dont echo an error msg if invalid bookmarks are found
-function! s:Bookmark.CacheBookmarks(silent)
- if filereadable(g:NERDTreeBookmarksFile)
- let g:NERDTreeBookmarks = []
- let g:NERDTreeInvalidBookmarks = []
- let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
- let invalidBookmarksFound = 0
- for i in bookmarkStrings
-
- "ignore blank lines
- if i != ''
-
- let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
- let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
-
- try
- let bookmark = s:Bookmark.New(name, s:Path.New(path))
- call add(g:NERDTreeBookmarks, bookmark)
- catch /^NERDTree.InvalidArgumentsError/
- call add(g:NERDTreeInvalidBookmarks, i)
- let invalidBookmarksFound += 1
- endtry
- endif
- endfor
- if invalidBookmarksFound
- call s:Bookmark.Write()
- if !a:silent
- call s:echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
- endif
- endif
- call s:Bookmark.Sort()
- endif
-endfunction
-" FUNCTION: Bookmark.compareTo(otherbookmark) {{{3
-" Compare these two bookmarks for sorting purposes
-function! s:Bookmark.compareTo(otherbookmark)
- return a:otherbookmark.name < self.name
-endfunction
-" FUNCTION: Bookmark.ClearAll() {{{3
-" Class method to delete all bookmarks.
-function! s:Bookmark.ClearAll()
- for i in s:Bookmark.Bookmarks()
- call i.delete()
- endfor
- call s:Bookmark.Write()
-endfunction
-" FUNCTION: Bookmark.delete() {{{3
-" Delete this bookmark. If the node for this bookmark is under the current
-" root, then recache bookmarks for its Path object
-function! s:Bookmark.delete()
- let node = {}
- try
- let node = self.getNode(1)
- catch /^NERDTree.BookmarkedNodeNotFoundError/
- endtry
- call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
- if !empty(node)
- call node.path.cacheDisplayString()
- endif
- call s:Bookmark.Write()
-endfunction
-" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{3
-" Gets the treenode for this bookmark
-"
-" Args:
-" searchFromAbsoluteRoot: specifies whether we should search from the current
-" tree root, or the highest cached node
-function! s:Bookmark.getNode(searchFromAbsoluteRoot)
- let searchRoot = a:searchFromAbsoluteRoot ? s:TreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot
- let targetNode = searchRoot.findNode(self.path)
- if empty(targetNode)
- throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name
- endif
- return targetNode
-endfunction
-" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3
-" Class method that finds the bookmark with the given name and returns the
-" treenode for it.
-function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
- let bookmark = s:Bookmark.BookmarkFor(a:name)
- return bookmark.getNode(a:searchFromAbsoluteRoot)
-endfunction
-" FUNCTION: Bookmark.GetSelected() {{{3
-" returns the Bookmark the cursor is over, or {}
-function! s:Bookmark.GetSelected()
- let line = getline(".")
- let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
- if name != line
- try
- return s:Bookmark.BookmarkFor(name)
- catch /^NERDTree.BookmarkNotFoundError/
- return {}
- endtry
- endif
- return {}
-endfunction
-
-" Function: Bookmark.InvalidBookmarks() {{{3
-" Class method to get all invalid bookmark strings read from the bookmarks
-" file
-function! s:Bookmark.InvalidBookmarks()
- if !exists("g:NERDTreeInvalidBookmarks")
- let g:NERDTreeInvalidBookmarks = []
- endif
- return g:NERDTreeInvalidBookmarks
-endfunction
-" FUNCTION: Bookmark.mustExist() {{{3
-function! s:Bookmark.mustExist()
- if !self.path.exists()
- call s:Bookmark.CacheBookmarks(1)
- throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
- \ self.name ."\" points to a non existing location: \"". self.path.str()
- endif
-endfunction
-" FUNCTION: Bookmark.New(name, path) {{{3
-" Create a new bookmark object with the given name and path object
-function! s:Bookmark.New(name, path)
- if a:name =~ ' '
- throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
- endif
-
- let newBookmark = copy(self)
- let newBookmark.name = a:name
- let newBookmark.path = a:path
- return newBookmark
-endfunction
-" FUNCTION: Bookmark.openInNewTab(options) {{{3
-" Create a new bookmark object with the given name and path object
-function! s:Bookmark.openInNewTab(options)
- let currentTab = tabpagenr()
- if self.path.isDirectory
- tabnew
- call s:initNerdTree(self.name)
- else
- exec "tabedit " . bookmark.path.str({'format': 'Edit'})
- endif
-
- if has_key(a:options, 'stayInCurrentTab')
- exec "tabnext " . currentTab
- endif
-endfunction
-" Function: Bookmark.setPath(path) {{{3
-" makes this bookmark point to the given path
-function! s:Bookmark.setPath(path)
- let self.path = a:path
-endfunction
-" Function: Bookmark.Sort() {{{3
-" Class method that sorts all bookmarks
-function! s:Bookmark.Sort()
- let CompareFunc = function("s:compareBookmarks")
- call sort(s:Bookmark.Bookmarks(), CompareFunc)
-endfunction
-" Function: Bookmark.str() {{{3
-" Get the string that should be rendered in the view for this bookmark
-function! s:Bookmark.str()
- let pathStrMaxLen = winwidth(s:getTreeWinNum()) - 4 - len(self.name)
- if &nu
- let pathStrMaxLen = pathStrMaxLen - &numberwidth
- endif
-
- let pathStr = self.path.str({'format': 'UI'})
- if len(pathStr) > pathStrMaxLen
- let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
- endif
- return '>' . self.name . ' ' . pathStr
-endfunction
-" FUNCTION: Bookmark.toRoot() {{{3
-" Make the node for this bookmark the new tree root
-function! s:Bookmark.toRoot()
- if self.validate()
- try
- let targetNode = self.getNode(1)
- catch /^NERDTree.BookmarkedNodeNotFoundError/
- let targetNode = s:TreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
- endtry
- call targetNode.makeRoot()
- call s:renderView()
- call targetNode.putCursorHere(0, 0)
- endif
-endfunction
-" FUNCTION: Bookmark.ToRoot(name) {{{3
-" Make the node for this bookmark the new tree root
-function! s:Bookmark.ToRoot(name)
- let bookmark = s:Bookmark.BookmarkFor(a:name)
- call bookmark.toRoot()
-endfunction
-
-
-"FUNCTION: Bookmark.validate() {{{3
-function! s:Bookmark.validate()
- if self.path.exists()
- return 1
- else
- call s:Bookmark.CacheBookmarks(1)
- call s:renderView()
- call s:echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
- return 0
- endif
-endfunction
-
-" Function: Bookmark.Write() {{{3
-" Class method to write all bookmarks to the bookmarks file
-function! s:Bookmark.Write()
- let bookmarkStrings = []
- for i in s:Bookmark.Bookmarks()
- call add(bookmarkStrings, i.name . ' ' . i.path.str())
- endfor
-
- "add a blank line before the invalid ones
- call add(bookmarkStrings, "")
-
- for j in s:Bookmark.InvalidBookmarks()
- call add(bookmarkStrings, j)
- endfor
- call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
-endfunction
-"CLASS: KeyMap {{{2
-"============================================================
-let s:KeyMap = {}
-"FUNCTION: KeyMap.All() {{{3
-function! s:KeyMap.All()
- if !exists("s:keyMaps")
- let s:keyMaps = []
- endif
- return s:keyMaps
-endfunction
-
-"FUNCTION: KeyMap.BindAll() {{{3
-function! s:KeyMap.BindAll()
- for i in s:KeyMap.All()
- call i.bind()
- endfor
-endfunction
-
-"FUNCTION: KeyMap.bind() {{{3
-function! s:KeyMap.bind()
- exec "nnoremap <silent> <buffer> ". self.key ." :call ". self.callback ."()<cr>"
-endfunction
-
-"FUNCTION: KeyMap.Create(options) {{{3
-function! s:KeyMap.Create(options)
- let newKeyMap = copy(self)
- let newKeyMap.key = a:options['key']
- let newKeyMap.quickhelpText = a:options['quickhelpText']
- let newKeyMap.callback = a:options['callback']
- call add(s:KeyMap.All(), newKeyMap)
-endfunction
-"CLASS: MenuController {{{2
-"============================================================
-let s:MenuController = {}
-"FUNCTION: MenuController.New(menuItems) {{{3
-"create a new menu controller that operates on the given menu items
-function! s:MenuController.New(menuItems)
- let newMenuController = copy(self)
- if a:menuItems[0].isSeparator()
- let newMenuController.menuItems = a:menuItems[1:-1]
- else
- let newMenuController.menuItems = a:menuItems
- endif
- return newMenuController
-endfunction
-
-"FUNCTION: MenuController.showMenu() {{{3
-"start the main loop of the menu and get the user to choose/execute a menu
-"item
-function! s:MenuController.showMenu()
- call self._saveOptions()
-
- try
- let self.selection = 0
-
- let done = 0
- while !done
- redraw!
- call self._echoPrompt()
- let key = nr2char(getchar())
- let done = self._handleKeypress(key)
- endwhile
- finally
- call self._restoreOptions()
- endtry
-
- if self.selection != -1
- let m = self._current()
- call m.execute()
- endif
-endfunction
-
-"FUNCTION: MenuController._echoPrompt() {{{3
-function! s:MenuController._echoPrompt()
- echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated"
- echo "=========================================================="
-
- for i in range(0, len(self.menuItems)-1)
- if self.selection == i
- echo "> " . self.menuItems[i].text
- else
- echo " " . self.menuItems[i].text
- endif
- endfor
-endfunction
-
-"FUNCTION: MenuController._current(key) {{{3
-"get the MenuItem that is curently selected
-function! s:MenuController._current()
- return self.menuItems[self.selection]
-endfunction
-
-"FUNCTION: MenuController._handleKeypress(key) {{{3
-"change the selection (if appropriate) and return 1 if the user has made
-"their choice, 0 otherwise
-function! s:MenuController._handleKeypress(key)
- if a:key == 'j'
- call self._cursorDown()
- elseif a:key == 'k'
- call self._cursorUp()
- elseif a:key == nr2char(27) "escape
- let self.selection = -1
- return 1
- elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
- return 1
- else
- let index = self._nextIndexFor(a:key)
- if index != -1
- let self.selection = index
- if len(self._allIndexesFor(a:key)) == 1
- return 1
- endif
- endif
- endif
-
- return 0
-endfunction
-
-"FUNCTION: MenuController._allIndexesFor(shortcut) {{{3
-"get indexes to all menu items with the given shortcut
-function! s:MenuController._allIndexesFor(shortcut)
- let toReturn = []
-
- for i in range(0, len(self.menuItems)-1)
- if self.menuItems[i].shortcut == a:shortcut
- call add(toReturn, i)
- endif
- endfor
-
- return toReturn
-endfunction
-
-"FUNCTION: MenuController._nextIndexFor(shortcut) {{{3
-"get the index to the next menu item with the given shortcut, starts from the
-"current cursor location and wraps around to the top again if need be
-function! s:MenuController._nextIndexFor(shortcut)
- for i in range(self.selection+1, len(self.menuItems)-1)
- if self.menuItems[i].shortcut == a:shortcut
- return i
- endif
- endfor
-
- for i in range(0, self.selection)
- if self.menuItems[i].shortcut == a:shortcut
- return i
- endif
- endfor
-
- return -1
-endfunction
-
-"FUNCTION: MenuController._setCmdheight() {{{3
-"sets &cmdheight to whatever is needed to display the menu
-function! s:MenuController._setCmdheight()
- let &cmdheight = len(self.menuItems) + 3
-endfunction
-
-"FUNCTION: MenuController._saveOptions() {{{3
-"set any vim options that are required to make the menu work (saving their old
-"values)
-function! s:MenuController._saveOptions()
- let self._oldLazyredraw = &lazyredraw
- let self._oldCmdheight = &cmdheight
- set nolazyredraw
- call self._setCmdheight()
-endfunction
-
-"FUNCTION: MenuController._restoreOptions() {{{3
-"restore the options we saved in _saveOptions()
-function! s:MenuController._restoreOptions()
- let &cmdheight = self._oldCmdheight
- let &lazyredraw = self._oldLazyredraw
-endfunction
-
-"FUNCTION: MenuController._cursorDown() {{{3
-"move the cursor to the next menu item, skipping separators
-function! s:MenuController._cursorDown()
- let done = 0
- while !done
- if self.selection < len(self.menuItems)-1
- let self.selection += 1
- else
- let self.selection = 0
- endif
-
- if !self._current().isSeparator()
- let done = 1
- endif
- endwhile
-endfunction
-
-"FUNCTION: MenuController._cursorUp() {{{3
-"move the cursor to the previous menu item, skipping separators
-function! s:MenuController._cursorUp()
- let done = 0
- while !done
- if self.selection > 0
- let self.selection -= 1
- else
- let self.selection = len(self.menuItems)-1
- endif
-
- if !self._current().isSeparator()
- let done = 1
- endif
- endwhile
-endfunction
-
-"CLASS: MenuItem {{{2
-"============================================================
-let s:MenuItem = {}
-"FUNCTION: MenuItem.All() {{{3
-"get all top level menu items
-function! s:MenuItem.All()
- if !exists("s:menuItems")
- let s:menuItems = []
- endif
- return s:menuItems
-endfunction
-
-"FUNCTION: MenuItem.AllEnabled() {{{3
-"get all top level menu items that are currently enabled
-function! s:MenuItem.AllEnabled()
- let toReturn = []
- for i in s:MenuItem.All()
- if i.enabled()
- call add(toReturn, i)
- endif
- endfor
- return toReturn
-endfunction
-
-"FUNCTION: MenuItem.Create(options) {{{3
-"make a new menu item and add it to the global list
-function! s:MenuItem.Create(options)
- let newMenuItem = copy(self)
-
- let newMenuItem.text = a:options['text']
- let newMenuItem.shortcut = a:options['shortcut']
- let newMenuItem.children = []
-
- let newMenuItem.isActiveCallback = -1
- if has_key(a:options, 'isActiveCallback')
- let newMenuItem.isActiveCallback = a:options['isActiveCallback']
- endif
-
- let newMenuItem.callback = -1
- if has_key(a:options, 'callback')
- let newMenuItem.callback = a:options['callback']
- endif
-
- if has_key(a:options, 'parent')
- call add(a:options['parent'].children, newMenuItem)
- else
- call add(s:MenuItem.All(), newMenuItem)
- endif
-
- return newMenuItem
-endfunction
-
-"FUNCTION: MenuItem.CreateSeparator(options) {{{3
-"make a new separator menu item and add it to the global list
-function! s:MenuItem.CreateSeparator(options)
- let standard_options = { 'text': '--------------------',
- \ 'shortcut': -1,
- \ 'callback': -1 }
- let options = extend(a:options, standard_options, "force")
-
- return s:MenuItem.Create(options)
-endfunction
-
-"FUNCTION: MenuItem.CreateSubmenu(options) {{{3
-"make a new submenu and add it to global list
-function! s:MenuItem.CreateSubmenu(options)
- let standard_options = { 'callback': -1 }
- let options = extend(a:options, standard_options, "force")
-
- return s:MenuItem.Create(options)
-endfunction
-
-"FUNCTION: MenuItem.enabled() {{{3
-"return 1 if this menu item should be displayed
-"
-"delegates off to the isActiveCallback, and defaults to 1 if no callback was
-"specified
-function! s:MenuItem.enabled()
- if self.isActiveCallback != -1
- return {self.isActiveCallback}()
- endif
- return 1
-endfunction
-
-"FUNCTION: MenuItem.execute() {{{3
-"perform the action behind this menu item, if this menuitem has children then
-"display a new menu for them, otherwise deletegate off to the menuitem's
-"callback
-function! s:MenuItem.execute()
- if len(self.children)
- let mc = s:MenuController.New(self.children)
- call mc.showMenu()
- else
- if self.callback != -1
- call {self.callback}()
- endif
- endif
-endfunction
-
-"FUNCTION: MenuItem.isSeparator() {{{3
-"return 1 if this menuitem is a separator
-function! s:MenuItem.isSeparator()
- return self.callback == -1 && self.children == []
-endfunction
-
-"FUNCTION: MenuItem.isSubmenu() {{{3
-"return 1 if this menuitem is a submenu
-function! s:MenuItem.isSubmenu()
- return self.callback == -1 && !empty(self.children)
-endfunction
-
-"CLASS: TreeFileNode {{{2
-"This class is the parent of the TreeDirNode class and constitures the
-"'Component' part of the composite design pattern between the treenode
-"classes.
-"============================================================
-let s:TreeFileNode = {}
-"FUNCTION: TreeFileNode.activate(forceKeepWinOpen) {{{3
-function! s:TreeFileNode.activate(forceKeepWinOpen)
- call self.open()
- if !a:forceKeepWinOpen
- call s:closeTreeIfQuitOnOpen()
- end
-endfunction
-"FUNCTION: TreeFileNode.bookmark(name) {{{3
-"bookmark this node with a:name
-function! s:TreeFileNode.bookmark(name)
- try
- let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1)
- call oldMarkedNode.path.cacheDisplayString()
- catch /^NERDTree.BookmarkNotFoundError/
- endtry
-
- call s:Bookmark.AddBookmark(a:name, self.path)
- call self.path.cacheDisplayString()
- call s:Bookmark.Write()
-endfunction
-"FUNCTION: TreeFileNode.cacheParent() {{{3
-"initializes self.parent if it isnt already
-function! s:TreeFileNode.cacheParent()
- if empty(self.parent)
- let parentPath = self.path.getParent()
- if parentPath.equals(self.path)
- throw "NERDTree.CannotCacheParentError: already at root"
- endif
- let self.parent = s:TreeFileNode.New(parentPath)
- endif
-endfunction
-"FUNCTION: TreeFileNode.compareNodes {{{3
-"This is supposed to be a class level method but i cant figure out how to
-"get func refs to work from a dict..
-"
-"A class level method that compares two nodes
-"
-"Args:
-"n1, n2: the 2 nodes to compare
-function! s:compareNodes(n1, n2)
- return a:n1.path.compareTo(a:n2.path)
-endfunction
-
-"FUNCTION: TreeFileNode.clearBoomarks() {{{3
-function! s:TreeFileNode.clearBoomarks()
- for i in s:Bookmark.Bookmarks()
- if i.path.equals(self.path)
- call i.delete()
- end
- endfor
- call self.path.cacheDisplayString()
-endfunction
-"FUNCTION: TreeFileNode.copy(dest) {{{3
-function! s:TreeFileNode.copy(dest)
- call self.path.copy(a:dest)
- let newPath = s:Path.New(a:dest)
- let parent = b:NERDTreeRoot.findNode(newPath.getParent())
- if !empty(parent)
- call parent.refresh()
- endif
- return parent.findNode(newPath)
-endfunction
-
-"FUNCTION: TreeFileNode.delete {{{3
-"Removes this node from the tree and calls the Delete method for its path obj
-function! s:TreeFileNode.delete()
- call self.path.delete()
- call self.parent.removeChild(self)
-endfunction
-
-"FUNCTION: TreeFileNode.displayString() {{{3
-"
-"Returns a string that specifies how the node should be represented as a
-"string
-"
-"Return:
-"a string that can be used in the view to represent this node
-function! s:TreeFileNode.displayString()
- return self.path.displayString()
-endfunction
-
-"FUNCTION: TreeFileNode.equals(treenode) {{{3
-"
-"Compares this treenode to the input treenode and returns 1 if they are the
-"same node.
-"
-"Use this method instead of == because sometimes when the treenodes contain
-"many children, vim seg faults when doing ==
-"
-"Args:
-"treenode: the other treenode to compare to
-function! s:TreeFileNode.equals(treenode)
- return self.path.str() ==# a:treenode.path.str()
-endfunction
-
-"FUNCTION: TreeFileNode.findNode(path) {{{3
-"Returns self if this node.path.Equals the given path.
-"Returns {} if not equal.
-"
-"Args:
-"path: the path object to compare against
-function! s:TreeFileNode.findNode(path)
- if a:path.equals(self.path)
- return self
- endif
- return {}
-endfunction
-"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{3
-"
-"Finds the next sibling for this node in the indicated direction. This sibling
-"must be a directory and may/may not have children as specified.
-"
-"Args:
-"direction: 0 if you want to find the previous sibling, 1 for the next sibling
-"
-"Return:
-"a treenode object or {} if no appropriate sibling could be found
-function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
- "if we have no parent then we can have no siblings
- if self.parent != {}
- let nextSibling = self.findSibling(a:direction)
-
- while nextSibling != {}
- if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
- return nextSibling
- endif
- let nextSibling = nextSibling.findSibling(a:direction)
- endwhile
- endif
-
- return {}
-endfunction
-"FUNCTION: TreeFileNode.findSibling(direction) {{{3
-"
-"Finds the next sibling for this node in the indicated direction
-"
-"Args:
-"direction: 0 if you want to find the previous sibling, 1 for the next sibling
-"
-"Return:
-"a treenode object or {} if no sibling could be found
-function! s:TreeFileNode.findSibling(direction)
- "if we have no parent then we can have no siblings
- if self.parent != {}
-
- "get the index of this node in its parents children
- let siblingIndx = self.parent.getChildIndex(self.path)
-
- if siblingIndx != -1
- "move a long to the next potential sibling node
- let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
-
- "keep moving along to the next sibling till we find one that is valid
- let numSiblings = self.parent.getChildCount()
- while siblingIndx >= 0 && siblingIndx < numSiblings
-
- "if the next node is not an ignored node (i.e. wont show up in the
- "view) then return it
- if self.parent.children[siblingIndx].path.ignore() ==# 0
- return self.parent.children[siblingIndx]
- endif
-
- "go to next node
- let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
- endwhile
- endif
- endif
-
- return {}
-endfunction
-
-"FUNCTION: TreeFileNode.getLineNum(){{{3
-"returns the line number this node is rendered on, or -1 if it isnt rendered
-function! s:TreeFileNode.getLineNum()
- "if the node is the root then return the root line no.
- if self.isRoot()
- return s:TreeFileNode.GetRootLineNum()
- endif
-
- let totalLines = line("$")
-
- "the path components we have matched so far
- let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
- "the index of the component we are searching for
- let curPathComponent = 1
-
- let fullpath = self.path.str({'format': 'UI'})
-
-
- let lnum = s:TreeFileNode.GetRootLineNum()
- while lnum > 0
- let lnum = lnum + 1
- "have we reached the bottom of the tree?
- if lnum ==# totalLines+1
- return -1
- endif
-
- let curLine = getline(lnum)
-
- let indent = s:indentLevelFor(curLine)
- if indent ==# curPathComponent
- let curLine = s:stripMarkupFromLine(curLine, 1)
-
- let curPath = join(pathcomponents, '/') . '/' . curLine
- if stridx(fullpath, curPath, 0) ==# 0
- if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
- let curLine = substitute(curLine, '/ *$', '', '')
- call add(pathcomponents, curLine)
- let curPathComponent = curPathComponent + 1
-
- if fullpath ==# curPath
- return lnum
- endif
- endif
- endif
- endif
- endwhile
- return -1
-endfunction
-
-"FUNCTION: TreeFileNode.GetRootForTab(){{{3
-"get the root node for this tab
-function! s:TreeFileNode.GetRootForTab()
- if s:treeExistsForTab()
- return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
- end
- return {}
-endfunction
-"FUNCTION: TreeFileNode.GetRootLineNum(){{{3
-"gets the line number of the root node
-function! s:TreeFileNode.GetRootLineNum()
- let rootLine = 1
- while getline(rootLine) !~ '^\(/\|<\)'
- let rootLine = rootLine + 1
- endwhile
- return rootLine
-endfunction
-
-"FUNCTION: TreeFileNode.GetSelected() {{{3
-"gets the treenode that the cursor is currently over
-function! s:TreeFileNode.GetSelected()
- try
- let path = s:getPath(line("."))
- if path ==# {}
- return {}
- endif
- return b:NERDTreeRoot.findNode(path)
- catch /NERDTree/
- return {}
- endtry
-endfunction
-"FUNCTION: TreeFileNode.isVisible() {{{3
-"returns 1 if this node should be visible according to the tree filters and
-"hidden file filters (and their on/off status)
-function! s:TreeFileNode.isVisible()
- return !self.path.ignore()
-endfunction
-"FUNCTION: TreeFileNode.isRoot() {{{3
-"returns 1 if this node is b:NERDTreeRoot
-function! s:TreeFileNode.isRoot()
- if !s:treeExistsForBuf()
- throw "NERDTree.NoTreeError: No tree exists for the current buffer"
- endif
-
- return self.equals(b:NERDTreeRoot)
-endfunction
-
-"FUNCTION: TreeFileNode.makeRoot() {{{3
-"Make this node the root of the tree
-function! s:TreeFileNode.makeRoot()
- if self.path.isDirectory
- let b:NERDTreeRoot = self
- else
- call self.cacheParent()
- let b:NERDTreeRoot = self.parent
- endif
-
- call b:NERDTreeRoot.open()
-
- "change dir to the dir of the new root if instructed to
- if g:NERDTreeChDirMode ==# 2
- exec "cd " . b:NERDTreeRoot.path.str({'format': 'Edit'})
- endif
-endfunction
-"FUNCTION: TreeFileNode.New(path) {{{3
-"Returns a new TreeNode object with the given path and parent
-"
-"Args:
-"path: a path object representing the full filesystem path to the file/dir that the node represents
-function! s:TreeFileNode.New(path)
- if a:path.isDirectory
- return s:TreeDirNode.New(a:path)
- else
- let newTreeNode = copy(self)
- let newTreeNode.path = a:path
- let newTreeNode.parent = {}
- return newTreeNode
- endif
-endfunction
-
-"FUNCTION: TreeFileNode.open() {{{3
-"Open the file represented by the given node in the current window, splitting
-"the window if needed
-"
-"ARGS:
-"treenode: file node to open
-function! s:TreeFileNode.open()
- if b:NERDTreeType ==# "secondary"
- exec 'edit ' . self.path.str({'format': 'Edit'})
- return
- endif
-
- "if the file is already open in this tab then just stick the cursor in it
- let winnr = bufwinnr('^' . self.path.str() . '$')
- if winnr != -1
- call s:exec(winnr . "wincmd w")
-
- else
- if !s:isWindowUsable(winnr("#")) && s:firstUsableWindow() ==# -1
- call self.openSplit()
- else
- try
- if !s:isWindowUsable(winnr("#"))
- call s:exec(s:firstUsableWindow() . "wincmd w")
- else
- call s:exec('wincmd p')
- endif
- exec ("edit " . self.path.str({'format': 'Edit'}))
- catch /^Vim\%((\a\+)\)\=:E37/
- call s:putCursorInTreeWin()
- throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified."
- catch /^Vim\%((\a\+)\)\=:/
- echo v:exception
- endtry
- endif
- endif
-endfunction
-"FUNCTION: TreeFileNode.openSplit() {{{3
-"Open this node in a new window
-function! s:TreeFileNode.openSplit()
-
- if b:NERDTreeType ==# "secondary"
- exec "split " . self.path.str({'format': 'Edit'})
- return
- endif
-
- " Save the user's settings for splitbelow and splitright
- let savesplitbelow=&splitbelow
- let savesplitright=&splitright
-
- " 'there' will be set to a command to move from the split window
- " back to the explorer window
- "
- " 'back' will be set to a command to move from the explorer window
- " back to the newly split window
- "
- " 'right' and 'below' will be set to the settings needed for
- " splitbelow and splitright IF the explorer is the only window.
- "
- let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
- let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
- let right= g:NERDTreeWinPos ==# "left"
- let below=0
-
- " Attempt to go to adjacent window
- call s:exec(back)
-
- let onlyOneWin = (winnr("$") ==# 1)
-
- " If no adjacent window, set splitright and splitbelow appropriately
- if onlyOneWin
- let &splitright=right
- let &splitbelow=below
- else
- " found adjacent window - invert split direction
- let &splitright=!right
- let &splitbelow=!below
- endif
-
- let splitMode = onlyOneWin ? "vertical" : ""
-
- " Open the new window
- try
- exec(splitMode." sp " . self.path.str({'format': 'Edit'}))
- catch /^Vim\%((\a\+)\)\=:E37/
- call s:putCursorInTreeWin()
- throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str() ." is already open and modified."
- catch /^Vim\%((\a\+)\)\=:/
- "do nothing
- endtry
-
- "resize the tree window if no other window was open before
- if onlyOneWin
- let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
- call s:exec(there)
- exec("silent ". splitMode ." resize ". size)
- call s:exec('wincmd p')
- endif
-
- " Restore splitmode settings
- let &splitbelow=savesplitbelow
- let &splitright=savesplitright
-endfunction
-"FUNCTION: TreeFileNode.openVSplit() {{{3
-"Open this node in a new vertical window
-function! s:TreeFileNode.openVSplit()
- if b:NERDTreeType ==# "secondary"
- exec "vnew " . self.path.str({'format': 'Edit'})
- return
- endif
-
- let winwidth = winwidth(".")
- if winnr("$")==#1
- let winwidth = g:NERDTreeWinSize
- endif
-
- call s:exec("wincmd p")
- exec "vnew " . self.path.str({'format': 'Edit'})
-
- "resize the nerd tree back to the original size
- call s:putCursorInTreeWin()
- exec("silent vertical resize ". winwidth)
- call s:exec('wincmd p')
-endfunction
-"FUNCTION: TreeFileNode.openInNewTab(options) {{{3
-function! s:TreeFileNode.openInNewTab(options)
- let currentTab = tabpagenr()
-
- if !has_key(a:options, 'keepTreeOpen')
- call s:closeTreeIfQuitOnOpen()
- endif
-
- exec "tabedit " . self.path.str({'format': 'Edit'})
-
- if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab']
- exec "tabnext " . currentTab
- endif
-
-endfunction
-"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{3
-"Places the cursor on the line number this node is rendered on
-"
-"Args:
-"isJump: 1 if this cursor movement should be counted as a jump by vim
-"recurseUpward: try to put the cursor on the parent if the this node isnt
-"visible
-function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
- let ln = self.getLineNum()
- if ln != -1
- if a:isJump
- mark '
- endif
- call cursor(ln, col("."))
- else
- if a:recurseUpward
- let node = self
- while node != {} && node.getLineNum() ==# -1
- let node = node.parent
- call node.open()
- endwhile
- call s:renderView()
- call node.putCursorHere(a:isJump, 0)
- endif
- endif
-endfunction
-
-"FUNCTION: TreeFileNode.refresh() {{{3
-function! s:TreeFileNode.refresh()
- call self.path.refresh()
-endfunction
-"FUNCTION: TreeFileNode.rename() {{{3
-"Calls the rename method for this nodes path obj
-function! s:TreeFileNode.rename(newName)
- let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
- call self.path.rename(newName)
- call self.parent.removeChild(self)
-
- let parentPath = self.path.getParent()
- let newParent = b:NERDTreeRoot.findNode(parentPath)
-
- if newParent != {}
- call newParent.createChild(self.path, 1)
- call newParent.refresh()
- endif
-endfunction
-"FUNCTION: TreeFileNode.renderToString {{{3
-"returns a string representation for this tree to be rendered in the view
-function! s:TreeFileNode.renderToString()
- return self._renderToString(0, 0, [], self.getChildCount() ==# 1)
-endfunction
-
-
-"Args:
-"depth: the current depth in the tree for this call
-"drawText: 1 if we should actually draw the line for this node (if 0 then the
-"child nodes are rendered only)
-"vertMap: a binary array that indicates whether a vertical bar should be draw
-"for each depth in the tree
-"isLastChild:true if this curNode is the last child of its parent
-function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
- let output = ""
- if a:drawText ==# 1
-
- let treeParts = ''
-
- "get all the leading spaces and vertical tree parts for this line
- if a:depth > 1
- for j in a:vertMap[0:-2]
- if j ==# 1
- let treeParts = treeParts . '| '
- else
- let treeParts = treeParts . ' '
- endif
- endfor
- endif
-
- "get the last vertical tree part for this line which will be different
- "if this node is the last child of its parent
- if a:isLastChild
- let treeParts = treeParts . '`'
- else
- let treeParts = treeParts . '|'
- endif
-
-
- "smack the appropriate dir/file symbol on the line before the file/dir
- "name itself
- if self.path.isDirectory
- if self.isOpen
- let treeParts = treeParts . '~'
- else
- let treeParts = treeParts . '+'
- endif
- else
- let treeParts = treeParts . '-'
- endif
- let line = treeParts . self.displayString()
-
- let output = output . line . "\n"
- endif
-
- "if the node is an open dir, draw its children
- if self.path.isDirectory ==# 1 && self.isOpen ==# 1
-
- let childNodesToDraw = self.getVisibleChildren()
- if len(childNodesToDraw) > 0
-
- "draw all the nodes children except the last
- let lastIndx = len(childNodesToDraw)-1
- if lastIndx > 0
- for i in childNodesToDraw[0:lastIndx-1]
- let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0)
- endfor
- endif
-
- "draw the last child, indicating that it IS the last
- let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1)
- endif
- endif
-
- return output
-endfunction
-"CLASS: TreeDirNode {{{2
-"This class is a child of the TreeFileNode class and constitutes the
-"'Composite' part of the composite design pattern between the treenode
-"classes.
-"============================================================
-let s:TreeDirNode = copy(s:TreeFileNode)
-"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{3
-"class method that returns the highest cached ancestor of the current root
-function! s:TreeDirNode.AbsoluteTreeRoot()
- let currentNode = b:NERDTreeRoot
- while currentNode.parent != {}
- let currentNode = currentNode.parent
- endwhile
- return currentNode
-endfunction
-"FUNCTION: TreeDirNode.activate(forceKeepWinOpen) {{{3
-unlet s:TreeDirNode.activate
-function! s:TreeDirNode.activate(forceKeepWinOpen)
- call self.toggleOpen()
- call s:renderView()
- call self.putCursorHere(0, 0)
-endfunction
-"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{3
-"Adds the given treenode to the list of children for this node
-"
-"Args:
-"-treenode: the node to add
-"-inOrder: 1 if the new node should be inserted in sorted order
-function! s:TreeDirNode.addChild(treenode, inOrder)
- call add(self.children, a:treenode)
- let a:treenode.parent = self
-
- if a:inOrder
- call self.sortChildren()
- endif
-endfunction
-
-"FUNCTION: TreeDirNode.close() {{{3
-"Closes this directory
-function! s:TreeDirNode.close()
- let self.isOpen = 0
-endfunction
-
-"FUNCTION: TreeDirNode.closeChildren() {{{3
-"Closes all the child dir nodes of this node
-function! s:TreeDirNode.closeChildren()
- for i in self.children
- if i.path.isDirectory
- call i.close()
- call i.closeChildren()
- endif
- endfor
-endfunction
-
-"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{3
-"Instantiates a new child node for this node with the given path. The new
-"nodes parent is set to this node.
-"
-"Args:
-"path: a Path object that this node will represent/contain
-"inOrder: 1 if the new node should be inserted in sorted order
-"
-"Returns:
-"the newly created node
-function! s:TreeDirNode.createChild(path, inOrder)
- let newTreeNode = s:TreeFileNode.New(a:path)
- call self.addChild(newTreeNode, a:inOrder)
- return newTreeNode
-endfunction
-
-"FUNCTION: TreeDirNode.findNode(path) {{{3
-"Will find one of the children (recursively) that has the given path
-"
-"Args:
-"path: a path object
-unlet s:TreeDirNode.findNode
-function! s:TreeDirNode.findNode(path)
- if a:path.equals(self.path)
- return self
- endif
- if stridx(a:path.str(), self.path.str(), 0) ==# -1
- return {}
- endif
-
- if self.path.isDirectory
- for i in self.children
- let retVal = i.findNode(a:path)
- if retVal != {}
- return retVal
- endif
- endfor
- endif
- return {}
-endfunction
-"FUNCTION: TreeDirNode.getChildCount() {{{3
-"Returns the number of children this node has
-function! s:TreeDirNode.getChildCount()
- return len(self.children)
-endfunction
-
-"FUNCTION: TreeDirNode.getChild(path) {{{3
-"Returns child node of this node that has the given path or {} if no such node
-"exists.
-"
-"This function doesnt not recurse into child dir nodes
-"
-"Args:
-"path: a path object
-function! s:TreeDirNode.getChild(path)
- if stridx(a:path.str(), self.path.str(), 0) ==# -1
- return {}
- endif
-
- let index = self.getChildIndex(a:path)
- if index ==# -1
- return {}
- else
- return self.children[index]
- endif
-
-endfunction
-
-"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{3
-"returns the child at the given index
-"Args:
-"indx: the index to get the child from
-"visible: 1 if only the visible children array should be used, 0 if all the
-"children should be searched.
-function! s:TreeDirNode.getChildByIndex(indx, visible)
- let array_to_search = a:visible? self.getVisibleChildren() : self.children
- if a:indx > len(array_to_search)
- throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
- endif
- return array_to_search[a:indx]
-endfunction
-
-"FUNCTION: TreeDirNode.getChildIndex(path) {{{3
-"Returns the index of the child node of this node that has the given path or
-"-1 if no such node exists.
-"
-"This function doesnt not recurse into child dir nodes
-"
-"Args:
-"path: a path object
-function! s:TreeDirNode.getChildIndex(path)
- if stridx(a:path.str(), self.path.str(), 0) ==# -1
- return -1
- endif
-
- "do a binary search for the child
- let a = 0
- let z = self.getChildCount()
- while a < z
- let mid = (a+z)/2
- let diff = a:path.compareTo(self.children[mid].path)
-
- if diff ==# -1
- let z = mid
- elseif diff ==# 1
- let a = mid+1
- else
- return mid
- endif
- endwhile
- return -1
-endfunction
-
-"FUNCTION: TreeDirNode.GetSelected() {{{3
-"Returns the current node if it is a dir node, or else returns the current
-"nodes parent
-unlet s:TreeDirNode.GetSelected
-function! s:TreeDirNode.GetSelected()
- let currentDir = s:TreeFileNode.GetSelected()
- if currentDir != {} && !currentDir.isRoot()
- if currentDir.path.isDirectory ==# 0
- let currentDir = currentDir.parent
- endif
- endif
- return currentDir
-endfunction
-"FUNCTION: TreeDirNode.getVisibleChildCount() {{{3
-"Returns the number of visible children this node has
-function! s:TreeDirNode.getVisibleChildCount()
- return len(self.getVisibleChildren())
-endfunction
-
-"FUNCTION: TreeDirNode.getVisibleChildren() {{{3
-"Returns a list of children to display for this node, in the correct order
-"
-"Return:
-"an array of treenodes
-function! s:TreeDirNode.getVisibleChildren()
- let toReturn = []
- for i in self.children
- if i.path.ignore() ==# 0
- call add(toReturn, i)
- endif
- endfor
- return toReturn
-endfunction
-
-"FUNCTION: TreeDirNode.hasVisibleChildren() {{{3
-"returns 1 if this node has any childre, 0 otherwise..
-function! s:TreeDirNode.hasVisibleChildren()
- return self.getVisibleChildCount() != 0
-endfunction
-
-"FUNCTION: TreeDirNode._initChildren() {{{3
-"Removes all childen from this node and re-reads them
-"
-"Args:
-"silent: 1 if the function should not echo any "please wait" messages for
-"large directories
-"
-"Return: the number of child nodes read
-function! s:TreeDirNode._initChildren(silent)
- "remove all the current child nodes
- let self.children = []
-
- "get an array of all the files in the nodes dir
- let dir = self.path
- let globDir = dir.str({'format': 'Glob'})
- let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
- let files = split(filesStr, "\n")
-
- if !a:silent && len(files) > g:NERDTreeNotificationThreshold
- call s:echo("Please wait, caching a large dir ...")
- endif
-
- let invalidFilesFound = 0
- for i in files
-
- "filter out the .. and . directories
- "Note: we must match .. AND ../ cos sometimes the globpath returns
- "../ for path with strange chars (eg $)
- if i !~ '\/\.\.\/\?$' && i !~ '\/\.\/\?$'
-
- "put the next file in a new node and attach it
- try
- let path = s:Path.New(i)
- call self.createChild(path, 0)
- catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
- let invalidFilesFound += 1
- endtry
- endif
- endfor
-
- call self.sortChildren()
-
- if !a:silent && len(files) > g:NERDTreeNotificationThreshold
- call s:echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
- endif
-
- if invalidFilesFound
- call s:echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
- endif
- return self.getChildCount()
-endfunction
-"FUNCTION: TreeDirNode.New(path) {{{3
-"Returns a new TreeNode object with the given path and parent
-"
-"Args:
-"path: a path object representing the full filesystem path to the file/dir that the node represents
-unlet s:TreeDirNode.New
-function! s:TreeDirNode.New(path)
- if a:path.isDirectory != 1
- throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
- endif
-
- let newTreeNode = copy(self)
- let newTreeNode.path = a:path
-
- let newTreeNode.isOpen = 0
- let newTreeNode.children = []
-
- let newTreeNode.parent = {}
-
- return newTreeNode
-endfunction
-"FUNCTION: TreeDirNode.open() {{{3
-"Reads in all this nodes children
-"
-"Return: the number of child nodes read
-unlet s:TreeDirNode.open
-function! s:TreeDirNode.open()
- let self.isOpen = 1
- if self.children ==# []
- return self._initChildren(0)
- else
- return 0
- endif
-endfunction
-
-" FUNCTION: TreeDirNode.openExplorer() {{{3
-" opens an explorer window for this node in the previous window (could be a
-" nerd tree or a netrw)
-function! s:TreeDirNode.openExplorer()
- let oldwin = winnr()
- call s:exec('wincmd p')
- if oldwin ==# winnr() || (&modified && s:bufInWindows(winbufnr(winnr())) < 2)
- call s:exec('wincmd p')
- call self.openSplit()
- else
- exec ("silent edit " . self.path.str({'format': 'Edit'}))
- endif
-endfunction
-"FUNCTION: TreeDirNode.openInNewTab(options) {{{3
-unlet s:TreeDirNode.openInNewTab
-function! s:TreeDirNode.openInNewTab(options)
- let currentTab = tabpagenr()
-
- if !has_key(a:options, 'keepTreeOpen') || !a:options['keepTreeOpen']
- call s:closeTreeIfQuitOnOpen()
- endif
-
- tabnew
- call s:initNerdTree(self.path.str())
-
- if has_key(a:options, 'stayInCurrentTab') && a:options['stayInCurrentTab']
- exec "tabnext " . currentTab
- endif
-endfunction
-"FUNCTION: TreeDirNode.openRecursively() {{{3
-"Opens this treenode and all of its children whose paths arent 'ignored'
-"because of the file filters.
-"
-"This method is actually a wrapper for the OpenRecursively2 method which does
-"the work.
-function! s:TreeDirNode.openRecursively()
- call self._openRecursively2(1)
-endfunction
-
-"FUNCTION: TreeDirNode._openRecursively2() {{{3
-"Opens this all children of this treenode recursively if either:
-" *they arent filtered by file filters
-" *a:forceOpen is 1
-"
-"Args:
-"forceOpen: 1 if this node should be opened regardless of file filters
-function! s:TreeDirNode._openRecursively2(forceOpen)
- if self.path.ignore() ==# 0 || a:forceOpen
- let self.isOpen = 1
- if self.children ==# []
- call self._initChildren(1)
- endif
-
- for i in self.children
- if i.path.isDirectory ==# 1
- call i._openRecursively2(0)
- endif
- endfor
- endif
-endfunction
-
-"FUNCTION: TreeDirNode.refresh() {{{3
-unlet s:TreeDirNode.refresh
-function! s:TreeDirNode.refresh()
- call self.path.refresh()
-
- "if this node was ever opened, refresh its children
- if self.isOpen || !empty(self.children)
- "go thru all the files/dirs under this node
- let newChildNodes = []
- let invalidFilesFound = 0
- let dir = self.path
- let globDir = dir.str({'format': 'Glob'})
- let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
- let files = split(filesStr, "\n")
- for i in files
- "filter out the .. and . directories
- "Note: we must match .. AND ../ cos sometimes the globpath returns
- "../ for path with strange chars (eg $)
- if i !~ '\/\.\.\/\?$' && i !~ '\/\.\/\?$'
-
- try
- "create a new path and see if it exists in this nodes children
- let path = s:Path.New(i)
- let newNode = self.getChild(path)
- if newNode != {}
- call newNode.refresh()
- call add(newChildNodes, newNode)
-
- "the node doesnt exist so create it
- else
- let newNode = s:TreeFileNode.New(path)
- let newNode.parent = self
- call add(newChildNodes, newNode)
- endif
-
-
- catch /^NERDTree.InvalidArgumentsError/
- let invalidFilesFound = 1
- endtry
- endif
- endfor
-
- "swap this nodes children out for the children we just read/refreshed
- let self.children = newChildNodes
- call self.sortChildren()
-
- if invalidFilesFound
- call s:echoWarning("some files could not be loaded into the NERD tree")
- endif
- endif
-endfunction
-
-"FUNCTION: TreeDirNode.reveal(path) {{{3
-"reveal the given path, i.e. cache and open all treenodes needed to display it
-"in the UI
-function! s:TreeDirNode.reveal(path)
- if !a:path.isUnder(self.path)
- throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
- endif
-
- call self.open()
-
- if self.path.equals(a:path.getParent())
- let n = self.findNode(a:path)
- call s:renderView()
- call n.putCursorHere(1,0)
- return
- endif
-
- let p = a:path
- while !p.getParent().equals(self.path)
- let p = p.getParent()
- endwhile
-
- let n = self.findNode(p)
- call n.reveal(a:path)
-endfunction
-"FUNCTION: TreeDirNode.removeChild(treenode) {{{3
-"
-"Removes the given treenode from this nodes set of children
-"
-"Args:
-"treenode: the node to remove
-"
-"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
-function! s:TreeDirNode.removeChild(treenode)
- for i in range(0, self.getChildCount()-1)
- if self.children[i].equals(a:treenode)
- call remove(self.children, i)
- return
- endif
- endfor
-
- throw "NERDTree.ChildNotFoundError: child node was not found"
-endfunction
-
-"FUNCTION: TreeDirNode.sortChildren() {{{3
-"
-"Sorts the children of this node according to alphabetical order and the
-"directory priority.
-"
-function! s:TreeDirNode.sortChildren()
- let CompareFunc = function("s:compareNodes")
- call sort(self.children, CompareFunc)
-endfunction
-
-"FUNCTION: TreeDirNode.toggleOpen() {{{3
-"Opens this directory if it is closed and vice versa
-function! s:TreeDirNode.toggleOpen()
- if self.isOpen ==# 1
- call self.close()
- else
- call self.open()
- endif
-endfunction
-
-"FUNCTION: TreeDirNode.transplantChild(newNode) {{{3
-"Replaces the child of this with the given node (where the child node's full
-"path matches a:newNode's fullpath). The search for the matching node is
-"non-recursive
-"
-"Arg:
-"newNode: the node to graft into the tree
-function! s:TreeDirNode.transplantChild(newNode)
- for i in range(0, self.getChildCount()-1)
- if self.children[i].equals(a:newNode)
- let self.children[i] = a:newNode
- let a:newNode.parent = self
- break
- endif
- endfor
-endfunction
-"============================================================
-"CLASS: Path {{{2
-"============================================================
-let s:Path = {}
-"FUNCTION: Path.AbsolutePathFor(str) {{{3
-function! s:Path.AbsolutePathFor(str)
- let prependCWD = 0
- if s:running_windows
- let prependCWD = a:str !~ '^.:\(\\\|\/\)'
- else
- let prependCWD = a:str !~ '^/'
- endif
-
- let toReturn = a:str
- if prependCWD
- let toReturn = getcwd() . s:Path.Slash() . a:str
- endif
-
- return toReturn
-endfunction
-"FUNCTION: Path.bookmarkNames() {{{3
-function! s:Path.bookmarkNames()
- if !exists("self._bookmarkNames")
- call self.cacheDisplayString()
- endif
- return self._bookmarkNames
-endfunction
-"FUNCTION: Path.cacheDisplayString() {{{3
-function! s:Path.cacheDisplayString()
- let self.cachedDisplayString = self.getLastPathComponent(1)
-
- if self.isExecutable
- let self.cachedDisplayString = self.cachedDisplayString . '*'
- endif
-
- let self._bookmarkNames = []
- for i in s:Bookmark.Bookmarks()
- if i.path.equals(self)
- call add(self._bookmarkNames, i.name)
- endif
- endfor
- if !empty(self._bookmarkNames)
- let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
- endif
-
- if self.isSymLink
- let self.cachedDisplayString .= ' -> ' . self.symLinkDest
- endif
-
- if self.isReadOnly
- let self.cachedDisplayString .= ' [RO]'
- endif
-endfunction
-"FUNCTION: Path.changeToDir() {{{3
-function! s:Path.changeToDir()
- let dir = self.str({'format': 'Cd'})
- if self.isDirectory ==# 0
- let dir = self.getParent().str({'format': 'Cd'})
- endif
-
- try
- execute "cd " . dir
- call s:echo("CWD is now: " . getcwd())
- catch
- throw "NERDTree.PathChangeError: cannot change CWD to " . dir
- endtry
-endfunction
-
-"FUNCTION: Path.compareTo() {{{3
-"
-"Compares this Path to the given path and returns 0 if they are equal, -1 if
-"this Path is "less than" the given path, or 1 if it is "greater".
-"
-"Args:
-"path: the path object to compare this to
-"
-"Return:
-"1, -1 or 0
-function! s:Path.compareTo(path)
- let thisPath = self.getLastPathComponent(1)
- let thatPath = a:path.getLastPathComponent(1)
-
- "if the paths are the same then clearly we return 0
- if thisPath ==# thatPath
- return 0
- endif
-
- let thisSS = self.getSortOrderIndex()
- let thatSS = a:path.getSortOrderIndex()
-
- "compare the sort sequences, if they are different then the return
- "value is easy
- if thisSS < thatSS
- return -1
- elseif thisSS > thatSS
- return 1
- else
- "if the sort sequences are the same then compare the paths
- "alphabetically
- let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
- if pathCompare
- return -1
- else
- return 1
- endif
- endif
-endfunction
-
-"FUNCTION: Path.Create(fullpath) {{{3
-"
-"Factory method.
-"
-"Creates a path object with the given path. The path is also created on the
-"filesystem. If the path already exists, a NERDTree.Path.Exists exception is
-"thrown. If any other errors occur, a NERDTree.Path exception is thrown.
-"
-"Args:
-"fullpath: the full filesystem path to the file/dir to create
-function! s:Path.Create(fullpath)
- "bail if the a:fullpath already exists
- if isdirectory(a:fullpath) || filereadable(a:fullpath)
- throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'"
- endif
-
- try
-
- "if it ends with a slash, assume its a dir create it
- if a:fullpath =~ '\(\\\|\/\)$'
- "whack the trailing slash off the end if it exists
- let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
-
- call mkdir(fullpath, 'p')
-
- "assume its a file and create
- else
- call writefile([], a:fullpath)
- endif
- catch
- throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'"
- endtry
-
- return s:Path.New(a:fullpath)
-endfunction
-
-"FUNCTION: Path.copy(dest) {{{3
-"
-"Copies the file/dir represented by this Path to the given location
-"
-"Args:
-"dest: the location to copy this dir/file to
-function! s:Path.copy(dest)
- if !s:Path.CopyingSupported()
- throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
- endif
-
- let dest = s:Path.WinToUnixPath(a:dest)
-
- let cmd = g:NERDTreeCopyCmd . " " . self.str() . " " . dest
- let success = system(cmd)
- if success != 0
- throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
- endif
-endfunction
-
-"FUNCTION: Path.CopyingSupported() {{{3
-"
-"returns 1 if copying is supported for this OS
-function! s:Path.CopyingSupported()
- return exists('g:NERDTreeCopyCmd')
-endfunction
-
-
-"FUNCTION: Path.copyingWillOverwrite(dest) {{{3
-"
-"returns 1 if copy this path to the given location will cause files to
-"overwritten
-"
-"Args:
-"dest: the location this path will be copied to
-function! s:Path.copyingWillOverwrite(dest)
- if filereadable(a:dest)
- return 1
- endif
-
- if isdirectory(a:dest)
- let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
- if filereadable(path)
- return 1
- endif
- endif
-endfunction
-
-"FUNCTION: Path.delete() {{{3
-"
-"Deletes the file represented by this path.
-"Deletion of directories is not supported
-"
-"Throws NERDTree.Path.Deletion exceptions
-function! s:Path.delete()
- if self.isDirectory
-
- let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
- let success = system(cmd)
-
- if v:shell_error != 0
- throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
- endif
- else
- let success = delete(self.str())
- if success != 0
- throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
- endif
- endif
-
- "delete all bookmarks for this path
- for i in self.bookmarkNames()
- let bookmark = s:Bookmark.BookmarkFor(i)
- call bookmark.delete()
- endfor
-endfunction
-
-"FUNCTION: Path.displayString() {{{3
-"
-"Returns a string that specifies how the path should be represented as a
-"string
-function! s:Path.displayString()
- if self.cachedDisplayString ==# ""
- call self.cacheDisplayString()
- endif
-
- return self.cachedDisplayString
-endfunction
-"FUNCTION: Path.extractDriveLetter(fullpath) {{{3
-"
-"If running windows, cache the drive letter for this path
-function! s:Path.extractDriveLetter(fullpath)
- if s:running_windows
- let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
- else
- let self.drive = ''
- endif
-
-endfunction
-"FUNCTION: Path.exists() {{{3
-"return 1 if this path points to a location that is readable or is a directory
-function! s:Path.exists()
- let p = self.str()
- return filereadable(p) || isdirectory(p)
-endfunction
-"FUNCTION: Path.getDir() {{{3
-"
-"Returns this path if it is a directory, else this paths parent.
-"
-"Return:
-"a Path object
-function! s:Path.getDir()
- if self.isDirectory
- return self
- else
- return self.getParent()
- endif
-endfunction
-"FUNCTION: Path.getParent() {{{3
-"
-"Returns a new path object for this paths parent
-"
-"Return:
-"a new Path object
-function! s:Path.getParent()
- if s:running_windows
- let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
- else
- let path = '/'. join(self.pathSegments[0:-2], '/')
- endif
-
- return s:Path.New(path)
-endfunction
-"FUNCTION: Path.getLastPathComponent(dirSlash) {{{3
-"
-"Gets the last part of this path.
-"
-"Args:
-"dirSlash: if 1 then a trailing slash will be added to the returned value for
-"directory nodes.
-function! s:Path.getLastPathComponent(dirSlash)
- if empty(self.pathSegments)
- return ''
- endif
- let toReturn = self.pathSegments[-1]
- if a:dirSlash && self.isDirectory
- let toReturn = toReturn . '/'
- endif
- return toReturn
-endfunction
-
-"FUNCTION: Path.getSortOrderIndex() {{{3
-"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
-function! s:Path.getSortOrderIndex()
- let i = 0
- while i < len(g:NERDTreeSortOrder)
- if self.getLastPathComponent(1) =~ g:NERDTreeSortOrder[i]
- return i
- endif
- let i = i + 1
- endwhile
- return s:NERDTreeSortStarIndex
-endfunction
-
-"FUNCTION: Path.ignore() {{{3
-"returns true if this path should be ignored
-function! s:Path.ignore()
- let lastPathComponent = self.getLastPathComponent(0)
-
- "filter out the user specified paths to ignore
- if b:NERDTreeIgnoreEnabled
- for i in g:NERDTreeIgnore
- if lastPathComponent =~ i
- return 1
- endif
- endfor
- endif
-
- "dont show hidden files unless instructed to
- if b:NERDTreeShowHidden ==# 0 && lastPathComponent =~ '^\.'
- return 1
- endif
-
- if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0
- return 1
- endif
-
- return 0
-endfunction
-
-"FUNCTION: Path.isUnder(path) {{{3
-"return 1 if this path is somewhere under the given path in the filesystem.
-"
-"a:path should be a dir
-function! s:Path.isUnder(path)
- if a:path.isDirectory == 0
- return 0
- endif
-
- let this = self.str()
- let that = a:path.str()
- return stridx(this, that . s:Path.Slash()) == 0
-endfunction
-
-"FUNCTION: Path.JoinPathStrings(...) {{{3
-function! s:Path.JoinPathStrings(...)
- let components = []
- for i in a:000
- let components = extend(components, split(i, '/'))
- endfor
- return '/' . join(components, '/')
-endfunction
-
-"FUNCTION: Path.equals() {{{3
-"
-"Determines whether 2 path objects are "equal".
-"They are equal if the paths they represent are the same
-"
-"Args:
-"path: the other path obj to compare this with
-function! s:Path.equals(path)
- return self.str() ==# a:path.str()
-endfunction
-
-"FUNCTION: Path.New() {{{3
-"The Constructor for the Path object
-function! s:Path.New(path)
- let newPath = copy(self)
-
- call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
-
- let newPath.cachedDisplayString = ""
-
- return newPath
-endfunction
-
-"FUNCTION: Path.Slash() {{{3
-"return the slash to use for the current OS
-function! s:Path.Slash()
- return s:running_windows ? '\' : '/'
-endfunction
-
-"FUNCTION: Path.readInfoFromDisk(fullpath) {{{3
-"
-"
-"Throws NERDTree.Path.InvalidArguments exception.
-function! s:Path.readInfoFromDisk(fullpath)
- call self.extractDriveLetter(a:fullpath)
-
- let fullpath = s:Path.WinToUnixPath(a:fullpath)
-
- if getftype(fullpath) ==# "fifo"
- throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
- endif
-
- let self.pathSegments = split(fullpath, '/')
-
- let self.isReadOnly = 0
- if isdirectory(a:fullpath)
- let self.isDirectory = 1
- elseif filereadable(a:fullpath)
- let self.isDirectory = 0
- let self.isReadOnly = filewritable(a:fullpath) ==# 0
- else
- throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
- endif
-
- let self.isExecutable = 0
- if !self.isDirectory
- let self.isExecutable = getfperm(a:fullpath) =~ 'x'
- endif
-
- "grab the last part of the path (minus the trailing slash)
- let lastPathComponent = self.getLastPathComponent(0)
-
- "get the path to the new node with the parent dir fully resolved
- let hardPath = resolve(self.strTrunk()) . '/' . lastPathComponent
-
- "if the last part of the path is a symlink then flag it as such
- let self.isSymLink = (resolve(hardPath) != hardPath)
- if self.isSymLink
- let self.symLinkDest = resolve(fullpath)
-
- "if the link is a dir then slap a / on the end of its dest
- if isdirectory(self.symLinkDest)
-
- "we always wanna treat MS windows shortcuts as files for
- "simplicity
- if hardPath !~ '\.lnk$'
-
- let self.symLinkDest = self.symLinkDest . '/'
- endif
- endif
- endif
-endfunction
-
-"FUNCTION: Path.refresh() {{{3
-function! s:Path.refresh()
- call self.readInfoFromDisk(self.str())
- call self.cacheDisplayString()
-endfunction
-
-"FUNCTION: Path.rename() {{{3
-"
-"Renames this node on the filesystem
-function! s:Path.rename(newPath)
- if a:newPath ==# ''
- throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
- endif
-
- let success = rename(self.str(), a:newPath)
- if success != 0
- throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
- endif
- call self.readInfoFromDisk(a:newPath)
-
- for i in self.bookmarkNames()
- let b = s:Bookmark.BookmarkFor(i)
- call b.setPath(copy(self))
- endfor
- call s:Bookmark.Write()
-endfunction
-
-"FUNCTION: Path.str() {{{3
-"
-"Returns a string representation of this Path
-"
-"Takes an optional dictionary param to specify how the output should be
-"formatted.
-"
-"The dict may have the following keys:
-" 'format'
-" 'escape'
-" 'truncateTo'
-"
-"The 'format' key may have a value of:
-" 'Cd' - a string to be used with the :cd command
-" 'Edit' - a string to be used with :e :sp :new :tabedit etc
-" 'UI' - a string used in the NERD tree UI
-"
-"The 'escape' key, if specified will cause the output to be escaped with
-"shellescape()
-"
-"The 'truncateTo' key causes the resulting string to be truncated to the value
-"'truncateTo' maps to. A '<' char will be prepended.
-function! s:Path.str(...)
- let options = a:0 ? a:1 : {}
- let toReturn = ""
-
- if has_key(options, 'format')
- let format = options['format']
- if has_key(self, '_strFor' . format)
- exec 'let toReturn = self._strFor' . format . '()'
- else
- raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
- endif
- else
- let toReturn = self._str()
- endif
-
- if has_key(options, 'escape') && options['escape']
- let toReturn = shellescape(toReturn)
- endif
-
- if has_key(options, 'truncateTo')
- let limit = options['truncateTo']
- if len(toReturn) > limit
- let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1)
- endif
- endif
-
- return toReturn
-endfunction
-
-"FUNCTION: Path._strForUI() {{{3
-function! s:Path._strForUI()
- let toReturn = '/' . join(self.pathSegments, '/')
- if self.isDirectory && toReturn != '/'
- let toReturn = toReturn . '/'
- endif
- return toReturn
-endfunction
-
-"FUNCTION: Path._strForCd() {{{3
-"
-" returns a string that can be used with :cd
-function! s:Path._strForCd()
- return escape(self.str(), s:escape_chars)
-endfunction
-"FUNCTION: Path._strForEdit() {{{3
-"
-"Return: the string for this path that is suitable to be used with the :edit
-"command
-function! s:Path._strForEdit()
- let p = self.str({'format': 'UI'})
- let cwd = getcwd()
-
- if s:running_windows
- let p = tolower(self.str())
- let cwd = tolower(getcwd())
- endif
-
- let p = escape(p, s:escape_chars)
-
- let cwd = cwd . s:Path.Slash()
-
- "return a relative path if we can
- if stridx(p, cwd) ==# 0
- let p = strpart(p, strlen(cwd))
- endif
-
- if p ==# ''
- let p = '.'
- endif
-
- return p
-
-endfunction
-"FUNCTION: Path._strForGlob() {{{3
-function! s:Path._strForGlob()
- let lead = s:Path.Slash()
-
- "if we are running windows then slap a drive letter on the front
- if s:running_windows
- let lead = self.drive . '\'
- endif
-
- let toReturn = lead . join(self.pathSegments, s:Path.Slash())
-
- if !s:running_windows
- let toReturn = escape(toReturn, s:escape_chars)
- endif
- return toReturn
-endfunction
-"FUNCTION: Path._str() {{{3
-"
-"Gets the string path for this path object that is appropriate for the OS.
-"EG, in windows c:\foo\bar
-" in *nix /foo/bar
-function! s:Path._str()
- let lead = s:Path.Slash()
-
- "if we are running windows then slap a drive letter on the front
- if s:running_windows
- let lead = self.drive . '\'
- endif
-
- return lead . join(self.pathSegments, s:Path.Slash())
-endfunction
-
-"FUNCTION: Path.strTrunk() {{{3
-"Gets the path without the last segment on the end.
-function! s:Path.strTrunk()
- return self.drive . '/' . join(self.pathSegments[0:-2], '/')
-endfunction
-
-"FUNCTION: Path.WinToUnixPath(pathstr){{{3
-"Takes in a windows path and returns the unix equiv
-"
-"A class level method
-"
-"Args:
-"pathstr: the windows path to convert
-function! s:Path.WinToUnixPath(pathstr)
- if !s:running_windows
- return a:pathstr
- endif
-
- let toReturn = a:pathstr
-
- "remove the x:\ of the front
- let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
-
- "convert all \ chars to /
- let toReturn = substitute(toReturn, '\', '/', "g")
-
- return toReturn
-endfunction
-
-" SECTION: General Functions {{{1
-"============================================================
-"FUNCTION: s:bufInWindows(bnum){{{2
-"[[STOLEN FROM VTREEEXPLORER.VIM]]
-"Determine the number of windows open to this buffer number.
-"Care of Yegappan Lakshman. Thanks!
-"
-"Args:
-"bnum: the subject buffers buffer number
-function! s:bufInWindows(bnum)
- let cnt = 0
- let winnum = 1
- while 1
- let bufnum = winbufnr(winnum)
- if bufnum < 0
- break
- endif
- if bufnum ==# a:bnum
- let cnt = cnt + 1
- endif
- let winnum = winnum + 1
- endwhile
-
- return cnt
-endfunction " >>>
-"FUNCTION: s:checkForBrowse(dir) {{{2
-"inits a secondary nerd tree in the current buffer if appropriate
-function! s:checkForBrowse(dir)
- if a:dir != '' && isdirectory(a:dir)
- call s:initNerdTreeInPlace(a:dir)
- endif
-endfunction
-"FUNCTION: s:compareBookmarks(first, second) {{{2
-"Compares two bookmarks
-function! s:compareBookmarks(first, second)
- return a:first.compareTo(a:second)
-endfunction
-
-" FUNCTION: s:completeBookmarks(A,L,P) {{{2
-" completion function for the bookmark commands
-function! s:completeBookmarks(A,L,P)
- return filter(s:Bookmark.BookmarkNames(), 'v:val =~ "^' . a:A . '"')
-endfunction
-" FUNCTION: s:exec(cmd) {{{2
-" same as :exec cmd but eventignore=all is set for the duration
-function! s:exec(cmd)
- let old_ei = &ei
- set ei=all
- exec a:cmd
- let &ei = old_ei
-endfunction
-" FUNCTION: s:findAndRevealPath() {{{2
-function! s:findAndRevealPath()
- try
- let p = s:Path.New(expand("%"))
- catch /^NERDTree.InvalidArgumentsError/
- call s:echo("no file for the current buffer")
- return
- endtry
-
- if !s:treeExistsForTab()
- call s:initNerdTree(p.getParent().str())
- else
- if !p.isUnder(s:TreeFileNode.GetRootForTab().path)
- call s:initNerdTree(p.getParent().str())
- else
- if !s:isTreeOpen()
- call s:toggle("")
- endif
- endif
- endif
- call s:putCursorInTreeWin()
- call b:NERDTreeRoot.reveal(p)
-endfunction
-"FUNCTION: s:initNerdTree(name) {{{2
-"Initialise the nerd tree for this tab. The tree will start in either the
-"given directory, or the directory associated with the given bookmark
-"
-"Args:
-"name: the name of a bookmark or a directory
-function! s:initNerdTree(name)
- let path = {}
- if s:Bookmark.BookmarkExistsFor(a:name)
- let path = s:Bookmark.BookmarkFor(a:name).path
- else
- let dir = a:name ==# '' ? getcwd() : a:name
-
- "hack to get an absolute path if a relative path is given
- if dir =~ '^\.'
- let dir = getcwd() . s:Path.Slash() . dir
- endif
- let dir = resolve(dir)
-
- try
- let path = s:Path.New(dir)
- catch /^NERDTree.InvalidArgumentsError/
- call s:echo("No bookmark or directory found for: " . a:name)
- return
- endtry
- endif
- if !path.isDirectory
- let path = path.getParent()
- endif
-
- "if instructed to, then change the vim CWD to the dir the NERDTree is
- "inited in
- if g:NERDTreeChDirMode != 0
- call path.changeToDir()
- endif
-
- if s:treeExistsForTab()
- if s:isTreeOpen()
- call s:closeTree()
- endif
- unlet t:NERDTreeBufName
- endif
-
- let newRoot = s:TreeDirNode.New(path)
- call newRoot.open()
-
- call s:createTreeWin()
- let b:treeShowHelp = 0
- let b:NERDTreeIgnoreEnabled = 1
- let b:NERDTreeShowFiles = g:NERDTreeShowFiles
- let b:NERDTreeShowHidden = g:NERDTreeShowHidden
- let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
- let b:NERDTreeRoot = newRoot
-
- let b:NERDTreeType = "primary"
-
- call s:renderView()
- call b:NERDTreeRoot.putCursorHere(0, 0)
-endfunction
-
-"FUNCTION: s:initNerdTreeInPlace(dir) {{{2
-function! s:initNerdTreeInPlace(dir)
- try
- let path = s:Path.New(a:dir)
- catch /^NERDTree.InvalidArgumentsError/
- call s:echo("Invalid directory name:" . a:name)
- return
- endtry
-
- "we want the directory buffer to disappear when we do the :edit below
- setlocal bufhidden=wipe
-
- let previousBuf = expand("#")
-
- "we need a unique name for each secondary tree buffer to ensure they are
- "all independent
- exec "silent edit " . s:nextBufferName()
-
- let b:NERDTreePreviousBuf = bufnr(previousBuf)
-
- let b:NERDTreeRoot = s:TreeDirNode.New(path)
- call b:NERDTreeRoot.open()
-
- "throwaway buffer options
- setlocal noswapfile
- setlocal buftype=nofile
- setlocal bufhidden=hide
- setlocal nowrap
- setlocal foldcolumn=0
- setlocal nobuflisted
- setlocal nospell
- if g:NERDTreeShowLineNumbers
- setlocal nu
- else
- setlocal nonu
- endif
-
- iabc <buffer>
-
- if g:NERDTreeHighlightCursorline
- setlocal cursorline
- endif
-
- call s:setupStatusline()
-
- let b:treeShowHelp = 0
- let b:NERDTreeIgnoreEnabled = 1
- let b:NERDTreeShowFiles = g:NERDTreeShowFiles
- let b:NERDTreeShowHidden = g:NERDTreeShowHidden
- let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
-
- let b:NERDTreeType = "secondary"
-
- call s:bindMappings()
- setfiletype nerdtree
- " syntax highlighting
- if has("syntax") && exists("g:syntax_on")
- call s:setupSyntaxHighlighting()
- endif
-
- call s:renderView()
-endfunction
-" FUNCTION: s:initNerdTreeMirror() {{{2
-function! s:initNerdTreeMirror()
-
- "get the names off all the nerd tree buffers
- let treeBufNames = []
- for i in range(1, tabpagenr("$"))
- let nextName = s:tabpagevar(i, 'NERDTreeBufName')
- if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
- call add(treeBufNames, nextName)
- endif
- endfor
- let treeBufNames = s:unique(treeBufNames)
-
- "map the option names (that the user will be prompted with) to the nerd
- "tree buffer names
- let options = {}
- let i = 0
- while i < len(treeBufNames)
- let bufName = treeBufNames[i]
- let treeRoot = getbufvar(bufName, "NERDTreeRoot")
- let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
- let i = i + 1
- endwhile
-
- "work out which tree to mirror, if there is more than 1 then ask the user
- let bufferName = ''
- if len(keys(options)) > 1
- let choices = ["Choose a tree to mirror"]
- let choices = extend(choices, sort(keys(options)))
- let choice = inputlist(choices)
- if choice < 1 || choice > len(options) || choice ==# ''
- return
- endif
-
- let bufferName = options[sort(keys(options))[choice-1]]
- elseif len(keys(options)) ==# 1
- let bufferName = values(options)[0]
- else
- call s:echo("No trees to mirror")
- return
- endif
-
- if s:treeExistsForTab() && s:isTreeOpen()
- call s:closeTree()
- endif
-
- let t:NERDTreeBufName = bufferName
- call s:createTreeWin()
- exec 'buffer ' . bufferName
- if !&hidden
- call s:renderView()
- endif
-endfunction
-" FUNCTION: s:nextBufferName() {{{2
-" returns the buffer name for the next nerd tree
-function! s:nextBufferName()
- let name = s:NERDTreeBufName . s:next_buffer_number
- let s:next_buffer_number += 1
- return name
-endfunction
-" FUNCTION: s:tabpagevar(tabnr, var) {{{2
-function! s:tabpagevar(tabnr, var)
- let currentTab = tabpagenr()
- let old_ei = &ei
- set ei=all
-
- exec "tabnext " . a:tabnr
- let v = -1
- if exists('t:' . a:var)
- exec 'let v = t:' . a:var
- endif
- exec "tabnext " . currentTab
-
- let &ei = old_ei
-
- return v
-endfunction
-" Function: s:treeExistsForBuffer() {{{2
-" Returns 1 if a nerd tree root exists in the current buffer
-function! s:treeExistsForBuf()
- return exists("b:NERDTreeRoot")
-endfunction
-" Function: s:treeExistsForTab() {{{2
-" Returns 1 if a nerd tree root exists in the current tab
-function! s:treeExistsForTab()
- return exists("t:NERDTreeBufName")
-endfunction
-" Function: s:unique(list) {{{2
-" returns a:list without duplicates
-function! s:unique(list)
- let uniqlist = []
- for elem in a:list
- if index(uniqlist, elem) ==# -1
- let uniqlist += [elem]
- endif
- endfor
- return uniqlist
-endfunction
-" SECTION: Public API {{{1
-"============================================================
-let g:NERDTreePath = s:Path
-let g:NERDTreeDirNode = s:TreeDirNode
-let g:NERDTreeFileNode = s:TreeFileNode
-let g:NERDTreeBookmark = s:Bookmark
-
-function! NERDTreeAddMenuItem(options)
- call s:MenuItem.Create(a:options)
-endfunction
-
-function! NERDTreeAddMenuSeparator(...)
- let opts = a:0 ? a:1 : {}
- call s:MenuItem.CreateSeparator(opts)
-endfunction
-
-function! NERDTreeAddSubmenu(options)
- return s:MenuItem.Create(a:options)
-endfunction
-
-function! NERDTreeAddKeyMap(options)
- call s:KeyMap.Create(a:options)
-endfunction
-
-function! NERDTreeRender()
- call s:renderView()
-endfunction
-
-" SECTION: View Functions {{{1
-"============================================================
-"FUNCTION: s:centerView() {{{2
-"centers the nerd tree window around the cursor (provided the nerd tree
-"options permit)
-function! s:centerView()
- if g:NERDTreeAutoCenter
- let current_line = winline()
- let lines_to_top = current_line
- let lines_to_bottom = winheight(s:getTreeWinNum()) - current_line
- if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold
- normal! zz
- endif
- endif
-endfunction
-"FUNCTION: s:closeTree() {{{2
-"Closes the primary NERD tree window for this tab
-function! s:closeTree()
- if !s:isTreeOpen()
- throw "NERDTree.NoTreeFoundError: no NERDTree is open"
- endif
-
- if winnr("$") != 1
- call s:exec(s:getTreeWinNum() . " wincmd w")
- close
- call s:exec("wincmd p")
- else
- close
- endif
-endfunction
-
-"FUNCTION: s:closeTreeIfOpen() {{{2
-"Closes the NERD tree window if it is open
-function! s:closeTreeIfOpen()
- if s:isTreeOpen()
- call s:closeTree()
- endif
-endfunction
-"FUNCTION: s:closeTreeIfQuitOnOpen() {{{2
-"Closes the NERD tree window if the close on open option is set
-function! s:closeTreeIfQuitOnOpen()
- if g:NERDTreeQuitOnOpen && s:isTreeOpen()
- call s:closeTree()
- endif
-endfunction
-"FUNCTION: s:createTreeWin() {{{2
-"Inits the NERD tree window. ie. opens it, sizes it, sets all the local
-"options etc
-function! s:createTreeWin()
- "create the nerd tree window
- let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
- let splitSize = g:NERDTreeWinSize
-
- if !exists('t:NERDTreeBufName')
- let t:NERDTreeBufName = s:nextBufferName()
- silent! exec splitLocation . 'vertical ' . splitSize . ' new'
- silent! exec "edit " . t:NERDTreeBufName
- else
- silent! exec splitLocation . 'vertical ' . splitSize . ' split'
- silent! exec "buffer " . t:NERDTreeBufName
- endif
-
- setlocal winfixwidth
-
- "throwaway buffer options
- setlocal noswapfile
- setlocal buftype=nofile
- setlocal nowrap
- setlocal foldcolumn=0
- setlocal nobuflisted
- setlocal nospell
- if g:NERDTreeShowLineNumbers
- setlocal nu
- else
- setlocal nonu
- endif
-
- iabc <buffer>
-
- if g:NERDTreeHighlightCursorline
- setlocal cursorline
- endif
-
- call s:setupStatusline()
-
- call s:bindMappings()
- setfiletype nerdtree
- " syntax highlighting
- if has("syntax") && exists("g:syntax_on")
- call s:setupSyntaxHighlighting()
- endif
-endfunction
-
-"FUNCTION: s:dumpHelp {{{2
-"prints out the quick help
-function! s:dumpHelp()
- let old_h = @h
- if b:treeShowHelp ==# 1
- let @h= "\" NERD tree (" . s:NERD_tree_version . ") quickhelp~\n"
- let @h=@h."\" ============================\n"
- let @h=@h."\" File node mappings~\n"
- let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n"
- let @h=@h."\" <CR>,\n"
- if b:NERDTreeType ==# "primary"
- let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n"
- else
- let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n"
- endif
- if b:NERDTreeType ==# "primary"
- let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n"
- endif
- let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
- let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
- let @h=@h."\" middle-click,\n"
- let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n"
- let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n"
- let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n"
- let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n"
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Directory node mappings~\n"
- let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n"
- let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n"
- let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n"
- let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n"
- let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n"
- let @h=@h."\" current node recursively\n"
- let @h=@h."\" middle-click,\n"
- let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n"
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Bookmark table mappings~\n"
- let @h=@h."\" double-click,\n"
- let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n"
- let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n"
- let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n"
- let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n"
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Tree navigation mappings~\n"
- let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n"
- let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n"
- let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n"
- let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n"
- let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n"
- let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n"
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Filesystem mappings~\n"
- let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n"
- let @h=@h."\" selected dir\n"
- let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n"
- let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n"
- let @h=@h."\" but leave old root open\n"
- let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n"
- let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n"
- let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n"
- let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n"
- let @h=@h."\" selected dir\n"
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Tree filtering mappings~\n"
- let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n"
- let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n"
- let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n"
- let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n"
-
- "add quickhelp entries for each custom key map
- if len(s:KeyMap.All())
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Custom mappings~\n"
- for i in s:KeyMap.All()
- let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n"
- endfor
- endif
-
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Other mappings~\n"
- let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n"
- let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n"
- let @h=@h."\" the NERDTree window\n"
- let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n"
- let @h=@h."\"\n\" ----------------------------\n"
- let @h=@h."\" Bookmark commands~\n"
- let @h=@h."\" :Bookmark <name>\n"
- let @h=@h."\" :BookmarkToRoot <name>\n"
- let @h=@h."\" :RevealBookmark <name>\n"
- let @h=@h."\" :OpenBookmark <name>\n"
- let @h=@h."\" :ClearBookmarks [<names>]\n"
- let @h=@h."\" :ClearAllBookmarks\n"
- else
- let @h="\" Press ". g:NERDTreeMapHelp ." for help\n"
- endif
-
- silent! put h
-
- let @h = old_h
-endfunction
-"FUNCTION: s:echo {{{2
-"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
-"
-"Args:
-"msg: the message to echo
-function! s:echo(msg)
- redraw
- echomsg "NERDTree: " . a:msg
-endfunction
-"FUNCTION: s:echoWarning {{{2
-"Wrapper for s:echo, sets the message type to warningmsg for this message
-"Args:
-"msg: the message to echo
-function! s:echoWarning(msg)
- echohl warningmsg
- call s:echo(a:msg)
- echohl normal
-endfunction
-"FUNCTION: s:echoError {{{2
-"Wrapper for s:echo, sets the message type to errormsg for this message
-"Args:
-"msg: the message to echo
-function! s:echoError(msg)
- echohl errormsg
- call s:echo(a:msg)
- echohl normal
-endfunction
-"FUNCTION: s:firstUsableWindow(){{{2
-"find the window number of the first normal window
-function! s:firstUsableWindow()
- let i = 1
- while i <= winnr("$")
- let bnum = winbufnr(i)
- if bnum != -1 && getbufvar(bnum, '&buftype') ==# ''
- \ && !getwinvar(i, '&previewwindow')
- \ && (!getbufvar(bnum, '&modified') || &hidden)
- return i
- endif
-
- let i += 1
- endwhile
- return -1
-endfunction
-"FUNCTION: s:getPath(ln) {{{2
-"Gets the full path to the node that is rendered on the given line number
-"
-"Args:
-"ln: the line number to get the path for
-"
-"Return:
-"A path if a node was selected, {} if nothing is selected.
-"If the 'up a dir' line was selected then the path to the parent of the
-"current root is returned
-function! s:getPath(ln)
- let line = getline(a:ln)
-
- let rootLine = s:TreeFileNode.GetRootLineNum()
-
- "check to see if we have the root node
- if a:ln == rootLine
- return b:NERDTreeRoot.path
- endif
-
- " in case called from outside the tree
- if line !~ '^ *[|`]' || line =~ '^$'
- return {}
- endif
-
- if line ==# s:tree_up_dir_line
- return b:NERDTreeRoot.path.getParent()
- endif
-
- let indent = s:indentLevelFor(line)
-
- "remove the tree parts and the leading space
- let curFile = s:stripMarkupFromLine(line, 0)
-
- let wasdir = 0
- if curFile =~ '/$'
- let wasdir = 1
- let curFile = substitute(curFile, '/\?$', '/', "")
- endif
-
- let dir = ""
- let lnum = a:ln
- while lnum > 0
- let lnum = lnum - 1
- let curLine = getline(lnum)
- let curLineStripped = s:stripMarkupFromLine(curLine, 1)
-
- "have we reached the top of the tree?
- if lnum == rootLine
- let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
- break
- endif
- if curLineStripped =~ '/$'
- let lpindent = s:indentLevelFor(curLine)
- if lpindent < indent
- let indent = indent - 1
-
- let dir = substitute (curLineStripped,'^\\', "", "") . dir
- continue
- endif
- endif
- endwhile
- let curFile = b:NERDTreeRoot.path.drive . dir . curFile
- let toReturn = s:Path.New(curFile)
- return toReturn
-endfunction
-
-"FUNCTION: s:getTreeWinNum() {{{2
-"gets the nerd tree window number for this tab
-function! s:getTreeWinNum()
- if exists("t:NERDTreeBufName")
- return bufwinnr(t:NERDTreeBufName)
- else
- return -1
- endif
-endfunction
-"FUNCTION: s:indentLevelFor(line) {{{2
-function! s:indentLevelFor(line)
- return match(a:line, '[^ \-+~`|]') / s:tree_wid
-endfunction
-"FUNCTION: s:isTreeOpen() {{{2
-function! s:isTreeOpen()
- return s:getTreeWinNum() != -1
-endfunction
-"FUNCTION: s:isWindowUsable(winnumber) {{{2
-"Returns 0 if opening a file from the tree in the given window requires it to
-"be split, 1 otherwise
-"
-"Args:
-"winnumber: the number of the window in question
-function! s:isWindowUsable(winnumber)
- "gotta split if theres only one window (i.e. the NERD tree)
- if winnr("$") ==# 1
- return 0
- endif
-
- let oldwinnr = winnr()
- call s:exec(a:winnumber . "wincmd p")
- let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
- let modified = &modified
- call s:exec(oldwinnr . "wincmd p")
-
- "if its a special window e.g. quickfix or another explorer plugin then we
- "have to split
- if specialWindow
- return 0
- endif
-
- if &hidden
- return 1
- endif
-
- return !modified || s:bufInWindows(winbufnr(a:winnumber)) >= 2
-endfunction
-
-" FUNCTION: s:jumpToChild(direction) {{{2
-" Args:
-" direction: 0 if going to first child, 1 if going to last
-function! s:jumpToChild(direction)
- let currentNode = s:TreeFileNode.GetSelected()
- if currentNode ==# {} || currentNode.isRoot()
- call s:echo("cannot jump to " . (a:direction ? "last" : "first") . " child")
- return
- end
- let dirNode = currentNode.parent
- let childNodes = dirNode.getVisibleChildren()
-
- let targetNode = childNodes[0]
- if a:direction
- let targetNode = childNodes[len(childNodes) - 1]
- endif
-
- if targetNode.equals(currentNode)
- let siblingDir = currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
- if siblingDir != {}
- let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
- let targetNode = siblingDir.getChildByIndex(indx, 1)
- endif
- endif
-
- call targetNode.putCursorHere(1, 0)
-
- call s:centerView()
-endfunction
-
-
-"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{2
-"prints out the given msg and, if the user responds by pushing 'y' then the
-"buffer with the given bufnum is deleted
-"
-"Args:
-"bufnum: the buffer that may be deleted
-"msg: a message that will be echoed to the user asking them if they wish to
-" del the buffer
-function! s:promptToDelBuffer(bufnum, msg)
- echo a:msg
- if nr2char(getchar()) ==# 'y'
- exec "silent bdelete! " . a:bufnum
- endif
-endfunction
-
-"FUNCTION: s:putCursorOnBookmarkTable(){{{2
-"Places the cursor at the top of the bookmarks table
-function! s:putCursorOnBookmarkTable()
- if !b:NERDTreeShowBookmarks
- throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active"
- endif
-
- let rootNodeLine = s:TreeFileNode.GetRootLineNum()
-
- let line = 1
- while getline(line) !~ '^>-\+Bookmarks-\+$'
- let line = line + 1
- if line >= rootNodeLine
- throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table"
- endif
- endwhile
- call cursor(line, 0)
-endfunction
-
-"FUNCTION: s:putCursorInTreeWin(){{{2
-"Places the cursor in the nerd tree window
-function! s:putCursorInTreeWin()
- if !s:isTreeOpen()
- throw "NERDTree.InvalidOperationError: cant put cursor in NERD tree window, no window exists"
- endif
-
- call s:exec(s:getTreeWinNum() . "wincmd w")
-endfunction
-
-"FUNCTION: s:renderBookmarks {{{2
-function! s:renderBookmarks()
-
- call setline(line(".")+1, ">----------Bookmarks----------")
- call cursor(line(".")+1, col("."))
-
- for i in s:Bookmark.Bookmarks()
- call setline(line(".")+1, i.str())
- call cursor(line(".")+1, col("."))
- endfor
-
- call setline(line(".")+1, '')
- call cursor(line(".")+1, col("."))
-endfunction
-"FUNCTION: s:renderView {{{2
-"The entry function for rendering the tree
-function! s:renderView()
- setlocal modifiable
-
- "remember the top line of the buffer and the current line so we can
- "restore the view exactly how it was
- let curLine = line(".")
- let curCol = col(".")
- let topLine = line("w0")
-
- "delete all lines in the buffer (being careful not to clobber a register)
- silent 1,$delete _
-
- call s:dumpHelp()
-
- "delete the blank line before the help and add one after it
- call setline(line(".")+1, "")
- call cursor(line(".")+1, col("."))
-
- if b:NERDTreeShowBookmarks
- call s:renderBookmarks()
- endif
-
- "add the 'up a dir' line
- call setline(line(".")+1, s:tree_up_dir_line)
- call cursor(line(".")+1, col("."))
-
- "draw the header line
- let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
- call setline(line(".")+1, header)
- call cursor(line(".")+1, col("."))
-
- "draw the tree
- let old_o = @o
- let @o = b:NERDTreeRoot.renderToString()
- silent put o
- let @o = old_o
-
- "delete the blank line at the top of the buffer
- silent 1,1delete _
-
- "restore the view
- let old_scrolloff=&scrolloff
- let &scrolloff=0
- call cursor(topLine, 1)
- normal! zt
- call cursor(curLine, curCol)
- let &scrolloff = old_scrolloff
-
- setlocal nomodifiable
-endfunction
-
-"FUNCTION: s:renderViewSavingPosition {{{2
-"Renders the tree and ensures the cursor stays on the current node or the
-"current nodes parent if it is no longer available upon re-rendering
-function! s:renderViewSavingPosition()
- let currentNode = s:TreeFileNode.GetSelected()
-
- "go up the tree till we find a node that will be visible or till we run
- "out of nodes
- while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
- let currentNode = currentNode.parent
- endwhile
-
- call s:renderView()
-
- if currentNode != {}
- call currentNode.putCursorHere(0, 0)
- endif
-endfunction
-"FUNCTION: s:restoreScreenState() {{{2
-"
-"Sets the screen state back to what it was when s:saveScreenState was last
-"called.
-"
-"Assumes the cursor is in the NERDTree window
-function! s:restoreScreenState()
- if !exists("b:NERDTreeOldTopLine") || !exists("b:NERDTreeOldPos") || !exists("b:NERDTreeOldWindowSize")
- return
- endif
- exec("silent vertical resize ".b:NERDTreeOldWindowSize)
-
- let old_scrolloff=&scrolloff
- let &scrolloff=0
- call cursor(b:NERDTreeOldTopLine, 0)
- normal! zt
- call setpos(".", b:NERDTreeOldPos)
- let &scrolloff=old_scrolloff
-endfunction
-
-"FUNCTION: s:saveScreenState() {{{2
-"Saves the current cursor position in the current buffer and the window
-"scroll position
-function! s:saveScreenState()
- let win = winnr()
- try
- call s:putCursorInTreeWin()
- let b:NERDTreeOldPos = getpos(".")
- let b:NERDTreeOldTopLine = line("w0")
- let b:NERDTreeOldWindowSize = winwidth("")
- call s:exec(win . "wincmd w")
- catch /^NERDTree.InvalidOperationError/
- endtry
-endfunction
-
-"FUNCTION: s:setupStatusline() {{{2
-function! s:setupStatusline()
- if g:NERDTreeStatusline != -1
- let &l:statusline = g:NERDTreeStatusline
- endif
-endfunction
-"FUNCTION: s:setupSyntaxHighlighting() {{{2
-function! s:setupSyntaxHighlighting()
- "treeFlags are syntax items that should be invisible, but give clues as to
- "how things should be highlighted
- syn match treeFlag #\~#
- syn match treeFlag #\[RO\]#
-
- "highlighting for the .. (up dir) line at the top of the tree
- execute "syn match treeUp #". s:tree_up_dir_line ."#"
-
- "highlighting for the ~/+ symbols for the directory nodes
- syn match treeClosable #\~\<#
- syn match treeClosable #\~\.#
- syn match treeOpenable #+\<#
- syn match treeOpenable #+\.#he=e-1
-
- "highlighting for the tree structural parts
- syn match treePart #|#
- syn match treePart #`#
- syn match treePartFile #[|`]-#hs=s+1 contains=treePart
-
- "quickhelp syntax elements
- syn match treeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1
- syn match treeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1
- syn match treeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=treeFlag
- syn match treeToggleOn #".*(on)#hs=e-2,he=e-1 contains=treeHelpKey
- syn match treeToggleOff #".*(off)#hs=e-3,he=e-1 contains=treeHelpKey
- syn match treeHelpCommand #" :.\{-}\>#hs=s+3
- syn match treeHelp #^".*# contains=treeHelpKey,treeHelpTitle,treeFlag,treeToggleOff,treeToggleOn,treeHelpCommand
-
- "highlighting for readonly files
- syn match treeRO #.*\[RO\]#hs=s+2 contains=treeFlag,treeBookmark,treePart,treePartFile
-
- "highlighting for sym links
- syn match treeLink #[^-| `].* -> # contains=treeBookmark,treeOpenable,treeClosable,treeDirSlash
-
- "highlighing for directory nodes and file nodes
- syn match treeDirSlash #/#
- syn match treeDir #[^-| `].*/# contains=treeLink,treeDirSlash,treeOpenable,treeClosable
- syn match treeExecFile #[|`]-.*\*\($\| \)# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark
- syn match treeFile #|-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile
- syn match treeFile #`-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile
- syn match treeCWD #^/.*$#
-
- "highlighting for bookmarks
- syn match treeBookmark # {.*}#hs=s+1
-
- "highlighting for the bookmarks table
- syn match treeBookmarksLeader #^>#
- syn match treeBookmarksHeader #^>-\+Bookmarks-\+$# contains=treeBookmarksLeader
- syn match treeBookmarkName #^>.\{-} #he=e-1 contains=treeBookmarksLeader
- syn match treeBookmark #^>.*$# contains=treeBookmarksLeader,treeBookmarkName,treeBookmarksHeader
-
- if g:NERDChristmasTree
- hi def link treePart Special
- hi def link treePartFile Type
- hi def link treeFile Normal
- hi def link treeExecFile Title
- hi def link treeDirSlash Identifier
- hi def link treeClosable Type
- else
- hi def link treePart Normal
- hi def link treePartFile Normal
- hi def link treeFile Normal
- hi def link treeClosable Title
- endif
-
- hi def link treeBookmarksHeader statement
- hi def link treeBookmarksLeader ignore
- hi def link treeBookmarkName Identifier
- hi def link treeBookmark normal
-
- hi def link treeHelp String
- hi def link treeHelpKey Identifier
- hi def link treeHelpCommand Identifier
- hi def link treeHelpTitle Macro
- hi def link treeToggleOn Question
- hi def link treeToggleOff WarningMsg
-
- hi def link treeDir Directory
- hi def link treeUp Directory
- hi def link treeCWD Statement
- hi def link treeLink Macro
- hi def link treeOpenable Title
- hi def link treeFlag ignore
- hi def link treeRO WarningMsg
- hi def link treeBookmark Statement
-
- hi def link NERDTreeCurrentNode Search
-endfunction
-
-"FUNCTION: s:stripMarkupFromLine(line, removeLeadingSpaces){{{2
-"returns the given line with all the tree parts stripped off
-"
-"Args:
-"line: the subject line
-"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces =
-"any spaces before the actual text of the node)
-function! s:stripMarkupFromLine(line, removeLeadingSpaces)
- let line = a:line
- "remove the tree parts and the leading space
- let line = substitute (line, s:tree_markup_reg,"","")
-
- "strip off any read only flag
- let line = substitute (line, ' \[RO\]', "","")
-
- "strip off any bookmark flags
- let line = substitute (line, ' {[^}]*}', "","")
-
- "strip off any executable flags
- let line = substitute (line, '*\ze\($\| \)', "","")
-
- let wasdir = 0
- if line =~ '/$'
- let wasdir = 1
- endif
- let line = substitute (line,' -> .*',"","") " remove link to
- if wasdir ==# 1
- let line = substitute (line, '/\?$', '/', "")
- endif
-
- if a:removeLeadingSpaces
- let line = substitute (line, '^ *', '', '')
- endif
-
- return line
-endfunction
-
-"FUNCTION: s:toggle(dir) {{{2
-"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
-"closed it is restored or initialized (if it doesnt exist)
-"
-"Args:
-"dir: the full path for the root node (is only used if the NERD tree is being
-"initialized.
-function! s:toggle(dir)
- if s:treeExistsForTab()
- if !s:isTreeOpen()
- call s:createTreeWin()
- if !&hidden
- call s:renderView()
- endif
- call s:restoreScreenState()
- else
- call s:closeTree()
- endif
- else
- call s:initNerdTree(a:dir)
- endif
-endfunction
-"SECTION: Interface bindings {{{1
-"============================================================
-"FUNCTION: s:activateNode(forceKeepWindowOpen) {{{2
-"If the current node is a file, open it in the previous window (or a new one
-"if the previous is modified). If it is a directory then it is opened.
-"
-"args:
-"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set
-function! s:activateNode(forceKeepWindowOpen)
- if getline(".") ==# s:tree_up_dir_line
- return s:upDir(0)
- endif
-
- let treenode = s:TreeFileNode.GetSelected()
- if treenode != {}
- call treenode.activate(a:forceKeepWindowOpen)
- else
- let bookmark = s:Bookmark.GetSelected()
- if !empty(bookmark)
- call bookmark.activate()
- endif
- endif
-endfunction
-
-"FUNCTION: s:bindMappings() {{{2
-function! s:bindMappings()
- " set up mappings and commands for this buffer
- nnoremap <silent> <buffer> <middlerelease> :call <SID>handleMiddleMouse()<cr>
- nnoremap <silent> <buffer> <leftrelease> <leftrelease>:call <SID>checkForActivate()<cr>
- nnoremap <silent> <buffer> <2-leftmouse> :call <SID>activateNode(0)<cr>
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapActivateNode . " :call <SID>activateNode(0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenSplit ." :call <SID>openEntrySplit(0,0)<cr>"
- exec "nnoremap <silent> <buffer> <cr> :call <SID>activateNode(0)<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreview ." :call <SID>previewNode(0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreviewSplit ." :call <SID>previewNode(1)<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenVSplit ." :call <SID>openEntrySplit(1,0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapPreviewVSplit ." :call <SID>previewNode(2)<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenRecursively ." :call <SID>openNodeRecursively()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdirKeepOpen ." :call <SID>upDir(1)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapUpdir ." :call <SID>upDir(0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChangeRoot ." :call <SID>chRoot()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapChdir ." :call <SID>chCwd()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapQuit ." :call <SID>closeTreeWindow()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefreshRoot ." :call <SID>refreshRoot()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapRefresh ." :call <SID>refreshCurrent()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapHelp ." :call <SID>displayHelp()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleZoom ." :call <SID>toggleZoom()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleHidden ." :call <SID>toggleShowHidden()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFilters ." :call <SID>toggleIgnoreFilter()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleFiles ." :call <SID>toggleShowFiles()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapToggleBookmarks ." :call <SID>toggleShowBookmarks()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseDir ." :call <SID>closeCurrentDir()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapCloseChildren ." :call <SID>closeChildren()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapMenu ." :call <SID>showMenu()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpParent ." :call <SID>jumpToParent()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpNextSibling ." :call <SID>jumpToSibling(1)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpPrevSibling ." :call <SID>jumpToSibling(0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpFirstChild ." :call <SID>jumpToFirstChild()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpLastChild ." :call <SID>jumpToLastChild()<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapJumpRoot ." :call <SID>jumpToRoot()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTab ." :call <SID>openInNewTab(0)<cr>"
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenInTabSilent ." :call <SID>openInNewTab(1)<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapOpenExpl ." :call <SID>openExplorer()<cr>"
-
- exec "nnoremap <silent> <buffer> ". g:NERDTreeMapDeleteBookmark ." :call <SID>deleteBookmark()<cr>"
-
- "bind all the user custom maps
- call s:KeyMap.BindAll()
-
- command! -buffer -nargs=1 Bookmark :call <SID>bookmarkNode('<args>')
- command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call <SID>revealBookmark('<args>')
- command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call <SID>openBookmark('<args>')
- command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call <SID>clearBookmarks('<args>')
- command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('<args>')
- command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() <bar> call <SID>renderView()
- command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) <bar> call <SID>renderView()
- command! -buffer -nargs=0 WriteBookmarks call s:Bookmark.Write()
-endfunction
-
-" FUNCTION: s:bookmarkNode(name) {{{2
-" Associate the current node with the given name
-function! s:bookmarkNode(name)
- let currentNode = s:TreeFileNode.GetSelected()
- if currentNode != {}
- try
- call currentNode.bookmark(a:name)
- call s:renderView()
- catch /^NERDTree.IllegalBookmarkNameError/
- call s:echo("bookmark names must not contain spaces")
- endtry
- else
- call s:echo("select a node first")
- endif
-endfunction
-"FUNCTION: s:checkForActivate() {{{2
-"Checks if the click should open the current node, if so then activate() is
-"called (directories are automatically opened if the symbol beside them is
-"clicked)
-function! s:checkForActivate()
- let currentNode = s:TreeFileNode.GetSelected()
- if currentNode != {}
- let startToCur = strpart(getline(line(".")), 0, col("."))
- let char = strpart(startToCur, strlen(startToCur)-1, 1)
-
- "if they clicked a dir, check if they clicked on the + or ~ sign
- "beside it
- if currentNode.path.isDirectory
- if startToCur =~ s:tree_markup_reg . '$' && char =~ '[+~]'
- call s:activateNode(0)
- return
- endif
- endif
-
- if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
- if char !~ s:tree_markup_reg && startToCur !~ '\/$'
- call s:activateNode(0)
- return
- endif
- endif
- endif
-endfunction
-
-" FUNCTION: s:chCwd() {{{2
-function! s:chCwd()
- let treenode = s:TreeFileNode.GetSelected()
- if treenode ==# {}
- call s:echo("Select a node first")
- return
- endif
-
- try
- call treenode.path.changeToDir()
- catch /^NERDTree.PathChangeError/
- call s:echoWarning("could not change cwd")
- endtry
-endfunction
-
-" FUNCTION: s:chRoot() {{{2
-" changes the current root to the selected one
-function! s:chRoot()
- let treenode = s:TreeFileNode.GetSelected()
- if treenode ==# {}
- call s:echo("Select a node first")
- return
- endif
-
- call treenode.makeRoot()
- call s:renderView()
- call b:NERDTreeRoot.putCursorHere(0, 0)
-endfunction
-
-" FUNCTION: s:clearBookmarks(bookmarks) {{{2
-function! s:clearBookmarks(bookmarks)
- if a:bookmarks ==# ''
- let currentNode = s:TreeFileNode.GetSelected()
- if currentNode != {}
- call currentNode.clearBoomarks()
- endif
- else
- for name in split(a:bookmarks, ' ')
- let bookmark = s:Bookmark.BookmarkFor(name)
- call bookmark.delete()
- endfor
- endif
- call s:renderView()
-endfunction
-" FUNCTION: s:closeChildren() {{{2
-" closes all childnodes of the current node
-function! s:closeChildren()
- let currentNode = s:TreeDirNode.GetSelected()
- if currentNode ==# {}
- call s:echo("Select a node first")
- return
- endif
-
- call currentNode.closeChildren()
- call s:renderView()
- call currentNode.putCursorHere(0, 0)
-endfunction
-" FUNCTION: s:closeCurrentDir() {{{2
-" closes the parent dir of the current node
-function! s:closeCurrentDir()
- let treenode = s:TreeFileNode.GetSelected()
- if treenode ==# {}
- call s:echo("Select a node first")
- return
- endif
-
- let parent = treenode.parent
- if parent ==# {} || parent.isRoot()
- call s:echo("cannot close tree root")
- else
- call treenode.parent.close()
- call s:renderView()
- call treenode.parent.putCursorHere(0, 0)
- endif
-endfunction
-" FUNCTION: s:closeTreeWindow() {{{2
-" close the tree window
-function! s:closeTreeWindow()
- if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1
- exec "buffer " . b:NERDTreePreviousBuf
- else
- if winnr("$") > 1
- call s:closeTree()
- else
- call s:echo("Cannot close last window")
- endif
- endif
-endfunction
-" FUNCTION: s:deleteBookmark() {{{2
-" if the cursor is on a bookmark, prompt to delete
-function! s:deleteBookmark()
- let bookmark = s:Bookmark.GetSelected()
- if bookmark ==# {}
- call s:echo("Put the cursor on a bookmark")
- return
- endif
-
- echo "Are you sure you wish to delete the bookmark:\n\"" . bookmark.name . "\" (yN):"
-
- if nr2char(getchar()) ==# 'y'
- try
- call bookmark.delete()
- call s:renderView()
- redraw
- catch /^NERDTree/
- call s:echoWarning("Could not remove bookmark")
- endtry
- else
- call s:echo("delete aborted" )
- endif
-
-endfunction
-
-" FUNCTION: s:displayHelp() {{{2
-" toggles the help display
-function! s:displayHelp()
- let b:treeShowHelp = b:treeShowHelp ? 0 : 1
- call s:renderView()
- call s:centerView()
-endfunction
-
-" FUNCTION: s:handleMiddleMouse() {{{2
-function! s:handleMiddleMouse()
- let curNode = s:TreeFileNode.GetSelected()
- if curNode ==# {}
- call s:echo("Put the cursor on a node first" )
- return
- endif
-
- if curNode.path.isDirectory
- call s:openExplorer()
- else
- call s:openEntrySplit(0,0)
- endif
-endfunction
-
-
-" FUNCTION: s:jumpToFirstChild() {{{2
-" wrapper for the jump to child method
-function! s:jumpToFirstChild()
- call s:jumpToChild(0)
-endfunction
-
-" FUNCTION: s:jumpToLastChild() {{{2
-" wrapper for the jump to child method
-function! s:jumpToLastChild()
- call s:jumpToChild(1)
-endfunction
-
-" FUNCTION: s:jumpToParent() {{{2
-" moves the cursor to the parent of the current node
-function! s:jumpToParent()
- let currentNode = s:TreeFileNode.GetSelected()
- if !empty(currentNode)
- if !empty(currentNode.parent)
- call currentNode.parent.putCursorHere(1, 0)
- call s:centerView()
- else
- call s:echo("cannot jump to parent")
- endif
- else
- call s:echo("put the cursor on a node first")
- endif
-endfunction
-
-" FUNCTION: s:jumpToRoot() {{{2
-" moves the cursor to the root node
-function! s:jumpToRoot()
- call b:NERDTreeRoot.putCursorHere(1, 0)
- call s:centerView()
-endfunction
-
-" FUNCTION: s:jumpToSibling() {{{2
-" moves the cursor to the sibling of the current node in the given direction
-"
-" Args:
-" forward: 1 if the cursor should move to the next sibling, 0 if it should
-" move back to the previous sibling
-function! s:jumpToSibling(forward)
- let currentNode = s:TreeFileNode.GetSelected()
- if !empty(currentNode)
- let sibling = currentNode.findSibling(a:forward)
-
- if !empty(sibling)
- call sibling.putCursorHere(1, 0)
- call s:centerView()
- endif
- else
- call s:echo("put the cursor on a node first")
- endif
-endfunction
-
-" FUNCTION: s:openBookmark(name) {{{2
-" put the cursor on the given bookmark and, if its a file, open it
-function! s:openBookmark(name)
- try
- let targetNode = s:Bookmark.GetNodeForName(a:name, 0)
- call targetNode.putCursorHere(0, 1)
- redraw!
- catch /^NERDTree.BookmarkedNodeNotFoundError/
- call s:echo("note - target node is not cached")
- let bookmark = s:Bookmark.BookmarkFor(a:name)
- let targetNode = s:TreeFileNode.New(bookmark.path)
- endtry
- if targetNode.path.isDirectory
- call targetNode.openExplorer()
- else
- call targetNode.open()
- endif
-endfunction
-" FUNCTION: s:openEntrySplit(vertical, forceKeepWindowOpen) {{{2
-"Opens the currently selected file from the explorer in a
-"new window
-"
-"args:
-"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set
-function! s:openEntrySplit(vertical, forceKeepWindowOpen)
- let treenode = s:TreeFileNode.GetSelected()
- if treenode != {}
- if a:vertical
- call treenode.openVSplit()
- else
- call treenode.openSplit()
- endif
- if !a:forceKeepWindowOpen
- call s:closeTreeIfQuitOnOpen()
- endif
- else
- call s:echo("select a node first")
- endif
-endfunction
-
-" FUNCTION: s:openExplorer() {{{2
-function! s:openExplorer()
- let treenode = s:TreeDirNode.GetSelected()
- if treenode != {}
- call treenode.openExplorer()
- else
- call s:echo("select a node first")
- endif
-endfunction
-
-" FUNCTION: s:openInNewTab(stayCurrentTab) {{{2
-" Opens the selected node or bookmark in a new tab
-" Args:
-" stayCurrentTab: if 1 then vim will stay in the current tab, if 0 then vim
-" will go to the tab where the new file is opened
-function! s:openInNewTab(stayCurrentTab)
- let target = s:TreeFileNode.GetSelected()
- if target == {}
- let target = s:Bookmark.GetSelected()
- endif
-
- if target != {}
- call target.openInNewTab({'stayInCurrentTab': a:stayCurrentTab})
- endif
-endfunction
-
-" FUNCTION: s:openNodeRecursively() {{{2
-function! s:openNodeRecursively()
- let treenode = s:TreeFileNode.GetSelected()
- if treenode ==# {} || treenode.path.isDirectory ==# 0
- call s:echo("Select a directory node first" )
- else
- call s:echo("Recursively opening node. Please wait...")
- call treenode.openRecursively()
- call s:renderView()
- redraw
- call s:echo("Recursively opening node. Please wait... DONE")
- endif
-
-endfunction
-
-"FUNCTION: s:previewNode() {{{2
-"Args:
-" openNewWin: if 0, use the previous window, if 1 open in new split, if 2
-" open in a vsplit
-function! s:previewNode(openNewWin)
- let currentBuf = bufnr("")
- if a:openNewWin > 0
- call s:openEntrySplit(a:openNewWin ==# 2,1)
- else
- call s:activateNode(1)
- end
- call s:exec(bufwinnr(currentBuf) . "wincmd w")
-endfunction
-
-" FUNCTION: s:revealBookmark(name) {{{2
-" put the cursor on the node associate with the given name
-function! s:revealBookmark(name)
- try
- let targetNode = s:Bookmark.GetNodeForName(a:name, 0)
- call targetNode.putCursorHere(0, 1)
- catch /^NERDTree.BookmarkNotFoundError/
- call s:echo("Bookmark isnt cached under the current root")
- endtry
-endfunction
-" FUNCTION: s:refreshRoot() {{{2
-" Reloads the current root. All nodes below this will be lost and the root dir
-" will be reloaded.
-function! s:refreshRoot()
- call s:echo("Refreshing the root node. This could take a while...")
- call b:NERDTreeRoot.refresh()
- call s:renderView()
- redraw
- call s:echo("Refreshing the root node. This could take a while... DONE")
-endfunction
-
-" FUNCTION: s:refreshCurrent() {{{2
-" refreshes the root for the current node
-function! s:refreshCurrent()
- let treenode = s:TreeDirNode.GetSelected()
- if treenode ==# {}
- call s:echo("Refresh failed. Select a node first")
- return
- endif
-
- call s:echo("Refreshing node. This could take a while...")
- call treenode.refresh()
- call s:renderView()
- redraw
- call s:echo("Refreshing node. This could take a while... DONE")
-endfunction
-" FUNCTION: s:showMenu() {{{2
-function! s:showMenu()
- let curNode = s:TreeFileNode.GetSelected()
- if curNode ==# {}
- call s:echo("Put the cursor on a node first" )
- return
- endif
-
- let mc = s:MenuController.New(s:MenuItem.AllEnabled())
- call mc.showMenu()
-endfunction
-
-" FUNCTION: s:toggleIgnoreFilter() {{{2
-" toggles the use of the NERDTreeIgnore option
-function! s:toggleIgnoreFilter()
- let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled
- call s:renderViewSavingPosition()
- call s:centerView()
-endfunction
-
-" FUNCTION: s:toggleShowBookmarks() {{{2
-" toggles the display of bookmarks
-function! s:toggleShowBookmarks()
- let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks
- if b:NERDTreeShowBookmarks
- call s:renderView()
- call s:putCursorOnBookmarkTable()
- else
- call s:renderViewSavingPosition()
- endif
- call s:centerView()
-endfunction
-" FUNCTION: s:toggleShowFiles() {{{2
-" toggles the display of hidden files
-function! s:toggleShowFiles()
- let b:NERDTreeShowFiles = !b:NERDTreeShowFiles
- call s:renderViewSavingPosition()
- call s:centerView()
-endfunction
-
-" FUNCTION: s:toggleShowHidden() {{{2
-" toggles the display of hidden files
-function! s:toggleShowHidden()
- let b:NERDTreeShowHidden = !b:NERDTreeShowHidden
- call s:renderViewSavingPosition()
- call s:centerView()
-endfunction
-
-" FUNCTION: s:toggleZoom() {{2
-" zoom (maximize/minimize) the NERDTree window
-function! s:toggleZoom()
- if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
- let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
- exec "silent vertical resize ". size
- let b:NERDTreeZoomed = 0
- else
- exec "vertical resize"
- let b:NERDTreeZoomed = 1
- endif
-endfunction
-
-"FUNCTION: s:upDir(keepState) {{{2
-"moves the tree up a level
-"
-"Args:
-"keepState: 1 if the current root should be left open when the tree is
-"re-rendered
-function! s:upDir(keepState)
- let cwd = b:NERDTreeRoot.path.str({'format': 'UI'})
- if cwd ==# "/" || cwd =~ '^[^/]..$'
- call s:echo("already at top dir")
- else
- if !a:keepState
- call b:NERDTreeRoot.close()
- endif
-
- let oldRoot = b:NERDTreeRoot
-
- if empty(b:NERDTreeRoot.parent)
- let path = b:NERDTreeRoot.path.getParent()
- let newRoot = s:TreeDirNode.New(path)
- call newRoot.open()
- call newRoot.transplantChild(b:NERDTreeRoot)
- let b:NERDTreeRoot = newRoot
- else
- let b:NERDTreeRoot = b:NERDTreeRoot.parent
- endif
-
- if g:NERDTreeChDirMode ==# 2
- call b:NERDTreeRoot.path.changeToDir()
- endif
-
- call s:renderView()
- call oldRoot.putCursorHere(0, 0)
- endif
-endfunction
-
-
-"reset &cpo back to users setting
-let &cpo = s:old_cpo
-
-" vim: set sw=4 sts=4 et fdm=marker: