diff --git a/.vim/.VimballRecord b/.vim/.VimballRecord new file mode 100644 index 0000000..58ea232 --- /dev/null +++ b/.vim/.VimballRecord @@ -0,0 +1 @@ +rainbow_parenthsis-4.0.vba: call delete('/Users/kreitz/.vim/autoload/rainbow_parenthsis.vim')|call delete('/Users/kreitz/.vim/doc/rainbow_parenthsis.txt')|call delete('/Users/kreitz/.vim/plugin/rainbow_parenthsis.vim')|call delete('/Users/kreitz/.vim/rainbow_parenthsis_options.vim') diff --git a/.vim/.gitignore b/.vim/.gitignore new file mode 100644 index 0000000..209e0e5 --- /dev/null +++ b/.vim/.gitignore @@ -0,0 +1 @@ +bundle/autojump.vim/ \ No newline at end of file diff --git a/.vim/.netrwhist b/.vim/.netrwhist new file mode 100644 index 0000000..d327016 --- /dev/null +++ b/.vim/.netrwhist @@ -0,0 +1,3 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhist_cnt =1 +let g:netrw_dirhist_1='/Users/kreitz/repos/public/tablib' diff --git a/.vim/autojump_py b/.vim/autojump_py new file mode 100644 index 0000000..cf108fb Binary files /dev/null and b/.vim/autojump_py differ diff --git a/.vim/autoload/pathogen.vim b/.vim/autoload/pathogen.vim new file mode 100644 index 0000000..6f0a4e3 --- /dev/null +++ b/.vim/autoload/pathogen.vim @@ -0,0 +1,142 @@ +" pathogen.vim - path option manipulation +" Maintainer: Tim Pope +" Version: 1.2 + +" Install in ~/.vim/autoload (or ~\vimfiles\autoload). +" +" API is documented below. + +if exists("g:loaded_pathogen") || &cp + finish +endif +let g:loaded_pathogen = 1 + +" Split a path into a list. +function! pathogen#split(path) abort " {{{1 + if type(a:path) == type([]) | return a:path | endif + let split = split(a:path,'\\\@/ contains=TOP,level1,level2,level3,level4,level5,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level2 matchgroup=level2c start=// contains=TOP,level2,level3,level4,level5,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level3 matchgroup=level3c start=// contains=TOP,level3,level4,level5,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level4 matchgroup=level4c start=// contains=TOP,level4,level5,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level5 matchgroup=level5c start=// contains=TOP,level5,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level6 matchgroup=level6c start=// contains=TOP,level6,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level7 matchgroup=level7c start=// contains=TOP,level7,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level8 matchgroup=level8c start=// contains=TOP,level8,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level9 matchgroup=level9c start=// contains=TOP,level9,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level10 matchgroup=level10c start=// contains=TOP,level10,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level11 matchgroup=level11c start=// contains=TOP,level11,level12,level13,level14,level15, level16,NoInParens + syntax region level12 matchgroup=level12c start=// contains=TOP,level12,level13,level14,level15, level16,NoInParens + syntax region level13 matchgroup=level13c start=// contains=TOP,level13,level14,level15, level16,NoInParens + syntax region level14 matchgroup=level14c start=// contains=TOP,level14,level15, level16,NoInParens + syntax region level15 matchgroup=level15c start=// contains=TOP,level15, level16,NoInParens + syntax region level16 matchgroup=level16c start=// contains=TOP,level16,NoInParens + let rainbow_parenthesis#active = 0 +endfunction + + " }}}1 +finish + +"------------------------------------------------------------------------------ +" Copyright (C) 2006 Martin Krischik +" +" Vim is Charityware - see ":help license" or uganda.txt for licence details. +"------------------------------------------------------------------------------ +" vim: textwidth=78 wrap tabstop=8 shiftwidth=4 softtabstop=4 expandtab +" vim: filetype=vim foldmethod=marker diff --git a/.vim/bundle/ack.vim/.gitignore b/.vim/bundle/ack.vim/.gitignore new file mode 100644 index 0000000..6e92f57 --- /dev/null +++ b/.vim/bundle/ack.vim/.gitignore @@ -0,0 +1 @@ +tags diff --git a/.vim/bundle/ack.vim/README.md b/.vim/bundle/ack.vim/README.md new file mode 100644 index 0000000..7e0c85d --- /dev/null +++ b/.vim/bundle/ack.vim/README.md @@ -0,0 +1,80 @@ +# ack.vim # + +This plugin is a front for the Perl module +[App::Ack](http://search.cpan.org/~petdance/ack/ack). Ack can be used as a +replacement for 99% of the uses of _grep_. This plugin will allow you to run +ack from vim, and shows the results in a split window. + +The *Official Version* of this plugin is available at [vim.org](http://www.vim.org/scripts/script.php?script_id=2572). + +## Installation ## + + +### Ack + +You have to install [ack](http://search.cpan.org/~petdance/ack/ack), of course. + +Install on Debian / Ubuntu with: + + sudo apt-get install ack-grep + +For Debian / Ubuntu you can add this line into your .vimrc: + + let g:ackprg="ack-grep -H --nocolor --nogroup --column" + +Install on Gentoo with: + + sudo emerge ack + +Install with MacPorts: + + sudo port install p5-app-ack + +Install with Gentoo Prefix + + emerge ack + +Otherwise, you are on your own. + +### The Plugin + +If you have [Rake](http://rake.rubyforge.org/) installed, you can just run: `rake install`. + +Otherwise, the file ack.vim goes in ~/.vim/plugin, and the ack.txt file belongs in ~/.vim/doc. Be sure to run + + :helptags ~/.vim/doc + +afterwards. + + +## Usage ## + + :Ack [options] {pattern} [{directory}] + +Search recursively in {directory} (which defaults to the current directory) for the {pattern}. + +Files containing the search term will be listed in the split window, along with +the line number of the occurrence, once for each occurrence. [Enter] on a line +in this window will open the file, and place the cursor on the matching line. + +Just like where you use :grep, :grepadd, :lgrep, and :lgrepadd, you can use `:Ack`, `:AckAdd`, `:LAck`, and `:LAckAdd` respectively. (See `doc/ack.txt`, or install and `:h Ack` for more information.) + +**From the [ack docs](http://search.cpan.org/~petdance/ack/ack)** (my favorite feature): + + --type=TYPE, --type=noTYPE + + Specify the types of files to include or exclude from a search. TYPE is a filetype, like perl or xml. --type=perl can also be specified as --perl, and --type=noperl can be done as --noperl. + + If a file is of both type "foo" and "bar", specifying --foo and --nobar will exclude the file, because an exclusion takes precedence over an inclusion. + + Type specifications can be repeated and are ORed together. + + See ack --help=types for a list of valid types. + +This Vim plugin is derived (and by derived, I mean copied, essentially) from +Antoine Imbert's blog post [Ack and Vim +Integration](http://blog.ant0ine.com/2007/03/ack_and_vim_integration.html) (in +particular, the function at the bottom of the post). I added a help file that +provides just enough reference to get you going. I also highly recommend you +check out the docs for the Perl script 'ack', for obvious reasons: [ack - +grep-like text finder](http://search.cpan.org/~petdance/ack/ack). diff --git a/.vim/bundle/ack.vim/Rakefile b/.vim/bundle/ack.vim/Rakefile new file mode 100644 index 0000000..af5a869 --- /dev/null +++ b/.vim/bundle/ack.vim/Rakefile @@ -0,0 +1,23 @@ +# Added by Josh Nichols, a.k.a. technicalpickles +require 'rake' + +files = ['doc/ack.txt', 'plugin/ack.vim'] + +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 " Copied #{file} to #{target_file}" + end + +end diff --git a/.vim/bundle/ack.vim/doc/ack.txt b/.vim/bundle/ack.vim/doc/ack.txt new file mode 100644 index 0000000..a97798b --- /dev/null +++ b/.vim/bundle/ack.vim/doc/ack.txt @@ -0,0 +1,50 @@ +*ack.txt* Plugin that integrates ack with Vim + +============================================================================== +Author: Antoine Imbert *ack-author* +License: Same terms as Vim itself (see |license|) + +============================================================================== +INTRODUCTION *ack* + +This plugin is a front for the Perl module App::Ack. Ack can be used as a +replacement for grep. This plugin will allow you to run ack from vim, and +shows the results in a split window. + +:Ack [options] {pattern} [{directory}] *:Ack* + + Search recursively in {directory} (which defaults to the current + directory) for the {pattern}. Behaves just like the |:grep| command, but + will open the |Quickfix| window for you. + +:AckAdd [options] {pattern} [{directory}] *:AckAdd* + + Just like |:Ack|, but instead of making a new list, the matches are + appended to the current |quickfix| list. + +:AckFromSearch [{directory}] *:AckFromSearch* + + Just like |:Ack| but the pattern is from previous search. + +:LAck [options] {pattern} [{directory}] *:LAck* + + Just like |:Ack| but instead of the |quickfix| list, matches are placed in + the current |location-list|. + +:LAckAdd [options] {pattern} [{directory}] *:LAckAdd* + + Just like |:AckAdd| but instead of the |quickfix| list, matches are added + to the current |location-list| + +:AckFile [options] {pattern} [{directory}] *:AckFile* + + Search recursively in {directory} (which defaults to the current + directory) for filenames matching the {pattern}. Behaves just like the + |:grep| command, but will open the |Quickfix| window for you. + +Files containing the search term will be listed in the split window, along +with the line number of the occurrence, once for each occurrence. on +a line in this window will open the file, and place the cursor on the matching +line. + +See http://search.cpan.org/~petdance/ack/ack for more information. diff --git a/.vim/bundle/ack.vim/plugin/ack.vim b/.vim/bundle/ack.vim/plugin/ack.vim new file mode 100644 index 0000000..b05041b --- /dev/null +++ b/.vim/bundle/ack.vim/plugin/ack.vim @@ -0,0 +1,61 @@ +" NOTE: You must, of course, install the ack script +" in your path. +" On Debian / Ubuntu: +" sudo apt-get install ack-grep +" On your vimrc: +" let g:ackprg="ack-grep -H --nocolor --nogroup --column" +" +" With MacPorts: +" sudo port install p5-app-ack + +" Location of the ack utility +if !exists("g:ackprg") + let g:ackprg="ack -H --nocolor --nogroup --column" +endif + +function! s:Ack(cmd, args) + redraw + echo "Searching ..." + + " Format, used to manage column jump + if a:cmd =~# '-g$' + let g:ackformat="%f" + else + let g:ackformat="%f:%l:%c:%m" + end + + let grepprg_bak=&grepprg + let grepformat_bak=&grepformat + try + let &grepprg=g:ackprg + let &grepformat=g:ackformat + silent execute a:cmd . " " . a:args + finally + let &grepprg=grepprg_bak + let &grepformat=grepformat_bak + endtry + + if a:cmd =~# '^l' + botright lopen + else + botright copen + endif + + exec "nnoremap q :ccl" + + redraw! +endfunction + +function! s:AckFromSearch(cmd, args) + let search = getreg('/') + " translate vim regular expression to perl regular expression. + let search = substitute(search,'\(\\<\|\\>\)','\\b','g') + call s:Ack(a:cmd, '"' . search .'" '. a:args) +endfunction + +command! -bang -nargs=* -complete=file Ack call s:Ack('grep',) +command! -bang -nargs=* -complete=file AckAdd call s:Ack('grepadd', ) +command! -bang -nargs=* -complete=file AckFromSearch call s:AckFromSearch('grep', ) +command! -bang -nargs=* -complete=file LAck call s:Ack('lgrep', ) +command! -bang -nargs=* -complete=file LAckAdd call s:Ack('lgrepadd', ) +command! -bang -nargs=* -complete=file AckFile call s:Ack('grep -g', ) diff --git a/.vim/bundle/delimitMate/.gitignore b/.vim/bundle/delimitMate/.gitignore new file mode 100644 index 0000000..5338046 --- /dev/null +++ b/.vim/bundle/delimitMate/.gitignore @@ -0,0 +1,8 @@ +*.sw? +*.un? +*.vba +*.zip +*.gz +vimball.txt +*.orig +tags diff --git a/.vim/bundle/delimitMate/Makefile b/.vim/bundle/delimitMate/Makefile new file mode 100644 index 0000000..2a5db0c --- /dev/null +++ b/.vim/bundle/delimitMate/Makefile @@ -0,0 +1,62 @@ +PLUGIN=$(shell basename "$$PWD") +SCRIPT=$(wildcard plugin/*.vim) +#AUTOL=$(wildcard autoload/*.vim) +AUTOL=autoload/$(PLUGIN).vim +DOC=$(wildcard doc/*.txt) +TESTS=$(wildcard autoload/*Tests.vim) +VERSION=$(shell perl -ne 'if (/\*\sCurrent\srelease:/) {s/^\s+(\d+\.\S+)\s.*$$/\1/;print}' $(DOC)) +VIMFOLDER=~/.vim/ +VIM=/usr/bin/vim + +.PHONY: $(PLUGIN).vba README + +all: vimball README zip gzip + +vimball: $(PLUGIN).vba + +clean: + @echo clean + rm -f *.vba */*.orig *.~* .VimballRecord *.zip *.gz + +dist-clean: clean + +undo: + for i in */*.orig; do mv -f "$$i" "$${i%.*}"; done + +README: + @echo README + cp -f $(DOC) README + +$(PLUGIN).vba: + @echo $(PLUGIN).vba + rm -f $(PLUGIN)-$(VERSION).vba + $(VIM) -N -c 'ru! vimballPlugin.vim' -c ':call append("0", [ "$(SCRIPT)", "$(AUTOL)", "$(DOC)"])' -c '$$d' -c ":%MkVimball $(PLUGIN)-$(VERSION) ." -c':q!' + ln -f $(PLUGIN)-$(VERSION).vba $(PLUGIN).vba + +zip: + @echo zip + rm -f *.zip + zip -r $(PLUGIN).zip doc plugin autoload + zip $(PLUGIN).zip -d \*.sw\? || echo 1 + zip $(PLUGIN).zip -d \*.un\? || echo 1 + zip $(PLUGIN).zip -d \*.orig || echo 1 + zip $(PLUGIN).zip -d \*tags || echo 1 + zip $(PLUGIN).zip -d $(TESTS) + ln -f $(PLUGIN).zip $(PLUGIN)-$(VERSION).zip + +gzip: vimball + @echo vimball + gzip -f $(PLUGIN).vba + +release: version all + +version: + @echo version: $(VERSION) + perl -i.orig -pne 'if (/^"\sVersion:/) {s/(\d+\.\S+)/$(VERSION)/}' $(SCRIPT) $(AUTOL) + perl -i.orig -pne 'if (/let\sdelimitMate_version/) {s/"(\d+\.\S+)"/"$(VERSION)"/}' $(SCRIPT) + perl -i.orig -pne 'if (/beasts/) {s/(v\d+\.\S+)/v$(VERSION)/}' $(DOC) + perl -i.orig -MPOSIX -pne 'if (/^"\sModified:/) {$$now_string = strftime "%F", localtime; s/(\d+-\d+-\d+)/$$now_string/e}' $(SCRIPT) $(AUTOL) + perl -i.orig -MPOSIX -pne 'if (/^\s+$(VERSION)\s+\d+-\d+-\d+\s+\*/) {$$now_string = strftime "%F", localtime; s/(\d+-\d+-\d+)/$$now_string/}' $(DOC) + @echo Version: $(VERSION) + +echo: diff --git a/.vim/bundle/delimitMate/README b/.vim/bundle/delimitMate/README new file mode 100644 index 0000000..5aa6117 --- /dev/null +++ b/.vim/bundle/delimitMate/README @@ -0,0 +1,761 @@ +*delimitMate.txt* Trying to keep those beasts at bay! v2.5.1 *delimitMate* + + + + MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMMMM MMMMMMMMMMMMMMMMMMMMM ~ + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMM MMMMMMMMMMMMMMMMMMMMM + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMM MMM M M MMMMMMMMMM MMMMMMMMM ~ + MMMM MMM MMM MM MM M M MMM MM MM MM MM MMM MMM MMM MM + MM MM M MM MMMMMM MMMMMMM MMM MMMMM MM M MMM MMM M M ~ + M M MM MM MM MM M M MM MMM MMM MMMMM MMMMM MMM MMM M + M M MM MMMMM MM MM M M MM MMM MMM MMMMM MMM MMM MMM MMMM ~ + M M MM M MM MM MM M M MM MMM MMM MMMMM MM M MMM MMM M M + MM MMM MMM MM MM M M MM MMM MM MMMMM MMM MMM MMM MM ~ + MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + + + +============================================================================== + 0.- CONTENTS *delimitMate-contents* + + 1. Introduction____________________________|delimitMateIntro| + 2. Customization___________________________|delimitMateOptions| + 2.1 Options summary____________________|delimitMateOptionSummary| + 2.2 Options details____________________|delimitMateOptionDetails| + 3. Functionality___________________________|delimitMateFunctionality| + 3.1 Automatic closing & exiting________|delimitMateAutoClose| + 3.2 Expansion of space and CR__________|delimitMateExpansion| + 3.3 Backspace__________________________|delimitMateBackspace| + 3.4 Smart Quotes_______________________|delimitMateSmartQuotes| + 3.5 Balancing matching pairs___________|delimitMateBalance| + 3.6 FileType based configuration_______|delimitMateFileType| + 3.7 Syntax awareness___________________|delimitMateSyntax| + 4. Commands________________________________|delimitMateCommands| + 5. Mappings________________________________|delimitMateMappings| + 6. Functions_______________________________|delimitMateFunctions| + 7. TODO list_______________________________|delimitMateTodo| + 8. Maintainer______________________________|delimitMateMaintainer| + 9. Credits_________________________________|delimitMateCredits| + 10. History_________________________________|delimitMateHistory| + +============================================================================== + 1.- INTRODUCTION *delimitMateIntro* + +This plug-in provides automatic closing of quotes, parenthesis, brackets, +etc.; besides some other related features that should make your time in insert +mode a little bit easier. + +Most of the features can be modified or disabled permanently, using global +variables, or on a FileType basis, using autocommands. With a couple of +exceptions and limitations, this features don't brake undo, redo or history. + +NOTE 1: If you have any trouble with this plugin, please run |:DelimitMateTest| +in a new buffer to see what is not working. + +NOTE 2: |'timeout'| needs to be set when working in the terminal, otherwise you +might find weird behaviour with mappings including or arrow keys. + +NOTE 3: Abbreiations set with |:iabbrev| will not be expanded by delimiters +used on delimitMate, you should use (read |i_CTRL-]|) to expand them on +the go. + +============================================================================== + 2. CUSTOMIZATION *delimitMateOptions* + +You can create your own mappings for some features using the global functions. +Read |DelimitMateFunctions| for more info. + +------------------------------------------------------------------------------ + 2.1 OPTIONS SUMMARY *delimitMateOptionSummary* + +The behaviour of this script can be customized setting the following options +in your vimrc file. You can use local options to set the configuration for +specific file types, see |delimitMateOptionDetails| for examples. + +|'loaded_delimitMate'| Turns off the script. + +|'delimitMate_autoclose'| Tells delimitMate whether to automagically + insert the closing delimiter. + +|'delimitMate_matchpairs'| Tells delimitMate which characters are + matching pairs. + +|'delimitMate_quotes'| Tells delimitMate which quotes should be + used. + +|'delimitMate_nesting_quotes'| Tells delimitMate which quotes should be + allowed to be nested. + +|'delimitMate_expand_cr'| Turns on/off the expansion of . + +|'delimitMate_expand_space'| Turns on/off the expansion of . + +|'delimitMate_smart_quotes'| Turns on/off the "smart quotes" feature. + +|'delimitMate_balance_matchpairs'|Turns on/off the "balance matching pairs" + feature. + +|'delimitMate_excluded_regions'| Turns off the script for the given regions or + syntax group names. + +|'delimitMate_excluded_ft'| Turns off the script for the given file types. + +|'delimitMate_apostrophes'| Tells delimitMate how it should "fix" + balancing of single quotes when used as + apostrophes. NOTE: Not needed any more, kept + for compatibility with older versions. + +------------------------------------------------------------------------------ + 2.2 OPTIONS DETAILS *delimitMateOptionDetails* + +Add the shown lines to your vimrc file in order to set the below options. +Buffer variables take precedence over global ones and can be used along with +autocmd to modify delimitMate's behavior for specific file types, read more in +|delimitMateFileType|. + +Note: Use buffer variables only to set options for specific file types using +:autocmd, use global variables to set options for every buffer. Read more in +|g:var| and |b:var|. + +------------------------------------------------------------------------------ + *'loaded_delimitMate'* + *'b:loaded_delimitMate'* +This option prevents delimitMate from loading. +e.g.: > + let loaded_delimitMate = 1 + au FileType mail let b:loaded_delimitMate = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_autoclose'* + *'b:delimitMate_autoclose'* +Values: 0 or 1. ~ +Default: 1 ~ + +If this option is set to 0, delimitMate will not add a closing delimiter +automagically. See |delimitMateAutoClose| for details. +e.g.: > + let delimitMate_autoclose = 0 + au FileType mail let b:delimitMate_autoclose = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_matchpairs'* + *'b:delimitMate_matchpairs'* +Values: A string with |'matchpairs'| syntax, plus support for multi-byte~ + characters.~ +Default: &matchpairs ~ + +Use this option to tell delimitMate which characters should be considered +matching pairs. Read |delimitMateAutoClose| for details. +e.g: > + let delimitMate_matchpairs = "(:),[:],{:},<:>" + au FileType vim,html let b:delimitMate_matchpairs = "(:),[:],{:},<:>" +< +------------------------------------------------------------------------------ + *'delimitMate_quotes'* + *'b:delimitMate_quotes'* +Values: A string of characters separated by spaces. ~ +Default: "\" ' `" ~ + +Use this option to tell delimitMate which characters should be considered as +quotes. Read |delimitMateAutoClose| for details. +e.g.: > + let delimitMate_quotes = "\" ' ` *" + au FileType html let b:delimitMate_quotes = "\" '" +< +------------------------------------------------------------------------------ + *'delimitMate_nesting_quotes'* + *'b:delimitMate_nesting_quotes'* +Values: A list of quotes. ~ +Default: [] ~ + +Quotes listed here will not be able to jump out of the empty pair, thus +allowing the autoclosed quotes to be nested. +e.g.: > + let delimitMate_nesting_quotes = ['"','`'] + au FileType python let b:delimitMate_nesting_quotes = ['"'] +< +------------------------------------------------------------------------------ + *'delimitMate_expand_cr'* + *'b:delimitMate_expand_cr'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. +e.g.: > + let delimitMate_expand_cr = 1 + au FileType mail let b:delimitMate_expand_cr = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_expand_space'* + *'b:delimitMate_expand_space'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. +e.g.: > + let delimitMate_expand_space = 1 + au FileType tcl let b:delimitMate_expand_space = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_smart_quotes'* + *'b:delimitMate_smart_quotes'* +Values: 1 or 0 ~ +Default: 1 ~ + +This option turns on/off the smart quotes feature. Read +|delimitMateSmartQuotes| for details. +e.g.: > + let delimitMate_smart_quotes = 0 + au FileType tcl let b:delimitMate_smart_quotes = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_balance_matchpairs'* + *'b:delimitMate_balance_matchpairs'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the balancing of matching pairs. Read +|delimitMateBalance| for details. +e.g.: > + let delimitMate_balance_matchpairs = 1 + au FileType tcl let b:delimitMate_balance_matchpairs = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_excluded_regions'* +Values: A string of syntax group names names separated by single commas. ~ +Default: Comment ~ + +This options turns delimitMate off for the listed regions, read |group-name| +for more info about what is a region. +e.g.: > + let delimitMate_excluded_regions = "Comments,String" +< +------------------------------------------------------------------------------ + *'delimitMate_excluded_ft'* +Values: A string of file type names separated by single commas. ~ +Default: Empty. ~ + +This options turns delimitMate off for the listed file types, use this option +only if you don't want any of the features it provides on those file types. +e.g.: > + let delimitMate_excluded_ft = "mail,txt" +< +------------------------------------------------------------------------------ + *'delimitMate_apostrophes'* +Values: Strings separated by ":". ~ +Default: No longer used. ~ + +NOTE: This feature is turned off by default, it's been kept for compatibility +with older version, read |delimitMateSmartQuotes| for details. +If auto-close is enabled, this option tells delimitMate how to try to fix the +balancing of single quotes when used as apostrophes. The values of this option +are strings of text where a single quote would be used as an apostrophe (e.g.: +the "n't" of wouldn't or can't) separated by ":". Set it to an empty string to +disable this feature. +e.g.: > + let delimitMate_apostrophes = "" + au FileType tcl let delimitMate_apostrophes = "" +< +============================================================================== + 3. FUNCTIONALITY *delimitMateFunctionality* + +------------------------------------------------------------------------------ + 3.1 AUTOMATIC CLOSING AND EXITING *delimitMateAutoClose* + +With automatic closing enabled, if an opening delimiter is inserted the plugin +inserts the closing delimiter and places the cursor between the pair. With +automatic closing disabled, no closing delimiters is inserted by delimitMate, +but when a pair of delimiters is typed, the cursor is placed in the middle. + +When the cursor is inside an empty pair or located next to the left of a +closing delimiter, the cursor is placed outside the pair to the right of the +closing delimiter. + +Unless |'delimitMate_matchpairs'| or |'delimitMate_quotes'|are set, this +script uses the values in '&matchpairs' to identify the pairs, and ", ' and ` +for quotes respectively. + +The following table shows the behaviour, this applies to quotes too (the final +position of the cursor is represented by a "|"): + +With auto-close: > + Type | You get + ==================== + ( | (|) + –––––––––|–––––––––– + () | ()| + –––––––––|–––––––––– + ( | ()| +< +Without auto-close: > + + Type | You get + ===================== + () | (|) + –––––––––-|–––––––––– + ()) | ()| + –––––––––-|–––––––––– + () | ()| +< +NOTE: Abbreviations will not be expanded by delimiters used on delimitMate, +you should use (read |i_CTRL-]|) to expand them on the go. + +------------------------------------------------------------------------------ + 3.2 EXPANSION OF SPACE AND CAR RETURN *delimitMateExpansion* + +When the cursor is inside an empty pair of delimiters, and can be +expanded, see |'delimitMate_expand_space'| and +|'delimitMate_expand_cr'|: + +Expand to: > + + | You get + ==================================== + (|) | ( | ) +< +Expand to: > + + | You get + ============================ + (|) | ( + | | + | ) +< + +NOTE that the expansion of will brake the redo command. + +Since and are used everywhere, I have made the functions involved +in expansions global, so they can be used to make custom mappings. Read +|delimitMateFunctions| for more details. + +------------------------------------------------------------------------------ + 3.3 BACKSPACE *delimitMateBackspace* + +If you press backspace inside an empty pair, both delimiters are deleted. When +expansions are enabled, will also delete the expansions. NOTE that +deleting expansions will brake the redo command. + +If you type (shift + backspace) instead, only the closing delimiter +will be deleted. NOTE that this will not usually work when using Vim from the +terminal, see 'delimitMate#JumpAny()' below to see how to fix it. + +e.g. typing at the "|": > + + What | Before | After + ============================================== + | call expand(|) | call expand| + ---------|-------------------|----------------- + | call expand( | ) | call expand(|) + ---------|-------------------|----------------- + | call expand( | call expand(|) + | | | + | ) | + ---------|-------------------|----------------- + | call expand(|) | call expand(| +< + +------------------------------------------------------------------------------ + 3.4 SMART QUOTES *delimitMateSmartQuotes* + +Only one quote will be inserted following a quote, a "\" or, following or +preceding an alphanumeric character. This should cover closing quotes after a +string, opening quotes before a string, escaped quotes and apostrophes. Except +for apostrophes, this feature can be disabled setting the option +|'delimitMate_smart_quotes'| to 0. + +e.g. typing at the "|": > + + What | Before | After + ======================================= + " | Text | | Text "|" + " | "String| | "String"| + " | let i = "| | let i = "|" + 'm | I| | I'm| +< +------------------------------------------------------------------------------ + 3.5 BALANCING MATCHING PAIRS *delimitMateBalance* + +When inserting an opening paren and |'delimitMate_balance_matchpairs'| is +enabled, delimitMate will try to balance the closing pairs in the current +line. + +e.g. typing at the "|": > + + What | Before | After + ======================================= + ( | |) | (|) + ( | | | (|) + ( | (|) | ((|)) +< +------------------------------------------------------------------------------ + 3.6 FILE TYPE BASED CONFIGURATION *delimitMateFileType* + +delimitMate options can be set globally for all buffers using global +("regular") variables in your |vimrc| file. But |:autocmd| can be used to set +options for specific file types (see |'filetype'|) using buffer variables in +the following way: > + + au FileType mail,text let b:delimitMate_autoclose = 0 + ^ ^ ^ ^ ^ + | | | | | + | | | | - Option value. + | | | - Option name. + | | - Buffer variable. + | - File types for which the option will be set. + - Don't forget to put this event. +< +NOTE that you should use buffer variables (|b:var|) only to set options with +|:autocmd|, for global options use regular variables (|g:var|) in your vimrc. + +------------------------------------------------------------------------------ + 3.7 SYNTAX AWARENESS *delimitMateSyntax* + +The features of this plug-in might not be always helpful, comments and strings +usualy don't need auto-completion. delimitMate monitors which region is being +edited and if it detects that the cursor is in a comment it'll turn itself off +until the cursor leaves the comment. The excluded regions can be set using the +option |'delimitMate_excluded_regions'|. Read |group-name| for a list of +regions or syntax group names. + +NOTE that this feature relies on a proper syntax file for the current file +type, if the appropiate syntax file doesn't define a region, delimitMate won't +know about it. + +============================================================================== + 4. COMMANDS *delimitMateCommands* + +------------------------------------------------------------------------------ +:DelimitMateReload *:DelimitMateReload* + +Re-sets all the mappings used for this script, use it if any option has been +changed or if the filetype option hasn't been set yet. + +------------------------------------------------------------------------------ +:DelimitMateSwitch *:DelimitMateSwitch* + +Switches the plug-in on and off. + +------------------------------------------------------------------------------ +:DelimitMateTest *:DelimitMateTest* + +This command tests every mapping set-up for this script, useful for testing +custom configurations. + +The following output corresponds to the default values, it will be different +depending on your configuration. "Open & close:" represents the final result +when the closing delimiter has been inserted, either manually or +automatically, see |delimitMateExpansion|. "Delete:" typing backspace in an +empty pair, see |delimitMateBackspace|. "Exit:" typing a closing delimiter +inside a pair of delimiters, see |delimitMateAutoclose|. "Space:" the +expansion, if any, of space, see |delimitMateExpansion|. "Visual-L", +"Visual-R" and "Visual" shows visual wrapping, see +|delimitMateVisualWrapping|. "Car return:" the expansion of car return, see +|delimitMateExpansion|. The cursor's position at the end of every test is +represented by an "|": > + + * AUTOCLOSE: + Open & close: (|) + Delete: | + Exit: ()| + Space: ( |) + Visual-L: (v) + Visual-R: (v) + Car return: ( + |) + + Open & close: {|} + Delete: | + Exit: {}| + Space: { |} + Visual-L: {v} + Visual-R: {v} + Car return: { + |} + + Open & close: [|] + Delete: | + Exit: []| + Space: [ |] + Visual-L: [v] + Visual-R: [v] + Car return: [ + |] + + Open & close: "|" + Delete: | + Exit: ""| + Space: " |" + Visual: "v" + Car return: " + |" + + Open & close: '|' + Delete: | + Exit: ''| + Space: ' |' + Visual: 'v' + Car return: ' + |' + + Open & close: `|` + Delete: | + Exit: ``| + Space: ` |` + Visual: `v` + Car return: ` + |` +< + +============================================================================== + 5. MAPPINGS *delimitMateMappings* + +delimitMate doesn't override any existing map, so you may encounter that it +doesn't work as expected because a mapping is missing. In that case, the +conflicting mappings should be resolved by either disabling the conflicting +mapping or creating a custom mappings. + +In order to make custom mappings easier and prevent overwritting existing +ones, delimitMate uses the || + |hasmapto()| (|usr_41.txt|) construct +for its mappings. + +The following are the mappings alway set by delimitMate: + + is mapped to delimitMateBS + is mapped to delimitMateS-BS + is mapped to delimitMateS-Tab + is mapped to delimitMateDel + is mapped to delimitMateEsc + is mapped to delimitMateLeft + is mapped to delimitMateRight + is mapped to delimitMateHome + is mapped to delimitMateEnd + is mapped to delimitMateUp + is mapped to delimitMateDown + is mapped to delimitMatePageUp + is mapped to delimitMatePageDown + is mapped to delimitMateS-Down + is mapped to delimitMateS-Up + is mapped to delimitMateMLeftMouse + is mapped to delimitMateMRightMouse + +The rest of the mappings correspond to parens, quotes, CR, Space, etc. and they +depend on the values of the delimitMate options, they have the following form: + +delimitMate + char + +e.g.: for "(": + +( is mapped to delimitMate( + +e.g.: If you have expansion enabled, you might want to skip it on pop-up +menus: + + imap pumvisible() ? + \"\" : + \ "delimitMateCR" + + +============================================================================== + 6. FUNCTIONS *delimitMateFunctions* + +------------------------------------------------------------------------------ +delimitMate#WithinEmptyPair() *delimitMate_WithinEmptyPair()* + +Returns 1 if the cursor is inside an empty pair, 0 otherwise. +e.g.: > + + inoremap delimitMate#WithinEmptyPair() ? + \ "\=delimitMate#ExpandReturn()\" : + \ "external_mapping" +< + +------------------------------------------------------------------------------ +delimitMate#ShouldJump() *delimitMate#ShouldJump()* + +Returns 1 if there is a closing delimiter or a quote to the right of the +cursor, 0 otherwise. + +------------------------------------------------------------------------------ +delimitMate#JumpAny(key) *delimitMate#JumpAny()* + +This function returns a mapping that will make the cursor jump to the right +when delimitMate#ShouldJump() returns 1, returns the argument "key" otherwise. +e.g.: You can use this to create your own mapping to jump over any delimiter. +> + inoremap =delimitMate#JumpAny("\") +< + +============================================================================== + 7. TODO LIST *delimitMateTodo* + +- Automatic set-up by file type. +- Make block-wise visual wrapping work on un-even regions. + +============================================================================== + 8. MAINTAINER *delimitMateMaintainer* + +Hi there! My name is Israel Chauca F. and I can be reached at: + mailto:israelchauca@gmail.com + +Feel free to send me any suggestions and/or comments about this plugin, I'll +be very pleased to read them. + +============================================================================== + 9. CREDITS *delimitMateCredits* + +Some of the code that make this script is modified or just shamelessly copied +from the following sources: + + - Ian McCracken + Post titled: Vim, Part II: Matching Pairs: + http://concisionandconcinnity.blogspot.com/ + + - Aristotle Pagaltzis + From the comments on the previous blog post and from: + http://gist.github.com/144619 + + - Karl Guertin + AutoClose: + http://www.vim.org/scripts/script.php?script_id=1849 + + - Thiago Alves + AutoClose: + http://www.vim.org/scripts/script.php?script_id=2009 + + - Edoardo Vacchi + ClosePairs: + http://www.vim.org/scripts/script.php?script_id=2373 + +This script was inspired by the auto-completion of delimiters on TextMate. + +============================================================================== + 10. HISTORY *delimitMateHistory* + + Version Date Release notes ~ +|---------|------------|-----------------------------------------------------| + 2.5.1 2010-09-30 * Current release: + - Remove visual wrapping. Surround.vim offers a much + better implementation. + - Minor mods to DelimitMateTest. +|---------|------------|-----------------------------------------------------| + 2.5 2010-09-22 * - Better handling of mappings. + - Add report for mappings in |:DelimitMateTest|. + - Allow the use of "|" and multi-byte characters in + |'delimitMate_quotes'| and |'delimitMate_matchpairs'|. + - Allow commands to be concatenated using |. +|---------|------------|-----------------------------------------------------| + 2.4.1 2010-07-31 * - Fix problem with and . + - Add missing doc on |'delimitMate_smart_quotes'|, + |delimitMateBalance| and + |'delimitMate_balance_matchpairs'|. +|---------|------------|-----------------------------------------------------| + 2.4 2010-07-29 * - Unbalanced parens: see :help delimitMateBalance. + - Visual wrapping now works on block-wise visual + with some limitations. + - Arrow keys didn't work on terminal. + - Added option to allow nested quotes. + - Expand Smart Quotes to look for a string on the + right of the cursor. + +|---------|------------|-----------------------------------------------------| + 2.3.1 2010-06-06 * - Fix: an extra is inserted after + expansion. + +|---------|------------|-----------------------------------------------------| + 2.3 2010-06-06 * - Syntax aware: Will turn off when editing comments + or other regions, customizable. + - Changed format of most mappings. + - Fix: expansion doesn't brake automatic + indentation adjustments anymore. + - Fix: Arrow keys would insert A, B, C or D instead + of moving the cursor when using Vim on a terminal. + +|---------|------------|-----------------------------------------------------| + 2.2 2010-05-16 * - Added command to switch the plug-in on and off. + - Fix: some problems with , and . + - Fix: A small problem when inserting a delimiter at + the beginning of the line. + +|---------|------------|-----------------------------------------------------| + 2.1 2010-05-10 * - Most of the functions have been moved to an + autoload script to avoid loading unnecessary ones. + - Fixed a problem with the redo command. + - Many small fixes. + +|---------|------------|-----------------------------------------------------| + 2.0 2010-04-01 * New features: + - All features are redo/undo-wise safe. + - A single quote typed after an alphanumeric + character is considered an apostrophe and one + single quote is inserted. + - A quote typed after another quote inserts a single + quote and the cursor jumps to the middle. + - jumps out of any empty pair. + - and expansions are fixed, but the + functions used for it are global and can be used in + custom mappings. The previous system is still + active if you have any of the expansion options + set. + - deletes the closing delimiter. + * Fixed bug: + - s:vars were being used to store buffer options. + +|---------|------------|-----------------------------------------------------| + 1.6 2009-10-10 * Now delimitMate tries to fix the balancing of single + quotes when used as apostrophes. You can read + |delimitMate_apostrophes| for details. + Fixed an error when |b:delimitMate_expand_space| + wasn't set but |delimitMate_expand_space| wasn't. + +|---------|------------|-----------------------------------------------------| + 1.5 2009-10-05 * Fix: delimitMate should work correctly for files + passed as arguments to Vim. Thanks to Ben Beuchler + for helping to nail this bug. + +|---------|------------|-----------------------------------------------------| + 1.4 2009-09-27 * Fix: delimitMate is now enabled on new buffers even + if they don't have set the file type option or were + opened directly from the terminal. + +|---------|------------|-----------------------------------------------------| + 1.3 2009-09-24 * Now local options can be used along with autocmd + for specific file type configurations. + Fixes: + - Unnamed register content is not lost on visual + mode. + - Use noremap where appropiate. + - Wrapping a single empty line works as expected. + +|---------|------------|-----------------------------------------------------| + 1.2 2009-09-07 * Fixes: + - When inside nested empty pairs, deleting the + innermost left delimiter would delete all right + contiguous delimiters. + - When inside an empty pair, inserting a left + delimiter wouldn't insert the right one, instead + the cursor would jump to the right. + - New buffer inside the current window wouldn't + have the mappings set. + +|---------|------------|-----------------------------------------------------| + 1.1 2009-08-25 * Fixed an error that ocurred when mapleader wasn't + set and added support for GetLatestScripts + auto-detection. + +|---------|------------|-----------------------------------------------------| + 1.0 2009-08-23 * Initial upload. + +|---------|------------|-----------------------------------------------------| + + + `\|||/´ MMM \|/ www __^__ ~ + (o o) (o o) @ @ (O-O) /(o o)\\ ~ +ooO_(_)_Ooo__ ooO_(_)_Ooo___oOO_(_)_OOo___oOO__(_)__OOo___oOO__(_)__OOo_____ ~ +_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ +__|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_ ~ +_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ + +vim:tw=78:et:ts=2:sw=2:ft=help:norl:formatoptions+=tcroqn:autoindent: diff --git a/.vim/bundle/delimitMate/autoload/delimitMate.vim b/.vim/bundle/delimitMate/autoload/delimitMate.vim new file mode 100644 index 0000000..c4c7ca4 --- /dev/null +++ b/.vim/bundle/delimitMate/autoload/delimitMate.vim @@ -0,0 +1,538 @@ +" ============================================================================ +" File: autoload/delimitMate.vim +" Version: 2.5.1 +" Modified: 2010-09-30 +" Description: This plugin provides auto-completion for quotes, parens, etc. +" Maintainer: Israel Chauca F. +" Manual: Read ":help delimitMate". + +" Utilities {{{ + +let delimitMate_loaded = 1 + +function! delimitMate#ShouldJump() "{{{ + " Returns 1 if the next character is a closing delimiter. + let col = col('.') + let lcol = col('$') + let char = getline('.')[col - 1] + + " Closing delimiter on the right. + for cdel in b:_l_delimitMate_right_delims + b:_l_delimitMate_quotes_list + if char == cdel + return 1 + endif + endfor + + " Closing delimiter with space expansion. + let nchar = getline('.')[col] + if b:_l_delimitMate_expand_space && char == " " + for cdel in b:_l_delimitMate_right_delims + b:_l_delimitMate_quotes_list + if nchar == cdel + return 1 + endif + endfor + endif + + " Closing delimiter with CR expansion. + let uchar = getline(line('.') + 1)[0] + if b:_l_delimitMate_expand_cr && char == "" + for cdel in b:_l_delimitMate_right_delims + b:_l_delimitMate_quotes_list + if uchar == cdel + return 1 + endif + endfor + endif + + return 0 +endfunction "}}} + +function! delimitMate#IsEmptyPair(str) "{{{ + for pair in b:_l_delimitMate_matchpairs_list + if a:str == join( split( pair, ':' ),'' ) + return 1 + endif + endfor + for quote in b:_l_delimitMate_quotes_list + if a:str == quote . quote + return 1 + endif + endfor + return 0 +endfunction "}}} + +function! delimitMate#IsCRExpansion() " {{{ + let nchar = getline(line('.')-1)[-1:] + let schar = getline(line('.')+1)[:0] + let isEmpty = getline('.') == "" + if index(b:_l_delimitMate_left_delims, nchar) > -1 && + \ index(b:_l_delimitMate_left_delims, nchar) == index(b:_l_delimitMate_right_delims, schar) && + \ isEmpty + return 1 + elseif index(b:_l_delimitMate_quotes_list, nchar) > -1 && + \ index(b:_l_delimitMate_quotes_list, nchar) == index(b:_l_delimitMate_quotes_list, schar) && + \ isEmpty + return 1 + else + return 0 + endif +endfunction " }}} delimitMate#IsCRExpansion() + +function! delimitMate#IsSpaceExpansion() " {{{ + let line = getline('.') + let col = col('.')-2 + if col > 0 + let pchar = line[col - 1] + let nchar = line[col + 2] + let isSpaces = (line[col] == line[col+1] && line[col] == " ") + + if index(b:_l_delimitMate_left_delims, pchar) > -1 && + \ index(b:_l_delimitMate_left_delims, pchar) == index(b:_l_delimitMate_right_delims, nchar) && + \ isSpaces + return 1 + elseif index(b:_l_delimitMate_quotes_list, pchar) > -1 && + \ index(b:_l_delimitMate_quotes_list, pchar) == index(b:_l_delimitMate_quotes_list, nchar) && + \ isSpaces + return 1 + endif + endif + return 0 +endfunction " }}} IsSpaceExpansion() + +function! delimitMate#WithinEmptyPair() "{{{ + let cur = strpart( getline('.'), col('.')-2, 2 ) + return delimitMate#IsEmptyPair( cur ) +endfunction "}}} + +function! delimitMate#WriteBefore(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if col < 0 + call setline('.',line[(col+len+1):]) + else + call setline('.',line[:(col)].line[(col+len+1):]) + endif + return a:str +endfunction " }}} + +function! delimitMate#WriteAfter(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if (col) < 0 + call setline('.',a:str.line) + else + call setline('.',line[:(col)].a:str.line[(col+len):]) + endif + return '' +endfunction " }}} + +function! delimitMate#GetSyntaxRegion(line, col) "{{{ + return synIDattr(synIDtrans(synID(a:line, a:col, 1)), 'name') +endfunction " }}} + +function! delimitMate#GetCurrentSyntaxRegion() "{{{ + let col = col('.') + if col == col('$') + let col = col - 1 + endif + return delimitMate#GetSyntaxRegion(line('.'), col) +endfunction " }}} + +function! delimitMate#GetCurrentSyntaxRegionIf(char) "{{{ + let col = col('.') + let origin_line = getline('.') + let changed_line = strpart(origin_line, 0, col - 1) . a:char . strpart(origin_line, col - 1) + call setline('.', changed_line) + let region = delimitMate#GetSyntaxRegion(line('.'), col) + call setline('.', origin_line) + return region +endfunction "}}} + +function! delimitMate#IsForbidden(char) "{{{ + if b:_l_delimitMate_excluded_regions_enabled == 0 + return 0 + endif + "let result = index(b:_l_delimitMate_excluded_regions_list, delimitMate#GetCurrentSyntaxRegion()) >= 0 + if index(b:_l_delimitMate_excluded_regions_list, delimitMate#GetCurrentSyntaxRegion()) >= 0 + "echom "Forbidden 1!" + return 1 + endif + let region = delimitMate#GetCurrentSyntaxRegionIf(a:char) + "let result = index(b:_l_delimitMate_excluded_regions_list, region) >= 0 + "return result || region == 'Comment' + "echom "Forbidden 2!" + return index(b:_l_delimitMate_excluded_regions_list, region) >= 0 +endfunction "}}} + +function! delimitMate#FlushBuffer() " {{{ + let b:_l_delimitMate_buffer = [] + return '' +endfunction " }}} + +function! delimitMate#BalancedParens(char) "{{{ + " Returns: + " = 0 => Parens balanced. + " > 0 => More opening parens. + " < 0 => More closing parens. + + let line = getline('.') + let col = col('.') - 2 + let col = col >= 0 ? col : 0 + let list = split(line, '\zs') + let left = b:_l_delimitMate_left_delims[index(b:_l_delimitMate_right_delims, a:char)] + let right = a:char + let opening = 0 + let closing = 0 + + " If the cursor is not at the beginning, count what's behind it. + if col > 0 + " Find the first opening paren: + let start = index(list, left) + " Must be before cursor: + let start = start < col ? start : col - 1 + " Now count from the first opening until the cursor, this will prevent + " extra closing parens from being counted. + let opening = count(list[start : col - 1], left) + let closing = count(list[start : col - 1], right) + " I don't care if there are more closing parens than opening parens. + let closing = closing > opening ? opening : closing + endif + + " Evaluate parens from the cursor to the end: + let opening += count(list[col :], left) + let closing += count(list[col :], right) + + "echom "–––––––––" + "echom line + "echom col + ""echom left.":".a:char + "echom string(list) + "echom string(list[start : col - 1]) . " : " . string(list[col :]) + "echom opening . " - " . closing . " = " . (opening - closing) + + " Return the found balance: + return opening - closing +endfunction "}}} + +" }}} + +" Doers {{{ +function! delimitMate#SkipDelim(char) "{{{ + if delimitMate#IsForbidden(a:char) + return a:char + endif + let col = col('.') - 1 + let line = getline('.') + if col > 0 + let cur = line[col] + let pre = line[col-1] + else + let cur = line[col] + let pre = "" + endif + if pre == "\\" + " Escaped character + return a:char + elseif cur == a:char + " Exit pair + "return delimitMate#WriteBefore(a:char) + return a:char . delimitMate#Del() + elseif delimitMate#IsEmptyPair( pre . a:char ) + " Add closing delimiter and jump back to the middle. + call insert(b:_l_delimitMate_buffer, a:char) + return delimitMate#WriteAfter(a:char) + else + " Nothing special here, return the same character. + return a:char + endif +endfunction "}}} + +function! delimitMate#ParenDelim(char) " {{{ + if delimitMate#IsForbidden(a:char) + return '' + endif + " Try to balance matchpairs + if b:_l_delimitMate_balance_matchpairs && + \ delimitMate#BalancedParens(a:char) <= 0 + return '' + endif + let line = getline('.') + let col = col('.')-2 + if b:_l_delimitMate_smart_matchpairs && + \ line[col+1] =~ '\S' + return '' + elseif (col) < 0 + call setline('.',a:char.line) + call insert(b:_l_delimitMate_buffer, a:char) + else + "echom string(col).':'.line[:(col)].'|'.line[(col+1):] + call setline('.',line[:(col)].a:char.line[(col+1):]) + call insert(b:_l_delimitMate_buffer, a:char) + endif + return '' +endfunction " }}} + +function! delimitMate#QuoteDelim(char) "{{{ + if delimitMate#IsForbidden(a:char) + return a:char + endif + let line = getline('.') + let col = col('.') - 2 + if line[col] == "\\" + " Seems like a escaped character, insert one quotation mark. + return a:char + elseif line[col + 1] == a:char && + \ index(b:_l_delimitMate_nesting_quotes, a:char) < 0 + " Get out of the string. + return a:char . delimitMate#Del() + elseif (line[col] =~ '\w' && a:char == "'") || + \ (b:_l_delimitMate_smart_quotes && + \ (line[col] =~ '\w' || + \ line[col + 1] =~ '\w')) + " Seems like an apostrophe or a smart quote case, insert a single quote. + return a:char + elseif (line[col] == a:char && line[col + 1 ] != a:char) && b:_l_delimitMate_smart_quotes + " Seems like we have an unbalanced quote, insert one quotation mark and jump to the middle. + call insert(b:_l_delimitMate_buffer, a:char) + return delimitMate#WriteAfter(a:char) + else + " Insert a pair and jump to the middle. + call insert(b:_l_delimitMate_buffer, a:char) + call delimitMate#WriteAfter(a:char) + return a:char + endif +endfunction "}}} + +function! delimitMate#JumpOut(char) "{{{ + if delimitMate#IsForbidden(a:char) + return a:char + endif + let line = getline('.') + let col = col('.')-2 + if line[col+1] == a:char + return a:char . delimitMate#Del() + else + return a:char + endif +endfunction " }}} + +function! delimitMate#JumpAny(key) " {{{ + if delimitMate#IsForbidden('') + return a:key + endif + if !delimitMate#ShouldJump() + return a:key + endif + " Let's get the character on the right. + let char = getline('.')[col('.')-1] + if char == " " + " Space expansion. + "let char = char . getline('.')[col('.')] . delimitMate#Del() + return char . getline('.')[col('.')] . delimitMate#Del() . delimitMate#Del() + "call delimitMate#RmBuffer(1) + elseif char == "" + " CR expansion. + "let char = "\" . getline(line('.') + 1)[0] . "\" + let b:_l_delimitMate_buffer = [] + return "\" . getline(line('.') + 1)[0] . "\" + else + "call delimitMate#RmBuffer(1) + return char . delimitMate#Del() + endif +endfunction " delimitMate#JumpAny() }}} + +function! delimitMate#MapMsg(msg) "{{{ + redraw + echomsg a:msg + return "" +endfunction "}}} + +function! delimitMate#ExpandReturn() "{{{ + if delimitMate#IsForbidden("") + return "\" + endif + if delimitMate#WithinEmptyPair() + " Expand: + call delimitMate#FlushBuffer() + "return "\a\x\\k$\"_xa" + return "\\\o" + else + return "\" + endif +endfunction "}}} + +function! delimitMate#ExpandSpace() "{{{ + if delimitMate#IsForbidden("\") + return "\" + endif + if delimitMate#WithinEmptyPair() + " Expand: + call insert(b:_l_delimitMate_buffer, 's') + return delimitMate#WriteAfter(' ') . "\" + else + return "\" + endif +endfunction "}}} + +function! delimitMate#BS() " {{{ + if delimitMate#IsForbidden("") + return "\" + endif + if delimitMate#WithinEmptyPair() + "call delimitMate#RmBuffer(1) + return "\" . delimitMate#Del() +" return "\\\" + elseif delimitMate#IsSpaceExpansion() + "call delimitMate#RmBuffer(1) + return "\" . delimitMate#Del() + elseif delimitMate#IsCRExpansion() + return "\\" + else + return "\" + endif +endfunction " }}} delimitMate#BS() + +function! delimitMate#Del() " {{{ + if len(b:_l_delimitMate_buffer) > 0 + let line = getline('.') + let col = col('.') - 2 + call delimitMate#RmBuffer(1) + call setline('.', line[:col] . line[col+2:]) + return '' + else + return "\" + endif +endfunction " }}} + +function! delimitMate#Finish() " {{{ + let len = len(b:_l_delimitMate_buffer) + if len > 0 + let buffer = join(b:_l_delimitMate_buffer, '') + let len2 = len(buffer) + " Reset buffer: + let b:_l_delimitMate_buffer = [] + let line = getline('.') + let col = col('.') -2 + "echom 'col: ' . col . '-' . line[:col] . "|" . line[col+len+1:] . '%' . buffer + if col < 0 + call setline('.', line[col+len2+1:]) + else + call setline('.', line[:col] . line[col+len2+1:]) + endif + let i = 1 + let lefts = "\" + while i < len + let lefts = lefts . "\" + let i += 1 + endwhile + return substitute(buffer, "s", "\", 'g') . lefts + endif + return '' +endfunction " }}} + +function! delimitMate#RmBuffer(num) " {{{ + if len(b:_l_delimitMate_buffer) > 0 + call remove(b:_l_delimitMate_buffer, 0, (a:num-1)) + endif + return "" +endfunction " }}} + +" }}} + +" Tools: {{{ +function! delimitMate#TestMappings() "{{{ + let options = sort(keys(delimitMate#OptionsList())) + let optoutput = ['delimitMate Report', '==================', '', '* Options: (-) unset, (g) global, (b) buffer',''] + for option in options + exec 'call add(optoutput, ''('.(exists('b:delimitMate_'.option) ? 'b' : exists('g:delimitMate_'.option) ? 'g' : '-').') delimitMate_''.option.'' = ''.string(b:_l_delimitMate_'.option.'))' + endfor + call append(line('$'), optoutput + ['--------------------','']) + + " Check if mappings were set. {{{ + let imaps = b:_l_delimitMate_right_delims + let imaps = imaps + ( b:_l_delimitMate_autoclose ? b:_l_delimitMate_left_delims : [] ) + let imaps = imaps + + \ b:_l_delimitMate_quotes_list + + \ b:_l_delimitMate_apostrophes_list + + \ ['', '', '', '', ''] + + \ ['', '', '', '', '', ''] + + \ ['', '', '', '', '', ''] + let imaps = imaps + ( b:_l_delimitMate_expand_cr ? [''] : [] ) + let imaps = imaps + ( b:_l_delimitMate_expand_space ? [''] : [] ) + + let vmaps = + \ b:_l_delimitMate_right_delims + + \ b:_l_delimitMate_left_delims + + \ b:_l_delimitMate_quotes_list + + let ibroken = [] + for map in imaps + if maparg(map, "i") !~? 'delimitMate' + let output = '' + if map == '|' + let map = '' + endif + redir => output | execute "verbose imap ".map | redir END + let ibroken = ibroken + [map.": is not set:"] + split(output, '\n') + endif + endfor + + unlet! output + if ibroken == [] + let output = ['* Mappings:', '', 'All mappings were set-up.', '--------------------', '', ''] + else + let output = ['* Mappings:', ''] + ibroken + ['--------------------', ''] + endif + call append('$', output+['* Showcase:', '']) + " }}} + if b:_l_delimitMate_autoclose + " {{{ + for i in range(len(b:_l_delimitMate_left_delims)) + exec "normal GGoOpen: " . b:_l_delimitMate_left_delims[i]. "|" + exec "normal oDelete: " . b:_l_delimitMate_left_delims[i] . "\|" + exec "normal oExit: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . "|" + exec "normal oSpace: " . b:_l_delimitMate_left_delims[i] . " |" + exec "normal oDelete space: " . b:_l_delimitMate_left_delims[i] . " \|" + exec "normal oCar return: " . b:_l_delimitMate_left_delims[i] . "\|" + exec "normal GGoDelete car return: " . b:_l_delimitMate_left_delims[i] . "\\|\GG\o" + endfor + for i in range(len(b:_l_delimitMate_quotes_list)) + exec "normal GGAOpen: " . b:_l_delimitMate_quotes_list[i] . "|" + exec "normal oDelete: " . b:_l_delimitMate_quotes_list[i] . "\|" + exec "normal oExit: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "|" + exec "normal oSpace: " . b:_l_delimitMate_quotes_list[i] . " |" + exec "normal oDelete space: " . b:_l_delimitMate_quotes_list[i] . " \|" + exec "normal oCar return: " . b:_l_delimitMate_quotes_list[i] . "\|" + exec "normal GGoDelete car return: " . b:_l_delimitMate_quotes_list[i] . "\\|\GG\o" + endfor + "}}} + else + "{{{ + for i in range(len(b:_l_delimitMate_left_delims)) + exec "normal GGoOpen & close: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . "|" + exec "normal oDelete: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . "\|" + exec "normal oExit: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . b:_l_delimitMate_right_delims[i] . "|" + exec "normal oSpace: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . " |" + exec "normal oDelete space: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . " \|" + exec "normal oCar return: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . "\|" + exec "normal GGoDelete car return: " . b:_l_delimitMate_left_delims[i] . b:_l_delimitMate_right_delims[i] . "\\|\GG\o" + endfor + for i in range(len(b:_l_delimitMate_quotes_list)) + exec "normal GGoOpen & close: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "|" + exec "normal oDelete: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "\|" + exec "normal oExit: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "|" + exec "normal oSpace: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . " |" + exec "normal oDelete space: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . " \|" + exec "normal oCar return: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "\|" + exec "normal GGoDelete car return: " . b:_l_delimitMate_quotes_list[i] . b:_l_delimitMate_quotes_list[i] . "\\|\GG\o" + endfor + endif "}}} +endfunction "}}} + +function! delimitMate#OptionsList() "{{{ + return {'autoclose' : 1,'matchpairs': &matchpairs, 'quotes' : '" '' `', 'nesting_quotes' : [], 'expand_cr' : 0, 'expand_space' : 0, 'smart_quotes' : 1, 'smart_matchpairs' : 1, 'balance_matchpairs' : 0, 'excluded_regions' : 'Comment', 'excluded_ft' : '', 'apostrophes' : ''} +endfunction " delimitMate#OptionsList }}} +"}}} + +" vim:foldmethod=marker:foldcolumn=4 diff --git a/.vim/bundle/delimitMate/autoload/delimitMateTests.vim b/.vim/bundle/delimitMate/autoload/delimitMateTests.vim new file mode 100644 index 0000000..c8a0dc6 --- /dev/null +++ b/.vim/bundle/delimitMate/autoload/delimitMateTests.vim @@ -0,0 +1,260 @@ +function! delimitMateTests#Main() + if !exists("g:delimitMate_testing") + echoerr "delimitMateTests#Main(): If you really want to use me, you must set delimitMate_testing to any value." + return + elseif g:delimitMate_testing == "fork" + !gvim -N -u NONE -U NONE -c "set backspace=eol,start" -c "set background=light" -c "syntax on" -c "let delimitMate_testing = 1" -c "so autoload/delimitMate.vim" -c "so autoload/delimitMateTests.vim" -c "so plugin/delimitMate.vim" -c "call delimitMateTests\#Main()" + return "" + endif + nmap :qall! + let nomore = &more + set nomore + let b:test_results = {} + let b:errors = 0 + let b:corrects = 0 + let b:ignores = 0 + + function! SetOptions(list) " {{{ + let b:delimitMate_autoclose = 1 + let b:delimitMate_matchpairs = &matchpairs + let b:delimitMate_quotes = "\" ' `" + let b:delimitMate_excluded_regions = "Comment" + let b:delimitMate_expand_space = 0 + let b:delimitMate_expand_cr = 0 + let b:delimitMate_smart_quotes = 1 + let b:delimitMate_apostrophes = "" + let b:delimitMate_tab2exit = 1 + " Set current test options: + for str in a:list + "echom '1:'.str + let op = strpart(str, 0, stridx(str,':')) + "echom op + let val = strpart(str, stridx(str, ':' ) + 1) + "echom val + exec "let b:delimitMate_" . op . " = " . val + endfor + DelimitMateReload + endfunction " }}} + + function! Type(name, input, output, options, ...) " {{{ + if a:0 > 0 + let ignore = a:1 + else + let ignore = 0 + endif + if a:input != "\." + " Set default options: + call SetOptions(a:options) + let CapR = "" + normal ggVG"_d + exec "normal i" . a:input . "|\" + else + let CapR = "_R" + normal gg. + endif + + exec "normal \" + call setpos('.', [0, 1, 1, 0]) + let result = len(a:output) != line('$') + for line in a:output + if getline('.') != line || result == 1 + let result = 1 + break + endif + call setpos('.', [0, line('.') + 1, 1, 0]) + endfor + let text = getline('.') + let i = 2 + while i <= line('$') + let text = text . "" . getline(i) + let i += 1 + endwhile + if ignore == 1 + let label = "Ignored" + let result = "?=" + let b:ignores += 1 + elseif result == 0 + let label = "Passed" + let result = "==" + let b:corrects += 1 + else + let label = "Failed" + let result = "!=" + let b:errors += 1 + endif + exec "let b:test_results['" . + \ substitute(a:name, "[^a-zA-Z0-9_]", "_", "g") . CapR . "'] = '" . + \ label . ": ' . a:input . ' => ' . text . ' " . + \ result . " ' . join(a:output, '')" + endfunction " }}} + + function! RepeatLast(name, output, ...) " {{{ + if a:0 > 0 + let arg1 = a:1 + else + let arg1 = '' + endif + call Type(a:name, "\.", a:output, [], arg1) + endfunction " }}} + + " Test's test {{{ + call Type("Test 1", "123", ["123|"], []) + call RepeatLast("Test 1", ["123|123|"]) + + " Auto-closing parens + call Type("Autoclose parens", "(", ["(|)"], []) + call RepeatLast("Autoclose_parens", ["(|)(|)"]) + + " Auto-closing quotes + call Type("Autoclose quotes", '"', ['"|"'], []) + call RepeatLast("Autoclose_quotes", ['"|""|"']) + + " Deleting parens + call Type("Delete empty parens", "(\", ["|"], []) + call RepeatLast("Delete empty parens", ["||"]) + + " Deleting quotes + call Type("Delete emtpy quotes", "\"\", ['|'], []) + call RepeatLast("Delete empty quotes", ["||"]) + + " Manual closing parens + call Type("Manual closing parens", "()", ["(|)"], ["autoclose:0"]) + call RepeatLast("Manual closing parens", ["(|)(|)"]) + + " Manual closing quotes + call Type("Manual closing quotes", "\"\"", ['"|"'], ["autoclose:0"]) + call RepeatLast("Manual closing quotes", ['"|""|"']) + + " Jump over paren + call Type("Jump over paren", "()", ['()|'], []) + call RepeatLast("Jump over paren", ['()|()|']) + + " Jump over quote + call Type("Jump over quote", "\"\"", ['""|'], []) + call RepeatLast("Jump over quote", ['""|""|']) + + " Apostrophe + call Type("Apostrophe", "test'", ["test'|"], []) + call RepeatLast("Apostrophe", ["test'|test'|"]) + + " Close quote + call Type("Close quote", "'\\a'", ["'|'"], []) + + " Closing paren + call Type("Closing paren", "abcd)", ["abcd)|"], []) + + " + call Type("S Tab", "(\", ["()|"], []) + call RepeatLast("S Tab", ["()|()|"]) + + " Space expansion + call Type("Space expansion", "(\\", ['(|)'], ['expand_space:1']) + call RepeatLast("BS with space expansion", ['(|)(|)']) + + " BS with space expansion + call Type("BS with space expansion", "(\", ['( | )'], ['expand_space:1']) + call RepeatLast("Space expansion", ['( | )( | )']) + + " Car return expansion + call Type("CR expansion", "(\", ['(', '|', ')'], ['expand_cr:1']) + call RepeatLast("CR expansion", ['(', '|', ')(', '|', ')'], 1) + + " BS with car return expansion + call Type("BS with CR expansion", "(\\", ['(|)'], ['expand_cr:1']) + call RepeatLast("BS with CR expansion", ['(|)(|)'], 1) + + " Smart quotes + call Type("Smart quote alphanumeric", "a\"4", ['a"4|'], []) + call RepeatLast("Smart quote alphanumeric", ['a"4|a"4|']) + + " Smart quotes + call Type("Smart quote escaped", "esc\\\"", ['esc\"|'], []) + call RepeatLast("Smart quote escaped", ['esc\"|esc\"|']) + + " Smart quotes + call Type("Smart quote apostrophe", "I'm", ["I'm|"], ['smart_quotes:0']) + call RepeatLast("Smart quote escaped", ["I'm|I'm|"]) + + " Backspace inside space expansion + call Type("Backspace inside space expansion", "(\\", ['(|)'], ['expand_space:1']) + call RepeatLast("Backspace inside space expansion", ['(|)(|)']) + + " inserts text + call Type(" inserts text", "(he\\th\\", ['(he) th|'], []) + + " Backspace inside CR expansion + call Type("Backspace inside CR expansion", "(\\", ['(|)'], ['expand_cr:1']) + call RepeatLast("Backspace inside CR expansion", ['(|)(|)'], 1) + + " FileType event + let g:delimitMate_excluded_ft = "vim" + set ft=vim + call Type("FileType Autoclose parens", "(", ["(|"], []) + unlet g:delimitMate_excluded_ft + set ft= + + " Duplicated delimiter after CR + call Type("Duplicated delimiter after CR", "(\", ['(', '|)'], []) + + " Deactivate on comments: The first call to a closing delimiter + " will not work here as expected, but it does in real life tests. + set ft=vim + call Type("Deactivate on comments", "\"()``[]''\"\"", ["\"()``[]''\"\"|"], ["autoclose:0"], 1) + set ft= + + " Deactivate parens on comments: The first call to a closing delimiter + " will not work here as expected, but it does in real life tests. + set ft=vim + call Type("Deactivate parens on comments", "\"()[]", ["\"()[]|"], ["autoclose:0"], 1) + set ft= + + " Deactivate quotes on comments: See previous note. + set ft=vim + call Type("Deactivate parens on comments", "\"(`", ["\"(``|"], [], 1) + set ft= + + " Manual close at start of line + call Type("Manual close at start of line", "m)\\)", [')|m)'], ["autoclose:0"]) + + " Use | in quotes + call Type("Use in quotes", "\bars", ['|bars|'], ["quotes:'|'"]) + + " Use | in matchpairs + call Type("Use in matchpairs", "\bars", ['|bars|$$'], ["matchpairs:'|:$'"]) + + "}}} + + " Show results: {{{ + normal ggVG"_d + call append(0, split(string(b:test_results)[1:-2], ', ')) + call append(0, "*TESTS REPORT: " . b:errors . " failed, " . b:corrects . " passed and " . b:ignores . " ignored.") + normal "_ddgg + let @/ = ".\\+Failed:.*!=" + 2,$sort /^.\+':/ + normal gg + exec search('Ignored:','nW').",$sort! /^.\\+':/" + set nohlsearch + syn match lineIgnored ".*Ignored.*" + syn match labelPassed "'\@<=.\+\(': 'Passed\)\@=" + syn match labelFailed "'\@<=.\+\(': 'Failed\)\@=" + syn match resultPassed "\('Passed: \)\@<=.\+\('$\)\@=" + syn match resultFailed "\('Failed: \)\@<=.\+\('$\)\@=" contains=resultInequal + syn match resultIgnored "\('Ignored: \)\@<=.\+\('$\)\@=" + syn match resultInequal "!=" + syn match resultSummary "^\*.\+" contains=resultSummaryNumber + syn match resultSummaryNumber "[1-9][0-9]* failed*" contained + + hi def link lineIgnored Ignore + hi def link labelPassed Comment + hi def link labelFailed Special + hi def link resultPassed Ignore + hi def link resultFailed Boolean + hi def link resultInequal Error + hi def link resultSummary SpecialComment + hi def link resultSummaryNumber Error + " }}} + + let &more = nomore +endfunction +" vim:foldmethod=marker:foldcolumn=4 + diff --git a/.vim/bundle/delimitMate/doc/delimitMate.txt b/.vim/bundle/delimitMate/doc/delimitMate.txt new file mode 100644 index 0000000..eddc253 --- /dev/null +++ b/.vim/bundle/delimitMate/doc/delimitMate.txt @@ -0,0 +1,761 @@ +*delimitMate.txt* Trying to keep those beasts at bay! v2.5.1 *delimitMate* + + + + MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMMMM MMMMMMMMMMMMMMMMMMMMM ~ + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMM MMMMMMMMMMMMMMMMMMMMM + MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMM MMM M M MMMMMMMMMM MMMMMMMMM ~ + MMMM MMM MMM MM MM M M MMM MM MM MM MM MMM MMM MMM MM + MM MM M MM MMMMMM MMMMMMM MMM MMMMM MM M MMM MMM M M ~ + M M MM MM MM MM M M MM MMM MMM MMMMM MMMMM MMM MMM M + M M MM MMMMM MM MM M M MM MMM MMM MMMMM MMM MMM MMM MMMM ~ + M M MM M MM MM MM M M MM MMM MMM MMMMM MM M MMM MMM M M + MM MMM MMM MM MM M M MM MMM MM MMMMM MMM MMM MMM MM ~ + MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + + + +============================================================================== + 0.- CONTENTS *delimitMate-contents* + + 1. Introduction____________________________|delimitMateIntro| + 2. Customization___________________________|delimitMateOptions| + 2.1 Options summary____________________|delimitMateOptionSummary| + 2.2 Options details____________________|delimitMateOptionDetails| + 3. Functionality___________________________|delimitMateFunctionality| + 3.1 Automatic closing & exiting________|delimitMateAutoClose| + 3.2 Expansion of space and CR__________|delimitMateExpansion| + 3.3 Backspace__________________________|delimitMateBackspace| + 3.4 Smart Quotes_______________________|delimitMateSmartQuotes| + 3.5 Balancing matching pairs___________|delimitMateBalance| + 3.6 FileType based configuration_______|delimitMateFileType| + 3.7 Syntax awareness___________________|delimitMateSyntax| + 4. Commands________________________________|delimitMateCommands| + 5. Mappings________________________________|delimitMateMappings| + 6. Functions_______________________________|delimitMateFunctions| + 7. TODO list_______________________________|delimitMateTodo| + 8. Maintainer______________________________|delimitMateMaintainer| + 9. Credits_________________________________|delimitMateCredits| + 10. History_________________________________|delimitMateHistory| + +============================================================================== + 1.- INTRODUCTION *delimitMateIntro* + +This plug-in provides automatic closing of quotes, parenthesis, brackets, +etc.; besides some other related features that should make your time in insert +mode a little bit easier. + +Most of the features can be modified or disabled permanently, using global +variables, or on a FileType basis, using autocommands. With a couple of +exceptions and limitations, this features don't brake undo, redo or history. + +NOTE 1: If you have any trouble with this plugin, please run |:DelimitMateTest| +in a new buffer to see what is not working. + +NOTE 2: |'timeout'| needs to be set when working in the terminal, otherwise you +might find weird behaviour with mappings including or arrow keys. + +NOTE 3: Abbreiations set with |:iabbrev| will not be expanded by delimiters +used on delimitMate, you should use (read |i_CTRL-]|) to expand them on +the go. + +============================================================================== + 2. CUSTOMIZATION *delimitMateOptions* + +You can create your own mappings for some features using the global functions. +Read |DelimitMateFunctions| for more info. + +------------------------------------------------------------------------------ + 2.1 OPTIONS SUMMARY *delimitMateOptionSummary* + +The behaviour of this script can be customized setting the following options +in your vimrc file. You can use local options to set the configuration for +specific file types, see |delimitMateOptionDetails| for examples. + +|'loaded_delimitMate'| Turns off the script. + +|'delimitMate_autoclose'| Tells delimitMate whether to automagically + insert the closing delimiter. + +|'delimitMate_matchpairs'| Tells delimitMate which characters are + matching pairs. + +|'delimitMate_quotes'| Tells delimitMate which quotes should be + used. + +|'delimitMate_nesting_quotes'| Tells delimitMate which quotes should be + allowed to be nested. + +|'delimitMate_expand_cr'| Turns on/off the expansion of . + +|'delimitMate_expand_space'| Turns on/off the expansion of . + +|'delimitMate_smart_quotes'| Turns on/off the "smart quotes" feature. + +|'delimitMate_balance_matchpairs'|Turns on/off the "balance matching pairs" + feature. + +|'delimitMate_excluded_regions'| Turns off the script for the given regions or + syntax group names. + +|'delimitMate_excluded_ft'| Turns off the script for the given file types. + +|'delimitMate_apostrophes'| Tells delimitMate how it should "fix" + balancing of single quotes when used as + apostrophes. NOTE: Not needed any more, kept + for compatibility with older versions. + +------------------------------------------------------------------------------ + 2.2 OPTIONS DETAILS *delimitMateOptionDetails* + +Add the shown lines to your vimrc file in order to set the below options. +Buffer variables take precedence over global ones and can be used along with +autocmd to modify delimitMate's behavior for specific file types, read more in +|delimitMateFileType|. + +Note: Use buffer variables only to set options for specific file types using +:autocmd, use global variables to set options for every buffer. Read more in +|g:var| and |b:var|. + +------------------------------------------------------------------------------ + *'loaded_delimitMate'* + *'b:loaded_delimitMate'* +This option prevents delimitMate from loading. +e.g.: > + let loaded_delimitMate = 1 + au FileType mail let b:loaded_delimitMate = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_autoclose'* + *'b:delimitMate_autoclose'* +Values: 0 or 1. ~ +Default: 1 ~ + +If this option is set to 0, delimitMate will not add a closing delimiter +automagically. See |delimitMateAutoClose| for details. +e.g.: > + let delimitMate_autoclose = 0 + au FileType mail let b:delimitMate_autoclose = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_matchpairs'* + *'b:delimitMate_matchpairs'* +Values: A string with |'matchpairs'| syntax, plus support for multi-byte~ + characters.~ +Default: &matchpairs ~ + +Use this option to tell delimitMate which characters should be considered +matching pairs. Read |delimitMateAutoClose| for details. +e.g: > + let delimitMate_matchpairs = "(:),[:],{:},<:>" + au FileType vim,html let b:delimitMate_matchpairs = "(:),[:],{:},<:>" +< +------------------------------------------------------------------------------ + *'delimitMate_quotes'* + *'b:delimitMate_quotes'* +Values: A string of characters separated by spaces. ~ +Default: "\" ' `" ~ + +Use this option to tell delimitMate which characters should be considered as +quotes. Read |delimitMateAutoClose| for details. +e.g.: > + let delimitMate_quotes = "\" ' ` *" + au FileType html let b:delimitMate_quotes = "\" '" +< +------------------------------------------------------------------------------ + *'delimitMate_nesting_quotes'* + *'b:delimitMate_nesting_quotes'* +Values: A list of quotes. ~ +Default: [] ~ + +Quotes listed here will not be able to jump out of the empty pair, thus +allowing the autoclosed quotes to be nested. +e.g.: > + let delimitMate_nesting_quotes = ['"','`'] + au FileType python let b:delimitMate_nesting_quotes = ['"'] +< +------------------------------------------------------------------------------ + *'delimitMate_expand_cr'* + *'b:delimitMate_expand_cr'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. NOTE This feature requires that 'backspace' is either set to 2 or +has "eol" and "start" as part of its value. +e.g.: > + let delimitMate_expand_cr = 1 + au FileType mail let b:delimitMate_expand_cr = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_expand_space'* + *'b:delimitMate_expand_space'* +Values: 1 or 0 ~ +Default: 0 ~ +This option turns on/off the expansion of . Read |delimitMateExpansion| +for details. +e.g.: > + let delimitMate_expand_space = 1 + au FileType tcl let b:delimitMate_expand_space = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_smart_quotes'* + *'b:delimitMate_smart_quotes'* +Values: 1 or 0 ~ +Default: 1 ~ + +This option turns on/off the smart quotes feature. Read +|delimitMateSmartQuotes| for details. +e.g.: > + let delimitMate_smart_quotes = 0 + au FileType tcl let b:delimitMate_smart_quotes = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_balance_matchpairs'* + *'b:delimitMate_balance_matchpairs'* +Values: 1 or 0 ~ +Default: 0 ~ + +This option turns on/off the balancing of matching pairs. Read +|delimitMateBalance| for details. +e.g.: > + let delimitMate_balance_matchpairs = 1 + au FileType tcl let b:delimitMate_balance_matchpairs = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_excluded_regions'* +Values: A string of syntax group names names separated by single commas. ~ +Default: Comment ~ + +This options turns delimitMate off for the listed regions, read |group-name| +for more info about what is a region. +e.g.: > + let delimitMate_excluded_regions = "Comments,String" +< +------------------------------------------------------------------------------ + *'delimitMate_excluded_ft'* +Values: A string of file type names separated by single commas. ~ +Default: Empty. ~ + +This options turns delimitMate off for the listed file types, use this option +only if you don't want any of the features it provides on those file types. +e.g.: > + let delimitMate_excluded_ft = "mail,txt" +< +------------------------------------------------------------------------------ + *'delimitMate_apostrophes'* +Values: Strings separated by ":". ~ +Default: No longer used. ~ + +NOTE: This feature is turned off by default, it's been kept for compatibility +with older version, read |delimitMateSmartQuotes| for details. +If auto-close is enabled, this option tells delimitMate how to try to fix the +balancing of single quotes when used as apostrophes. The values of this option +are strings of text where a single quote would be used as an apostrophe (e.g.: +the "n't" of wouldn't or can't) separated by ":". Set it to an empty string to +disable this feature. +e.g.: > + let delimitMate_apostrophes = "" + au FileType tcl let delimitMate_apostrophes = "" +< +============================================================================== + 3. FUNCTIONALITY *delimitMateFunctionality* + +------------------------------------------------------------------------------ + 3.1 AUTOMATIC CLOSING AND EXITING *delimitMateAutoClose* + +With automatic closing enabled, if an opening delimiter is inserted the plugin +inserts the closing delimiter and places the cursor between the pair. With +automatic closing disabled, no closing delimiters is inserted by delimitMate, +but when a pair of delimiters is typed, the cursor is placed in the middle. + +When the cursor is inside an empty pair or located next to the left of a +closing delimiter, the cursor is placed outside the pair to the right of the +closing delimiter. + +Unless |'delimitMate_matchpairs'| or |'delimitMate_quotes'|are set, this +script uses the values in '&matchpairs' to identify the pairs, and ", ' and ` +for quotes respectively. + +The following table shows the behaviour, this applies to quotes too (the final +position of the cursor is represented by a "|"): + +With auto-close: > + Type | You get + ==================== + ( | (|) + –––––––––|–––––––––– + () | ()| + –––––––––|–––––––––– + ( | ()| +< +Without auto-close: > + + Type | You get + ===================== + () | (|) + –––––––––-|–––––––––– + ()) | ()| + –––––––––-|–––––––––– + () | ()| +< +NOTE: Abbreviations will not be expanded by delimiters used on delimitMate, +you should use (read |i_CTRL-]|) to expand them on the go. + +------------------------------------------------------------------------------ + 3.2 EXPANSION OF SPACE AND CAR RETURN *delimitMateExpansion* + +When the cursor is inside an empty pair of delimiters, and can be +expanded, see |'delimitMate_expand_space'| and +|'delimitMate_expand_cr'|: + +Expand to: > + + | You get + ==================================== + (|) | ( | ) +< +Expand to: > + + | You get + ============================ + (|) | ( + | | + | ) +< + +NOTE that the expansion of will brake the redo command. + +Since and are used everywhere, I have made the functions involved +in expansions global, so they can be used to make custom mappings. Read +|delimitMateFunctions| for more details. + +------------------------------------------------------------------------------ + 3.3 BACKSPACE *delimitMateBackspace* + +If you press backspace inside an empty pair, both delimiters are deleted. When +expansions are enabled, will also delete the expansions. NOTE that +deleting expansions will brake the redo command. + +If you type (shift + backspace) instead, only the closing delimiter +will be deleted. NOTE that this will not usually work when using Vim from the +terminal, see 'delimitMate#JumpAny()' below to see how to fix it. + +e.g. typing at the "|": > + + What | Before | After + ============================================== + | call expand(|) | call expand| + ---------|-------------------|----------------- + | call expand( | ) | call expand(|) + ---------|-------------------|----------------- + | call expand( | call expand(|) + | | | + | ) | + ---------|-------------------|----------------- + | call expand(|) | call expand(| +< + +------------------------------------------------------------------------------ + 3.4 SMART QUOTES *delimitMateSmartQuotes* + +Only one quote will be inserted following a quote, a "\" or, following or +preceding an alphanumeric character. This should cover closing quotes after a +string, opening quotes before a string, escaped quotes and apostrophes. Except +for apostrophes, this feature can be disabled setting the option +|'delimitMate_smart_quotes'| to 0. + +e.g. typing at the "|": > + + What | Before | After + ======================================= + " | Text | | Text "|" + " | "String| | "String"| + " | let i = "| | let i = "|" + 'm | I| | I'm| +< +------------------------------------------------------------------------------ + 3.5 BALANCING MATCHING PAIRS *delimitMateBalance* + +When inserting an opening paren and |'delimitMate_balance_matchpairs'| is +enabled, delimitMate will try to balance the closing pairs in the current +line. + +e.g. typing at the "|": > + + What | Before | After + ======================================= + ( | |) | (|) + ( | | | (|) + ( | (|) | ((|)) +< +------------------------------------------------------------------------------ + 3.6 FILE TYPE BASED CONFIGURATION *delimitMateFileType* + +delimitMate options can be set globally for all buffers using global +("regular") variables in your |vimrc| file. But |:autocmd| can be used to set +options for specific file types (see |'filetype'|) using buffer variables in +the following way: > + + au FileType mail,text let b:delimitMate_autoclose = 0 + ^ ^ ^ ^ ^ + | | | | | + | | | | - Option value. + | | | - Option name. + | | - Buffer variable. + | - File types for which the option will be set. + - Don't forget to put this event. +< +NOTE that you should use buffer variables (|b:var|) only to set options with +|:autocmd|, for global options use regular variables (|g:var|) in your vimrc. + +------------------------------------------------------------------------------ + 3.7 SYNTAX AWARENESS *delimitMateSyntax* + +The features of this plug-in might not be always helpful, comments and strings +usualy don't need auto-completion. delimitMate monitors which region is being +edited and if it detects that the cursor is in a comment it'll turn itself off +until the cursor leaves the comment. The excluded regions can be set using the +option |'delimitMate_excluded_regions'|. Read |group-name| for a list of +regions or syntax group names. + +NOTE that this feature relies on a proper syntax file for the current file +type, if the appropiate syntax file doesn't define a region, delimitMate won't +know about it. + +============================================================================== + 4. COMMANDS *delimitMateCommands* + +------------------------------------------------------------------------------ +:DelimitMateReload *:DelimitMateReload* + +Re-sets all the mappings used for this script, use it if any option has been +changed or if the filetype option hasn't been set yet. + +------------------------------------------------------------------------------ +:DelimitMateSwitch *:DelimitMateSwitch* + +Switches the plug-in on and off. + +------------------------------------------------------------------------------ +:DelimitMateTest *:DelimitMateTest* + +This command tests every mapping set-up for this script, useful for testing +custom configurations. + +The following output corresponds to the default values, it will be different +depending on your configuration. "Open & close:" represents the final result +when the closing delimiter has been inserted, either manually or +automatically, see |delimitMateExpansion|. "Delete:" typing backspace in an +empty pair, see |delimitMateBackspace|. "Exit:" typing a closing delimiter +inside a pair of delimiters, see |delimitMateAutoclose|. "Space:" the +expansion, if any, of space, see |delimitMateExpansion|. "Visual-L", +"Visual-R" and "Visual" shows visual wrapping, see +|delimitMateVisualWrapping|. "Car return:" the expansion of car return, see +|delimitMateExpansion|. The cursor's position at the end of every test is +represented by an "|": > + + * AUTOCLOSE: + Open & close: (|) + Delete: | + Exit: ()| + Space: ( |) + Visual-L: (v) + Visual-R: (v) + Car return: ( + |) + + Open & close: {|} + Delete: | + Exit: {}| + Space: { |} + Visual-L: {v} + Visual-R: {v} + Car return: { + |} + + Open & close: [|] + Delete: | + Exit: []| + Space: [ |] + Visual-L: [v] + Visual-R: [v] + Car return: [ + |] + + Open & close: "|" + Delete: | + Exit: ""| + Space: " |" + Visual: "v" + Car return: " + |" + + Open & close: '|' + Delete: | + Exit: ''| + Space: ' |' + Visual: 'v' + Car return: ' + |' + + Open & close: `|` + Delete: | + Exit: ``| + Space: ` |` + Visual: `v` + Car return: ` + |` +< + +============================================================================== + 5. MAPPINGS *delimitMateMappings* + +delimitMate doesn't override any existing map, so you may encounter that it +doesn't work as expected because a mapping is missing. In that case, the +conflicting mappings should be resolved by either disabling the conflicting +mapping or creating a custom mappings. + +In order to make custom mappings easier and prevent overwritting existing +ones, delimitMate uses the || + |hasmapto()| (|usr_41.txt|) construct +for its mappings. + +The following are the mappings alway set by delimitMate: + + is mapped to delimitMateBS + is mapped to delimitMateS-BS + is mapped to delimitMateS-Tab + is mapped to delimitMateDel + is mapped to delimitMateEsc + is mapped to delimitMateLeft + is mapped to delimitMateRight + is mapped to delimitMateHome + is mapped to delimitMateEnd + is mapped to delimitMateUp + is mapped to delimitMateDown + is mapped to delimitMatePageUp + is mapped to delimitMatePageDown + is mapped to delimitMateS-Down + is mapped to delimitMateS-Up + is mapped to delimitMateMLeftMouse + is mapped to delimitMateMRightMouse + +The rest of the mappings correspond to parens, quotes, CR, Space, etc. and they +depend on the values of the delimitMate options, they have the following form: + +delimitMate + char + +e.g.: for "(": + +( is mapped to delimitMate( + +e.g.: If you have expansion enabled, you might want to skip it on pop-up +menus: + + imap pumvisible() ? + \"\" : + \ "delimitMateCR" + + +============================================================================== + 6. FUNCTIONS *delimitMateFunctions* + +------------------------------------------------------------------------------ +delimitMate#WithinEmptyPair() *delimitMate_WithinEmptyPair()* + +Returns 1 if the cursor is inside an empty pair, 0 otherwise. +e.g.: > + + inoremap delimitMate#WithinEmptyPair() ? + \ "\=delimitMate#ExpandReturn()\" : + \ "external_mapping" +< + +------------------------------------------------------------------------------ +delimitMate#ShouldJump() *delimitMate#ShouldJump()* + +Returns 1 if there is a closing delimiter or a quote to the right of the +cursor, 0 otherwise. + +------------------------------------------------------------------------------ +delimitMate#JumpAny(key) *delimitMate#JumpAny()* + +This function returns a mapping that will make the cursor jump to the right +when delimitMate#ShouldJump() returns 1, returns the argument "key" otherwise. +e.g.: You can use this to create your own mapping to jump over any delimiter. +> + inoremap =delimitMate#JumpAny("\") +< + +============================================================================== + 7. TODO LIST *delimitMateTodo* + +- Automatic set-up by file type. +- Make block-wise visual wrapping work on un-even regions. + +============================================================================== + 8. MAINTAINER *delimitMateMaintainer* + +Hi there! My name is Israel Chauca F. and I can be reached at: + mailto:israelchauca@gmail.com + +Feel free to send me any suggestions and/or comments about this plugin, I'll +be very pleased to read them. + +============================================================================== + 9. CREDITS *delimitMateCredits* + +Some of the code that make this script is modified or just shamelessly copied +from the following sources: + + - Ian McCracken + Post titled: Vim, Part II: Matching Pairs: + http://concisionandconcinnity.blogspot.com/ + + - Aristotle Pagaltzis + From the comments on the previous blog post and from: + http://gist.github.com/144619 + + - Karl Guertin + AutoClose: + http://www.vim.org/scripts/script.php?script_id=1849 + + - Thiago Alves + AutoClose: + http://www.vim.org/scripts/script.php?script_id=2009 + + - Edoardo Vacchi + ClosePairs: + http://www.vim.org/scripts/script.php?script_id=2373 + +This script was inspired by the auto-completion of delimiters on TextMate. + +============================================================================== + 10. HISTORY *delimitMateHistory* + + Version Date Release notes ~ +|---------|------------|-----------------------------------------------------| + 2.5.1 2010-09-30 * Current release: + - Remove visual wrapping. Surround.vim offers a much + better implementation. + - Minor mods to DelimitMateTest. +|---------|------------|-----------------------------------------------------| + 2.5 2010-09-22 * - Better handling of mappings. + - Add report for mappings in |:DelimitMateTest|. + - Allow the use of "|" and multi-byte characters in + |'delimitMate_quotes'| and |'delimitMate_matchpairs'|. + - Allow commands to be concatenated using |. +|---------|------------|-----------------------------------------------------| + 2.4.1 2010-07-31 * - Fix problem with and . + - Add missing doc on |'delimitMate_smart_quotes'|, + |delimitMateBalance| and + |'delimitMate_balance_matchpairs'|. +|---------|------------|-----------------------------------------------------| + 2.4 2010-07-29 * - Unbalanced parens: see :help delimitMateBalance. + - Visual wrapping now works on block-wise visual + with some limitations. + - Arrow keys didn't work on terminal. + - Added option to allow nested quotes. + - Expand Smart Quotes to look for a string on the + right of the cursor. + +|---------|------------|-----------------------------------------------------| + 2.3.1 2010-06-06 * - Fix: an extra is inserted after + expansion. + +|---------|------------|-----------------------------------------------------| + 2.3 2010-06-06 * - Syntax aware: Will turn off when editing comments + or other regions, customizable. + - Changed format of most mappings. + - Fix: expansion doesn't brake automatic + indentation adjustments anymore. + - Fix: Arrow keys would insert A, B, C or D instead + of moving the cursor when using Vim on a terminal. + +|---------|------------|-----------------------------------------------------| + 2.2 2010-05-16 * - Added command to switch the plug-in on and off. + - Fix: some problems with , and . + - Fix: A small problem when inserting a delimiter at + the beginning of the line. + +|---------|------------|-----------------------------------------------------| + 2.1 2010-05-10 * - Most of the functions have been moved to an + autoload script to avoid loading unnecessary ones. + - Fixed a problem with the redo command. + - Many small fixes. + +|---------|------------|-----------------------------------------------------| + 2.0 2010-04-01 * New features: + - All features are redo/undo-wise safe. + - A single quote typed after an alphanumeric + character is considered an apostrophe and one + single quote is inserted. + - A quote typed after another quote inserts a single + quote and the cursor jumps to the middle. + - jumps out of any empty pair. + - and expansions are fixed, but the + functions used for it are global and can be used in + custom mappings. The previous system is still + active if you have any of the expansion options + set. + - deletes the closing delimiter. + * Fixed bug: + - s:vars were being used to store buffer options. + +|---------|------------|-----------------------------------------------------| + 1.6 2009-10-10 * Now delimitMate tries to fix the balancing of single + quotes when used as apostrophes. You can read + |delimitMate_apostrophes| for details. + Fixed an error when |b:delimitMate_expand_space| + wasn't set but |delimitMate_expand_space| wasn't. + +|---------|------------|-----------------------------------------------------| + 1.5 2009-10-05 * Fix: delimitMate should work correctly for files + passed as arguments to Vim. Thanks to Ben Beuchler + for helping to nail this bug. + +|---------|------------|-----------------------------------------------------| + 1.4 2009-09-27 * Fix: delimitMate is now enabled on new buffers even + if they don't have set the file type option or were + opened directly from the terminal. + +|---------|------------|-----------------------------------------------------| + 1.3 2009-09-24 * Now local options can be used along with autocmd + for specific file type configurations. + Fixes: + - Unnamed register content is not lost on visual + mode. + - Use noremap where appropiate. + - Wrapping a single empty line works as expected. + +|---------|------------|-----------------------------------------------------| + 1.2 2009-09-07 * Fixes: + - When inside nested empty pairs, deleting the + innermost left delimiter would delete all right + contiguous delimiters. + - When inside an empty pair, inserting a left + delimiter wouldn't insert the right one, instead + the cursor would jump to the right. + - New buffer inside the current window wouldn't + have the mappings set. + +|---------|------------|-----------------------------------------------------| + 1.1 2009-08-25 * Fixed an error that ocurred when mapleader wasn't + set and added support for GetLatestScripts + auto-detection. + +|---------|------------|-----------------------------------------------------| + 1.0 2009-08-23 * Initial upload. + +|---------|------------|-----------------------------------------------------| + + + `\|||/´ MMM \|/ www __^__ ~ + (o o) (o o) @ @ (O-O) /(o o)\\ ~ +ooO_(_)_Ooo__ ooO_(_)_Ooo___oOO_(_)_OOo___oOO__(_)__OOo___oOO__(_)__OOo_____ ~ +_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ +__|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_ ~ +_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ + +vim:tw=78:et:ts=2:sw=2:ft=help:norl:formatoptions+=tcroqn:autoindent: diff --git a/.vim/bundle/delimitMate/plugin/delimitMate.vim b/.vim/bundle/delimitMate/plugin/delimitMate.vim new file mode 100644 index 0000000..dc895ab --- /dev/null +++ b/.vim/bundle/delimitMate/plugin/delimitMate.vim @@ -0,0 +1,427 @@ +" ============================================================================ +" File: plugin/delimitMate.vim +" Version: 2.5.1 +" Modified: 2010-09-30 +" Description: This plugin provides auto-completion for quotes, parens, etc. +" Maintainer: Israel Chauca F. +" Manual: Read ":help delimitMate". + +" Initialization: {{{ + +if exists("g:loaded_delimitMate") || &cp + " User doesn't want this plugin or compatible is set, let's get out! + finish +endif +let g:loaded_delimitMate = 1 + +if exists("s:loaded_delimitMate") && !exists("g:delimitMate_testing") + " Don't define the functions if they already exist: just do the work + " (unless we are testing): + call s:DelimitMateDo() + finish +endif + +if v:version < 700 + echoerr "delimitMate: this plugin requires vim >= 7!" + finish +endif + +let s:loaded_delimitMate = 1 +let delimitMate_version = "2.5.1" + +function! s:option_init(name, default) "{{{ + let b = exists("b:delimitMate_" . a:name) + let g = exists("g:delimitMate_" . a:name) + let prefix = "_l_delimitMate_" + + if !b && !g + let sufix = a:default + elseif !b && g + exec "let sufix = g:delimitMate_" . a:name + else + exec "let sufix = b:delimitMate_" . a:name + endif + if exists("b:" . prefix . a:name) + exec "unlockvar! b:" . prefix . a:name + endif + exec "let b:" . prefix . a:name . " = " . string(sufix) + exec "lockvar! b:" . prefix . a:name +endfunction "}}} + +function! s:init() "{{{ +" Initialize variables: + + " autoclose + call s:option_init("autoclose", 1) + + " matchpairs + call s:option_init("matchpairs", string(&matchpairs)[1:-2]) + call s:option_init("matchpairs_list", split(b:_l_delimitMate_matchpairs, ',')) + call s:option_init("left_delims", split(b:_l_delimitMate_matchpairs, ':.,\=')) + call s:option_init("right_delims", split(b:_l_delimitMate_matchpairs, ',\=.:')) + + " quotes + call s:option_init("quotes", "\" ' `") + call s:option_init("quotes_list", split(b:_l_delimitMate_quotes)) + + " nesting_quotes + call s:option_init("nesting_quotes", []) + + " excluded_regions + call s:option_init("excluded_regions", "Comment") + call s:option_init("excluded_regions_list", split(b:_l_delimitMate_excluded_regions, ',\s*')) + let enabled = len(b:_l_delimitMate_excluded_regions_list) > 0 + call s:option_init("excluded_regions_enabled", enabled) + + " excluded filetypes + call s:option_init("excluded_ft", "") + + " expand_space + if exists("b:delimitMate_expand_space") && type(b:delimitMate_expand_space) == type("") + echom "b:delimitMate_expand_space is '".b:delimitMate_expand_space."' but it must be either 1 or 0!" + echom "Read :help 'delimitMate_expand_space' for more details." + unlet b:delimitMate_expand_space + let b:delimitMate_expand_space = 1 + endif + if exists("g:delimitMate_expand_space") && type(g:delimitMate_expand_space) == type("") + echom "delimitMate_expand_space is '".g:delimitMate_expand_space."' but it must be either 1 or 0!" + echom "Read :help 'delimitMate_expand_space' for more details." + unlet g:delimitMate_expand_space + let g:delimitMate_expand_space = 1 + endif + call s:option_init("expand_space", 0) + + " expand_cr + if exists("b:delimitMate_expand_cr") && type(b:delimitMate_expand_cr) == type("") + echom "b:delimitMate_expand_cr is '".b:delimitMate_expand_cr."' but it must be either 1 or 0!" + echom "Read :help 'delimitMate_expand_cr' for more details." + unlet b:delimitMate_expand_cr + let b:delimitMate_expand_cr = 1 + endif + if exists("g:delimitMate_expand_cr") && type(g:delimitMate_expand_cr) == type("") + echom "delimitMate_expand_cr is '".g:delimitMate_expand_cr."' but it must be either 1 or 0!" + echom "Read :help 'delimitMate_expand_cr' for more details." + unlet g:delimitMate_expand_cr + let g:delimitMate_expand_cr = 1 + endif + if ((&backspace !~ 'eol' || &backspace !~ 'start') && &backspace != 2) && + \ ((exists('b:delimitMate_expand_cr') && b:delimitMate_expand_cr == 1) || + \ (exists('g:delimitMate_expand_cr') && g:delimitMate_expand_cr == 1)) + echom "delimitMate: There seems to be some incompatibility with your settings that may interfer with the expansion of . See :help 'delimitMate_expand_cr' for details." + endif + call s:option_init("expand_cr", 0) + + " smart_matchpairs + call s:option_init("smart_matchpairs", 1) + + " smart_quotes + call s:option_init("smart_quotes", 1) + + " apostrophes + call s:option_init("apostrophes", "") + call s:option_init("apostrophes_list", split(b:_l_delimitMate_apostrophes, ":\s*")) + + " tab2exit + call s:option_init("tab2exit", 1) + + " balance_matchpairs + call s:option_init("balance_matchpairs", 0) + + let b:_l_delimitMate_buffer = [] + + let b:loaded_delimitMate = 1 + +endfunction "}}} Init() + +"}}} + +" Functions: {{{ + +function! s:Map() "{{{ + " Set mappings: + try + let save_cpo = &cpo + let save_keymap = &keymap + let save_iminsert = &iminsert + let save_imsearch = &imsearch + set keymap= + set cpo&vim + if b:_l_delimitMate_autoclose + call s:AutoClose() + else + call s:NoAutoClose() + endif + call s:ExtraMappings() + finally + let &cpo = save_cpo + let &keymap = save_keymap + let &iminsert = save_iminsert + let &imsearch = save_imsearch + endtry + + let b:delimitMate_enabled = 1 + +endfunction "}}} Map() + +function! s:Unmap() " {{{ + let imaps = + \ b:_l_delimitMate_right_delims + + \ b:_l_delimitMate_left_delims + + \ b:_l_delimitMate_quotes_list + + \ b:_l_delimitMate_apostrophes_list + + \ ['', '', '', '', '', '', ''] + + \ ['', '', '', '', '', ''] + + \ ['', '', '', '', '', ''] + + for map in imaps + if maparg(map, "i") =~? 'delimitMate' + if map == '|' + let map = '' + endif + exec 'silent! iunmap ' . map + endif + endfor + + if !has('gui_running') + silent! iunmap OC + endif + + let b:delimitMate_enabled = 0 +endfunction " }}} s:Unmap() + +function! s:TestMappingsDo() "{{{ + %d + if !exists("g:delimitMate_testing") + silent call delimitMate#TestMappings() + else + let temp_varsDM = [b:_l_delimitMate_expand_space, b:_l_delimitMate_expand_cr, b:_l_delimitMate_autoclose] + for i in [0,1] + let b:delimitMate_expand_space = i + let b:delimitMate_expand_cr = i + for a in [0,1] + let b:delimitMate_autoclose = a + call s:init() + call s:Unmap() + call s:Map() + call delimitMate#TestMappings() + normal o + endfor + endfor + let b:delimitMate_expand_space = temp_varsDM[0] + let b:delimitMate_expand_cr = temp_varsDM[1] + let b:delimitMate_autoclose = temp_varsDM[2] + unlet temp_varsDM + endif + normal gg + g/\%^$/d +endfunction "}}} + +function! s:DelimitMateDo(...) "{{{ + " Initialize settings: + call s:init() + + " Check if this file type is excluded: + if exists("g:delimitMate_excluded_ft") && + \ index(split(g:delimitMate_excluded_ft, ','), &filetype, 0, 1) >= 0 + + " Remove any magic: + call s:Unmap() + + " Finish here: + return 1 + endif + + " First, remove all magic, if needed: + if exists("b:delimitMate_enabled") && b:delimitMate_enabled == 1 + call s:Unmap() + endif + + " Now, add magic: + call s:Map() + + if a:0 > 0 + echo "delimitMate has been reset." + endif +endfunction "}}} + +function! s:DelimitMateSwitch() "{{{ + call s:init() + if exists("b:delimitMate_enabled") && b:delimitMate_enabled + call s:Unmap() + echo "delimitMate has been disabled." + else + call s:Unmap() + call s:Map() + echo "delimitMate has been enabled." + endif +endfunction "}}} + +function! s:Finish() + if exists('g:delimitMate_loaded') + return delimitMate#Finish() + endif + return '' +endfunction + +function! s:FlushBuffer() + if exists('g:delimitMate_loaded') + return delimitMate#FlushBuffer() + endif + return '' +endfunction + +"}}} + +" Mappers: {{{ +function! s:NoAutoClose() "{{{ + " inoremap ) =delimitMate#SkipDelim('\)') + for delim in b:_l_delimitMate_right_delims + b:_l_delimitMate_quotes_list + if delim == '|' + let delim = '' + endif + exec 'inoremap delimitMate' . delim . ' =delimitMate#SkipDelim("' . escape(delim,'"') . '")' + exec 'silent! imap '.delim.' delimitMate'.delim + endfor +endfunction "}}} + +function! s:AutoClose() "{{{ + " Add matching pair and jump to the midle: + " inoremap ( () + let i = 0 + while i < len(b:_l_delimitMate_matchpairs_list) + let ld = b:_l_delimitMate_left_delims[i] == '|' ? '' : b:_l_delimitMate_left_delims[i] + let rd = b:_l_delimitMate_right_delims[i] == '|' ? '' : b:_l_delimitMate_right_delims[i] + exec 'inoremap delimitMate' . ld . ' ' . ld . '=delimitMate#ParenDelim("' . escape(rd, '|') . '")' + exec 'silent! imap '.ld.' delimitMate'.ld + let i += 1 + endwhile + + " Exit from inside the matching pair: + for delim in b:_l_delimitMate_right_delims + exec 'inoremap delimitMate' . delim . ' =delimitMate#JumpOut("\' . delim . '")' + exec 'silent! imap ' . delim . ' delimitMate'. delim + endfor + + " Add matching quote and jump to the midle, or exit if inside a pair of matching quotes: + " inoremap " =delimitMate#QuoteDelim("\"") + for delim in b:_l_delimitMate_quotes_list + if delim == '|' + let delim = '' + endif + exec 'inoremap delimitMate' . delim . ' =delimitMate#QuoteDelim("\' . delim . '")' + exec 'silent! imap ' . delim . ' delimitMate' . delim + endfor + + " Try to fix the use of apostrophes (kept for backward compatibility): + " inoremap n't n't + for map in b:_l_delimitMate_apostrophes_list + exec "inoremap " . map . " " . map + exec 'silent! imap ' . map . ' delimitMate' . map + endfor +endfunction "}}} + +function! s:ExtraMappings() "{{{ + " If pair is empty, delete both delimiters: + inoremap delimitMateBS =delimitMate#BS() + " If pair is empty, delete closing delimiter: + inoremap delimitMateS-BS delimitMate#WithinEmptyPair() ? "\=delimitMate#Del()\" : "\" + " Expand return if inside an empty pair: + inoremap delimitMateCR =delimitMate#ExpandReturn() + " Expand space if inside an empty pair: + inoremap delimitMateSpace =delimitMate#ExpandSpace() + " Jump out ot any empty pair: + inoremap delimitMateS-Tab =delimitMate#JumpAny("\") + " Change char buffer on Del: + inoremap delimitMateDel =delimitMate#Del() + " Flush the char buffer on movement keystrokes or when leaving insert mode: + for map in ['Esc', 'Left', 'Right', 'Home', 'End'] + exec 'inoremap delimitMate'.map.' =Finish()<'.map.'>' + if !hasmapto('delimitMate'.map, 'i') + exec 'silent! imap <'.map.'> delimitMate'.map + endif + endfor + " Except when pop-up menu is active: + for map in ['Up', 'Down', 'PageUp', 'PageDown', 'S-Down', 'S-Up'] + exec 'inoremap delimitMate'.map.' pumvisible() ? "\<'.map.'>" : "\=\Finish()\\<'.map.'>"' + if !hasmapto('delimitMate'.map, 'i') + exec 'silent! imap <'.map.'> delimitMate'.map + endif + endfor + " Avoid ambiguous mappings: + for map in ['LeftMouse', 'RightMouse'] + exec 'inoremap delimitMateM'.map.' =delimitMate#Finish()<'.map.'>' + if !hasmapto('delimitMate'.map, 'i') + exec 'silent! imap <'.map.'> delimitMateM'.map + endif + endfor + + " Map away! + if !hasmapto('delimitMateDel', 'i') + silent! imap delimitMateDel + endif + if !hasmapto('delimitMateBS','i') + silent! imap delimitMateBS + endif + if !hasmapto('delimitMateS-BS','i') + silent! imap delimitMateS-BS + endif + if b:_l_delimitMate_expand_cr != 0 && !hasmapto('delimitMateCR', 'i') + silent! imap delimitMateCR + endif + if b:_l_delimitMate_expand_space != 0 && !hasmapto('delimitMateSpace', 'i') + silent! imap delimitMateSpace + endif + if b:_l_delimitMate_tab2exit && !hasmapto('delimitMateS-Tab', 'i') + silent! imap delimitMateS-Tab + endif + " The following simply creates an ambiguous mapping so vim fully processes + " the escape sequence for terminal keys, see 'ttimeout' for a rough + " explanation, this just forces it to work + if !has('gui_running') + imap OC + endif +endfunction "}}} + +"}}} + +" Commands: {{{ + +call s:DelimitMateDo() + +" Let me refresh without re-loading the buffer: +command! -bar DelimitMateReload call s:DelimitMateDo(1) + +" Quick test: +command! -bar DelimitMateTest silent call s:TestMappingsDo() + +" Switch On/Off: +command! -bar DelimitMateSwitch call s:DelimitMateSwitch() +"}}} + +" Autocommands: {{{ + +augroup delimitMate + au! + " Run on file type change. + "autocmd VimEnter * autocmd FileType * call DelimitMateDo() + autocmd FileType * call DelimitMateDo() + + " Run on new buffers. + autocmd BufNewFile,BufRead,BufEnter * + \ if !exists("b:loaded_delimitMate") | + \ call DelimitMateDo() | + \ endif + + " Flush the char buffer: + autocmd InsertEnter * call FlushBuffer() + autocmd BufEnter * + \ if mode() == 'i' | + \ call FlushBuffer() | + \ endif + +augroup END + +"}}} + +" GetLatestVimScripts: 2754 1 :AutoInstall: delimitMate.vim +" vim:foldmethod=marker:foldcolumn=4 diff --git a/.vim/bundle/markdown/ftdetect/markdown.vim b/.vim/bundle/markdown/ftdetect/markdown.vim new file mode 100644 index 0000000..1c5a36a --- /dev/null +++ b/.vim/bundle/markdown/ftdetect/markdown.vim @@ -0,0 +1,6 @@ +autocmd BufNewFile,BufRead *.markdown,*.md,*.mdown,*.mkd,*.mkdn + \ if &ft =~# '^\%(conf\|modula2\)$' | + \ set ft=markdown | + \ else | + \ setf markdown | + \ endif diff --git a/.vim/bundle/markdown/ftplugin/markdown.vim b/.vim/bundle/markdown/ftplugin/markdown.vim new file mode 100644 index 0000000..28cac11 --- /dev/null +++ b/.vim/bundle/markdown/ftplugin/markdown.vim @@ -0,0 +1,18 @@ +" Vim filetype plugin +" Language: Markdown +" Maintainer: Tim Pope + +if exists("b:did_ftplugin") + finish +endif + +runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +unlet! b:did_ftplugin + +setlocal comments=fb:*,fb:-,fb:+,n:> commentstring=>\ %s +setlocal formatoptions+=tcqln +setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+ + +let b:undo_ftplugin .= "|setl cms< com< fo<" + +" vim:set sw=2: diff --git a/.vim/bundle/markdown/syntax/markdown.vim b/.vim/bundle/markdown/syntax/markdown.vim new file mode 100644 index 0000000..b67347a --- /dev/null +++ b/.vim/bundle/markdown/syntax/markdown.vim @@ -0,0 +1,101 @@ +" Vim syntax file +" Language: Markdown +" Maintainer: Tim Pope +" Filenames: *.markdown + +if exists("b:current_syntax") + finish +endif + +runtime! syntax/html.vim +unlet! b:current_syntax + +syn sync minlines=10 +syn case ignore + +syn match markdownValid '[<>]\S\@!' +syn match markdownValid '&\%(#\=\w*;\)\@!' + +syn match markdownLineStart "^[<@]\@!" nextgroup=@markdownBlock + +syn cluster markdownBlock contains=markdownH1,markdownH2,markdownH3,markdownH4,markdownH5,markdownH6,markdownBlockquote,markdownListMarker,markdownOrderedListMarker,markdownCodeBlock,markdownRule +syn cluster markdownInline contains=markdownLineBreak,markdownLinkText,markdownItalic,markdownBold,markdownCode,markdownEscape,@htmlTop + +syn match markdownH1 ".\+\n=\+$" contained contains=@markdownInline,markdownHeadingRule +syn match markdownH2 ".\+\n-\+$" contained contains=@markdownInline,markdownHeadingRule + +syn match markdownHeadingRule "^[=-]\+$" contained + +syn region markdownH1 matchgroup=markdownHeadingDelimiter start="##\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained +syn region markdownH2 matchgroup=markdownHeadingDelimiter start="###\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained +syn region markdownH3 matchgroup=markdownHeadingDelimiter start="####\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained +syn region markdownH4 matchgroup=markdownHeadingDelimiter start="#####\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained +syn region markdownH5 matchgroup=markdownHeadingDelimiter start="######\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained +syn region markdownH6 matchgroup=markdownHeadingDelimiter start="#######\@!" end="#*\s*$" keepend oneline contains=@markdownInline contained + +syn match markdownBlockquote ">\s" contained nextgroup=@markdownBlock + +syn region markdownCodeBlock start=" \|\t" end="$" contained + +" TODO: real nesting +syn match markdownListMarker " \{0,4\}[-*+]\%(\s\+\S\)\@=" contained +syn match markdownOrderedListMarker " \{0,4}\<\d\+\.\%(\s*\S\)\@=" contained + +syn match markdownRule "\* *\* *\*[ *]*$" contained +syn match markdownRule "- *- *-[ -]*$" contained + +syn match markdownLineBreak "\s\{2,\}$" + +syn region markdownIdDeclaration matchgroup=markdownLinkDelimiter start="^ \{0,3\}!\=\[" end="\]:" oneline keepend nextgroup=markdownUrl skipwhite +syn match markdownUrl "\S\+" nextgroup=markdownUrlTitle skipwhite contained +syn region markdownUrl matchgroup=markdownUrlDelimiter start="<" end=">" oneline keepend nextgroup=markdownUrlTitle skipwhite contained +syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+"+ end=+"+ keepend contained +syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+'+ end=+'+ keepend contained +syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+(+ end=+)+ keepend contained + +syn region markdownLinkText matchgroup=markdownLinkTextDelimiter start="!\=\[\%(\_[^]]*]\%( \=[[(]\)\)\@=" end="\]\%( \=[[(]\)\@=" keepend nextgroup=markdownLink,markdownId skipwhite contains=@markdownInline,markdownLineStart +syn region markdownLink matchgroup=markdownLinkDelimiter start="(" end=")" contains=markdownUrl keepend contained +syn region markdownId matchgroup=markdownIdDelimiter start="\[" end="\]" keepend contained +syn region markdownAutomaticLink matchgroup=markdownUrlDelimiter start="<\%(\w\+:\|[[:alnum:]_+-]\+@\)\@=" end=">" keepend oneline + +syn region markdownItalic start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart +syn region markdownItalic start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart +syn region markdownBold start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart +syn region markdownBold start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart +syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" transparent keepend contains=markdownLineStart +syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart + +syn match markdownEscape "\\[][\\`*_{}()#+.!-]" + +hi def link markdownH1 htmlH1 +hi def link markdownH2 htmlH2 +hi def link markdownH3 htmlH3 +hi def link markdownH4 htmlH4 +hi def link markdownH5 htmlH5 +hi def link markdownH6 htmlH6 +hi def link markdownHeadingRule markdownRule +hi def link markdownHeadingDelimiter Delimiter +hi def link markdownOrderedListMarker markdownListMarker +hi def link markdownListMarker htmlTagName +hi def link markdownBlockquote Comment +hi def link markdownRule PreProc + +hi def link markdownLinkText htmlLink +hi def link markdownIdDeclaration Typedef +hi def link markdownId Type +hi def link markdownAutomaticLink markdownUrl +hi def link markdownUrl Float +hi def link markdownUrlTitle String +hi def link markdownIdDelimiter markdownLinkDelimiter +hi def link markdownUrlDelimiter htmlTag +hi def link markdownUrlTitleDelimiter Delimiter + +hi def link markdownItalic htmlItalic +hi def link markdownBold htmlBold +hi def link markdownCodeDelimiter Delimiter + +hi def link markdownEscape Special + +let b:current_syntax = "markdown" + +" vim:set sw=2: diff --git a/.vim/bundle/nerdcommenter/.gitignore b/.vim/bundle/nerdcommenter/.gitignore new file mode 100644 index 0000000..b72f9be --- /dev/null +++ b/.vim/bundle/nerdcommenter/.gitignore @@ -0,0 +1,2 @@ +*~ +*.swp diff --git a/.vim/bundle/nerdcommenter/Rakefile b/.vim/bundle/nerdcommenter/Rakefile new file mode 100644 index 0000000..b3cf2ca --- /dev/null +++ b/.vim/bundle/nerdcommenter/Rakefile @@ -0,0 +1,18 @@ +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 --git a/.vim/bundle/nerdcommenter/doc/NERD_commenter.txt b/.vim/bundle/nerdcommenter/doc/NERD_commenter.txt new file mode 100644 index 0000000..d79d278 --- /dev/null +++ b/.vim/bundle/nerdcommenter/doc/NERD_commenter.txt @@ -0,0 +1,991 @@ +*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 --git a/.vim/bundle/nerdcommenter/plugin/NERD_commenter.vim b/.vim/bundle/nerdcommenter/plugin/NERD_commenter.vim new file mode 100644 index 0000000..b7d9dfc --- /dev/null +++ b/.vim/bundle/nerdcommenter/plugin/NERD_commenter.vim @@ -0,0 +1,3146 @@ +" ============================================================================ +" 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 --git a/.vim/bundle/nerdtree/.gitignore b/.vim/bundle/nerdtree/.gitignore new file mode 100644 index 0000000..3698c0e --- /dev/null +++ b/.vim/bundle/nerdtree/.gitignore @@ -0,0 +1,3 @@ +*~ +*.swp +tags diff --git a/.vim/bundle/nerdtree/Rakefile b/.vim/bundle/nerdtree/Rakefile new file mode 100644 index 0000000..f6c72b8 --- /dev/null +++ b/.vim/bundle/nerdtree/Rakefile @@ -0,0 +1,75 @@ +# 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 --git a/.vim/bundle/nerdtree/doc/NERD_tree.txt b/.vim/bundle/nerdtree/doc/NERD_tree.txt new file mode 100644 index 0000000..2e2278c --- /dev/null +++ b/.vim/bundle/nerdtree/doc/NERD_tree.txt @@ -0,0 +1,1222 @@ +*NERD_tree.txt* A tree explorer plugin that owns your momma! + + + + omg its ... ~ + + ________ ________ _ ____________ ____ __________ ____________~ + /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~ + / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~ + / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~ + /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~ + + + Reference Manual~ + + + + +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERD tree mappings................|NERDTreeMappings| + 2.4.The NERD tree menu................|NERDTreeMenu| + 3.Options.................................|NERDTreeOptions| + 3.1.Option summary....................|NERDTreeOptionSummary| + 3.2.Option details....................|NERDTreeOptionDetails| + 4.The NERD tree API.......................|NERDTreeAPI| + 4.1.Key map API.......................|NERDTreeKeymapAPI| + 4.2.Menu API..........................|NERDTreeMenuAPI| + 5.About...................................|NERDTreeAbout| + 6.Changelog...............................|NERDTreeChangelog| + 7.Credits.................................|NERDTreeCredits| + 8.License.................................|NERDTreeLicense| + +============================================================================== +1. Intro *NERDTree* + +What is this "NERD tree"?? + +The NERD tree allows you to explore your filesystem and to open files and +directories. It presents the filesystem to you in the form of a tree which you +manipulate with the keyboard and/or mouse. It also allows you to perform +simple filesystem operations. + +The following features and functionality are provided by the NERD tree: + * Files and directories are displayed in a hierarchical tree structure + * Different highlighting is provided for the following types of nodes: + * files + * directories + * sym-links + * windows .lnk files + * read-only files + * executable files + * Many (customisable) mappings are provided to manipulate the tree: + * Mappings to open/close/explore directory nodes + * Mappings to open files in new/existing windows/tabs + * Mappings to change the current root of the tree + * Mappings to navigate around the tree + * ... + * Directories and files can be bookmarked. + * Most NERD tree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * custom file filters to prevent e.g. vim backup files being displayed + * optional displaying of hidden files (. files) + * files can be "turned off" so that only directories are displayed + * The position and size of the NERD tree window can be customised + * The order in which the nodes in the tree are listed can be customised. + * A model of your filesystem is created/maintained as you explore it. This + has several advantages: + * All filesystem information is cached and is only re-read on demand + * If you revisit a part of the tree that you left earlier in your + session, the directory nodes will be opened/closed as you left them + * The script remembers the cursor position and window position in the NERD + tree so you can toggle it off (or just close the tree window) and then + reopen it (with NERDTreeToggle) the NERD tree window will appear exactly + as you left it + * You can have a separate NERD tree for each tab, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netw), so if + you :edit a directory a (slighly modified) NERD tree will appear in the + current window + * A programmable menu system is provided (simulates right clicking on a + node) + * one default menu plugin is provided to perform basic filesytem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [ | ] *:NERDTree* + Opens a fresh NERD tree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeFromBookmark *:NERDTreeFromBookmark* + Opens a fresh NERD tree with the root initialized to the dir for + . This only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [ | ] *:NERDTreeToggle* + If a NERD tree already exists for this tab, it is reopened and rendered + again. If no NERD tree exists for this tab then this command acts the + same as the |:NERDTree| command. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERD tree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERD tree exists, that tree is automatically mirrored. If + more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERD tree in this tab. + +:NERDTreeFind *:NERDTreeFind* + Find the current file in the tree. If no tree exists for the current tab, + or the file is not under the current root, then initialize a new tree where + the root is the directory of the current file. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note that the following commands are only available in the NERD tree buffer. + +:Bookmark + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + must point to a file. The file is opened as though |NERDTree-o| + was applied. If the node is cached under the current root then it will be + revealed and the cursor will be placed on it. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default Description~ help-tag~ +Key~ + +o.......Open files, directories and bookmarks....................|NERDTree-o| +go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| +t.......Open selected node/bookmark in a new tab.................|NERDTree-t| +T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| +i.......Open selected file in a split window.....................|NERDTree-i| +gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| +s.......Open selected file in a new vsplit.......................|NERDTree-s| +gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| +O.......Recursively open the selected directory..................|NERDTree-O| +x.......Close the current nodes parent...........................|NERDTree-x| +X.......Recursively close all children of the current node.......|NERDTree-X| +e.......Edit the current dif.....................................|NERDTree-e| + +...............same as |NERDTree-o|. +double-click.......same as the |NERDTree-o| map. +middle-click.......same as |NERDTree-i| for files, same as + |NERDTree-e| for dirs. + +D.......Delete the current bookmark .............................|NERDTree-D| + +P.......Jump to the root node....................................|NERDTree-P| +p.......Jump to current nodes parent.............................|NERDTree-p| +K.......Jump up inside directories at the current tree depth.....|NERDTree-K| +J.......Jump down inside directories at the current tree depth...|NERDTree-J| +...Jump down to the next sibling of the current directory...|NERDTree-C-J| +...Jump up to the previous sibling of the current directory.|NERDTree-C-K| + +C.......Change the tree root to the selected dir.................|NERDTree-C| +u.......Move the tree root up one directory......................|NERDTree-u| +U.......Same as 'u' except the old root node is left open........|NERDTree-U| +r.......Recursively refresh the current directory................|NERDTree-r| +R.......Recursively refresh the current root.....................|NERDTree-R| +m.......Display the NERD tree menu...............................|NERDTree-m| +cd......Change the CWD to the dir of the selected node...........|NERDTree-cd| + +I.......Toggle whether hidden files displayed....................|NERDTree-I| +f.......Toggle whether the file filters are used.................|NERDTree-f| +F.......Toggle whether files are displayed.......................|NERDTree-F| +B.......Toggle whether the bookmark table is displayed...........|NERDTree-B| + +q.......Close the NERDTree window................................|NERDTree-q| +A.......Zoom (maximize/minimize) the NERDTree window.............|NERDTree-A| +?.......Toggle the display of the quick help.....................|NERDTree-?| + +------------------------------------------------------------------------------ + *NERDTree-o* +Default key: o +Map option: NERDTreeMapActivateNode +Applies to: files and directories. + +If a file node is selected, it is opened in the previous window. + +If a directory is selected it is opened or closed depending on its current +state. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *NERDTree-go* +Default key: go +Map option: None +Applies to: files. + +If a file node is selected, it is opened in the previous window, but the +cursor does not move. + +The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see +|NERDTree-o|). + +------------------------------------------------------------------------------ + *NERDTree-t* +Default key: t +Map option: NERDTreeMapOpenInTab +Applies to: files and directories. + +Opens the selected file in a new tab. If a directory is selected, a fresh +NERD Tree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERD tree for +that directory in a new tab. If the bookmark points to a file, open that file +in a new tab. + +------------------------------------------------------------------------------ + *NERDTree-T* +Default key: T +Map option: NERDTreeMapOpenInTabSilent +Applies to: files and directories. + +The same as |NERDTree-t| except that the focus is kept in the current tab. + +------------------------------------------------------------------------------ + *NERDTree-i* +Default key: i +Map option: NERDTreeMapOpenSplit +Applies to: files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map option: None +Applies to: files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map option: NERDTreeMapOpenVSplit +Applies to: files. + +Opens the selected file in a new vertically split window and puts the cursor in +the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map option: None +Applies to: files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *NERDTree-O* +Default key: O +Map option: NERDTreeMapOpenRecursively +Applies to: directories. + +Recursively opens the selelected directory. + +All files and directories are cached, but if a directory would not be +displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the +hidden file filter (see |'NERDTreeShowHidden'|) then its contents are not +cached. This is handy, especially if you have .svn directories. + +------------------------------------------------------------------------------ + *NERDTree-x* +Default key: x +Map option: NERDTreeMapCloseDir +Applies to: files and directories. + +Closes the parent of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-X* +Default key: X +Map option: NERDTreeMapCloseChildren +Applies to: directories. + +Recursively closes all children of the selected directory. + +Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. + +------------------------------------------------------------------------------ + *NERDTree-e* +Default key: e +Map option: NERDTreeMapOpenExpl +Applies to: files and directories. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERD tree or a netrw being opened, depending on +|'NERDTreeHijackNetrw'|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map option: NERDTreeMapDeleteBookmark +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *NERDTree-P* +Default key: P +Map option: NERDTreeMapJumpRoot +Applies to: no restrictions. + +Jump to the tree root. + +------------------------------------------------------------------------------ + *NERDTree-p* +Default key: p +Map option: NERDTreeMapJumpParent +Applies to: files and directories. + +Jump to the parent node of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-K* +Default key: K +Map option: NERDTreeMapJumpFirstChild +Applies to: files and directories. + +Jump to the first child of the current nodes parent. + +If the cursor is already on the first node then do the following: + * loop back thru the siblings of the current nodes parent until we find an + open dir with children + * go to the first child of that node + +------------------------------------------------------------------------------ + *NERDTree-J* +Default key: J +Map option: NERDTreeMapJumpLastChild +Applies to: files and directories. + +Jump to the last child of the current nodes parent. + +If the cursor is already on the last node then do the following: + * loop forward thru the siblings of the current nodes parent until we find + an open dir with children + * go to the last child of that node + +------------------------------------------------------------------------------ + *NERDTree-C-J* +Default key: +Map option: NERDTreeMapJumpNextSibling +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: +Map option: NERDTreeMapJumpPrevSibling +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map option: NERDTreeMapChdir +Applies to: directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *NERDTree-u* +Default key: u +Map option: NERDTreeMapUpdir +Applies to: no restrictions. + +Move the tree root up a dir (like doing a "cd .."). + +------------------------------------------------------------------------------ + *NERDTree-U* +Default key: U +Map option: NERDTreeMapUpdirKeepOpen +Applies to: no restrictions. + +Like |NERDTree-u| except that the old tree root is kept open. + +------------------------------------------------------------------------------ + *NERDTree-r* +Default key: r +Map option: NERDTreeMapRefresh +Applies to: files and directories. + +If a dir is selected, recursively refresh that dir, i.e. scan the filesystem +for changes and represent them in the tree. + +If a file node is selected then the above is done on it's parent. + +------------------------------------------------------------------------------ + *NERDTree-R* +Default key: R +Map option: NERDTreeMapRefreshRoot +Applies to: no restrictions. + +Recursively refresh the tree root. + +------------------------------------------------------------------------------ + *NERDTree-m* +Default key: m +Map option: NERDTreeMapMenu +Applies to: files and directories. + +Display the NERD tree menu. See |NERDTreeMenu| for details. + +------------------------------------------------------------------------------ + *NERDTree-cd* +Default key: cd +Map option: NERDTreeMapChdir +Applies to: files and directories. + +Change vims current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map option: NERDTreeMapToggleHidden +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *NERDTree-f* +Default key: f +Map option: NERDTreeMapToggleFilters +Applies to: no restrictions. + +Toggles whether file filters are used. See |'NERDTreeIgnore'| for details. + +------------------------------------------------------------------------------ + *NERDTree-F* +Default key: F +Map option: NERDTreeMapToggleFiles +Applies to: no restrictions. + +Toggles whether file nodes are displayed. + +------------------------------------------------------------------------------ + *NERDTree-B* +Default key: B +Map option: NERDTreeMapToggleBookmarks +Applies to: no restrictions. + +Toggles whether the bookmarks table is displayed. + +------------------------------------------------------------------------------ + *NERDTree-q* +Default key: q +Map option: NERDTreeMapQuit +Applies to: no restrictions. + +Closes the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-A* +Default key: A +Map option: NERDTreeMapToggleZoom +Applies to: no restrictions. + +Maximize (zoom) and minimize the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-?* +Default key: ? +Map option: NERDTreeMapHelp +Applies to: no restrictions. + +Toggles whether the quickhelp is displayed. + +------------------------------------------------------------------------------ +2.3. The NERD tree menu *NERDTreeMenu* + +The NERD tree has a menu that can be programmed via the an API (see +|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most +file explorers have. + +The script comes with two default menu plugins: exec_menuitem.vim and +fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for +creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a +menu item to execute executable files. + +Related tags: |NERDTree-m| |NERDTreeApi| + +============================================================================== +3. Customisation *NERDTreeOptions* + + +------------------------------------------------------------------------------ +3.1. Customisation summary *NERDTreeOptionSummary* + +The script provides the following options that can customise the behaviour the +NERD tree. These options should be set in your vimrc. + +|'loaded_nerd_tree'| Turns off the script. + +|'NERDChristmasTree'| Tells the NERD tree to make itself colourful + and pretty. + +|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers + when the cursor moves within a specified + distance to the top/bottom of the window. +|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering. + +|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case + sensitive or not when sorting nodes. + +|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change + vim's current working directory. + +|'NERDTreeHighlightCursorline'| Tell the NERD tree whether to highlight the + current cursor line. + +|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw + autocommands for exploring local directories. + +|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. + +|'NERDTreeBookmarksFile'| Where the bookmarks are stored. + +|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse + clicks. + +|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. + +|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the + bookmarks table on startup. + +|'NERDTreeShowFiles'| Tells the NERD tree whether to display files + in the tree on startup. + +|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden + files on startup. + +|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line + numbers in the tree window. + +|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in + the tree. + +|'NERDTreeStatusline'| Set a statusline for NERD tree windows. + +|'NERDTreeWinPos'| Tells the script where to put the NERD tree + window. + +|'NERDTreeWinSize'| Sets the window size when the NERD tree is + opened. + +------------------------------------------------------------------------------ +3.2. Customisation details *NERDTreeOptionDetails* + +To enable any of the below options you should put the given line in your +~/.vimrc + + *'loaded_nerd_tree'* +If this plugin is making you feel homicidal, it may be a good idea to turn it +off with this line in your vimrc: > + let loaded_nerd_tree=1 +< +------------------------------------------------------------------------------ + *'NERDChristmasTree'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then some extra syntax highlighting elements are +added to the nerd tree to make it more colourful. + +Set it to 0 for a more vanilla looking tree. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenter'* +Values: 0 or 1. +Default: 1 + +If set to 1, the NERD tree window will center around the cursor if it moves to +within |'NERDTreeAutoCenterThreshold'| lines of the top/bottom of the window. + +This is ONLY done in response to tree navigation mappings, +i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| +|NERDTree-P| + +The centering is done with a |zz| operation. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenterThreshold'* +Values: Any natural number. +Default: 3 + +This option controls the "sensitivity" of the NERD tree auto centering. See +|'NERDTreeAutoCenter'| for details. + +------------------------------------------------------------------------------ + *'NERDTreeCaseSensitiveSort'* +Values: 0 or 1. +Default: 0. + +By default the NERD tree does not sort nodes case sensitively, i.e. nodes +could appear like this: > + bar.c + Baz.c + blarg.c + boner.c + Foo.c +< +But, if you set this option to 1 then the case of the nodes will be taken into +account. The above nodes would then be sorted like this: > + Baz.c + Foo.c + bar.c + blarg.c + boner.c +< +------------------------------------------------------------------------------ + *'NERDTreeChDirMode'* + +Values: 0, 1 or 2. +Default: 0. + +Use this option to tell the script when (if at all) to change the current +working directory (CWD) for vim. + +If it is set to 0 then the CWD is never changed by the NERD tree. + +If set to 1 then the CWD is changed when the NERD tree is first loaded to the +directory it is initialized in. For example, if you start the NERD tree with > + :NERDTree /home/marty/foobar +< +then the CWD will be changed to /home/marty/foobar and will not be changed +again unless you init another NERD tree with a similar command. + +If the option is set to 2 then it behaves the same as if set to 1 except that +the CWD is changed whenever the tree root is changed. For example, if the CWD +is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new +root then the CWD will become /home/marty/foobar/baz. + +------------------------------------------------------------------------------ + *'NERDTreeHighlightCursorline'* +Values: 0 or 1. +Default: 1. + +If set to 1, the current cursor line in the NERD tree buffer will be +highlighted. This is done using the |'cursorline'| option. + +------------------------------------------------------------------------------ + *'NERDTreeHijackNetrw'* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit +< +will open up a "secondary" NERD tree instead of a netrw in the target window. + +Secondary NERD trees behaves slighly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have as many secondary tree as you want in the same tab. + +------------------------------------------------------------------------------ + *'NERDTreeIgnore'* +Values: a list of regular expressions. +Default: ['\~$']. + +This option is used to specify which files the NERD tree should ignore. It +must be a list of regular expressions. When the NERD tree is rendered, any +files/dirs that match any of the regex's in 'NERDTreeIgnore' wont be +displayed. + +For example if you put the following line in your vimrc: > + let NERDTreeIgnore=['\.vim$', '\~$'] +< +then all files ending in .vim or ~ will be ignored. + +Note: to tell the NERD tree not to ignore any files you must use the following +line: > + let NERDTreeIgnore=[] +< + +The file filters can be turned on and off dynamically with the |NERDTree-f| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksFile'* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *'NERDTreeMouseMode'* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *'NERDTreeQuitOnOpen'* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. + +------------------------------------------------------------------------------ + *'NERDTreeShowBookmarks'* +Values: 0 or 1. +Default: 0. + +If this option is set to 1 then the bookmarks table will be displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeShowFiles'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then files are displayed in the NERD tree. If it is +set to 0 then only directories are displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *'NERDTreeShowHidden'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display hidden files by default. This option +can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one +of the follow lines to set this option: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeShowLineNumbers'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines to set this option: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeSortOrder'* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This option is set to a list of regular expressions which are used to +specify the order of nodes under their parent. + +For example, if the option is set to: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be placed at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesnt match any of the other regexps should be placed here. + +If no star is present in 'NERDTreeSortOrder' then one is automatically +appended to the array. + +The regex '\/$' should be used to match directory nodes. + +After this sorting is done, the files in each group are sorted alphabetically. + +Other examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Dirs will appear first, then ruby and php. Swap files, bak files and vim + backup files will appear last with everything else preceding them. + +------------------------------------------------------------------------------ + *'NERDTreeStatusline'* +Values: Any valid statusline setting. +Default: %{b:NERDTreeRoot.path.strForOS(0)} + +Tells the script what to use as the |'statusline'| setting for NERD tree +windows. + +Note that the statusline is set using |:let-&| not |:set| so escaping spaces +isn't necessary. + +Setting this option to -1 will will deactivate it so that your global +statusline setting is used instead. + +------------------------------------------------------------------------------ + *'NERDTreeWinPos'* +Values: "left" or "right" +Default: "left". + +This option is used to determine where NERD tree window is placed on the +screen. + +This option makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERD tree on the right. + +------------------------------------------------------------------------------ + *'NERDTreeWinSize'* +Values: a positive integer. +Default: 31. + +This option is used to change the size of the NERD tree when it is loaded. + +============================================================================== +4. The NERD tree API *NERDTreeAPI* + +The NERD tree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERD tree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'b', + \ 'callback': 'NERDTreeEchoCurrentNode', + \ 'quickhelpText': 'echo full path of current node' }) + + function! NERDTreeEchoCurrentNode() + let n = g:NERDTreeFileNode.GetSelected() + if n != {} + echomsg 'Current node: ' . n.path.str() + endif + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (rather useless) mapping on 'b' which echos the full path to the + current node. + +------------------------------------------------------------------------------ +4.2. Menu API *NERDTreeMenuAPI* + +NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* + Creates and returns a new submenu. + + {options} must be a dictionary and must contain the following keys: + "text" - the text of the submenu that the user will see + "shortcut" - a shortcut key for the submenu (need not be unique) + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this submenu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - the parent submenu of the new submenu (returned from a previous + invocation of NERDTreeAddSubmenu()). If this key is left out then the new + submenu will sit under the top level menu. + + See below for an example. + +NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* + Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|). + + {options} must be a dictionary and must contain the + following keys: + "text" - the text of the menu item which the user will see + "shortcut" - a shortcut key for the menu item (need not be unique) + "callback" - the function that will be called when the user activates the + menu item. + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this menu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - if the menu item belongs under a submenu then this key must be + specified. This value for this key will be the object that + was returned when the submenu was created with |NERDTreeAddSubmenu()|. + + See below for an example. + +NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* + Adds a menu separator (a row of dashes). + + {options} is an optional dictionary that may contain the following keys: + "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. + +Below is an example of the menu API in action. > + call NERDTreeAddMenuSeparator() + + call NERDTreeAddMenuItem({ + \ 'text': 'a (t)op level menu item', + \ 'shortcut': 't', + \ 'callback': 'SomeFunction' }) + + let submenu = NERDTreeAddSubmenu({ + \ 'text': 'a (s)ub menu', + \ 'shortcut': 's' }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 1', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 2', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) +< +This will create the following menu: > + -------------------- + a (t)op level menu item + a (s)ub menu +< +Where selecting "a (s)ub menu" will lead to a second menu: > + (n)ested item 1 + (n)ested item 2 +< +When any of the 3 concrete menu items are selected the function "SomeFunction" +will be called. + +------------------------------------------------------------------------------ +NERDTreeRender() *NERDTreeRender()* + Re-renders the NERD tree buffer. Useful if you change the state of the + tree and you want to it to be reflected in the UI. + +============================================================================== +5. About *NERDTreeAbout* + +The author of the NERD tree is a terrible terrible monster called Martyzilla +who gobbles up small children with milk and sugar for breakfast. + +He can be reached at martin.grenfell at gmail dot com. He would love to hear +from you, so feel free to send him suggestions and/or comments about this +plugin. Don't be shy --- the worst he can do is slaughter you and stuff you in +the fridge for later ;) + +The latest stable versions can be found at + http://www.vim.org/scripts/script.php?script_id=1658 + +The latest dev versions are on github + http://github.com/scrooloose/nerdtree + + +============================================================================== +6. Changelog *NERDTreeChangelog* + +4.1.0 + features: + - NERDTreeFind to reveal the node for the current buffer in the tree, + see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by + Doug McInnes) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan + Ritter and Rémi Prévost. + - truncate the root node if wider than the tree window. Thanks to Victor + Gonzalez. + + bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, + jfilip1024, and Chris Chambers + +4.0.0 + - add a new programmable menu system (see :help NERDTreeMenu). + - add new APIs to add menus/menu-items to the menu system as well as + custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). + - removed the old API functions + - added a mapping to maximize/restore the size of nerd tree window, thanks + to Guillaume Duranceau for the patch. See :help NERDTree-A for details. + + - fix a bug where secondary nerd trees (netrw hijacked trees) and + NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. + - fix a bug where the script ignored directories whose name ended in a dot, + thanks to Aggelos Orfanakos for the patch. + - fix a bug when using the x mapping on the tree root, thanks to Bryan + Venteicher for the patch. + - fix a bug where the cursor position/window size of the nerd tree buffer + wasnt being stored on closing the window, thanks to Richard Hart. + - fix a bug where NERDTreeMirror would mirror the wrong tree + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + " (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree would fail if was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring + +============================================================================== +7. Credits *NERDTreeCredits* + +Thanks to the following people for testing, bug reports, ideas etc. Without +you I probably would have got bored of the hacking the NERD tree and +just downloaded pr0n instead. + + Tim Carey-Smith (halorgium) + Vigil + Nick Brettell + Thomas Scott Urban + Terrance Cohen + Yegappan Lakshmanan + Jason Mills + Michael Geddes (frogonwheels) + Yu Jun + Michael Madsen + AOYAMA Shotaro + Zhang Weiwu + Niels Aan de Brugh + Olivier Yiptong + Zhang Shuhan + Cory Echols + Piotr Czachur + Yuan Jiang + Matan Nassau + Maxim Kim + Charlton Wang + Matt Wozniski (godlygeek) + knekk + Sean Chou + Ryan Penn + Simon Peter Nicholls + Michael Foobar + Tomasz Chomiuk + Denis Pokataev + Tim Pope (tpope) + James Kanze + James Vega (jamessan) + Frederic Chanal (nach) + Alf Mikula + Lucas S. Buchala + Curtis Harvey + Guillaume Duranceau + Richard Hart (hates) + Doug McInnes + Stefan Ritter + Rémi Prévost + Victor Gonzalez + Stephan Baumeister + Ricky + jfilip1024 + Chris Chambers + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. diff --git a/.vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim b/.vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..e7a7c53 --- /dev/null +++ b/.vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim @@ -0,0 +1,41 @@ +" ============================================================================ +" File: exec_menuitem.vim +" Description: plugin for NERD Tree that provides an execute file menu item +" Maintainer: Martin Grenfell +" Last Change: 22 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_exec_menuitem") + finish +endif +let g:loaded_nerdtree_exec_menuitem = 1 + +call NERDTreeAddMenuItem({ + \ 'text': '(!)Execute file', + \ 'shortcut': '!', + \ 'callback': 'NERDTreeExecFile', + \ 'isActiveCallback': 'NERDTreeExecFileActive' }) + +function! NERDTreeExecFileActive() + let node = g:NERDTreeFileNode.GetSelected() + return !node.path.isDirectory && node.path.isExecutable +endfunction + +function! NERDTreeExecFile() + let treenode = g:NERDTreeFileNode.GetSelected() + echo "==========================================================\n" + echo "Complete the command to execute (add arguments etc):\n" + let cmd = treenode.path.str({'escape': 1}) + let cmd = input(':!', cmd . ' ') + + if cmd != '' + exec ':!' . cmd + else + echo "Aborted" + endif +endfunction diff --git a/.vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim b/.vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..e25b38c --- /dev/null +++ b/.vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,194 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell +" Last Change: 17 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_fs_menu") + finish +endif +let g:loaded_nerdtree_fs_menu = 1 + +call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) +call NERDTreeAddMenuItem({'text': '(m)ove the curent node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the curent node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) +if g:NERDTreePath.CopyingSupported() + call NERDTreeAddMenuItem({'text': '(c)copy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'}) +endif + +"FUNCTION: s:echo(msg){{{1 +function! s:echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction + +"FUNCTION: s:echoWarning(msg){{{1 +function! s:echoWarning(msg) + echohl warningmsg + call s:echo(a:msg) + echohl normal +endfunction + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if nr2char(getchar()) ==# 'y' + exec "silent bdelete! " . a:bufnum + endif +endfunction + +"FUNCTION: NERDTreeAddNode(){{{1 +function! NERDTreeAddNode() + let curDirNode = g:NERDTreeDirNode.GetSelected() + + let newNodeName = input("Add a childnode\n". + \ "==========================================================\n". + \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . + \ "", curDirNode.path.str({'format': 'Glob'}) . g:NERDTreePath.Slash()) + + if newNodeName ==# '' + call s:echo("Node Creation Aborted.") + return + endif + + try + let newPath = g:NERDTreePath.Create(newNodeName) + let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) + + let newTreeNode = g:NERDTreeFileNode.New(newPath) + if parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call NERDTreeRender() + call newTreeNode.putCursorHere(1, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Node Not Created.") + endtry +endfunction + +"FUNCTION: NERDTreeMoveNode(){{{1 +function! NERDTreeMoveNode() + let curNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Rename the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path for the node: \n" . + \ "", curNode.path.str()) + + if newNodePath ==# '' + call s:echo("Node Renaming Aborted.") + return + endif + + try + let bufnum = bufnr(curNode.path.str()) + + call curNode.rename(newNodePath) + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + if bufnum != -1 + let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + call curNode.putCursorHere(1, 0) + + redraw + catch /^NERDTree/ + call s:echoWarning("Node Not Renamed.") + endtry +endfunction + +" FUNCTION: NERDTreeDeleteNode() {{{1 +function! NERDTreeDeleteNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let confirmed = 0 + + if currentNode.path.isDirectory + let choice =input("Delete the current node\n" . + \ "==========================================================\n" . + \ "STOP! To delete this entire directory, type 'yes'\n" . + \ "" . currentNode.path.str() . ": ") + let confirmed = choice ==# 'yes' + else + echo "Delete the current node\n" . + \ "==========================================================\n". + \ "Are you sure you wish to delete the node:\n" . + \ "" . currentNode.path.str() . " (yN):" + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + + if confirmed + try + call currentNode.delete() + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr(currentNode.path.str()) + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove node") + endtry + else + call s:echo("delete aborted") + endif + +endfunction + +" FUNCTION: NERDTreeCopyNode() {{{1 +function! NERDTreeCopyNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Copy the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path to copy the node to: \n" . + \ "", currentNode.path.str()) + + if newNodePath != "" + "strip trailing slash + let newNodePath = substitute(newNodePath, '\/$', '', '') + + let confirmed = 1 + if currentNode.path.copyingWillOverwrite(newNodePath) + call s:echo("Warning: copying may overwrite files! Continue? (yN)") + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + let newNode = currentNode.copy(newNodePath) + call NERDTreeRender() + call newNode.putCursorHere(0, 0) + catch /^NERDTree/ + call s:echoWarning("Could not copy node") + endtry + endif + else + call s:echo("Copy aborted.") + endif + redraw +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/.vim/bundle/nerdtree/plugin/NERD_tree.vim b/.vim/bundle/nerdtree/plugin/NERD_tree.vim new file mode 100644 index 0000000..c5a014c --- /dev/null +++ b/.vim/bundle/nerdtree/plugin/NERD_tree.vim @@ -0,0 +1,4076 @@ +" ============================================================================ +" 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 . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'" + return 1 + endif + return 0 +endfunction + +"SECTION: Init variable calls and other random constants {{{2 +call s:initVariable("g:NERDChristmasTree", 1) +call s:initVariable("g:NERDTreeAutoCenter", 1) +call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) +call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) +call s:initVariable("g:NERDTreeChDirMode", 0) +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() + call s:closeTreeIfQuitOnOpen() + endif + endif +endfunction +" FUNCTION: Bookmark.AddBookmark(name, path) {{{3 +" Class method to add a new bookmark to the list, if a previous bookmark exists +" with the same name, just update the path for that bookmark +function! s:Bookmark.AddBookmark(name, path) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + let i.path = a:path + return + endif + endfor + call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) + call s:Bookmark.Sort() +endfunction +" Function: Bookmark.Bookmarks() {{{3 +" Class method to get all bookmarks. Lazily initializes the bookmarks global +" variable +function! s:Bookmark.Bookmarks() + if !exists("g:NERDTreeBookmarks") + let g:NERDTreeBookmarks = [] + endif + return g:NERDTreeBookmarks +endfunction +" Function: Bookmark.BookmarkExistsFor(name) {{{3 +" class method that returns 1 if a bookmark with the given name is found, 0 +" otherwise +function! s:Bookmark.BookmarkExistsFor(name) + try + call s:Bookmark.BookmarkFor(a:name) + return 1 + catch /^NERDTree.BookmarkNotFoundError/ + return 0 + endtry +endfunction +" Function: Bookmark.BookmarkFor(name) {{{3 +" Class method to get the bookmark that has the given name. {} is return if no +" bookmark is found +function! s:Bookmark.BookmarkFor(name) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + return i + endif + endfor + throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"' +endfunction +" Function: Bookmark.BookmarkNames() {{{3 +" Class method to return an array of all bookmark names +function! s:Bookmark.BookmarkNames() + let names = [] + for i in s:Bookmark.Bookmarks() + call add(names, i.name) + endfor + return names +endfunction +" FUNCTION: Bookmark.CacheBookmarks(silent) {{{3 +" Class method to read all bookmarks from the bookmarks file intialize +" bookmark objects for each one. +" +" Args: +" silent - dont echo an error msg if invalid bookmarks are found +function! s:Bookmark.CacheBookmarks(silent) + if filereadable(g:NERDTreeBookmarksFile) + let g:NERDTreeBookmarks = [] + let g:NERDTreeInvalidBookmarks = [] + let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) + let invalidBookmarksFound = 0 + for i in bookmarkStrings + + "ignore blank lines + if i != '' + + let name = substitute(i, '^\(.\{-}\) .*$', '\1', '') + let path = substitute(i, '^.\{-} \(.*\)$', '\1', '') + + try + let bookmark = s:Bookmark.New(name, s:Path.New(path)) + call add(g:NERDTreeBookmarks, bookmark) + catch /^NERDTree.InvalidArgumentsError/ + call add(g:NERDTreeInvalidBookmarks, i) + let invalidBookmarksFound += 1 + endtry + endif + endfor + if invalidBookmarksFound + call s:Bookmark.Write() + if !a:silent + call s:echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") + endif + endif + call s:Bookmark.Sort() + endif +endfunction +" FUNCTION: Bookmark.compareTo(otherbookmark) {{{3 +" Compare these two bookmarks for sorting purposes +function! s:Bookmark.compareTo(otherbookmark) + return a:otherbookmark.name < self.name +endfunction +" FUNCTION: Bookmark.ClearAll() {{{3 +" Class method to delete all bookmarks. +function! s:Bookmark.ClearAll() + for i in s:Bookmark.Bookmarks() + call i.delete() + endfor + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.delete() {{{3 +" Delete this bookmark. If the node for this bookmark is under the current +" root, then recache bookmarks for its Path object +function! s:Bookmark.delete() + let node = {} + try + let node = self.getNode(1) + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self)) + if !empty(node) + call node.path.cacheDisplayString() + endif + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{3 +" Gets the treenode for this bookmark +" +" Args: +" searchFromAbsoluteRoot: specifies whether we should search from the current +" tree root, or the highest cached node +function! s:Bookmark.getNode(searchFromAbsoluteRoot) + let searchRoot = a:searchFromAbsoluteRoot ? s:TreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot + let targetNode = searchRoot.findNode(self.path) + if empty(targetNode) + throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name + endif + return targetNode +endfunction +" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3 +" Class method that finds the bookmark with the given name and returns the +" treenode for it. +function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) + let bookmark = s:Bookmark.BookmarkFor(a:name) + return bookmark.getNode(a:searchFromAbsoluteRoot) +endfunction +" FUNCTION: Bookmark.GetSelected() {{{3 +" returns the Bookmark the cursor is over, or {} +function! s:Bookmark.GetSelected() + let line = getline(".") + let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '') + if name != line + try + return s:Bookmark.BookmarkFor(name) + catch /^NERDTree.BookmarkNotFoundError/ + return {} + endtry + endif + return {} +endfunction + +" Function: Bookmark.InvalidBookmarks() {{{3 +" Class method to get all invalid bookmark strings read from the bookmarks +" file +function! s:Bookmark.InvalidBookmarks() + if !exists("g:NERDTreeInvalidBookmarks") + let g:NERDTreeInvalidBookmarks = [] + endif + return g:NERDTreeInvalidBookmarks +endfunction +" FUNCTION: Bookmark.mustExist() {{{3 +function! s:Bookmark.mustExist() + if !self.path.exists() + call s:Bookmark.CacheBookmarks(1) + throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"". + \ self.name ."\" points to a non existing location: \"". self.path.str() + endif +endfunction +" FUNCTION: Bookmark.New(name, path) {{{3 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.New(name, path) + if a:name =~ ' ' + throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name + endif + + let newBookmark = copy(self) + let newBookmark.name = a:name + let newBookmark.path = a:path + return newBookmark +endfunction +" FUNCTION: Bookmark.openInNewTab(options) {{{3 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.openInNewTab(options) + let currentTab = tabpagenr() + if self.path.isDirectory + tabnew + call s:initNerdTree(self.name) + else + exec "tabedit " . 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) + + "if a bookmark exists with the same name and the node is cached then save + "it so we can update its display string + let oldMarkedNode = {} + try + let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1) + catch /^NERDTree.BookmarkNotFoundError/ + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + + call s:Bookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call s:Bookmark.Write() + + if !empty(oldMarkedNode) + call oldMarkedNode.path.cacheDisplayString() + endif +endfunction +"FUNCTION: TreeFileNode.cacheParent() {{{3 +"initializes self.parent if it isnt already +function! s:TreeFileNode.cacheParent() + if empty(self.parent) + let parentPath = self.path.getParent() + if parentPath.equals(self.path) + throw "NERDTree.CannotCacheParentError: already at root" + endif + let self.parent = s:TreeFileNode.New(parentPath) + endif +endfunction +"FUNCTION: TreeFileNode.compareNodes {{{3 +"This is supposed to be a class level method but i cant figure out how to +"get func refs to work from a dict.. +" +"A class level method that compares two nodes +" +"Args: +"n1, n2: the 2 nodes to compare +function! s:compareNodes(n1, n2) + return a:n1.path.compareTo(a:n2.path) +endfunction + +"FUNCTION: TreeFileNode.clearBoomarks() {{{3 +function! s:TreeFileNode.clearBoomarks() + for i in s:Bookmark.Bookmarks() + if i.path.equals(self.path) + call i.delete() + end + endfor + call self.path.cacheDisplayString() +endfunction +"FUNCTION: TreeFileNode.copy(dest) {{{3 +function! s:TreeFileNode.copy(dest) + call self.path.copy(a:dest) + let newPath = s:Path.New(a:dest) + let parent = b:NERDTreeRoot.findNode(newPath.getParent()) + if !empty(parent) + call parent.refresh() + 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 + if winnr() == s:getTreeWinNum() + wincmd p + let bufnr = bufnr("") + wincmd p + else + let bufnr = bufnr("") + endif + + call s:exec(s:getTreeWinNum() . " wincmd w") + close + call s:exec(bufwinnr(bufnr) . " wincmd w") + else + close + endif +endfunction + +"FUNCTION: s:closeTreeIfOpen() {{{2 +"Closes the NERD tree window if it is open +function! s:closeTreeIfOpen() + if s:isTreeOpen() + call s:closeTree() + endif +endfunction +"FUNCTION: s:closeTreeIfQuitOnOpen() {{{2 +"Closes the NERD tree window if the close on open option is set +function! s:closeTreeIfQuitOnOpen() + if g:NERDTreeQuitOnOpen && s:isTreeOpen() + call s:closeTree() + endif +endfunction +"FUNCTION: s:createTreeWin() {{{2 +"Inits the NERD tree window. ie. opens it, sizes it, sets all the local +"options etc +function! s:createTreeWin() + "create the nerd tree window + let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright " + let splitSize = g:NERDTreeWinSize + + if !exists('t:NERDTreeBufName') + let t:NERDTreeBufName = s:nextBufferName() + silent! exec splitLocation . 'vertical ' . splitSize . ' new' + silent! exec "edit " . t:NERDTreeBufName + else + silent! exec splitLocation . 'vertical ' . splitSize . ' split' + silent! exec "buffer " . t:NERDTreeBufName + endif + + setlocal winfixwidth + + "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: diff --git a/.vim/bundle/snipmate/README.markdown b/.vim/bundle/snipmate/README.markdown new file mode 100644 index 0000000..160f807 --- /dev/null +++ b/.vim/bundle/snipmate/README.markdown @@ -0,0 +1,5 @@ +Quickly install with: + + git clone git://github.com/msanders/snipmate.vim.git + cd snipmate.vim + cp -R * ~/.vim diff --git a/.vim/bundle/snipmate/after/plugin/snipMate.vim b/.vim/bundle/snipmate/after/plugin/snipMate.vim new file mode 100644 index 0000000..bdbe199 --- /dev/null +++ b/.vim/bundle/snipmate/after/plugin/snipMate.vim @@ -0,0 +1,40 @@ +" These are the mappings for snipMate.vim. Putting it here ensures that it +" will be mapped after other plugins such as supertab.vim. +if !exists('loaded_snips') || exists('s:did_snips_mappings') + finish +endif +let s:did_snips_mappings = 1 + +" This is put here in the 'after' directory in order for snipMate to override +" other plugin mappings (e.g., supertab). +" +" You can safely adjust these mappings to your preferences (as explained in +" :help snipMate-remap). +ino =TriggerSnippet() +snor i=TriggerSnippet() +ino =BackwardsSnippet() +snor i=BackwardsSnippet() +ino =ShowAvailableSnips() + +" The default mappings for these are annoying & sometimes break snipMate. +" You can change them back if you want, I've put them here for convenience. +snor b +snor a +snor bi +snor ' b' +snor ` b` +snor % b% +snor U bU +snor ^ b^ +snor \ b\ +snor b + +" By default load snippets in snippets_dir +if empty(snippets_dir) + finish +endif + +call GetSnippets(snippets_dir, '_') " Get global snippets + +au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/snipmate/autoload/snipMate.vim b/.vim/bundle/snipmate/autoload/snipMate.vim new file mode 100644 index 0000000..0ad5a58 --- /dev/null +++ b/.vim/bundle/snipmate/autoload/snipMate.vim @@ -0,0 +1,435 @@ +fun! Filename(...) + let filename = expand('%:t:r') + if filename == '' | return a:0 == 2 ? a:2 : '' | endif + return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') +endf + +fun s:RemoveSnippet() + unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen + \ s:lastBuf s:oldWord + if exists('s:update') + unl s:startCol s:origWordLen s:update + if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif + endif + aug! snipMateAutocmds +endf + +fun snipMate#expandSnip(snip, col) + let lnum = line('.') | let col = a:col + + let snippet = s:ProcessSnippet(a:snip) + " Avoid error if eval evaluates to nothing + if snippet == '' | return '' | endif + + " Expand snippet onto current position with the tab stops removed + let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1) + + let line = getline(lnum) + let afterCursor = strpart(line, col - 1) + " Keep text after the cursor + if afterCursor != "\t" && afterCursor != ' ' + let line = strpart(line, 0, col - 1) + let snipLines[-1] .= afterCursor + else + let afterCursor = '' + " For some reason the cursor needs to move one right after this + if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' + let col += 1 + endif + endif + + call setline(lnum, line.snipLines[0]) + + " Autoindent snippet according to previous indentation + let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1 + call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val")) + + " Open any folds snippet expands into + if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif + + let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent) + + if s:snipLen + aug snipMateAutocmds + au CursorMovedI * call s:UpdateChangedSnip(0) + au InsertEnter * call s:UpdateChangedSnip(1) + aug END + let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer + let s:curPos = 0 + let s:endCol = g:snipPos[s:curPos][1] + let s:endLine = g:snipPos[s:curPos][0] + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + let s:prevLen = [line('$'), col('$')] + if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif + else + unl g:snipPos s:snipLen + " Place cursor at end of snippet if no tab stop is given + let newlines = len(snipLines) - 1 + call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor) + \ + (newlines ? 0: col - 1)) + endif + return '' +endf + +" Prepare snippet to be processed by s:BuildTabStops +fun s:ProcessSnippet(snip) + let snippet = a:snip + " Evaluate eval (`...`) expressions. + " Backquotes prefixed with a backslash "\" are ignored. + " Using a loop here instead of a regex fixes a bug with nested "\=". + if stridx(snippet, '`') != -1 + while match(snippet, '\(^\|[^\\]\)`.\{-}[^\\]`') != -1 + let snippet = substitute(snippet, '\(^\|[^\\]\)\zs`.\{-}[^\\]`\ze', + \ substitute(eval(matchstr(snippet, '\(^\|[^\\]\)`\zs.\{-}[^\\]\ze`')), + \ "\n\\%$", '', ''), '') + endw + let snippet = substitute(snippet, "\r", "\n", 'g') + let snippet = substitute(snippet, '\\`', '`', 'g') + endif + + " Place all text after a colon in a tab stop after the tab stop + " (e.g. "${#:foo}" becomes "${:foo}foo"). + " This helps tell the position of the tab stops later. + let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g') + + " Update the a:snip so that all the $# become the text after + " the colon in their associated ${#}. + " (e.g. "${1:foo}" turns all "$1"'s into "foo") + let i = 1 + while stridx(snippet, '${'.i) != -1 + let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}') + if s != '' + let snippet = substitute(snippet, '$'.i, s.'&', 'g') + endif + let i += 1 + endw + + if &et " Expand tabs to spaces if 'expandtab' is set. + return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g') + endif + return snippet +endf + +" Counts occurences of haystack in needle +fun s:Count(haystack, needle) + let counter = 0 + let index = stridx(a:haystack, a:needle) + while index != -1 + let index = stridx(a:haystack, a:needle, index+1) + let counter += 1 + endw + return counter +endf + +" Builds a list of a list of each tab stop in the snippet containing: +" 1.) The tab stop's line number. +" 2.) The tab stop's column number +" (by getting the length of the string between the last "\n" and the +" tab stop). +" 3.) The length of the text after the colon for the current tab stop +" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned. +" 4.) If the "${#:}" construct is given, another list containing all +" the matches of "$#", to be replaced with the placeholder. This list is +" composed the same way as the parent; the first item is the line number, +" and the second is the column. +fun s:BuildTabStops(snip, lnum, col, indent) + let snipPos = [] + let i = 1 + let withoutVars = substitute(a:snip, '$\d\+', '', 'g') + while stridx(a:snip, '${'.i) != -1 + let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D') + let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g') + + let j = i - 1 + call add(snipPos, [0, 0, -1]) + let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n") + let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D')) + if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif + + " Get all $# matches in another list, if ${#:name} is given + if stridx(withoutVars, '${'.i.':') != -1 + let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}')) + let dots = repeat('.', snipPos[j][2]) + call add(snipPos[j], []) + let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g') + while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1 + let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)') + call add(snipPos[j][3], [0, 0]) + let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n") + let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum + \ ? len(matchstr(beforeMark, '.*\n\zs.*')) + \ : a:col + len(beforeMark)) + let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '') + endw + endif + let i += 1 + endw + return [snipPos, i - 1] +endf + +fun snipMate#jumpTabStop(backwards) + let leftPlaceholder = exists('s:origWordLen') + \ && s:origWordLen != g:snipPos[s:curPos][2] + if leftPlaceholder && exists('s:oldEndCol') + let startPlaceholder = s:oldEndCol + 1 + endif + + if exists('s:update') + call s:UpdatePlaceholderTabStops() + else + call s:UpdateTabStops() + endif + + " Don't reselect placeholder if it has been modified + if leftPlaceholder && g:snipPos[s:curPos][2] != -1 + if exists('startPlaceholder') + let g:snipPos[s:curPos][1] = startPlaceholder + else + let g:snipPos[s:curPos][1] = col('.') + let g:snipPos[s:curPos][2] = 0 + endif + endif + + let s:curPos += a:backwards ? -1 : 1 + " Loop over the snippet when going backwards from the beginning + if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif + + if s:curPos == s:snipLen + let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2] + call s:RemoveSnippet() + return sMode ? "\" : TriggerSnippet() + endif + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + + let s:endLine = g:snipPos[s:curPos][0] + let s:endCol = g:snipPos[s:curPos][1] + let s:prevLen = [line('$'), col('$')] + + return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord() +endf + +fun s:UpdatePlaceholderTabStops() + let changeLen = s:origWordLen - g:snipPos[s:curPos][2] + unl s:startCol s:origWordLen s:update + if !exists('s:oldVars') | return | endif + " Update tab stops in snippet if text has been added via "$#" + " (e.g., in "${1:foo}bar$1${2}"). + if changeLen != 0 + let curLine = line('.') + + for pos in g:snipPos + if pos == g:snipPos[s:curPos] | continue | endif + let changed = pos[0] == curLine && pos[1] > s:oldEndCol + let changedVars = 0 + let endPlaceholder = pos[2] - 1 + pos[1] + " Subtract changeLen from each tab stop that was after any of + " the current tab stop's placeholders. + for [lnum, col] in s:oldVars + if lnum > pos[0] | break | endif + if pos[0] == lnum + if pos[1] > col || (pos[2] == -1 && pos[1] == col) + let changed += 1 + elseif col < endPlaceholder + let changedVars += 1 + endif + endif + endfor + let pos[1] -= changeLen * changed + let pos[2] -= changeLen * changedVars " Parse variables within placeholders + " e.g., "${1:foo} ${2:$1bar}" + + if pos[2] == -1 | continue | endif + " Do the same to any placeholders in the other tab stops. + for nPos in pos[3] + let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol + for [lnum, col] in s:oldVars + if lnum > nPos[0] | break | endif + if nPos[0] == lnum && nPos[1] > col + let changed += 1 + endif + endfor + let nPos[1] -= changeLen * changed + endfor + endfor + endif + unl s:endCol s:oldVars s:oldEndCol +endf + +fun s:UpdateTabStops() + let changeLine = s:endLine - g:snipPos[s:curPos][0] + let changeCol = s:endCol - g:snipPos[s:curPos][1] + if exists('s:origWordLen') + let changeCol -= s:origWordLen + unl s:origWordLen + endif + let lnum = g:snipPos[s:curPos][0] + let col = g:snipPos[s:curPos][1] + " Update the line number of all proceeding tab stops if has + " been inserted. + if changeLine != 0 + let changeLine -= 1 + for pos in g:snipPos + if pos[0] >= lnum + if pos[0] == lnum | let pos[1] += changeCol | endif + let pos[0] += changeLine + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] >= lnum + if nPos[0] == lnum | let nPos[1] += changeCol | endif + let nPos[0] += changeLine + endif + endfor + endfor + elseif changeCol != 0 + " Update the column of all proceeding tab stops if text has + " been inserted/deleted in the current line. + for pos in g:snipPos + if pos[1] >= col && pos[0] == lnum + let pos[1] += changeCol + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] >= col + let nPos[1] += changeCol + endif + endfor + endfor + endif +endf + +fun s:SelectWord() + let s:origWordLen = g:snipPos[s:curPos][2] + let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1, + \ s:origWordLen) + let s:prevLen[1] -= s:origWordLen + if !empty(g:snipPos[s:curPos][3]) + let s:update = 1 + let s:endCol = -1 + let s:startCol = g:snipPos[s:curPos][1] - 1 + endif + if !s:origWordLen | return '' | endif + let l = col('.') != 1 ? 'l' : '' + if &sel == 'exclusive' + return "\".l.'v'.s:origWordLen."l\" + endif + return s:origWordLen == 1 ? "\".l.'gh' + \ : "\".l.'v'.(s:origWordLen - 1)."l\" +endf + +" This updates the snippet as you type when text needs to be inserted +" into multiple places (e.g. in "${1:default text}foo$1bar$1", +" "default text" would be highlighted, and if the user types something, +" UpdateChangedSnip() would be called so that the text after "foo" & "bar" +" are updated accordingly) +" +" It also automatically quits the snippet if the cursor is moved out of it +" while in insert mode. +fun s:UpdateChangedSnip(entering) + if exists('g:snipPos') && bufnr(0) != s:lastBuf + call s:RemoveSnippet() + elseif exists('s:update') " If modifying a placeholder + if !exists('s:oldVars') && s:curPos + 1 < s:snipLen + " Save the old snippet & word length before it's updated + " s:startCol must be saved too, in case text is added + " before the snippet (e.g. in "foo$1${2}bar${1:foo}"). + let s:oldEndCol = s:startCol + let s:oldVars = deepcopy(g:snipPos[s:curPos][3]) + endif + let col = col('.') - 1 + + if s:endCol != -1 + let changeLen = col('$') - s:prevLen[1] + let s:endCol += changeLen + else " When being updated the first time, after leaving select mode + if a:entering | return | endif + let s:endCol = col - 1 + endif + + " If the cursor moves outside the snippet, quit it + if line('.') != g:snipPos[s:curPos][0] || col < s:startCol || + \ col - 1 > s:endCol + unl! s:startCol s:origWordLen s:oldVars s:update + return s:RemoveSnippet() + endif + + call s:UpdateVars() + let s:prevLen[1] = col('$') + elseif exists('g:snipPos') + if !a:entering && g:snipPos[s:curPos][2] != -1 + let g:snipPos[s:curPos][2] = -2 + endif + + let col = col('.') + let lnum = line('.') + let changeLine = line('$') - s:prevLen[0] + + if lnum == s:endLine + let s:endCol += col('$') - s:prevLen[1] + let s:prevLen = [line('$'), col('$')] + endif + if changeLine != 0 + let s:endLine += changeLine + let s:endCol = col + endif + + " Delete snippet if cursor moves out of it in insert mode + if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1])) + \ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0] + call s:RemoveSnippet() + endif + endif +endf + +" This updates the variables in a snippet when a placeholder has been edited. +" (e.g., each "$1" in "${1:foo} $1bar $1bar") +fun s:UpdateVars() + let newWordLen = s:endCol - s:startCol + 1 + let newWord = strpart(getline('.'), s:startCol, newWordLen) + if newWord == s:oldWord || empty(g:snipPos[s:curPos][3]) + return + endif + + let changeLen = g:snipPos[s:curPos][2] - newWordLen + let curLine = line('.') + let startCol = col('.') + let oldStartSnip = s:startCol + let updateTabStops = changeLen != 0 + let i = 0 + + for [lnum, col] in g:snipPos[s:curPos][3] + if updateTabStops + let start = s:startCol + if lnum == curLine && col <= start + let s:startCol -= changeLen + let s:endCol -= changeLen + endif + for nPos in g:snipPos[s:curPos][3][(i):] + " This list is in ascending order, so quit if we've gone too far. + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] > col + let nPos[1] -= changeLen + endif + endfor + if lnum == curLine && col > start + let col -= changeLen + let g:snipPos[s:curPos][3][i][1] = col + endif + let i += 1 + endif + + " "Very nomagic" is used here to allow special characters. + call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'. + \ escape(s:oldWord, '\'), escape(newWord, '\&'), '')) + endfor + if oldStartSnip != s:startCol + call cursor(0, startCol + s:startCol - oldStartSnip) + endif + + let s:oldWord = newWord + let g:snipPos[s:curPos][2] = newWordLen +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/snipmate/doc/snipMate.txt b/.vim/bundle/snipmate/doc/snipMate.txt new file mode 100644 index 0000000..521235d --- /dev/null +++ b/.vim/bundle/snipmate/doc/snipMate.txt @@ -0,0 +1,322 @@ +*snipMate.txt* Plugin for using TextMate-style snippets in Vim. + +snipMate *snippet* *snippets* *snipMate* +Last Change: December 27, 2009 + +|snipMate-description| Description +|snipMate-syntax| Snippet syntax +|snipMate-usage| Usage +|snipMate-settings| Settings +|snipMate-features| Features +|snipMate-disadvantages| Disadvantages to TextMate +|snipMate-contact| Contact +|snipMate-license| License + +For Vim version 7.0 or later. +This plugin only works if 'compatible' is not set. +{Vi does not have any of these features.} + +============================================================================== +DESCRIPTION *snipMate-description* + +snipMate.vim implements some of TextMate's snippets features in Vim. A +snippet is a piece of often-typed text that you can insert into your +document using a trigger word followed by a . + +For instance, in a C file using the default installation of snipMate.vim, if +you type "for" in insert mode, it will expand a typical for loop in C: > + + for (i = 0; i < count; i++) { + + } + + +To go to the next item in the loop, simply over to it; if there is +repeated code, such as the "i" variable in this example, you can simply +start typing once it's highlighted and all the matches specified in the +snippet will be updated. To go in reverse, use . + +============================================================================== +SYNTAX *snippet-syntax* + +Snippets can be defined in two ways. They can be in their own file, named +after their trigger in 'snippets//.snippet', or they can be +defined together in a 'snippets/.snippets' file. Note that dotted +'filetype' syntax is supported -- e.g., you can use > + + :set ft=html.eruby + +to activate snippets for both HTML and eRuby for the current file. + +The syntax for snippets in *.snippets files is the following: > + + snippet trigger + expanded text + more expanded text + +Note that the first hard tab after the snippet trigger is required, and not +expanded in the actual snippet. The syntax for *.snippet files is the same, +only without the trigger declaration and starting indentation. + +Also note that snippets must be defined using hard tabs. They can be expanded +to spaces later if desired (see |snipMate-indenting|). + +"#" is used as a line-comment character in *.snippets files; however, they can +only be used outside of a snippet declaration. E.g.: > + + # this is a correct comment + snippet trigger + expanded text + snippet another_trigger + # this isn't a comment! + expanded text +< +This should hopefully be obvious with the included syntax highlighting. + + *snipMate-${#}* +Tab stops ~ + +By default, the cursor is placed at the end of a snippet. To specify where the +cursor is to be placed next, use "${#}", where the # is the number of the tab +stop. E.g., to place the cursor first on the id of a
tag, and then allow +the user to press to go to the middle of it: + > + snippet div +
+ ${2} +
+< + *snipMate-placeholders* *snipMate-${#:}* *snipMate-$#* +Placeholders ~ + +Placeholder text can be supplied using "${#:text}", where # is the number of +the tab stop. This text then can be copied throughout the snippet using "$#", +given # is the same number as used before. So, to make a C for loop: > + + snippet for + for (${2:i}; $2 < ${1:count}; $1++) { + ${4} + } + +This will cause "count" to first be selected and change if the user starts +typing. When is pressed, the "i" in ${2}'s position will be selected; +all $2 variables will default to "i" and automatically be updated if the user +starts typing. +NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate. + +Variables within variables are also possible. For instance: > + + snippet opt + + +Will, as usual, cause "option" to first be selected and update all the $1 +variables if the user starts typing. Since one of these variables is inside of +${2}, this text will then be used as a placeholder for the next tab stop, +allowing the user to change it if he wishes. + +To copy a value throughout a snippet without supplying default text, simply +use the "${#:}" construct without the text; e.g.: > + + snippet foo + ${1:}bar$1 +< *snipMate-commands* +Interpolated Vim Script ~ + +Snippets can also contain Vim script commands that are executed (via |eval()|) +when the snippet is inserted. Commands are given inside backticks (`...`); for +TextMates's functionality, use the |system()| function. E.g.: > + + snippet date + `system("date +%Y-%m-%d")` + +will insert the current date, assuming you are on a Unix system. Note that you +can also (and should) use |strftime()| for this example. + +Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()* + +Since the current filename is used often in snippets, a default function +has been defined for it in snipMate.vim, appropriately called Filename(). + +With no arguments, the default filename without an extension is returned; +the first argument specifies what to place before or after the filename, +and the second argument supplies the default text to be used if the file +has not been named. "$1" in the first argument is replaced with the filename; +if you only want the filename to be returned, the first argument can be left +blank. Examples: > + + snippet filename + `Filename()` + snippet filename_with_default + `Filename('', 'name')` + snippet filename_foo + `filename('$1_foo')` + +The first example returns the filename if it the file has been named, and an +empty string if it hasn't. The second returns the filename if it's been named, +and "name" if it hasn't. The third returns the filename followed by "_foo" if +it has been named, and an empty string if it hasn't. + + *multi_snip* +To specify that a snippet can have multiple matches in a *.snippets file, use +this syntax: > + + snippet trigger A description of snippet #1 + expand this text + snippet trigger A description of snippet #2 + expand THIS text! + +In this example, when "trigger" is typed, a numbered menu containing all +of the descriptions of the "trigger" will be shown; when the user presses the +corresponding number, that snippet will then be expanded. + +To create a snippet with multiple matches using *.snippet files, +simply place all the snippets in a subdirectory with the trigger name: +'snippets///.snippet'. + +============================================================================== +USAGE *snipMate-usage* + + *'snippets'* *g:snippets_dir* +Snippets are by default looked for any 'snippets' directory in your +'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or +'$HOME\vimfiles\snippets\' on Windows. To change that location or add another +one, change the g:snippets_dir variable in your |.vimrc| to your preferred +directory, or use the |ExtractSnips()|function. This will be used by the +|globpath()| function, and so accepts the same syntax as it (e.g., +comma-separated paths). + +ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets* + +ExtractSnipsFile() extracts the specified *.snippets file for the given +filetype. A .snippets file contains multiple snippet declarations for the +filetype. It is further explained above, in |snippet-syntax|. + +ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet* + +ExtractSnips() extracts *.snippet files from the specified directory and +defines them as snippets for the given filetype. The directory tree should +look like this: 'snippets//.snippet'. If the snippet has +multiple matches, it should look like this: +'snippets///.snippet' (see |multi_snip|). + +ResetAllSnippets() *ResetAllSnippets()* +ResetAllSnippets() removes all snippets from memory. This is useful to put at +the top of a snippet setup file for if you would like to |:source| it multiple +times. + +ResetSnippets({filetype}) *ResetSnippets()* +ResetSnippets() removes all snippets from memory for the given filetype. + +ReloadAllSnippets() *ReloadAllSnippets()* +ReloadAllSnippets() reloads all snippets for all filetypes. This is useful for +testing and debugging. + +ReloadSnippets({filetype}) *ReloadSnippets()* +ReloadSnippets() reloads all snippets for the given filetype. + + *list-snippets* *i_CTRL-R_* +If you would like to see what snippets are available, simply type +in the current buffer to show a list via |popupmenu-completion|. + +============================================================================== +SETTINGS *snipMate-settings* *g:snips_author* + +The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set +to your name; it can then be used in snippets to automatically add it. E.g.: > + + let g:snips_author = 'Hubert Farnsworth' + snippet name + `g:snips_author` +< + *snipMate-expandtab* *snipMate-indenting* +If you would like your snippets to be expanded using spaces instead of tabs, +just enable 'expandtab' and set 'softtabstop' to your preferred amount of +spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead. + + *snipMate-remap* +snipMate does not come with a setting to customize the trigger key, but you +can remap it easily in the two lines it's defined in the 'after' directory +under 'plugin/snipMate.vim'. For instance, to change the trigger key +to CTRL-J, just change this: > + + ino =TriggerSnippet() + snor i=TriggerSnippet() + +to this: > + ino =TriggerSnippet() + snor i=TriggerSnippet() + +============================================================================== +FEATURES *snipMate-features* + +snipMate.vim has the following features among others: + - The syntax of snippets is very similar to TextMate's, allowing + easy conversion. + - The position of the snippet is kept transparently (i.e. it does not use + markers/placeholders written to the buffer), which allows you to escape + out of an incomplete snippet, something particularly useful in Vim. + - Variables in snippets are updated as-you-type. + - Snippets can have multiple matches. + - Snippets can be out of order. For instance, in a do...while loop, the + condition can be added before the code. + - [New] File-based snippets are supported. + - [New] Triggers after non-word delimiters are expanded, e.g. "foo" + in "bar.foo". + - [New] can now be used to jump tab stops in reverse order. + +============================================================================== +DISADVANTAGES *snipMate-disadvantages* + +snipMate.vim currently has the following disadvantages to TextMate's snippets: + - There is no $0; the order of tab stops must be explicitly stated. + - Placeholders within placeholders are not possible. E.g.: > + + '${3}
' +< + In TextMate this would first highlight ' id="some_id"', and if + you hit delete it would automatically skip ${2} and go to ${3} + on the next , but if you didn't delete it it would highlight + "some_id" first. You cannot do this in snipMate.vim. + - Regex cannot be performed on variables, such as "${1/.*/\U&}" + - Placeholders cannot span multiple lines. + - Activating snippets in different scopes of the same file is + not possible. + +Perhaps some of these features will be added in a later release. + +============================================================================== +CONTACT *snipMate-contact* *snipMate-author* + +To contact the author (Michael Sanders), please email: + msanders42+snipmate gmail com + +I greatly appreciate any suggestions or improvements offered for the script. + +============================================================================== +LICENSE *snipMate-license* + +snipMate is released under the MIT license: + +Copyright 2009-2010 Michael Sanders. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The software is provided "as is", without warranty of any kind, express or +implied, including but not limited to the warranties of merchantability, +fitness for a particular purpose and noninfringement. In no event shall the +authors or copyright holders be liable for any claim, damages or other +liability, whether in an action of contract, tort or otherwise, arising from, +out of or in connection with the software or the use or other dealings in the +software. + +============================================================================== + +vim:tw=78:ts=8:ft=help:norl: diff --git a/.vim/bundle/snipmate/ftplugin/html_snip_helper.vim b/.vim/bundle/snipmate/ftplugin/html_snip_helper.vim new file mode 100644 index 0000000..2e54570 --- /dev/null +++ b/.vim/bundle/snipmate/ftplugin/html_snip_helper.vim @@ -0,0 +1,10 @@ +" Helper function for (x)html snippets +if exists('s:did_snip_helper') || &cp || !exists('loaded_snips') + finish +endif +let s:did_snip_helper = 1 + +" Automatically closes tag if in xhtml +fun! Close() + return stridx(&ft, 'xhtml') == -1 ? '' : ' /' +endf diff --git a/.vim/bundle/snipmate/plugin-info.txt b/.vim/bundle/snipmate/plugin-info.txt new file mode 100644 index 0000000..0936bc1 --- /dev/null +++ b/.vim/bundle/snipmate/plugin-info.txt @@ -0,0 +1,8 @@ +{ + "name" : "snipmate", + "version" : "dev", + "author" : "Michael Sanders ", + "repository" : {"type": "git", "url": "git://github.com/msanders/snipmate.vim.git"}, + "dependencies" : {}, + "description" : "snipMate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim." +} diff --git a/.vim/bundle/snipmate/plugin/snipMate.vim b/.vim/bundle/snipmate/plugin/snipMate.vim new file mode 100644 index 0000000..ef03b12 --- /dev/null +++ b/.vim/bundle/snipmate/plugin/snipMate.vim @@ -0,0 +1,271 @@ +" File: snipMate.vim +" Author: Michael Sanders +" Version: 0.84 +" Description: snipMate.vim implements some of TextMate's snippets features in +" Vim. A snippet is a piece of often-typed text that you can +" insert into your document using a trigger word followed by a "". +" +" For more help see snipMate.txt; you can do this by using: +" :helptags ~/.vim/doc +" :h snipMate.txt + +if exists('loaded_snips') || &cp || version < 700 + finish +endif +let loaded_snips = 1 +if !exists('snips_author') | let snips_author = 'Me' | endif + +au BufRead,BufNewFile *.snippets\= set ft=snippet +au FileType snippet setl noet fdm=indent + +let s:snippets = {} | let s:multi_snips = {} + +if !exists('snippets_dir') + let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g') +endif + +fun! MakeSnip(scope, trigger, content, ...) + let multisnip = a:0 && a:1 != '' + let var = multisnip ? 's:multi_snips' : 's:snippets' + if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif + if !has_key({var}[a:scope], a:trigger) + let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content + elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]] + else + echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.' + \ .' See :h multi_snip for help on snippets with multiple matches.' + endif +endf + +fun! ExtractSnips(dir, ft) + for path in split(globpath(a:dir, '*'), "\n") + if isdirectory(path) + let pathname = fnamemodify(path, ':t') + for snipFile in split(globpath(path, '*.snippet'), "\n") + call s:ProcessFile(snipFile, a:ft, pathname) + endfor + elseif fnamemodify(path, ':e') == 'snippet' + call s:ProcessFile(path, a:ft) + endif + endfor +endf + +" Processes a single-snippet file; optionally add the name of the parent +" directory for a snippet with multiple matches. +fun s:ProcessFile(file, ft, ...) + let keyword = fnamemodify(a:file, ':t:r') + if keyword == '' | return | endif + try + let text = join(readfile(a:file), "\n") + catch /E484/ + echom "Error in snipMate.vim: couldn't read file: ".a:file + endtry + return a:0 ? MakeSnip(a:ft, a:1, text, keyword) + \ : MakeSnip(a:ft, keyword, text) +endf + +fun! ExtractSnipsFile(file, ft) + if !filereadable(a:file) | return | endif + let text = readfile(a:file) + let inSnip = 0 + for line in text + ["\n"] + if inSnip && (line[0] == "\t" || line == '') + let content .= strpart(line, 1)."\n" + continue + elseif inSnip + call MakeSnip(a:ft, trigger, content[:-2], name) + let inSnip = 0 + endif + + if line[:6] == 'snippet' + let inSnip = 1 + let trigger = strpart(line, 8) + let name = '' + let space = stridx(trigger, ' ') + 1 + if space " Process multi snip + let name = strpart(trigger, space) + let trigger = strpart(trigger, 0, space - 1) + endif + let content = '' + endif + endfor +endf + +" Reset snippets for filetype. +fun! ResetSnippets(ft) + let ft = a:ft == '' ? '_' : a:ft + for dict in [s:snippets, s:multi_snips, g:did_ft] + if has_key(dict, ft) + unlet dict[ft] + endif + endfor +endf + +" Reset snippets for all filetypes. +fun! ResetAllSnippets() + let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {} +endf + +" Reload snippets for filetype. +fun! ReloadSnippets(ft) + let ft = a:ft == '' ? '_' : a:ft + call ResetSnippets(ft) + call GetSnippets(g:snippets_dir, ft) +endf + +" Reload snippets for all filetypes. +fun! ReloadAllSnippets() + for ft in keys(g:did_ft) + call ReloadSnippets(ft) + endfor +endf + +let g:did_ft = {} +fun! GetSnippets(dir, filetypes) + for ft in split(a:filetypes, '\.') + if has_key(g:did_ft, ft) | continue | endif + call s:DefineSnips(a:dir, ft, ft) + if ft == 'objc' || ft == 'cpp' || ft == 'cs' + call s:DefineSnips(a:dir, 'c', ft) + elseif ft == 'xhtml' + call s:DefineSnips(a:dir, 'html', 'xhtml') + endif + let g:did_ft[ft] = 1 + endfor +endf + +" Define "aliasft" snippets for the filetype "realft". +fun s:DefineSnips(dir, aliasft, realft) + for path in split(globpath(a:dir, a:aliasft.'/')."\n". + \ globpath(a:dir, a:aliasft.'-*/'), "\n") + call ExtractSnips(path, a:realft) + endfor + for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n". + \ globpath(a:dir, a:aliasft.'-*.snippets'), "\n") + call ExtractSnipsFile(path, a:realft) + endfor +endf + +fun! TriggerSnippet() + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingForward == "" + let SuperTabKey = "\" + elseif g:SuperTabMappingBackward == "" + let SuperTabKey = "\" + endif + endif + + if pumvisible() " Update snippet if completion is used, or deal with supertab + if exists('SuperTabKey') + call feedkeys(SuperTabKey) | return '' + endif + call feedkeys("\a", 'n') " Close completion menu + call feedkeys("\") | return '' + endif + + if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif + + let word = matchstr(getline('.'), '\S\+\%'.col('.').'c') + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let [trigger, snippet] = s:GetSnippet(word, scope) + " If word is a trigger for a snippet, delete the trigger & expand + " the snippet. + if snippet != '' + let col = col('.') - len(trigger) + sil exe 's/\V'.escape(trigger, '/\.').'\%#//' + return snipMate#expandSnip(snippet, col) + endif + endfor + + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\" +endf + +fun! BackwardsSnippet() + if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif + + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingBackward == "" + let SuperTabKey = "\" + elseif g:SuperTabMappingForward == "" + let SuperTabKey = "\" + endif + endif + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\" +endf + +" Check if word under cursor is snippet trigger; if it isn't, try checking if +" the text after non-word characters is (e.g. check for "foo" in "bar.foo") +fun s:GetSnippet(word, scope) + let word = a:word | let snippet = '' + while snippet == '' + if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:snippets[a:scope][word] + elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:ChooseSnippet(a:scope, word) + if snippet == '' | break | endif + else + if match(word, '\W') == -1 | break | endif + let word = substitute(word, '.\{-}\W', '', '') + endif + endw + if word == '' && a:word != '.' && stridx(a:word, '.') != -1 + let [word, snippet] = s:GetSnippet('.', a:scope) + endif + return [word, snippet] +endf + +fun s:ChooseSnippet(scope, trigger) + let snippet = [] + let i = 1 + for snip in s:multi_snips[a:scope][a:trigger] + let snippet += [i.'. '.snip[0]] + let i += 1 + endfor + if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif + let num = inputlist(snippet) - 1 + return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1] +endf + +fun! ShowAvailableSnips() + let line = getline('.') + let col = col('.') + let word = matchstr(getline('.'), '\S\+\%'.col.'c') + let words = [word] + if stridx(word, '.') + let words += split(word, '\.', 1) + endif + let matchlen = 0 + let matches = [] + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : [] + if has_key(s:multi_snips, scope) + let triggers += keys(s:multi_snips[scope]) + endif + for trigger in triggers + for word in words + if word == '' + let matches += [trigger] " Show all matches if word is empty + elseif trigger =~ '^'.word + let matches += [trigger] + let len = len(word) + if len > matchlen | let matchlen = len | endif + endif + endfor + endfor + endfor + + " This is to avoid a bug with Vim when using complete(col - matchlen, matches) + " (Issue#46 on the Google Code snipMate issue tracker). + call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', '')) + call complete(col, matches) + return '' +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/snipmate/snippets/_.snippets b/.vim/bundle/snipmate/snippets/_.snippets new file mode 100644 index 0000000..d3ee355 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/_.snippets @@ -0,0 +1,9 @@ +# Global snippets + +# (c) holds no legal value ;) +snippet c) + Copyright `&enc[:2] == "utf" ? "©" : "(c)"` `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2} +snippet date + `strftime("%Y-%m-%d")` +snippet ddate + `strftime("%B %d, %Y")` diff --git a/.vim/bundle/snipmate/snippets/autoit.snippets b/.vim/bundle/snipmate/snippets/autoit.snippets new file mode 100644 index 0000000..690018c --- /dev/null +++ b/.vim/bundle/snipmate/snippets/autoit.snippets @@ -0,0 +1,66 @@ +snippet if + If ${1:condition} Then + ${2:; True code} + EndIf +snippet el + Else + ${1} +snippet elif + ElseIf ${1:condition} Then + ${2:; True code} +# If/Else block +snippet ifel + If ${1:condition} Then + ${2:; True code} + Else + ${3:; Else code} + EndIf +# If/ElseIf/Else block +snippet ifelif + If ${1:condition 1} Then + ${2:; True code} + ElseIf ${3:condition 2} Then + ${4:; True code} + Else + ${5:; Else code} + EndIf +# Switch block +snippet switch + Switch (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSwitch +# Select block +snippet select + Select (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSelect +# While loop +snippet while + While (${1:condition}) + ${2:; code...} + WEnd +# For loop +snippet for + For ${1:n} = ${3:1} to ${2:count} + ${4:; code...} + Next +# New Function +snippet func + Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${4:Return} + EndFunc +# Message box +snippet msg + MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"}) +# Debug Message +snippet debug + MsgBox(0, "Debug", ${1:"Debug Message"}) +# Show Variable Debug Message +snippet showvar + MsgBox(0, "${1:VarName}", $1) diff --git a/.vim/bundle/snipmate/snippets/c.snippets b/.vim/bundle/snipmate/snippets/c.snippets new file mode 100644 index 0000000..e1c4f05 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/c.snippets @@ -0,0 +1,113 @@ +# main() +snippet main + int main(int argc, const char *argv[]) + { + ${1} + return 0; + } +snippet mainn + int main(void) + { + ${1} + return 0; + } +# #include <...> +snippet inc + #include <${1:stdio}.h>${2} +# #include "..." +snippet Inc + #include "${1:`Filename("$1.h")`}"${2} +# #ifndef ... #define ... #endif +snippet Def + #ifndef $1 + #define ${1:SYMBOL} ${2:value} + #endif${3} +snippet def + #define +snippet ifdef + #ifdef ${1:FOO} + ${2:#define } + #endif +snippet #if + #if ${1:FOO} + ${2} + #endif +# Header Include-Guard +snippet once + #ifndef ${1:`toupper(Filename('$1_H', 'UNTITLED_H'))`} + + #define $1 + + ${2} + + #endif /* end of include guard: $1 */ +# If Condition +snippet if + if (${1:/* condition */}) { + ${2:/* code */} + } +snippet el + else { + ${1} + } +# Ternary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# Do While Loop +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# While Loop +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# For Loop +snippet for + for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) { + ${4:/* code */} + } +# Custom For Loop +snippet forr + for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) { + ${5:/* code */} + } +# Function +snippet fun + ${1:void} ${2:function_name}(${3}) + { + ${4:/* code */} + } +# Function Declaration +snippet fund + ${1:void} ${2:function_name}(${3});${4} +# Typedef +snippet td + typedef ${1:int} ${2:MyCustomType};${3} +# Struct +snippet st + struct ${1:`Filename('$1_t', 'name')`} { + ${2:/* data */} + }${3: /* optional variable list */};${4} +# Typedef struct +snippet tds + typedef struct ${2:_$1 }{ + ${3:/* data */} + } ${1:`Filename('$1_t', 'name')`}; +# Typdef enum +snippet tde + typedef enum { + ${1:/* data */} + } ${2:foo}; +# printf +# unfortunately version this isn't as nice as TextMates's, given the lack of a +# dynamic `...` +snippet pr + printf("${1:%s}\n"${2});${3} +# fprintf (again, this isn't as nice as TextMate's version, but it works) +snippet fpr + fprintf(${1:stderr}, "${2:%s}\n"${3});${4} +# This is kind of convenient +snippet . + [${1}]${2} diff --git a/.vim/bundle/snipmate/snippets/cpp.snippets b/.vim/bundle/snipmate/snippets/cpp.snippets new file mode 100644 index 0000000..fdabd63 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/cpp.snippets @@ -0,0 +1,34 @@ +# Read File Into Vector +snippet readfile + std::vector v; + if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) { + char buf[1024]; + while (size_t len = fread(buf, 1, sizeof(buf), $2)) + v.insert(v.end(), buf, buf + len); + fclose($2); + }${3} +# std::map +snippet map + std::map<${1:key}, ${2:value}> map${3}; +# std::vector +snippet vector + std::vector<${1:char}> v${2}; +# Namespace +snippet ns + namespace ${1:`Filename('', 'my')`} { + ${2} + } /* $1 */ +# Class +snippet cl + class ${1:`Filename('$1_t', 'name')`} { + public: + $1 (${2:arguments}); + virtual ~$1 (); + + private: + ${3:/* data */} + }; +snippet fori + for (int ${2:i} = 0; $2 < ${1:count}; $2${3:++}) { + ${4:/* code */} + } diff --git a/.vim/bundle/snipmate/snippets/erlang.snippets b/.vim/bundle/snipmate/snippets/erlang.snippets new file mode 100644 index 0000000..7238149 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/erlang.snippets @@ -0,0 +1,39 @@ +# module and export all +snippet mod + -module(${1:`Filename('', 'my')`}). + + -compile([export_all]). + + start() -> + ${2} + + stop() -> + ok. +# define directive +snippet def + -define(${1:macro}, ${2:body}).${3} +# export directive +snippet exp + -export([${1:function}/${2:arity}]). +# include directive +snippet inc + -include("${1:file}").${2} +# behavior directive +snippet beh + -behaviour(${1:behaviour}).${2} +# if expression +snippet if + if + ${1:guard} -> + ${2:body} + end +# case expression +snippet case + case ${1:expression} of + ${2:pattern} -> + ${3:body}; + end +# record directive +snippet rec + -record(${1:record}, { + ${2:field}=${3:value}}).${4} diff --git a/.vim/bundle/snipmate/snippets/html.snippets b/.vim/bundle/snipmate/snippets/html.snippets new file mode 100644 index 0000000..302cea2 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/html.snippets @@ -0,0 +1,190 @@ +# Some useful Unicode entities +# Non-Breaking Space +snippet nbs +   +# ← +snippet left + ← +# → +snippet right + → +# ↑ +snippet up + ↑ +# ↓ +snippet down + ↓ +# ↩ +snippet return + ↩ +# ⇤ +snippet backtab + ⇤ +# ⇥ +snippet tab + ⇥ +# ⇧ +snippet shift + ⇧ +# ⌃ +snippet control + ⌃ +# ⌅ +snippet enter + ⌅ +# ⌘ +snippet command + ⌘ +# ⌥ +snippet option + ⌥ +# ⌦ +snippet delete + ⌦ +# ⌫ +snippet backspace + ⌫ +# ⎋ +snippet escape + ⎋ +# Generic Doctype +snippet doctype HTML 4.01 Strict + +snippet doctype HTML 4.01 Transitional + +snippet doctype HTML 5 + +snippet doctype XHTML 1.0 Frameset + +snippet doctype XHTML 1.0 Strict + +snippet doctype XHTML 1.0 Transitional + +snippet doctype XHTML 1.1 + +# HTML Doctype 4.01 Strict +snippet docts + +# HTML Doctype 4.01 Transitional +snippet doct + +# HTML Doctype 5 +snippet doct5 + +# XHTML Doctype 1.0 Frameset +snippet docxf + +# XHTML Doctype 1.0 Strict +snippet docxs + +# XHTML Doctype 1.0 Transitional +snippet docxt + +# XHTML Doctype 1.1 +snippet docx + +snippet html + + ${1} + +snippet xhtml + + ${1} + +snippet body + + ${1} + +snippet head + + + + ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`} + ${2} + +snippet title + ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}${2} +snippet script + ${2} +snippet scriptsrc + ${2} +snippet style + ${3} +snippet base + +snippet r + +snippet div +
+ ${2} +
+# Embed QT Movie +snippet movie + + + + + + ${6} +snippet fieldset +
+ ${1:name} + + ${3} +
+snippet form +
+ ${3} + + +

+
+snippet h1 +

${2:$1}

+snippet input + ${4} +snippet label + ${7} +snippet link + ${4} +snippet mailto + ${3:email me} +snippet meta + ${3} +snippet opt + ${3} +snippet optt + ${2} +snippet select + ${5} +snippet table + + + +
${2:Header}
${3:Data}
${4} +snippet textarea + ${5} diff --git a/.vim/bundle/snipmate/snippets/java.snippets b/.vim/bundle/snipmate/snippets/java.snippets new file mode 100644 index 0000000..dd96b79 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/java.snippets @@ -0,0 +1,95 @@ +snippet main + public static void main (String [] args) + { + ${1:/* code */} + } +snippet pu + public +snippet po + protected +snippet pr + private +snippet st + static +snippet fi + final +snippet ab + abstract +snippet re + return +snippet br + break; +snippet de + default: + ${1} +snippet ca + catch(${1:Exception} ${2:e}) ${3} +snippet th + throw +snippet sy + synchronized +snippet im + import +snippet imp + implements +snippet ext + extends +snippet j.u + java.util +snippet j.i + java.io. +snippet j.b + java.beans. +snippet j.n + java.net. +snippet j.m + java.math. +snippet if + if (${1}) ${2} +snippet el + else +snippet elif + else if (${1}) ${2} +snippet wh + while (${1}) ${2} +snippet for + for (${1}; ${2}; ${3}) ${4} +snippet fore + for (${1} : ${2}) ${3} +snippet sw + switch (${1}) ${2} +snippet cs + case ${1}: + ${2} + ${3} +snippet tc + public class ${1:`Filename()`} extends ${2:TestCase} +snippet t + public void test${1:Name}() throws Exception ${2} +snippet cl + class ${1:`Filename("", "untitled")`} ${2} +snippet in + interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3} +snippet m + ${1:void} ${2:method}(${3}) ${4:throws }${5} +snippet v + ${1:String} ${2:var}${3: = null}${4};${5} +snippet co + static public final ${1:String} ${2:var} = ${3};${4} +snippet cos + static public final String ${1:var} = "${2}";${3} +snippet as + assert ${1:test} : "${2:Failure message}";${3} +snippet try + try { + ${3} + } catch(${1:Exception} ${2:e}) { + } +snippet tryf + try { + ${3} + } catch(${1:Exception} ${2:e}) { + } finally { + } +snippet rst + ResultSet ${1:rst}${2: = null}${3};${4} diff --git a/.vim/bundle/snipmate/snippets/javascript.snippets b/.vim/bundle/snipmate/snippets/javascript.snippets new file mode 100644 index 0000000..f869e2f --- /dev/null +++ b/.vim/bundle/snipmate/snippets/javascript.snippets @@ -0,0 +1,74 @@ +# Prototype +snippet proto + ${1:class_name}.prototype.${2:method_name} = + function(${3:first_argument}) { + ${4:// body...} + }; +# Function +snippet fun + function ${1:function_name} (${2:argument}) { + ${3:// body...} + } +# Anonymous Function +snippet f + function(${1}) {${2}}; +# if +snippet if + if (${1:true}) {${2}} +# if ... else +snippet ife + if (${1:true}) {${2}} + else{${3}} +# tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# switch +snippet switch + switch(${1:expression}) { + case '${3:case}': + ${4:// code} + break; + ${5} + default: + ${2:// code} + } +# case +snippet case + case '${1:case}': + ${2:// code} + break; + ${3} +# for (...) {...} +snippet for + for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) { + ${4:$1[$2]} + }; +# for (...) {...} (Improved Native For-Loop) +snippet forr + for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) { + ${4:$1[$2]} + }; +# while (...) {...} +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# do...while +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# Object Method +snippet :f + ${1:method_name}: function(${2:attribute}) { + ${4} + }${3:,} +# setTimeout function +snippet timeout + setTimeout(function() {${3}}${2}, ${1:10}; +# Get Elements +snippet get + getElementsBy${1:TagName}('${2}')${3} +# Get Element +snippet gett + getElementBy${1:Id}('${2}')${3} diff --git a/.vim/bundle/snipmate/snippets/mako.snippets b/.vim/bundle/snipmate/snippets/mako.snippets new file mode 100644 index 0000000..2a0aef9 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/mako.snippets @@ -0,0 +1,54 @@ +snippet def + <%def name="${1:name}"> + ${2:} + +snippet call + <%call expr="${1:name}"> + ${2:} + +snippet doc + <%doc> + ${1:} + +snippet text + <%text> + ${1:} + +snippet for + % for ${1:i} in ${2:iter}: + ${3:} + % endfor +snippet if if + % if ${1:condition}: + ${2:} + % endif +snippet if if/else + % if ${1:condition}: + ${2:} + % else: + ${3:} + % endif +snippet try + % try: + ${1:} + % except${2:}: + ${3:pass} + % endtry +snippet wh + % while ${1:}: + ${2:} + % endwhile +snippet $ + ${ ${1:} } +snippet <% + <% ${1:} %> +snippet +snippet inherit + <%inherit file="${1:filename}" /> +snippet include + <%include file="${1:filename}" /> +snippet namespace + <%namespace file="${1:name}" /> +snippet page + <%page args="${1:}" /> diff --git a/.vim/bundle/snipmate/snippets/objc.snippets b/.vim/bundle/snipmate/snippets/objc.snippets new file mode 100644 index 0000000..85b80d9 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/objc.snippets @@ -0,0 +1,247 @@ +# #import <...> +snippet Imp + #import <${1:Cocoa/Cocoa.h}>${2} +# #import "..." +snippet imp + #import "${1:`Filename()`.h}"${2} +# @selector(...) +snippet sel + @selector(${1:method}:)${3} +# @"..." string +snippet s + @"${1}"${2} +# Object +snippet o + ${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5} +# NSLog(...) +snippet log + NSLog(@"${1:%@}"${2});${3} +# Class +snippet objc + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + { + } + @end + + @implementation $1 + ${3} + @end +# Class Interface +snippet int + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + {${3} + } + ${4} + @end +snippet @interface + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + {${3} + } + ${4} + @end +# Class Implementation +snippet impl + @implementation ${1:`Filename('', 'someClass')`} + ${2} + @end +snippet @implementation + @implementation ${1:`Filename('', 'someClass')`} + ${2} + @end +# Protocol +snippet pro + @protocol ${1:`Filename('$1Delegate', 'MyProtocol')`} ${2:} + ${3} + @end +snippet @protocol + @protocol ${1:`Filename('$1Delegate', 'MyProtocol')`} ${2:} + ${3} + @end +# init Definition +snippet init + - (id)init + { + if (self = [super init]) { + ${1} + } + return self; + } +# dealloc Definition +snippet dealloc + - (void) dealloc + { + ${1:deallocations} + [super dealloc]; + } +snippet su + [super ${1:init}]${2} +snippet ibo + IBOutlet ${1:NSSomeClass} *${2:$1};${3} +# Category +snippet cat + @interface ${1:NSObject} (${2:MyCategory}) + @end + + @implementation $1 ($2) + ${3} + @end +# Category Interface +snippet cath + @interface ${1:`Filename('$1', 'NSObject')`} (${2:MyCategory}) + ${3} + @end +# Method +snippet m + - (${1:id})${2:method} + { + ${3} + } +# Method declaration +snippet md + - (${1:id})${2:method};${3} +# IBAction declaration +snippet ibad + - (IBAction)${1:method}:(${2:id})sender;${3} +# IBAction method +snippet iba + - (IBAction)${1:method}:(${2:id})sender + { + ${3} + } +# awakeFromNib method +snippet wake + - (void)awakeFromNib + { + ${1} + } +# Class Method +snippet M + + (${1:id})${2:method} + { + ${3:return nil;} + } +# Sub-method (Call super) +snippet sm + - (${1:id})${2:method} + { + [super $2];${3} + return self; + } +# Accessor Methods For: +# Object +snippet objacc + - (${1:id})${2:thing} + { + return $2; + } + + - (void)set$2:($1)${3:new$2} + { + [$3 retain]; + [$2 release]; + $2 = $3; + }${4} +# for (object in array) +snippet forin + for (${1:Class} *${2:some$1} in ${3:array}) { + ${4} + } +snippet fore + for (${1:object} in ${2:array}) { + ${3:statements} + } +snippet forarray + unsigned int ${1:object}Count = [${2:array} count]; + + for (unsigned int index = 0; index < $1Count; index++) { + ${3:id} $1 = [$2 $1AtIndex:index]; + ${4} + } +snippet fora + unsigned int ${1:object}Count = [${2:array} count]; + + for (unsigned int index = 0; index < $1Count; index++) { + ${3:id} $1 = [$2 $1AtIndex:index]; + ${4} + } +# Try / Catch Block +snippet @try + @try { + ${1:statements} + } + @catch (NSException * e) { + ${2:handler} + } + @finally { + ${3:statements} + } +snippet @catch + @catch (${1:exception}) { + ${2:handler} + } +snippet @finally + @finally { + ${1:statements} + } +# IBOutlet +# @property (Objective-C 2.0) +snippet prop + @property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4} +# @synthesize (Objective-C 2.0) +snippet syn + @synthesize ${1:property};${2} +# [[ alloc] init] +snippet alloc + [[${1:foo} alloc] init${2}];${3} +snippet a + [[${1:foo} alloc] init${2}];${3} +# retain +snippet ret + [${1:foo} retain];${2} +# release +snippet rel + [${1:foo} release]; +# autorelease +snippet arel + [${1:foo} autorelease]; +# autorelease pool +snippet pool + NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init]; + ${2:/* code */} + [$1 drain]; +# Throw an exception +snippet except + NSException *${1:badness}; + $1 = [NSException exceptionWithName:@"${2:$1Name}" + reason:@"${3}" + userInfo:nil]; + [$1 raise]; +snippet prag + #pragma mark ${1:-} +snippet cl + @class ${1:Foo};${2} +snippet color + [[NSColor ${1:blackColor}] set]; +# NSArray +snippet array + NSMutableArray *${1:array} = [NSMutable array];${2} +snippet nsa + NSArray ${1} +snippet nsma + NSMutableArray ${1} +snippet aa + NSArray * array;${1} +snippet ma + NSMutableArray * array;${1} +# NSDictionary +snippet dict + NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2} +snippet nsd + NSDictionary ${1} +snippet nsmd + NSMutableDictionary ${1} +# NSString +snippet nss + NSString ${1} +snippet nsms + NSMutableString ${1} diff --git a/.vim/bundle/snipmate/snippets/perl.snippets b/.vim/bundle/snipmate/snippets/perl.snippets new file mode 100644 index 0000000..c85ff11 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/perl.snippets @@ -0,0 +1,97 @@ +# #!/usr/bin/perl +snippet #! + #!/usr/bin/perl + +# Hash Pointer +snippet . + => +# Function +snippet sub + sub ${1:function_name} { + ${2:#body ...} + } +# Conditional +snippet if + if (${1}) { + ${2:# body...} + } +# Conditional if..else +snippet ife + if (${1}) { + ${2:# body...} + } + else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if (${1}) { + ${2:# body...} + } + elsif (${3}) { + ${4:# elsif...} + } + else { + ${5:# else...} + } +# Conditional One-line +snippet xif + ${1:expression} if ${2:condition};${3} +# Unless conditional +snippet unless + unless (${1}) { + ${2:# body...} + } +# Unless conditional One-line +snippet xunless + ${1:expression} unless ${2:condition};${3} +# Try/Except +snippet eval + eval { + ${1:# do something risky...} + }; + if ($@) { + ${2:# handle failure...} + } +# While Loop +snippet wh + while (${1}) { + ${2:# body...} + } +# While Loop One-line +snippet xwh + ${1:expression} while ${2:condition};${3} +# C-style For Loop +snippet cfor + for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4:# body...} + } +# For loop one-line +snippet xfor + ${1:expression} for @${2:array};${3} +# Foreach Loop +snippet for + foreach my $${1:x} (@${2:array}) { + ${3:# body...} + } +# Foreach Loop One-line +snippet fore + ${1:expression} foreach @${2:array};${3} +# Package +snippet cl + package ${1:ClassName}; + + use base qw(${2:ParentClass}); + + sub new { + my $class = shift; + $class = ref $class if ref $class; + my $self = bless {}, $class; + $self; + } + + 1;${3} +# Read File +snippet slurp + my $${1:var}; + { local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = ; close FILE }${3} diff --git a/.vim/bundle/snipmate/snippets/php.snippets b/.vim/bundle/snipmate/snippets/php.snippets new file mode 100644 index 0000000..3ce9e26 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/php.snippets @@ -0,0 +1,216 @@ +snippet php + +snippet ec + echo "${1:string}"${2}; +snippet inc + include '${1:file}';${2} +snippet inc1 + include_once '${1:file}';${2} +snippet req + require '${1:file}';${2} +snippet req1 + require_once '${1:file}';${2} +# $GLOBALS['...'] +snippet globals + $GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5} +snippet $_ COOKIE['...'] + $_COOKIE['${1:variable}']${2} +snippet $_ ENV['...'] + $_ENV['${1:variable}']${2} +snippet $_ FILES['...'] + $_FILES['${1:variable}']${2} +snippet $_ Get['...'] + $_GET['${1:variable}']${2} +snippet $_ POST['...'] + $_POST['${1:variable}']${2} +snippet $_ REQUEST['...'] + $_REQUEST['${1:variable}']${2} +snippet $_ SERVER['...'] + $_SERVER['${1:variable}']${2} +snippet $_ SESSION['...'] + $_SESSION['${1:variable}']${2} +# Start Docblock +snippet /* + /** + * ${1} + **/ +# Class - post doc +snippet doc_cp + /** + * ${1:undocumented class} + * + * @package ${2:default} + * @author ${3:`g:snips_author`} + **/${4} +# Class Variable - post doc +snippet doc_vp + /** + * ${1:undocumented class variable} + * + * @var ${2:string} + **/${3} +# Class Variable +snippet doc_v + /** + * ${3:undocumented class variable} + * + * @var ${4:string} + **/ + ${1:var} $${2};${5} +# Class +snippet doc_c + /** + * ${3:undocumented class} + * + * @packaged ${4:default} + * @author ${5:`g:snips_author`} + **/ + ${1:}class ${2:} + {${6} + } // END $1class $2 +# Constant Definition - post doc +snippet doc_dp + /** + * ${1:undocumented constant} + **/${2} +# Constant Definition +snippet doc_d + /** + * ${3:undocumented constant} + **/ + define(${1}, ${2});${4} +# Function - post doc +snippet doc_fp + /** + * ${1:undocumented function} + * + * @return ${2:void} + * @author ${3:`g:snips_author`} + **/${4} +# Function signature +snippet doc_s + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3});${7} +# Function +snippet doc_f + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3}) + {${7} + } +# Header +snippet doc_h + /** + * ${1} + * + * @author ${2:`g:snips_author`} + * @version ${3:$Id$} + * @copyright ${4:$2}, `strftime('%d %B, %Y')` + * @package ${5:default} + **/ + + /** + * Define DocBlock + *// +# Interface +snippet doc_i + /** + * ${2:undocumented class} + * + * @package ${3:default} + * @author ${4:`g:snips_author`} + **/ + interface ${1:} + {${5} + } // END interface $1 +# class ... +snippet class + /** + * ${1} + **/ + class ${2:ClassName} + { + ${3} + function ${4:__construct}(${5:argument}) + { + ${6:// code...} + } + } +# define(...) +snippet def + define('${1}'${2});${3} +# defined(...) +snippet def? + ${1}defined('${2}')${3} +snippet wh + while (${1:/* condition */}) { + ${2:// code...} + } +# do ... while +snippet do + do { + ${2:// code... } + } while (${1:/* condition */}); +snippet if + if (${1:/* condition */}) { + ${2:// code...} + } +snippet ife + if (${1:/* condition */}) { + ${2:// code...} + } else { + ${3:// code...} + } + ${4} +snippet else + else { + ${1:// code...} + } +snippet elseif + elseif (${1:/* condition */}) { + ${2:// code...} + } +# Tertiary conditional +snippet t + $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5} +snippet switch + switch ($${1:variable}) { + case '${2:value}': + ${3:// code...} + break; + ${5} + default: + ${4:// code...} + break; + } +snippet case + case '${1:value}': + ${2:// code...} + break;${3} +snippet for + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4: // code...} + } +snippet foreach + foreach ($${1:variable} as $${2:key}) { + ${3:// code...} + } +snippet fun + ${1:public }function ${2:FunctionName}(${3}) + { + ${4:// code...} + } +# $... = array (...) +snippet array + $${1:arrayName} = array('${2}' => ${3});${4} diff --git a/.vim/bundle/snipmate/snippets/python.snippets b/.vim/bundle/snipmate/snippets/python.snippets new file mode 100644 index 0000000..735ec98 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/python.snippets @@ -0,0 +1,89 @@ +snippet env + #!/usr/bin/env python + +snippet enc + # -*- coding: utf-8 -*- + +snippet imp + import ${1:module} +# Module Docstring +snippet docs + ''' + File: ${1:`Filename('$1.py', 'foo.py')`} + Author: ${2:`g:snips_author`} + Description: ${3} + ''' +snippet wh + while ${1:condition}: + ${2:# code...} +snippet for + for ${1:needle} in ${2:haystack}: + ${3:# code...} +# New Class +snippet class + class ${1:ClassName}(${2:object}): + """${3:docstring for $1}""" + def __init__(self, ${4:arg}): + ${5:super($1, self).__init__()} + self.$4 = $4 + ${6} +# New Function +snippet def + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + """${3:docstring for $1}""" + ${4:pass} +snippet deff + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${3} +# New Method +snippet defs + def ${1:mname}(self, ${2:arg}): + ${3:pass} +# New Property +snippet property + def ${1:foo}(): + doc = "${2:The $1 property.}" + def fget(self): + ${3:return self._$1} + def fset(self, value): + ${4:self._$1 = value} +# Lambda +snippet ld + ${1:var} = lambda ${2:vars} : ${3:action} +snippet . + self. +snippet try Try/Except + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} +snippet try Try/Except/Else + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} +snippet try Try/Except/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + finally: + ${5:pass} +snippet try Try/Except/Else/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} + finally: + ${6:pass} +# if __name__ == '__main__': +snippet ifmain + if __name__ == '__main__': + ${1:main()} +# __magic__ +snippet _ + __${1:init}__${2} diff --git a/.vim/bundle/snipmate/snippets/ruby.snippets b/.vim/bundle/snipmate/snippets/ruby.snippets new file mode 100644 index 0000000..50080d9 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/ruby.snippets @@ -0,0 +1,504 @@ +# #!/usr/bin/env ruby +snippet #! + #!/usr/bin/env ruby + +# New Block +snippet =b + =begin rdoc + ${1} + =end +snippet y + :yields: ${1:arguments} +snippet rb + #!/usr/bin/env ruby -wKU +snippet beg + begin + ${3} + rescue ${1:Exception} => ${2:e} + end + +snippet req + require "${1}"${2} +snippet # + # => +snippet end + __END__ +snippet case + case ${1:object} + when ${2:condition} + ${3} + end +snippet when + when ${1:condition} + ${2} +snippet def + def ${1:method_name} + ${2} + end +snippet deft + def test_${1:case_name} + ${2} + end +snippet if + if ${1:condition} + ${2} + end +snippet ife + if ${1:condition} + ${2} + else + ${3} + end +snippet elsif + elsif ${1:condition} + ${2} +snippet unless + unless ${1:condition} + ${2} + end +snippet while + while ${1:condition} + ${2} + end +snippet for + for ${1:e} in ${2:c} + ${3} + end +snippet until + until ${1:condition} + ${2} + end +snippet cla class .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet cla class .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + def initialize(${2:args}) + ${3} + end + + + end +snippet cla class .. < ParentClass .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass} + def initialize(${3:args}) + ${4} + end + + + end +snippet cla ClassName = Struct .. do .. end + ${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do + def ${3:method_name} + ${4} + end + + + end +snippet cla class BlankSlate .. initialize .. end + class ${1:BlankSlate} + instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ } +snippet cla class << self .. end + class << ${1:self} + ${2} + end +# class .. < DelegateClass .. initialize .. end +snippet cla- + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass}) + def initialize(${3:args}) + super(${4:del_obj}) + + ${5} + end + + + end +snippet mod module .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet mod module .. module_function .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module_function + + ${2} + end +snippet mod module .. ClassMethods .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module ClassMethods + ${2} + end + + module InstanceMethods + + end + + def self.included(receiver) + receiver.extend ClassMethods + receiver.send :include, InstanceMethods + end + end +# attr_reader +snippet r + attr_reader :${1:attr_names} +# attr_writer +snippet w + attr_writer :${1:attr_names} +# attr_accessor +snippet rw + attr_accessor :${1:attr_names} +# include Enumerable +snippet Enum + include Enumerable + + def each(&block) + ${1} + end +# include Comparable +snippet Comp + include Comparable + + def <=>(other) + ${1} + end +# extend Forwardable +snippet Forw- + extend Forwardable +# def self +snippet defs + def self.${1:class_method_name} + ${2} + end +# def method_missing +snippet defmm + def method_missing(meth, *args, &blk) + ${1} + end +snippet defd + def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name} +snippet defds + def_delegators :${1:@del_obj}, :${2:del_methods} +snippet am + alias_method :${1:new_name}, :${2:old_name} +snippet app + if __FILE__ == $PROGRAM_NAME + ${1} + end +# usage_if() +snippet usai + if ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +# usage_unless() +snippet usau + unless ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +snippet array + Array.new(${1:10}) { |${2:i}| ${3} } +snippet hash + Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} } +snippet file File.foreach() { |line| .. } + File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} } +snippet file File.read() + File.read(${1:"path/to/file"})${2} +snippet Dir Dir.global() { |file| .. } + Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} } +snippet Dir Dir[".."] + Dir[${1:"glob/**/*.rb"}]${2} +snippet dir + Filename.dirname(__FILE__) +snippet deli + delete_if { |${1:e}| ${2} } +snippet fil + fill(${1:range}) { |${2:i}| ${3} } +# flatten_once() +snippet flao + inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3} +snippet zip + zip(${1:enums}) { |${2:row}| ${3} } +# downto(0) { |n| .. } +snippet dow + downto(${1:0}) { |${2:n}| ${3} } +snippet ste + step(${1:2}) { |${2:n}| ${3} } +snippet tim + times { |${1:n}| ${2} } +snippet upt + upto(${1:1.0/0.0}) { |${2:n}| ${3} } +snippet loo + loop { ${1} } +snippet ea + each { |${1:e}| ${2} } +snippet ead + each do |${1:e}| + ${2} + end +snippet eab + each_byte { |${1:byte}| ${2} } +snippet eac- each_char { |chr| .. } + each_char { |${1:chr}| ${2} } +snippet eac- each_cons(..) { |group| .. } + each_cons(${1:2}) { |${2:group}| ${3} } +snippet eai + each_index { |${1:i}| ${2} } +snippet eaid + each_index do |${1:i}| + end +snippet eak + each_key { |${1:key}| ${2} } +snippet eakd + each_key do |${1:key}| + ${2} + end +snippet eal + each_line { |${1:line}| ${2} } +snippet eald + each_line do |${1:line}| + ${2} + end +snippet eap + each_pair { |${1:name}, ${2:val}| ${3} } +snippet eapd + each_pair do |${1:name}, ${2:val}| + ${3} + end +snippet eas- + each_slice(${1:2}) { |${2:group}| ${3} } +snippet easd- + each_slice(${1:2}) do |${2:group}| + ${3} + end +snippet eav + each_value { |${1:val}| ${2} } +snippet eavd + each_value do |${1:val}| + ${2} + end +snippet eawi + each_with_index { |${1:e}, ${2:i}| ${3} } +snippet eawid + each_with_index do |${1:e},${2:i}| + ${3} + end +snippet reve + reverse_each { |${1:e}| ${2} } +snippet reved + reverse_each do |${1:e}| + ${2} + end +snippet inj + inject(${1:init}) { |${2:mem}, ${3:var}| ${4} } +snippet injd + inject(${1:init}) do |${2:mem}, ${3:var}| + ${4} + end +snippet map + map { |${1:e}| ${2} } +snippet mapd + map do |${1:e}| + ${2} + end +snippet mapwi- + enum_with_index.map { |${1:e}, ${2:i}| ${3} } +snippet sor + sort { |a, b| ${1} } +snippet sorb + sort_by { |${1:e}| ${2} } +snippet ran + sort_by { rand } +snippet all + all? { |${1:e}| ${2} } +snippet any + any? { |${1:e}| ${2} } +snippet cl + classify { |${1:e}| ${2} } +snippet col + collect { |${1:e}| ${2} } +snippet cold + collect do |${1:e}| + ${2} + end +snippet det + detect { |${1:e}| ${2} } +snippet detd + detect do |${1:e}| + ${2} + end +snippet fet + fetch(${1:name}) { |${2:key}| ${3} } +snippet fin + find { |${1:e}| ${2} } +snippet find + find do |${1:e}| + ${2} + end +snippet fina + find_all { |${1:e}| ${2} } +snippet finad + find_all do |${1:e}| + ${2} + end +snippet gre + grep(${1:/pattern/}) { |${2:match}| ${3} } +snippet sub + ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} } +snippet sca + scan(${1:/pattern/}) { |${2:match}| ${3} } +snippet scad + scan(${1:/pattern/}) do |${2:match}| + ${3} + end +snippet max + max { |a, b| ${1} } +snippet min + min { |a, b| ${1} } +snippet par + partition { |${1:e}| ${2} } +snippet pard + partition do |${1:e}| + ${2} + end +snippet rej + reject { |${1:e}| ${2} } +snippet rejd + reject do |${1:e}| + ${2} + end +snippet sel + select { |${1:e}| ${2} } +snippet seld + select do |${1:e}| + ${2} + end +snippet lam + lambda { |${1:args}| ${2} } +snippet do + do |${1:variable}| + ${2} + end +snippet : + :${1:key} => ${2:"value"}${3} +snippet ope + open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} } +# path_from_here() +snippet patfh + File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2} +# unix_filter {} +snippet unif + ARGF.each_line${1} do |${2:line}| + ${3} + end +# option_parse {} +snippet optp + require "optparse" + + options = {${1:default => "args"}} + + ARGV.options do |opts| + opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} +snippet opt + opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String}, + "${4:Option description.}") do |${5:opt}| + ${6} + end +snippet tc + require "test/unit" + + require "${1:library_file_name}" + + class Test${2:$1} < Test::Unit::TestCase + def test_${3:case_name} + ${4} + end + end +snippet ts + require "test/unit" + + require "tc_${1:test_case_file}" + require "tc_${2:test_case_file}"${3} +snippet as + assert(${1:test}, "${2:Failure message.}")${3} +snippet ase + assert_equal(${1:expected}, ${2:actual})${3} +snippet asne + assert_not_equal(${1:unexpected}, ${2:actual})${3} +snippet asid + assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4} +snippet asio + assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3} +snippet asko + assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3} +snippet asn + assert_nil(${1:instance})${2} +snippet asnn + assert_not_nil(${1:instance})${2} +snippet asm + assert_match(/${1:expected_pattern}/, ${2:actual_string})${3} +snippet asnm + assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3} +snippet aso + assert_operator(${1:left}, :${2:operator}, ${3:right})${4} +snippet asr + assert_raise(${1:Exception}) { ${2} } +snippet asnr + assert_nothing_raised(${1:Exception}) { ${2} } +snippet asrt + assert_respond_to(${1:object}, :${2:method})${3} +snippet ass assert_same(..) + assert_same(${1:expected}, ${2:actual})${3} +snippet ass assert_send(..) + assert_send([${1:object}, :${2:message}, ${3:args}])${4} +snippet asns + assert_not_same(${1:unexpected}, ${2:actual})${3} +snippet ast + assert_throws(:${1:expected}) { ${2} } +snippet asnt + assert_nothing_thrown { ${1} } +snippet fl + flunk("${1:Failure message.}")${2} +# Benchmark.bmbm do .. end +snippet bm- + TESTS = ${1:10_000} + Benchmark.bmbm do |results| + ${2} + end +snippet rep + results.report("${1:name}:") { TESTS.times { ${2} }} +# Marshal.dump(.., file) +snippet Md + File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4} +# Mashal.load(obj) +snippet Ml + File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3} +# deep_copy(..) +snippet deec + Marshal.load(Marshal.dump(${1:obj_to_copy}))${2} +snippet Pn- + PStore.new(${1:"file_name.pstore"})${2} +snippet tra + transaction(${1:true}) { ${2} } +# xmlread(..) +snippet xml- + REXML::Document.new(File.read(${1:"path/to/file"}))${2} +# xpath(..) { .. } +snippet xpa + elements.each(${1:"//Xpath"}) do |${2:node}| + ${3} + end +# class_from_name() +snippet clafn + split("::").inject(Object) { |par, const| par.const_get(const) } +# singleton_class() +snippet sinc + class << self; self end +snippet nam + namespace :${1:`Filename()`} do + ${2} + end +snippet tas + desc "${1:Task description\}" + task :${2:task_name => [:dependent, :tasks]} do + ${3} + end diff --git a/.vim/bundle/snipmate/snippets/sh.snippets b/.vim/bundle/snipmate/snippets/sh.snippets new file mode 100644 index 0000000..f035126 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/sh.snippets @@ -0,0 +1,28 @@ +# #!/bin/bash +snippet #! + #!/bin/bash + +snippet if + if [[ ${1:condition} ]]; then + ${2:#statements} + fi +snippet elif + elif [[ ${1:condition} ]]; then + ${2:#statements} +snippet for + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do + ${3:#statements} + done +snippet wh + while [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet until + until [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet case + case ${1:word} in + ${2:pattern}) + ${3};; + esac diff --git a/.vim/bundle/snipmate/snippets/snippet.snippets b/.vim/bundle/snipmate/snippets/snippet.snippets new file mode 100644 index 0000000..854c058 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/snippet.snippets @@ -0,0 +1,7 @@ +# snippets for making snippets :) +snippet snip + snippet ${1:trigger} + ${2} +snippet msnip + snippet ${1:trigger} ${2:description} + ${3} diff --git a/.vim/bundle/snipmate/snippets/tcl.snippets b/.vim/bundle/snipmate/snippets/tcl.snippets new file mode 100644 index 0000000..1fe1cb9 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/tcl.snippets @@ -0,0 +1,92 @@ +# #!/usr/bin/env tclsh +snippet #! + #!/usr/bin/env tclsh + +# Process +snippet pro + proc ${1:function_name} {${2:args}} { + ${3:#body ...} + } +#xif +snippet xif + ${1:expr}? ${2:true} : ${3:false} +# Conditional +snippet if + if {${1}} { + ${2:# body...} + } +# Conditional if..else +snippet ife + if {${1}} { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if {${1}} { + ${2:# body...} + } elseif {${3}} { + ${4:# elsif...} + } else { + ${5:# else...} + } +# If catch then +snippet ifc + if { [catch {${1:#do something...}} ${2:err}] } { + ${3:# handle failure...} + } +# Catch +snippet catch + catch {${1}} ${2:err} ${3:options} +# While Loop +snippet wh + while {${1}} { + ${2:# body...} + } +# For Loop +snippet for + for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach ${1:x} {${2:#list}} { + ${3:# body...} + } +# after ms script... +snippet af + after ${1:ms} ${2:#do something} +# after cancel id +snippet afc + after cancel ${1:id or script} +# after idle +snippet afi + after idle ${1:script} +# after info id +snippet afin + after info ${1:id} +# Expr +snippet exp + expr {${1:#expression here}} +# Switch +snippet sw + switch ${1:var} { + ${3:pattern 1} { + ${4:#do something} + } + default { + ${2:#do something} + } + } +# Case +snippet ca + ${1:pattern} { + ${2:#do something} + }${3} +# Namespace eval +snippet ns + namespace eval ${1:path} {${2:#script...}} +# Namespace current +snippet nsc + namespace current diff --git a/.vim/bundle/snipmate/snippets/tex.snippets b/.vim/bundle/snipmate/snippets/tex.snippets new file mode 100644 index 0000000..22f7316 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/tex.snippets @@ -0,0 +1,115 @@ +# \begin{}...\end{} +snippet begin + \begin{${1:env}} + ${2} + \end{$1} +# Tabular +snippet tab + \begin{${1:tabular}}{${2:c}} + ${3} + \end{$1} +# Align(ed) +snippet ali + \begin{align${1:ed}} + ${2} + \end{align$1} +# Gather(ed) +snippet gat + \begin{gather${1:ed}} + ${2} + \end{gather$1} +# Equation +snippet eq + \begin{equation} + ${1} + \end{equation} +# Unnumbered Equation +snippet \ + \\[ + ${1} + \\] +# Enumerate +snippet enum + \begin{enumerate} + \item ${1} + \end{enumerate} +# Itemize +snippet item + \begin{itemize} + \item ${1} + \end{itemize} +# Description +snippet desc + \begin{description} + \item[${1}] ${2} + \end{description} +# Matrix +snippet mat + \begin{${1:p/b/v/V/B/small}matrix} + ${2} + \end{$1matrix} +# Cases +snippet cas + \begin{cases} + ${1:equation}, &\text{ if }${2:case}\\ + ${3} + \end{cases} +# Split +snippet spl + \begin{split} + ${1} + \end{split} +# Part +snippet part + \part{${1:part name}} % (fold) + \label{prt:${2:$1}} + ${3} + % part $2 (end) +# Chapter +snippet cha + \chapter{${1:chapter name}} % (fold) + \label{cha:${2:$1}} + ${3} + % chapter $2 (end) +# Section +snippet sec + \section{${1:section name}} % (fold) + \label{sec:${2:$1}} + ${3} + % section $2 (end) +# Sub Section +snippet sub + \subsection{${1:subsection name}} % (fold) + \label{sub:${2:$1}} + ${3} + % subsection $2 (end) +# Sub Sub Section +snippet subs + \subsubsection{${1:subsubsection name}} % (fold) + \label{ssub:${2:$1}} + ${3} + % subsubsection $2 (end) +# Paragraph +snippet par + \paragraph{${1:paragraph name}} % (fold) + \label{par:${2:$1}} + ${3} + % paragraph $2 (end) +# Sub Paragraph +snippet subp + \subparagraph{${1:subparagraph name}} % (fold) + \label{subp:${2:$1}} + ${3} + % subparagraph $2 (end) +snippet itd + \item[${1:description}] ${2:item} +snippet figure + ${1:Figure}~\ref{${2:fig:}}${3} +snippet table + ${1:Table}~\ref{${2:tab:}}${3} +snippet listing + ${1:Listing}~\ref{${2:list}}${3} +snippet section + ${1:Section}~\ref{${2:sec:}}${3} +snippet page + ${1:page}~\pageref{${2}}${3} diff --git a/.vim/bundle/snipmate/snippets/vim.snippets b/.vim/bundle/snipmate/snippets/vim.snippets new file mode 100644 index 0000000..64e7807 --- /dev/null +++ b/.vim/bundle/snipmate/snippets/vim.snippets @@ -0,0 +1,32 @@ +snippet header + " File: ${1:`expand('%:t')`} + " Author: ${2:`g:snips_author`} + " Description: ${3} + ${4:" Last Modified: `strftime("%B %d, %Y")`} +snippet guard + if exists('${1:did_`Filename()`}') || &cp${2: || version < 700} + finish + endif + let $1 = 1${3} +snippet f + fun ${1:function_name}(${2}) + ${3:" code} + endf +snippet for + for ${1:needle} in ${2:haystack} + ${3:" code} + endfor +snippet wh + while ${1:condition} + ${2:" code} + endw +snippet if + if ${1:condition} + ${2:" code} + endif +snippet ife + if ${1:condition} + ${2} + else + ${3} + endif diff --git a/.vim/bundle/snipmate/snippets/zsh.snippets b/.vim/bundle/snipmate/snippets/zsh.snippets new file mode 100644 index 0000000..7aee05b --- /dev/null +++ b/.vim/bundle/snipmate/snippets/zsh.snippets @@ -0,0 +1,58 @@ +# #!/bin/zsh +snippet #! + #!/bin/zsh + +snippet if + if ${1:condition}; then + ${2:# statements} + fi +snippet ife + if ${1:condition}; then + ${2:# statements} + else + ${3:# statements} + fi +snippet elif + elif ${1:condition} ; then + ${2:# statements} +snippet for + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do + ${3:# statements} + done +snippet fore + for ${1:item} in ${2:list}; do + ${3:# statements} + done +snippet wh + while ${1:condition}; do + ${2:# statements} + done +snippet until + until ${1:condition}; do + ${2:# statements} + done +snippet repeat + repeat ${1:integer}; do + ${2:# statements} + done +snippet case + case ${1:word} in + ${2:pattern}) + ${3};; + esac +snippet select + select ${1:answer} in ${2:choices}; do + ${3:# statements} + done +snippet ( + ( ${1:#statements} ) +snippet { + { ${1:#statements} } +snippet [ + [[ ${1:test} ]] +snippet always + { ${1:try} } always { ${2:always} } +snippet fun + function ${1:name} (${2:args}) { + ${3:# body} + } diff --git a/.vim/bundle/snipmate/syntax/snippet.vim b/.vim/bundle/snipmate/syntax/snippet.vim new file mode 100644 index 0000000..3aa8571 --- /dev/null +++ b/.vim/bundle/snipmate/syntax/snippet.vim @@ -0,0 +1,19 @@ +" Syntax highlighting for snippet files (used for snipMate.vim) +" Hopefully this should make snippets a bit nicer to write! +syn match snipComment '^#.*' +syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand +syn match tabStop '\$\d\+' +syn match snipCommand '[^\\]`.\{-}`' +syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword +syn match multiSnipText '\S\+ \zs.*' contained +syn match snipKeyword '^snippet'me=s+8 contained +syn match snipError "^[^#s\t].*$" + +hi link snipComment Comment +hi link multiSnipText String +hi link snipKeyword Keyword +hi link snipComment Comment +hi link placeHolder Special +hi link tabStop Special +hi link snipCommand String +hi link snipError Error diff --git a/.vim/bundle/sparkup/ftplugin/html/sparkup.py b/.vim/bundle/sparkup/ftplugin/html/sparkup.py new file mode 100755 index 0000000..cc229af --- /dev/null +++ b/.vim/bundle/sparkup/ftplugin/html/sparkup.py @@ -0,0 +1,950 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import re +from optparse import OptionParser + +VERSION = "v0.1.99-20100514" + +# ============================================================================= + +class Dialect: + shortcuts = {} + synonyms = {} + required = {} + short_tags = () + +class HtmlDialect(Dialect): + shortcuts = { + 'cc:ie': { + 'opening_tag': ''}, + 'cc:ie6': { + 'opening_tag': ''}, + 'cc:ie7': { + 'opening_tag': ''}, + 'cc:noie': { + 'opening_tag': '', + 'closing_tag': ''}, + 'html:4t': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'html:4s': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'html:xt': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'html:xs': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'html:xxs': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'html:5': { + 'expand': True, + 'opening_tag': + '\n' + + '\n' + + '\n' + + ' ' + '\n' + + ' ' + '\n' + + '\n' + + '', + 'closing_tag': + '\n' + + ''}, + 'input:button': { + 'name': 'input', + 'attributes': { 'class': 'button', 'type': 'button', 'name': '', 'value': '' } + }, + 'input:password': { + 'name': 'input', + 'attributes': { 'class': 'text password', 'type': 'password', 'name': '', 'value': '' } + }, + 'input:radio': { + 'name': 'input', + 'attributes': { 'class': 'radio', 'type': 'radio', 'name': '', 'value': '' } + }, + 'input:checkbox': { + 'name': 'input', + 'attributes': { 'class': 'checkbox', 'type': 'checkbox', 'name': '', 'value': '' } + }, + 'input:file': { + 'name': 'input', + 'attributes': { 'class': 'file', 'type': 'file', 'name': '', 'value': '' } + }, + 'input:text': { + 'name': 'input', + 'attributes': { 'class': 'text', 'type': 'text', 'name': '', 'value': '' } + }, + 'input:submit': { + 'name': 'input', + 'attributes': { 'class': 'submit', 'type': 'submit', 'value': '' } + }, + 'input:hidden': { + 'name': 'input', + 'attributes': { 'type': 'hidden', 'name': '', 'value': '' } + }, + 'script:src': { + 'name': 'script', + 'attributes': { 'src': '' } + }, + 'script:jquery': { + 'name': 'script', + 'attributes': { 'src': 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js' } + }, + 'script:jsapi': { + 'name': 'script', + 'attributes': { 'src': 'http://www.google.com/jsapi' } + }, + 'script:jsapix': { + 'name': 'script', + 'text': '\n google.load("jquery", "1.3.2");\n google.setOnLoadCallback(function() {\n \n });\n' + }, + 'link:css': { + 'name': 'link', + 'attributes': { 'rel': 'stylesheet', 'type': 'text/css', 'href': '', 'media': 'all' }, + }, + 'link:print': { + 'name': 'link', + 'attributes': { 'rel': 'stylesheet', 'type': 'text/css', 'href': '', 'media': 'print' }, + }, + 'link:favicon': { + 'name': 'link', + 'attributes': { 'rel': 'shortcut icon', 'type': 'image/x-icon', 'href': '' }, + }, + 'link:touch': { + 'name': 'link', + 'attributes': { 'rel': 'apple-touch-icon', 'href': '' }, + }, + 'link:rss': { + 'name': 'link', + 'attributes': { 'rel': 'alternate', 'type': 'application/rss+xml', 'title': 'RSS', 'href': '' }, + }, + 'link:atom': { + 'name': 'link', + 'attributes': { 'rel': 'alternate', 'type': 'application/atom+xml', 'title': 'Atom', 'href': '' }, + }, + 'meta:ie7': { + 'name': 'meta', + 'attributes': { 'http-equiv': 'X-UA-Compatible', 'content': 'IE=7' }, + }, + 'meta:ie8': { + 'name': 'meta', + 'attributes': { 'http-equiv': 'X-UA-Compatible', 'content': 'IE=8' }, + }, + 'form:get': { + 'name': 'form', + 'attributes': { 'method': 'get' }, + }, + 'form:g': { + 'name': 'form', + 'attributes': { 'method': 'get' }, + }, + 'form:post': { + 'name': 'form', + 'attributes': { 'method': 'post' }, + }, + 'form:p': { + 'name': 'form', + 'attributes': { 'method': 'post' }, + }, + } + synonyms = { + 'checkbox': 'input:checkbox', + 'check': 'input:checkbox', + 'input:c': 'input:checkbox', + 'button': 'input:button', + 'input:b': 'input:button', + 'input:h': 'input:hidden', + 'hidden': 'input:hidden', + 'submit': 'input:submit', + 'input:s': 'input:submit', + 'radio': 'input:radio', + 'input:r': 'input:radio', + 'text': 'input:text', + 'passwd': 'input:password', + 'password': 'input:password', + 'pw': 'input:password', + 'input:t': 'input:text', + 'linkcss': 'link:css', + 'scriptsrc': 'script:src', + 'jquery': 'script:jquery', + 'jsapi': 'script:jsapi', + 'html5': 'html:5', + 'html4': 'html:4s', + 'html4s': 'html:4s', + 'html4t': 'html:4t', + 'xhtml': 'html:xxs', + 'xhtmlt': 'html:xt', + 'xhtmls': 'html:xs', + 'xhtml11': 'html:xxs', + 'opt': 'option', + 'st': 'strong', + 'css': 'style', + 'csss': 'link:css', + 'css:src': 'link:css', + 'csssrc': 'link:css', + 'js': 'script', + 'jss': 'script:src', + 'js:src': 'script:src', + 'jssrc': 'script:src', + } + short_tags = ( + 'area', 'base', 'basefont', 'br', 'embed', 'hr', + 'input', 'img', 'link', 'param', 'meta') + required = { + 'a': {'href':''}, + 'base': {'href':''}, + 'abbr': {'title': ''}, + 'acronym':{'title': ''}, + 'bdo': {'dir': ''}, + 'link': {'rel': 'stylesheet', 'href': ''}, + 'style': {'type': 'text/css'}, + 'script': {'type': 'text/javascript'}, + 'img': {'src':'', 'alt':''}, + 'iframe': {'src': '', 'frameborder': '0'}, + 'embed': {'src': '', 'type': ''}, + 'object': {'data': '', 'type': ''}, + 'param': {'name': '', 'value': ''}, + 'form': {'action': '', 'method': 'post'}, + 'table': {'cellspacing': '0'}, + 'input': {'type': '', 'name': '', 'value': ''}, + 'base': {'href': ''}, + 'area': {'shape': '', 'coords': '', 'href': '', 'alt': ''}, + 'select': {'name': ''}, + 'option': {'value': ''}, + 'textarea':{'name': ''}, + 'meta': {'content': ''}, + } + +class Parser: + """The parser. + """ + + # Constructor + # ------------------------------------------------------------------------- + + def __init__(self, options, string, dialect=HtmlDialect()): + """Constructor. + """ + + self.tokens = [] + self.string = string + self.options = options + self.dialect = dialect + self.root = Element(parser=self) + self.caret = [] + self.caret.append(self.root) + self._last = [] + + self._tokenize() + self._parse() + + + # Methods + # ------------------------------------------------------------------------- + + def render(self): + """Renders. + Called by [[Router]]. + """ + + # Get the initial render of the root node + output = self.root.render() + + # Indent by whatever the input is indented with + indent = re.findall(r"^[\r\n]*(\s*)", self.string)[0] + output = indent + output.replace("\n", "\n" + indent) + + # Strip newline if not needed + if not self.options.last_newline \ + or self.prefix or self.suffix: + output = re.sub(r'\n\s*$', '', output) + + # TextMate mode + if self.options.textmate: + output = self._textmatify(output) + + return output + + # Protected methods + # ------------------------------------------------------------------------- + + def _textmatify(self, output): + """Returns a version of the output with TextMate placeholders in it. + """ + + matches = re.findall(r'(>$%i]+>\s*)", string) + if match is None: break + if self.prefix is None: self.prefix = '' + self.prefix += match.group(0) + string = string[len(match.group(0)):] + + while True: + match = re.findall(r"(\s*<[^>]+>[\s\n\r]*)$", string) + if not match: break + if self.suffix is None: self.suffix = '' + self.suffix = match[0] + self.suffix + string = string[:-len(match[0])] + + # Split by the element separators + for token in re.split('(<|>|\+(?!\\s*\+|$))', string): + if token.strip() != '': + self.tokens.append(Token(token, parser=self)) + + def _parse(self): + """Takes the tokens and does its thing. + Populates [[self.root]]. + """ + + # Carry it over to the root node. + if self.prefix or self.suffix: + self.root.prefix = self.prefix + self.root.suffix = self.suffix + self.root.depth += 1 + + for token in self.tokens: + if token.type == Token.ELEMENT: + # Reset the "last elements added" list. We will + # repopulate this with the new elements added now. + self._last[:] = [] + + # Create [[Element]]s from a [[Token]]. + # They will be created as many as the multiplier specifies, + # multiplied by how many carets we have + count = 0 + for caret in self.caret: + for local_count in range(1, token.multiplier + 1): + count += 1 + new = Element(token, caret, + count = count, + local_count = local_count, + parser = self) + self._last.append(new) + caret.append(new) + + # For > + elif token.type == Token.CHILD: + # The last children added. + self.caret[:] = self._last + + # For < + elif token.type == Token.PARENT: + # If we're the root node, don't do anything + parent = self.caret[0].parent + if parent is not None: + self.caret[:] = [parent] + + # Properties + # ------------------------------------------------------------------------- + + # Property: dialect + # The dialect of XML + dialect = None + + # Property: string + # The string + string = '' + + # Property: tokens + # The list of tokens + tokens = [] + + # Property: options + # Reference to the [[Options]] instance + options = None + + # Property: root + # The root [[Element]] node. + root = None + + # Property: caret + # The current insertion point. + caret = None + + # Property: _last + # List of the last appended stuff + _last = None + + # Property: indent + # Yeah + indent = '' + + # Property: prefix + # (String) The trailing tag in the beginning. + # + # Description: + # For instance, in `
ul>li
`, the `prefix` is `
`. + prefix = '' + + # Property: suffix + # (string) The trailing tag at the end. + suffix = '' + +# ============================================================================= + +class Element: + """An element. + """ + + def __init__(self, token=None, parent=None, count=None, local_count=None, + parser=None, opening_tag=None, closing_tag=None, + attributes=None, name=None, text=None): + """Constructor. + + This is called by ???. + + Description: + All parameters are optional. + + token - (Token) The token (required) + parent - (Element) Parent element; `None` if root + count - (Int) The number to substitute for `&` (e.g., in `li.item-&`) + local_count - (Int) The number to substitute for `$` (e.g., in `li.item-$`) + parser - (Parser) The parser + + attributes - ... + name - ... + text - ... + """ + + self.children = [] + self.attributes = {} + self.parser = parser + + if token is not None: + # Assumption is that token is of type [[Token]] and is + # a [[Token.ELEMENT]]. + self.name = token.name + self.attributes = token.attributes.copy() + self.text = token.text + self.populate = token.populate + self.expand = token.expand + self.opening_tag = token.opening_tag + self.closing_tag = token.closing_tag + + # `count` can be given. This will substitude & in classname and ID + if count is not None: + for key in self.attributes: + attrib = self.attributes[key] + attrib = attrib.replace('&', ("%i" % count)) + if local_count is not None: + attrib = attrib.replace('$', ("%i" % local_count)) + self.attributes[key] = attrib + + # Copy over from parameters + if attributes: self.attributes = attributes + if name: self.name = name + if text: self.text = text + + self._fill_attributes() + + self.parent = parent + if parent is not None: + self.depth = parent.depth + 1 + + if self.populate: self._populate() + + def render(self): + """Renders the element, along with it's subelements, into HTML code. + + [Grouped under "Rendering methods"] + """ + + options = self.parser.options + output = "" + spaces_count = options.indent_spaces + spaces = ' ' * spaces_count + indent = self.depth * spaces + + prefix, suffix = ('', '') + if self.prefix: prefix = self.prefix + "\n" + if self.suffix: suffix = self.suffix + + # Make the guide from the ID (/#header), or the class if there's no + # ID (/.item) + # This is for the start-guide, end-guide and post_tag_guides + guide_string = '' + if 'id' in self.attributes: + guide_string += "#%s" % self.attributes['id'] + elif 'class' in self.attributes: + guide_string += ".%s" % self.attributes['class'].replace(' ', '.') + + # Build the post-tag guide (e.g.,
), + # the start guide, and the end guide. + guide = '' + start_guide = '' + end_guide = '' + + if ((self.name == 'div') and \ + (('id' in self.attributes) or ('class' in self.attributes))): + + if (options.post_tag_guides): + guide = "" % guide_string + + if (options.start_guide_format): + format = options.start_guide_format + try: start_guide = format % guide_string + except: start_guide = (format + " " + guide_string).strip() + start_guide = "%s\n" % (indent, start_guide) + + if (options.end_guide_format): + format = options.end_guide_format + try: end_guide = format % guide_string + except: end_guide = (format + " " + guide_string).strip() + + if options.end_guide_newline: + end_guide = "\n%s" % (indent, end_guide) + else: + end_guide = "" % (end_guide) + + # Short, self-closing tags (
) + short_tags = self.parser.dialect.short_tags + + # When it should be expanded.. + # (That is,
\n...\n
or similar -- wherein something must go + # inside the opening/closing tags) + if len(self.children) > 0 \ + or self.expand \ + or prefix or suffix \ + or (self.parser.options.expand_divs and self.name == 'div'): + + for child in self.children: + output += child.render() + + # For expand divs: if there are no children (that is, `output` + # is still blank despite above), fill it with a blank line. + if (output == ''): output = indent + spaces + "\n" + + # If we're a root node and we have a prefix or suffix... + # (Only the root node can have a prefix or suffix.) + if prefix or suffix: + output = "%s%s%s%s%s\n" % \ + (indent, prefix, output, suffix, guide) + + # Uh.. + elif self.name != '' or \ + self.opening_tag is not None or \ + self.closing_tag is not None: + output = start_guide + \ + indent + self.get_opening_tag() + "\n" + \ + output + \ + indent + self.get_closing_tag() + \ + guide + end_guide + "\n" + + + # Short, self-closing tags (
) + elif self.name in short_tags: + output = "%s<%s />\n" % (indent, self.get_default_tag()) + + # Tags with text, possibly + elif self.name != '' or \ + self.opening_tag is not None or \ + self.closing_tag is not None: + output = "%s%s%s%s%s%s%s%s" % \ + (start_guide, indent, self.get_opening_tag(), \ + self.text, \ + self.get_closing_tag(), \ + guide, end_guide, "\n") + + return output + + def get_default_tag(self): + """Returns the opening tag (without brackets). + + Usage: + element.get_default_tag() + + [Grouped under "Rendering methods"] + """ + + output = '%s' % (self.name) + for key, value in self.attributes.iteritems(): + output += ' %s="%s"' % (key, value) + return output + + def get_opening_tag(self): + if self.opening_tag is None: + return "<%s>" % self.get_default_tag() + else: + return self.opening_tag + + def get_closing_tag(self): + if self.closing_tag is None: + return "" % self.name + else: + return self.closing_tag + + def append(self, object): + """Registers an element as a child of this element. + + Usage: + element.append(child) + + Description: + Adds a given element `child` to the children list of this element. It + will be rendered when [[render()]] is called on the element. + + See also: + - [[get_last_child()]] + + [Grouped under "Traversion methods"] + """ + + self.children.append(object) + + def get_last_child(self): + """Returns the last child element which was [[append()]]ed + to this element. + + Usage: + element.get_last_child() + + Description: + This is the same as using `element.children[-1]`. + + [Grouped under "Traversion methods"] + """ + + return self.children[-1] + + def _populate(self): + """Expands with default items. + + This is called when the [[populate]] flag is turned on. + """ + + if self.name == 'ul': + elements = [Element(name='li', parent=self, parser=self.parser)] + + elif self.name == 'dl': + elements = [ + Element(name='dt', parent=self, parser=self.parser), + Element(name='dd', parent=self, parser=self.parser)] + + elif self.name == 'table': + tr = Element(name='tr', parent=self, parser=self.parser) + td = Element(name='td', parent=tr, parser=self.parser) + tr.children.append(td) + elements = [tr] + + else: + elements = [] + + for el in elements: + self.children.append(el) + + def _fill_attributes(self): + """Fills default attributes for certain elements. + + Description: + This is called by the constructor. + + [Protected, grouped under "Protected methods"] + """ + + # Make sure 's have a href, 's have an src, etc. + required = self.parser.dialect.required + + for element, attribs in required.iteritems(): + if self.name == element: + for attrib in attribs: + if attrib not in self.attributes: + self.attributes[attrib] = attribs[attrib] + + # ------------------------------------------------------------------------- + + # Property: last_child + # [Read-only] + last_child = property(get_last_child) + + # ------------------------------------------------------------------------- + + # Property: parent + # (Element) The parent element. + parent = None + + # Property: name + # (String) The name of the element (e.g., `div`) + name = '' + + # Property: attributes + # (Dict) The dictionary of attributes (e.g., `{'src': 'image.jpg'}`) + attributes = None + + # Property: children + # (List of Elements) The children + children = None + + # Property: opening_tag + # (String or None) The opening tag. Optional; will use `name` and + # `attributes` if this is not given. + opening_tag = None + + # Property: closing_tag + # (String or None) The closing tag + closing_tag = None + + text = '' + depth = -1 + expand = False + populate = False + parser = None + + # Property: prefix + # Only the root note can have this. + prefix = None + suffix = None + +# ============================================================================= + +class Token: + def __init__(self, string, parser=None): + """Token. + + Description: + string - The string to parse + + In the string `div > ul`, there are 3 tokens. (`div`, `>`, and `ul`) + + For `>`, it will be a `Token` with `type` set to `Token.CHILD` + """ + + self.string = string.strip() + self.attributes = {} + self.parser = parser + + # Set the type. + if self.string == '<': + self.type = Token.PARENT + elif self.string == '>': + self.type = Token.CHILD + elif self.string == '+': + self.type = Token.SIBLING + else: + self.type = Token.ELEMENT + self._init_element() + + def _init_element(self): + """Initializes. Only called if the token is an element token. + [Private] + """ + + # Get the tag name. Default to DIV if none given. + name = re.findall(r'^([\w\-:]*)', self.string)[0] + name = name.lower().replace('-', ':') + + # Find synonyms through this thesaurus + synonyms = self.parser.dialect.synonyms + if name in synonyms.keys(): + name = synonyms[name] + + if ':' in name: + shortcuts = self.parser.dialect.shortcuts + if name in shortcuts.keys(): + for key, value in shortcuts[name].iteritems(): + setattr(self, key, value) + if 'html' in name: + return + else: + self.name = name + + elif (name == ''): self.name = 'div' + else: self.name = name + + # Look for attributes + attribs = [] + for attrib in re.findall(r'\[([^\]]*)\]', self.string): + attribs.append(attrib) + self.string = self.string.replace("[" + attrib + "]", "") + if len(attribs) > 0: + for attrib in attribs: + try: key, value = attrib.split('=', 1) + except: key, value = attrib, '' + self.attributes[key] = value + + # Try looking for text + text = None + for text in re.findall(r'\{([^\}]*)\}', self.string): + self.string = self.string.replace("{" + text + "}", "") + if text is not None: + self.text = text + + # Get the class names + classes = [] + for classname in re.findall(r'\.([\$a-zA-Z0-9_\-\&]+)', self.string): + classes.append(classname) + if len(classes) > 0: + try: self.attributes['class'] + except: self.attributes['class'] = '' + self.attributes['class'] += ' ' + ' '.join(classes) + self.attributes['class'] = self.attributes['class'].strip() + + # Get the ID + id_match = re.search(r'#([\$a-zA-Z0-9_\-\&]+)', self.string) + if id_match is not None: + self.attributes['id'] = id_match.group(1) + + # See if there's a multiplier (e.g., "li*3") + multiplier_match = re.search(r'\*\s*([0-9]+)', self.string) + if multiplier_match is not None: + self.multiplier = int(multiplier_match.group(1)) + + # Populate flag (e.g., ul+) + flags_match = re.search(r'[\+\!]+$', self.string) + if flags_match is not None: + if '+' in flags_match.group(0): + self.populate = True + if '!' in flags_match.group(0): + self.expand = True + + def __str__(self): + return self.string + + string = '' + parser = None + + # For elements + # See the properties of `Element` for description on these. + name = '' + attributes = None + multiplier = 1 + expand = False + populate = False + text = '' + opening_tag = None + closing_tag = None + + # Type + type = 0 + ELEMENT = 2 + CHILD = 4 + PARENT = 8 + SIBLING = 16 + +# ============================================================================= + +def parse_args(): + optparser = OptionParser(version=VERSION, + description="Expands input into HTML.", + epilog="Please refer to the manual for more information.") + + + optparser.add_option('--no-guides', action="store_true", help='Deprecated') + optparser.add_option('--post-tag-guides', action="store_true", + help='Adds comments at the end of DIV tags') + optparser.add_option('--textmate', action="store_true", + help='Adds snippet info (textmate mode)') + optparser.add_option('--indent-spaces', help='Indent spaces') + optparser.add_option('--expand-divs', action="store_true", + help='Automatically expand divs') + optparser.add_option('--no-last-newline', action="store_false", + help='Skip the trailing newline') + optparser.add_option('--start-guide-format', help='To be documented') + optparser.add_option('--end-guide-format', help='To be documented') + optparser.add_option('--end-guide-newline', help='To be documented') + + optparser.set_defaults(post_tag_guides=False, textmate=False, + indent_spaces=4, expand_divs=False, last_newline=True, + start_guide_format="", end_guide_format="", end_guide_newline=True) + + # Make sure they're the correct types + opt_args = optparser.parse_args() + opt_args[0].indent_spaces = int(opt_args[0].indent_spaces) + opt_args[0].end_guide_newline = bool(int(opt_args[0].end_guide_newline)) + return opt_args + +def main(): + (options, _) = parse_args() + + lines = sys.stdin.read() + + parser = Parser(options, lines) + + output = parser.render() + sys.stdout.write(output) + +if __name__ == "__main__": + main() diff --git a/.vim/bundle/sparkup/ftplugin/html/sparkup.vim b/.vim/bundle/sparkup/ftplugin/html/sparkup.vim new file mode 100644 index 0000000..c5285d8 --- /dev/null +++ b/.vim/bundle/sparkup/ftplugin/html/sparkup.vim @@ -0,0 +1,74 @@ +" Sparkup +" Installation: +" Copy the contents of vim/ftplugin/ to your ~/.vim/ftplugin directory. +" +" $ cp -R vim/ftplugin ~/.vim/ftplugin/ +" +" Configuration: +" g:sparkup (Default: 'sparkup') - +" Location of the sparkup executable. You shouldn't need to change this +" setting if you used the install option above. +" +" g:sparkupArgs (Default: '--no-last-newline') - +" Additional args passed to sparkup. +" +" g:sparkupExecuteMapping (Default: '') - +" Mapping used to execute sparkup. +" +" g:sparkupNextMapping (Default: '') - +" Mapping used to jump to the next empty tag/attribute. + +if !exists('g:sparkupExecuteMapping') + let g:sparkupExecuteMapping = '' +endif + +if !exists('g:sparkupNextMapping') + let g:sparkupNextMapping = '' +endif + +exec 'nnoremap ' . g:sparkupExecuteMapping . ' :call Sparkup()' +exec 'inoremap ' . g:sparkupExecuteMapping . ' u:call Sparkup()' +exec 'nnoremap ' . g:sparkupNextMapping . ' :call SparkupNext()' +exec 'inoremap ' . g:sparkupNextMapping . ' u:call SparkupNext()' + +if exists('*s:Sparkup') + finish +endif + +function! s:Sparkup() + if !exists('s:sparkup') + let s:sparkup = exists('g:sparkup') ? g:sparkup : 'sparkup' + let s:sparkupArgs = exists('g:sparkupArgs') ? g:sparkupArgs : '--no-last-newline' + " check the user's path first. if not found then search relative to + " sparkup.vim in the runtimepath. + if !executable(s:sparkup) + let paths = substitute(escape(&runtimepath, ' '), '\(,\|$\)', '/**\1', 'g') + let s:sparkup = findfile('sparkup.py', paths) + + if !filereadable(s:sparkup) + echohl WarningMsg + echom 'Warning: could not find sparkup on your path or in your vim runtime path.' + echohl None + finish + endif + endif + let s:sparkup = '"' . s:sparkup . '"' + let s:sparkup .= printf(' %s --indent-spaces=%s', s:sparkupArgs, &shiftwidth) + if has('win32') || has('win64') + let s:sparkup = 'python ' . s:sparkup + endif + endif + exec '.!' . s:sparkup + call s:SparkupNext() +endfunction + +function! s:SparkupNext() + " 1: empty tag, 2: empty attribute, 3: empty line + let n = search('><\/\|\(""\)\|^\s*$', 'Wp') + if n == 3 + startinsert! + else + execute 'normal l' + startinsert + endif +endfunction diff --git a/.vim/bundle/sparkup/ftplugin/htmldjango b/.vim/bundle/sparkup/ftplugin/htmldjango new file mode 120000 index 0000000..6e8ea6c --- /dev/null +++ b/.vim/bundle/sparkup/ftplugin/htmldjango @@ -0,0 +1 @@ +/Users/sjl/lib/dotfiles/vim/bundle/sparkup/ftplugin/html \ No newline at end of file diff --git a/.vim/bundle/vim-config-python-ide/.gitignore b/.vim/bundle/vim-config-python-ide/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/.vim/bundle/vim-config-python-ide/.vimrc b/.vim/bundle/vim-config-python-ide/.vimrc new file mode 100644 index 0000000..ac58cb0 --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/.vimrc @@ -0,0 +1,118 @@ +" vimrc file for following the coding standards specified in PEP 7 & 8. +" +" To use this file, source it in your own personal .vimrc file (``source +" ``) or, if you don't have a .vimrc file, you can just symlink to it +" (``ln -s ~/.vimrc``). All options are protected by autocmds +" (read below for an explanation of the command) so blind sourcing of this file +" is safe and will not affect your settings for non-Python or non-C files. +" +" +" All setting are protected by 'au' ('autocmd') statements. Only files ending +" in .py or .pyw will trigger the Python settings while files ending in *.c or +" *.h will trigger the C settings. This makes the file "safe" in terms of only +" adjusting settings for Python and C files. +" +" Only basic settings needed to enforce the style guidelines are set. +" Some suggested options are listed but commented out at the end of this file. + +" Number of spaces that a pre-existing tab is equal to. +" For the amount of space used for a new tab use shiftwidth. +au BufRead,BufNewFile *py,*pyw,*.c,*.h set tabstop=8 + +" What to use for an indent. +" This will affect Ctrl-T and 'autoindent'. +" Python: 4 spaces +" C: tabs (pre-existing files) or 4 spaces (new files) +au BufRead,BufNewFile *.py,*pyw,*.html,*.js set shiftwidth=4 +au BufRead,BufNewFile *.py,*.pyw set expandtab +fu Select_c_style() + if search('^\t', 'n', 150) + set shiftwidth=8 + set noexpandtab + el + set shiftwidth=4 + set expandtab + en +endf +au BufRead,BufNewFile *.c,*.h call Select_c_style() +au BufRead,BufNewFile Makefile* set noexpandtab + +" Use the below highlight group when displaying bad whitespace is desired. +highlight BadWhitespace ctermbg=red guibg=red + +" Display tabs at the beginning of a line in Python mode as bad. +au BufRead,BufNewFile *.py,*.pyw match BadWhitespace /^\t\+/ +" Make trailing whitespace be flagged as bad. +au BufRead,BufNewFile *.py,*.pyw,*.c,*.h match BadWhitespace /\s\+$/ + +" Wrap text after a certain number of characters +" Python: 79 +" C: 79 +au BufRead,BufNewFile *.py,*.pyw,*.c,*.h set textwidth=79 + +" Turn off settings in 'formatoptions' relating to comment formatting. +" - c : do not automatically insert the comment leader when wrapping based on +" 'textwidth' +" - o : do not insert the comment leader when using 'o' or 'O' from command mode +" - r : do not insert the comment leader when hitting in insert mode +" Python: not needed +" C: prevents insertion of '*' at the beginning of every line in a comment +au BufRead,BufNewFile *.c,*.h set formatoptions-=c formatoptions-=o formatoptions-=r + +" Use UNIX (\n) line endings. +" Only used for new files so as to not force existing files to change their +" line endings. +" Python: yes +" C: yes +au BufNewFile *.py,*.pyw,*.c,*.h set fileformat=unix + + +" ---------------------------------------------------------------------------- +" The following section contains suggested settings. While in no way required +" to meet coding standards, they are helpful. + +" Set the default file encoding to UTF-8: +set encoding=utf-8 + +" Puts a marker at the beginning of the file to differentiate between UTF and +" UCS encoding (WARNING: can trick shells into thinking a text file is actually +" a binary file when executing the text file): ``set bomb`` + +" For full syntax highlighting: +let python_highlight_all=1 +syntax on + +" Automatically indent based on file type: +"filetype indent on +" Keep indentation level from previous line: +"set autoindent + +" Folding based on indentation: +set foldmethod=indent +set nofoldenable + +"""""""""""""""""""""""""""""""" +" END http://svn.python.org/projects/python/trunk/Misc/Vim/vimrc +"""""""""""""""""""""""""""""""" + +filetype plugin on +set iskeyword+=. + +autocmd FileType python set omnifunc=pythoncomplete#Complete +autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS +autocmd FileType html set omnifunc=htmlcomplete#CompleteTags +autocmd FileType css set omnifunc=csscomplete#CompleteCSS + +" inoremap + +" setlocal tabstop=4 +setlocal softtabstop=4 +" setlocal shiftwidth=4 +" setlocal textwidth=80 +" setlocal smarttab +" setlocal expandtab +" setlocal smartindent +" set noic "no ignore case +" set t_Co=256 + + diff --git a/.vim/bundle/vim-config-python-ide/README.rst b/.vim/bundle/vim-config-python-ide/README.rst new file mode 100644 index 0000000..06b22a0 --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/README.rst @@ -0,0 +1,83 @@ +Python-Vim-IDE +============== + +There will be multiple branches. The first branch will be the basic branch. +The basic branch will stay true to vim defaults, adding PEP008 and basic +onmicomplete, folding and path-hacking for django settings with few/no remaps. +I will branch from here with a more featureful config with nerdtree, supertab and more. + +The idea will be that one can check it out and symlink to $VIMRUNTIME and change +configs just by checking out a different branch. + + +Current details of basic +======================== + +* Syntax highlighting + + * (http://www.vim.org/scripts/script.php?script_id=790) + * now in .vim/syntax/python.vim + +* Indention + + * simple use of the following works:: + + if has("autocmd") + filetype plugin indent on + endif + + I uncommented this from my global /etc/vim/vimrc + +* Folding + + * Just going to use indentation folds from the default .vimrc:: + + :help fold + + zM to fold everything + zR to unfold everything + za to toggle the current fold + zA to recursively toggle the current fold + + Everything is unfolded to start. + +* Code completion + + * Going with regular http://www.vim.org/scripts/script.php?script_id=1542:: + + still for omnicomplete (may remap to ) + still for keyword completion (may remap to ) + + * :help preview + + To see how to do things like close the preview viewport (:pc) + +* Django settings: + + There are two ways that you can get the settings module imported and be able to omnicomplete + modules that rely on ``DJANGO_SETTINGS_MODULE``:: + + 1) You can be in an environment with django and settings.py in the CWD, parent or grandparent + + 2) You can be inside a virtualenv that contains pinax + + +supertab branch +=============== + +The same as above except that code completion is context sensitive and you +can get it with . So, if you are in insert mode and you have:: + + import django + +you can start typing django and complete it with keyword completion:: + + dja + +then you can type ``.`` and ```` again and get omnicompletion:: + + django.c + +this will give you a dropdown between ``conf``, ``core`` and ``contrib`` + + diff --git a/.vim/bundle/vim-config-python-ide/autoload/pythoncomplete.vim b/.vim/bundle/vim-config-python-ide/autoload/pythoncomplete.vim new file mode 100644 index 0000000..c37741e --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/autoload/pythoncomplete.vim @@ -0,0 +1,662 @@ +"pythoncomplete.vim - Omni Completion for python +" Maintainer: Aaron Griffin +" Version: 0.9 +" Last Updated: 18 Jun 2009 +" +" Changes +" TODO: +" 'info' item output can use some formatting work +" Add an "unsafe eval" mode, to allow for return type evaluation +" Complete basic syntax along with import statements +" i.e. "import url" +" Continue parsing on invalid line?? +" +" v 0.9 +" * Fixed docstring parsing for classes and functions +" * Fixed parsing of *args and **kwargs type arguments +" * Better function param parsing to handle things like tuples and +" lambda defaults args +" +" v 0.8 +" * Fixed an issue where the FIRST assignment was always used instead of +" using a subsequent assignment for a variable +" * Fixed a scoping issue when working inside a parameterless function +" +" +" v 0.7 +" * Fixed function list sorting (_ and __ at the bottom) +" * Removed newline removal from docs. It appears vim handles these better in +" recent patches +" +" v 0.6: +" * Fixed argument completion +" * Removed the 'kind' completions, as they are better indicated +" with real syntax +" * Added tuple assignment parsing (whoops, that was forgotten) +" * Fixed import handling when flattening scope +" +" v 0.5: +" Yeah, I skipped a version number - 0.4 was never public. +" It was a bugfix version on top of 0.3. This is a complete +" rewrite. +" + +if !has('python') + echo "Error: Required vim compiled with +python" + finish +endif + +function! pythoncomplete#Complete(findstart, base) + "findstart = 1 when we need to get the text length + if a:findstart == 1 + let line = getline('.') + let idx = col('.') + while idx > 0 + let idx -= 1 + let c = line[idx] + if c =~ '\w' + continue + elseif ! c =~ '\.' + let idx = -1 + break + else + break + endif + endwhile + + return idx + "findstart = 0 when we need to return the list of completions + else + "vim no longer moves the cursor upon completion... fix that + let line = getline('.') + let idx = col('.') + let cword = '' + while idx > 0 + let idx -= 1 + let c = line[idx] + if c =~ '\w' || c =~ '\.' + let cword = c . cword + continue + elseif strlen(cword) > 0 || idx == 0 + break + endif + endwhile + execute "python vimcomplete('" . cword . "', '" . a:base . "')" + return g:pythoncomplete_completions + endif +endfunction + +function! s:DefPython() +python << PYTHONEOF +import sys, tokenize, cStringIO, types, os +from token import NAME, DEDENT, NEWLINE, STRING + +''' Path-hacking for django by SKYL ''' + +parent = os.path.split( os.getcwd() )[0] +gparent = os.path.split( parent )[0] + +sys.path.append( os.getcwd() ) +sys.path.append( parent ) +sys.path.append( gparent ) + +try: + # if you have django installed, and a settings.py in your CWD, + # the parent or the grandparent, + # you can use those project settings + import settings + import django.core.management + django.core.management.setup_environ(settings) + + #print 'got Django settings', settings.__file__ + +except ImportError: + # if you have pinax in your env, you can use the social_project + # settings + try: + from pinax.projects.social_project import settings + import django.core.management + django.core.management.setup_environ(settings) + + #print 'got Django settings', settings.__file__ + + except ImportError: + pass + +''' END PATH HACKING ''' + + +debugstmts=[] +def dbg(s): debugstmts.append(s) +def showdbg(): + for d in debugstmts: print "DBG: %s " % d + +def vimcomplete(context,match): + global debugstmts + debugstmts = [] + try: + import vim + def complsort(x,y): + try: + xa = x['abbr'] + ya = y['abbr'] + if xa[0] == '_': + if xa[1] == '_' and ya[0:2] == '__': + return xa > ya + elif ya[0:2] == '__': + return -1 + elif y[0] == '_': + return xa > ya + else: + return 1 + elif ya[0] == '_': + return -1 + else: + return xa > ya + except: + return 0 + cmpl = Completer() + cmpl.evalsource('\n'.join(vim.current.buffer),vim.eval("line('.')")) + all = cmpl.get_completions(context,match) + all.sort(complsort) + dictstr = '[' + # have to do this for double quoting + for cmpl in all: + dictstr += '{' + for x in cmpl: dictstr += '"%s":"%s",' % (x,cmpl[x]) + dictstr += '"icase":0},' + if dictstr[-1] == ',': dictstr = dictstr[:-1] + dictstr += ']' + #dbg("dict: %s" % dictstr) + vim.command("silent let g:pythoncomplete_completions = %s" % dictstr) + #dbg("Completion dict:\n%s" % all) + except vim.error: + dbg("VIM Error: %s" % vim.error) + +class Completer(object): + def __init__(self): + self.compldict = {} + self.parser = PyParser() + + def evalsource(self,text,line=0): + sc = self.parser.parse(text,line) + src = sc.get_code() + dbg("source: %s" % src) + try: exec(src) in self.compldict + except: dbg("parser: %s, %s" % (sys.exc_info()[0],sys.exc_info()[1])) + for l in sc.locals: + try: exec(l) in self.compldict + except: dbg("locals: %s, %s [%s]" % (sys.exc_info()[0],sys.exc_info()[1],l)) + + def _cleanstr(self,doc): + return doc.replace('"',' ').replace("'",' ') + + def get_arguments(self,func_obj): + def _ctor(obj): + try: return class_ob.__init__.im_func + except AttributeError: + for base in class_ob.__bases__: + rc = _find_constructor(base) + if rc is not None: return rc + return None + + arg_offset = 1 + if type(func_obj) == types.ClassType: func_obj = _ctor(func_obj) + elif type(func_obj) == types.MethodType: func_obj = func_obj.im_func + else: arg_offset = 0 + + arg_text='' + if type(func_obj) in [types.FunctionType, types.LambdaType]: + try: + cd = func_obj.func_code + real_args = cd.co_varnames[arg_offset:cd.co_argcount] + defaults = func_obj.func_defaults or '' + defaults = map(lambda name: "=%s" % name, defaults) + defaults = [""] * (len(real_args)-len(defaults)) + defaults + items = map(lambda a,d: a+d, real_args, defaults) + if func_obj.func_code.co_flags & 0x4: + items.append("...") + if func_obj.func_code.co_flags & 0x8: + items.append("***") + arg_text = (','.join(items)) + ')' + + except: + dbg("arg completion: %s: %s" % (sys.exc_info()[0],sys.exc_info()[1])) + pass + if len(arg_text) == 0: + # The doc string sometimes contains the function signature + # this works for alot of C modules that are part of the + # standard library + doc = func_obj.__doc__ + if doc: + doc = doc.lstrip() + pos = doc.find('\n') + if pos > 0: + sigline = doc[:pos] + lidx = sigline.find('(') + ridx = sigline.find(')') + if lidx > 0 and ridx > 0: + arg_text = sigline[lidx+1:ridx] + ')' + if len(arg_text) == 0: arg_text = ')' + return arg_text + + def get_completions(self,context,match): + dbg("get_completions('%s','%s')" % (context,match)) + stmt = '' + if context: stmt += str(context) + if match: stmt += str(match) + try: + result = None + all = {} + ridx = stmt.rfind('.') + if len(stmt) > 0 and stmt[-1] == '(': + result = eval(_sanitize(stmt[:-1]), self.compldict) + doc = result.__doc__ + if doc is None: doc = '' + args = self.get_arguments(result) + return [{'word':self._cleanstr(args),'info':self._cleanstr(doc)}] + elif ridx == -1: + match = stmt + all = self.compldict + else: + match = stmt[ridx+1:] + stmt = _sanitize(stmt[:ridx]) + result = eval(stmt, self.compldict) + all = dir(result) + + dbg("completing: stmt:%s" % stmt) + completions = [] + + try: maindoc = result.__doc__ + except: maindoc = ' ' + if maindoc is None: maindoc = ' ' + for m in all: + if m == "_PyCmplNoType": continue #this is internal + try: + dbg('possible completion: %s' % m) + if m.find(match) == 0: + if result is None: inst = all[m] + else: inst = getattr(result,m) + try: doc = inst.__doc__ + except: doc = maindoc + typestr = str(inst) + if doc is None or doc == '': doc = maindoc + + wrd = m[len(match):] + c = {'word':wrd, 'abbr':m, 'info':self._cleanstr(doc)} + if "function" in typestr: + c['word'] += '(' + c['abbr'] += '(' + self._cleanstr(self.get_arguments(inst)) + elif "method" in typestr: + c['word'] += '(' + c['abbr'] += '(' + self._cleanstr(self.get_arguments(inst)) + elif "module" in typestr: + c['word'] += '.' + elif "class" in typestr: + c['word'] += '(' + c['abbr'] += '(' + completions.append(c) + except: + i = sys.exc_info() + dbg("inner completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt)) + return completions + except: + i = sys.exc_info() + dbg("completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt)) + return [] + +class Scope(object): + def __init__(self,name,indent,docstr=''): + self.subscopes = [] + self.docstr = docstr + self.locals = [] + self.parent = None + self.name = name + self.indent = indent + + def add(self,sub): + #print 'push scope: [%s@%s]' % (sub.name,sub.indent) + sub.parent = self + self.subscopes.append(sub) + return sub + + def doc(self,str): + """ Clean up a docstring """ + d = str.replace('\n',' ') + d = d.replace('\t',' ') + while d.find(' ') > -1: d = d.replace(' ',' ') + while d[0] in '"\'\t ': d = d[1:] + while d[-1] in '"\'\t ': d = d[:-1] + dbg("Scope(%s)::docstr = %s" % (self,d)) + self.docstr = d + + def local(self,loc): + self._checkexisting(loc) + self.locals.append(loc) + + def copy_decl(self,indent=0): + """ Copy a scope's declaration only, at the specified indent level - not local variables """ + return Scope(self.name,indent,self.docstr) + + def _checkexisting(self,test): + "Convienance function... keep out duplicates" + if test.find('=') > -1: + var = test.split('=')[0].strip() + for l in self.locals: + if l.find('=') > -1 and var == l.split('=')[0].strip(): + self.locals.remove(l) + + def get_code(self): + str = "" + if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n' + for l in self.locals: + if l.startswith('import'): str += l+'\n' + str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n' + for sub in self.subscopes: + str += sub.get_code() + for l in self.locals: + if not l.startswith('import'): str += l+'\n' + + return str + + def pop(self,indent): + #print 'pop scope: [%s] to [%s]' % (self.indent,indent) + outer = self + while outer.parent != None and outer.indent >= indent: + outer = outer.parent + return outer + + def currentindent(self): + #print 'parse current indent: %s' % self.indent + return ' '*self.indent + + def childindent(self): + #print 'parse child indent: [%s]' % (self.indent+1) + return ' '*(self.indent+1) + +class Class(Scope): + def __init__(self, name, supers, indent, docstr=''): + Scope.__init__(self,name,indent, docstr) + self.supers = supers + def copy_decl(self,indent=0): + c = Class(self.name,self.supers,indent, self.docstr) + for s in self.subscopes: + c.add(s.copy_decl(indent+1)) + return c + def get_code(self): + str = '%sclass %s' % (self.currentindent(),self.name) + if len(self.supers) > 0: str += '(%s)' % ','.join(self.supers) + str += ':\n' + if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n' + if len(self.subscopes) > 0: + for s in self.subscopes: str += s.get_code() + else: + str += '%spass\n' % self.childindent() + return str + + +class Function(Scope): + def __init__(self, name, params, indent, docstr=''): + Scope.__init__(self,name,indent, docstr) + self.params = params + def copy_decl(self,indent=0): + return Function(self.name,self.params,indent, self.docstr) + def get_code(self): + str = "%sdef %s(%s):\n" % \ + (self.currentindent(),self.name,','.join(self.params)) + if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n' + str += "%spass\n" % self.childindent() + return str + +class PyParser: + def __init__(self): + self.top = Scope('global',0) + self.scope = self.top + + def _parsedotname(self,pre=None): + #returns (dottedname, nexttoken) + name = [] + if pre is None: + tokentype, token, indent = self.next() + if tokentype != NAME and token != '*': + return ('', token) + else: token = pre + name.append(token) + while True: + tokentype, token, indent = self.next() + if token != '.': break + tokentype, token, indent = self.next() + if tokentype != NAME: break + name.append(token) + return (".".join(name), token) + + def _parseimportlist(self): + imports = [] + while True: + name, token = self._parsedotname() + if not name: break + name2 = '' + if token == 'as': name2, token = self._parsedotname() + imports.append((name, name2)) + while token != "," and "\n" not in token: + tokentype, token, indent = self.next() + if token != ",": break + return imports + + def _parenparse(self): + name = '' + names = [] + level = 1 + while True: + tokentype, token, indent = self.next() + if token in (')', ',') and level == 1: + if '=' not in name: name = name.replace(' ', '') + names.append(name.strip()) + name = '' + if token == '(': + level += 1 + name += "(" + elif token == ')': + level -= 1 + if level == 0: break + else: name += ")" + elif token == ',' and level == 1: + pass + else: + name += "%s " % str(token) + return names + + def _parsefunction(self,indent): + self.scope=self.scope.pop(indent) + tokentype, fname, ind = self.next() + if tokentype != NAME: return None + + tokentype, open, ind = self.next() + if open != '(': return None + params=self._parenparse() + + tokentype, colon, ind = self.next() + if colon != ':': return None + + return Function(fname,params,indent) + + def _parseclass(self,indent): + self.scope=self.scope.pop(indent) + tokentype, cname, ind = self.next() + if tokentype != NAME: return None + + super = [] + tokentype, next, ind = self.next() + if next == '(': + super=self._parenparse() + elif next != ':': return None + + return Class(cname,super,indent) + + def _parseassignment(self): + assign='' + tokentype, token, indent = self.next() + if tokentype == tokenize.STRING or token == 'str': + return '""' + elif token == '(' or token == 'tuple': + return '()' + elif token == '[' or token == 'list': + return '[]' + elif token == '{' or token == 'dict': + return '{}' + elif tokentype == tokenize.NUMBER: + return '0' + elif token == 'open' or token == 'file': + return 'file' + elif token == 'None': + return '_PyCmplNoType()' + elif token == 'type': + return 'type(_PyCmplNoType)' #only for method resolution + else: + assign += token + level = 0 + while True: + tokentype, token, indent = self.next() + if token in ('(','{','['): + level += 1 + elif token in (']','}',')'): + level -= 1 + if level == 0: break + elif level == 0: + if token in (';','\n'): break + assign += token + return "%s" % assign + + def next(self): + type, token, (lineno, indent), end, self.parserline = self.gen.next() + if lineno == self.curline: + #print 'line found [%s] scope=%s' % (line.replace('\n',''),self.scope.name) + self.currentscope = self.scope + return (type, token, indent) + + def _adjustvisibility(self): + newscope = Scope('result',0) + scp = self.currentscope + while scp != None: + if type(scp) == Function: + slice = 0 + #Handle 'self' params + if scp.parent != None and type(scp.parent) == Class: + slice = 1 + newscope.local('%s = %s' % (scp.params[0],scp.parent.name)) + for p in scp.params[slice:]: + i = p.find('=') + if len(p) == 0: continue + pvar = '' + ptype = '' + if i == -1: + pvar = p + ptype = '_PyCmplNoType()' + else: + pvar = p[:i] + ptype = _sanitize(p[i+1:]) + if pvar.startswith('**'): + pvar = pvar[2:] + ptype = '{}' + elif pvar.startswith('*'): + pvar = pvar[1:] + ptype = '[]' + + newscope.local('%s = %s' % (pvar,ptype)) + + for s in scp.subscopes: + ns = s.copy_decl(0) + newscope.add(ns) + for l in scp.locals: newscope.local(l) + scp = scp.parent + + self.currentscope = newscope + return self.currentscope + + #p.parse(vim.current.buffer[:],vim.eval("line('.')")) + def parse(self,text,curline=0): + self.curline = int(curline) + buf = cStringIO.StringIO(''.join(text) + '\n') + self.gen = tokenize.generate_tokens(buf.readline) + self.currentscope = self.scope + + try: + freshscope=True + while True: + tokentype, token, indent = self.next() + #dbg( 'main: token=[%s] indent=[%s]' % (token,indent)) + + if tokentype == DEDENT or token == "pass": + self.scope = self.scope.pop(indent) + elif token == 'def': + func = self._parsefunction(indent) + if func is None: + print "function: syntax error..." + continue + dbg("new scope: function") + freshscope = True + self.scope = self.scope.add(func) + elif token == 'class': + cls = self._parseclass(indent) + if cls is None: + print "class: syntax error..." + continue + freshscope = True + dbg("new scope: class") + self.scope = self.scope.add(cls) + + elif token == 'import': + imports = self._parseimportlist() + for mod, alias in imports: + loc = "import %s" % mod + if len(alias) > 0: loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + elif token == 'from': + mod, token = self._parsedotname() + if not mod or token != "import": + print "from: syntax error..." + continue + names = self._parseimportlist() + for name, alias in names: + loc = "from %s import %s" % (mod,name) + if len(alias) > 0: loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + elif tokentype == STRING: + if freshscope: self.scope.doc(token) + elif tokentype == NAME: + name,token = self._parsedotname(token) + if token == '=': + stmt = self._parseassignment() + dbg("parseassignment: %s = %s" % (name, stmt)) + if stmt != None: + self.scope.local("%s = %s" % (name,stmt)) + freshscope = False + except StopIteration: #thrown on EOF + pass + except: + dbg("parse error: %s, %s @ %s" % + (sys.exc_info()[0], sys.exc_info()[1], self.parserline)) + return self._adjustvisibility() + +def _sanitize(str): + val = '' + level = 0 + for c in str: + if c in ('(','{','['): + level += 1 + elif c in (']','}',')'): + level -= 1 + elif level == 0: + val += c + return val + + +sys.path.extend(['.','..']) + +PYTHONEOF +endfunction + +call s:DefPython() +" vim: set et ts=4: diff --git a/.vim/bundle/vim-config-python-ide/doc/supertab.txt b/.vim/bundle/vim-config-python-ide/doc/supertab.txt new file mode 100644 index 0000000..3eadefe --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/doc/supertab.txt @@ -0,0 +1,308 @@ +*supertab.txt* + +Authors: + Original: Gergely Kontra + Current: Eric Van Dewoestine (as of version 0.4) + +Contributors: + Christophe-Marie Duquesne (documentation) + +Please direct all correspondence to Eric. + +This plugin is licensed under the terms of the BSD License. Please see +supertab.vim for the license in its entirety. + +============================================================================== +Supertab *supertab* + +1. Introduction |supertab-intro| +2. Supertab Usage |supertab-usage| +3. Supertab Options |supertab-options| + Default completion type |supertab-defaultcompletion| + Secondary default completion type |supertab-contextdefault| + Completion contexts |supertab-completioncontexts| + Context text |supertab-contexttext| + Context Discover |supertab-contextdiscover| + Example |supertab-contextexample| + Completion Duration |supertab-duration| + Midword completion |supertab-midword| + Changing default mapping |supertab-forwardbackward| + Inserting true tabs |supertab-mappingtabliteral| + Preselecting the first entry |supertab-longesthighlight| + +============================================================================== +1. Introduction *supertab-intro* + +Supertab is a plugin which allows you to perform all your insert completion +(|ins-completion|) using the tab key. + +Supertab requires Vim version 7.0 or above. + +============================================================================== +2. Supertab usage *supertab-usage* + +Using Supertab is as easy as hitting or (shift+tab) while in +insert mode, with at least one non whitespace character before the cursor, to +start the completion and then or again to cycle forwards or +backwards through the available completions. + +Example ('|' denotes the cursor location): + +bar +baz +b| Hitting here will start the completion, allowing you to + then cycle through the suggested words ('bar' and 'baz'). + +============================================================================== +3. Supertab Options *supertab-options* + +Supertab is configured via several global variables that you can set in your +|vimrc| file according to your needs. Below is a comprehensive list of +the variables available. + +g:SuperTabDefaultCompletionType |supertab-defaultcompletion| + The default completion type to use. If you program in languages that support + omni or user completions, it is highly recommended setting this to + 'context'. + + For help about built in completion types in vim, see |i_CTRL-X_index|. + +g:SuperTabContextDefaultCompletionType |supertab-contextdefault| + The default completion type to use when 'context' is the global default, but + context completion has determined that neither omni, user, or file + completion should be used in the current context. + +g:SuperTabCompletionContexts |supertab-completioncontexts| + Used to configure a list of function names which are used when the global + default type is 'context'. These functions will be consulted in order to + determine which completion type to use. Advanced users can plug in their own + functions here to customize their 'context' completion. + +g:SuperTabRetainCompletionDuration |supertab-duration| + This setting determines how long a non-default completion type should be + retained as the temporary default. By default supertab will retain the + alternate completion type until you leave insert mode. + +g:SuperTabMidWordCompletion |supertab-midword| + This can be used to turn off completion if you are in the middle of a word + (word characters immediately preceding and following the cursor). + +g:SuperTabMappingForward |supertab-forwardbackward| +g:SuperTabMappingBackward |supertab-forwardbackward| + If using the tab key for completion isn't for you, then you can use these to + set an alternate key to be used for your insert completion needs. + +g:SuperTabMappingTabLiteral |supertab-mappingtabliteral| + For those rare cases where supertab would normal want to start insert + completion, but you just want to insert a tab, this setting is used to + define the key combination to use to do just that. By default Ctrl-Tab is + used. + +g:SuperTabLongestHighlight |supertab-longesthighlight| + When enabled and you have the completion popup enable and 'longest' in your + completeopt, supertab will auto highlight the first selection in the popup. + + +Default Completion Type *supertab-defaultcompletion* + *g:SuperTabDefaultCompletionType* + +g:SuperTabDefaultCompletionType (default value: "") + +Used to set the default completion type. There is no need to escape this +value as that will be done for you when the type is set. + + Example: setting the default completion to 'user' completion: + + let g:SuperTabDefaultCompletionType = "" + +Note: a special value of 'context' is supported which will result in +super tab attempting to use the text preceding the cursor to decide which +type of completion to attempt. Currently super tab can recognize method +calls or attribute references via '.', '::' or '->', and file path +references containing '/'. + + let g:SuperTabDefaultCompletionType = "context" + + /usr/l # will use filename completion + myvar.t # will use user completion if completefunc set, + # or omni completion if omnifunc set. + myvar-> # same as above + +When using context completion, super tab will fall back to a secondary default +completion type set by |g:SuperTabContextDefaultCompletionType|. + +Note: once the buffer has been initialized, changing the value of this setting +will not change the default complete type used. If you want to change the +default completion type for the current buffer after it has been set, perhaps +in an ftplugin, you'll need to call SuperTabSetDefaultCompletionType like so, +supplying the completion type you wish to switch to: + + call SuperTabSetDefaultCompletionType("") + + +Secondary default completion type *supertab-contextdefault* + *g:SuperTabContextDefaultCompletionType* + +g:SuperTabContextDefaultCompletionType (default value: "") + +Sets the default completion type used when g:SuperTabDefaultCompletionType is +set to 'context' and no completion type is returned by any of the configured +contexts. + + +Completion contexts *supertab-completioncontexts* + *g:SuperTabCompletionContexts* + +g:SuperTabCompletionContexts (default value: ['s:ContextText']) + +Sets the list of contexts used for context completion. This value should +be a list of function names which provide the context implementation. + +When supertab starts the default completion, each of these contexts will be +consulted, in the order they were supplied, to determine the completion type +to use. If a context returns a completion type, that type will be used, +otherwise the next context in the list will be consulted. If after executing +all the context functions, no completion type has been determined, then the +value of g:SuperTabContextDefaultCompletionType will be used. + +Built in completion contexts: + + s:ContextText *supertab-contexttext* + + The text context will examine the text near the cursor to decide which type + of completion to attempt. Currently the text context can recognize method + calls or attribute references via '.', '::' or '->', and file path + references containing '/'. + + /usr/l # will use filename completion + myvar.t # will use user completion if completefunc set, or + # omni completion if omnifunc set. + myvar-> # same as above + + Supported configuration attributes: + + g:SuperTabContextTextFileTypeExclusions + List of file types for which the text context will be skipped. + + g:SuperTabContextTextOmniPrecedence + List of omni completion option names in the order of precedence that they + should be used if available. By default, user completion will be given + precedence over omni completion, but you can use this variable to give + omni completion higher precedence by placing it first in the list. + + s:ContextDiscover *supertab-contextdiscover* + + This context will use the 'g:SuperTabContextDiscoverDiscovery' variable to + determine the completion type to use. It will evaluate each value, in the + order they were defined, until a variable evaluates to a non-zero or + non-empty value, then the associated completion type is used. + + Supported configuration properties: + + g:SuperTabContextDiscoverDiscovery + List of variable:completionType mappings. + + Example context configuration: *supertab-contextexample* + + let g:SuperTabCompletionContexts = ['s:ContextText', 's:ContextDiscover'] + let g:SuperTabContextTextOmniPrecedence = ['&omnifunc', '&completefunc'] + let g:SuperTabContextDiscoverDiscovery = + \ ["&completefunc:", "&omnifunc:"] + + In addition to the default completion contexts, you can plug in your own + implementation by creating a globally accessible function that returns + the completion type to use (eg. "\\"). + + function MyTagContext() + if filereadable(expand('%:p:h') . '/tags') + return "\\" + endif + " no return will result in the evaluation of the next + " configured context + endfunction + let g:SuperTabCompletionContexts = + \ ['MyTagContext', 's:ContextText', 's:ContextDiscover'] + + Note: supertab also supports the b:SuperTabCompletionContexts variable + allowing you to set the list of contexts separately for the current buffer, + like from an ftplugin for example. + + +Completion Duration *supertab-duration* + *g:SuperTabRetainCompletionDuration* + +g:SuperTabRetainCompletionDuration (default value: 'insert') + +Determines if, and for how long, the current completion type is retained. +The possible values include: +'completion' - The current completion type is only retained for the + current completion. Once you have chosen a completion + result or exited the completion mode, the default + completion type is restored. +'insert' - The current completion type is saved until you exit insert + mode (via ESC). Once you exit insert mode the default + completion type is restored. (supertab default) +'session' - The current completion type is saved for the duration of + your vim session or until you enter a different completion + mode. + + +Midword completion *supertab-midword* + *g:SuperTabMidWordCompletion* + +g:SuperTabMidWordCompletion (default value: 1) + +Sets whether or not mid word completion is enabled. When enabled, will +kick off completion when ever a non whitespace character is to the left of the +cursor. When disabled, completion will only occur if the char to the left is +non whitespace char and the char to the right is not a keyword character (you +are at the end of the word). + + +Changing the default mapping *supertab-forwardbackward* + *g:SuperTabMappingForward* + *g:SuperTabMappingBackward* + +g:SuperTabMappingForward (default value: '') +g:SuperTabMappingBackward (default value: '') + +These two variables allow you to set the keys used to kick off the current +completion. By default this is and . To change to something +like and , you can add the following to your |vimrc|. + + let g:SuperTabMappingForward = '' + let g:SuperTabMappingBackward = '' + +Note: if the above does not have the desired effect (which may happen in +console version of vim), you can try the following mappings. Although the +backwards mapping still doesn't seem to work in the console for me, your +milage may vary. + + let g:SuperTabMappingForward = '' + let g:SuperTabMappingBackward = '' + + +Inserting true tabs *supertab-mappingtabliteral* + *g:SuperTabMappingTabLiteral* + +g:SuperTabMappingTabLiteral (default value: '') + +Sets the key mapping used to insert a literal tab where supertab would +otherwise attempt to kick off insert completion. The default is '' +(ctrl-tab) which unfortunately might not work at the console. So if you are +using a console vim and want this functionality, you may have to change it to +something that is supported. Alternatively, you can escape the with + (see |i_CTRL-V| for more infos). + + +Preselecting the first entry *supertab-longesthighlight* + *g:SuperTabLongestHighlight* + +g:SuperTabLongestHighlight (default value: 0) + +Sets whether or not to pre-highlight the first match when completeopt has the +popup menu enabled and the 'longest' option as well. When enabled, will +kick off completion and pre-select the first entry in the popup menu, allowing +you to simply hit to use it. + +vim:tw=78:ts=8:ft=help:norl: diff --git a/.vim/bundle/vim-config-python-ide/plugin/supertab.vim b/.vim/bundle/vim-config-python-ide/plugin/supertab.vim new file mode 100644 index 0000000..f277950 --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/plugin/supertab.vim @@ -0,0 +1,511 @@ +" Author: +" Original: Gergely Kontra +" Current: Eric Van Dewoestine (as of version 0.4) +" Please direct all correspondence to Eric. +" Version: 1.0 +" GetLatestVimScripts: 1643 1 :AutoInstall: supertab.vim +" +" Description: {{{ +" Use your tab key to do all your completion in insert mode! +" You can cycle forward and backward with the and keys +" Note: you must press once to be able to cycle back +" +" http://www.vim.org/scripts/script.php?script_id=1643 +" }}} +" +" License: {{{ +" Software License Agreement (BSD License) +" +" Copyright (c) 2002 - 2009 +" All rights reserved. +" +" Redistribution and use of this software in source and binary forms, with +" or without modification, are permitted provided that the following +" conditions are met: +" +" * Redistributions of source code must retain the above +" copyright notice, this list of conditions and the +" following disclaimer. +" +" * Redistributions in binary form must reproduce the above +" copyright notice, this list of conditions and the +" following disclaimer in the documentation and/or other +" materials provided with the distribution. +" +" * Neither the name of Gergely Kontra or Eric Van Dewoestine nor the names +" of its contributors may be used to endorse or promote products derived +" from this software without specific prior written permission of Gergely +" Kontra or Eric Van Dewoestine. +" +" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +" IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +" THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +" }}} +" +" Testing Info: {{{ +" Running vim + supertab with the absolute bar minimum settings: +" $ vim -u NONE -U NONE -c "set nocp | runtime plugin/supertab.vim" +" }}} + +if v:version < 700 + finish +endif + +if exists('complType') " Integration with other completion functions. + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Global Variables {{{ + + if !exists("g:SuperTabDefaultCompletionType") + let g:SuperTabDefaultCompletionType = "context" + endif + + if !exists("g:SuperTabContextDefaultCompletionType") + let g:SuperTabContextDefaultCompletionType = "" + endif + + if !exists("g:SuperTabCompletionContexts") + let g:SuperTabCompletionContexts = ['s:ContextText'] + endif + + if !exists("g:SuperTabRetainCompletionDuration") + let g:SuperTabRetainCompletionDuration = 'completion' + endif + + if !exists("g:SuperTabMidWordCompletion") + let g:SuperTabMidWordCompletion = 1 + endif + + if !exists("g:SuperTabMappingForward") + let g:SuperTabMappingForward = '' + + endif + if !exists("g:SuperTabMappingBackward") + let g:SuperTabMappingBackward = '' + endif + + if !exists("g:SuperTabMappingTabLiteral") + let g:SuperTabMappingTabLiteral = '' + endif + + if !exists("g:SuperTabLongestHighlight") + let g:SuperTabLongestHighlight = 0 + endif + +" }}} + +" Script Variables {{{ + + " construct the help text. + let s:tabHelp = + \ "Hit or CTRL-] on the completion type you wish to switch to.\n" . + \ "Use :help ins-completion for more information.\n" . + \ "\n" . + \ "|| - Keywords in 'complete' searching down.\n" . + \ "|| - Keywords in 'complete' searching up (SuperTab default).\n" . + \ "|| - Whole lines.\n" . + \ "|| - Keywords in current file.\n" . + \ "|| - Keywords in 'dictionary'.\n" . + \ "|| - Keywords in 'thesaurus', thesaurus-style.\n" . + \ "|| - Keywords in the current and included files.\n" . + \ "|| - Tags.\n" . + \ "|| - File names.\n" . + \ "|| - Definitions or macros.\n" . + \ "|| - Vim command-line.\n" . + \ "|| - User defined completion.\n" . + \ "|| - Omni completion.\n" . + \ "|s| - Spelling suggestions." + + " set the available completion types and modes. + let s:types = + \ "\\\\\\\\" . + \ "\\\\\\\\\s" + let s:modes = '/^E/^Y/^L/^N/^K/^T/^I/^]/^F/^D/^V/^P/^U/^O/s' + let s:types = s:types . "np" + let s:modes = s:modes . '/n/p' + +" }}} + +" SuperTabSetDefaultCompletionType(type) {{{ +" Globally available function that users can use to set the default +" completion type for the current buffer, like in an ftplugin. +function! SuperTabSetDefaultCompletionType(type) + " init hack for workaround. + let b:complCommandLine = 0 + + let b:SuperTabDefaultCompletionType = a:type + + " set the current completion type to the default + call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) +endfunction " }}} + +" SuperTabSetCompletionType(type) {{{ +" Globally available function that users can use to create mappings to quickly +" switch completion modes. Useful when a user wants to restore the default or +" switch to another mode without having to kick off a completion of that type +" or use SuperTabHelp. Note, this function only changes the current +" completion type, not the default, meaning that the default will still be +" restored once the configured retension duration has been met (see +" g:SuperTabRetainCompletionDuration). To change the default for the current +" buffer, use SuperTabDefaultCompletionType(type) instead. Example mapping to +" restore SuperTab default: +" nmap :call SetSuperTabCompletionType("") +function! SuperTabSetCompletionType(type) + exec "let b:complType = \"" . escape(a:type, '<') . "\"" +endfunction " }}} + +" SuperTabAlternateCompletion(type) {{{ +" Function which can be mapped to a key to kick off an alternate completion +" other than the default. For instance, if you have 'context' as the default +" and want to map ctrl+space to issue keyword completion. +" Note: due to the way vim expands ctrl characters in mappings, you cannot +" create the alternate mapping like so: +" imap =SuperTabAlternateCompletion("") +" instead, you have to use \ to prevent vim from expanding the key +" when creating the mapping. +" gvim: +" imap =SuperTabAlternateCompletion("\c-p>") +" console: +" imap =SuperTabAlternateCompletion("\c-p>") +function! SuperTabAlternateCompletion(type) + call SuperTabSetCompletionType(a:type) + " end any current completion before attempting to start the new one. + " use feedkeys to prevent possible remapping of from causing issues. + "call feedkeys("\", 'n') + " ^ since we can't detect completion mode vs regular insert mode, we force + " vim into keyword completion mode and end that mode to prevent the regular + " insert behavior of from occurring. + call feedkeys("\\\", 'n') + call feedkeys(b:complType) + return '' +endfunction " }}} + +" s:Init {{{ +" Global initilization when supertab is loaded. +function! s:Init() + augroup supertab_init + autocmd! + autocmd BufEnter * call InitBuffer() + augroup END + + " ensure InitBuffer gets called for the first buffer, after the ftplugins + " have been called. + augroup supertab_init_first + autocmd! + autocmd FileType call InitBuffer() + augroup END + + " Setup mechanism to restore orignial completion type upon leaving insert + " mode if configured to do so + if g:SuperTabRetainCompletionDuration == 'insert' + augroup supertab_retain + autocmd! + autocmd InsertLeave * call s:SetDefaultCompletionType() + augroup END + endif +endfunction " }}} + +" s:InitBuffer {{{ +" Per buffer initilization. +function! s:InitBuffer() + if exists("b:complType") + return + endif + + " init hack for workaround. + let b:complCommandLine = 0 + + let b:SuperTabDefaultCompletionType = g:SuperTabDefaultCompletionType + + " set the current completion type to the default + call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) +endfunction " }}} + +" s:ManualCompletionEnter() {{{ +" Handles manual entrance into completion mode. +function! s:ManualCompletionEnter() + if &smd + echo '' | echohl ModeMsg | echo '-- ^X++ mode (' . s:modes . ')' | echohl None + endif + let complType = nr2char(getchar()) + if stridx(s:types, complType) != -1 + if stridx("\\", complType) != -1 " no memory, just scroll... + return "\" . complType + elseif stridx('np', complType) != -1 + let complType = nr2char(char2nr(complType) - 96) + else + let complType = "\" . complType + endif + + if index(['insert', 'session'], g:SuperTabRetainCompletionDuration) != -1 + let b:complType = complType + endif + + " Hack to workaround bug when invoking command line completion via = + if complType == "\\" + return s:CommandLineCompletion() + endif + + return complType + endif + + echohl "Unknown mode" + return complType +endfunction " }}} + +" s:SetCompletionType() {{{ +" Sets the completion type based on what the user has chosen from the help +" buffer. +function! s:SetCompletionType() + let chosen = substitute(getline('.'), '.*|\(.*\)|.*', '\1', '') + if chosen != getline('.') + let winnr = b:winnr + close + exec winnr . 'winc w' + call SuperTabSetCompletionType(chosen) + endif +endfunction " }}} + +" s:SetDefaultCompletionType() {{{ +function! s:SetDefaultCompletionType() + if exists('b:SuperTabDefaultCompletionType') && + \ (!exists('b:complCommandLine') || !b:complCommandLine) + call SuperTabSetCompletionType(b:SuperTabDefaultCompletionType) + endif +endfunction " }}} + +" s:SuperTab(command) {{{ +" Used to perform proper cycle navigation as the user requests the next or +" previous entry in a completion list, and determines whether or not to simply +" retain the normal usage of based on the cursor position. +function! s:SuperTab(command) + if s:WillComplete() + " rare case where no autocmds have fired for this buffer to initialize the + " supertab vars. + call s:InitBuffer() + + let key = '' + " highlight first result if longest enabled + if g:SuperTabLongestHighlight && !pumvisible() && &completeopt =~ 'longest' + let key = (b:complType == "\") ? "\" : "\" + endif + + " exception: if in mode, then should move up the list, and + " down the list. + if a:command == 'p' && + \ (b:complType == "\" || + \ (b:complType == 'context' && + \ tolower(g:SuperTabContextDefaultCompletionType) == '')) + return "\" + elseif a:command == 'p' && + \ (b:complType == "\" || + \ (b:complType == 'context' && + \ tolower(g:SuperTabContextDefaultCompletionType) == '')) + return "\" + endif + + " handle 'context' completion. + if b:complType == 'context' + let complType = s:ContextCompletion() + if complType == '' + exec "let complType = \"" . + \ escape(g:SuperTabContextDefaultCompletionType, '<') . "\"" + endif + return complType . key + endif + + " Hack to workaround bug when invoking command line completion via = + if b:complType == "\\" + return s:CommandLineCompletion() + endif + return b:complType . key + endif + + return "\" +endfunction " }}} + +" s:SuperTabHelp() {{{ +" Opens a help window where the user can choose a completion type to enter. +function! s:SuperTabHelp() + let winnr = winnr() + if bufwinnr("SuperTabHelp") == -1 + botright split SuperTabHelp + + setlocal noswapfile + setlocal buftype=nowrite + setlocal bufhidden=delete + + let saved = @" + let @" = s:tabHelp + silent put + call cursor(1, 1) + silent 1,delete + call cursor(4, 1) + let @" = saved + exec "resize " . line('$') + + syntax match Special "|.\{-}|" + + setlocal readonly + setlocal nomodifiable + + nmap :call SetCompletionType() + nmap :call SetCompletionType() + else + exec bufwinnr("SuperTabHelp") . "winc w" + endif + let b:winnr = winnr +endfunction " }}} + +" s:WillComplete() {{{ +" Determines if completion should be kicked off at the current location. +function! s:WillComplete() + let line = getline('.') + let cnum = col('.') + + " Start of line. + let prev_char = strpart(line, cnum - 2, 1) + if prev_char =~ '^\s*$' + return 0 + endif + + " Within a word, but user does not have mid word completion enabled. + let next_char = strpart(line, cnum - 1, 1) + if !g:SuperTabMidWordCompletion && next_char =~ '\k' + return 0 + endif + + " In keyword completion mode and no preceding word characters. + "if (b:complType == "\" || b:complType == "\") && prev_char !~ '\k' + " return 0 + "endif + + return 1 +endfunction " }}} + +" s:CommandLineCompletion() {{{ +" Hack needed to account for apparent bug in vim command line mode completion +" when invoked via = +function! s:CommandLineCompletion() + " This hack will trigger InsertLeave which will then invoke + " s:SetDefaultCompletionType. To prevent default completion from being + " restored prematurely, set an internal flag for s:SetDefaultCompletionType + " to check for. + let b:complCommandLine = 1 + return "\\:call feedkeys('\\\', 'n') | " . + \ "let b:complCommandLine = 0\" +endfunction " }}} + +" s:ContextCompletion() {{{ +function! s:ContextCompletion() + let contexts = exists('b:SuperTabCompletionContexts') ? + \ b:SuperTabCompletionContexts : g:SuperTabCompletionContexts + + for context in contexts + try + let Context = function(context) + let complType = Context() + unlet Context + if type(complType) == 1 && complType != '' + return complType + endif + catch /E700/ + echohl Error + echom 'supertab: no context function "' . context . '" found.' + echohl None + endtry + endfor + return '' +endfunction " }}} + +" s:ContextDiscover() {{{ +function! s:ContextDiscover() + let discovery = exists('g:SuperTabContextDiscoverDiscovery') ? + \ g:SuperTabContextDiscoverDiscovery : [] + + " loop through discovery list to find the default + if !empty(discovery) + for pair in discovery + let var = substitute(pair, '\(.*\):.*', '\1', '') + let type = substitute(pair, '.*:\(.*\)', '\1', '') + exec 'let value = ' . var + if value !~ '^\s*$' && value != '0' + exec "let complType = \"" . escape(type, '<') . "\"" + return complType + endif + endfor + endif +endfunction " }}} + +" s:ContextText() {{{ +function! s:ContextText() + let exclusions = exists('g:SuperTabContextTextFileTypeExclusions') ? + \ g:SuperTabContextTextFileTypeExclusions : [] + + if index(exclusions, &ft) == -1 + let curline = getline('.') + let cnum = col('.') + let synname = synIDattr(synID(line('.'), cnum - 1, 1), 'name') + if curline =~ '.*/\w*\%' . cnum . 'c' || + \ ((has('win32') || has('win64')) && curline =~ '.*\\\w*\%' . cnum . 'c') + return "\\" + + elseif curline =~ '.*\(\w\|[\])]\)\(\.\|::\|->\)\w*\%' . cnum . 'c' && + \ synname !~ '\(String\|Comment\)' + let omniPrecedence = exists('g:SuperTabContextTextOmniPrecedence') ? + \ g:SuperTabContextTextOmniPrecedence : ['&completefunc', '&omnifunc'] + + for omniFunc in omniPrecedence + if omniFunc !~ '^&' + let omniFunc = '&' . omniFunc + endif + if getbufvar(bufnr('%'), omniFunc) != '' + return omniFunc == '&omnifunc' ? "\\" : "\\" + endif + endfor + endif + endif +endfunction " }}} + +" Key Mappings {{{ + " map a regular tab to ctrl-tab (note: doesn't work in console vim) + exec 'inoremap ' . g:SuperTabMappingTabLiteral . ' ' + + imap =ManualCompletionEnter() + + " From the doc |insert.txt| improved + exec 'imap ' . g:SuperTabMappingForward . ' ' + exec 'imap ' . g:SuperTabMappingBackward . ' ' + + " After hitting , hitting it once more will go to next match + " (because in XIM mode and mappings are ignored) + " and wont start a brand new completion + " The side effect, that in the beginning of line and inserts a + " , but I hope it may not be a problem... + inoremap =SuperTab('n') + inoremap =SuperTab('p') +" }}} + +" Command Mappings {{{ + if !exists(":SuperTabHelp") + command SuperTabHelp :call SuperTabHelp() + endif +" }}} + +call s:Init() + +let &cpo = s:save_cpo + +" vim:ft=vim:fdm=marker diff --git a/.vim/bundle/vim-config-python-ide/syntax/python.vim b/.vim/bundle/vim-config-python-ide/syntax/python.vim new file mode 100644 index 0000000..04cf875 --- /dev/null +++ b/.vim/bundle/vim-config-python-ide/syntax/python.vim @@ -0,0 +1,358 @@ +" Vim syntax file +" Language: Python +" Maintainer: Dmitry Vasiliev +" URL: http://www.hlabs.spb.ru/vim/python.vim +" Last Change: 2009-07-24 +" Filenames: *.py +" Version: 2.6.5 +" +" Based on python.vim (from Vim 6.1 distribution) +" by Neil Schemenauer +" +" Thanks: +" +" Jeroen Ruigrok van der Werven +" for the idea to highlight erroneous operators +" Pedro Algarvio +" for the patch to enable spell checking only for the right spots +" (strings and comments) +" John Eikenberry +" for the patch fixing small typo +" Caleb Adamantine +" for the patch fixing highlighting for decorators + +" +" Options: +" +" For set option do: let OPTION_NAME = 1 +" For clear option do: let OPTION_NAME = 0 +" +" Option names: +" +" For highlight builtin functions: +" python_highlight_builtins +" +" For highlight standard exceptions: +" python_highlight_exceptions +" +" For highlight string formatting: +" python_highlight_string_formatting +" +" For highlight str.format syntax: +" python_highlight_string_format +" +" For highlight string.Template syntax: +" python_highlight_string_templates +" +" For highlight indentation errors: +" python_highlight_indent_errors +" +" For highlight trailing spaces: +" python_highlight_space_errors +" +" For highlight doc-tests: +" python_highlight_doctests +" +" If you want all Python highlightings above: +" python_highlight_all +" (This option not override previously set options) +" +" For fast machines: +" python_slow_sync +" +" For "print" builtin as function: +" python_print_as_function + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +if exists("python_highlight_all") && python_highlight_all != 0 + " Not override previously set options + if !exists("python_highlight_builtins") + let python_highlight_builtins = 1 + endif + if !exists("python_highlight_exceptions") + let python_highlight_exceptions = 1 + endif + if !exists("python_highlight_string_formatting") + let python_highlight_string_formatting = 1 + endif + if !exists("python_highlight_string_format") + let python_highlight_string_format = 1 + endif + if !exists("python_highlight_string_templates") + let python_highlight_string_templates = 1 + endif + if !exists("python_highlight_indent_errors") + let python_highlight_indent_errors = 1 + endif + if !exists("python_highlight_space_errors") + let python_highlight_space_errors = 1 + endif + if !exists("python_highlight_doctests") + let python_highlight_doctests = 1 + endif +endif + +" Keywords +syn keyword pythonStatement break continue del +syn keyword pythonStatement exec return +syn keyword pythonStatement pass raise +syn keyword pythonStatement global assert +syn keyword pythonStatement lambda yield +syn keyword pythonStatement with +syn keyword pythonStatement def class nextgroup=pythonFunction skipwhite +syn match pythonFunction "[a-zA-Z_][a-zA-Z0-9_]*" display contained +syn keyword pythonRepeat for while +syn keyword pythonConditional if elif else +syn keyword pythonPreCondit import from as +syn keyword pythonException try except finally +syn keyword pythonOperator and in is not or + +if !exists("python_print_as_function") || python_print_as_function == 0 + syn keyword pythonStatement print +endif + +" Decorators (new in Python 2.4) +syn match pythonDecorator "@" display nextgroup=pythonDottedName skipwhite +syn match pythonDottedName "[a-zA-Z_][a-zA-Z0-9_]*\(\.[a-zA-Z_][a-zA-Z0-9_]*\)*" display contained +syn match pythonDot "\." display containedin=pythonDottedName + +" Comments +syn match pythonComment "#.*$" display contains=pythonTodo,@Spell +syn match pythonRun "\%^#!.*$" +syn match pythonCoding "\%^.*\(\n.*\)\?#.*coding[:=]\s*[0-9A-Za-z-_.]\+.*$" +syn keyword pythonTodo TODO FIXME XXX contained + +" Errors +syn match pythonError "\<\d\+\D\+\>" display +syn match pythonError "[$?]" display +syn match pythonError "[&|]\{2,}" display +syn match pythonError "[=]\{3,}" display + +" TODO: Mixing spaces and tabs also may be used for pretty formatting multiline +" statements. For now I don't know how to work around this. +if exists("python_highlight_indent_errors") && python_highlight_indent_errors != 0 + syn match pythonIndentError "^\s*\( \t\|\t \)\s*\S"me=e-1 display +endif + +" Trailing space errors +if exists("python_highlight_space_errors") && python_highlight_space_errors != 0 + syn match pythonSpaceError "\s\+$" display +endif + +" Strings +syn region pythonString start=+[bB]\='+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell +syn region pythonString start=+[bB]\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonEscapeError,@Spell +syn region pythonString start=+[bB]\="""+ end=+"""+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonString start=+[bB]\='''+ end=+'''+ keepend contains=pythonEscape,pythonEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonEscape +\\[abfnrtv'"\\]+ display contained +syn match pythonEscape "\\\o\o\=\o\=" display contained +syn match pythonEscapeError "\\\o\{,2}[89]" display contained +syn match pythonEscape "\\x\x\{2}" display contained +syn match pythonEscapeError "\\x\x\=\X" display contained +syn match pythonEscape "\\$" + +" Unicode strings +syn region pythonUniString start=+[uU]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell +syn region pythonUniString start=+[uU]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,@Spell +syn region pythonUniString start=+[uU]"""+ end=+"""+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonUniString start=+[uU]'''+ end=+'''+ keepend contains=pythonEscape,pythonUniEscape,pythonEscapeError,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonUniEscape "\\u\x\{4}" display contained +syn match pythonUniEscapeError "\\u\x\{,3}\X" display contained +syn match pythonUniEscape "\\U\x\{8}" display contained +syn match pythonUniEscapeError "\\U\x\{,7}\X" display contained +syn match pythonUniEscape "\\N{[A-Z ]\+}" display contained +syn match pythonUniEscapeError "\\N{[^A-Z ]\+}" display contained + +" Raw strings +syn region pythonRawString start=+[rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,@Spell +syn region pythonRawString start=+[rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,@Spell +syn region pythonRawString start=+[rR]"""+ end=+"""+ keepend contains=pythonDocTest2,pythonSpaceError,@Spell +syn region pythonRawString start=+[rR]'''+ end=+'''+ keepend contains=pythonDocTest,pythonSpaceError,@Spell + +syn match pythonRawEscape +\\['"]+ display transparent contained + +" Unicode raw strings +syn region pythonUniRawString start=+[uU][rR]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell +syn region pythonUniRawString start=+[uU][rR]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonRawEscape,pythonUniRawEscape,pythonUniRawEscapeError,@Spell +syn region pythonUniRawString start=+[uU][rR]"""+ end=+"""+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest2,pythonSpaceError,@Spell +syn region pythonUniRawString start=+[uU][rR]'''+ end=+'''+ keepend contains=pythonUniRawEscape,pythonUniRawEscapeError,pythonDocTest,pythonSpaceError,@Spell + +syn match pythonUniRawEscape "\([^\\]\(\\\\\)*\)\@<=\\u\x\{4}" display contained +syn match pythonUniRawEscapeError "\([^\\]\(\\\\\)*\)\@<=\\u\x\{,3}\X" display contained + +if exists("python_highlight_string_formatting") && python_highlight_string_formatting != 0 + " String formatting + syn match pythonStrFormatting "%\(([^)]\+)\)\=[-#0 +]*\d*\(\.\d\+\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrFormatting "%[-#0 +]*\(\*\|\d\+\)\=\(\.\(\*\|\d\+\)\)\=[hlL]\=[diouxXeEfFgGcrs%]" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_string_format") && python_highlight_string_format != 0 + " str.format syntax + syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrFormat "{\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)\(\.[a-zA-Z_][a-zA-Z0-9_]*\|\[\(\d\+\|[^!:\}]\+\)\]\)*\(![rs]\)\=\(:\({\([a-zA-Z_][a-zA-Z0-9_]*\|\d\+\)}\|\([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*\(\.\d\+\)\=[bcdeEfFgGnoxX%]\=\)\=\)\=}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_string_templates") && python_highlight_string_templates != 0 + " String templates + syn match pythonStrTemplate "\$\$" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrTemplate "\${[a-zA-Z_][a-zA-Z0-9_]*}" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString + syn match pythonStrTemplate "\$[a-zA-Z_][a-zA-Z0-9_]*" contained containedin=pythonString,pythonUniString,pythonRawString,pythonUniRawString +endif + +if exists("python_highlight_doctests") && python_highlight_doctests != 0 + " DocTests + syn region pythonDocTest start="^\s*>>>" end=+'''+he=s-1 end="^\s*$" contained + syn region pythonDocTest2 start="^\s*>>>" end=+"""+he=s-1 end="^\s*$" contained +endif + +" Numbers (ints, longs, floats, complex) +syn match pythonHexError "\<0[xX]\x*[g-zG-Z]\x*[lL]\=\>" display + +syn match pythonHexNumber "\<0[xX]\x\+[lL]\=\>" display +syn match pythonOctNumber "\<0[oO]\o\+[lL]\=\>" display +syn match pythonBinNumber "\<0[bB][01]\+[lL]\=\>" display + +syn match pythonNumber "\<\d\+[lLjJ]\=\>" display + +syn match pythonFloat "\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" display +syn match pythonFloat "\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display +syn match pythonFloat "\<\d\+\.\d*\([eE][+-]\=\d\+\)\=[jJ]\=" display + +syn match pythonOctError "\<0[oO]\=\o*[8-9]\d*[lL]\=\>" display +syn match pythonBinError "\<0[bB][01]*[2-9]\d*[lL]\=\>" display + +if exists("python_highlight_builtins") && python_highlight_builtins != 0 + " Builtin functions, types and objects + syn keyword pythonBuiltinObj True False Ellipsis None NotImplemented + syn keyword pythonBuiltinObj __debug__ __doc__ __file__ __name__ __package__ + + syn keyword pythonBuiltinFunc __import__ abs all any apply + syn keyword pythonBuiltinFunc basestring bin bool buffer bytearray bytes callable + syn keyword pythonBuiltinFunc chr classmethod cmp coerce compile complex + syn keyword pythonBuiltinFunc delattr dict dir divmod enumerate eval + syn keyword pythonBuiltinFunc execfile file filter float format frozenset getattr + syn keyword pythonBuiltinFunc globals hasattr hash help hex id + syn keyword pythonBuiltinFunc input int intern isinstance + syn keyword pythonBuiltinFunc issubclass iter len list locals long map max + syn keyword pythonBuiltinFunc min next object oct open ord + syn keyword pythonBuiltinFunc pow property range + syn keyword pythonBuiltinFunc raw_input reduce reload repr + syn keyword pythonBuiltinFunc reversed round set setattr + syn keyword pythonBuiltinFunc slice sorted staticmethod str sum super tuple + syn keyword pythonBuiltinFunc type unichr unicode vars xrange zip + + if exists("python_print_as_function") && python_print_as_function != 0 + syn keyword pythonBuiltinFunc print + endif +endif + +if exists("python_highlight_exceptions") && python_highlight_exceptions != 0 + " Builtin exceptions and warnings + syn keyword pythonExClass BaseException + syn keyword pythonExClass Exception StandardError ArithmeticError + syn keyword pythonExClass LookupError EnvironmentError + + syn keyword pythonExClass AssertionError AttributeError BufferError EOFError + syn keyword pythonExClass FloatingPointError GeneratorExit IOError + syn keyword pythonExClass ImportError IndexError KeyError + syn keyword pythonExClass KeyboardInterrupt MemoryError NameError + syn keyword pythonExClass NotImplementedError OSError OverflowError + syn keyword pythonExClass ReferenceError RuntimeError StopIteration + syn keyword pythonExClass SyntaxError IndentationError TabError + syn keyword pythonExClass SystemError SystemExit TypeError + syn keyword pythonExClass UnboundLocalError UnicodeError + syn keyword pythonExClass UnicodeEncodeError UnicodeDecodeError + syn keyword pythonExClass UnicodeTranslateError ValueError VMSError + syn keyword pythonExClass WindowsError ZeroDivisionError + + syn keyword pythonExClass Warning UserWarning BytesWarning DeprecationWarning + syn keyword pythonExClass PendingDepricationWarning SyntaxWarning + syn keyword pythonExClass RuntimeWarning FutureWarning + syn keyword pythonExClass ImportWarning UnicodeWarning +endif + +if exists("python_slow_sync") && python_slow_sync != 0 + syn sync minlines=2000 +else + " This is fast but code inside triple quoted strings screws it up. It + " is impossible to fix because the only way to know if you are inside a + " triple quoted string is to start from the beginning of the file. + syn sync match pythonSync grouphere NONE "):$" + syn sync maxlines=200 +endif + +if version >= 508 || !exists("did_python_syn_inits") + if version <= 508 + let did_python_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + + HiLink pythonStatement Statement + HiLink pythonPreCondit Statement + HiLink pythonFunction Function + HiLink pythonConditional Conditional + HiLink pythonRepeat Repeat + HiLink pythonException Exception + HiLink pythonOperator Operator + + HiLink pythonDecorator Define + HiLink pythonDottedName Function + HiLink pythonDot Normal + + HiLink pythonComment Comment + HiLink pythonCoding Special + HiLink pythonRun Special + HiLink pythonTodo Todo + + HiLink pythonError Error + HiLink pythonIndentError Error + HiLink pythonSpaceError Error + + HiLink pythonString String + HiLink pythonUniString String + HiLink pythonRawString String + HiLink pythonUniRawString String + + HiLink pythonEscape Special + HiLink pythonEscapeError Error + HiLink pythonUniEscape Special + HiLink pythonUniEscapeError Error + HiLink pythonUniRawEscape Special + HiLink pythonUniRawEscapeError Error + + HiLink pythonStrFormatting Special + HiLink pythonStrFormat Special + HiLink pythonStrTemplate Special + + HiLink pythonDocTest Special + HiLink pythonDocTest2 Special + + HiLink pythonNumber Number + HiLink pythonHexNumber Number + HiLink pythonOctNumber Number + HiLink pythonBinNumber Number + HiLink pythonFloat Float + HiLink pythonOctError Error + HiLink pythonHexError Error + HiLink pythonBinError Error + + HiLink pythonBuiltinObj Structure + HiLink pythonBuiltinFunc Function + + HiLink pythonExClass Structure + + delcommand HiLink +endif + +let b:current_syntax = "python" diff --git a/.vim/bundle/vim-fugitive/.gitignore b/.vim/bundle/vim-fugitive/.gitignore new file mode 100644 index 0000000..0a56e3f --- /dev/null +++ b/.vim/bundle/vim-fugitive/.gitignore @@ -0,0 +1 @@ +/doc/tags diff --git a/.vim/bundle/vim-fugitive/README.markdown b/.vim/bundle/vim-fugitive/README.markdown new file mode 100644 index 0000000..0ae91a0 --- /dev/null +++ b/.vim/bundle/vim-fugitive/README.markdown @@ -0,0 +1,45 @@ +fugitive.vim +============ + +I'm not going to lie to you; fugitive.vim may very well be the best +Git wrapper of all time. Check out these features: + +View any blob, tree, commit, or tag in the repository with `:Gedit` (and +`:Gsplit`, `:Gvsplit`, `:Gtabedit`, ...). Edit a file in the index and +write to it to stage the changes. Use `:Gdiff` to bring up the staged +version of the file side by side with the working tree version and use +Vim's diff handling capabilities to stage a subset of the file's +changes. + +Bring up the output of `git status` with `:Gstatus`. Press `-` to +`add`/`reset` a file's changes, or `p` to `add`/`reset` `--patch` that +mofo. And guess what `:Gcommit` does! + +`:Gblame` brings up an interactive vertical split with `git blame` +output. Press enter on a line to reblame the file as it stood in that +commit, or `o` to open that commit in a split. + +`:Gmove` does a `git mv` on a file and simultaneously renames the +buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes +the buffer. + +Use `:Ggrep` to search the work tree (or any arbitrary commit) with +`git grep`, skipping over that which is not tracked in the repository. +`:Glog` loads all previous revisions of a file into the quickfix list so +you can iterate over them and watch the file evolve! + +`:Gread` is a variant of `git checkout -- filename` that operates on the +buffer rather than the filename. This means you can use `u` to undo it +and you never get any warnings about the file changing outside Vim. +`:Gwrite` writes to both the work tree and index versions of a file, +making it like `git add` when called from a work tree file and like +`git checkout` when called from the index or a blob in history. + +Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator +with the current branch in (surprise!) your statusline. + +Oh, and of course there's `:Git` for running any arbitrary command. + +Like fugitive.vim? Follow the repository on +[GitHub](http://github.com/tpope/vim-fugitive) and vote for it on +[vim.org](http://www.vim.org/scripts/script.php?script_id=2975). diff --git a/.vim/bundle/vim-fugitive/doc/fugitive.txt b/.vim/bundle/vim-fugitive/doc/fugitive.txt new file mode 100644 index 0000000..8ba2e8b --- /dev/null +++ b/.vim/bundle/vim-fugitive/doc/fugitive.txt @@ -0,0 +1,226 @@ +*fugitive.txt* A Git wrapper so awesome, it should be illegal + +Author: Tim Pope *fugitive-author* +License: Same terms as Vim itself (see |license|) + +This plugin is only available if 'compatible' is not set. + +INTRODUCTION *fugitive* + +Install in ~/.vim, or in ~\vimfiles if you're on Windows and feeling lucky. +Vim 7.2 is recommended as it ships with syntax highlighting for many Git file +types. + +If you're in a hurry to get started, here are some things to try: + +In any file in your repository, run |:Gedit| HEAD. Press to jump to the +current branch. Press again to jump to the top most commit. Keep using + to explore parent commits, trees, and blobs. Use C in a tree or blob to +get back to the commit. + +Edit a file in the work tree and make some changes. Use |:Gdiff| to open up +the indexed version. Use |do| and |dp| on various hunks to bring the files in +sync, or use |:Gread| to pull in all changes. Write the indexed version to +stage the file. + +Run |:Gstatus| to check your repository's status. Use "-" to stage and reset +files and "p" to add/reset --patch them. Invoke |:Gcommit| to commit your +changes. + +Run |:Gblame| in a work tree file to see a blame in a vertical split. Press + on any line to reopen and reblame that file as it stood in that commit. +Press o or O on any line to inspect that commit in a split or a tab. + +Run |:Ggrep| to search the work tree or history. Run |:Gmove| to rename a +file. Run |:Gremove| to delete a file. + +COMMANDS *fugitive-commands* + +These commands are local to the buffers in which they work (generally, buffers +that are part of Git repositories). + + *fugitive-:Git* +:Git [args] Run an arbitrary git command. Similar to :!git [args] + but chdir to the repository tree first. + + *fugitive-:Gcd* +:Gcd [directory] |:cd| relative to the repository. + + *fugitive-:Glcd* +:Glcd [directory] |:lcd| relative to the repository. + + *fugitive-:Gstatus* +:Gstatus Bring up the output of git-status in the preview + window. In addition to standard motions, you can + use and to jump from filename to + filename. Press D to |:Gdiff| the file on the cursor + line, or dh to |:Gdiff!|. Press - to stage or unstage + the file on the cursor line. Press p to do so on a + per hunk basis (--patch). Press C to invoke + |:Gcommit|. + + *fugitive-:Gcommit* +:Gcommit [args] A wrapper around git-commit. If there is nothing + to commit, |:Gstatus| is called instead. Unless the + arguments given would skip the invocation of an editor + (e.g., -m), a split window will be used to obtain a + commit message. Write and close that window (:wq or + |:Gwrite|) to finish the commit. Unlike when running + the actual git-commit command, it is possible (but + unadvisable) to muck with the index with commands like + git-add and git-reset while a commit message is + pending. + + *fugitive-:Ggrep* +:Ggrep [args] |:grep| with git-grep as 'grepprg'. + + *fugitive-:Glog* +:Glog [args] Load all previous revisions of the current file into + the quickfix list. Additional git-log arguments can + be given (for example, --reverse). If "--" appears as + an argument, no file specific filtering is done, and + commits are loaded into the quickfix list. + + *fugitive-:Gedit* *fugitive-:Ge* +:Gedit [revision] |:edit| a |fugitive-revision|. + + *fugitive-:Gsplit* +:Gsplit [revision] |:split| a |fugitive-revision|. + + *fugitive-:Gvsplit* +:Gvsplit [revision] |:vsplit| a |fugitive-revision|. + + *fugitive-:Gtabedit* +:Gtabedit [revision] |:tabedit| a |fugitive-revision| + + *fugitive-:Gpedit* +:Gpedit [revision] |:pedit| a |fugitive-revision| + + *fugitive-:Gread* +:Gread [revision] Empty the buffer and |:read| a |fugitive-revision|. + When the argument is omitted, this is similar to + git-checkout on a work tree file or git-add on a stage + file, but without writing anything to disk. + +:{range}Gread [revision] + |:read| in a |fugitive-revision| after {range}. + + *fugitive-:Gread!* +:Gread! [revision] Deprecated synonym for |:Gread|. + + *fugitive-:Gwrite* +:Gwrite Write to the current file's path and stage the results. + When run in a work tree file, it is effectively git + add. Elsewhere, it is effectively git-checkout. A + great deal of effort is expended to behave sensibly + when the work tree or index version of the file is + open in another buffer. + +:Gwrite {path} You can give |:Gwrite| an explicit path of where in + the work tree to write. You can also give a path like + :0:foo.txt or even :0 to write to just that stage in + the index. + + *fugitive-:Gdiff* +:Gdiff [revision] Perform a |vimdiff| against the current file in the + given revision. With no argument, the version in the + index is used (which means a three-way diff during a + merge conflict, making it a git-mergetool + alternative). The newer of the two files is placed + to the right. Use |do| and |dp| and write to the + index file to simulate "git add --patch". + + *fugitive-:Gdiff!* +:Gdiff! [revision] Like |:Gdiff|, but split horizontally. + + *fugitive-:Gmove* +:Gmove {destination} Wrapper around git-mv that renames the buffer + afterward. The destination is relative to the current + directory except when started with a /, in which case + it is relative to the work tree. Add a ! to pass -f. + + *fugitive-:Gremove* +:Gremove Wrapper around git-rm that deletes the buffer + afterward. When invoked in an index file, --cached is + passed. Add a ! to pass -f and forcefully discard the + buffer. + + *fugitive-:Gblame* +:Gblame [flags] Run git-blame on the file and open the results in a + scroll bound vertical split. Press enter on a line to + reblame the file as it was in that commit. You can + give any of ltwfsMC as flags and they will be passed + along to git-blame. + +:[range]Gblame [flags] Run git-blame on the given range. + +MAPPINGS *fugitive-mappings* + +These maps are available in Git objects. + + *fugitive-* + Jump to the revision under the cursor. + + *fugitive-o* +o Jump to the revision under the cursor in a new split. + + *fugitive-O* +O Jump to the revision under the cursor in a new tab. + + *fugitive-~* +~ Go to the current file in the [count]th first + ancestor. + + *fugitive-P* +P Go to the current file in the [count]th parent. + + *fugitive-C* +C Go to the commit containing the current file. + + *fugitive-a* +a Show the current tag, commit, or tree in an alternate + format. + +SPECIFYING REVISIONS *fugitive-revision* + +Fugitive revisions are similar to Git revisions as defined in the "SPECIFYING +REVISIONS" section in the git-rev-parse man page. For commands that accept an +optional revision, the default is the file in the index for work tree files +and the work tree file for everything else. Example revisions follow. + +Revision Meaning ~ +HEAD .git/HEAD +master .git/refs/heads/master +HEAD^{} The commit referenced by HEAD +HEAD^ The parent of the commit referenced by HEAD +HEAD: The tree referenced by HEAD +/HEAD The file named HEAD in the work tree +Makefile The file named Makefile in the work tree +HEAD^:Makefile The file named Makefile in the parent of HEAD +:Makefile The file named Makefile in the index (writable) +- The current file in HEAD +^ The current file in the previous commit +~3 The current file 3 commits ago +: .git/index (Same as |:Gstatus|) +:0 The current file in the index +:1 The current file's common ancestor during a conflict +:2 The current file in the target branch during a conflict +:3 The current file in the merged branch during a conflict +:/foo The most recent commit with "foo" in the message + +STATUSLINE *fugitive-statusline* + + *fugitive#statusline()* +Add %{fugitive#statusline()} to your statusline to get an indicator including +the current branch and the currently edited file's commit. If you don't have +a statusline, this one matches the default when 'ruler' is set: +> + set statusline=%<%f\ %h%m%r%{fugitive#statusline()}%=%-14.(%l,%c%V%)\ %P +< +ABOUT *fugitive-about* + +Grab the latest version or report a bug on GitHub: + +http://github.com/tpope/vim-fugitive + + vim:tw=78:et:ft=help:norl: diff --git a/.vim/bundle/vim-fugitive/plugin/fugitive.vim b/.vim/bundle/vim-fugitive/plugin/fugitive.vim new file mode 100644 index 0000000..310da52 --- /dev/null +++ b/.vim/bundle/vim-fugitive/plugin/fugitive.vim @@ -0,0 +1,1767 @@ +" fugitive.vim - A Git wrapper so awesome, it should be illegal +" Maintainer: Tim Pope +" Version: 1.1 +" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim + +if exists('g:loaded_fugitive') || &cp + finish +endif +let g:loaded_fugitive = 1 + +if !exists('g:fugitive_git_executable') + let g:fugitive_git_executable = 'git' +endif + +" Utility {{{1 + +function! s:function(name) abort + return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),'')) +endfunction + +function! s:sub(str,pat,rep) abort + return substitute(a:str,'\v\C'.a:pat,a:rep,'') +endfunction + +function! s:gsub(str,pat,rep) abort + return substitute(a:str,'\v\C'.a:pat,a:rep,'g') +endfunction + +function! s:shellesc(arg) abort + if a:arg =~ '^[A-Za-z0-9_/.-]\+$' + return a:arg + elseif &shell =~# 'cmd' && a:arg !~# '"' + return '"'.a:arg.'"' + else + return shellescape(a:arg) + endif +endfunction + +function! s:fnameescape(file) abort + if exists('*fnameescape') + return fnameescape(a:file) + else + return escape(a:file," \t\n*?[{`$\\%#'\"|!<") + endif +endfunction + +function! s:throw(string) abort + let v:errmsg = 'fugitive: '.a:string + throw v:errmsg +endfunction + +function! s:warn(str) + echohl WarningMsg + echomsg a:str + echohl None + let v:warningmsg = a:str +endfunction + +function! s:shellslash(path) + if exists('+shellslash') && !&shellslash + return s:gsub(a:path,'\\','/') + else + return a:path + endif +endfunction + +function! s:add_methods(namespace, method_names) abort + for name in a:method_names + let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name) + endfor +endfunction + +let s:commands = [] +function! s:command(definition) abort + let s:commands += [a:definition] +endfunction + +function! s:define_commands() + for command in s:commands + exe 'command! -buffer '.command + endfor +endfunction + +function! s:compatibility_check() + if exists('b:git_dir') && exists('*GitBranchInfoCheckGitDir') && !exists('g:fugitive_did_compatibility_warning') + let g:fugitive_did_compatibility_warning = 1 + call s:warn("See http://github.com/tpope/vim-fugitive/issues#issue/1 for why you should remove git-branch-info.vim") + endif +endfunction + +augroup fugitive_utility + autocmd! + autocmd User Fugitive call s:define_commands() + autocmd VimEnter * call s:compatibility_check() +augroup END + +let s:abstract_prototype = {} + +" }}}1 +" Initialization {{{1 + +function! s:ExtractGitDir(path) abort + let path = s:shellslash(a:path) + if path =~? '^fugitive://.*//' + return matchstr(path,'fugitive://\zs.\{-\}\ze//') + endif + let fn = fnamemodify(path,':s?[\/]$??') + let ofn = "" + let nfn = fn + while fn != ofn + if isdirectory(fn . '/.git') + return s:sub(simplify(fnamemodify(fn . '/.git',':p')),'\W$','') + elseif fn =~ '\.git$' && filereadable(fn . '/HEAD') + return s:sub(simplify(fnamemodify(fn,':p')),'\W$','') + endif + let ofn = fn + let fn = fnamemodify(ofn,':h') + endwhile + return '' +endfunction + +function! s:Detect(path) + if exists('b:git_dir') && b:git_dir ==# '' + unlet b:git_dir + endif + if !exists('b:git_dir') + let dir = s:ExtractGitDir(a:path) + if dir != '' + let b:git_dir = dir + endif + endif + if exists('b:git_dir') + silent doautocmd User Fugitive + cnoremap fugitive#buffer().rev() + let buffer = fugitive#buffer() + if expand('%:p') =~# '//' + call buffer.setvar('&path',s:sub(buffer.getvar('&path'),'^\.%(,|$)','')) + endif + if b:git_dir !~# ',' && stridx(buffer.getvar('&tags'),b:git_dir.'/tags') == -1 + call buffer.setvar('&tags',buffer.getvar('&tags').','.b:git_dir.'/tags') + endif + endif +endfunction + +augroup fugitive + autocmd! + autocmd BufNewFile,BufReadPost * call s:Detect(expand(':p')) + autocmd FileType netrw call s:Detect(expand(':p')) + autocmd VimEnter * if expand('')==''|call s:Detect(getcwd())|endif + autocmd BufWinLeave * execute getwinvar(+winnr(), 'fugitive_restore') +augroup END + +" }}}1 +" Repository {{{1 + +let s:repo_prototype = {} +let s:repos = {} + +function! s:repo(...) abort + let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : s:ExtractGitDir(expand('%:p'))) + if dir !=# '' + if has_key(s:repos,dir) + let repo = get(s:repos,dir) + else + let repo = {'git_dir': dir} + let s:repos[dir] = repo + endif + return extend(extend(repo,s:repo_prototype,'keep'),s:abstract_prototype,'keep') + endif + call s:throw('not a git repository: '.expand('%:p')) +endfunction + +function! s:repo_dir(...) dict abort + return join([self.git_dir]+a:000,'/') +endfunction + +function! s:repo_tree(...) dict abort + if !self.bare() + let dir = fnamemodify(self.git_dir,':h') + return join([dir]+a:000,'/') + endif + call s:throw('no work tree') +endfunction + +function! s:repo_bare() dict abort + return self.dir() !~# '/\.git$' +endfunction + +function! s:repo_translate(spec) dict abort + if a:spec ==# '.' || a:spec ==# '/.' + return self.bare() ? self.dir() : self.tree() + elseif a:spec =~# '^/' + return fnamemodify(self.dir(),':h').a:spec + elseif a:spec =~# '^:[0-3]:' + return 'fugitive://'.self.dir().'//'.a:spec[1].'/'.a:spec[3:-1] + elseif a:spec ==# ':' + if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(s:repo().dir())] ==# s:repo().dir('') && filereadable($GIT_INDEX_FILE) + return fnamemodify($GIT_INDEX_FILE,':p') + else + return self.dir('index') + endif + elseif a:spec =~# '^:/' + let ref = self.rev_parse(matchstr(a:spec,'.[^:]*')) + return 'fugitive://'.self.dir().'//'.ref + elseif a:spec =~# '^:' + return 'fugitive://'.self.dir().'//0/'.a:spec[1:-1] + elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(self.dir(a:spec)) + return self.dir(a:spec) + elseif filereadable(s:repo().dir('refs/'.a:spec)) + return self.dir('refs/'.a:spec) + elseif filereadable(s:repo().dir('refs/tags/'.a:spec)) + return self.dir('refs/tags/'.a:spec) + elseif filereadable(s:repo().dir('refs/heads/'.a:spec)) + return self.dir('refs/heads/'.a:spec) + elseif filereadable(s:repo().dir('refs/remotes/'.a:spec)) + return self.dir('refs/remotes/'.a:spec) + elseif filereadable(s:repo().dir('refs/remotes/'.a:spec.'/HEAD')) + return self.dir('refs/remotes/'.a:spec,'/HEAD') + else + try + let ref = self.rev_parse(matchstr(a:spec,'[^:]*')) + let path = s:sub(matchstr(a:spec,':.*'),'^:','/') + return 'fugitive://'.self.dir().'//'.ref.path + catch /^fugitive:/ + return self.tree(a:spec) + endtry + endif +endfunction + +call s:add_methods('repo',['dir','tree','bare','translate']) + +function! s:repo_git_command(...) dict abort + let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) + return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'') +endfunction + +function! s:repo_git_chomp(...) dict abort + return s:sub(system(call(self.git_command,a:000,self)),'\n$','') +endfunction + +function! s:repo_git_chomp_in_tree(...) dict abort + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd.'`=s:repo().tree()`' + return call(s:repo().git_chomp, a:000, s:repo()) + finally + execute cd.'`=dir`' + endtry +endfunction + +function! s:repo_rev_parse(rev) dict abort + let hash = self.git_chomp('rev-parse','--verify',a:rev) + if hash =~ '^\x\{40\}$' + return hash + endif + call s:throw('rev-parse '.a:rev.': '.hash) +endfunction + +call s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse']) + +function! s:repo_dirglob(base) dict abort + let base = s:sub(a:base,'^/','') + let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*/')),"\n") + call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]') + return matches +endfunction + +function! s:repo_superglob(base) dict abort + if a:base =~# '^/' || a:base !~# ':' + let results = [] + if a:base !~# '^/' + let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"] + let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n")) + call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base') + let results += heads + endif + if !self.bare() + let base = s:sub(a:base,'^/','') + let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*')),"\n") + call map(matches,'s:shellslash(v:val)') + call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val') + call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]') + let results += matches + endif + return results + + elseif a:base =~# '^:' + let entries = split(self.git_chomp('ls-files','--stage'),"\n") + call map(entries,'s:sub(v:val,".*(\\d)\\t(.*)",":\\1:\\2")') + if a:base !~# '^:[0-3]\%(:\|$\)' + call filter(entries,'v:val[1] == "0"') + call map(entries,'v:val[2:-1]') + endif + call filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base') + return entries + + else + let tree = matchstr(a:base,'.*[:/]') + let entries = split(self.git_chomp('ls-tree',tree),"\n") + call map(entries,'s:sub(v:val,"^04.*\\zs$","/")') + call map(entries,'tree.s:sub(v:val,".*\t","")') + return filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base') + endif +endfunction + +call s:add_methods('repo',['dirglob','superglob']) + +function! s:repo_keywordprg() dict abort + let args = ' --git-dir='.escape(self.dir(),"\\\"' ").' show' + if has('gui_running') && !has('win32') + return g:fugitive_git_executable . ' --no-pager' . args + else + return g:fugitive_git_executable . args + endif +endfunction + +call s:add_methods('repo',['keywordprg']) + +" }}}1 +" Buffer {{{1 + +let s:buffer_prototype = {} + +function! s:buffer(...) abort + let buffer = {'#': bufnr(a:0 ? a:1 : '%')} + call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep') + if buffer.getvar('git_dir') !=# '' + return buffer + endif + call s:throw('not a git repository: '.expand('%:p')) +endfunction + +function! fugitive#buffer(...) abort + return s:buffer(a:0 ? a:1 : '%') +endfunction + +function! s:buffer_getvar(var) dict abort + return getbufvar(self['#'],a:var) +endfunction + +function! s:buffer_setvar(var,value) dict abort + return setbufvar(self['#'],a:var,a:value) +endfunction + +function! s:buffer_getline(lnum) dict abort + return getbufline(self['#'],a:lnum)[0] +endfunction + +function! s:buffer_repo() dict abort + return s:repo(self.getvar('git_dir')) +endfunction + +function! s:buffer_type(...) dict abort + if self.getvar('fugitive_type') != '' + let type = self.getvar('fugitive_type') + elseif fnamemodify(self.spec(),':p') =~# '.\git/refs/\|\.git/\w*HEAD$' + let type = 'head' + elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == '' + let type = 'tree' + elseif self.getline(1) =~ '^\d\{6\} \w\{4\} \x\{40\}\>\t' + let type = 'tree' + elseif self.getline(1) =~ '^\d\{6\} \x\{40\}\> \d\t' + let type = 'index' + elseif isdirectory(self.spec()) + let type = 'directory' + elseif self.spec() == '' + let type = 'null' + elseif filereadable(self.spec()) + let type = 'file' + else + let type = '' + endif + if a:0 + return !empty(filter(copy(a:000),'v:val ==# type')) + else + return type + endif +endfunction + +function! s:buffer_spec() dict abort + let bufname = bufname(self['#']) + return s:shellslash(bufname == '' ? '' : fnamemodify(bufname,':p')) +endfunction + +function! s:buffer_name() dict abort + return self.spec() +endfunction + +function! s:buffer_commit() dict abort + return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*') +endfunction + +function! s:buffer_path(...) dict abort + let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*') + if rev != '' + let rev = s:sub(rev,'\w*','') + else + let rev = self.spec()[strlen(self.repo().tree()) : -1] + endif + return s:sub(rev,'^/',a:0 ? a:1 : '') +endfunction + +function! s:buffer_rev() dict abort + let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*') + if rev =~ '^\x/' + return ':'.rev[0].':'.rev[2:-1] + elseif rev =~ '.' + return s:sub(rev,'/',':') + elseif self.spec() =~ '\.git/index$' + return ':' + elseif self.spec() =~ '\.git/refs/\|\.git/.*HEAD$' + return self.spec()[strlen(self.repo().dir())+1 : -1] + else + return self.path() + endif +endfunction + +function! s:buffer_sha1() dict abort + if self.spec() =~ '^fugitive://' || self.spec() =~ '\.git/refs/\|\.git/.*HEAD$' + return self.repo().rev_parse(self.rev()) + else + return '' + endif +endfunction + +function! s:buffer_expand(rev) dict abort + if a:rev =~# '^:[0-3]$' + let file = a:rev.self.path(':') + elseif a:rev =~# '^-' + let file = 'HEAD^{}'.a:rev[1:-1].self.path(':') + elseif a:rev =~# '^@{' + let file = 'HEAD'.a:rev.self.path(':') + elseif a:rev =~# '^[~^]' + let commit = s:sub(self.commit(),'^\d=$','HEAD') + let file = commit.a:rev.self.path(':') + else + let file = a:rev + endif + return s:sub(file,'\%$',self.path()) +endfunction + +function! s:buffer_containing_commit() dict abort + if self.commit() =~# '^\d$' + return ':' + elseif self.commit() =~# '.' + return self.commit() + else + return 'HEAD' + endif +endfunction + +call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','name','commit','path','rev','sha1','expand','containing_commit']) + +" }}}1 +" Git {{{1 + +call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(0,)") + +function! s:ExecuteInTree(cmd) abort + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd.'`=s:repo().tree()`' + execute a:cmd + finally + execute cd.'`=dir`' + endtry +endfunction + +function! s:Git(bang,cmd) abort + let git = s:repo().git_command() + if has('gui_running') && !has('win32') + let git .= ' --no-pager' + endif + let cmd = matchstr(a:cmd,'\v\C.{-}%($|\\@ `=s:repo().bare() ? s:repo().dir() : s:repo().tree()`") +call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd `=s:repo().bare() ? s:repo().dir() : s:repo().tree()`") + +" }}}1 +" Gstatus {{{1 + +call s:command("-bar Gstatus :execute s:Status()") + +function! s:Status() abort + try + Gpedit : + wincmd P + nnoremap q :bdelete + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry + return '' +endfunction + +function! fugitive#reload_status() abort + let mytab = tabpagenr() + for tab in [mytab] + range(1,tabpagenr('$')) + for winnr in range(1,tabpagewinnr(tab,'$')) + if getbufvar(tabpagebuflist(tab)[winnr-1],'fugitive_type') ==# 'index' + execute 'tabnext '.tab + if winnr != winnr() + execute winnr.'wincmd w' + let restorewinnr = 1 + endif + try + if !&modified + call s:BufReadIndex() + endif + finally + if exists('restorewinnr') + wincmd p + endif + execute 'tabnext '.mytab + endtry + endif + endfor + endfor +endfunction + +function! s:StageDiff(bang) abort + let section = getline(search('^# .*:$','bnW')) + let line = getline('.') + let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*') + if filename ==# '' && section == '# Changes to be committed:' + return 'Git diff --cached' + elseif filename ==# '' + return 'Git diff' + elseif line =~# '^#\trenamed:' && filename =~ ' -> ' + let [old, new] = split(filename,' -> ') + execute 'Gedit '.s:fnameescape(':0:'.new) + return 'Gdiff'.a:bang.' HEAD:'.s:fnameescape(old) + elseif section == '# Changes to be committed:' + execute 'Gedit '.s:fnameescape(':0:'.filename) + return 'Gdiff'.a:bang.' -' + else + execute 'Gedit '.s:fnameescape('/'.filename) + return 'Gdiff'.a:bang + endif +endfunction + +function! s:StageToggle(lnum1,lnum2) abort + try + let output = '' + for lnum in range(a:lnum1,a:lnum2) + let line = getline(lnum) + if getline('.') == '# Changes to be committed:' + return 'Gcommit' + endif + let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*') + if filename ==# '' + continue + endif + if !exists('first_filename') + let first_filename = filename + endif + execute lnum + let section = getline(search('^# .*:$','bnW')) + if line =~# '^#\trenamed:' && filename =~ ' -> ' + let cmd = ['mv','--'] + reverse(split(filename,' -> ')) + let filename = cmd[-1] + elseif section =~? ' to be ' + let cmd = ['reset','-q','--',filename] + elseif line =~# '^#\tdeleted:' + let cmd = ['rm','--',filename] + else + let cmd = ['add','--',filename] + endif + let output .= call(s:repo().git_chomp_in_tree,cmd,s:repo())."\n" + endfor + if exists('first_filename') + let jump = first_filename + let f = matchstr(getline(a:lnum1-1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*') + if f !=# '' | let jump = f | endif + let f = matchstr(getline(a:lnum2+1),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*') + if f !=# '' | let jump = f | endif + silent! edit! + 1 + redraw + call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.jump.'\$','W') + endif + echo s:sub(s:gsub(output,'\n+','\n'),'\n$','') + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry + return 'checktime' +endfunction + +function! s:StagePatch(lnum1,lnum2) abort + let add = [] + let reset = [] + + for lnum in range(a:lnum1,a:lnum2) + let line = getline(lnum) + if line == '# Changes to be committed:' + return 'Git reset --patch' + elseif line == '# Changed but not updated:' + return 'Git add --patch' + endif + let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*') + if filename ==# '' + continue + endif + if !exists('first_filename') + let first_filename = filename + endif + execute lnum + let section = getline(search('^# .*:$','bnW')) + if line =~# '^#\trenamed:' && filename =~ ' -> ' + let reset += [split(filename,' -> ')[1]] + elseif section =~? ' to be ' + let reset += [filename] + elseif line !~# '^#\tdeleted:' + let add += [filename] + endif + endfor + try + if !empty(add) + execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)')) + endif + if !empty(reset) + execute "Git reset --patch -- ".join(map(add,'s:shellesc(v:val)')) + endif + if exists('first_filename') + silent! edit! + 1 + redraw + call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.first_filename.'\$','W') + endif + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry + return 'checktime' +endfunction + +" }}}1 +" Gcommit {{{1 + +call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute s:Commit()") + +function! s:Commit(args) abort + let old_type = s:buffer().type() + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + let msgfile = s:repo().dir('COMMIT_EDITMSG') + let outfile = tempname() + let errorfile = tempname() + try + execute cd.'`=s:repo().tree()`' + let command = '' + if &shell =~# 'cmd' + let old_editor = $GIT_EDITOR + let $GIT_EDITOR = 'false' + elseif &shell !~# 'csh' + let command = 'GIT_EDITOR=false ' + endif + let command .= s:repo().git_command('commit').' '.a:args + if &shell =~# 'csh' + silent execute '!setenv GIT_EDITOR false; ('.command.' > '.outfile.') >& '.errorfile + elseif a:args =~# '\%(^\| \)--interactive\>' + execute '!'.command.' 2> '.errorfile + else + silent execute '!'.command.' > '.outfile.' 2> '.errorfile + endif + if !v:shell_error + if filereadable(outfile) + for line in readfile(outfile) + echo line + endfor + endif + return '' + else + let errors = readfile(errorfile) + let error = get(errors,-2,get(errors,-1,'!')) + if error =~# "'false'\\.$" + let args = a:args + let args = s:gsub(args,'%(%(^| )-- )@' + let args = '--cleanup=strip '.args + endif + if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod + edit `=msgfile` + else + split `=msgfile` + endif + if old_type ==# 'index' + bdelete # + endif + let b:fugitive_commit_arguments = args + setlocal bufhidden=delete filetype=gitcommit + return '1' + elseif error ==# '!' + return s:Status() + else + call s:throw(error) + endif + endif + catch /^fugitive:/ + return 'echoerr v:errmsg' + finally + if exists('old_editor') + let $GIT_EDITOR = old_editor + endif + call delete(outfile) + call delete(errorfile) + execute cd.'`=dir`' + call fugitive#reload_status() + endtry +endfunction + +function! s:CommitComplete(A,L,P) abort + if a:A =~ '^-' || type(a:A) == type(0) " a:A is 0 on :Gcommit - + let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--template=', '--untracked-files', '--verbose'] + return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A') + else + return s:repo().superglob(a:A) + endif +endfunction + +function! s:FinishCommit() + let args = getbufvar(+expand(''),'fugitive_commit_arguments') + if !empty(args) + call setbufvar(+expand(''),'fugitive_commit_arguments','') + return s:Commit(args) + endif + return '' +endfunction + +augroup fugitive_commit + autocmd! + autocmd VimLeavePre,BufDelete *.git/COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE') +augroup END + +" }}}1 +" Ggrep, Glog {{{1 + +if !exists('g:fugitive_summary_format') + let g:fugitive_summary_format = '%s' +endif + +call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep(0,)") +call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Glog :execute s:Log('grep',)") + +function! s:Grep(bang,arg) abort + let grepprg = &grepprg + let grepformat = &grepformat + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd.'`=s:repo().tree()`' + let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n') + let &grepformat = '%f:%l:%m' + exe 'grep! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|') + let list = getqflist() + for entry in list + if bufname(entry.bufnr) =~ ':' + let entry.filename = s:repo().translate(bufname(entry.bufnr)) + unlet! entry.bufnr + elseif a:arg =~# '\%(^\| \)--cached\>' + let entry.filename = s:repo().translate(':0:'.bufname(entry.bufnr)) + unlet! entry.bufnr + endif + endfor + call setqflist(list,'r') + if !a:bang && !empty(list) + return 'cfirst'.matchstr(a:arg,'\v\C[''" ]\zs\|.*') + else + return matchstr(a:arg,'\v\C[''" ]\|\zs.*') + endif + finally + let &grepprg = grepprg + let &grepformat = grepformat + execute cd.'`=dir`' + endtry +endfunction + +function! s:Log(cmd,...) + let path = s:buffer().path('/') + if path =~# '^/\.git\%(/\|$\)' || index(a:000,'--') != -1 + let path = '' + endif + let cmd = ['--no-pager', 'log', '--no-color'] + let cmd += [escape('--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.'::'.g:fugitive_summary_format,'%')] + if empty(filter(a:000[0 : index(a:000,'--')],'v:val !~# "^-"')) + if s:buffer().commit() =~# '\x\{40\}' + let cmd += [s:buffer().commit()] + elseif s:buffer().path() =~# '^\.git/refs/\|^\.git/.*HEAD$' + let cmd += [s:buffer().path()[5:-1]] + endif + end + let cmd += map(copy(a:000),'s:sub(v:val,"^\\%(%(:\\w)*)","\\=fnamemodify(s:buffer().path(),submatch(1))")') + if path =~# '/.' + let cmd += ['--',path[1:-1]] + endif + let grepformat = &grepformat + let grepprg = &grepprg + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd.'`=s:repo().tree()`' + let &grepprg = call(s:repo().git_command,cmd,s:repo()) + let &grepformat = '%f::%m' + exe a:cmd + finally + let &grepformat = grepformat + let &grepprg = grepprg + execute cd.'`=dir`' + endtry +endfunction + +" }}}1 +" Gedit, Gpedit, Gsplit, Gvsplit, Gtabedit, Gread {{{1 + +function! s:Edit(cmd,...) abort + if a:0 && a:1 == '' + return '' + elseif a:0 + let file = s:buffer().expand(a:1) + elseif s:buffer().commit() ==# '' && s:buffer().path('/') !~# '^/.git\>' + let file = s:buffer().path(':') + else + let file = s:buffer().path('/') + endif + try + let file = s:repo().translate(file) + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry + if a:cmd =~# 'read!$' || a:cmd ==# 'read' + if a:cmd =~# '!$' + call s:warn(':Gread! is deprecated. Use :Gread') + endif + return 'silent %delete|read '.s:fnameescape(file).'|silent 1delete_|diffupdate|'.line('.') + else + if &previewwindow && getbufvar('','fugitive_type') ==# 'index' + wincmd p + endif + return a:cmd.' '.s:fnameescape(file) + endif +endfunction + +function! s:EditComplete(A,L,P) abort + return s:repo().superglob(a:A) +endfunction + +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Ge :execute s:Edit('edit',)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gedit :execute s:Edit('edit',)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gpedit :execute s:Edit('pedit',)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gsplit :execute s:Edit('split',)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gvsplit :execute s:Edit('vsplit',)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gtabedit :execute s:Edit('tabedit',)") +call s:command("-bar -bang -nargs=? -count -complete=customlist,s:EditComplete Gread :execute s:Edit((! && ? '' : ).'read',)") + +" }}}1 +" Gwrite {{{1 + +call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwrite :execute s:Write(0,)") + +function! s:Write(force,...) abort + if exists('b:fugitive_commit_arguments') + return 'write|bdelete' + elseif expand('%:t') == 'COMMIT_EDITMSG' && $GIT_INDEX_FILE != '' + return 'wq' + elseif s:buffer().type() == 'index' + return 'Gcommit' + endif + let mytab = tabpagenr() + let mybufnr = bufnr('') + let path = a:0 ? a:1 : s:buffer().path() + if path =~# '^:\d\>' + return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path))) + endif + let always_permitted = (s:buffer().path() ==# path && s:buffer().commit() =~# '^0\=$') + if !always_permitted && !a:force && s:repo().git_chomp_in_tree('diff','--name-status','HEAD','--',path) . s:repo().git_chomp_in_tree('ls-files','--others','--',path) !=# '' + let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)' + return 'echoerr v:errmsg' + endif + let file = s:repo().translate(path) + let treebufnr = 0 + for nr in range(1,bufnr('$')) + if fnamemodify(bufname(nr),':p') ==# file + let treebufnr = nr + endif + endfor + + if treebufnr > 0 && treebufnr != bufnr('') + let temp = tempname() + silent execute '%write '.temp + for tab in [mytab] + range(1,tabpagenr('$')) + for winnr in range(1,tabpagewinnr(tab,'$')) + if tabpagebuflist(tab)[winnr-1] == treebufnr + execute 'tabnext '.tab + if winnr != winnr() + execute winnr.'wincmd w' + let restorewinnr = 1 + endif + try + let lnum = line('.') + let last = line('$') + silent execute '$read '.temp + silent execute '1,'.last.'delete_' + silent write! + silent execute lnum + let did = 1 + finally + if exists('restorewinnr') + wincmd p + endif + execute 'tabnext '.mytab + endtry + endif + endfor + endfor + if !exists('did') + call writefile(readfile(temp,'b'),file,'b') + endif + else + execute 'write! '.s:fnameescape(s:repo().translate(path)) + endif + + if a:force + let error = s:repo().git_chomp_in_tree('add', '--force', file) + else + let error = s:repo().git_chomp_in_tree('add', file) + endif + if v:shell_error + let v:errmsg = 'fugitive: '.error + return 'echoerr v:errmsg' + endif + if s:buffer().path() ==# path && s:buffer().commit() =~# '^\d$' + set nomodified + endif + + let one = s:repo().translate(':1:'.path) + let two = s:repo().translate(':2:'.path) + let three = s:repo().translate(':3:'.path) + for nr in range(1,bufnr('$')) + if bufloaded(nr) && !getbufvar(nr,'&modified') && (bufname(nr) == one || bufname(nr) == two || bufname(nr) == three) + execute nr.'bdelete' + endif + endfor + + unlet! restorewinnr + let zero = s:repo().translate(':0:'.path) + for tab in range(1,tabpagenr('$')) + for winnr in range(1,tabpagewinnr(tab,'$')) + let bufnr = tabpagebuflist(tab)[winnr-1] + let bufname = bufname(bufnr) + if bufname ==# zero && bufnr != mybufnr + execute 'tabnext '.tab + if winnr != winnr() + execute winnr.'wincmd w' + let restorewinnr = 1 + endif + try + let lnum = line('.') + let last = line('$') + silent $read `=file` + silent execute '1,'.last.'delete_' + silent execute lnum + set nomodified + diffupdate + finally + if exists('restorewinnr') + wincmd p + endif + execute 'tabnext '.mytab + endtry + break + endif + endfor + endfor + call fugitive#reload_status() + return 'checktime' +endfunction + +" }}}1 +" Gdiff {{{1 + +call s:command("-bang -bar -nargs=? -complete=customlist,s:EditComplete Gdiff :execute s:Diff(0,)") +call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gvdiff :execute s:Diff(0,)") +call s:command("-bar -nargs=? -complete=customlist,s:EditComplete Gsdiff :execute s:Diff(1,)") + +augroup fugitive_diff + autocmd! + autocmd BufWinLeave * if s:diff_window_count() == 2 && &diff && getbufvar(+expand(''), 'git_dir') !=# '' | execute 'windo call s:diff_off()' | endif + autocmd BufWinEnter * if s:diff_window_count() == 1 && &diff && getbufvar(+expand(''), 'git_dir') !=# '' | call s:diff_off() | endif +augroup END + +function! s:diff_window_count() + let c = 0 + for nr in range(1,winnr('$')) + let c += getwinvar(nr,'&diff') + endfor + return c +endfunction + +function! s:diff_off() + if &l:diff + diffoff + endif +endfunction + +function! s:buffer_compare_age(commit) dict abort + let scores = {':0': 1, ':1': 2, ':2': 3, ':': 4, ':3': 5} + let my_score = get(scores,':'.self.commit(),0) + let their_score = get(scores,':'.a:commit,0) + if my_score || their_score + return my_score < their_score ? -1 : my_score != their_score + elseif self.commit() ==# a:commit + return 0 + endif + let base = self.repo().git_chomp('merge-base',self.commit(),a:commit) + if base ==# self.commit() + return -1 + elseif base ==# a:commit + return 1 + endif + let my_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',self.commit()) + let their_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',a:commit) + return my_time < their_time ? -1 : my_time != their_time +endfunction + +call s:add_methods('buffer',['compare_age']) + +function! s:Diff(bang,...) abort + let split = a:bang ? 'split' : 'vsplit' + if exists(':DiffGitCached') + return 'DiffGitCached' + elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# '' + execute 'leftabove '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`' + diffthis + wincmd p + execute 'rightbelow '.split.' `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`' + diffthis + wincmd p + diffthis + return '' + elseif a:0 + if a:1 ==# '' + return '' + elseif a:1 ==# '/' + let file = s:buffer().path('/') + elseif a:1 ==# ':' + let file = s:buffer().path(':0:') + elseif a:1 =~# '^:/' + try + let file = s:repo().rev_parse(a:1).s:buffer().path(':') + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry + else + let file = s:buffer().expand(a:1) + endif + if file !~# ':' && file !~# '^/' && s:repo().git_chomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$' + let file = file.s:buffer().path(':') + endif + else + let file = s:buffer().path(s:buffer().commit() == '' ? ':0:' : '/') + endif + try + let spec = s:repo().translate(file) + let commit = matchstr(spec,'\C[^:/]//\zs\x\+') + if s:buffer().compare_age(commit) < 0 + execute 'rightbelow '.split.' `=spec`' + else + execute 'leftabove '.split.' `=spec`' + endif + diffthis + wincmd p + diffthis + return '' + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +" }}}1 +" Gmove, Gremove {{{1 + +function! s:Move(force,destination) + if a:destination =~# '^/' + let destination = a:destination[1:-1] + else + let destination = fnamemodify(s:sub(a:destination,'[%#]%(:\w)*','\=expand(submatch(0))'),':p') + if destination[0:strlen(s:repo().tree())] ==# s:repo().tree('') + let destination = destination[strlen(s:repo().tree('')):-1] + endif + endif + let message = call(s:repo().git_chomp_in_tree,['mv']+(a:force ? ['-f'] : [])+['--', s:buffer().path(), destination], s:repo()) + if v:shell_error + let v:errmsg = 'fugitive: '.message + return 'echoerr v:errmsg' + endif + let destination = s:repo().tree(destination) + if isdirectory(destination) + let destination = fnamemodify(s:sub(destination,'/$','').'/'.expand('%:t'),':.') + endif + call fugitive#reload_status() + if s:buffer().commit() == '' + return 'saveas! '.s:fnameescape(destination) + else + return 'file '.s:fnameescape(s:repo().translate(':0:'.destination) + endif +endfunction + +function! s:MoveComplete(A,L,P) + if a:A =~ '^/' + return s:repo().superglob(a:A) + else + let matches = split(glob(a:A.'*'),"\n") + call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val') + return matches + endif +endfunction + +function! s:Remove(force) + if s:buffer().commit() ==# '' + let cmd = ['rm'] + elseif s:buffer().commit() ==# '0' + let cmd = ['rm','--cached'] + else + let v:errmsg = 'fugitive: rm not supported here' + return 'echoerr v:errmsg' + endif + if a:force + let cmd += ['--force'] + endif + let message = call(s:repo().git_chomp_in_tree,cmd+['--',s:buffer().path()],s:repo()) + if v:shell_error + let v:errmsg = 'fugitive: '.s:sub(message,'error:.*\zs\n\(.*-f.*',' (add ! to force)') + return 'echoerr '.string(v:errmsg) + else + call fugitive#reload_status() + return 'bdelete'.(a:force ? '!' : '') + endif +endfunction + +augroup fugitive_remove + autocmd! + autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' | + \ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(0,)" | + \ exe "command! -buffer -bar -bang Gremove :execute s:Remove(0)" | + \ endif +augroup END + +" }}}1 +" Gblame {{{1 + +augroup fugitive_blame + autocmd! + autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame + autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif + autocmd Syntax fugitiveblame call s:BlameSyntax() + autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(0,,,,[])" | endif +augroup END + +function! s:Blame(bang,line1,line2,count,args) abort + try + if s:buffer().path() == '' + call s:throw('file or blob required') + endif + if filter(copy(a:args),'v:val !~# "^\\%(--root\|--show-name\\|-\\=\\%([ltwfs]\\|[MC]\\d*\\)\\+\\)$"') != [] + call s:throw('unsupported option') + endif + call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")') + let git_dir = s:repo().dir() + let cmd = ['--no-pager', 'blame', '--show-number'] + a:args + if s:buffer().commit() =~# '\D\|..' + let cmd += [s:buffer().commit()] + else + let cmd += ['--contents', '-'] + endif + let basecmd = call(s:repo().git_command,cmd+['--',s:buffer().path()],s:repo()) + try + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + if !s:repo().bare() + let dir = getcwd() + execute cd.'`=s:repo().tree()`' + endif + if a:count + execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') + else + let error = tempname() + let temp = error.'.fugitiveblame' + if &shell =~# 'csh' + silent! execute '%write !('.basecmd.' > '.temp.') >& '.error + else + silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error + endif + if exists('l:dir') + execute cd.'`=dir`' + unlet dir + endif + if v:shell_error + call s:throw(join(readfile(error),"\n")) + endif + let bufnr = bufnr('') + let restore = 'call setwinvar(bufwinnr('.bufnr.'),"&scrollbind",0)' + if &l:wrap + let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&wrap",1)' + endif + if &l:foldenable + let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&foldenable",1)' + endif + let winnr = winnr() + windo set noscrollbind + exe winnr.'wincmd w' + setlocal scrollbind nowrap nofoldenable + let top = line('w0') + &scrolloff + let current = line('.') + exe 'leftabove vsplit '.temp + let b:git_dir = git_dir + let b:fugitive_type = 'blame' + let b:fugitive_blamed_bufnr = bufnr + let w:fugitive_restore = restore + let b:fugitive_blame_arguments = join(a:args,' ') + call s:Detect(expand('%:p')) + execute top + normal! zt + execute current + execute "vertical resize ".(match(getline('.'),'\s\+\d\+)')+1) + setlocal nomodified nomodifiable bufhidden=delete nonumber scrollbind nowrap foldcolumn=0 nofoldenable filetype=fugitiveblame + nnoremap q :bdelete + nnoremap :exe BlameJump('') + nnoremap P :exe BlameJump('^'.v:count1) + nnoremap ~ :exe BlameJump('~'.v:count1) + nnoremap o :exe Edit((&splitbelow ? "botright" : "topleft")." split", matchstr(getline('.'),'\x\+')) + nnoremap O :exe Edit("tabedit", matchstr(getline('.'),'\x\+')) + syncbind + endif + finally + if exists('l:dir') + execute cd.'`=dir`' + endif + endtry + return '' + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +function! s:BlameJump(suffix) abort + let commit = matchstr(getline('.'),'^\^\=\zs\x\+') + if commit =~# '^0\+$' + let commit = ':0' + endif + let lnum = matchstr(getline('.'),'\d\+\ze\s\+[([:digit:]]') + let path = matchstr(getline('.'),'^\^\=\zs\x\+\s\+\zs.\{-\}\ze\s*\d\+ ') + if path ==# '' + let path = s:buffer(b:fugitive_blamed_bufnr).path() + endif + let args = b:fugitive_blame_arguments + let offset = line('.') - line('w0') + let bufnr = bufnr('%') + let winnr = bufwinnr(b:fugitive_blamed_bufnr) + if winnr > 0 + exe winnr.'wincmd w' + endif + execute s:Edit('edit',commit.a:suffix.':'.path) + if winnr > 0 + exe bufnr.'bdelete' + endif + execute 'Gblame '.args + execute lnum + let delta = line('.') - line('w0') - offset + if delta > 0 + execute 'norm! 'delta."\" + elseif delta < 0 + execute 'norm! '(-delta)."\" + endif + syncbind + return '' +endfunction + +function! s:BlameSyntax() abort + let b:current_syntax = 'fugitiveblame' + syn match FugitiveblameBoundary "^\^" + syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite + syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite + syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite + syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline + syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation + syn match FugitiveblameLineNumber " \@<=\d\+)\@=" contained containedin=FugitiveblameAnnotation + syn match FugitiveblameOriginalFile " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\=\s\%((\|\s*\d\+)\)\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite + syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s(\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite + syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s\+\d\+)\)\@=" contained nextgroup=FugitiveblameShort skipwhite + syn match FugitiveblameShort "\d\+)" contained contains=FugitiveblameLineNumber + syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation + hi def link FugitiveblameBoundary Keyword + hi def link FugitiveblameHash Identifier + hi def link FugitiveblameUncommitted Function + hi def link FugitiveblameTime PreProc + hi def link FugitiveblameLineNumber Number + hi def link FugitiveblameOriginalFile String + hi def link FugitiveblameOriginalLineNumber Float + hi def link FugitiveblameShort FugitiveblameDelimiter + hi def link FugitiveblameDelimiter Delimiter + hi def link FugitiveblameNotCommittedYet Comment +endfunction + +" }}}1 +" File access {{{1 + +function! s:ReplaceCmd(cmd,...) abort + let fn = bufname('') + let tmp = tempname() + let aw = &autowrite + let prefix = '' + try + if a:0 && a:1 != '' + if &shell =~# 'cmd' + let old_index = $GIT_INDEX_FILE + let $GIT_INDEX_FILE = a:1 + elseif &shell =~# 'csh' + let prefix = 'setenv GIT_INDEX_FILE '.s:shellesc(a:1).'; ' + else + let prefix = 'GIT_INDEX_FILE='.s:shellesc(a:1).' ' + endif + endif + set noautowrite + silent exe '!'.escape(prefix.a:cmd,'%#').' > '.tmp + finally + let &autowrite = aw + if exists('old_index') + let $GIT_INDEX_FILE = old_index + endif + endtry + silent exe 'keepalt file '.tmp + silent edit! + silent exe 'keepalt file '.s:fnameescape(fn) + call delete(tmp) + silent exe 'doau BufReadPost '.s:fnameescape(fn) +endfunction + +function! s:BufReadIndex() + if !exists('b:fugitive_display_format') + let b:fugitive_display_format = filereadable(expand('%').'.lock') + endif + let b:fugitive_display_format = b:fugitive_display_format % 2 + let b:fugitive_type = 'index' + try + let b:git_dir = s:repo().dir() + setlocal noro ma + if fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : b:git_dir . '/index', ':p') ==# expand('%:p') + let index = '' + else + let index = expand('%:p') + endif + if b:fugitive_display_format + call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index) + set ft=git nospell + else + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + execute cd.'`=s:repo().tree()`' + call s:ReplaceCmd(s:repo().git_command('status'),index) + finally + execute cd.'`=dir`' + endtry + set ft=gitcommit + endif + setlocal ro noma nomod nomodeline bufhidden=delete + nnoremap a :let b:fugitive_display_format += 1exe BufReadIndex() + nnoremap i :let b:fugitive_display_format -= 1exe BufReadIndex() + nnoremap D :execute StageDiff('') + nnoremap dd :execute StageDiff('') + nnoremap dh :execute StageDiff('!') + nnoremap - :execute StageToggle(line('.'),line('.')+v:count1-1) + xnoremap - :execute StageToggle(line("'<"),line("'>")) + nnoremap p :execute StagePatch(line('.'),line('.')+v:count1-1) + xnoremap p :execute StagePatch(line("'<"),line("'>")) + nnoremap :call search('^#\t.*','W'). + nnoremap :call search('^#\t.*','Wbe'). + call s:JumpInit() + nunmap P + nunmap ~ + nnoremap C :Gcommit + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +function! s:FileRead() + try + let repo = s:repo(s:ExtractGitDir(expand(''))) + let path = s:sub(s:sub(matchstr(expand(''),'fugitive://.\{-\}//\zs.*'),'/',':'),'^\d:',':&') + let hash = repo.rev_parse(path) + if path =~ '^:' + let type = 'blob' + else + let type = repo.git_chomp('cat-file','-t',hash) + endif + " TODO: use count, if possible + return "read !".escape(repo.git_command('cat-file',type,hash),'%#\') + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +function! s:BufReadIndexFile() + try + let b:fugitive_type = 'blob' + let b:git_dir = s:repo().dir() + call s:ReplaceCmd(s:repo().git_command('cat-file','blob',s:buffer().sha1())) + return '' + catch /^fugitive: rev-parse/ + silent exe 'doau BufNewFile '.s:fnameescape(bufname('')) + return '' + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +function! s:BufWriteIndexFile() + let tmp = tempname() + try + let path = matchstr(expand(''),'//\d/\zs.*') + let stage = matchstr(expand(''),'//\zs\d') + silent execute 'write !'.s:repo().git_command('hash-object','-w','--stdin').' > '.tmp + let sha1 = readfile(tmp)[0] + let old_mode = matchstr(s:repo().git_chomp('ls-files','--stage',path),'^\d\+') + if old_mode == '' + let old_mode = executable(s:repo().tree(path)) ? '100755' : '100644' + endif + let info = old_mode.' '.sha1.' '.stage."\t".path + call writefile([info],tmp) + if has('win32') + let error = system('type '.tmp.'|'.s:repo().git_command('update-index','--index-info')) + else + let error = system(s:repo().git_command('update-index','--index-info').' < '.tmp) + endif + if v:shell_error == 0 + setlocal nomodified + silent execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p')) + call fugitive#reload_status() + return '' + else + return 'echoerr '.string('fugitive: '.error) + endif + finally + call delete(tmp) + endtry +endfunction + +function! s:BufReadObject() + try + setlocal noro ma + let b:git_dir = s:repo().dir() + let hash = s:buffer().sha1() + if !exists("b:fugitive_type") + let b:fugitive_type = s:repo().git_chomp('cat-file','-t',hash) + endif + if b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$' + return "echoerr 'fugitive: unrecognized git type'" + endif + let firstline = getline('.') + if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob' + let b:fugitive_display_format = +getbufvar('#','fugitive_display_format') + endif + + let pos = getpos('.') + silent %delete + setlocal endofline + + if b:fugitive_type == 'tree' + let b:fugitive_display_format = b:fugitive_display_format % 2 + if b:fugitive_display_format + call s:ReplaceCmd(s:repo().git_command('ls-tree',hash)) + else + call s:ReplaceCmd(s:repo().git_command('show',hash)) + endif + elseif b:fugitive_type == 'tag' + let b:fugitive_display_format = b:fugitive_display_format % 2 + if b:fugitive_display_format + call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash)) + else + call s:ReplaceCmd(s:repo().git_command('cat-file','-p',hash)) + endif + elseif b:fugitive_type == 'commit' + let b:fugitive_display_format = b:fugitive_display_format % 2 + if b:fugitive_display_format + call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash)) + else + call s:ReplaceCmd(s:repo().git_command('show','--pretty=format:tree %T%nparent %P%nauthor %an <%ae> %ad%ncommitter %cn <%ce> %cd%nencoding %e%n%n%s%n%n%b',hash)) + call search('^parent ') + if getline('.') ==# 'parent ' + silent delete_ + else + silent s/\%(^parent\)\@\)\=$','W',line('.')+3) + silent delete_ + end + 1 + endif + elseif b:fugitive_type ==# 'blob' + call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash)) + endif + call setpos('.',pos) + setlocal ro noma nomod nomodeline + if b:fugitive_type !=# 'blob' + set filetype=git + nnoremap a :let b:fugitive_display_format += v:count1exe BufReadObject() + nnoremap i :let b:fugitive_display_format -= v:count1exe BufReadObject() + else + call s:JumpInit() + endif + + return '' + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +augroup fugitive_files + autocmd! + autocmd BufReadCmd *.git/index exe s:BufReadIndex() + autocmd BufReadCmd *.git/*index*.lock exe s:BufReadIndex() + autocmd FileReadCmd fugitive://**//[0-3]/** exe s:FileRead() + autocmd BufReadCmd fugitive://**//[0-3]/** exe s:BufReadIndexFile() + autocmd BufWriteCmd fugitive://**//[0-3]/** exe s:BufWriteIndexFile() + autocmd BufReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:BufReadObject() + autocmd FileReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:FileRead() + autocmd FileType git call s:JumpInit() +augroup END + +" }}}1 +" Go to file {{{1 + +function! s:JumpInit() abort + nnoremap :exe GF("edit") + if !&modifiable + nnoremap o :exe GF("split") + nnoremap O :exe GF("tabedit") + nnoremap P :exe Edit('edit',buffer().commit().'^'.v:count1.buffer().path(':')) + nnoremap ~ :exe Edit('edit',buffer().commit().'~'.v:count1.buffer().path(':')) + nnoremap C :exe Edit('edit',buffer().containing_commit()) + nnoremap cc :exe Edit('edit',buffer().containing_commit()) + nnoremap co :exe Edit('split',buffer().containing_commit()) + nnoremap cO :exe Edit('tabedit',buffer().containing_commit()) + nnoremap cp :exe Edit('pedit',buffer().containing_commit()) + endif +endfunction + +function! s:GF(mode) abort + try + let buffer = s:buffer() + let myhash = buffer.sha1() + + if buffer.type('tree') + let showtree = (getline(1) =~# '^tree ' && getline(2) == "") + if showtree && line('.') == 1 + return "" + elseif showtree && line('.') > 2 + return s:Edit(a:mode,buffer.commit().':'.(buffer.path() == '' ? '' : buffer.path().'/').s:sub(getline('.'),'/$','')) + elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t' + return s:Edit(a:mode,buffer.commit().':'.(buffer.path() == '' ? '' : buffer.path().'/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$','')) + endif + + elseif buffer.type('blob') + let ref = expand("") + try + let sha1 = buffer.repo().rev_parse(ref) + catch /^fugitive:/ + endtry + if exists('sha1') + return s:Edit(a:mode,ref) + endif + + else + + " Index + if getline('.') =~# '^\d\{6\} \x\{40\} \d\t' + let ref = matchstr(getline('.'),'\x\{40\}') + let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':') + return s:Edit(a:mode,file) + + elseif getline('.') =~# '^#\trenamed:.* -> ' + let file = '/'.matchstr(getline('.'),' -> \zs.*') + return s:Edit(a:mode,file) + elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.' + let file = '/'.matchstr(getline('.'),': *\zs.*') + return s:Edit(a:mode,file) + elseif getline('.') =~# '^#\t.' + let file = '/'.matchstr(getline('.'),'#\t\zs.*') + return s:Edit(a:mode,file) + elseif getline('.') =~# ': needs merge$' + let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$') + return s:Edit(a:mode,file).'|Gdiff' + + elseif getline('.') ==# '# Not currently on any branch.' + return s:Edit(a:mode,'HEAD') + elseif getline('.') =~# '^# On branch ' + let file = 'refs/heads/'.getline('.')[12:] + return s:Edit(a:mode,file) + elseif getline('.') =~# "^# Your branch .*'" + let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'") + return s:Edit(a:mode,file) + endif + + let showtree = (getline(1) =~# '^tree ' && getline(2) == "") + + if getline('.') =~# '^ref: ' + let ref = strpart(getline('.'),5) + + elseif getline('.') =~# '^parent \x\{40\}\>' + let ref = matchstr(getline('.'),'\x\{40\}') + let line = line('.') + let parent = 0 + while getline(line) =~# '^parent ' + let parent += 1 + let line -= 1 + endwhile + return s:Edit(a:mode,ref) + + elseif getline('.') =~ '^tree \x\{40\}$' + let ref = matchstr(getline('.'),'\x\{40\}') + if s:repo().rev_parse(myhash.':') == ref + let ref = myhash.':' + endif + return s:Edit(a:mode,ref) + + elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$' + let ref = matchstr(getline('.'),'\x\{40\}') + let type = matchstr(getline(line('.')+1),'type \zs.*') + + elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$' + return '' + + elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>' + let ref = matchstr(getline('.'),'\x\{40\}') + echoerr "warning: unknown context ".matchstr(getline('.'),'^\l*') + + elseif getline('.') =~# '^[+-]\{3\} [ab/]' + let ref = getline('.')[4:] + + elseif getline('.') =~# '^rename from ' + let ref = 'a/'.getline('.')[12:] + elseif getline('.') =~# '^rename to ' + let ref = 'b/'.getline('.')[10:] + + elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' + let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') + let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') + let dcmd = 'Gdiff' + + elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' + let line = getline(line('.')-1) + let dref = matchstr(line,'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') + let ref = matchstr(line,'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') + let dcmd = 'Gdiff!' + + elseif line('$') == 1 && getline('.') =~ '^\x\{40\}$' + let ref = getline('.') + else + let ref = '' + endif + + if myhash ==# '' + let ref = s:sub(ref,'^a/','HEAD:') + let ref = s:sub(ref,'^b/',':0:') + if exists('dref') + let dref = s:sub(dref,'^a/','HEAD:') + endif + else + let ref = s:sub(ref,'^a/',myhash.'^:') + let ref = s:sub(ref,'^b/',myhash.':') + if exists('dref') + let dref = s:sub(dref,'^a/',myhash.'^:') + endif + endif + + if ref ==# '/dev/null' + " Empty blob + let ref = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391' + endif + + if exists('dref') + return s:Edit(a:mode,ref) . '|'.dcmd.' '.s:fnameescape(dref) + elseif ref != "" + return s:Edit(a:mode,ref) + endif + + endif + return '' + catch /^fugitive:/ + return 'echoerr v:errmsg' + endtry +endfunction + +" }}}1 +" Statusline {{{1 + +function! s:repo_head_ref() dict abort + return readfile(s:repo().dir('HEAD'))[0] +endfunction + +call s:add_methods('repo',['head_ref']) + +function! fugitive#statusline(...) + if !exists('b:git_dir') + return '' + endif + let status = '' + if s:buffer().commit() != '' + let status .= ':' . s:buffer().commit()[0:7] + endif + let head = s:repo().head_ref() + if head =~# '^ref: ' + let status .= s:sub(head,'^ref: %(refs/%(heads/|remotes/|tags/)=)=','(').')' + elseif head =~# '^\x\{40\}$' + let status .= '('.head[0:7].')' + endif + if &statusline =~# '%[MRHWY]' && &statusline !~# '%[mrhwy]' + return ',GIT'.status + else + return '[Git'.status.']' + endif +endfunction + +function! s:repo_config(conf) dict abort + return matchstr(system(s:repo().git_command('config').' '.a:conf),"[^\r\n]*") +endfun + +function! s:repo_user() dict abort + let username = s:repo().config('user.name') + let useremail = s:repo().config('user.email') + return username.' <'.useremail.'>' +endfun + +call s:add_methods('repo',['config', 'user']) + +" }}}1 + +" vim:set ft=vim ts=8 sw=2 sts=2: diff --git a/.vim/bundle/vim-pathogen/autoload/pathogen.vim b/.vim/bundle/vim-pathogen/autoload/pathogen.vim new file mode 100644 index 0000000..6f0a4e3 --- /dev/null +++ b/.vim/bundle/vim-pathogen/autoload/pathogen.vim @@ -0,0 +1,142 @@ +" pathogen.vim - path option manipulation +" Maintainer: Tim Pope +" Version: 1.2 + +" Install in ~/.vim/autoload (or ~\vimfiles\autoload). +" +" API is documented below. + +if exists("g:loaded_pathogen") || &cp + finish +endif +let g:loaded_pathogen = 1 + +" Split a path into a list. +function! pathogen#split(path) abort " {{{1 + if type(a:path) == type([]) | return a:path | endif + let split = split(a:path,'\\\@p` opens the current project directory with the PeepOpen application. + +Use the [vim-rooter](http://github.com/airblade/vim-rooter) plugin for automatic assignment of the current working directory for projects stored in Git. + +(Leader is mapped to '\' by default) + +Credits +------- + +- Initial Vim Plugin by [Andrew Stewart](http://www.airbladesoftware.com/). +- Some plugin boilerplate from [Rein Henrichs](http://reinh.com/). + diff --git a/.vim/bundle/vim-peepopen/plugin/peepopen.vim b/.vim/bundle/vim-peepopen/plugin/peepopen.vim new file mode 100644 index 0000000..882f2a4 --- /dev/null +++ b/.vim/bundle/vim-peepopen/plugin/peepopen.vim @@ -0,0 +1,46 @@ +" plugin/peepopen.vim +" Author: Geoffrey Grosenbach +" License: MIT License + +" Install this file as plugin/peepopen.vim. + +" If you prefer Command-T, use this snippet in your .gvimrc: + +" if has("gui_macvim") +" macmenu &File.New\ Tab key= +" map PeepOpen +" end + +" ============================================================================ + +" Exit quickly when: +" - this plugin was already loaded (or disabled) +" - when 'compatible' is set +if &cp || exists("g:peepopen_loaded") && g:peepopen_loaded + finish +endif +let g:peepopen_loaded = 1 + +let s:save_cpo = &cpo +set cpo&vim + +function s:LaunchPeepOpenViaVim() + let cwd = getcwd() + silent exe "!open -a PeepOpen " . shellescape(cwd) +endfunction + +command! PeepOpen :call LaunchPeepOpenViaVim() + +noremap