# HG changeset patch # User Steve Losh # Date 1290455115 18000 # Node ID 57fb163c7556d8581d66c2c89be44c358da11723 # Parent df20584e0efde1e997e1fab3acdc66a3cbe6d16d sub: vim/nerd* diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdcommenter/.gitignore --- a/vim/bundle/nerdcommenter/.gitignore Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -*~ -*.swp diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdcommenter/Rakefile --- a/vim/bundle/nerdcommenter/Rakefile Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -desc "Copy the vim/doc files into ~/.vim" -task :deploy_local do - run "cp plugin/NERD_commenter.vim ~/.vim/plugin" - run "cp doc/NERD_commenter.txt ~/.vim/doc" -end - - -desc "Create a zip archive for release to vim.org" -task :zip do - abort "NERD_commenter.zip already exists, aborting" if File.exist?("NERD_commenter.zip") - run "zip NERD_commenter.zip plugin/NERD_commenter.vim doc/NERD_commenter.txt" -end - -def run(cmd) - puts "Executing: #{cmd}" - system cmd -end - diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdcommenter/doc/NERD_commenter.txt --- a/vim/bundle/nerdcommenter/doc/NERD_commenter.txt Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,991 +0,0 @@ -*NERD_commenter.txt* Plugin for commenting code - - - NERD COMMENTER REFERENCE MANUAL~ - - - - - -============================================================================== -CONTENTS *NERDCommenterContents* - - 1.Intro...................................|NERDCommenter| - 2.Functionality provided..................|NERDComFunctionality| - 2.1 Functionality Summary.............|NERDComFunctionalitySummary| - 2.2 Functionality Details.............|NERDComFunctionalityDetails| - 2.2.1 Comment map.................|NERDComComment| - 2.2.2 Nested comment map..........|NERDComNestedComment| - 2.2.3 Toggle comment map..........|NERDComToggleComment| - 2.2.4 Minimal comment map.........|NERDComMinimalComment| - 2.2.5 Invert comment map..........|NERDComInvertComment| - 2.2.6 Sexy comment map............|NERDComSexyComment| - 2.2.7 Yank comment map............|NERDComYankComment| - 2.2.8 Comment to EOL map..........|NERDComEOLComment| - 2.2.9 Append com to line map......|NERDComAppendComment| - 2.2.10 Insert comment map.........|NERDComInsertComment| - 2.2.11 Use alternate delims map...|NERDComAltDelim| - 2.2.12 Comment aligned maps.......|NERDComAlignedComment| - 2.2.13 Uncomment line map.........|NERDComUncommentLine| - 2.3 Supported filetypes...............|NERDComFiletypes| - 2.4 Sexy Comments.....................|NERDComSexyComments| - 2.5 The NERDComment function..........|NERDComNERDComment| - 3.Options.................................|NERDComOptions| - 3.1 Options summary...................|NERDComOptionsSummary| - 3.2 Options details...................|NERDComOptionsDetails| - 3.3 Default delimiter Options.........|NERDComDefaultDelims| - 4. Customising key mappings...............|NERDComMappings| - 5. Issues with the script.................|NERDComIssues| - 5.1 Delimiter detection heuristics....|NERDComHeuristics| - 5.2 Nesting issues....................|NERDComNesting| - 6.About.. ............................|NERDComAbout| - 7.Changelog...............................|NERDComChangelog| - 8.Credits.................................|NERDComCredits| - 9.License.................................|NERDComLicense| - -============================================================================== -1. Intro *NERDCommenter* - -The NERD commenter provides many different commenting operations and styles -which are invoked via key mappings and a menu. These operations are available -for most filetypes. - -There are also options that allow to tweak the commenting engine to your -taste. - -============================================================================== -2. Functionality provided *NERDComFunctionality* - ------------------------------------------------------------------------------- -2.1 Functionality summary *NERDComFunctionalitySummary* - -The following key mappings are provided by default (there is also a menu -with items corresponding to all the mappings below): - -[count],cc |NERDComComment| -Comment out the current line or text selected in visual mode. - - -[count],cn |NERDComNestedComment| -Same as ,cc but forces nesting. - - -[count],c |NERDComToggleComment| -Toggles the comment state of the selected line(s). If the topmost selected -line is commented, all selected lines are uncommented and vice versa. - - -[count],cm |NERDComMinimalComment| -Comments the given lines using only one set of multipart delimiters. - - -[count],ci |NERDComInvertComment| -Toggles the comment state of the selected line(s) individually. - - -[count],cs |NERDComSexyComment| -Comments out the selected lines ``sexily'' - - -[count],cy |NERDComYankComment| -Same as ,cc except that the commented line(s) are yanked first. - - -,c$ |NERDComEOLComment| -Comments the current line from the cursor to the end of line. - - -,cA |NERDComAppendComment| -Adds comment delimiters to the end of line and goes into insert mode between -them. - - -|NERDComInsertComment| -Adds comment delimiters at the current cursor position and inserts between. -Disabled by default. - - -,ca |NERDComAltDelim| -Switches to the alternative set of delimiters. - - -[count],cl -[count],cb |NERDComAlignedComment| -Same as |NERDComComment| except that the delimiters are aligned down the -left side (,cl) or both sides (,cb). - - -[count],cu |NERDComUncommentLine| -Uncomments the selected line(s). - ------------------------------------------------------------------------------- -2.2 Functionality details *NERDComFunctionalityDetails* - ------------------------------------------------------------------------------- -2.2.1 Comment map *NERDComComment* - -Default mapping: [count],cc -Mapped to: NERDCommenterComment -Applicable modes: normal visual visual-line visual-block. - - -Comments out the current line. If multiple lines are selected in visual-line -mode, they are all commented out. If some text is selected in visual or -visual-block mode then the script will try to comment out the exact text that -is selected using multi-part delimiters if they are available. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - ------------------------------------------------------------------------------- -2.2.2 Nested comment map *NERDComNestedComment* - -Default mapping: [count],cn -Mapped to: NERDCommenterNest -Applicable modes: normal visual visual-line visual-block. - -Performs nested commenting. Works the same as ,cc except that if a line is -already commented then it will be commented again. - -If |'NERDUsePlaceHolders'| is set then the previous comment delimiters will -be replaced by place-holder delimiters if needed. Otherwise the nested -comment will only be added if the current commenting delimiters have no right -delimiter (to avoid syntax errors) - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - -Related options: -|'NERDDefaultNesting'| - ------------------------------------------------------------------------------- -2.2.3 Toggle comment map *NERDComToggleComment* - -Default mapping: [count],c -Mapped to: NERDCommenterToggle -Applicable modes: normal visual-line. - -Toggles commenting of the lines selected. The behaviour of this mapping -depends on whether the first line selected is commented or not. If so, all -selected lines are uncommented and vice versa. - -With this mapping, a line is only considered to be commented if it starts with -a left delimiter. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - ------------------------------------------------------------------------------- -2.2.4 Minimal comment map *NERDComMinimalComment* - -Default mapping: [count],cm -Mapped to: NERDCommenterMinimal -Applicable modes: normal visual-line. - -Comments the selected lines using one set of multipart delimiters if possible. - -For example: if you are programming in c and you select 5 lines and press ,cm -then a '/*' will be placed at the start of the top line and a '*/' will be -placed at the end of the last line. - -Sets of multipart comment delimiters that are between the top and bottom -selected lines are replaced with place holders (see |'NERDLPlace'|) if -|'NERDUsePlaceHolders'| is set for the current filetype. If it is not, then -the comment will be aborted if place holders are required to prevent illegal -syntax. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - ------------------------------------------------------------------------------- -2.2.5 Invert comment map *NERDComInvertComment* - -Default mapping: ,ci -Mapped to: NERDCommenterInvert -Applicable modes: normal visual-line. - -Inverts the commented state of each selected line. If the a selected line is -commented then it is uncommented and vice versa. Each line is examined and -commented/uncommented individually. - -With this mapping, a line is only considered to be commented if it starts with -a left delimiter. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - ------------------------------------------------------------------------------- -2.2.6 Sexy comment map *NERDComSexyComment* - -Default mapping: [count],cs -Mapped to: NERDCommenterSexy -Applicable modes: normal, visual-line. - -Comments the selected line(s) ``sexily''... see |NERDComSexyComments| for -a description of what sexy comments are. Can only be done on filetypes for -which there is at least one set of multipart comment delimiters specified. - -Sexy comments cannot be nested and lines inside a sexy comment cannot be -commented again. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - -Related options: -|'NERDCompactSexyComs'| - ------------------------------------------------------------------------------- -2.2.7 Yank comment map *NERDComYankComment* - -Default mapping: [count],cy -Mapped to: NERDCommenterYank -Applicable modes: normal visual visual-line visual-block. - -Same as ,cc except that it yanks the line(s) that are commented first. - ------------------------------------------------------------------------------- -2.2.8 Comment to EOL map *NERDComEOLComment* - -Default mapping: ,c$ -Mapped to: NERDCommenterToEOL -Applicable modes: normal. - -Comments the current line from the current cursor position up to the end of -the line. - ------------------------------------------------------------------------------- -2.2.9 Append com to line map *NERDComAppendComment* - -Default mapping: ,cA -Mapped to: NERDCommenterAppend -Applicable modes: normal. - -Appends comment delimiters to the end of the current line and goes -to insert mode between the new delimiters. - ------------------------------------------------------------------------------- -2.2.10 Insert comment map *NERDComInsertComment* - -Default mapping: disabled by default. -Map it to: NERDCommenterInInsert -Applicable modes: insert. - -Adds comment delimiters at the current cursor position and inserts -between them. - -NOTE: prior to version 2.1.17 this was mapped to ctrl-c. To restore this -mapping add > - let NERDComInsertMap='' -< -to your vimrc. - ------------------------------------------------------------------------------- -2.2.11 Use alternate delims map *NERDComAltDelim* - -Default mapping: ,ca -Mapped to: NERDCommenterAltDelims -Applicable modes: normal. - -Changes to the alternative commenting style if one is available. For example, -if the user is editing a c++ file using // comments and they hit ,ca -then they will be switched over to /**/ comments. - -See also |NERDComDefaultDelims| - ------------------------------------------------------------------------------- -2.2.12 Comment aligned maps *NERDComAlignedComment* - -Default mappings: [count],cl [count],cb -Mapped to: NERDCommenterAlignLeft - NERDCommenterAlignBoth -Applicable modes: normal visual-line. - -Same as ,cc except that the comment delimiters are aligned on the left side or -both sides respectively. These comments are always nested if the line(s) are -already commented. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - ------------------------------------------------------------------------------- -2.2.13 Uncomment line map *NERDComUncommentLine* - -Default mapping: [count],cu -Mapped to: NERDCommenterUncomment -Applicable modes: normal visual visual-line visual-block. - -Uncomments the current line. If multiple lines are selected in -visual mode then they are all uncommented. - -When uncommenting, if the line contains multiple sets of delimiters then the -``outtermost'' pair of delimiters will be removed. - -The script uses a set of heurisics to distinguish ``real'' delimiters from -``fake'' ones when uncommenting. See |NERDComIssues| for details. - -If a [count] is given in normal mode, the mapping works as though that many -lines were selected in visual-line mode. - -Related options: -|'NERDRemoveAltComs'| -|'NERDRemoveExtraSpaces'| - ------------------------------------------------------------------------------- -2.3 Supported filetypes *NERDComFiletypes* - -Filetypes that can be commented by this plugin: -abaqus abc acedb ada ahdl amiga aml ampl ant apache apachestyle asm68k asm asn -aspvbs atlas autohotkey autoit automake ave awk basic b bc bdf bib bindzone -bst btm caos catalog c cfg cg ch changelog cl clean clipper cmake conf config -context cpp crontab cs csc csp css cterm cupl csv cvs dcl debchangelog -debcontrol debsources def diff django docbk dns dosbatch dosini dot dracula -dsl dtd dtml dylan ecd eiffel elf elmfilt erlang eruby eterm expect exports -fetchmail fgl focexec form fortran foxpro fstab fvwm fx gdb gdmo geek -gentoo-package-keywords' gentoo-package-mask' gentoo-package-use' gnuplot -gtkrc haskell hb h help hercules hog html htmldjango htmlos ia64 icon idlang -idl indent inform inittab ishd iss ist jam java javascript jess jgraph -jproperties jproperties jsp kconfig kix kscript lace lex lftp lifelines lilo -lisp lite lotos lout lprolog lscript lss lua lynx m4 mail make maple masm -master matlab mel mf mib mma model moduala. modula2 modula3 monk mush muttrc -named nasm nastran natural ncf netdict netrw nqc nroff nsis objc ocaml occam -omlet omnimark openroad opl ora otl ox pascal passwd pcap pccts perl pfmain -php phtml pic pike pilrc pine plaintex plm plsql po postscr pov povini ppd -ppwiz procmail progress prolog psf ptcap python python qf radiance ratpoison r -rc readline rebol registry remind rexx robots rpl rtf ruby sa samba sas sass -sather scheme scilab screen scsh sdl sed selectbuf sgml sgmldecl sgmllnx sh -sicad simula sinda skill slang sl slrnrc sm smarty smil smith sml snnsnet -snnspat snnsres snobol4 spec specman spice sql sqlforms sqlj sqr squid st stp -strace svn systemverilog tads taglist tags tak tasm tcl terminfo tex text -plaintex texinfo texmf tf tidy tli trasys tsalt tsscl tssgm uc uil vb verilog -verilog_systemverilog vgrindefs vhdl vim viminfo virata vo_base vrml vsejcl -webmacro wget winbatch wml wvdial xdefaults xf86conf xhtml xkb xmath xml -xmodmap xpm2 xpm xslt yacc yaml z8a - -If a language is not in the list of hardcoded supported filetypes then the -&commentstring vim option is used. - ------------------------------------------------------------------------------- -2.4 Sexy Comments *NERDComSexyComments* -These are comments that use one set of multipart comment delimiters as well as -one other marker symbol. For example: > - /* - * This is a c style sexy comment - * So there! - */ - - /* This is a c style sexy comment - * So there! - * But this one is ``compact'' style */ -< -Here the multipart delimiters are /* and */ and the marker is *. - ------------------------------------------------------------------------------- -2.5 The NERDComment function *NERDComNERDComment* - -All of the NERD commenter mappings and menu items invoke a single function -which delegates the commenting work to other functions. This function is -public and has the prototype: > - function! NERDComment(isVisual, type) -< -The arguments to this function are simple: - - isVisual: if you wish to do any kind of visual comment then set this to - 1 and the function will use the '< and '> marks to find the comment - boundries. If set to 0 then the function will operate on the current - line. - - type: is used to specify what type of commenting operation is to be - performed, and it can be one of the following: "sexy", "invert", - "minimal", "toggle", "alignLeft", "alignBoth", "norm", "nested", - "toEOL", "append", "insert", "uncomment", "yank" - -For example, if you typed > - :call NERDComment(1, 'sexy') -< -then the script would do a sexy comment on the last visual selection. - - -============================================================================== -3. Options *NERDComOptions* - ------------------------------------------------------------------------------- -3.1 Options summary *NERDComOptionsSummary* - -|'loaded_nerd_comments'| Turns off the script. -|'NERDAllowAnyVisualDelims'| Allows multipart alternative delims to - be used when commenting in - visual/visual-block mode. -|'NERDBlockComIgnoreEmpty'| Forces right delims to be placed when - doing visual-block comments. -|'NERDCommentWholeLinesInVMode'| Changes behaviour of visual comments. -|'NERDCreateDefaultMappings'| Turn the default mappings on/off. -|'NERDDefaultNesting'| Tells the script to use nested comments - by default. -|'NERDMenuMode'| Specifies how the NERD commenter menu - will appear (if at all). -|'NERDLPlace'| Specifies what to use as the left - delimiter placeholder when nesting - comments. -|'NERDUsePlaceHolders'| Specifies which filetypes may use - placeholders when nesting comments. -|'NERDRemoveAltComs'| Tells the script whether to remove - alternative comment delimiters when - uncommenting. -|'NERDRemoveExtraSpaces'| Tells the script to always remove the - extra spaces when uncommenting - (regardless of whether NERDSpaceDelims - is set) -|'NERDRPlace'| Specifies what to use as the right - delimiter placeholder when nesting - comments. -|'NERDSpaceDelims'| Specifies whether to add extra spaces - around delimiters when commenting, and - whether to remove them when - uncommenting. -|'NERDCompactSexyComs'| Specifies whether to use the compact - style sexy comments. - ------------------------------------------------------------------------------- -3.3 Options details *NERDComOptionsDetails* - -To enable any of the below options you should put the given line in your -~/.vimrc - - *'loaded_nerd_comments'* -If this script is driving you insane you can turn it off by setting this -option > - let loaded_nerd_comments=1 -< ------------------------------------------------------------------------------- - *'NERDAllowAnyVisualDelims'* -Values: 0 or 1. -Default: 1. - -If set to 1 then, when doing a visual or visual-block comment (but not a -visual-line comment), the script will choose the right delimiters to use for -the comment. This means either using the current delimiters if they are -multipart or using the alternative delimiters if THEY are multipart. For -example if we are editing the following java code: > - float foo = 1221; - float bar = 324; - System.out.println(foo * bar); -< -If we are using // comments and select the "foo" and "bar" in visual-block -mode, as shown left below (where '|'s are used to represent the visual-block -boundary), and comment it then the script will use the alternative delims as -shown on the right: > - - float |foo| = 1221; float /*foo*/ = 1221; - float |bar| = 324; float /*bar*/ = 324; - System.out.println(foo * bar); System.out.println(foo * bar); -< ------------------------------------------------------------------------------- - *'NERDBlockComIgnoreEmpty'* -Values: 0 or 1. -Default: 1. - -This option affects visual-block mode commenting. If this option is turned -on, lines that begin outside the right boundary of the selection block will be -ignored. - -For example, if you are commenting this chunk of c code in visual-block mode -(where the '|'s are used to represent the visual-block boundary) > - #include - #include - #include - |int| main(){ - | | printf("SUCK THIS\n"); - | | while(1){ - | | fork(); - | | } - |} | -< -If NERDBlockComIgnoreEmpty=0 then this code will become: > - #include - #include - #include - /*int*/ main(){ - /* */ printf("SUCK THIS\n"); - /* */ while(1){ - /* */ fork(); - /* */ } - /*} */ -< -Otherwise, the code block would become: > - #include - #include - #include - /*int*/ main(){ - printf("SUCK THIS\n"); - while(1){ - fork(); - } - /*} */ -< ------------------------------------------------------------------------------- - *'NERDCommentWholeLinesInVMode'* -Values: 0, 1 or 2. -Default: 0. - -By default the script tries to comment out exactly what is selected in visual -mode (v). For example if you select and comment the following c code (using | -to represent the visual boundary): > - in|t foo = 3; - int bar =| 9; - int baz = foo + bar; -< -This will result in: > - in/*t foo = 3;*/ - /*int bar =*/ 9; - int baz = foo + bar; -< -But some people prefer it if the whole lines are commented like: > - /*int foo = 3;*/ - /*int bar = 9;*/ - int baz = foo + bar; -< -If you prefer the second option then stick this line in your vimrc: > - let NERDCommentWholeLinesInVMode=1 -< - -If the filetype you are editing only has no multipart delimiters (for example -a shell script) and you hadnt set this option then the above would become > - in#t foo = 3; - #int bar = 9; -< -(where # is the comment delimiter) as this is the closest the script can -come to commenting out exactly what was selected. If you prefer for whole -lines to be commented out when there is no multipart delimiters but the EXACT -text that was selected to be commented out if there IS multipart delimiters -then stick the following line in your vimrc: > - let NERDCommentWholeLinesInVMode=2 -< - -Note that this option does not affect the behaviour of commenting in -|visual-block| mode. - ------------------------------------------------------------------------------- - *'NERDCreateDefaultMappings'* -Values: 0 or 1. -Default: 1. - -If set to 0, none of the default mappings will be created. - -See also |NERDComMappings|. - ------------------------------------------------------------------------------- - *'NERDRemoveAltComs'* -Values: 0 or 1. -Default: 1. - -When uncommenting a line (for a filetype with an alternative commenting style) -this option tells the script whether to look for, and remove, comment -delimiters of the alternative style. - -For example, if you are editing a c++ file using // style comments and you go -,cu on this line: > - /* This is a c++ comment baby! */ -< -It will not be uncommented if the NERDRemoveAltComs is set to 0. - ------------------------------------------------------------------------------- - *'NERDRemoveExtraSpaces'* -Values: 0 or 1. -Default: 1. - -By default, the NERD commenter will remove spaces around comment delimiters if -either: -1. |'NERDSpaceDelims'| is set to 1. -2. NERDRemoveExtraSpaces is set to 1. - -This means that if we have the following lines in a c code file: > - /* int foo = 5; */ - /* int bar = 10; */ - int baz = foo + bar -< -If either of the above conditions hold then if these lines are uncommented -they will become: > - int foo = 5; - int bar = 10; - int baz = foo + bar -< -Otherwise they would become: > - int foo = 5; - int bar = 10; - int baz = foo + bar -< -If you want the spaces to be removed only if |'NERDSpaceDelims'| is set then -set NERDRemoveExtraSpaces to 0. - ------------------------------------------------------------------------------- - *'NERDLPlace'* - *'NERDRPlace'* -Values: arbitrary string. -Default: - NERDLPlace: "[>" - NERDRPlace: "<]" - -These options are used to control the strings used as place-holder delimiters. -Place holder delimiters are used when performing nested commenting when the -filetype supports commenting styles with both left and right delimiters. -To set these options use lines like: > - let NERDLPlace="FOO" - let NERDRPlace="BAR" -< -Following the above example, if we have line of c code: > - /* int horse */ -< -and we comment it with ,cn it will be changed to: > - /*FOO int horse BAR*/ -< -When we uncomment this line it will go back to what it was. - ------------------------------------------------------------------------------- - *'NERDMenuMode'* -Values: 0, 1, 2, 3. -Default: 3 - -This option can take 4 values: - "0": Turns the menu off. - "1": Turns the 'comment' menu on with no menu shortcut. - "2": Turns the 'comment 'menu on with -c as the shortcut. - "3": Turns the 'Plugin -> comment' menu on with -c as the shortcut. - ------------------------------------------------------------------------------- - *'NERDUsePlaceHolders'* -Values: 0 or 1. -Default 1. - -This option is used to specify whether place-holder delimiters should be used -when creating a nested comment. - ------------------------------------------------------------------------------- - *'NERDSpaceDelims'* -Values: 0 or 1. -Default 0. - -Some people prefer a space after the left delimiter and before the right -delimiter like this: > - /* int foo=2; */ -< -as opposed to this: > - /*int foo=2;*/ -< -If you want spaces to be added then set NERDSpaceDelims to 1 in your vimrc. - -See also |'NERDRemoveExtraSpaces'|. - ------------------------------------------------------------------------------- - *'NERDCompactSexyComs'* -Values: 0 or 1. -Default 0. - -Some people may want their sexy comments to be like this: > - /* Hi There! - * This is a sexy comment - * in c */ -< -As opposed to like this: > - /* - * Hi There! - * This is a sexy comment - * in c - */ -< -If this option is set to 1 then the top style will be used. - ------------------------------------------------------------------------------- - *'NERDDefaultNesting'* -Values: 0 or 1. -Default 1. - -When this option is set to 1, comments are nested automatically. That is, if -you hit ,cc on a line that is already commented it will be commented again - ------------------------------------------------------------------------------- -3.3 Default delimiter customisation *NERDComDefaultDelims* - -If you want the NERD commenter to use the alternative delimiters for a -specific filetype by default then put a line of this form into your vimrc: > - let NERD__alt_style=1 -< -Example: java uses // style comments by default, but you want it to default to -/* */ style comments instead. You would put this line in your vimrc: > - let NERD_java_alt_style=1 -< - -See |NERDComAltDelim| for switching commenting styles at runtime. - -============================================================================== -4. Key mapping customisation *NERDComMappings* - -To change a mapping just map another key combo to the internal mapping. -For example, to remap the |NERDComComment| mapping to ",omg" you would put -this line in your vimrc: > - map ,omg NERDCommenterComment -< -This will stop the corresponding default mappings from being created. - -See the help for the mapping in question to see which mapping to -map to. - -See also |'NERDCreateDefaultMappings'|. - -============================================================================== -5. Issues with the script *NERDComIssues* - - ------------------------------------------------------------------------------- -5.1 Delimiter detection heuristics *NERDComHeuristics* - -Heuristics are used to distinguish the real comment delimiters - -Because we have comment mappings that place delimiters in the middle of lines, -removing comment delimiters is a bit tricky. This is because if comment -delimiters appear in a line doesnt mean they really ARE delimiters. For -example, Java uses // comments but the line > - System.out.println("//"); -< -clearly contains no real comment delimiters. - -To distinguish between ``real'' comment delimiters and ``fake'' ones we use a -set of heuristics. For example, one such heuristic states that any comment -delimiter that has an odd number of non-escaped " characters both preceding -and following it on the line is not a comment because it is probably part of a -string. These heuristics, while usually pretty accurate, will not work for all -cases. - ------------------------------------------------------------------------------- -5.2 Nesting issues *NERDComNesting* - -If we have some line of code like this: > - /*int foo */ = /*5 + 9;*/ -< -This will not be uncommented legally. The NERD commenter will remove the -"outter most" delimiters so the line will become: > - int foo */ = /*5 + 9; -< -which almost certainly will not be what you want. Nested sets of comments will -uncomment fine though. Eg: > - /*int/* foo =*/ 5 + 9;*/ -< -will become: > - int/* foo =*/ 5 + 9; -< -(Note that in the above examples I have deliberately not used place holders -for simplicity) - -============================================================================== -6. About *NERDComAbout* - -The author of the NERD commenter is Martyzillatron --- the half robot, half -dinosaur bastard son of Megatron and Godzilla. He enjoys destroying -metropolises and eating tourist busses. - -Drop him a line at martin_grenfell at msn.com. He would love to hear from you. -its a lonely life being the worlds premier terror machine. How would you feel -if your face looked like a toaster and a t-rex put together? :( - -The latest stable versions can be found at - http://www.vim.org/scripts/script.php?script_id=1218 - -The latest dev versions are on github - http://github.com/scrooloose/nerdcommenter - -============================================================================== -8. Changelog *NERDComChangelog* - -2.2.2 - - remove the NERDShutup option and the message is suppresses, this makes - the plugin silently rely on &commentstring for unknown filetypes. - - add support for dhcpd, limits, ntp, resolv, rgb, sysctl, udevconf and - udevrules. Thanks to Thilo Six. - - match filetypes case insensitively - - add support for mp (metapost), thanks to Andrey Skvortsov. - - add support for htmlcheetah, thanks to Simon Hengel. - - add support for javacc, thanks to Matt Tolton. - - make <%# %> the default delims for eruby, thanks to tpope. - - add support for javascript.jquery, thanks to Ivan Devat. - - add support for cucumber and pdf. Fix sass and railslog delims, - thanks to tpope - -2.2.1 - - add support for newlisp and clojure, thanks to Matthew Lee Hinman. - - fix automake comments, thanks to Elias Pipping - - make haml comments default to -# with / as the alternative delimiter, - thanks to tpope - - add support for actionscript and processing thanks to Edwin Benavides - - add support for ps1 (powershell), thanks to Jason Mills - - add support for hostsaccess, thanks to Thomas Rowe - - add support for CVScommit - - add support for asciidoc, git and gitrebase. Thanks to Simon Ruderich. - - use # for gitcommit comments, thanks to Simon Ruderich. - - add support for mako and genshi, thanks to Keitheis. - - add support for conkyrc, thanks to David - - add support for SVNannotate, thanks to Miguel Jaque Barbero. - - add support for sieve, thanks to Stefan Walk - - add support for objj, thanks to Adam Thorsen. - -2.2.0 - - rewrote the mappings system to be more "standard". - - removed all the mapping options. Now, mappings to mappings are - used - - see :help NERDComMappings, and :help NERDCreateDefaultMappings for - more info - - remove "prepend comments" and "right aligned comments". - - add support for applescript, calbire, man, SVNcommit, potwiki, txt2tags and SVNinfo. - Thanks to nicothakis, timberke, sgronblo, mntnoe, Bernhard Grotz, John - O'Shea, François and Giacomo Mariani respectively. - - bugfix for haskell delimiters. Thanks to mntnoe. -2.1.18 - - add support for llvm. Thanks to nicothakis. - - add support for xquery. Thanks to Phillip Kovalev. -2.1.17 - - fixed haskell delimiters (hackily). Thanks to Elias Pipping. - - add support for mailcap. Thanks to Pascal Brueckner. - - add support for stata. Thanks to Jerónimo Carballo. - - applied a patch from ewfalor to fix an error in the help file with the - NERDMapleader doc - - disable the insert mode ctrl-c mapping by default, see :help - NERDComInsertComment if you wish to restore it - -============================================================================== -8. Credits *NERDComCredits* - -Thanks to the follow people for suggestions and patches: - -Nick Brettell -Matthew Hawkins -Mathieu Clabaut -Greg Searle -Nguyen -Litchi -Jorge Scandaliaris -Shufeng Zheng -Martin Stubenschrott -Markus Erlmann -Brent Rice -Richard Willis -Igor Prischepoff -Harry -David Bourgeois -Eike Von Seggern -Torsten Blix -Alexander Bosecke -Stefano Zacchiroli -Norick Chen -Joseph Barker -Gary Church -Tim Carey-Smith -Markus Klinik -Anders -Seth Mason -James Hales -Heptite -Cheng Fang -Yongwei Wu -David Miani -Jeremy Hinegardner -Marco -Ingo Karkat -Zhang Shuhan -tpope -Ben Schmidt -David Fishburn -Erik Falor -JaGoTerr -Elias Pipping -mntnoe -Mark S. - - -Thanks to the following people for sending me new filetypes to support: - -The hackers The filetypes~ -Sam R verilog -Jonathan Derque context, plaintext and mail -Vigil fetchmail -Michael Brunner kconfig -Antono Vasiljev netdict -Melissa Reid omlet -Ilia N Ternovich quickfix -John O'Shea RTF, SVNcommitlog and vcscommit, SVNCommit -Anders occam -Mark Woodward csv -fREW gentoo-package-mask, - gentoo-package-keywords, - gentoo-package-use, and vo_base -Alexey verilog_systemverilog, systemverilog -Lizendir fstab -Michael Böhler autoit, autohotkey and docbk -Aaron Small cmake -Ramiro htmldjango and django -Stefano Zacchiroli debcontrol, debchangelog, mkd -Alex Tarkovsky ebuild and eclass -Jorge Rodrigues gams -Rainer Müller Objective C -Jason Mills Groovy, ps1 -Normandie Azucena vera -Florian Apolloner ldif -David Fishburn lookupfile -Niels Aan de Brugh rst -Don Hatlestad ahk -Christophe Benz Desktop and xsd -Eyolf Østrem lilypond, bbx and lytex -Ingo Karkat dosbatch -Nicolas Weber markdown, objcpp -tinoucas gentoo-conf-d -Greg Weber D, haml -Bruce Sherrod velocity -timberke cobol, calibre -Aaron Schaefer factor -Mr X asterisk, mplayerconf -Kuchma Michael plsql -Brett Warneke spectre -Pipp lhaskell -Renald Buter scala -Vladimir Lomov asymptote -Marco mrxvtrc, aap -nicothakis SVNAnnotate, CVSAnnotate, SVKAnnotate, - SVNdiff, gitAnnotate, gitdiff, dtrace - llvm, applescript -Chen Xing Wikipedia -Jacobo Diaz dakota, patran -Li Jin gentoo-env-d, gentoo-init-d, - gentoo-make-conf, grub, modconf, sudoers -SpookeyPeanut rib -Greg Jandl pyrex/cython -Christophe Benz services, gitcommit -A Pontus vimperator -Stromnov slice, bzr -Martin Kustermann pamconf -Indriði Einarsson mason -Chris map -Krzysztof A. Adamski group -Pascal Brueckner mailcap -Jerónimo Carballo stata -Phillip Kovalev xquery -Bernhard Grotz potwiki -sgronblo man -François txt2tags -Giacomo Mariani SVNinfo -Matthew Lee Hinman newlisp, clojure -Elias Pipping automake -Edwin Benavides actionscript, processing -Thomas Rowe hostsaccess -Simon Ruderich asciidoc, git, gitcommit, gitrebase -Keitheis mako, genshi -David conkyrc -Miguel Jaque Barbero SVNannotate -Stefan Walk sieve -Adam Thorsen objj -Thilo Six dhcpd, limits, ntp, resolv, rgb, sysctl, - udevconf, udevrules -Andrey Skvortsov mp -Simon Hengel htmlcheetah -Matt Tolton javacc -Ivan Devat javascript.jquery -tpope cucumber,pdf -============================================================================== -9. License *NERDComLicense* - -The NERD commenter is released under the wtfpl. -See http://sam.zoy.org/wtfpl/COPYING. diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdcommenter/plugin/NERD_commenter.vim --- 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 -" 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('','') - 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 NERDCommenterAltDelims :call SwitchToAlternativeDelimiters(1) - -" comment out lines -nnoremap NERDCommenterComment :call NERDComment(0, "norm") -vnoremap NERDCommenterComment :call NERDComment(1, "norm") - -" toggle comments -nnoremap NERDCommenterToggle :call NERDComment(0, "toggle") -vnoremap NERDCommenterToggle :call NERDComment(1, "toggle") - -" minimal comments -nnoremap NERDCommenterMinimal :call NERDComment(0, "minimal") -vnoremap NERDCommenterMinimal :call NERDComment(1, "minimal") - -" sexy comments -nnoremap NERDCommenterSexy :call NERDComment(0, "sexy") -vnoremap NERDCommenterSexy :call NERDComment(1, "sexy") - -" invert comments -nnoremap NERDCommenterInvert :call NERDComment(0, "invert") -vnoremap NERDCommenterInvert :call NERDComment(1, "invert") - -" yank then comment -nmap NERDCommenterYank :call NERDComment(0, "yank") -vmap NERDCommenterYank :call NERDComment(1, "yank") - -" left aligned comments -nnoremap NERDCommenterAlignLeft :call NERDComment(0, "alignLeft") -vnoremap NERDCommenterAlignLeft :call NERDComment(1, "alignLeft") - -" left and right aligned comments -nnoremap NERDCommenterAlignBoth :call NERDComment(0, "alignBoth") -vnoremap NERDCommenterAlignBoth :call NERDComment(1, "alignBoth") - -" nested comments -nnoremap NERDCommenterNest :call NERDComment(0, "nested") -vnoremap NERDCommenterNest :call NERDComment(1, "nested") - -" uncomment -nnoremap NERDCommenterUncomment :call NERDComment(0, "uncomment") -vnoremap NERDCommenterUncomment :call NERDComment(1, "uncomment") - -" comment till the end of the line -nnoremap NERDCommenterToEOL :call NERDComment(0, "toEOL") - -" append comments -nmap NERDCommenterAppend :call NERDComment(0, "append") - -" insert comments -inoremap NERDCommenterInInsert :call NERDComment(0, "insert") - - -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('NERDCommenterComment', ',cc') - call s:CreateMaps('NERDCommenterToggle', ',c') - call s:CreateMaps('NERDCommenterMinimal', ',cm') - call s:CreateMaps('NERDCommenterSexy', ',cs') - call s:CreateMaps('NERDCommenterInvert', ',ci') - call s:CreateMaps('NERDCommenterYank', ',cy') - call s:CreateMaps('NERDCommenterAlignLeft', ',cl') - call s:CreateMaps('NERDCommenterAlignBoth', ',cb') - call s:CreateMaps('NERDCommenterNest', ',cn') - call s:CreateMaps('NERDCommenterUncomment', ',cu') - call s:CreateMaps('NERDCommenterToEOL', ',c$') - call s:CreateMaps('NERDCommenterAppend', ',cA') - - if !hasmapto('NERDCommenterAltDelims', 'n') - nmap ,ca 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 ' . a:root . '.' . a:desc . ' ' . a:target - exec 'vmenu ' . a:root . '.' . a:desc . ' ' . a:target - endfunction - call s:CreateMenuItems("NERDCommenterComment", 'Comment', menuRoot) - call s:CreateMenuItems("NERDCommenterToggle", 'Toggle', menuRoot) - call s:CreateMenuItems('NERDCommenterMinimal', 'Minimal', menuRoot) - call s:CreateMenuItems('NERDCommenterNest', 'Nested', menuRoot) - exec 'nmenu '. menuRoot .'.To\ EOL NERDCommenterToEOL' - call s:CreateMenuItems('NERDCommenterInvert', 'Invert', menuRoot) - call s:CreateMenuItems('NERDCommenterSexy', 'Sexy', menuRoot) - call s:CreateMenuItems('NERDCommenterYank', 'Yank\ then\ comment', menuRoot) - exec 'nmenu '. menuRoot .'.Append NERDCommenterAppend' - exec 'menu '. menuRoot .'.-Sep- :' - call s:CreateMenuItems('NERDCommenterAlignLeft', 'Left\ aligned', menuRoot) - call s:CreateMenuItems('NERDCommenterAlignBoth', 'Left\ and\ right\ aligned', menuRoot) - exec 'menu '. menuRoot .'.-Sep2- :' - call s:CreateMenuItems('NERDCommenterUncomment', 'Uncomment', menuRoot) - exec 'nmenu '. menuRoot .'.Switch\ Delimiters NERDCommenterAltDelims' - exec 'imenu '. menuRoot .'.Insert\ Comment\ Here NERDCommenterInInsert' - exec 'menu '. menuRoot .'.-Sep3- :' - exec 'menu '. menuRoot .'.Help :help NERDCommenterContents' -endif -" vim: set foldmethod=marker : diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/.gitignore --- a/vim/bundle/nerdtree/.gitignore Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -*~ -*.swp -tags diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/Rakefile --- a/vim/bundle/nerdtree/Rakefile Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -# written by travis jeffery -# contributions by scrooloose - -require 'rake' -require 'find' -require 'pathname' - -IGNORE = [/\.gitignore$/, /Rakefile$/] - -files = `git ls-files`.split("\n") -files.reject! { |f| IGNORE.any? { |re| f.match(re) } } - -desc 'Zip up the project files' -task :zip do - zip_name = File.basename(File.dirname(__FILE__)) - zip_name.gsub!(/ /, '_') - zip_name = "#{zip_name}.zip" - - if File.exist?(zip_name) - abort("Zip file #{zip_name} already exists. Remove it first.") - end - - puts "Creating zip file: #{zip_name}" - system("zip #{zip_name} #{files.join(" ")}") -end - -desc 'Install plugin and documentation' -task :install do - vimfiles = if ENV['VIMFILES'] - ENV['VIMFILES'] - elsif RUBY_PLATFORM =~ /(win|w)32$/ - File.expand_path("~/vimfiles") - else - File.expand_path("~/.vim") - end - files.each do |file| - target_file = File.join(vimfiles, file) - FileUtils.mkdir_p File.dirname(target_file) - FileUtils.cp file, target_file - - puts "Installed #{file} to #{target_file}" - end - -end - -desc 'Pulls from origin' -task :pull do - puts "Updating local repo..." - system("cd " << Dir.new(File.dirname(__FILE__)).path << " && git pull") -end - -desc 'Calls pull task and then install task' -task :update => ['pull', 'install'] do - puts "Update of vim script complete." -end - -desc 'Uninstall plugin and documentation' -task :uninstall do - vimfiles = if ENV['VIMFILES'] - ENV['VIMFILES'] - elsif RUBY_PLATFORM =~ /(win|w)32$/ - File.expand_path("~/vimfiles") - else - File.expand_path("~/.vim") - end - files.each do |file| - target_file = File.join(vimfiles, file) - FileUtils.rm target_file - - puts "Uninstalled #{target_file}" - end - -end - -task :default => ['update'] diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/doc/NERD_tree.txt --- a/vim/bundle/nerdtree/doc/NERD_tree.txt Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1222 +0,0 @@ -*NERD_tree.txt* A tree explorer plugin that owns your momma! - - - - omg its ... ~ - - ________ ________ _ ____________ ____ __________ ____________~ - /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~ - / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~ - / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~ - /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~ - - - Reference Manual~ - - - - -============================================================================== -CONTENTS *NERDTree-contents* - - 1.Intro...................................|NERDTree| - 2.Functionality provided..................|NERDTreeFunctionality| - 2.1.Global commands...................|NERDTreeGlobalCommands| - 2.2.Bookmarks.........................|NERDTreeBookmarks| - 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| - 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| - 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| - 2.3.NERD tree mappings................|NERDTreeMappings| - 2.4.The NERD tree menu................|NERDTreeMenu| - 3.Options.................................|NERDTreeOptions| - 3.1.Option summary....................|NERDTreeOptionSummary| - 3.2.Option details....................|NERDTreeOptionDetails| - 4.The NERD tree API.......................|NERDTreeAPI| - 4.1.Key map API.......................|NERDTreeKeymapAPI| - 4.2.Menu API..........................|NERDTreeMenuAPI| - 5.About...................................|NERDTreeAbout| - 6.Changelog...............................|NERDTreeChangelog| - 7.Credits.................................|NERDTreeCredits| - 8.License.................................|NERDTreeLicense| - -============================================================================== -1. Intro *NERDTree* - -What is this "NERD tree"?? - -The NERD tree allows you to explore your filesystem and to open files and -directories. It presents the filesystem to you in the form of a tree which you -manipulate with the keyboard and/or mouse. It also allows you to perform -simple filesystem operations. - -The following features and functionality are provided by the NERD tree: - * Files and directories are displayed in a hierarchical tree structure - * Different highlighting is provided for the following types of nodes: - * files - * directories - * sym-links - * windows .lnk files - * read-only files - * executable files - * Many (customisable) mappings are provided to manipulate the tree: - * Mappings to open/close/explore directory nodes - * Mappings to open files in new/existing windows/tabs - * Mappings to change the current root of the tree - * Mappings to navigate around the tree - * ... - * Directories and files can be bookmarked. - * Most NERD tree navigation can also be done with the mouse - * Filtering of tree content (can be toggled at runtime) - * custom file filters to prevent e.g. vim backup files being displayed - * optional displaying of hidden files (. files) - * files can be "turned off" so that only directories are displayed - * The position and size of the NERD tree window can be customised - * The order in which the nodes in the tree are listed can be customised. - * A model of your filesystem is created/maintained as you explore it. This - has several advantages: - * All filesystem information is cached and is only re-read on demand - * If you revisit a part of the tree that you left earlier in your - session, the directory nodes will be opened/closed as you left them - * The script remembers the cursor position and window position in the NERD - tree so you can toggle it off (or just close the tree window) and then - reopen it (with NERDTreeToggle) the NERD tree window will appear exactly - as you left it - * You can have a separate NERD tree for each tab, share trees across tabs, - or a mix of both. - * By default the script overrides the default file browser (netw), so if - you :edit a directory a (slighly modified) NERD tree will appear in the - current window - * A programmable menu system is provided (simulates right clicking on a - node) - * one default menu plugin is provided to perform basic filesytem - operations (create/delete/move/copy files/directories) - * There's an API for adding your own keymappings - - -============================================================================== -2. Functionality provided *NERDTreeFunctionality* - ------------------------------------------------------------------------------- -2.1. Global Commands *NERDTreeGlobalCommands* - -:NERDTree [ | ] *:NERDTree* - Opens a fresh NERD tree. The root of the tree depends on the argument - given. There are 3 cases: If no argument is given, the current directory - will be used. If a directory is given, that will be used. If a bookmark - name is given, the corresponding directory will be used. For example: > - :NERDTree /home/marty/vim7/src - :NERDTree foo (foo is the name of a bookmark) -< -:NERDTreeFromBookmark *:NERDTreeFromBookmark* - Opens a fresh NERD tree with the root initialized to the dir for - . This only reason to use this command over :NERDTree is for - the completion (which is for bookmarks rather than directories). - -:NERDTreeToggle [ | ] *:NERDTreeToggle* - If a NERD tree already exists for this tab, it is reopened and rendered - again. If no NERD tree exists for this tab then this command acts the - same as the |:NERDTree| command. - -:NERDTreeMirror *:NERDTreeMirror* - Shares an existing NERD tree, from another tab, in the current tab. - Changes made to one tree are reflected in both as they are actually the - same buffer. - - If only one other NERD tree exists, that tree is automatically mirrored. If - more than one exists, the script will ask which tree to mirror. - -:NERDTreeClose *:NERDTreeClose* - Close the NERD tree in this tab. - -:NERDTreeFind *:NERDTreeFind* - Find the current file in the tree. If no tree exists for the current tab, - or the file is not under the current root, then initialize a new tree where - the root is the directory of the current file. - ------------------------------------------------------------------------------- -2.2. Bookmarks *NERDTreeBookmarks* - -Bookmarks in the NERD tree are a way to tag files or directories of interest. -For example, you could use bookmarks to tag all of your project directories. - ------------------------------------------------------------------------------- -2.2.1. The Bookmark Table *NERDTreeBookmarkTable* - -If the bookmark table is active (see |NERDTree-B| and -|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double -click bookmarks or use the |NERDTree-o| mapping to activate them. See also, -|NERDTree-t| and |NERDTree-T| - ------------------------------------------------------------------------------- -2.2.2. Bookmark commands *NERDTreeBookmarkCommands* - -Note that the following commands are only available in the NERD tree buffer. - -:Bookmark - Bookmark the current node as . If there is already a - bookmark, it is overwritten. must not contain spaces. - -:BookmarkToRoot - Make the directory corresponding to the new root. If a treenode - corresponding to is already cached somewhere in the tree then - the current tree will be used, otherwise a fresh tree will be opened. - Note that if points to a file then its parent will be used - instead. - -:RevealBookmark - If the node is cached under the current root then it will be revealed - (i.e. directory nodes above it will be opened) and the cursor will be - placed on it. - -:OpenBookmark - must point to a file. The file is opened as though |NERDTree-o| - was applied. If the node is cached under the current root then it will be - revealed and the cursor will be placed on it. - -:ClearBookmarks [] - Remove all the given bookmarks. If no bookmarks are given then remove all - bookmarks on the current node. - -:ClearAllBookmarks - Remove all bookmarks. - -:ReadBookmarks - Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. - -See also |:NERDTree| and |:NERDTreeFromBookmark|. - ------------------------------------------------------------------------------- -2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* - -If invalid bookmarks are detected, the script will issue an error message and -the invalid bookmarks will become unavailable for use. - -These bookmarks will still be stored in the bookmarks file (see -|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line -after the valid bookmarks but before the invalid ones. - -Each line in the bookmarks file represents one bookmark. The proper format is: - - -After you have corrected any invalid bookmarks, either restart vim, or go -:ReadBookmarks from the NERD tree window. - ------------------------------------------------------------------------------- -2.3. NERD tree Mappings *NERDTreeMappings* - -Default Description~ help-tag~ -Key~ - -o.......Open files, directories and bookmarks....................|NERDTree-o| -go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| -t.......Open selected node/bookmark in a new tab.................|NERDTree-t| -T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| -i.......Open selected file in a split window.....................|NERDTree-i| -gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| -s.......Open selected file in a new vsplit.......................|NERDTree-s| -gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| -O.......Recursively open the selected directory..................|NERDTree-O| -x.......Close the current nodes parent...........................|NERDTree-x| -X.......Recursively close all children of the current node.......|NERDTree-X| -e.......Edit the current dif.....................................|NERDTree-e| - -...............same as |NERDTree-o|. -double-click.......same as the |NERDTree-o| map. -middle-click.......same as |NERDTree-i| for files, same as - |NERDTree-e| for dirs. - -D.......Delete the current bookmark .............................|NERDTree-D| - -P.......Jump to the root node....................................|NERDTree-P| -p.......Jump to current nodes parent.............................|NERDTree-p| -K.......Jump up inside directories at the current tree depth.....|NERDTree-K| -J.......Jump down inside directories at the current tree depth...|NERDTree-J| -...Jump down to the next sibling of the current directory...|NERDTree-C-J| -...Jump up to the previous sibling of the current directory.|NERDTree-C-K| - -C.......Change the tree root to the selected dir.................|NERDTree-C| -u.......Move the tree root up one directory......................|NERDTree-u| -U.......Same as 'u' except the old root node is left open........|NERDTree-U| -r.......Recursively refresh the current directory................|NERDTree-r| -R.......Recursively refresh the current root.....................|NERDTree-R| -m.......Display the NERD tree menu...............................|NERDTree-m| -cd......Change the CWD to the dir of the selected node...........|NERDTree-cd| - -I.......Toggle whether hidden files displayed....................|NERDTree-I| -f.......Toggle whether the file filters are used.................|NERDTree-f| -F.......Toggle whether files are displayed.......................|NERDTree-F| -B.......Toggle whether the bookmark table is displayed...........|NERDTree-B| - -q.......Close the NERDTree window................................|NERDTree-q| -A.......Zoom (maximize/minimize) the NERDTree window.............|NERDTree-A| -?.......Toggle the display of the quick help.....................|NERDTree-?| - ------------------------------------------------------------------------------- - *NERDTree-o* -Default key: o -Map option: NERDTreeMapActivateNode -Applies to: files and directories. - -If a file node is selected, it is opened in the previous window. - -If a directory is selected it is opened or closed depending on its current -state. - -If a bookmark that links to a directory is selected then that directory -becomes the new root. - -If a bookmark that links to a file is selected then that file is opened in the -previous window. - ------------------------------------------------------------------------------- - *NERDTree-go* -Default key: go -Map option: None -Applies to: files. - -If a file node is selected, it is opened in the previous window, but the -cursor does not move. - -The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see -|NERDTree-o|). - ------------------------------------------------------------------------------- - *NERDTree-t* -Default key: t -Map option: NERDTreeMapOpenInTab -Applies to: files and directories. - -Opens the selected file in a new tab. If a directory is selected, a fresh -NERD Tree for that directory is opened in a new tab. - -If a bookmark which points to a directory is selected, open a NERD tree for -that directory in a new tab. If the bookmark points to a file, open that file -in a new tab. - ------------------------------------------------------------------------------- - *NERDTree-T* -Default key: T -Map option: NERDTreeMapOpenInTabSilent -Applies to: files and directories. - -The same as |NERDTree-t| except that the focus is kept in the current tab. - ------------------------------------------------------------------------------- - *NERDTree-i* -Default key: i -Map option: NERDTreeMapOpenSplit -Applies to: files. - -Opens the selected file in a new split window and puts the cursor in the new -window. - ------------------------------------------------------------------------------- - *NERDTree-gi* -Default key: gi -Map option: None -Applies to: files. - -The same as |NERDTree-i| except that the cursor is not moved. - -The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see -|NERDTree-i|). - ------------------------------------------------------------------------------- - *NERDTree-s* -Default key: s -Map option: NERDTreeMapOpenVSplit -Applies to: files. - -Opens the selected file in a new vertically split window and puts the cursor in -the new window. - ------------------------------------------------------------------------------- - *NERDTree-gs* -Default key: gs -Map option: None -Applies to: files. - -The same as |NERDTree-s| except that the cursor is not moved. - -The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see -|NERDTree-s|). - ------------------------------------------------------------------------------- - *NERDTree-O* -Default key: O -Map option: NERDTreeMapOpenRecursively -Applies to: directories. - -Recursively opens the selelected directory. - -All files and directories are cached, but if a directory would not be -displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the -hidden file filter (see |'NERDTreeShowHidden'|) then its contents are not -cached. This is handy, especially if you have .svn directories. - ------------------------------------------------------------------------------- - *NERDTree-x* -Default key: x -Map option: NERDTreeMapCloseDir -Applies to: files and directories. - -Closes the parent of the selected node. - ------------------------------------------------------------------------------- - *NERDTree-X* -Default key: X -Map option: NERDTreeMapCloseChildren -Applies to: directories. - -Recursively closes all children of the selected directory. - -Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. - ------------------------------------------------------------------------------- - *NERDTree-e* -Default key: e -Map option: NERDTreeMapOpenExpl -Applies to: files and directories. - -|:edit|s the selected directory, or the selected file's directory. This could -result in a NERD tree or a netrw being opened, depending on -|'NERDTreeHijackNetrw'|. - ------------------------------------------------------------------------------- - *NERDTree-D* -Default key: D -Map option: NERDTreeMapDeleteBookmark -Applies to: lines in the bookmarks table - -Deletes the currently selected bookmark. - ------------------------------------------------------------------------------- - *NERDTree-P* -Default key: P -Map option: NERDTreeMapJumpRoot -Applies to: no restrictions. - -Jump to the tree root. - ------------------------------------------------------------------------------- - *NERDTree-p* -Default key: p -Map option: NERDTreeMapJumpParent -Applies to: files and directories. - -Jump to the parent node of the selected node. - ------------------------------------------------------------------------------- - *NERDTree-K* -Default key: K -Map option: NERDTreeMapJumpFirstChild -Applies to: files and directories. - -Jump to the first child of the current nodes parent. - -If the cursor is already on the first node then do the following: - * loop back thru the siblings of the current nodes parent until we find an - open dir with children - * go to the first child of that node - ------------------------------------------------------------------------------- - *NERDTree-J* -Default key: J -Map option: NERDTreeMapJumpLastChild -Applies to: files and directories. - -Jump to the last child of the current nodes parent. - -If the cursor is already on the last node then do the following: - * loop forward thru the siblings of the current nodes parent until we find - an open dir with children - * go to the last child of that node - ------------------------------------------------------------------------------- - *NERDTree-C-J* -Default key: -Map option: NERDTreeMapJumpNextSibling -Applies to: files and directories. - -Jump to the next sibling of the selected node. - ------------------------------------------------------------------------------- - *NERDTree-C-K* -Default key: -Map option: NERDTreeMapJumpPrevSibling -Applies to: files and directories. - -Jump to the previous sibling of the selected node. - ------------------------------------------------------------------------------- - *NERDTree-C* -Default key: C -Map option: NERDTreeMapChdir -Applies to: directories. - -Make the selected directory node the new tree root. If a file is selected, its -parent is used. - ------------------------------------------------------------------------------- - *NERDTree-u* -Default key: u -Map option: NERDTreeMapUpdir -Applies to: no restrictions. - -Move the tree root up a dir (like doing a "cd .."). - ------------------------------------------------------------------------------- - *NERDTree-U* -Default key: U -Map option: NERDTreeMapUpdirKeepOpen -Applies to: no restrictions. - -Like |NERDTree-u| except that the old tree root is kept open. - ------------------------------------------------------------------------------- - *NERDTree-r* -Default key: r -Map option: NERDTreeMapRefresh -Applies to: files and directories. - -If a dir is selected, recursively refresh that dir, i.e. scan the filesystem -for changes and represent them in the tree. - -If a file node is selected then the above is done on it's parent. - ------------------------------------------------------------------------------- - *NERDTree-R* -Default key: R -Map option: NERDTreeMapRefreshRoot -Applies to: no restrictions. - -Recursively refresh the tree root. - ------------------------------------------------------------------------------- - *NERDTree-m* -Default key: m -Map option: NERDTreeMapMenu -Applies to: files and directories. - -Display the NERD tree menu. See |NERDTreeMenu| for details. - ------------------------------------------------------------------------------- - *NERDTree-cd* -Default key: cd -Map option: NERDTreeMapChdir -Applies to: files and directories. - -Change vims current working directory to that of the selected node. - ------------------------------------------------------------------------------- - *NERDTree-I* -Default key: I -Map option: NERDTreeMapToggleHidden -Applies to: no restrictions. - -Toggles whether hidden files (i.e. "dot files") are displayed. - ------------------------------------------------------------------------------- - *NERDTree-f* -Default key: f -Map option: NERDTreeMapToggleFilters -Applies to: no restrictions. - -Toggles whether file filters are used. See |'NERDTreeIgnore'| for details. - ------------------------------------------------------------------------------- - *NERDTree-F* -Default key: F -Map option: NERDTreeMapToggleFiles -Applies to: no restrictions. - -Toggles whether file nodes are displayed. - ------------------------------------------------------------------------------- - *NERDTree-B* -Default key: B -Map option: NERDTreeMapToggleBookmarks -Applies to: no restrictions. - -Toggles whether the bookmarks table is displayed. - ------------------------------------------------------------------------------- - *NERDTree-q* -Default key: q -Map option: NERDTreeMapQuit -Applies to: no restrictions. - -Closes the NERDtree window. - ------------------------------------------------------------------------------- - *NERDTree-A* -Default key: A -Map option: NERDTreeMapToggleZoom -Applies to: no restrictions. - -Maximize (zoom) and minimize the NERDtree window. - ------------------------------------------------------------------------------- - *NERDTree-?* -Default key: ? -Map option: NERDTreeMapHelp -Applies to: no restrictions. - -Toggles whether the quickhelp is displayed. - ------------------------------------------------------------------------------- -2.3. The NERD tree menu *NERDTreeMenu* - -The NERD tree has a menu that can be programmed via the an API (see -|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most -file explorers have. - -The script comes with two default menu plugins: exec_menuitem.vim and -fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for -creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a -menu item to execute executable files. - -Related tags: |NERDTree-m| |NERDTreeApi| - -============================================================================== -3. Customisation *NERDTreeOptions* - - ------------------------------------------------------------------------------- -3.1. Customisation summary *NERDTreeOptionSummary* - -The script provides the following options that can customise the behaviour the -NERD tree. These options should be set in your vimrc. - -|'loaded_nerd_tree'| Turns off the script. - -|'NERDChristmasTree'| Tells the NERD tree to make itself colourful - and pretty. - -|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers - when the cursor moves within a specified - distance to the top/bottom of the window. -|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering. - -|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case - sensitive or not when sorting nodes. - -|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change - vim's current working directory. - -|'NERDTreeHighlightCursorline'| Tell the NERD tree whether to highlight the - current cursor line. - -|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw - autocommands for exploring local directories. - -|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. - -|'NERDTreeBookmarksFile'| Where the bookmarks are stored. - -|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse - clicks. - -|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. - -|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the - bookmarks table on startup. - -|'NERDTreeShowFiles'| Tells the NERD tree whether to display files - in the tree on startup. - -|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden - files on startup. - -|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line - numbers in the tree window. - -|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in - the tree. - -|'NERDTreeStatusline'| Set a statusline for NERD tree windows. - -|'NERDTreeWinPos'| Tells the script where to put the NERD tree - window. - -|'NERDTreeWinSize'| Sets the window size when the NERD tree is - opened. - ------------------------------------------------------------------------------- -3.2. Customisation details *NERDTreeOptionDetails* - -To enable any of the below options you should put the given line in your -~/.vimrc - - *'loaded_nerd_tree'* -If this plugin is making you feel homicidal, it may be a good idea to turn it -off with this line in your vimrc: > - let loaded_nerd_tree=1 -< ------------------------------------------------------------------------------- - *'NERDChristmasTree'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1 then some extra syntax highlighting elements are -added to the nerd tree to make it more colourful. - -Set it to 0 for a more vanilla looking tree. - ------------------------------------------------------------------------------- - *'NERDTreeAutoCenter'* -Values: 0 or 1. -Default: 1 - -If set to 1, the NERD tree window will center around the cursor if it moves to -within |'NERDTreeAutoCenterThreshold'| lines of the top/bottom of the window. - -This is ONLY done in response to tree navigation mappings, -i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| -|NERDTree-P| - -The centering is done with a |zz| operation. - ------------------------------------------------------------------------------- - *'NERDTreeAutoCenterThreshold'* -Values: Any natural number. -Default: 3 - -This option controls the "sensitivity" of the NERD tree auto centering. See -|'NERDTreeAutoCenter'| for details. - ------------------------------------------------------------------------------- - *'NERDTreeCaseSensitiveSort'* -Values: 0 or 1. -Default: 0. - -By default the NERD tree does not sort nodes case sensitively, i.e. nodes -could appear like this: > - bar.c - Baz.c - blarg.c - boner.c - Foo.c -< -But, if you set this option to 1 then the case of the nodes will be taken into -account. The above nodes would then be sorted like this: > - Baz.c - Foo.c - bar.c - blarg.c - boner.c -< ------------------------------------------------------------------------------- - *'NERDTreeChDirMode'* - -Values: 0, 1 or 2. -Default: 0. - -Use this option to tell the script when (if at all) to change the current -working directory (CWD) for vim. - -If it is set to 0 then the CWD is never changed by the NERD tree. - -If set to 1 then the CWD is changed when the NERD tree is first loaded to the -directory it is initialized in. For example, if you start the NERD tree with > - :NERDTree /home/marty/foobar -< -then the CWD will be changed to /home/marty/foobar and will not be changed -again unless you init another NERD tree with a similar command. - -If the option is set to 2 then it behaves the same as if set to 1 except that -the CWD is changed whenever the tree root is changed. For example, if the CWD -is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new -root then the CWD will become /home/marty/foobar/baz. - ------------------------------------------------------------------------------- - *'NERDTreeHighlightCursorline'* -Values: 0 or 1. -Default: 1. - -If set to 1, the current cursor line in the NERD tree buffer will be -highlighted. This is done using the |'cursorline'| option. - ------------------------------------------------------------------------------- - *'NERDTreeHijackNetrw'* -Values: 0 or 1. -Default: 1. - -If set to 1, doing a > - :edit -< -will open up a "secondary" NERD tree instead of a netrw in the target window. - -Secondary NERD trees behaves slighly different from a regular trees in the -following respects: - 1. 'o' will open the selected file in the same window as the tree, - replacing it. - 2. you can have as many secondary tree as you want in the same tab. - ------------------------------------------------------------------------------- - *'NERDTreeIgnore'* -Values: a list of regular expressions. -Default: ['\~$']. - -This option is used to specify which files the NERD tree should ignore. It -must be a list of regular expressions. When the NERD tree is rendered, any -files/dirs that match any of the regex's in 'NERDTreeIgnore' wont be -displayed. - -For example if you put the following line in your vimrc: > - let NERDTreeIgnore=['\.vim$', '\~$'] -< -then all files ending in .vim or ~ will be ignored. - -Note: to tell the NERD tree not to ignore any files you must use the following -line: > - let NERDTreeIgnore=[] -< - -The file filters can be turned on and off dynamically with the |NERDTree-f| -mapping. - ------------------------------------------------------------------------------- - *'NERDTreeBookmarksFile'* -Values: a path -Default: $HOME/.NERDTreeBookmarks - -This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. - ------------------------------------------------------------------------------- - *'NERDTreeMouseMode'* -Values: 1, 2 or 3. -Default: 1. - -If set to 1 then a double click on a node is required to open it. -If set to 2 then a single click will open directory nodes, while a double -click will still be required for file nodes. -If set to 3 then a single click will open any node. - -Note: a double click anywhere on a line that a tree node is on will -activate it, but all single-click activations must be done on name of the node -itself. For example, if you have the following node: > - | | |-application.rb -< -then (to single click activate it) you must click somewhere in -'application.rb'. - ------------------------------------------------------------------------------- - *'NERDTreeQuitOnOpen'* - -Values: 0 or 1. -Default: 0 - -If set to 1, the NERD tree window will close after opening a file with the -|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. - ------------------------------------------------------------------------------- - *'NERDTreeShowBookmarks'* -Values: 0 or 1. -Default: 0. - -If this option is set to 1 then the bookmarks table will be displayed. - -This option can be toggled dynamically, per tree, with the |NERDTree-B| -mapping. - ------------------------------------------------------------------------------- - *'NERDTreeShowFiles'* -Values: 0 or 1. -Default: 1. - -If this option is set to 1 then files are displayed in the NERD tree. If it is -set to 0 then only directories are displayed. - -This option can be toggled dynamically, per tree, with the |NERDTree-F| -mapping and is useful for drastically shrinking the tree when you are -navigating to a different part of the tree. - ------------------------------------------------------------------------------- - *'NERDTreeShowHidden'* -Values: 0 or 1. -Default: 0. - -This option tells vim whether to display hidden files by default. This option -can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one -of the follow lines to set this option: > - let NERDTreeShowHidden=0 - let NERDTreeShowHidden=1 -< - ------------------------------------------------------------------------------- - *'NERDTreeShowLineNumbers'* -Values: 0 or 1. -Default: 0. - -This option tells vim whether to display line numbers for the NERD tree -window. Use one of the follow lines to set this option: > - let NERDTreeShowLineNumbers=0 - let NERDTreeShowLineNumbers=1 -< - ------------------------------------------------------------------------------- - *'NERDTreeSortOrder'* -Values: a list of regular expressions. -Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] - -This option is set to a list of regular expressions which are used to -specify the order of nodes under their parent. - -For example, if the option is set to: > - ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] -< -then all .vim files will be placed at the top, followed by all .c files then -all .h files. All files containing the string 'foobar' will be placed at the -end. The star is a special flag: it tells the script that every node that -doesnt match any of the other regexps should be placed here. - -If no star is present in 'NERDTreeSortOrder' then one is automatically -appended to the array. - -The regex '\/$' should be used to match directory nodes. - -After this sorting is done, the files in each group are sorted alphabetically. - -Other examples: > - (1) ['*', '\/$'] - (2) [] - (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] -< -1. Directories will appear last, everything else will appear above. -2. Everything will simply appear in alphabetical order. -3. Dirs will appear first, then ruby and php. Swap files, bak files and vim - backup files will appear last with everything else preceding them. - ------------------------------------------------------------------------------- - *'NERDTreeStatusline'* -Values: Any valid statusline setting. -Default: %{b:NERDTreeRoot.path.strForOS(0)} - -Tells the script what to use as the |'statusline'| setting for NERD tree -windows. - -Note that the statusline is set using |:let-&| not |:set| so escaping spaces -isn't necessary. - -Setting this option to -1 will will deactivate it so that your global -statusline setting is used instead. - ------------------------------------------------------------------------------- - *'NERDTreeWinPos'* -Values: "left" or "right" -Default: "left". - -This option is used to determine where NERD tree window is placed on the -screen. - -This option makes it possible to use two different explorer plugins -simultaneously. For example, you could have the taglist plugin on the left of -the window and the NERD tree on the right. - ------------------------------------------------------------------------------- - *'NERDTreeWinSize'* -Values: a positive integer. -Default: 31. - -This option is used to change the size of the NERD tree when it is loaded. - -============================================================================== -4. The NERD tree API *NERDTreeAPI* - -The NERD tree script allows you to add custom key mappings and menu items via -a set of API calls. Any scripts that use this API should be placed in -~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). - -The script exposes some prototype objects that can be used to manipulate the -tree and/or get information from it: > - g:NERDTreePath - g:NERDTreeDirNode - g:NERDTreeFileNode - g:NERDTreeBookmark -< -See the code/comments in NERD_tree.vim to find how to use these objects. The -following code conventions are used: - * class members start with a capital letter - * instance members start with a lower case letter - * private members start with an underscore - -See this blog post for more details: - http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html - ------------------------------------------------------------------------------- -4.1. Key map API *NERDTreeKeymapAPI* - -NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* - Adds a new keymapping for all NERD tree buffers. - {options} must be a dictionary, and must contain the following keys: - "key" - the trigger key for the new mapping - "callback" - the function the new mapping will be bound to - "quickhelpText" - the text that will appear in the quickhelp (see - |NERDTree-?|) - - Example: > - call NERDTreeAddKeyMap({ - \ 'key': 'b', - \ 'callback': 'NERDTreeEchoCurrentNode', - \ 'quickhelpText': 'echo full path of current node' }) - - function! NERDTreeEchoCurrentNode() - let n = g:NERDTreeFileNode.GetSelected() - if n != {} - echomsg 'Current node: ' . n.path.str() - endif - endfunction -< - This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. - It adds a (rather useless) mapping on 'b' which echos the full path to the - current node. - ------------------------------------------------------------------------------- -4.2. Menu API *NERDTreeMenuAPI* - -NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* - Creates and returns a new submenu. - - {options} must be a dictionary and must contain the following keys: - "text" - the text of the submenu that the user will see - "shortcut" - a shortcut key for the submenu (need not be unique) - - The following keys are optional: - "isActiveCallback" - a function that will be called to determine whether - this submenu item will be displayed or not. The callback function must return - 0 or 1. - "parent" - the parent submenu of the new submenu (returned from a previous - invocation of NERDTreeAddSubmenu()). If this key is left out then the new - submenu will sit under the top level menu. - - See below for an example. - -NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* - Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|). - - {options} must be a dictionary and must contain the - following keys: - "text" - the text of the menu item which the user will see - "shortcut" - a shortcut key for the menu item (need not be unique) - "callback" - the function that will be called when the user activates the - menu item. - - The following keys are optional: - "isActiveCallback" - a function that will be called to determine whether - this menu item will be displayed or not. The callback function must return - 0 or 1. - "parent" - if the menu item belongs under a submenu then this key must be - specified. This value for this key will be the object that - was returned when the submenu was created with |NERDTreeAddSubmenu()|. - - See below for an example. - -NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* - Adds a menu separator (a row of dashes). - - {options} is an optional dictionary that may contain the following keys: - "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. - -Below is an example of the menu API in action. > - call NERDTreeAddMenuSeparator() - - call NERDTreeAddMenuItem({ - \ 'text': 'a (t)op level menu item', - \ 'shortcut': 't', - \ 'callback': 'SomeFunction' }) - - let submenu = NERDTreeAddSubmenu({ - \ 'text': 'a (s)ub menu', - \ 'shortcut': 's' }) - - call NERDTreeAddMenuItem({ - \ 'text': '(n)ested item 1', - \ 'shortcut': 'n', - \ 'callback': 'SomeFunction', - \ 'parent': submenu }) - - call NERDTreeAddMenuItem({ - \ 'text': '(n)ested item 2', - \ 'shortcut': 'n', - \ 'callback': 'SomeFunction', - \ 'parent': submenu }) -< -This will create the following menu: > - -------------------- - a (t)op level menu item - a (s)ub menu -< -Where selecting "a (s)ub menu" will lead to a second menu: > - (n)ested item 1 - (n)ested item 2 -< -When any of the 3 concrete menu items are selected the function "SomeFunction" -will be called. - ------------------------------------------------------------------------------- -NERDTreeRender() *NERDTreeRender()* - Re-renders the NERD tree buffer. Useful if you change the state of the - tree and you want to it to be reflected in the UI. - -============================================================================== -5. About *NERDTreeAbout* - -The author of the NERD tree is a terrible terrible monster called Martyzilla -who gobbles up small children with milk and sugar for breakfast. - -He can be reached at martin.grenfell at gmail dot com. He would love to hear -from you, so feel free to send him suggestions and/or comments about this -plugin. Don't be shy --- the worst he can do is slaughter you and stuff you in -the fridge for later ;) - -The latest stable versions can be found at - http://www.vim.org/scripts/script.php?script_id=1658 - -The latest dev versions are on github - http://github.com/scrooloose/nerdtree - - -============================================================================== -6. Changelog *NERDTreeChangelog* - -4.1.0 - features: - - NERDTreeFind to reveal the node for the current buffer in the tree, - see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by - Doug McInnes) into the script. - - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan - Ritter and Rémi Prévost. - - truncate the root node if wider than the tree window. Thanks to Victor - Gonzalez. - - bugfixes: - - really fix window state restoring - - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, - jfilip1024, and Chris Chambers - -4.0.0 - - add a new programmable menu system (see :help NERDTreeMenu). - - add new APIs to add menus/menu-items to the menu system as well as - custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). - - removed the old API functions - - added a mapping to maximize/restore the size of nerd tree window, thanks - to Guillaume Duranceau for the patch. See :help NERDTree-A for details. - - - fix a bug where secondary nerd trees (netrw hijacked trees) and - NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. - - fix a bug where the script ignored directories whose name ended in a dot, - thanks to Aggelos Orfanakos for the patch. - - fix a bug when using the x mapping on the tree root, thanks to Bryan - Venteicher for the patch. - - fix a bug where the cursor position/window size of the nerd tree buffer - wasnt being stored on closing the window, thanks to Richard Hart. - - fix a bug where NERDTreeMirror would mirror the wrong tree - -3.1.1 - - fix a bug where a non-listed no-name buffer was getting created every - time the tree windows was created, thanks to Derek Wyatt and owen1 - - make behave the same as the 'o' mapping - - some helptag fixes in the doc, thanks strull - - fix a bug when using :set nohidden and opening a file where the previous - buf was modified. Thanks iElectric - - other minor fixes - -3.1.0 - New features: - - add mappings to open files in a vsplit, see :help NERDTree-s and :help - NERDTree-gs - - make the statusline for the nerd tree window default to something - hopefully more useful. See :help 'NERDTreeStatusline' - Bugfixes: - - make the hijack netrw functionality work when vim is started with "vim - " (thanks to Alf Mikula for the patch). - - fix a bug where the CWD wasnt being changed for some operations even when - NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) - - add -bar to all the nerd tree :commands so they can chain with other - :commands (thanks to tpope) - - fix bugs when ignorecase was set (thanks to nach) - - fix a bug with the relative path code (thanks to nach) - - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) - - -3.0.1 - Bugfixes: - - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden - was not set - - fix a bug where :NERDTree would fail if was relative and - didnt start with a ./ or ../ Thanks to James Kanze. - - make the q mapping work with secondary (:e style) trees, - thanks to jamessan - - fix a bunch of small bugs with secondary trees - - More insane refactoring. - -3.0.0 - - hijack netrw so that doing an :edit will put a NERD tree in - the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' - - allow sharing of trees across tabs, see :help :NERDTreeMirror - - remove "top" and "bottom" as valid settings for NERDTreeWinPos - - change the '' mapping to 'i' - - change the 'H' mapping to 'I' - - lots of refactoring - -============================================================================== -7. Credits *NERDTreeCredits* - -Thanks to the following people for testing, bug reports, ideas etc. Without -you I probably would have got bored of the hacking the NERD tree and -just downloaded pr0n instead. - - Tim Carey-Smith (halorgium) - Vigil - Nick Brettell - Thomas Scott Urban - Terrance Cohen - Yegappan Lakshmanan - Jason Mills - Michael Geddes (frogonwheels) - Yu Jun - Michael Madsen - AOYAMA Shotaro - Zhang Weiwu - Niels Aan de Brugh - Olivier Yiptong - Zhang Shuhan - Cory Echols - Piotr Czachur - Yuan Jiang - Matan Nassau - Maxim Kim - Charlton Wang - Matt Wozniski (godlygeek) - knekk - Sean Chou - Ryan Penn - Simon Peter Nicholls - Michael Foobar - Tomasz Chomiuk - Denis Pokataev - Tim Pope (tpope) - James Kanze - James Vega (jamessan) - Frederic Chanal (nach) - Alf Mikula - Lucas S. Buchala - Curtis Harvey - Guillaume Duranceau - Richard Hart (hates) - Doug McInnes - Stefan Ritter - Rémi Prévost - Victor Gonzalez - Stephan Baumeister - Ricky - jfilip1024 - Chris Chambers - -============================================================================== -8. License *NERDTreeLicense* - -The NERD tree is released under the wtfpl. -See http://sam.zoy.org/wtfpl/COPYING. diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim --- a/vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -" ============================================================================ -" File: exec_menuitem.vim -" Description: plugin for NERD Tree that provides an execute file menu item -" Maintainer: Martin Grenfell -" Last Change: 22 July, 2009 -" License: This program is free software. It comes without any warranty, -" to the extent permitted by applicable law. You can redistribute -" it and/or modify it under the terms of the Do What The Fuck You -" Want To Public License, Version 2, as published by Sam Hocevar. -" See http://sam.zoy.org/wtfpl/COPYING for more details. -" -" ============================================================================ -if exists("g:loaded_nerdtree_exec_menuitem") - finish -endif -let g:loaded_nerdtree_exec_menuitem = 1 - -call NERDTreeAddMenuItem({ - \ 'text': '(!)Execute file', - \ 'shortcut': '!', - \ 'callback': 'NERDTreeExecFile', - \ 'isActiveCallback': 'NERDTreeExecFileActive' }) - -function! NERDTreeExecFileActive() - let node = g:NERDTreeFileNode.GetSelected() - return !node.path.isDirectory && node.path.isExecutable -endfunction - -function! NERDTreeExecFile() - let treenode = g:NERDTreeFileNode.GetSelected() - echo "==========================================================\n" - echo "Complete the command to execute (add arguments etc):\n" - let cmd = treenode.path.str({'escape': 1}) - let cmd = input(':!', cmd . ' ') - - if cmd != '' - exec ':!' . cmd - else - echo "Aborted" - endif -endfunction diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim --- a/vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim Mon Nov 22 14:44:00 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -" ============================================================================ -" File: fs_menu.vim -" Description: plugin for the NERD Tree that provides a file system menu -" Maintainer: Martin Grenfell -" Last Change: 17 July, 2009 -" License: This program is free software. It comes without any warranty, -" to the extent permitted by applicable law. You can redistribute -" it and/or modify it under the terms of the Do What The Fuck You -" Want To Public License, Version 2, as published by Sam Hocevar. -" See http://sam.zoy.org/wtfpl/COPYING for more details. -" -" ============================================================================ -if exists("g:loaded_nerdtree_fs_menu") - finish -endif -let g:loaded_nerdtree_fs_menu = 1 - -call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) -call NERDTreeAddMenuItem({'text': '(m)ove the curent node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) -call NERDTreeAddMenuItem({'text': '(d)elete the curent node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) -if g:NERDTreePath.CopyingSupported() - call NERDTreeAddMenuItem({'text': '(c)copy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'}) -endif - -"FUNCTION: s:echo(msg){{{1 -function! s:echo(msg) - redraw - echomsg "NERDTree: " . a:msg -endfunction - -"FUNCTION: s:echoWarning(msg){{{1 -function! s:echoWarning(msg) - echohl warningmsg - call s:echo(a:msg) - echohl normal -endfunction - -"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1 -"prints out the given msg and, if the user responds by pushing 'y' then the -"buffer with the given bufnum is deleted -" -"Args: -"bufnum: the buffer that may be deleted -"msg: a message that will be echoed to the user asking them if they wish to -" del the buffer -function! s:promptToDelBuffer(bufnum, msg) - echo a:msg - if nr2char(getchar()) ==# 'y' - exec "silent bdelete! " . a:bufnum - endif -endfunction - -"FUNCTION: NERDTreeAddNode(){{{1 -function! NERDTreeAddNode() - let curDirNode = g:NERDTreeDirNode.GetSelected() - - let newNodeName = input("Add a childnode\n". - \ "==========================================================\n". - \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . - \ "", curDirNode.path.str({'format': 'Glob'}) . g:NERDTreePath.Slash()) - - if newNodeName ==# '' - call s:echo("Node Creation Aborted.") - return - endif - - try - let newPath = g:NERDTreePath.Create(newNodeName) - let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) - - let newTreeNode = g:NERDTreeFileNode.New(newPath) - if parentNode.isOpen || !empty(parentNode.children) - call parentNode.addChild(newTreeNode, 1) - call NERDTreeRender() - call newTreeNode.putCursorHere(1, 0) - endif - catch /^NERDTree/ - call s:echoWarning("Node Not Created.") - endtry -endfunction - -"FUNCTION: NERDTreeMoveNode(){{{1 -function! NERDTreeMoveNode() - let curNode = g:NERDTreeFileNode.GetSelected() - let newNodePath = input("Rename the current node\n" . - \ "==========================================================\n" . - \ "Enter the new path for the node: \n" . - \ "", curNode.path.str()) - - if newNodePath ==# '' - call s:echo("Node Renaming Aborted.") - return - endif - - try - let bufnum = bufnr(curNode.path.str()) - - call curNode.rename(newNodePath) - call NERDTreeRender() - - "if the node is open in a buffer, ask the user if they want to - "close that buffer - if bufnum != -1 - let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" - call s:promptToDelBuffer(bufnum, prompt) - endif - - call curNode.putCursorHere(1, 0) - - redraw - catch /^NERDTree/ - call s:echoWarning("Node Not Renamed.") - endtry -endfunction - -" FUNCTION: NERDTreeDeleteNode() {{{1 -function! NERDTreeDeleteNode() - let currentNode = g:NERDTreeFileNode.GetSelected() - let confirmed = 0 - - if currentNode.path.isDirectory - let choice =input("Delete the current node\n" . - \ "==========================================================\n" . - \ "STOP! To delete this entire directory, type 'yes'\n" . - \ "" . currentNode.path.str() . ": ") - let confirmed = choice ==# 'yes' - else - echo "Delete the current node\n" . - \ "==========================================================\n". - \ "Are you sure you wish to delete the node:\n" . - \ "" . currentNode.path.str() . " (yN):" - let choice = nr2char(getchar()) - let confirmed = choice ==# 'y' - endif - - - if confirmed - try - call currentNode.delete() - call NERDTreeRender() - - "if the node is open in a buffer, ask the user if they want to - "close that buffer - let bufnum = bufnr(currentNode.path.str()) - if buflisted(bufnum) - let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" - call s:promptToDelBuffer(bufnum, prompt) - endif - - redraw - catch /^NERDTree/ - call s:echoWarning("Could not remove node") - endtry - else - call s:echo("delete aborted") - endif - -endfunction - -" FUNCTION: NERDTreeCopyNode() {{{1 -function! NERDTreeCopyNode() - let currentNode = g:NERDTreeFileNode.GetSelected() - let newNodePath = input("Copy the current node\n" . - \ "==========================================================\n" . - \ "Enter the new path to copy the node to: \n" . - \ "", currentNode.path.str()) - - if newNodePath != "" - "strip trailing slash - let newNodePath = substitute(newNodePath, '\/$', '', '') - - let confirmed = 1 - if currentNode.path.copyingWillOverwrite(newNodePath) - call s:echo("Warning: copying may overwrite files! Continue? (yN)") - let choice = nr2char(getchar()) - let confirmed = choice ==# 'y' - endif - - if confirmed - try - let newNode = currentNode.copy(newNodePath) - call NERDTreeRender() - call newNode.putCursorHere(0, 0) - catch /^NERDTree/ - call s:echoWarning("Could not copy node") - endtry - endif - else - call s:echo("Copy aborted.") - endif - redraw -endfunction - -" vim: set sw=4 sts=4 et fdm=marker: diff -r df20584e0efd -r 57fb163c7556 vim/bundle/nerdtree/plugin/NERD_tree.vim --- 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 -" 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", "") -call s:initVariable("g:NERDTreeMapJumpParent", "p") -call s:initVariable("g:NERDTreeMapJumpPrevSibling", "") -call s:initVariable("g:NERDTreeMapJumpRoot", "P") -call s:initVariable("g:NERDTreeMapOpenExpl", "e") -call s:initVariable("g:NERDTreeMapOpenInTab", "t") -call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T") -call s:initVariable("g:NERDTreeMapOpenRecursively", "O") -call s:initVariable("g:NERDTreeMapOpenSplit", "i") -call s:initVariable("g:NERDTreeMapOpenVSplit", "s") -call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode) -call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit) -call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit) -call s:initVariable("g:NERDTreeMapQuit", "q") -call s:initVariable("g:NERDTreeMapRefresh", "r") -call s:initVariable("g:NERDTreeMapRefreshRoot", "R") -call s:initVariable("g:NERDTreeMapToggleBookmarks", "B") -call s:initVariable("g:NERDTreeMapToggleFiles", "F") -call s:initVariable("g:NERDTreeMapToggleFilters", "f") -call s:initVariable("g:NERDTreeMapToggleHidden", "I") -call s:initVariable("g:NERDTreeMapToggleZoom", "A") -call s:initVariable("g:NERDTreeMapUpdir", "u") -call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U") - -"SECTION: Script level variable declaration{{{2 -if s:running_windows - let s:escape_chars = " `\|\"#%&,?()\*^<>" -else - let s:escape_chars = " \\`\|\"#%&,?()\*^<>" -endif -let s:NERDTreeBufName = 'NERD_tree_' - -let s:tree_wid = 2 -let s:tree_markup_reg = '^[ `|]*[\-+~]' -let s:tree_up_dir_line = '.. (up a dir)' - -"the number to add to the nerd tree buffer name to make the buf name unique -let s:next_buffer_number = 1 - -" SECTION: Commands {{{1 -"============================================================ -"init the command that users start the nerd tree with -command! -n=? -complete=dir -bar NERDTree :call s:initNerdTree('') -command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('') -command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen() -command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('') -command! -n=0 -bar NERDTreeMirror call s:initNerdTreeMirror() -command! -n=0 -bar NERDTreeFind call s:findAndRevealPath() -" SECTION: Auto commands {{{1 -"============================================================ -augroup NERDTree - "Save the cursor position whenever we close the nerd tree - exec "autocmd BufWinLeave ". s:NERDTreeBufName ."* call saveScreenState()" - "cache bookmarks when vim loads - autocmd VimEnter * call s:Bookmark.CacheBookmarks(0) - - "load all nerdtree plugins after vim starts - autocmd VimEnter * runtime! nerdtree_plugin/**/*.vim -augroup END - -if g:NERDTreeHijackNetrw - augroup NERDTreeHijackNetrw - autocmd VimEnter * silent! autocmd! FileExplorer - au BufEnter,VimEnter * call s:checkForBrowse(expand("")) - augroup END -endif - -"SECTION: Classes {{{1 -"============================================================ -"CLASS: Bookmark {{{2 -"============================================================ -let s:Bookmark = {} -" FUNCTION: Bookmark.activate() {{{3 -function! s:Bookmark.activate() - if self.path.isDirectory - call self.toRoot() - else - if self.validate() - let n = s:TreeFileNode.New(self.path) - call n.open() - 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 ". self.key ." :call ". self.callback ."()" -endfunction - -"FUNCTION: KeyMap.Create(options) {{{3 -function! s:KeyMap.Create(options) - let newKeyMap = copy(self) - let newKeyMap.key = a:options['key'] - let newKeyMap.quickhelpText = a:options['quickhelpText'] - let newKeyMap.callback = a:options['callback'] - call add(s:KeyMap.All(), newKeyMap) -endfunction -"CLASS: MenuController {{{2 -"============================================================ -let s:MenuController = {} -"FUNCTION: MenuController.New(menuItems) {{{3 -"create a new menu controller that operates on the given menu items -function! s:MenuController.New(menuItems) - let newMenuController = copy(self) - if a:menuItems[0].isSeparator() - let newMenuController.menuItems = a:menuItems[1:-1] - else - let newMenuController.menuItems = a:menuItems - endif - return newMenuController -endfunction - -"FUNCTION: MenuController.showMenu() {{{3 -"start the main loop of the menu and get the user to choose/execute a menu -"item -function! s:MenuController.showMenu() - call self._saveOptions() - - try - let self.selection = 0 - - let done = 0 - while !done - redraw! - call self._echoPrompt() - let key = nr2char(getchar()) - let done = self._handleKeypress(key) - endwhile - finally - call self._restoreOptions() - endtry - - if self.selection != -1 - let m = self._current() - call m.execute() - endif -endfunction - -"FUNCTION: MenuController._echoPrompt() {{{3 -function! s:MenuController._echoPrompt() - echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated" - echo "==========================================================" - - for i in range(0, len(self.menuItems)-1) - if self.selection == i - echo "> " . self.menuItems[i].text - else - echo " " . self.menuItems[i].text - endif - endfor -endfunction - -"FUNCTION: MenuController._current(key) {{{3 -"get the MenuItem that is 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 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 - - 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 - - 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."\" ,\n" - if b:NERDTreeType ==# "primary" - let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n" - else - let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n" - endif - if b:NERDTreeType ==# "primary" - let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n" - endif - let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" - let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" - let @h=@h."\" middle-click,\n" - let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n" - let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n" - let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n" - let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n" - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Directory node mappings~\n" - let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n" - let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n" - let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n" - let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n" - let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n" - let @h=@h."\" current node recursively\n" - let @h=@h."\" middle-click,\n" - let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n" - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Bookmark table mappings~\n" - let @h=@h."\" double-click,\n" - let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n" - let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" - let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" - let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n" - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Tree navigation mappings~\n" - let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n" - let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n" - let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n" - let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n" - let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n" - let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n" - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Filesystem mappings~\n" - let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n" - let @h=@h."\" selected dir\n" - let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n" - let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n" - let @h=@h."\" but leave old root open\n" - let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n" - let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n" - let @h=@h."\" ". g:NERDTreeMapMenu .": Show menu\n" - let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n" - let @h=@h."\" selected dir\n" - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Tree filtering mappings~\n" - let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n" - let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n" - let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n" - let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n" - - "add quickhelp entries for each custom key map - if len(s:KeyMap.All()) - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Custom mappings~\n" - for i in s:KeyMap.All() - let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n" - endfor - endif - - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Other mappings~\n" - let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n" - let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n" - let @h=@h."\" the NERDTree window\n" - let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n" - let @h=@h."\"\n\" ----------------------------\n" - let @h=@h."\" Bookmark commands~\n" - let @h=@h."\" :Bookmark \n" - let @h=@h."\" :BookmarkToRoot \n" - let @h=@h."\" :RevealBookmark \n" - let @h=@h."\" :OpenBookmark \n" - let @h=@h."\" :ClearBookmarks []\n" - let @h=@h."\" :ClearAllBookmarks\n" - 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 :call handleMiddleMouse() - nnoremap :call checkForActivate() - nnoremap <2-leftmouse> :call activateNode(0) - - exec "nnoremap ". g:NERDTreeMapActivateNode . " :call activateNode(0)" - exec "nnoremap ". g:NERDTreeMapOpenSplit ." :call openEntrySplit(0,0)" - exec "nnoremap :call activateNode(0)" - - exec "nnoremap ". g:NERDTreeMapPreview ." :call previewNode(0)" - exec "nnoremap ". g:NERDTreeMapPreviewSplit ." :call previewNode(1)" - - exec "nnoremap ". g:NERDTreeMapOpenVSplit ." :call openEntrySplit(1,0)" - exec "nnoremap ". g:NERDTreeMapPreviewVSplit ." :call previewNode(2)" - - exec "nnoremap ". g:NERDTreeMapOpenRecursively ." :call openNodeRecursively()" - - exec "nnoremap ". g:NERDTreeMapUpdirKeepOpen ." :call upDir(1)" - exec "nnoremap ". g:NERDTreeMapUpdir ." :call upDir(0)" - exec "nnoremap ". g:NERDTreeMapChangeRoot ." :call chRoot()" - - exec "nnoremap ". g:NERDTreeMapChdir ." :call chCwd()" - - exec "nnoremap ". g:NERDTreeMapQuit ." :call closeTreeWindow()" - - exec "nnoremap ". g:NERDTreeMapRefreshRoot ." :call refreshRoot()" - exec "nnoremap ". g:NERDTreeMapRefresh ." :call refreshCurrent()" - - exec "nnoremap ". g:NERDTreeMapHelp ." :call displayHelp()" - exec "nnoremap ". g:NERDTreeMapToggleZoom ." :call toggleZoom()" - exec "nnoremap ". g:NERDTreeMapToggleHidden ." :call toggleShowHidden()" - exec "nnoremap ". g:NERDTreeMapToggleFilters ." :call toggleIgnoreFilter()" - exec "nnoremap ". g:NERDTreeMapToggleFiles ." :call toggleShowFiles()" - exec "nnoremap ". g:NERDTreeMapToggleBookmarks ." :call toggleShowBookmarks()" - - exec "nnoremap ". g:NERDTreeMapCloseDir ." :call closeCurrentDir()" - exec "nnoremap ". g:NERDTreeMapCloseChildren ." :call closeChildren()" - - exec "nnoremap ". g:NERDTreeMapMenu ." :call showMenu()" - - exec "nnoremap ". g:NERDTreeMapJumpParent ." :call jumpToParent()" - exec "nnoremap ". g:NERDTreeMapJumpNextSibling ." :call jumpToSibling(1)" - exec "nnoremap ". g:NERDTreeMapJumpPrevSibling ." :call jumpToSibling(0)" - exec "nnoremap ". g:NERDTreeMapJumpFirstChild ." :call jumpToFirstChild()" - exec "nnoremap ". g:NERDTreeMapJumpLastChild ." :call jumpToLastChild()" - exec "nnoremap ". g:NERDTreeMapJumpRoot ." :call jumpToRoot()" - - exec "nnoremap ". g:NERDTreeMapOpenInTab ." :call openInNewTab(0)" - exec "nnoremap ". g:NERDTreeMapOpenInTabSilent ." :call openInNewTab(1)" - - exec "nnoremap ". g:NERDTreeMapOpenExpl ." :call openExplorer()" - - exec "nnoremap ". g:NERDTreeMapDeleteBookmark ." :call deleteBookmark()" - - "bind all the user custom maps - call s:KeyMap.BindAll() - - command! -buffer -nargs=1 Bookmark :call bookmarkNode('') - command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call revealBookmark('') - command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call openBookmark('') - command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call clearBookmarks('') - command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('') - command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() call renderView() - command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) call renderView() - command! -buffer -nargs=0 WriteBookmarks call s:Bookmark.Write() -endfunction - -" FUNCTION: s:bookmarkNode(name) {{{2 -" Associate the current node with the given name -function! s:bookmarkNode(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: