From a82ce15c2419c45bb164836d0cf30c85461c2d03 Mon Sep 17 00:00:00 2001 From: Buddy Sandidge Date: Thu, 7 May 2015 13:39:11 -0700 Subject: [PATCH] Update Dockerfile to have user with some configs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Use demo user inside the container • Add .bashrc and .vimrc/.vim config files --- Dockerfile | 43 +- config/home/bashrc | 114 ++ config/home/vim/autoload/pathogen.vim | 347 ++++ config/home/vim/bundle/nerdtree/.gitignore | 3 + .../home/vim/bundle/nerdtree/README.markdown | 103 ++ .../vim/bundle/nerdtree/autoload/nerdtree.vim | 136 ++ .../nerdtree/autoload/nerdtree/ui_glue.vim | 644 ++++++++ .../vim/bundle/nerdtree/doc/NERD_tree.txt | 1399 +++++++++++++++++ .../bundle/nerdtree/lib/nerdtree/bookmark.vim | 319 ++++ .../bundle/nerdtree/lib/nerdtree/creator.vim | 362 +++++ .../bundle/nerdtree/lib/nerdtree/event.vim | 13 + .../bundle/nerdtree/lib/nerdtree/flag_set.vim | 56 + .../bundle/nerdtree/lib/nerdtree/key_map.vim | 159 ++ .../nerdtree/lib/nerdtree/menu_controller.vim | 180 +++ .../nerdtree/lib/nerdtree/menu_item.vim | 114 ++ .../bundle/nerdtree/lib/nerdtree/nerdtree.vim | 137 ++ .../bundle/nerdtree/lib/nerdtree/notifier.vim | 35 + .../bundle/nerdtree/lib/nerdtree/opener.vim | 352 +++++ .../vim/bundle/nerdtree/lib/nerdtree/path.vim | 761 +++++++++ .../nerdtree/lib/nerdtree/tree_dir_node.vim | 543 +++++++ .../nerdtree/lib/nerdtree/tree_file_node.vim | 431 +++++ .../vim/bundle/nerdtree/lib/nerdtree/ui.vim | 506 ++++++ .../nerdtree_plugin/exec_menuitem.vim | 41 + .../nerdtree/nerdtree_plugin/fs_menu.vim | 270 ++++ .../vim/bundle/nerdtree/plugin/NERD_tree.vim | 210 +++ .../vim/bundle/nerdtree/syntax/nerdtree.vim | 105 ++ config/home/vim/bundle/syntastic/.gitignore | 4 + .../home/vim/bundle/syntastic/CONTRIBUTING.md | 105 ++ config/home/vim/bundle/syntastic/LICENCE | 13 + .../home/vim/bundle/syntastic/README.markdown | 462 ++++++ .../bundle/syntastic/_assets/screenshot_1.png | Bin 0 -> 92425 bytes .../bundle/syntastic/autoload/syntastic/c.vim | 345 ++++ .../syntastic/autoload/syntastic/log.vim | 182 +++ .../autoload/syntastic/postprocess.vim | 73 + .../autoload/syntastic/preprocess.vim | 316 ++++ .../syntastic/autoload/syntastic/util.vim | 414 +++++ .../vim/bundle/syntastic/doc/syntastic.txt | 956 +++++++++++ .../vim/bundle/syntastic/plugin/syntastic.vim | 672 ++++++++ .../plugin/syntastic/autoloclist.vim | 38 + .../syntastic/plugin/syntastic/balloons.vim | 59 + .../syntastic/plugin/syntastic/checker.vim | 228 +++ .../syntastic/plugin/syntastic/cursor.vim | 138 ++ .../plugin/syntastic/highlighting.vim | 104 ++ .../syntastic/plugin/syntastic/loclist.vim | 434 +++++ .../syntastic/plugin/syntastic/modemap.vim | 117 ++ .../syntastic/plugin/syntastic/notifiers.vim | 86 + .../syntastic/plugin/syntastic/registry.vim | 333 ++++ .../syntastic/plugin/syntastic/signs.vim | 138 ++ .../syntax_checkers/actionscript/mxmlc.vim | 67 + .../syntastic/syntax_checkers/ada/gcc.vim | 47 + .../apiblueprint/snowcrash.vim | 66 + .../applescript/osacompile.vim | 49 + .../syntax_checkers/asciidoc/asciidoc.vim | 47 + .../syntastic/syntax_checkers/asm/gcc.vim | 58 + .../syntax_checkers/bemhtml/bemhtmllint.vim | 35 + .../syntastic/syntax_checkers/bro/bro.vim | 60 + .../syntastic/syntax_checkers/c/avrgcc.vim | 57 + .../syntax_checkers/c/checkpatch.vim | 60 + .../syntax_checkers/c/clang_check.vim | 61 + .../syntax_checkers/c/clang_tidy.vim | 61 + .../syntastic/syntax_checkers/c/cppcheck.vim | 62 + .../syntastic/syntax_checkers/c/gcc.vim | 59 + .../syntastic/syntax_checkers/c/make.vim | 61 + .../syntastic/syntax_checkers/c/oclint.vim | 65 + .../syntastic/syntax_checkers/c/pc_lint.vim | 66 + .../syntastic/syntax_checkers/c/sparse.vim | 48 + .../syntastic/syntax_checkers/c/splint.vim | 55 + .../syntastic/syntax_checkers/cabal/cabal.vim | 55 + .../syntax_checkers/chef/foodcritic.vim | 39 + .../syntastic/syntax_checkers/co/coco.vim | 47 + .../syntastic/syntax_checkers/cobol/cobc.vim | 47 + .../syntax_checkers/coffee/coffee.vim | 58 + .../syntax_checkers/coffee/coffeelint.vim | 47 + .../syntastic/syntax_checkers/coq/coqtop.vim | 40 + .../syntax_checkers/cpp/clang_check.vim | 25 + .../syntax_checkers/cpp/clang_tidy.vim | 25 + .../syntax_checkers/cpp/cppcheck.vim | 24 + .../syntastic/syntax_checkers/cpp/cpplint.vim | 52 + .../syntastic/syntax_checkers/cpp/gcc.vim | 56 + .../syntastic/syntax_checkers/cpp/oclint.vim | 24 + .../syntastic/syntax_checkers/cpp/pc_lint.vim | 26 + .../syntastic/syntax_checkers/cs/mcs.vim | 39 + .../syntastic/syntax_checkers/css/csslint.vim | 47 + .../syntastic/syntax_checkers/css/phpcs.vim | 25 + .../syntax_checkers/css/prettycss.vim | 61 + .../syntastic/syntax_checkers/css/recess.vim | 26 + .../syntax_checkers/cucumber/cucumber.vim | 42 + .../syntastic/syntax_checkers/cuda/nvcc.vim | 66 + .../syntastic/syntax_checkers/d/dmd.vim | 60 + .../syntax_checkers/dart/dartanalyzer.vim | 76 + .../syntastic/syntax_checkers/docbk/igor.vim | 55 + .../syntax_checkers/docbk/xmllint.vim | 25 + .../syntax_checkers/dustjs/swiffer.vim | 38 + .../syntax_checkers/elixir/elixir.vim | 61 + .../erlang/erlang_check_file.erl | 76 + .../syntax_checkers/erlang/escript.vim | 61 + .../syntax_checkers/erlang/syntaxerl.vim | 42 + .../syntastic/syntax_checkers/eruby/ruby.vim | 82 + .../syntax_checkers/fortran/gfortran.vim | 99 ++ .../syntastic/syntax_checkers/glsl/cgc.vim | 81 + .../syntastic/syntax_checkers/go/go.vim | 96 ++ .../syntastic/syntax_checkers/go/gofmt.vim | 45 + .../syntastic/syntax_checkers/go/golint.vim | 42 + .../syntastic/syntax_checkers/go/gotype.vim | 46 + .../syntastic/syntax_checkers/go/govet.vim | 52 + .../syntastic/syntax_checkers/haml/haml.vim | 46 + .../syntax_checkers/haml/haml_lint.vim | 37 + .../syntax_checkers/handlebars/handlebars.vim | 43 + .../syntax_checkers/haskell/ghc-mod.vim | 83 + .../syntax_checkers/haskell/hdevtools.vim | 56 + .../syntax_checkers/haskell/hlint.vim | 39 + .../syntax_checkers/haskell/scan.vim | 43 + .../syntastic/syntax_checkers/haxe/haxe.vim | 63 + .../syntastic/syntax_checkers/hss/hss.vim | 38 + .../syntastic/syntax_checkers/html/jshint.vim | 50 + .../syntastic/syntax_checkers/html/tidy.vim | 212 +++ .../syntax_checkers/html/validator.vim | 69 + .../syntastic/syntax_checkers/html/w3.vim | 62 + .../syntax_checkers/java/checkstyle.vim | 77 + .../syntastic/syntax_checkers/java/javac.vim | 420 +++++ .../javascript/closurecompiler.vim | 76 + .../syntax_checkers/javascript/eslint.vim | 60 + .../syntax_checkers/javascript/flow.vim | 60 + .../syntax_checkers/javascript/gjslint.vim | 45 + .../syntax_checkers/javascript/jscs.vim | 44 + .../syntax_checkers/javascript/jshint.vim | 60 + .../syntax_checkers/javascript/jsl.vim | 48 + .../syntax_checkers/javascript/jslint.vim | 51 + .../syntax_checkers/javascript/jsxhint.vim | 51 + .../syntax_checkers/javascript/standard.vim | 47 + .../syntax_checkers/json/jsonlint.vim | 43 + .../syntax_checkers/json/jsonval.vim | 41 + .../syntax_checkers/less/less-lint.coffee | 41 + .../syntax_checkers/less/less-lint.js | 57 + .../syntastic/syntax_checkers/less/lessc.vim | 66 + .../syntastic/syntax_checkers/less/recess.vim | 44 + .../syntastic/syntax_checkers/lex/flex.vim | 50 + .../syntastic/syntax_checkers/limbo/limbo.vim | 46 + .../syntastic/syntax_checkers/lisp/clisp.vim | 57 + .../syntastic/syntax_checkers/llvm/llvm.vim | 39 + .../syntastic/syntax_checkers/lua/luac.vim | 65 + .../syntax_checkers/lua/luacheck.vim | 67 + .../syntax_checkers/markdown/mdl.vim | 45 + .../syntax_checkers/matlab/mlint.vim | 41 + .../syntastic/syntax_checkers/mercury/mmc.vim | 49 + .../syntastic/syntax_checkers/nasm/nasm.vim | 41 + .../syntastic/syntax_checkers/nroff/igor.vim | 25 + .../syntax_checkers/nroff/mandoc.vim | 41 + .../syntastic/syntax_checkers/objc/gcc.vim | 59 + .../syntastic/syntax_checkers/objc/oclint.vim | 24 + .../syntastic/syntax_checkers/objcpp/gcc.vim | 59 + .../syntax_checkers/objcpp/oclint.vim | 24 + .../syntax_checkers/ocaml/camlp4o.vim | 140 ++ .../syntastic/syntax_checkers/perl/perl.vim | 99 ++ .../syntax_checkers/perl/perlcritic.vim | 52 + .../syntax_checkers/perl/podchecker.vim | 25 + .../syntastic/syntax_checkers/php/php.vim | 52 + .../syntastic/syntax_checkers/php/phpcs.vim | 41 + .../syntastic/syntax_checkers/php/phplint.vim | 91 ++ .../syntastic/syntax_checkers/php/phpmd.vim | 77 + .../syntastic/syntax_checkers/po/msgfmt.vim | 50 + .../syntax_checkers/pod/podchecker.vim | 51 + .../syntax_checkers/puppet/puppet.vim | 47 + .../syntax_checkers/puppet/puppetlint.vim | 52 + .../syntastic/syntax_checkers/python/codec.py | 31 + .../syntax_checkers/python/compile.py | 13 + .../syntax_checkers/python/flake8.vim | 72 + .../syntax_checkers/python/frosted.vim | 63 + .../syntastic/syntax_checkers/python/mypy.vim | 35 + .../syntax_checkers/python/pep257.vim | 59 + .../syntastic/syntax_checkers/python/pep8.vim | 48 + .../syntax_checkers/python/prospector.vim | 73 + .../syntax_checkers/python/py3kwarn.vim | 36 + .../syntax_checkers/python/pyflakes.vim | 74 + .../syntax_checkers/python/pylama.vim | 74 + .../syntax_checkers/python/pylint.vim | 97 ++ .../syntax_checkers/python/python.vim | 57 + .../syntastic/syntax_checkers/r/lint.vim | 83 + .../syntastic/syntax_checkers/r/svtools.vim | 78 + .../syntax_checkers/racket/code-ayatollah.vim | 62 + .../syntax_checkers/racket/racket.vim | 50 + .../syntastic/syntax_checkers/rnc/rnv.vim | 38 + .../syntax_checkers/rst/rst2pseudoxml.vim | 62 + .../syntax_checkers/rst/rstcheck.vim | 50 + .../syntastic/syntax_checkers/ruby/jruby.vim | 50 + .../syntax_checkers/ruby/macruby.vim | 49 + .../syntastic/syntax_checkers/ruby/mri.vim | 82 + .../syntastic/syntax_checkers/ruby/reek.vim | 56 + .../syntax_checkers/ruby/rubocop.vim | 57 + .../syntax_checkers/ruby/rubylint.vim | 45 + .../syntastic/syntax_checkers/sass/sass.vim | 84 + .../syntastic/syntax_checkers/sass/sassc.vim | 38 + .../syntastic/syntax_checkers/scala/fsc.vim | 48 + .../syntax_checkers/scala/scalac.vim | 43 + .../syntax_checkers/scala/scalastyle.vim | 77 + .../syntastic/syntax_checkers/scss/sass.vim | 25 + .../syntastic/syntax_checkers/scss/sassc.vim | 25 + .../syntax_checkers/scss/scss_lint.vim | 57 + .../syntastic/syntax_checkers/sh/bashate.vim | 48 + .../syntax_checkers/sh/checkbashisms.vim | 42 + .../syntastic/syntax_checkers/sh/sh.vim | 93 ++ .../syntax_checkers/sh/shellcheck.vim | 44 + .../syntastic/syntax_checkers/slim/slimrb.vim | 55 + .../syntastic/syntax_checkers/sml/smlnj.vim | 47 + .../syntax_checkers/spec/rpmlint.vim | 43 + .../syntax_checkers/tcl/nagelfar.vim | 44 + .../syntastic/syntax_checkers/tex/chktex.vim | 52 + .../syntastic/syntax_checkers/tex/lacheck.vim | 40 + .../syntax_checkers/texinfo/makeinfo.vim | 47 + .../syntax_checkers/text/atdtool.vim | 61 + .../syntastic/syntax_checkers/text/igor.vim | 25 + .../syntax_checkers/text/language_check.vim | 37 + .../syntax_checkers/twig/twiglint.vim | 41 + .../syntax_checkers/typescript/tsc.vim | 60 + .../syntax_checkers/typescript/tslint.vim | 46 + .../syntastic/syntax_checkers/vala/valac.vim | 84 + .../syntax_checkers/verilog/verilator.vim | 42 + .../syntastic/syntax_checkers/vhdl/ghdl.vim | 38 + .../syntastic/syntax_checkers/vim/vimlint.vim | 105 ++ .../syntastic/syntax_checkers/vim/vint.vim | 55 + .../syntax_checkers/xhtml/jshint.vim | 25 + .../syntastic/syntax_checkers/xhtml/tidy.vim | 92 ++ .../syntastic/syntax_checkers/xml/plutil.vim | 42 + .../syntastic/syntax_checkers/xml/xmllint.vim | 54 + .../syntax_checkers/xslt/xmllint.vim | 25 + .../syntastic/syntax_checkers/yacc/bison.vim | 55 + .../syntastic/syntax_checkers/yaml/jsyaml.vim | 47 + .../syntastic/syntax_checkers/yaml/yamlxs.vim | 72 + .../syntax_checkers/z80/z80syntaxchecker.vim | 39 + .../syntastic/syntax_checkers/zpt/zptlint.vim | 42 + .../syntastic/syntax_checkers/zsh/zsh.vim | 38 + config/home/vimrc | 62 + 232 files changed, 22899 insertions(+), 7 deletions(-) create mode 100644 config/home/bashrc create mode 100644 config/home/vim/autoload/pathogen.vim create mode 100644 config/home/vim/bundle/nerdtree/.gitignore create mode 100644 config/home/vim/bundle/nerdtree/README.markdown create mode 100644 config/home/vim/bundle/nerdtree/autoload/nerdtree.vim create mode 100644 config/home/vim/bundle/nerdtree/autoload/nerdtree/ui_glue.vim create mode 100644 config/home/vim/bundle/nerdtree/doc/NERD_tree.txt create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/bookmark.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/creator.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/event.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/flag_set.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/key_map.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/menu_controller.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/menu_item.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/nerdtree.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/notifier.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/opener.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/path.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/tree_dir_node.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/tree_file_node.vim create mode 100644 config/home/vim/bundle/nerdtree/lib/nerdtree/ui.vim create mode 100644 config/home/vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim create mode 100644 config/home/vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim create mode 100644 config/home/vim/bundle/nerdtree/plugin/NERD_tree.vim create mode 100644 config/home/vim/bundle/nerdtree/syntax/nerdtree.vim create mode 100644 config/home/vim/bundle/syntastic/.gitignore create mode 100644 config/home/vim/bundle/syntastic/CONTRIBUTING.md create mode 100644 config/home/vim/bundle/syntastic/LICENCE create mode 100644 config/home/vim/bundle/syntastic/README.markdown create mode 100644 config/home/vim/bundle/syntastic/_assets/screenshot_1.png create mode 100644 config/home/vim/bundle/syntastic/autoload/syntastic/c.vim create mode 100644 config/home/vim/bundle/syntastic/autoload/syntastic/log.vim create mode 100644 config/home/vim/bundle/syntastic/autoload/syntastic/postprocess.vim create mode 100644 config/home/vim/bundle/syntastic/autoload/syntastic/preprocess.vim create mode 100644 config/home/vim/bundle/syntastic/autoload/syntastic/util.vim create mode 100644 config/home/vim/bundle/syntastic/doc/syntastic.txt create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/autoloclist.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/balloons.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/checker.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/cursor.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/highlighting.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/loclist.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/modemap.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/notifiers.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/registry.vim create mode 100644 config/home/vim/bundle/syntastic/plugin/syntastic/signs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/actionscript/mxmlc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ada/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/apiblueprint/snowcrash.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/applescript/osacompile.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/asciidoc/asciidoc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/asm/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/bemhtml/bemhtmllint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/bro/bro.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/avrgcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/checkpatch.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/clang_check.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/clang_tidy.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/cppcheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/make.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/oclint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/pc_lint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/sparse.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/c/splint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cabal/cabal.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/chef/foodcritic.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/co/coco.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cobol/cobc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/coffee/coffee.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/coffee/coffeelint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/coq/coqtop.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/clang_check.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/clang_tidy.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/cppcheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/cpplint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/oclint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cpp/pc_lint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cs/mcs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/css/csslint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/css/phpcs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/css/prettycss.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/css/recess.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cucumber/cucumber.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/cuda/nvcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/d/dmd.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/dart/dartanalyzer.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/docbk/igor.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/docbk/xmllint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/dustjs/swiffer.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/elixir/elixir.vim create mode 100755 config/home/vim/bundle/syntastic/syntax_checkers/erlang/erlang_check_file.erl create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/erlang/escript.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/erlang/syntaxerl.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/eruby/ruby.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/fortran/gfortran.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/glsl/cgc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/go/go.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/go/gofmt.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/go/golint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/go/gotype.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/go/govet.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haml/haml.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haml/haml_lint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/handlebars/handlebars.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haskell/ghc-mod.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haskell/hdevtools.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haskell/hlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haskell/scan.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/haxe/haxe.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/hss/hss.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/html/jshint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/html/tidy.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/html/validator.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/html/w3.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/java/checkstyle.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/java/javac.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/closurecompiler.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/eslint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/flow.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/gjslint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/jscs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/jshint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/jsl.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/jslint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/jsxhint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/javascript/standard.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/json/jsonlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/json/jsonval.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/less/less-lint.coffee create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/less/less-lint.js create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/less/lessc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/less/recess.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/lex/flex.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/limbo/limbo.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/lisp/clisp.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/llvm/llvm.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/lua/luac.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/lua/luacheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/markdown/mdl.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/matlab/mlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/mercury/mmc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/nasm/nasm.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/nroff/igor.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/nroff/mandoc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/objc/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/objc/oclint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/objcpp/gcc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/objcpp/oclint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ocaml/camlp4o.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/perl/perl.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/perl/perlcritic.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/perl/podchecker.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/php/php.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/php/phpcs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/php/phplint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/php/phpmd.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/po/msgfmt.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/pod/podchecker.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/puppet/puppet.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/puppet/puppetlint.vim create mode 100755 config/home/vim/bundle/syntastic/syntax_checkers/python/codec.py create mode 100755 config/home/vim/bundle/syntastic/syntax_checkers/python/compile.py create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/flake8.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/frosted.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/mypy.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/pep257.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/pep8.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/prospector.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/py3kwarn.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/pyflakes.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/pylama.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/pylint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/python/python.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/r/lint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/r/svtools.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/racket/code-ayatollah.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/racket/racket.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/rnc/rnv.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/rst/rst2pseudoxml.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/rst/rstcheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/jruby.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/macruby.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/mri.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/reek.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/rubocop.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/ruby/rubylint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sass/sass.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sass/sassc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scala/fsc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scala/scalac.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scala/scalastyle.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scss/sass.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scss/sassc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/scss/scss_lint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sh/bashate.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sh/checkbashisms.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sh/sh.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sh/shellcheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/slim/slimrb.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/sml/smlnj.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/spec/rpmlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/tcl/nagelfar.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/tex/chktex.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/tex/lacheck.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/texinfo/makeinfo.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/text/atdtool.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/text/igor.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/text/language_check.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/twig/twiglint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/typescript/tsc.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/typescript/tslint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/vala/valac.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/verilog/verilator.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/vhdl/ghdl.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/vim/vimlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/vim/vint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/xhtml/jshint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/xhtml/tidy.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/xml/plutil.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/xml/xmllint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/xslt/xmllint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/yacc/bison.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/yaml/jsyaml.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/yaml/yamlxs.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/z80/z80syntaxchecker.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/zpt/zptlint.vim create mode 100644 config/home/vim/bundle/syntastic/syntax_checkers/zsh/zsh.vim create mode 100644 config/home/vimrc diff --git a/Dockerfile b/Dockerfile index 2571714..f374e25 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ RUN curl --location --silent --output /opt/phantom-1.9.8.tar.bz2 \ RUN gem install compass --version 1.0.1 # Node -ENV NODE_VERSION 0.10.35 +ENV NODE_VERSION 0.12.2 RUN mkdir -p /opt/node && \ curl --silent --output /opt/node.tar.gz \ https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz && \ @@ -55,22 +55,51 @@ RUN mkdir -p /opt/node && \ RUN cd /usr/local/bin/ && ln -s phantomjs-1.9.8 phantomjs -ENV PATH /opt/node/bin:$PATH +ENV PATH /opt/node/bin:/opt/phantom-talk/node_modules/.bin:$PATH ENV PHANTOMJS_BIN /usr/local/bin/phantomjs +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ + vim \ + git \ + && rm -r /var/lib/apt/lists + +RUN adduser \ + --disabled-password \ + --home /home/demo \ + --shell /bin/bash \ + --gecos "Demo" \ + demo \ + && mkdir /opt/phantom-talk + +ADD ./config/home/bashrc /home/demo/.bashrc +ADD ./config/home/vimrc /home/demo/.vimrc +ADD ./config/home/vim /home/demo/.vim + +RUN chown -R demo:demo /home/demo \ + && chown demo:demo /opt/phantom-talk + +USER demo +ENV EDITOR vim +ENV HOME /home/demo +ENV TERM screen-256color WORKDIR /opt/phantom-talk -COPY ./package.json /opt/phantom-talk/package.json -COPY ./README.md /opt/phantom-talk/README.md -RUN ["npm", "install"] +ADD ./package.json /opt/phantom-talk/package.json +ADD ./README.md /opt/phantom-talk/README.md +RUN npm install ADD . /opt/phantom-talk +USER root +RUN chown demo:demo -R /opt/phantom-talk +USER demo -ENV TERM screen-256color +RUN npm run build -RUN ["npm", "run", "build"] EXPOSE 8000 EXPOSE 8001 EXPOSE 8002 EXPOSE 35729 + ENTRYPOINT ["npm"] CMD ["run", "deck"] diff --git a/config/home/bashrc b/config/home/bashrc new file mode 100644 index 0000000..988d698 --- /dev/null +++ b/config/home/bashrc @@ -0,0 +1,114 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +HISTCONTROL=ignoreboth + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# If set, the pattern "**" used in a pathname expansion context will +# match all files and zero or more directories and subdirectories. +#shopt -s globstar + +# make less more friendly for non-text input files, see lesspipe(1) +[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, unless we know we "want" color) +case "$TERM" in + xterm-color) color_prompt=yes;; +esac + +# uncomment for a colored prompt, if the terminal has the capability; turned +# off by default to not distract the user: the focus in a terminal window +# should be on the output of commands, not on the prompt +force_color_prompt=yes + +if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi +fi + +if [ "$color_prompt" = yes ]; then + PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\n\$ ' +else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\n\$ ' +fi +unset color_prompt force_color_prompt + +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; +*) + ;; +esac + +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' +fi + +# some more ls aliases +alias ll='ls -alF' +alias la='ls -A' +alias l='ls -CF' + +# Add an "alert" alias for long running commands. Use like so: +# sleep 10; alert +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' + +# Alias definitions. +# You may want to put all your additions into a separate file like +# ~/.bash_aliases, instead of adding them here directly. +# See /usr/share/doc/bash-doc/examples in the bash-doc package. + +if [ -f ~/.bash_aliases ]; then + . ~/.bash_aliases +fi + +# enable programmable completion features (you don't need to enable +# this, if it's already enabled in /etc/bash.bashrc and /etc/profile +# sources /etc/bash.bashrc). +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi diff --git a/config/home/vim/autoload/pathogen.vim b/config/home/vim/autoload/pathogen.vim new file mode 100644 index 0000000..a13ae08 --- /dev/null +++ b/config/home/vim/autoload/pathogen.vim @@ -0,0 +1,347 @@ +" pathogen.vim - path option manipulation +" Maintainer: Tim Pope +" Version: 2.3 + +" Install in ~/.vim/autoload (or ~\vimfiles\autoload). +" +" For management of individually installed plugins in ~/.vim/bundle (or +" ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your +" .vimrc is the only other setup necessary. +" +" The API is documented inline below. + +if exists("g:loaded_pathogen") || &cp + finish +endif +let g:loaded_pathogen = 1 + +" Point of entry for basic default usage. Give a relative path to invoke +" pathogen#interpose() (defaults to "bundle/{}"), or an absolute path to invoke +" pathogen#surround(). Curly braces are expanded with pathogen#expand(): +" "bundle/{}" finds all subdirectories inside "bundle" inside all directories +" in the runtime path. +function! pathogen#infect(...) abort + for path in a:0 ? filter(reverse(copy(a:000)), 'type(v:val) == type("")') : ['bundle/{}'] + if path =~# '^\%({\=[$~\\/]\|{\=\w:[\\/]\).*[{}*]' + call pathogen#surround(path) + elseif path =~# '^\%([$~\\/]\|\w:[\\/]\)' + call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')') + call pathogen#surround(path . '/{}') + elseif path =~# '[{}*]' + call pathogen#interpose(path) + else + call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')') + call pathogen#interpose(path . '/{}') + endif + endfor + call pathogen#cycle_filetype() + if pathogen#is_disabled($MYVIMRC) + return 'finish' + endif + return '' +endfunction + +" Split a path into a list. +function! pathogen#split(path) abort + if type(a:path) == type([]) | return a:path | endif + if empty(a:path) | return [] | endif + let split = split(a:path,'\\\@]','\\&','') + endif +endfunction + +" Like findfile(), but hardcoded to use the runtimepath. +function! pathogen#runtime_findfile(file,count) abort "{{{1 + let rtp = pathogen#join(1,pathogen#split(&rtp)) + let file = findfile(a:file,rtp,a:count) + if file ==# '' + return '' + else + return fnamemodify(file,':p') + endif +endfunction + +" Section: Deprecated + +function! s:warn(msg) abort + echohl WarningMsg + echomsg a:msg + echohl NONE +endfunction + +" Prepend all subdirectories of path to the rtp, and append all 'after' +" directories in those subdirectories. Deprecated. +function! pathogen#runtime_prepend_subdirectories(path) abort + call s:warn('Change pathogen#runtime_prepend_subdirectories('.string(a:path).') to pathogen#infect('.string(a:path.'/{}').')') + return pathogen#surround(a:path . pathogen#slash() . '{}') +endfunction + +function! pathogen#incubate(...) abort + let name = a:0 ? a:1 : 'bundle/{}' + call s:warn('Change pathogen#incubate('.(a:0 ? string(a:1) : '').') to pathogen#infect('.string(name).')') + return pathogen#interpose(name) +endfunction + +" Deprecated alias for pathogen#interpose(). +function! pathogen#runtime_append_all_bundles(...) abort + if a:0 + call s:warn('Change pathogen#runtime_append_all_bundles('.string(a:1).') to pathogen#infect('.string(a:1.'/{}').')') + else + call s:warn('Change pathogen#runtime_append_all_bundles() to pathogen#infect()') + endif + return pathogen#interpose(a:0 ? a:1 . '/{}' : 'bundle/{}') +endfunction + +if exists(':Vedit') + finish +endif + +let s:vopen_warning = 0 + +function! s:find(count,cmd,file,lcd) + let rtp = pathogen#join(1,pathogen#split(&runtimepath)) + let file = pathogen#runtime_findfile(a:file,a:count) + if file ==# '' + return "echoerr 'E345: Can''t find file \"".a:file."\" in runtimepath'" + endif + if !s:vopen_warning + let s:vopen_warning = 1 + let warning = '|echohl WarningMsg|echo "Install scriptease.vim to continue using :V'.a:cmd.'"|echohl NONE' + else + let warning = '' + endif + if a:lcd + let path = file[0:-strlen(a:file)-2] + execute 'lcd `=path`' + return a:cmd.' '.pathogen#fnameescape(a:file) . warning + else + return a:cmd.' '.pathogen#fnameescape(file) . warning + endif +endfunction + +function! s:Findcomplete(A,L,P) + let sep = pathogen#slash() + let cheats = { + \'a': 'autoload', + \'d': 'doc', + \'f': 'ftplugin', + \'i': 'indent', + \'p': 'plugin', + \'s': 'syntax'} + if a:A =~# '^\w[\\/]' && has_key(cheats,a:A[0]) + let request = cheats[a:A[0]].a:A[1:-1] + else + let request = a:A + endif + let pattern = substitute(request,'/\|\'.sep,'*'.sep,'g').'*' + let found = {} + for path in pathogen#split(&runtimepath) + let path = expand(path, ':p') + let matches = split(glob(path.sep.pattern),"\n") + call map(matches,'isdirectory(v:val) ? v:val.sep : v:val') + call map(matches,'expand(v:val, ":p")[strlen(path)+1:-1]') + for match in matches + let found[match] = 1 + endfor + endfor + return sort(keys(found)) +endfunction + +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Ve :execute s:find(,'edit',,0) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vedit :execute s:find(,'edit',,0) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vopen :execute s:find(,'edit',,1) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vsplit :execute s:find(,'split',,1) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vvsplit :execute s:find(,'vsplit',,1) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vtabedit :execute s:find(,'tabedit',,1) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vpedit :execute s:find(,'pedit',,1) +command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vread :execute s:find(,'read',,1) + +" vim:set et sw=2 foldmethod=expr foldexpr=getline(v\:lnum)=~'^\"\ Section\:'?'>1'\:getline(v\:lnum)=~#'^fu'?'a1'\:getline(v\:lnum)=~#'^endf'?'s1'\:'=': diff --git a/config/home/vim/bundle/nerdtree/.gitignore b/config/home/vim/bundle/nerdtree/.gitignore new file mode 100644 index 0000000..3698c0e --- /dev/null +++ b/config/home/vim/bundle/nerdtree/.gitignore @@ -0,0 +1,3 @@ +*~ +*.swp +tags diff --git a/config/home/vim/bundle/nerdtree/README.markdown b/config/home/vim/bundle/nerdtree/README.markdown new file mode 100644 index 0000000..880079a --- /dev/null +++ b/config/home/vim/bundle/nerdtree/README.markdown @@ -0,0 +1,103 @@ +The NERD Tree +============= + +Intro +----- + +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 (netrw), so if + you :edit a directory a (slightly 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 filesystem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + +Installation +------------ + +[pathogen.vim](https://github.com/tpope/vim-pathogen) is the recommended way to install nerdtree. + + cd ~/.vim/bundle + git clone https://github.com/scrooloose/nerdtree.git + +Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`. + + +Faq +--- + +> Is there any support for `git` flags? + +Yes, install [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin). + + +> Can I have the nerdtree on every tab automatically? + +Nope. If this is something you want then chances are you aren't using tabs and +buffers as they were intended to be used. Read this +http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers + +If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs) + +> How can I open a NERDTree automatically when vim starts up? + +Stick this in your vimrc: `autocmd vimenter * NERDTree` + +> How can I open a NERDTree automatically when vim starts up if no files were specified? + +Stick this in your vimrc + + autocmd StdinReadPre * let s:std_in=1 + autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif + +> How can I map a specific key or shortcut to open NERDTree? + +Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): + +`map :NERDTreeToggle` + +> How can I close vim if the only window left open is a NERDTree? + +Stick this in your vimrc: + + `autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif` diff --git a/config/home/vim/bundle/nerdtree/autoload/nerdtree.vim b/config/home/vim/bundle/nerdtree/autoload/nerdtree.vim new file mode 100644 index 0000000..22283aa --- /dev/null +++ b/config/home/vim/bundle/nerdtree/autoload/nerdtree.vim @@ -0,0 +1,136 @@ +if exists("g:loaded_nerdtree_autoload") + finish +endif +let g:loaded_nerdtree_autoload = 1 + +function! nerdtree#version() + return '4.2.0' +endfunction + +" SECTION: General Functions {{{1 +"============================================================ + +"FUNCTION: nerdtree#checkForBrowse(dir) {{{2 +"inits a secondary nerd tree in the current buffer if appropriate +function! nerdtree#checkForBrowse(dir) + if a:dir != '' && isdirectory(a:dir) + call g:NERDTreeCreator.CreateSecondary(a:dir) + endif +endfunction + +" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2 +" completion function for the bookmark commands +function! nerdtree#completeBookmarks(A,L,P) + return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"') +endfunction + +"FUNCTION: nerdtree#compareBookmarks(dir) {{{2 +function! nerdtree#compareBookmarks(first, second) + return a:first.compareTo(a:second) +endfunction + +"FUNCTION: nerdtree#compareNodes(dir) {{{2 +function! nerdtree#compareNodes(n1, n2) + return a:n1.path.compareTo(a:n2.path) +endfunction + +" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2 +" Issue a deprecation warning for a:func. If a second arg is given, use this +" as the deprecation message +function! nerdtree#deprecated(func, ...) + let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated' + + if !exists('s:deprecationWarnings') + let s:deprecationWarnings = {} + endif + if !has_key(s:deprecationWarnings, a:func) + let s:deprecationWarnings[a:func] = 1 + echomsg msg + endif +endfunction + +" FUNCTION: nerdtree#exec(cmd) {{{2 +" same as :exec cmd but eventignore=all is set for the duration +function! nerdtree#exec(cmd) + let old_ei = &ei + set ei=all + exec a:cmd + let &ei = old_ei +endfunction + +" FUNCTION: nerdtree#has_opt(options, name) {{{2 +function! nerdtree#has_opt(options, name) + return has_key(a:options, a:name) && a:options[a:name] == 1 +endfunction + +" FUNCTION: nerdtree#loadClassFiles() {{{2 +function! nerdtree#loadClassFiles() + runtime lib/nerdtree/path.vim + runtime lib/nerdtree/menu_controller.vim + runtime lib/nerdtree/menu_item.vim + runtime lib/nerdtree/key_map.vim + runtime lib/nerdtree/bookmark.vim + runtime lib/nerdtree/tree_file_node.vim + runtime lib/nerdtree/tree_dir_node.vim + runtime lib/nerdtree/opener.vim + runtime lib/nerdtree/creator.vim + runtime lib/nerdtree/flag_set.vim + runtime lib/nerdtree/nerdtree.vim + runtime lib/nerdtree/ui.vim + runtime lib/nerdtree/event.vim + runtime lib/nerdtree/notifier.vim +endfunction + +" FUNCTION: nerdtree#postSourceActions() {{{2 +function! nerdtree#postSourceActions() + call g:NERDTreeBookmark.CacheBookmarks(0) + call nerdtree#ui_glue#createDefaultBindings() + + "load all nerdtree plugins + runtime! nerdtree_plugin/**/*.vim +endfunction + +"FUNCTION: nerdtree#runningWindows(dir) {{{2 +function! nerdtree#runningWindows() + return has("win16") || has("win32") || has("win64") +endfunction + +" SECTION: View Functions {{{1 +"============================================================ + +"FUNCTION: nerdtree#echo {{{2 +"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages +" +"Args: +"msg: the message to echo +function! nerdtree#echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction + +"FUNCTION: nerdtree#echoError {{{2 +"Wrapper for nerdtree#echo, sets the message type to errormsg for this message +"Args: +"msg: the message to echo +function! nerdtree#echoError(msg) + echohl errormsg + call nerdtree#echo(a:msg) + echohl normal +endfunction + +"FUNCTION: nerdtree#echoWarning {{{2 +"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message +"Args: +"msg: the message to echo +function! nerdtree#echoWarning(msg) + echohl warningmsg + call nerdtree#echo(a:msg) + echohl normal +endfunction + +"FUNCTION: nerdtree#renderView {{{2 +function! nerdtree#renderView() + call b:NERDTree.render() +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/autoload/nerdtree/ui_glue.vim b/config/home/vim/bundle/nerdtree/autoload/nerdtree/ui_glue.vim new file mode 100644 index 0000000..1f922df --- /dev/null +++ b/config/home/vim/bundle/nerdtree/autoload/nerdtree/ui_glue.vim @@ -0,0 +1,644 @@ +if exists("g:loaded_nerdtree_ui_glue_autoload") + finish +endif +let g:loaded_nerdtree_ui_glue_autoload = 1 + +" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1 +function! nerdtree#ui_glue#createDefaultBindings() + let s = '' . s:SID() . '_' + + call NERDTreeAddKeyMap({ 'key': '', 'scope': "all", 'callback': s."handleMiddleMouse" }) + call NERDTreeAddKeyMap({ 'key': '', 'scope': "all", 'callback': s."handleLeftClick" }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "Bookmark", 'callback': s."activateBookmark" }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "all", 'callback': s."activateAll" }) + + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "DirNode", 'callback': s."activateDirNode" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "FileNode", 'callback': s."activateFileNode" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "Bookmark", 'callback': s."activateBookmark" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "all", 'callback': s."activateAll" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Node", 'callback': s."openHSplit" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Node", 'callback': s."openVSplit" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Bookmark", 'callback': s."openHSplit" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Bookmark", 'callback': s."openVSplit" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Node", 'callback': s."previewNodeCurrent" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Node", 'callback': s."previewNodeVSplit" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Node", 'callback': s."previewNodeHSplit" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Bookmark", 'callback': s."previewNodeCurrent" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Bookmark", 'callback': s."previewNodeVSplit" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Bookmark", 'callback': s."previewNodeHSplit" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': "DirNode", 'callback': s."openNodeRecursively" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': "all", 'callback': s."upDirCurrentRootClosed" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': "all", 'callback': s."upDirCurrentRootOpen" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': "Node", 'callback': s."chRoot" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': "all", 'callback': s."closeTreeWindow" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': "all", 'callback': "nerdtree#ui_glue#chRootCwd" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': "all", 'callback': s."refreshRoot" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': "Node", 'callback': s."refreshCurrent" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': "all", 'callback': s."displayHelp" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': "all", 'callback': s."toggleZoom" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': "all", 'callback': s."toggleShowHidden" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': "all", 'callback': s."toggleIgnoreFilter" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': "all", 'callback': s."toggleShowFiles" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': "all", 'callback': s."toggleShowBookmarks" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': "Node", 'callback': s."closeCurrentDir" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': "DirNode", 'callback': s."closeChildren" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': "Node", 'callback': s."showMenu" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': "Node", 'callback': s."jumpToParent" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': "Node", 'callback': s."jumpToFirstChild" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': "Node", 'callback': s."jumpToLastChild" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': "all", 'callback': s."jumpToRoot" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Node", 'callback': s."openInNewTab" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Node", 'callback': s."openInNewTabSilent" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Bookmark", 'callback': s."openInNewTab" }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Bookmark", 'callback': s."openInNewTabSilent" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': "DirNode", 'callback': s."openExplorer" }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': "Bookmark", 'callback': s."deleteBookmark" }) +endfunction + + +"SECTION: Interface bindings {{{1 +"============================================================ + +"FUNCTION: s:activateAll() {{{1 +"handle the user activating the updir line +function! s:activateAll() + if getline(".") ==# g:NERDTreeUI.UpDirLine() + return nerdtree#ui_glue#upDir(0) + endif +endfunction + +"FUNCTION: s:activateDirNode() {{{1 +"handle the user activating a tree node +function! s:activateDirNode(node) + call a:node.activate() +endfunction + +"FUNCTION: s:activateFileNode() {{{1 +"handle the user activating a tree node +function! s:activateFileNode(node) + call a:node.activate({'reuse': 'all', 'where': 'p'}) +endfunction + +"FUNCTION: s:activateBookmark() {{{1 +"handle the user activating a bookmark +function! s:activateBookmark(bm) + call a:bm.activate(!a:bm.path.isDirectory ? {'where': 'p'} : {}) +endfunction + +" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1 +" Associate the current node with the given name +function! nerdtree#ui_glue#bookmarkNode(...) + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode != {} + let name = a:1 + if empty(name) + let name = currentNode.path.getLastPathComponent(0) + endif + try + call currentNode.bookmark(name) + call b:NERDTree.render() + catch /^NERDTree.IllegalBookmarkNameError/ + call nerdtree#echo("bookmark names must not contain spaces") + endtry + else + call nerdtree#echo("select a node first") + endif +endfunction + +" FUNCTION: s:chCwd(node) {{{1 +function! s:chCwd(node) + try + call a:node.path.changeToDir() + catch /^NERDTree.PathChangeError/ + call nerdtree#echoWarning("could not change cwd") + endtry +endfunction + +" FUNCTION: s:chRoot(node) {{{1 +" changes the current root to the selected one +function! s:chRoot(node) + call a:node.makeRoot() + call b:NERDTree.render() + call b:NERDTreeRoot.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1 +" changes the current root to CWD +function! nerdtree#ui_glue#chRootCwd() + try + let cwd = g:NERDTreePath.New(getcwd()) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo("current directory does not exist.") + return + endtry + if cwd.str() == g:NERDTreeFileNode.GetRootForTab().path.str() + return + endif + call s:chRoot(g:NERDTreeDirNode.New(cwd)) +endfunction + +" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1 +function! nerdtree#ui_glue#clearBookmarks(bookmarks) + if a:bookmarks ==# '' + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode != {} + call currentNode.clearBookmarks() + endif + else + for name in split(a:bookmarks, ' ') + let bookmark = g:NERDTreeBookmark.BookmarkFor(name) + call bookmark.delete() + endfor + endif + call b:NERDTree.render() +endfunction + +" FUNCTION: s:closeChildren(node) {{{1 +" closes all childnodes of the current node +function! s:closeChildren(node) + call a:node.closeChildren() + call b:NERDTree.render() + call a:node.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:closeCurrentDir(node) {{{1 +" closes the parent dir of the current node +function! s:closeCurrentDir(node) + let parent = a:node.parent + if parent ==# {} || parent.isRoot() + call nerdtree#echo("cannot close tree root") + else + while g:NERDTreeCascadeOpenSingleChildDir && !parent.parent.isRoot() + if parent.parent.getVisibleChildCount() == 1 + call parent.close() + let parent = parent.parent + else + break + endif + endwhile + call parent.close() + call b:NERDTree.render() + call parent.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: s:closeTreeWindow() {{{1 +" close the tree window +function! s:closeTreeWindow() + if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1 + exec "buffer " . b:NERDTreePreviousBuf + else + if winnr("$") > 1 + call g:NERDTree.Close() + else + call nerdtree#echo("Cannot close last window") + endif + endif +endfunction + +" FUNCTION: s:deleteBookmark(bm) {{{1 +" if the cursor is on a bookmark, prompt to delete +function! s:deleteBookmark(bm) + echo "Are you sure you wish to delete the bookmark:\n\"" . a:bm.name . "\" (yN):" + + if nr2char(getchar()) ==# 'y' + try + call a:bm.delete() + call b:NERDTree.render() + redraw + catch /^NERDTree/ + call nerdtree#echoWarning("Could not remove bookmark") + endtry + else + call nerdtree#echo("delete aborted" ) + endif + +endfunction + +" FUNCTION: s:displayHelp() {{{1 +" toggles the help display +function! s:displayHelp() + let b:treeShowHelp = b:treeShowHelp ? 0 : 1 + call b:NERDTree.render() + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:findAndRevealPath() {{{1 +function! s:findAndRevealPath() + try + let p = g:NERDTreePath.New(expand("%:p")) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo("no file for the current buffer") + return + endtry + + if p.isUnixHiddenPath() + let showhidden=g:NERDTreeShowHidden + let g:NERDTreeShowHidden = 1 + endif + + if !g:NERDTree.ExistsForTab() + try + let cwd = g:NERDTreePath.New(getcwd()) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo("current directory does not exist.") + let cwd = p.getParent() + endtry + + if p.isUnder(cwd) + call g:NERDTreeCreator.CreatePrimary(cwd.str()) + else + call g:NERDTreeCreator.CreatePrimary(p.getParent().str()) + endif + else + if !p.isUnder(g:NERDTreeFileNode.GetRootForTab().path) + if !g:NERDTree.IsOpen() + call g:NERDTreeCreator.TogglePrimary('') + else + call g:NERDTree.CursorToTreeWin() + endif + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + call s:chRoot(g:NERDTreeDirNode.New(p.getParent())) + else + if !g:NERDTree.IsOpen() + call g:NERDTreeCreator.TogglePrimary("") + endif + endif + endif + call g:NERDTree.CursorToTreeWin() + call b:NERDTreeRoot.reveal(p) + + if p.isUnixHiddenFile() + let g:NERDTreeShowHidden = showhidden + endif +endfunction + +"FUNCTION: s:handleLeftClick() {{{1 +"Checks if the click should open the current node +function! s:handleLeftClick() + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode != {} + + "the dir arrows are multibyte chars, and vim's string functions only + "deal with single bytes - so split the line up with the hack below and + "take the line substring manually + let line = split(getline(line(".")), '\zs') + let startToCur = "" + for i in range(0,len(line)-1) + let startToCur .= line[i] + endfor + + if currentNode.path.isDirectory + if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~▾▸] \?$' + call currentNode.activate() + return + endif + endif + + if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3 + let char = strpart(startToCur, strlen(startToCur)-1, 1) + if char !~# g:NERDTreeUI.MarkupReg() + if currentNode.path.isDirectory + call currentNode.activate() + else + call currentNode.activate({'reuse': 'all', 'where': 'p'}) + endif + return + endif + endif + endif +endfunction + +" FUNCTION: s:handleMiddleMouse() {{{1 +function! s:handleMiddleMouse() + let curNode = g:NERDTreeFileNode.GetSelected() + if curNode ==# {} + call nerdtree#echo("Put the cursor on a node first" ) + return + endif + + if curNode.path.isDirectory + call nerdtree#openExplorer(curNode) + else + call curNode.open({'where': 'h'}) + endif +endfunction + +" FUNCTION: s:jumpToChild(direction) {{{2 +" Args: +" direction: 0 if going to first child, 1 if going to last +function! s:jumpToChild(currentNode, direction) + if a:currentNode.isRoot() + return nerdtree#echo("cannot jump to " . (a:direction ? "last" : "first") . " child") + end + let dirNode = a:currentNode.parent + let childNodes = dirNode.getVisibleChildren() + + let targetNode = childNodes[0] + if a:direction + let targetNode = childNodes[len(childNodes) - 1] + endif + + if targetNode.equals(a:currentNode) + let siblingDir = a: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 b:NERDTree.ui.centerView() +endfunction + + +" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1 +"this is needed since I cant figure out how to invoke dict functions from a +"key map +function! nerdtree#ui_glue#invokeKeyMap(key) + call g:NERDTreeKeyMap.Invoke(a:key) +endfunction + +" FUNCTION: s:jumpToFirstChild() {{{1 +" wrapper for the jump to child method +function! s:jumpToFirstChild(node) + call s:jumpToChild(a:node, 0) +endfunction + +" FUNCTION: s:jumpToLastChild() {{{1 +" wrapper for the jump to child method +function! s:jumpToLastChild(node) + call s:jumpToChild(a:node, 1) +endfunction + +" FUNCTION: s:jumpToParent(node) {{{1 +" moves the cursor to the parent of the current node +function! s:jumpToParent(node) + if !empty(a:node.parent) + call a:node.parent.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() + else + call nerdtree#echo("cannot jump to parent") + endif +endfunction + +" FUNCTION: s:jumpToRoot() {{{1 +" moves the cursor to the root node +function! s:jumpToRoot() + call b:NERDTreeRoot.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:jumpToNextSibling(node) {{{1 +function! s:jumpToNextSibling(node) + call s:jumpToSibling(a:node, 1) +endfunction + +" FUNCTION: s:jumpToPrevSibling(node) {{{1 +function! s:jumpToPrevSibling(node) + call s:jumpToSibling(a:node, 0) +endfunction + +" FUNCTION: s:jumpToSibling(currentNode, forward) {{{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(currentNode, forward) + let sibling = a:currentNode.findSibling(a:forward) + + if !empty(sibling) + call sibling.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() + endif +endfunction + +" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1 +" put the cursor on the given bookmark and, if its a file, open it +function! nerdtree#ui_glue#openBookmark(name) + try + let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + redraw! + catch /^NERDTree.BookmarkedNodeNotFoundError/ + call nerdtree#echo("note - target node is not cached") + let bookmark = g:NERDTreeBookmark.BookmarkFor(a:name) + let targetNode = g:NERDTreeFileNode.New(bookmark.path) + endtry + if targetNode.path.isDirectory + call targetNode.openExplorer() + else + call targetNode.open({'where': 'p'}) + endif +endfunction + +" FUNCTION: s:openHSplit(target) {{{1 +function! s:openHSplit(target) + call a:target.activate({'where': 'h'}) +endfunction + +" FUNCTION: s:openVSplit(target) {{{1 +function! s:openVSplit(target) + call a:target.activate({'where': 'v'}) +endfunction + +" FUNCTION: s:openExplorer(node) {{{1 +function! s:openExplorer(node) + call a:node.openExplorer() +endfunction + +" FUNCTION: s:openInNewTab(target) {{{1 +function! s:openInNewTab(target) + call a:target.activate({'where': 't'}) +endfunction + +" FUNCTION: s:openInNewTabSilent(target) {{{1 +function! s:openInNewTabSilent(target) + call a:target.activate({'where': 't', 'stay': 1}) +endfunction + +" FUNCTION: s:openNodeRecursively(node) {{{1 +function! s:openNodeRecursively(node) + call nerdtree#echo("Recursively opening node. Please wait...") + call a:node.openRecursively() + call b:NERDTree.render() + redraw + call nerdtree#echo("Recursively opening node. Please wait... DONE") +endfunction + +"FUNCTION: s:previewNodeCurrent(node) {{{1 +function! s:previewNodeCurrent(node) + call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1}) +endfunction + +"FUNCTION: s:previewNodeHSplit(node) {{{1 +function! s:previewNodeHSplit(node) + call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1}) +endfunction + +"FUNCTION: s:previewNodeVSplit(node) {{{1 +function! s:previewNodeVSplit(node) + call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1}) +endfunction + +" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1 +" put the cursor on the node associate with the given name +function! nerdtree#ui_glue#revealBookmark(name) + try + let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + catch /^NERDTree.BookmarkNotFoundError/ + call nerdtree#echo("Bookmark isnt cached under the current root") + endtry +endfunction + +" FUNCTION: s:refreshRoot() {{{1 +" Reloads the current root. All nodes below this will be lost and the root dir +" will be reloaded. +function! s:refreshRoot() + call nerdtree#echo("Refreshing the root node. This could take a while...") + call b:NERDTreeRoot.refresh() + call b:NERDTree.render() + redraw + call nerdtree#echo("Refreshing the root node. This could take a while... DONE") +endfunction + +" FUNCTION: s:refreshCurrent(node) {{{1 +" refreshes the root for the current node +function! s:refreshCurrent(node) + let node = a:node + if !node.path.isDirectory + let node = node.parent + endif + + call nerdtree#echo("Refreshing node. This could take a while...") + call node.refresh() + call b:NERDTree.render() + redraw + call nerdtree#echo("Refreshing node. This could take a while... DONE") +endfunction + +" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1 +function! nerdtree#ui_glue#setupCommands() + command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('') + command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('') + command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close() + command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('') + command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror() + command! -n=0 -bar NERDTreeFind call s:findAndRevealPath() + command! -n=0 -bar NERDTreeFocus call NERDTreeFocus() + command! -n=0 -bar NERDTreeCWD call NERDTreeCWD() +endfunction + +" Function: s:SID() {{{1 +function s:SID() + if !exists("s:sid") + let s:sid = matchstr(expand(''), '\zs\d\+\ze_SID$') + endif + return s:sid +endfun + +" FUNCTION: s:showMenu(node) {{{1 +function! s:showMenu(node) + let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled()) + call mc.showMenu() +endfunction + +" FUNCTION: s:toggleIgnoreFilter() {{{1 +function! s:toggleIgnoreFilter() + call b:NERDTree.ui.toggleIgnoreFilter() +endfunction + +" FUNCTION: s:toggleShowBookmarks() {{{1 +function! s:toggleShowBookmarks() + call b:NERDTree.ui.toggleShowBookmarks() +endfunction + +" FUNCTION: s:toggleShowFiles() {{{1 +function! s:toggleShowFiles() + call b:NERDTree.ui.toggleShowFiles() +endfunction + +" FUNCTION: s:toggleShowHidden() {{{1 +" toggles the display of hidden files +function! s:toggleShowHidden() + call b:NERDTree.ui.toggleShowHidden() +endfunction + +" FUNCTION: s:toggleZoom() {{{1 +function! s:toggleZoom() + call b:NERDTree.ui.toggleZoom() +endfunction + +"FUNCTION: nerdtree#ui_glue#upDir(keepState) {{{1 +"moves the tree up a level +" +"Args: +"keepState: 1 if the current root should be left open when the tree is +"re-rendered +function! nerdtree#ui_glue#upDir(keepState) + let cwd = b:NERDTreeRoot.path.str({'format': 'UI'}) + if cwd ==# "/" || cwd =~# '^[^/]..$' + call nerdtree#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 = g:NERDTreeDirNode.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 b:NERDTree.render() + call oldRoot.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: s:upDirCurrentRootOpen() {{{1 +function! s:upDirCurrentRootOpen() + call nerdtree#ui_glue#upDir(1) +endfunction + +" FUNCTION: s:upDirCurrentRootClosed() {{{1 +function! s:upDirCurrentRootClosed() + call nerdtree#ui_glue#upDir(0) +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/doc/NERD_tree.txt b/config/home/vim/bundle/nerdtree/doc/NERD_tree.txt new file mode 100644 index 0000000..6418b57 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/doc/NERD_tree.txt @@ -0,0 +1,1399 @@ +*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| + 4.3.Menu API..........................|NERDTreeAddPathFilter()| + 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 (netrw), so if + you :edit a directory a (slightly 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 filesystem + 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 + . The 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 and the current file is under vim's CWD, then init a + tree at the CWD and reveal the file. Otherwise init a tree in the current + file's directory. + + In any case, the current file is revealed and the cursor is placed on it. + +:NERDTreeCWD *:NERDTreeCWD* + Change tree root to current directory. If no NERD tree exists for this + tab, a new tree will be opened. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note that the following commands are only available in the NERD tree buffer. + +:Bookmark [] + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + If is not provided, it defaults to the file or directory name. + For directories, a trailing slash is present. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + must point to a file. The file is opened as though |NERDTree-o| + was applied. If the node is cached under the current root then it will be + revealed and the cursor will be placed on it. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default Description~ help-tag~ +Key~ + +o.......Open files, directories and bookmarks....................|NERDTree-o| +go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| +t.......Open selected node/bookmark in a new tab.................|NERDTree-t| +T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| +i.......Open selected file in a split window.....................|NERDTree-i| +gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| +s.......Open selected file in a new vsplit.......................|NERDTree-s| +gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| +O.......Recursively open the selected directory..................|NERDTree-O| +x.......Close the current nodes parent...........................|NERDTree-x| +X.......Recursively close all children of the current node.......|NERDTree-X| +e.......Edit the current dir.....................................|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| +CD......Change tree root to the CWD..............................|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 selected 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: NERDTreeMapChangeRoot +Applies to: files and 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-CD* +Default key: CD +Map option: NERDTreeMapCWD +Applies to: no restrictions. + +Change tree root to vims current working directory. + +------------------------------------------------------------------------------ + *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. + +|'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. + +|'NERDTreeSortHiddenFirst'| Tells the NERD tree whether to take the dot + at the beginning of the hidden file names + into account 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. + +|'NERDTreeRespectWildIgnore'| Tells the NERD tree to respect |'wildignore'|. + +|'NERDTreeBookmarksFile'| Where the bookmarks are stored. + +|'NERDTreeBookmarksSort'| Whether the bookmarks list is sorted on + display. + +|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse + clicks. + +|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. + +|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the + bookmarks table on startup. + +|'NERDTreeShowFiles'| Tells the NERD tree whether to display files + in the tree on startup. + +|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden + files on startup. + +|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line + numbers in the tree window. + +|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in + the tree. + +|'NERDTreeStatusline'| Set a statusline for NERD tree windows. + +|'NERDTreeWinPos'| Tells the script where to put the NERD tree + window. + +|'NERDTreeWinSize'| Sets the window size when the NERD tree is + opened. + +|'NERDTreeMinimalUI'| Disables display of the 'Bookmarks' label and + 'Press ? for help' text. + +|'NERDTreeDirArrows'| Tells the NERD tree to use arrows instead of + + ~ chars when displaying directories. + +|'NERDTreeCascadeOpenSingleChildDir'| + Cascade open while selected directory has only + one child that also is a directory. + +|'NERDTreeAutoDeleteBuffer'| Tells the NERD tree to automatically remove + a buffer when a file is being deleted or renamed + via a context menu command. + +------------------------------------------------------------------------------ +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 +< + +------------------------------------------------------------------------------ + *'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 slightly 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. + +There are 2 magic flags that can be appended to the end of each regular +expression to specify that the regex should match only files or only dirs. +These flags are "[[dir]]" and "[[file]]". Example: > + let NERDTreeIgnore=['.d$[[dir]]', '.o$[[file]]'] +< +This will cause all dirs ending in ".d" to be ignored and all files ending in +".o" to 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. + +------------------------------------------------------------------------------ + *'NERDTreeRespectWildIgnore'* +Values: 0 or 1. +Default: 0. + +If set to 1, the |'wildignore'| setting is respected. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksFile'* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksSort'* +Values: 0 or 1 +Default: 1 + +If set to 0 then the bookmarks list is not sorted. +If set to 1 the bookmarks list is sorted. + +------------------------------------------------------------------------------ + *'NERDTreeMouseMode'* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *'NERDTreeQuitOnOpen'* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. + +------------------------------------------------------------------------------ + *'NERDTreeShowBookmarks'* +Values: 0 or 1. +Default: 0. + +If this option is set to 1 then the bookmarks table will be displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeShowFiles'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then files are displayed in the NERD tree. If it is +set to 0 then only directories are displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *'NERDTreeShowHidden'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display hidden files by default. This option +can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one +of the follow lines to set this option: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeShowLineNumbers'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines to set this option: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeSortOrder'* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This option is set to a list of regular expressions which are used to +specify the order of nodes under their parent. + +For example, if the option is set to: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be placed at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesnt match any of the other regexps should be placed here. + +If no star is present in 'NERDTreeSortOrder' then one is automatically +appended to the array. + +The regex '\/$' should be used to match directory nodes. + +After this sorting is done, the files in each group are sorted alphabetically. + +Other examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Dirs will appear first, then ruby and php. Swap files, bak files and vim + backup files will appear last with everything else preceding them. + +------------------------------------------------------------------------------ + *'NERDTreeStatusline'* +Values: Any valid statusline setting. +Default: %{b:NERDTreeRoot.path.strForOS(0)} + +Tells the script what to use as the |'statusline'| setting for NERD tree +windows. + +Note that the statusline is set using |:let-&| not |:set| so escaping spaces +isn't necessary. + +Setting this option to -1 will will deactivate it so that your global +statusline setting is used instead. + +------------------------------------------------------------------------------ + *'NERDTreeWinPos'* +Values: "left" or "right" +Default: "left". + +This option is used to determine where NERD tree window is placed on the +screen. + +This option makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERD tree on the right. + +------------------------------------------------------------------------------ + *'NERDTreeWinSize'* +Values: a positive integer. +Default: 31. + +This option is used to change the size of the NERD tree when it is loaded. + +------------------------------------------------------------------------------ + *'NERDTreeMinimalUI'* +Values: 0 or 1 +Default: 0 + +This options disables the 'Bookmarks' label 'Press ? for help' text. Use one +of the following lines to set this option: > + let NERDTreeMinimalUI=0 + let NERDTreeMinimalUI=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeDirArrows'* +Values: 0 or 1 +Default: 0. + +This option is used to change the default look of directory nodes displayed in +the tree. When set to 0 it shows old-school bars (|), + and ~ chars. If set to +1 it shows right and down arrows. Use one of the follow lines to set this +option: > + let NERDTreeDirArrows=0 + let NERDTreeDirArrows=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeCascadeOpenSingleChildDir'* +Values: 0 or 1 +Default: 1. + +When opening dir nodes, this option tells NERDTree to recursively open dirs +that have only one child which is also a dir. NERDTree will stop when it finds +a dir that contains anything but another single dir. This option also causes +the |NERDTree-x| mapping to close dirs in the same manner. This option may be +useful for Java projects. Use one of the follow lines to set this option: > + let NERDTreeCascadeOpenSingleChildDir=0 + let NERDTreeCascadeOpenSingleChildDir=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeAutoDeleteBuffer'* +Values: 0 or 1 +Default: 0. + +When using a context menu to delete or rename a file you may also want to delete +the buffer which is no more valid. If the option is not set you will see a +confirmation if you really want to delete an old buffer. If you always press 'y' +then it worths to set this option to 1. Use one of the follow lines to set this +option: > + let NERDTreeAutoDeleteBuffer=0 + let NERDTreeAutoDeleteBuffer=1 +< + +============================================================================== +4. The NERD tree API *NERDTreeAPI* + +The NERD tree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERD tree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + "override" - if 1 then this new mapping will override whatever previous + mapping was defined for the key/scope combo. Useful for overriding the + default mappings. + + Additionally, a "scope" argument may be supplied. This constrains the + mapping so that it is only activated if the cursor is on a certain object. + That object is then passed into the handling method. Possible values are: + "FileNode" - a file node + "DirNode" - a directory node + "Node" - a file or directory node + "Bookmark" - A bookmark + "all" - the keymap is not constrained to any scope (default). When + thei is used, the handling function is not passed any arguments. + + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'foo', + \ 'callback': 'NERDTreeCDHandler', + \ 'quickhelpText': 'echo full path of current node', + \ 'scope': 'DirNode' }) + + function! NERDTreeCDHandler(dirnode) + call a:dirnode.changeToDir() + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (redundant) mapping on 'foo' which changes vim's CWD to that of + the current dir node. Note this mapping will only fire when the cursor is + on a directory 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. + +------------------------------------------------------------------------------ +4.3 NERDTreeAddPathFilter(callback) *NERDTreeAddPathFilter()* + +Path filters are essentially a more powerful version of |NERDTreeIgnore|. +If the simple regex matching in |NERDTreeIgnore| is not enough then use +|NERDTreeAddPathFilter()| to add a callback function that paths will be +checked against when the decision to ignore them is made. Example > + + call NERDTreeAddPathFilter('MyFilter') + + function! MyFilter(params) + "params is a dict containing keys: 'nerdtree' and 'path' which are + "g:NERDTree and g:NERDTreePath objects + + "return 1 to ignore params['path'] or 0 otherwise + endfunction +< + +------------------------------------------------------------------------------ +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* + +Next + - add 'scope' argument to the key map API + - add NERDTreeCustomIgnoreFilter hook - needs doc + - add magic [[dir]] and [[file]] flags to NERDTreeIgnore + - add support for custom path filters. See :help NERDTreeAddPathFilter() + +4.2.0 + - Add NERDTreeDirArrows option to make the UI use pretty arrow chars + instead of the old +~| chars to define the tree structure (sickill) + - shift the syntax highlighting out into its own syntax file (gnap) + - add some mac specific options to the filesystem menu - for macvim + only (andersonfreitas) + - Add NERDTreeMinimalUI option to remove some non functional parts of the + nerdtree ui (camthompson) + - tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the + new behaviour (benjamingeiger) + - if no name is given to :Bookmark, make it default to the name of the + target file/dir (minyoung) + - use 'file' completion when doing copying, create, and move + operations (EvanDotPro) + - lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly + Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!) + +4.1.0 + features: + - NERDTreeFind to reveal the node for the current buffer in the tree, + see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by + Doug McInnes) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan + Ritter and Rémi Prévost. + - truncate the root node if wider than the tree window. Thanks to Victor + Gonzalez. + + bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, + jfilip1024, and Chris Chambers + +4.0.0 + - add a new programmable menu system (see :help NERDTreeMenu). + - add new APIs to add menus/menu-items to the menu system as well as + custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). + - removed the old API functions + - added a mapping to maximize/restore the size of nerd tree window, thanks + to Guillaume Duranceau for the patch. See :help NERDTree-A for details. + + - fix a bug where secondary nerd trees (netrw hijacked trees) and + NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. + - fix a bug where the script ignored directories whose name ended in a dot, + thanks to Aggelos Orfanakos for the patch. + - fix a bug when using the x mapping on the tree root, thanks to Bryan + Venteicher for the patch. + - fix a bug where the cursor position/window size of the nerd tree buffer + wasnt being stored on closing the window, thanks to Richard Hart. + - fix a bug where NERDTreeMirror would mirror the wrong tree + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + " (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree would fail if was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring + +============================================================================== +7. Credits *NERDTreeCredits* + +Thanks to the following people for testing, bug reports, ideas etc. Without +you I probably would have got bored of the hacking the NERD tree and +just downloaded pr0n instead. + + Tim Carey-Smith (halorgium) + Vigil + Nick Brettell + Thomas Scott Urban + Terrance Cohen + Yegappan Lakshmanan + Jason Mills + Michael Geddes (frogonwheels) + Yu Jun + Michael Madsen + AOYAMA Shotaro + Zhang Weiwu + Niels Aan de Brugh + Olivier Yiptong + Zhang Shuhan + Cory Echols + Piotr Czachur + Yuan Jiang + Matan Nassau + Maxim Kim + Charlton Wang + Matt Wozniski (godlygeek) + knekk + Sean Chou + Ryan Penn + Simon Peter Nicholls + Michael Foobar + Tomasz Chomiuk + Denis Pokataev + Tim Pope (tpope) + James Kanze + James Vega (jamessan) + Frederic Chanal (nach) + Alf Mikula + Lucas S. Buchala + Curtis Harvey + Guillaume Duranceau + Richard Hart (hates) + Doug McInnes + Stefan Ritter + Rémi Prévost + Victor Gonzalez + Stephan Baumeister + Ricky + jfilip1024 + Chris Chambers + Vitaly Bogdanov + Patrick O'Loughlin (paddyoloughlin) + Cam Thompson (camthompson) + Marcin Kulik (sickill) + Steve DeWald (sdewald) + Ivan Necas (iNecas) + George Ang (gnap) + Evan Coury (EvanDotPro) + Andrew Radev (AndrewRadev) + Matt Gauger (mathias) + Scott Stevenson (scottstvnsn) + Anderson Freitas (andersonfreitas) + Kamil K. Lemański (kml) + Yehuda Katz (wycats) + Min-Young Wu (minyoung) + Benjamin Geiger (benjamingeiger) + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/bookmark.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/bookmark.vim new file mode 100644 index 0000000..8a94b25 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/bookmark.vim @@ -0,0 +1,319 @@ +"CLASS: Bookmark +"============================================================ +let s:Bookmark = {} +let g:NERDTreeBookmark = s:Bookmark + +" FUNCTION: Bookmark.activate() {{{1 +function! s:Bookmark.activate(...) + call self.open(a:0 ? a:1 : {}) +endfunction + +" FUNCTION: Bookmark.AddBookmark(name, path) {{{1 +" 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)) + if g:NERDTreeBookmarksSort ==# 1 + call s:Bookmark.Sort() + endif +endfunction + +" FUNCTION: Bookmark.Bookmarks() {{{1 +" 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) {{{1 +" 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) {{{1 +" 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() {{{1 +" 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) {{{1 +" Class method to read all bookmarks from the bookmarks file initialize +" 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, g:NERDTreePath.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 nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") + endif + endif + if g:NERDTreeBookmarksSort ==# 1 + call s:Bookmark.Sort() + endif + endif +endfunction + +" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1 +" Compare these two bookmarks for sorting purposes +function! s:Bookmark.compareTo(otherbookmark) + return a:otherbookmark.name < self.name +endfunction +" FUNCTION: Bookmark.ClearAll() {{{1 +" 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() {{{1 +" 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) {{{1 +" 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 ? g:NERDTreeDirNode.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) {{{1 +" 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() {{{1 +" 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() {{{1 +" 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() {{{1 +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) {{{1 +" 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.open([options]) {{{1 +"Args: +"A dictionary containing the following keys (all optional): +" 'where': Specifies whether the node should be opened in new split/tab or in +" the previous window. Can be either 'v' (vertical split), 'h' +" (horizontal split), 't' (new tab) or 'p' (previous window). +" 'reuse': if a window is displaying the file then jump the cursor there +" 'keepopen': dont close the tree window +" 'stay': open the file, but keep the cursor in the tree win +" +function! s:Bookmark.open(...) + let opts = a:0 ? a:1 : {} + + if self.path.isDirectory && !has_key(opts, 'where') + call self.toRoot() + else + let opener = g:NERDTreeOpener.New(self.path, opts) + call opener.open(self) + endif +endfunction + +" FUNCTION: Bookmark.openInNewTab(options) {{{1 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.openInNewTab(options) + call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead') + call self.open(a:options) +endfunction + +" FUNCTION: Bookmark.setPath(path) {{{1 +" makes this bookmark point to the given path +function! s:Bookmark.setPath(path) + let self.path = a:path +endfunction + +" FUNCTION: Bookmark.Sort() {{{1 +" Class method that sorts all bookmarks +function! s:Bookmark.Sort() + let CompareFunc = function("nerdtree#compareBookmarks") + call sort(s:Bookmark.Bookmarks(), CompareFunc) +endfunction + +" FUNCTION: Bookmark.str() {{{1 +" Get the string that should be rendered in the view for this bookmark +function! s:Bookmark.str() + let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 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() {{{1 +" 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 = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path) + endtry + call targetNode.makeRoot() + call b:NERDTree.render() + call targetNode.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: Bookmark.ToRoot(name) {{{1 +" 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() {{{1 +function! s:Bookmark.validate() + if self.path.exists() + return 1 + else + call s:Bookmark.CacheBookmarks(1) + call b:NERDTree.render() + call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.") + return 0 + endif +endfunction + +" FUNCTION: Bookmark.Write() {{{1 +" 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 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/creator.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/creator.vim new file mode 100644 index 0000000..2d6a5c2 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/creator.vim @@ -0,0 +1,362 @@ +"CLASS: Creator +"Creates primary/secondary/mirror nerdtree windows. Sets up all the window and +"buffer options and key mappings etc. +"============================================================ +let s:Creator = {} +let g:NERDTreeCreator = s:Creator + +"FUNCTION: s:Creator._bindMappings() {{{1 +function! s:Creator._bindMappings() + "make do the same as the activate node mapping + nnoremap :call nerdtree#ui_glue#invokeKeyMap(g:NERDTreeMapActivateNode) + + call g:NERDTreeKeyMap.BindAll() + + command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#ui_glue#openBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('') + command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() call b:NERDTree.render() + command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) call b:NERDTree.render() + command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write() +endfunction + +"FUNCTION: s:Creator._broadcastInitEvent() {{{1 +function! s:Creator._broadcastInitEvent() + silent doautocmd User NERDTreeInit +endfunction + +" FUNCTION: s:Creator.BufNamePrefix() {{{2 +function! s:Creator.BufNamePrefix() + return 'NERD_tree_' +endfunction + +"FUNCTION: s:Creator.CreatePrimary(a:name) {{{1 +function! s:Creator.CreatePrimary(name) + let creator = s:Creator.New() + call creator.createPrimary(a:name) +endfunction + +"FUNCTION: s:Creator.createPrimary(a:name) {{{1 +"name: the name of a bookmark or a directory +function! s:Creator.createPrimary(name) + let path = self._pathForString(a:name) + + "abort if exception was thrown (bookmark/dir doesn't exist) + if empty(path) + return + 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 g:NERDTree.ExistsForTab() + if g:NERDTree.IsOpen() + call g:NERDTree.Close() + endif + unlet t:NERDTreeBufName + endif + + call self._createTreeWin() + call self._createNERDTree(path) + let b:NERDTreeType = "primary" + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + + call b:NERDTree.render() + call b:NERDTreeRoot.putCursorHere(0, 0) + + call self._broadcastInitEvent() +endfunction + +"FUNCTION: s:Creator.CreateSecondary(dir) {{{1 +function! s:Creator.CreateSecondary(dir) + let creator = s:Creator.New() + call creator.createSecondary(a:dir) +endfunction + +"FUNCTION: s:Creator.createSecondary(dir) {{{1 +function! s:Creator.createSecondary(dir) + try + let path = g:NERDTreePath.New(a:dir) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#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 " . self._nextBufferName() + + let b:NERDTreePreviousBuf = bufnr(previousBuf) + call self._createNERDTree(path) + call self._setCommonBufOptions() + let b:NERDTreeType = "secondary" + + call b:NERDTree.render() + + call self._broadcastInitEvent() +endfunction + +" FUNCTION: s:Creator._createNERDTree(path) {{{1 +function! s:Creator._createNERDTree(path) + let b:NERDTree = g:NERDTree.New(a:path) + "TODO: This is kept for compatability only since many things use + "b:NERDTreeRoot instead of the new NERDTree.root + "Remove this one day + let b:NERDTreeRoot = b:NERDTree.root + + call b:NERDTree.root.open() +endfunction + +" FUNCTION: s:Creator.CreateMirror() {{{1 +function! s:Creator.CreateMirror() + let creator = s:Creator.New() + call creator.createMirror() +endfunction + +" FUNCTION: s:Creator.createMirror() {{{1 +function! s:Creator.createMirror() + "get the names off all the nerd tree buffers + let treeBufNames = [] + for i in range(1, tabpagenr("$")) + let nextName = self._tabpagevar(i, 'NERDTreeBufName') + if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName) + call add(treeBufNames, nextName) + endif + endfor + let treeBufNames = self._uniq(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 nerdtree#echo("No trees to mirror") + return + endif + + if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen() + call g:NERDTree.Close() + endif + + let t:NERDTreeBufName = bufferName + call self._createTreeWin() + exec 'buffer ' . bufferName + if !&hidden + call b:NERDTree.render() + endif +endfunction + +"FUNCTION: s:Creator._createTreeWin() {{{1 +"Inits the NERD tree window. ie. opens it, sizes it, sets all the local +"options etc +function! s:Creator._createTreeWin() + "create the nerd tree window + let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright " + let splitSize = g:NERDTreeWinSize + + if !exists('t:NERDTreeBufName') + let t:NERDTreeBufName = self._nextBufferName() + silent! exec splitLocation . 'vertical ' . splitSize . ' new' + silent! exec "edit " . t:NERDTreeBufName + else + silent! exec splitLocation . 'vertical ' . splitSize . ' split' + silent! exec "buffer " . t:NERDTreeBufName + endif + + setlocal winfixwidth + call self._setCommonBufOptions() +endfunction + +"FUNCTION: s:Creator.New() {{{1 +function! s:Creator.New() + let newCreator = copy(self) + return newCreator +endfunction + +" FUNCTION: s:Creator._nextBufferName() {{{2 +" returns the buffer name for the next nerd tree +function! s:Creator._nextBufferName() + let name = s:Creator.BufNamePrefix() . self._nextBufferNumber() + return name +endfunction + +" FUNCTION: s:Creator._nextBufferNumber() {{{2 +" the number to add to the nerd tree buffer name to make the buf name unique +function! s:Creator._nextBufferNumber() + if !exists("s:Creator._NextBufNum") + let s:Creator._NextBufNum = 1 + else + let s:Creator._NextBufNum += 1 + endif + + return s:Creator._NextBufNum +endfunction + +"FUNCTION: s:Creator._pathForString(str) {{{1 +"find a bookmark or adirectory for the given string +function! s:Creator._pathForString(str) + let path = {} + if g:NERDTreeBookmark.BookmarkExistsFor(a:str) + let path = g:NERDTreeBookmark.BookmarkFor(a:str).path + else + let dir = a:str ==# '' ? getcwd() : a:str + + "hack to get an absolute path if a relative path is given + if dir =~# '^\.' + let dir = getcwd() . g:NERDTreePath.Slash() . dir + endif + let dir = g:NERDTreePath.Resolve(dir) + + try + let path = g:NERDTreePath.New(dir) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo("No bookmark or directory found for: " . a:str) + return + endtry + endif + if !path.isDirectory + let path = path.getParent() + endif + + return path +endfunction + +"FUNCTION: s:Creator._setCommonBufOptions() {{{1 +function! s:Creator._setCommonBufOptions() + "throwaway buffer options + setlocal noswapfile + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal nowrap + setlocal foldcolumn=0 + setlocal foldmethod=manual + setlocal nofoldenable + setlocal nobuflisted + setlocal nospell + if g:NERDTreeShowLineNumbers + setlocal nu + else + setlocal nonu + if v:version >= 703 + setlocal nornu + endif + endif + + iabc + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call self._setupStatusline() + + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + call self._bindMappings() + setlocal filetype=nerdtree +endfunction + +"FUNCTION: s:Creator._setupStatusline() {{{1 +function! s:Creator._setupStatusline() + if g:NERDTreeStatusline != -1 + let &l:statusline = g:NERDTreeStatusline + endif +endfunction + +" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1 +function! s:Creator._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:Creator.TogglePrimary(dir) {{{1 +function! s:Creator.TogglePrimary(dir) + let creator = s:Creator.New() + call creator.togglePrimary(a:dir) +endfunction + +"FUNCTION: s:Creator.togglePrimary(dir) {{{1 +"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:Creator.togglePrimary(dir) + if g:NERDTree.ExistsForTab() + if !g:NERDTree.IsOpen() + call self._createTreeWin() + if !&hidden + call b:NERDTree.render() + endif + call b:NERDTree.ui.restoreScreenState() + else + call g:NERDTree.Close() + endif + else + call self.createPrimary(a:dir) + endif +endfunction + +" Function: s:Creator._uniq(list) {{{1 +" returns a:list without duplicates +function! s:Creator._uniq(list) + let uniqlist = [] + for elem in a:list + if index(uniqlist, elem) ==# -1 + let uniqlist += [elem] + endif + endfor + return uniqlist +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/event.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/event.vim new file mode 100644 index 0000000..964e8ff --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/event.vim @@ -0,0 +1,13 @@ +"CLASS: Event +"============================================================ +let s:Event = {} +let g:NERDTreeEvent = s:Event + +function! s:Event.New(nerdtree, subject, action, params) abort + let newObj = copy(self) + let newObj.nerdtree = a:nerdtree + let newObj.subject = a:subject + let newObj.action = a:action + let newObj.params = a:params + return newObj +endfunction diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/flag_set.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/flag_set.vim new file mode 100644 index 0000000..9d8d335 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/flag_set.vim @@ -0,0 +1,56 @@ +"CLASS: FlagSet +"============================================================ +let s:FlagSet = {} +let g:NERDTreeFlagSet = s:FlagSet + +"FUNCTION: FlagSet.addFlag(scope, flag) {{{1 +function! s:FlagSet.addFlag(scope, flag) + let flags = self._flagsForScope(a:scope) + if index(flags, a:flag) == -1 + call add(flags, a:flag) + end +endfunction + +"FUNCTION: FlagSet.clearFlags(scope) {{{1 +function! s:FlagSet.clearFlags(scope) + let self._flags[a:scope] = [] +endfunction + +"FUNCTION: FlagSet._flagsForScope(scope) {{{1 +function! s:FlagSet._flagsForScope(scope) + if !has_key(self._flags, a:scope) + let self._flags[a:scope] = [] + endif + return self._flags[a:scope] +endfunction + +"FUNCTION: FlagSet.New() {{{1 +function! s:FlagSet.New() + let newObj = copy(self) + let newObj._flags = {} + return newObj +endfunction + +"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1 +function! s:FlagSet.removeFlag(scope, flag) + let flags = self._flagsForScope(a:scope) + + let i = index(flags, a:flag) + if i >= 0 + call remove(flags, i) + endif +endfunction + +"FUNCTION: FlagSet.renderToString() {{{1 +function! s:FlagSet.renderToString() + let flagstring = "" + for i in values(self._flags) + let flagstring .= join(i) + endfor + + if len(flagstring) == 0 + return "" + endif + + return '[' . flagstring . ']' +endfunction diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/key_map.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/key_map.vim new file mode 100644 index 0000000..2411406 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/key_map.vim @@ -0,0 +1,159 @@ +"CLASS: KeyMap +"============================================================ +let s:KeyMap = {} +let g:NERDTreeKeyMap = s:KeyMap + +"FUNCTION: KeyMap.All() {{{1 +function! s:KeyMap.All() + if !exists("s:keyMaps") + let s:keyMaps = [] + endif + return s:keyMaps +endfunction + +"FUNCTION: KeyMap.FindFor(key, scope) {{{1 +function! s:KeyMap.FindFor(key, scope) + for i in s:KeyMap.All() + if i.key ==# a:key && i.scope ==# a:scope + return i + endif + endfor + return {} +endfunction + +"FUNCTION: KeyMap.BindAll() {{{1 +function! s:KeyMap.BindAll() + for i in s:KeyMap.All() + call i.bind() + endfor +endfunction + +"FUNCTION: KeyMap.bind() {{{1 +function! s:KeyMap.bind() + " If the key sequence we're trying to map contains any '<>' notation, we + " must replace each of the '<' characters with '' to ensure the string + " is not translated into its corresponding keycode during the later part + " of the map command below + " :he <> + let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)' + if self.key =~# specialNotationRegex + let keymapInvokeString = substitute(self.key, specialNotationRegex, '\1', 'g') + else + let keymapInvokeString = self.key + endif + + let premap = self.key == "" ? " " : " " + + exec 'nnoremap '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")' +endfunction + +"FUNCTION: KeyMap.Remove(key, scope) {{{1 +function! s:KeyMap.Remove(key, scope) + let maps = s:KeyMap.All() + for i in range(len(maps)) + if maps[i].key ==# a:key && maps[i].scope ==# a:scope + return remove(maps, i) + endif + endfor +endfunction + +"FUNCTION: KeyMap.invoke() {{{1 +"Call the KeyMaps callback function +function! s:KeyMap.invoke(...) + let Callback = function(self.callback) + if a:0 + call Callback(a:1) + else + call Callback() + endif +endfunction + +"FUNCTION: KeyMap.Invoke() {{{1 +"Find a keymapping for a:key and the current scope invoke it. +" +"Scope is determined as follows: +" * if the cursor is on a dir node then "DirNode" +" * if the cursor is on a file node then "FileNode" +" * if the cursor is on a bookmark then "Bookmark" +" +"If a keymap has the scope of "all" then it will be called if no other keymap +"is found for a:key and the scope. +function! s:KeyMap.Invoke(key) + + "required because clicking the command window below another window still + "invokes the mapping - but changes the window cursor + "is in first + " + "TODO: remove this check when the vim bug is fixed + if !g:NERDTree.ExistsForBuf() + return {} + endif + + let node = g:NERDTreeFileNode.GetSelected() + if !empty(node) + + "try file node + if !node.path.isDirectory + let km = s:KeyMap.FindFor(a:key, "FileNode") + if !empty(km) + return km.invoke(node) + endif + endif + + "try dir node + if node.path.isDirectory + let km = s:KeyMap.FindFor(a:key, "DirNode") + if !empty(km) + return km.invoke(node) + endif + endif + + "try generic node + let km = s:KeyMap.FindFor(a:key, "Node") + if !empty(km) + return km.invoke(node) + endif + + endif + + "try bookmark + let bm = g:NERDTreeBookmark.GetSelected() + if !empty(bm) + let km = s:KeyMap.FindFor(a:key, "Bookmark") + if !empty(km) + return km.invoke(bm) + endif + endif + + "try all + let km = s:KeyMap.FindFor(a:key, "all") + if !empty(km) + return km.invoke() + endif +endfunction + +"FUNCTION: KeyMap.Create(options) {{{1 +function! s:KeyMap.Create(options) + let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options)) + + "dont override other mappings unless the 'override' option is given + if get(opts, 'override', 0) == 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope'])) + return + end + + let newKeyMap = copy(self) + let newKeyMap.key = opts['key'] + let newKeyMap.quickhelpText = opts['quickhelpText'] + let newKeyMap.callback = opts['callback'] + let newKeyMap.scope = opts['scope'] + + call s:KeyMap.Add(newKeyMap) +endfunction + +"FUNCTION: KeyMap.Add(keymap) {{{1 +function! s:KeyMap.Add(keymap) + call s:KeyMap.Remove(a:keymap.key, a:keymap.scope) + call add(s:KeyMap.All(), a:keymap) +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_controller.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_controller.vim new file mode 100644 index 0000000..ae0ee84 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_controller.vim @@ -0,0 +1,180 @@ +"CLASS: MenuController +"============================================================ +let s:MenuController = {} +let g:NERDTreeMenuController = s:MenuController + +"FUNCTION: MenuController.New(menuItems) {{{1 +"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() {{{1 +"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() {{{1 +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) {{{1 +"get the MenuItem that is currently selected +function! s:MenuController._current() + return self.menuItems[self.selection] +endfunction + +"FUNCTION: MenuController._handleKeypress(key) {{{1 +"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) {{{1 +"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) {{{1 +"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() {{{1 +"sets &cmdheight to whatever is needed to display the menu +function! s:MenuController._setCmdheight() + let &cmdheight = len(self.menuItems) + 3 +endfunction + +"FUNCTION: MenuController._saveOptions() {{{1 +"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() {{{1 +"restore the options we saved in _saveOptions() +function! s:MenuController._restoreOptions() + let &cmdheight = self._oldCmdheight + let &lazyredraw = self._oldLazyredraw +endfunction + +"FUNCTION: MenuController._cursorDown() {{{1 +"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() {{{1 +"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 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_item.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_item.vim new file mode 100644 index 0000000..92c1bbb --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/menu_item.vim @@ -0,0 +1,114 @@ +"CLASS: MenuItem +"============================================================ +let s:MenuItem = {} +let g:NERDTreeMenuItem = s:MenuItem + +"FUNCTION: MenuItem.All() {{{1 +"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() {{{1 +"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) {{{1 +"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) {{{1 +"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) {{{1 +"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() {{{1 +"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() {{{1 +"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 = g:NERDTreeMenuController.New(self.children) + call mc.showMenu() + else + if self.callback != -1 + call {self.callback}() + endif + endif +endfunction + +"FUNCTION: MenuItem.isSeparator() {{{1 +"return 1 if this menuitem is a separator +function! s:MenuItem.isSeparator() + return self.callback == -1 && self.children == [] +endfunction + +"FUNCTION: MenuItem.isSubmenu() {{{1 +"return 1 if this menuitem is a submenu +function! s:MenuItem.isSubmenu() + return self.callback == -1 && !empty(self.children) +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/nerdtree.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/nerdtree.vim new file mode 100644 index 0000000..55f3dd7 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/nerdtree.vim @@ -0,0 +1,137 @@ +"CLASS: NERDTree +"============================================================ +let s:NERDTree = {} +let g:NERDTree = s:NERDTree + +"FUNCTION: s:NERDTree.AddPathFilter() {{{1 +function! s:NERDTree.AddPathFilter(callback) + call add(s:NERDTree.PathFilters(), a:callback) +endfunction + +"FUNCTION: s:NERDTree.Close() {{{1 +"Closes the primary NERD tree window for this tab +function! s:NERDTree.Close() + if !s:NERDTree.IsOpen() + return + endif + + if winnr("$") != 1 + if winnr() == s:NERDTree.GetWinNum() + call nerdtree#exec("wincmd p") + let bufnr = bufnr("") + call nerdtree#exec("wincmd p") + else + let bufnr = bufnr("") + endif + + call nerdtree#exec(s:NERDTree.GetWinNum() . " wincmd w") + close + call nerdtree#exec(bufwinnr(bufnr) . " wincmd w") + else + close + endif +endfunction + +"FUNCTION: s:NERDTree.CloseIfQuitOnOpen() {{{1 +"Closes the NERD tree window if the close on open option is set +function! s:NERDTree.CloseIfQuitOnOpen() + if g:NERDTreeQuitOnOpen && s:NERDTree.IsOpen() + call s:NERDTree.Close() + endif +endfunction + +"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1 +"Places the cursor at the top of the bookmarks table +function! s:NERDTree.CursorToBookmarkTable() + if !b:NERDTreeShowBookmarks + throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active" + endif + + if g:NERDTreeMinimalUI + return cursor(1, 2) + endif + + let rootNodeLine = b:NERDTree.ui.getRootLineNum() + + let line = 1 + while getline(line) !~# '^>-\+Bookmarks-\+$' + let line = line + 1 + if line >= rootNodeLine + throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table" + endif + endwhile + call cursor(line, 2) +endfunction + +"FUNCTION: s:NERDTree.CursorToTreeWin(){{{1 +"Places the cursor in the nerd tree window +function! s:NERDTree.CursorToTreeWin() + call g:NERDTree.MustBeOpen() + call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w") +endfunction + +" Function: s:NERDTree.ExistsForBuffer() {{{1 +" Returns 1 if a nerd tree root exists in the current buffer +function! s:NERDTree.ExistsForBuf() + return exists("b:NERDTreeRoot") +endfunction + +" Function: s:NERDTree.ExistsForTab() {{{1 +" Returns 1 if a nerd tree root exists in the current tab +function! s:NERDTree.ExistsForTab() + return exists("t:NERDTreeBufName") +endfunction + +function! s:NERDTree.ForCurrentBuf() + if s:NERDTree.ExistsForBuf() + return b:NERDTree + else + return {} + endif +endfunction + +"FUNCTION: s:NERDTree.GetWinNum() {{{1 +"gets the nerd tree window number for this tab +function! s:NERDTree.GetWinNum() + if exists("t:NERDTreeBufName") + return bufwinnr(t:NERDTreeBufName) + else + return -1 + endif +endfunction + +"FUNCTION: s:NERDTree.IsOpen() {{{1 +function! s:NERDTree.IsOpen() + return s:NERDTree.GetWinNum() != -1 +endfunction + +"FUNCTION: s:NERDTree.MustBeOpen() {{{1 +function! s:NERDTree.MustBeOpen() + if !s:NERDTree.IsOpen() + throw "NERDTree.TreeNotOpen" + endif +endfunction + +"FUNCTION: s:NERDTree.New() {{{1 +function! s:NERDTree.New(path) + let newObj = copy(self) + let newObj.ui = g:NERDTreeUI.New(newObj) + let newObj.root = g:NERDTreeDirNode.New(a:path) + + return newObj +endfunction + +"FUNCTION: s:NERDTree.PathFilters() {{{1 +function! s:NERDTree.PathFilters() + if !exists('s:NERDTree._PathFilters') + let s:NERDTree._PathFilters = [] + endif + return s:NERDTree._PathFilters +endfunction + + +"FUNCTION: s:NERDTree.render() {{{1 +"A convenience function - since this is called often +function! s:NERDTree.render() + call self.ui.render() +endfunction diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/notifier.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/notifier.vim new file mode 100644 index 0000000..b445f8a --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/notifier.vim @@ -0,0 +1,35 @@ +"CLASS: Notifier +"============================================================ +let s:Notifier = {} + +function! s:Notifier.AddListener(event, funcname) + let listeners = s:Notifier.GetListenersForEvent(a:event) + if listeners == [] + let listenersMap = s:Notifier.GetListenersMap() + let listenersMap[a:event] = listeners + endif + call add(listeners, a:funcname) +endfunction + +function! s:Notifier.NotifyListeners(event, path, params) + let event = g:NERDTreeEvent.New(b:NERDTree, a:path, a:event, a:params) + + for listener in s:Notifier.GetListenersForEvent(a:event) + call {listener}(event) + endfor +endfunction + +function! s:Notifier.GetListenersMap() + if !exists("s:refreshListenersMap") + let s:refreshListenersMap = {} + endif + return s:refreshListenersMap +endfunction + +function! s:Notifier.GetListenersForEvent(name) + let listenersMap = s:Notifier.GetListenersMap() + return get(listenersMap, a:name, []) +endfunction + +let g:NERDTreePathNotifier = deepcopy(s:Notifier) + diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/opener.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/opener.vim new file mode 100644 index 0000000..3a6b392 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/opener.vim @@ -0,0 +1,352 @@ +"CLASS: Opener +"============================================================ +let s:Opener = {} +let g:NERDTreeOpener = s:Opener + +"FUNCTION: s:Opener._bufInWindows(bnum){{{1 +"[[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:Opener._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: Opener._checkToCloseTree(newtab) {{{1 +"Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see +"if the tree should be closed now. +" +"Args: +"a:newtab - boolean. If set, only close the tree now if we are opening the +"target in a new tab. This is needed because we have to close tree before we +"leave the tab +function! s:Opener._checkToCloseTree(newtab) + if self._keepopen + return + endif + + if (a:newtab && self._where == 't') || !a:newtab + call g:NERDTree.CloseIfQuitOnOpen() + endif +endfunction + + +"FUNCTION: s:Opener._firstUsableWindow(){{{1 +"find the window number of the first normal window +function! s:Opener._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: Opener._gotoTargetWin() {{{1 +function! s:Opener._gotoTargetWin() + if b:NERDTreeType ==# "secondary" + if self._where == 'v' + vsplit + elseif self._where == 'h' + split + elseif self._where == 't' + tabnew + endif + else + call self._checkToCloseTree(1) + + if self._where == 'v' + call self._newVSplit() + elseif self._where == 'h' + call self._newSplit() + elseif self._where == 't' + tabnew + elseif self._where == 'p' + call self._previousWindow() + endif + + call self._checkToCloseTree(0) + endif +endfunction + +"FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1 +"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:Opener._isWindowUsable(winnumber) + "gotta split if theres only one window (i.e. the NERD tree) + if winnr("$") ==# 1 + return 0 + endif + + let oldwinnr = winnr() + call nerdtree#exec(a:winnumber . "wincmd p") + let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') + let modified = &modified + call nerdtree#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 || self._bufInWindows(winbufnr(a:winnumber)) >= 2 +endfunction + +"FUNCTION: Opener.New(path, opts) {{{1 +"Args: +" +"a:path: The path object that is to be opened. +" +"a:opts: +" +"A dictionary containing the following keys (all optional): +" 'where': Specifies whether the node should be opened in new split/tab or in +" the previous window. Can be either 'v' or 'h' or 't' (for open in +" new tab) +" 'reuse': if a window is displaying the file then jump the cursor there. Can +" 'all', 'currenttab' or empty to not reuse. +" 'keepopen': dont close the tree window +" 'stay': open the file, but keep the cursor in the tree win +function! s:Opener.New(path, opts) + let newObj = copy(self) + + let newObj._path = a:path + let newObj._stay = nerdtree#has_opt(a:opts, 'stay') + + if has_key(a:opts, 'reuse') + let newObj._reuse = a:opts['reuse'] + else + let newObj._reuse = '' + endif + + let newObj._keepopen = nerdtree#has_opt(a:opts, 'keepopen') + let newObj._where = has_key(a:opts, 'where') ? a:opts['where'] : '' + let newObj._treetype = b:NERDTreeType + call newObj._saveCursorPos() + + return newObj +endfunction + +"FUNCTION: Opener._newSplit() {{{1 +function! s:Opener._newSplit() + " 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 nerdtree#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 ") + catch /^Vim\%((\a\+)\)\=:E37/ + call g:NERDTree.CursorToTreeWin() + 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 nerdtree#exec(there) + exec("silent ". splitMode ." resize ". size) + call nerdtree#exec('wincmd p') + endif + + " Restore splitmode settings + let &splitbelow=savesplitbelow + let &splitright=savesplitright +endfunction + +"FUNCTION: Opener._newVSplit() {{{1 +function! s:Opener._newVSplit() + let winwidth = winwidth(".") + if winnr("$")==#1 + let winwidth = g:NERDTreeWinSize + endif + + call nerdtree#exec("wincmd p") + vnew + + "resize the nerd tree back to the original size + call g:NERDTree.CursorToTreeWin() + exec("silent vertical resize ". winwidth) + call nerdtree#exec('wincmd p') +endfunction + +"FUNCTION: Opener.open(target) {{{1 +function! s:Opener.open(target) + if self._path.isDirectory + call self._openDirectory(a:target) + else + call self._openFile() + endif +endfunction + +"FUNCTION: Opener._openFile() {{{1 +function! s:Opener._openFile() + if self._reuseWindow() + return + endif + + call self._gotoTargetWin() + + if self._treetype ==# "secondary" + call self._path.edit() + else + call self._path.edit() + + + if self._stay + call self._restoreCursorPos() + endif + endif +endfunction + +"FUNCTION: Opener._openDirectory(node) {{{1 +function! s:Opener._openDirectory(node) + if self._treetype ==# "secondary" + call self._gotoTargetWin() + call g:NERDTreeCreator.CreateSecondary(a:node.path.str()) + else + call self._gotoTargetWin() + if empty(self._where) + call a:node.makeRoot() + call b:NERDTree.render() + call a:node.putCursorHere(0, 0) + elseif self._where == 't' + call g:NERDTreeCreator.CreatePrimary(a:node.path.str()) + else + call g:NERDTreeCreator.CreateSecondary(a:node.path.str()) + endif + endif + + if self._stay + call self._restoreCursorPos() + endif +endfunction + +"FUNCTION: Opener._previousWindow() {{{1 +function! s:Opener._previousWindow() + if !self._isWindowUsable(winnr("#")) && self._firstUsableWindow() ==# -1 + call self._newSplit() + else + try + if !self._isWindowUsable(winnr("#")) + call nerdtree#exec(self._firstUsableWindow() . "wincmd w") + else + call nerdtree#exec('wincmd p') + endif + catch /^Vim\%((\a\+)\)\=:E37/ + call g:NERDTree.CursorToTreeWin() + throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified." + catch /^Vim\%((\a\+)\)\=:/ + echo v:exception + endtry + endif +endfunction + +"FUNCTION: Opener._restoreCursorPos(){{{1 +function! s:Opener._restoreCursorPos() + call nerdtree#exec('normal ' . self._tabnr . 'gt') + call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w') +endfunction + +"FUNCTION: Opener._reuseWindow(){{{1 +"put the cursor in the first window we find for this file +" +"return 1 if we were successful +function! s:Opener._reuseWindow() + if empty(self._reuse) + return 0 + endif + + "check the current tab for the window + let winnr = bufwinnr('^' . self._path.str() . '$') + if winnr != -1 + call nerdtree#exec(winnr . "wincmd w") + call self._checkToCloseTree(0) + return 1 + endif + + if self._reuse == 'currenttab' + return 0 + endif + + "check other tabs + let tabnr = self._path.tabnr() + if tabnr + call self._checkToCloseTree(1) + call nerdtree#exec('normal! ' . tabnr . 'gt') + let winnr = bufwinnr('^' . self._path.str() . '$') + call nerdtree#exec(winnr . "wincmd w") + return 1 + endif + + return 0 +endfunction + +"FUNCTION: Opener._saveCursorPos(){{{1 +function! s:Opener._saveCursorPos() + let self._bufnr = bufnr("") + let self._tabnr = tabpagenr() +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/path.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/path.vim new file mode 100644 index 0000000..48793eb --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/path.vim @@ -0,0 +1,761 @@ +"we need to use this number many times for sorting... so we calculate it only +"once here +let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*') + +"CLASS: Path +"============================================================ +let s:Path = {} +let g:NERDTreePath = s:Path + +"FUNCTION: Path.AbsolutePathFor(str) {{{1 +function! s:Path.AbsolutePathFor(str) + let prependCWD = 0 + if nerdtree#runningWindows() + let prependCWD = a:str !~# '^.:\(\\\|\/\)' && 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() {{{1 +function! s:Path.bookmarkNames() + if !exists("self._bookmarkNames") + call self.cacheDisplayString() + endif + return self._bookmarkNames +endfunction + +"FUNCTION: Path.cacheDisplayString() {{{1 +function! s:Path.cacheDisplayString() abort + let self.cachedDisplayString = self.flagSet.renderToString() + + let self.cachedDisplayString .= self.getLastPathComponent(1) + + if self.isExecutable + let self.cachedDisplayString = self.cachedDisplayString . '*' + endif + + let self._bookmarkNames = [] + for i in g:NERDTreeBookmark.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() {{{1 +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 nerdtree#echo("CWD is now: " . getcwd()) + catch + throw "NERDTree.PathChangeError: cannot change CWD to " . dir + endtry +endfunction + +"FUNCTION: Path.compareTo() {{{1 +" +"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 !g:NERDTreeSortHiddenFirst + let thisPath = substitute(thisPath, '^[._]', '', '') + let thatPath = substitute(thatPath, '^[._]', '', '') + endif + "if the sort sequences are the same then compare the paths + "alphabetically + let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath " + endif + + return " \\`\|\"#%&,?()\*^<>[]" +endfunction + +"FUNCTION: Path.getDir() {{{1 +" +"Returns this path if it is a directory, else this paths parent. +" +"Return: +"a Path object +function! s:Path.getDir() + if self.isDirectory + return self + else + return self.getParent() + endif +endfunction + +"FUNCTION: Path.getParent() {{{1 +" +"Returns a new path object for this paths parent +" +"Return: +"a new Path object +function! s:Path.getParent() + if nerdtree#runningWindows() + let path = self.drive . '\' . join(self.pathSegments[0:-2], '\') + else + let path = '/'. join(self.pathSegments[0:-2], '/') + endif + + return s:Path.New(path) +endfunction + +"FUNCTION: Path.getLastPathComponent(dirSlash) {{{1 +" +"Gets the last part of this path. +" +"Args: +"dirSlash: if 1 then a trailing slash will be added to the returned value for +"directory nodes. +function! s:Path.getLastPathComponent(dirSlash) + if empty(self.pathSegments) + return '' + endif + let toReturn = self.pathSegments[-1] + if a:dirSlash && self.isDirectory + let toReturn = toReturn . '/' + endif + return toReturn +endfunction + +"FUNCTION: Path.getSortOrderIndex() {{{1 +"returns the index of the pattern in g:NERDTreeSortOrder that this path matches +function! s:Path.getSortOrderIndex() + let i = 0 + while i < len(g:NERDTreeSortOrder) + if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i] + return i + endif + let i = i + 1 + endwhile + return s:NERDTreeSortStarIndex +endfunction + +"FUNCTION: Path.isUnixHiddenFile() {{{1 +"check for unix hidden files +function! s:Path.isUnixHiddenFile() + return self.getLastPathComponent(0) =~# '^\.' +endfunction + +"FUNCTION: Path.isUnixHiddenPath() {{{1 +"check for unix path with hidden components +function! s:Path.isUnixHiddenPath() + if self.getLastPathComponent(0) =~# '^\.' + return 1 + else + for segment in self.pathSegments + if segment =~# '^\.' + return 1 + endif + endfor + return 0 + endif +endfunction + +"FUNCTION: Path.ignore() {{{1 +"returns true if this path should be ignored +function! s:Path.ignore() + "filter out the user specified paths to ignore + if b:NERDTreeIgnoreEnabled + for i in g:NERDTreeIgnore + if self._ignorePatternMatches(i) + return 1 + endif + endfor + + for callback in g:NERDTree.PathFilters() + if {callback}({'path': self, 'nerdtree': b:NERDTree}) + return 1 + endif + endfor + endif + + "dont show hidden files unless instructed to + if b:NERDTreeShowHidden ==# 0 && self.isUnixHiddenFile() + return 1 + endif + + if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0 + return 1 + endif + + return 0 +endfunction + +"FUNCTION: Path._ignorePatternMatches(pattern) {{{1 +"returns true if this path matches the given ignore pattern +function! s:Path._ignorePatternMatches(pattern) + let pat = a:pattern + if strpart(pat,len(pat)-7) == '[[dir]]' + if !self.isDirectory + return 0 + endif + let pat = strpart(pat,0, len(pat)-7) + elseif strpart(pat,len(pat)-8) == '[[file]]' + if self.isDirectory + return 0 + endif + let pat = strpart(pat,0, len(pat)-8) + endif + + return self.getLastPathComponent(0) =~# pat +endfunction + +"FUNCTION: Path.isUnder(path) {{{1 +"return 1 if this path is somewhere under the given path in the filesystem. +" +"a:path should be a dir +function! s:Path.isUnder(path) + if a:path.isDirectory == 0 + return 0 + endif + + let this = self.str() + let that = a:path.str() + return stridx(this, that . s:Path.Slash()) == 0 +endfunction + +"FUNCTION: Path.JoinPathStrings(...) {{{1 +function! s:Path.JoinPathStrings(...) + let components = [] + for i in a:000 + let components = extend(components, split(i, '/')) + endfor + return '/' . join(components, '/') +endfunction + +"FUNCTION: Path.equals() {{{1 +" +"Determines whether 2 path objects are "equal". +"They are equal if the paths they represent are the same +" +"Args: +"path: the other path obj to compare this with +function! s:Path.equals(path) + return self.str() ==# a:path.str() +endfunction + +"FUNCTION: Path.New() {{{1 +"The Constructor for the Path object +function! s:Path.New(path) + let newPath = copy(self) + + call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path)) + + let newPath.cachedDisplayString = "" + let newPath.flagSet = g:NERDTreeFlagSet.New() + + return newPath +endfunction + +"FUNCTION: Path.Slash() {{{1 +"return the slash to use for the current OS +function! s:Path.Slash() + return nerdtree#runningWindows() ? '\' : '/' +endfunction + +"FUNCTION: Path.Resolve() {{{1 +"Invoke the vim resolve() function and return the result +"This is necessary because in some versions of vim resolve() removes trailing +"slashes while in other versions it doesn't. This always removes the trailing +"slash +function! s:Path.Resolve(path) + let tmp = resolve(a:path) + return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp +endfunction + +"FUNCTION: Path.readInfoFromDisk(fullpath) {{{1 +" +" +"Throws NERDTree.Path.InvalidArguments exception. +function! s:Path.readInfoFromDisk(fullpath) + call self.extractDriveLetter(a:fullpath) + + let fullpath = s:Path.WinToUnixPath(a:fullpath) + + if getftype(fullpath) ==# "fifo" + throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath + endif + + let self.pathSegments = split(fullpath, '/') + + let self.isReadOnly = 0 + if isdirectory(a:fullpath) + let self.isDirectory = 1 + elseif filereadable(a:fullpath) + let self.isDirectory = 0 + let self.isReadOnly = filewritable(a:fullpath) ==# 0 + else + throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath + endif + + let self.isExecutable = 0 + if !self.isDirectory + let self.isExecutable = getfperm(a:fullpath) =~# 'x' + endif + + "grab the last part of the path (minus the trailing slash) + let lastPathComponent = self.getLastPathComponent(0) + + "get the path to the new node with the parent dir fully resolved + let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent + + "if the last part of the path is a symlink then flag it as such + let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath) + if self.isSymLink + let self.symLinkDest = s:Path.Resolve(fullpath) + + "if the link is a dir then slap a / on the end of its dest + if isdirectory(self.symLinkDest) + + "we always wanna treat MS windows shortcuts as files for + "simplicity + if hardPath !~# '\.lnk$' + + let self.symLinkDest = self.symLinkDest . '/' + endif + endif + endif +endfunction + +"FUNCTION: Path.refresh() {{{1 +function! s:Path.refresh() + call self.readInfoFromDisk(self.str()) + call g:NERDTreePathNotifier.NotifyListeners('refresh', self, {}) + call self.cacheDisplayString() +endfunction + +"FUNCTION: Path.refreshFlags() {{{1 +function! s:Path.refreshFlags() + call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, {}) + call self.cacheDisplayString() +endfunction + +"FUNCTION: Path.rename() {{{1 +" +"Renames this node on the filesystem +function! s:Path.rename(newPath) + if a:newPath ==# '' + throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath + endif + + let success = rename(self.str(), a:newPath) + if success != 0 + throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath + endif + call self.readInfoFromDisk(a:newPath) + + for i in self.bookmarkNames() + let b = g:NERDTreeBookmark.BookmarkFor(i) + call b.setPath(copy(self)) + endfor + call g:NERDTreeBookmark.Write() +endfunction + +"FUNCTION: Path.str() {{{1 +" +"Returns a string representation of this Path +" +"Takes an optional dictionary param to specify how the output should be +"formatted. +" +"The dict may have the following keys: +" 'format' +" 'escape' +" 'truncateTo' +" +"The 'format' key may have a value of: +" 'Cd' - a string to be used with the :cd command +" 'Edit' - a string to be used with :e :sp :new :tabedit etc +" 'UI' - a string used in the NERD tree UI +" +"The 'escape' key, if specified will cause the output to be escaped with +"shellescape() +" +"The 'truncateTo' key causes the resulting string to be truncated to the value +"'truncateTo' maps to. A '<' char will be prepended. +function! s:Path.str(...) + let options = a:0 ? a:1 : {} + let toReturn = "" + + if has_key(options, 'format') + let format = options['format'] + if has_key(self, '_strFor' . format) + exec 'let toReturn = self._strFor' . format . '()' + else + raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"' + endif + else + let toReturn = self._str() + endif + + if nerdtree#has_opt(options, 'escape') + let toReturn = shellescape(toReturn) + endif + + if has_key(options, 'truncateTo') + let limit = options['truncateTo'] + if len(toReturn) > limit-1 + let toReturn = toReturn[(len(toReturn)-limit+1):] + if len(split(toReturn, '/')) > 1 + let toReturn = ' len(array_to_search) + throw "NERDTree.InvalidArgumentsError: Index is out of bounds." + endif + return array_to_search[a:indx] +endfunction + +"FUNCTION: TreeDirNode.getChildIndex(path) {{{1 +"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() {{{1 +"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 = g:NERDTreeFileNode.GetSelected() + if currentDir != {} && !currentDir.isRoot() + if currentDir.path.isDirectory ==# 0 + let currentDir = currentDir.parent + endif + endif + return currentDir +endfunction + +"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1 +"Returns the number of visible children this node has +function! s:TreeDirNode.getVisibleChildCount() + return len(self.getVisibleChildren()) +endfunction + +"FUNCTION: TreeDirNode.getVisibleChildren() {{{1 +"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() {{{1 +"returns 1 if this node has any childre, 0 otherwise.. +function! s:TreeDirNode.hasVisibleChildren() + return self.getVisibleChildCount() != 0 +endfunction + +"FUNCTION: TreeDirNode._initChildren() {{{1 +"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'}) + + if version >= 703 + let filesStr = globpath(globDir, '*', !g:NERDTreeRespectWildIgnore) . "\n" . globpath(globDir, '.*', !g:NERDTreeRespectWildIgnore) + else + let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*') + endif + + let files = split(filesStr, "\n") + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call nerdtree#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 = g:NERDTreePath.New(i) + call self.createChild(path, 0) + call g:NERDTreePathNotifier.NotifyListeners('init', path, {}) + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + let invalidFilesFound += 1 + endtry + endif + endfor + + call self.sortChildren() + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).") + endif + + if invalidFilesFound + call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree") + endif + return self.getChildCount() +endfunction + +"FUNCTION: TreeDirNode.New(path) {{{1 +"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([opts]) {{{1 +"Open the dir in the current tree or in a new tree elsewhere. +" +"If opening in the current tree, return the number of cached nodes. +unlet s:TreeDirNode.open +function! s:TreeDirNode.open(...) + let opts = a:0 ? a:1 : {} + + if has_key(opts, 'where') && !empty(opts['where']) + let opener = g:NERDTreeOpener.New(self.path, opts) + call opener.open(self) + else + let self.isOpen = 1 + if self.children ==# [] + return self._initChildren(0) + else + return 0 + endif + endif +endfunction + +"FUNCTION: TreeDirNode.openAlong([opts]) {{{1 +"recursive open the dir if it has only one directory child. +" +"return the level of opened directories. +function! s:TreeDirNode.openAlong(...) + let opts = a:0 ? a:1 : {} + let level = 0 + + let node = self + while node.path.isDirectory + call node.open(opts) + let level += 1 + if node.getVisibleChildCount() == 1 + let node = node.getChildByIndex(0, 1) + else + break + endif + endwhile + return level +endfunction + +" FUNCTION: TreeDirNode.openExplorer() {{{1 +" opens an explorer window for this node in the previous window (could be a +" nerd tree or a netrw) +function! s:TreeDirNode.openExplorer() + call self.open({'where': 'p'}) +endfunction + +"FUNCTION: TreeDirNode.openInNewTab(options) {{{1 +unlet s:TreeDirNode.openInNewTab +function! s:TreeDirNode.openInNewTab(options) + call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead') + call self.open({'where': 't'}) +endfunction + +"FUNCTION: TreeDirNode._openInNewTab() {{{1 +function! s:TreeDirNode._openInNewTab() + tabnew + call g:NERDTreeCreator.CreatePrimary(self.path.str()) +endfunction + +"FUNCTION: TreeDirNode.openRecursively() {{{1 +"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() {{{1 +"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() {{{1 +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 = g:NERDTreePath.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 = g:NERDTreeFileNode.New(path) + let newNode.parent = self + call add(newChildNodes, newNode) + endif + + + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + 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 nerdtree#echoWarning("some files could not be loaded into the NERD tree") + endif + endif +endfunction + +"FUNCTION: TreeDirNode.refreshFlags() {{{1 +unlet s:TreeDirNode.refreshFlags +function! s:TreeDirNode.refreshFlags() + call self.path.refreshFlags() + for i in self.children + call i.refreshFlags() + endfor +endfunction + +"FUNCTION: TreeDirNode.refreshDirFlags() {{{1 +function! s:TreeDirNode.refreshDirFlags() + call self.path.refreshFlags() +endfunction + +"FUNCTION: TreeDirNode.reveal(path) {{{1 +"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 b:NERDTree.render() + 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) {{{1 +" +"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() {{{1 +" +"Sorts the children of this node according to alphabetical order and the +"directory priority. +" +function! s:TreeDirNode.sortChildren() + let CompareFunc = function("nerdtree#compareNodes") + call sort(self.children, CompareFunc) +endfunction + +"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1 +"Opens this directory if it is closed and vice versa +function! s:TreeDirNode.toggleOpen(...) + let opts = a:0 ? a:1 : {} + if self.isOpen ==# 1 + call self.close() + else + if g:NERDTreeCascadeOpenSingleChildDir == 0 + call self.open(opts) + else + call self.openAlong(opts) + endif + endif +endfunction + +"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1 +"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 + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/tree_file_node.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/tree_file_node.vim new file mode 100644 index 0000000..b4924d7 --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/tree_file_node.vim @@ -0,0 +1,431 @@ +"CLASS: TreeFileNode +"This class is the parent of the TreeDirNode class and is the +"'Component' part of the composite design pattern between the treenode +"classes. +"============================================================ +let s:TreeFileNode = {} +let g:NERDTreeFileNode = s:TreeFileNode + +"FUNCTION: TreeFileNode.activate(...) {{{1 +function! s:TreeFileNode.activate(...) + call self.open(a:0 ? a:1 : {}) +endfunction + +"FUNCTION: TreeFileNode.bookmark(name) {{{1 +"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 = g:NERDTreeBookmark.GetNodeForName(a:name, 1) + catch /^NERDTree.BookmarkNotFoundError/ + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + + call g:NERDTreeBookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call g:NERDTreeBookmark.Write() + + if !empty(oldMarkedNode) + call oldMarkedNode.path.cacheDisplayString() + endif +endfunction + +"FUNCTION: TreeFileNode.cacheParent() {{{1 +"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.clearBookmarks() {{{1 +function! s:TreeFileNode.clearBookmarks() + for i in g:NERDTreeBookmark.Bookmarks() + if i.path.equals(self.path) + call i.delete() + end + endfor + call self.path.cacheDisplayString() +endfunction + +"FUNCTION: TreeFileNode.copy(dest) {{{1 +function! s:TreeFileNode.copy(dest) + call self.path.copy(a:dest) + let newPath = g:NERDTreePath.New(a:dest) + let parent = b:NERDTreeRoot.findNode(newPath.getParent()) + if !empty(parent) + call parent.refresh() + return parent.findNode(newPath) + else + return {} + endif +endfunction + +"FUNCTION: TreeFileNode.delete {{{1 +"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() {{{1 +" +"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) {{{1 +" +"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) {{{1 +"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) {{{1 +" +"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) {{{1 +" +"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.GetRootForTab(){{{1 +"get the root node for this tab +function! s:TreeFileNode.GetRootForTab() + if g:NERDTree.ExistsForTab() + return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot') + end + return {} +endfunction + +"FUNCTION: TreeFileNode.GetSelected() {{{1 +"gets the treenode that the cursor is currently over +function! s:TreeFileNode.GetSelected() + try + let path = b:NERDTree.ui.getPath(line(".")) + if path ==# {} + return {} + endif + return b:NERDTreeRoot.findNode(path) + catch /^NERDTree/ + return {} + endtry +endfunction + +"FUNCTION: TreeFileNode.isVisible() {{{1 +"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() {{{1 +"returns 1 if this node is b:NERDTreeRoot +function! s:TreeFileNode.isRoot() + if !g:NERDTree.ExistsForBuf() + throw "NERDTree.NoTreeError: No tree exists for the current buffer" + endif + + return self.equals(b:NERDTreeRoot) +endfunction + +"FUNCTION: TreeFileNode.makeRoot() {{{1 +"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 + + silent doautocmd User NERDTreeNewRoot +endfunction + +"FUNCTION: TreeFileNode.New(path) {{{1 +"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 g:NERDTreeDirNode.New(a:path) + else + let newTreeNode = copy(self) + let newTreeNode.path = a:path + let newTreeNode.parent = {} + return newTreeNode + endif +endfunction + +"FUNCTION: TreeFileNode.open() {{{1 +function! s:TreeFileNode.open(...) + let opts = a:0 ? a:1 : {} + let opener = g:NERDTreeOpener.New(self.path, opts) + call opener.open(self) +endfunction + +"FUNCTION: TreeFileNode.openSplit() {{{1 +"Open this node in a new window +function! s:TreeFileNode.openSplit() + call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.') + call self.open({'where': 'h'}) +endfunction + +"FUNCTION: TreeFileNode.openVSplit() {{{1 +"Open this node in a new vertical window +function! s:TreeFileNode.openVSplit() + call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.') + call self.open({'where': 'v'}) +endfunction + +"FUNCTION: TreeFileNode.openInNewTab(options) {{{1 +function! s:TreeFileNode.openInNewTab(options) + echomsg 'TreeFileNode.openInNewTab is deprecated' + call self.open(extend({'where': 't'}, a:options)) +endfunction + +"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1 +"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 = b:NERDTree.ui.getLineNum(self) + if ln != -1 + if a:isJump + mark ' + endif + call cursor(ln, col(".")) + else + if a:recurseUpward + let node = self + while node != {} && b:NERDTree.ui.getLineNum(node) ==# -1 + let node = node.parent + call node.open() + endwhile + call b:NERDTree.render() + call node.putCursorHere(a:isJump, 0) + endif + endif +endfunction + +"FUNCTION: TreeFileNode.refresh() {{{1 +function! s:TreeFileNode.refresh() + call self.path.refresh() +endfunction + +"FUNCTION: TreeFileNode.refreshFlags() {{{1 +function! s:TreeFileNode.refreshFlags() + call self.path.refreshFlags() +endfunction + +"FUNCTION: TreeFileNode.rename() {{{1 +"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 {{{1 +"returns a string representation for this tree to be rendered in the view +function! s:TreeFileNode.renderToString() + return self._renderToString(0, 0, [], self.getChildCount() ==# 1) +endfunction + +"Args: +"depth: the current depth in the tree for this call +"drawText: 1 if we should actually draw the line for this node (if 0 then the +"child nodes are rendered only) +"vertMap: a binary array that indicates whether a vertical bar should be draw +"for each depth in the tree +"isLastChild:true if this curNode is the last child of its parent +function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild) + let output = "" + if a:drawText ==# 1 + + let treeParts = '' + + "get all the leading spaces and vertical tree parts for this line + if a:depth > 1 + for j in a:vertMap[0:-2] + if g:NERDTreeDirArrows + let treeParts = treeParts . ' ' + else + if j ==# 1 + let treeParts = treeParts . '| ' + else + let treeParts = treeParts . ' ' + endif + endif + endfor + endif + + "get the last vertical tree part for this line which will be different + "if this node is the last child of its parent + if !g:NERDTreeDirArrows + if a:isLastChild + let treeParts = treeParts . '`' + else + let treeParts = treeParts . '|' + endif + endif + + "smack the appropriate dir/file symbol on the line before the file/dir + "name itself + if self.path.isDirectory + if self.isOpen + if g:NERDTreeDirArrows + let treeParts = treeParts . '▾ ' + else + let treeParts = treeParts . '~' + endif + else + if g:NERDTreeDirArrows + let treeParts = treeParts . '▸ ' + else + let treeParts = treeParts . '+' + endif + endif + else + if g:NERDTreeDirArrows + let treeParts = treeParts . ' ' + else + let treeParts = treeParts . '-' + endif + endif + let line = treeParts . self.displayString() + + let output = output . line . "\n" + endif + + "if the node is an open dir, draw its children + if self.path.isDirectory ==# 1 && self.isOpen ==# 1 + + let childNodesToDraw = self.getVisibleChildren() + if len(childNodesToDraw) > 0 + + "draw all the nodes children except the last + let lastIndx = len(childNodesToDraw)-1 + if lastIndx > 0 + for i in childNodesToDraw[0:lastIndx-1] + let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0) + endfor + endif + + "draw the last child, indicating that it IS the last + let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1) + endif + endif + + return output +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/lib/nerdtree/ui.vim b/config/home/vim/bundle/nerdtree/lib/nerdtree/ui.vim new file mode 100644 index 0000000..22e450c --- /dev/null +++ b/config/home/vim/bundle/nerdtree/lib/nerdtree/ui.vim @@ -0,0 +1,506 @@ +"CLASS: UI +"============================================================ +let s:UI = {} +let g:NERDTreeUI = s:UI + +"FUNCTION: s:UI.centerView() {{{2 +"centers the nerd tree window around the cursor (provided the nerd tree +"options permit) +function! s:UI.centerView() + if g:NERDTreeAutoCenter + let current_line = winline() + let lines_to_top = current_line + let lines_to_bottom = winheight(g:NERDTree.GetWinNum()) - current_line + if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold + normal! zz + endif + endif +endfunction + +"FUNCTION: s:UI._dumpHelp {{{1 +"prints out the quick help +function! s:UI._dumpHelp() + let old_h = @h + if b:treeShowHelp ==# 1 + let @h= "\" NERD tree (" . nerdtree#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."\" ". g:NERDTreeMapCWD .":change tree root to CWD\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 + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Custom mappings~\n" + for i in g:NERDTreeKeyMap.All() + if !empty(i.quickhelpText) + let @h=@h."\" ". i.key .": ". i.quickhelpText ."\n" + endif + endfor + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Other mappings~\n" + let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n" + let @h=@h."\" ". g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n" + let @h=@h."\" the NERDTree window\n" + let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n" + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Bookmark commands~\n" + let @h=@h."\" :Bookmark []\n" + let @h=@h."\" :BookmarkToRoot \n" + let @h=@h."\" :RevealBookmark \n" + let @h=@h."\" :OpenBookmark \n" + let @h=@h."\" :ClearBookmarks []\n" + let @h=@h."\" :ClearAllBookmarks\n" + silent! put h + elseif g:NERDTreeMinimalUI == 0 + let @h="\" Press ". g:NERDTreeMapHelp ." for help\n" + silent! put h + endif + + let @h = old_h +endfunction + + +"FUNCTION: s:UI.new(nerdtree) {{{1 +function! s:UI.New(nerdtree) + let newObj = copy(self) + let newObj.nerdtree = a:nerdtree + return newObj +endfunction + +"FUNCTION: s:UI.getPath(ln) {{{1 +"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:UI.getPath(ln) + let line = getline(a:ln) + + let rootLine = self.getRootLineNum() + + "check to see if we have the root node + if a:ln == rootLine + return b:NERDTreeRoot.path + endif + + if !g:NERDTreeDirArrows + " in case called from outside the tree + if line !~# '^ *[|`▸▾ ]' || line =~# '^$' + return {} + endif + endif + + if line ==# s:UI.UpDirLine() + return b:NERDTreeRoot.path.getParent() + endif + + let indent = self._indentLevelFor(line) + + "remove the tree parts and the leading space + let curFile = self._stripMarkup(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 = self._stripMarkup(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 = self._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 = g:NERDTreePath.New(curFile) + return toReturn +endfunction + +"FUNCTION: s:UI.getLineNum(file_node){{{1 +"returns the line number this node is rendered on, or -1 if it isnt rendered +function! s:UI.getLineNum(file_node) + "if the node is the root then return the root line no. + if a:file_node.isRoot() + return b:NERDTree.ui.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 = a:file_node.path.str({'format': 'UI'}) + + let lnum = b:NERDTree.ui.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 = self._indentLevelFor(curLine) + if indent ==# curPathComponent + let curLine = self._stripMarkup(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: s:UI.getRootLineNum(){{{1 +"gets the line number of the root node +function! s:UI.getRootLineNum() + let rootLine = 1 + while getline(rootLine) !~# '^\(/\|<\)' + let rootLine = rootLine + 1 + endwhile + return rootLine +endfunction + +"FUNCTION: s:UI._indentLevelFor(line) {{{1 +function! s:UI._indentLevelFor(line) + let level = match(a:line, '[^ \-+~▸▾`|]') / s:UI.IndentWid() + " check if line includes arrows + if match(a:line, '[▸▾]') > -1 + " decrement level as arrow uses 3 ascii chars + let level = level - 1 + endif + return level +endfunction + +"FUNCTION: s:UI.IndentWid() {{{1 +function! s:UI.IndentWid() + return 2 +endfunction + +"FUNCTION: s:UI.MarkupReg() {{{1 +function! s:UI.MarkupReg() + if g:NERDTreeDirArrows + return '^\([▾▸] \| \+[▾▸] \| \+\)' + endif + + return '^[ `|]*[\-+~]' +endfunction + +"FUNCTION: s:UI._renderBookmarks {{{1 +function! s:UI._renderBookmarks() + + if g:NERDTreeMinimalUI == 0 + call setline(line(".")+1, ">----------Bookmarks----------") + call cursor(line(".")+1, col(".")) + endif + + for i in g:NERDTreeBookmark.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:UI.restoreScreenState() {{{1 +" +"Sets the screen state back to what it was when nerdtree#saveScreenState was last +"called. +" +"Assumes the cursor is in the NERDTree window +function! s:UI.restoreScreenState() + if !has_key(self, '_screenState') + return + endif + exec("silent vertical resize " . self._screenState['oldWindowSize']) + + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(self._screenState['oldTopLine'], 0) + normal! zt + call setpos(".", self._screenState['oldPos']) + let &scrolloff=old_scrolloff +endfunction + +"FUNCTION: s:UI.saveScreenState() {{{1 +"Saves the current cursor position in the current buffer and the window +"scroll position +function! s:UI.saveScreenState() + let win = winnr() + call g:NERDTree.CursorToTreeWin() + let self._screenState = {} + let self._screenState['oldPos'] = getpos(".") + let self._screenState['oldTopLine'] = line("w0") + let self._screenState['oldWindowSize']= winwidth("") + call nerdtree#exec(win . "wincmd w") +endfunction + +"FUNCTION: s:UI._stripMarkup(line, removeLeadingSpaces){{{1 +"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:UI._stripMarkup(line, removeLeadingSpaces) + let line = a:line + "remove the tree parts and the leading space + let line = substitute (line, g:NERDTreeUI.MarkupReg(),"","") + + "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\($\| \)', "","") + + "strip off any generic flags + let line = substitute (line, '\[[^]]*\]', "","") + + 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:UI.render() {{{1 +function! s:UI.render() + 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 self._dumpHelp() + + "delete the blank line before the help and add one after it + if g:NERDTreeMinimalUI == 0 + call setline(line(".")+1, "") + call cursor(line(".")+1, col(".")) + endif + + if b:NERDTreeShowBookmarks + call self._renderBookmarks() + endif + + "add the 'up a dir' line + if !g:NERDTreeMinimalUI + call setline(line(".")+1, s:UI.UpDirLine()) + call cursor(line(".")+1, col(".")) + endif + + "draw the header line + let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)}) + call setline(line(".")+1, header) + call cursor(line(".")+1, col(".")) + + "draw the tree + let old_o = @o + let @o = b:NERDTreeRoot.renderToString() + silent put o + let @o = old_o + + "delete the blank line at the top of the buffer + silent 1,1delete _ + + "restore the view + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(topLine, 1) + normal! zt + call cursor(curLine, curCol) + let &scrolloff = old_scrolloff + + setlocal nomodifiable +endfunction + + +"FUNCTION: UI.renderViewSavingPosition {{{1 +"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:UI.renderViewSavingPosition() + let currentNode = g:NERDTreeFileNode.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 b:NERDTree.render() + + if currentNode != {} + call currentNode.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: s:UI.toggleIgnoreFilter() {{{1 +" toggles the use of the NERDTreeIgnore option +function! s:UI.toggleIgnoreFilter() + let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled + call b:NERDTree.ui.renderViewSavingPosition() + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowBookmarks() {{{1 +" toggles the display of bookmarks +function! s:UI.toggleShowBookmarks() + let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks + if b:NERDTreeShowBookmarks + call b:NERDTree.render() + call g:NERDTree.CursorToBookmarkTable() + else + call b:NERDTree.ui.renderViewSavingPosition() + endif + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowFiles() {{{1 +" toggles the display of hidden files +function! s:UI.toggleShowFiles() + let b:NERDTreeShowFiles = !b:NERDTreeShowFiles + call b:NERDTree.ui.renderViewSavingPosition() + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowHidden() {{{1 +" toggles the display of hidden files +function! s:UI.toggleShowHidden() + let b:NERDTreeShowHidden = !b:NERDTreeShowHidden + call b:NERDTree.ui.renderViewSavingPosition() + call self.centerView() +endfunction + +" FUNCTION: s:UI.toggleZoom() {{{1 +" zoom (maximize/minimize) the NERDTree window +function! s:UI.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:UI.UpDirLine() {{{1 +function! s:UI.UpDirLine() + return '.. (up a dir)' +endfunction diff --git a/config/home/vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim b/config/home/vim/bundle/nerdtree/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..e7a7c53 --- /dev/null +++ b/config/home/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/config/home/vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim b/config/home/vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..e99a85b --- /dev/null +++ b/config/home/vim/bundle/nerdtree/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,270 @@ +" ============================================================================ +" 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 + +"Automatically delete the buffer after deleting or renaming a file +if !exists("g:NERDTreeAutoDeleteBuffer") + let g:NERDTreeAutoDeleteBuffer = 0 +endif + +call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) +call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) + +if has("gui_mac") || has("gui_macvim") + call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'}) + call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'}) + call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'}) +endif + +if g:NERDTreePath.CopyingSupported() + call NERDTreeAddMenuItem({'text': '(c)opy 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 g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y' + " 1. ensure that all windows which display the just deleted filename + " now display an empty buffer (so a layout is preserved). + " Is not it better to close single tabs with this file only ? + let s:originalTabNumber = tabpagenr() + let s:originalWindowNumber = winnr() + exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif" + exec "tabnext " . s:originalTabNumber + exec s:originalWindowNumber . "wincmd w" + " 3. We don't need a previous buffer anymore + exec "bwipeout! " . a:bufnum + endif +endfunction + +"FUNCTION: s:promptToRenameBuffer(bufnum, msg){{{1 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is replaced with a new one +" +"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:promptToRenameBuffer(bufnum, msg, newFileName) + echo a:msg + if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y' + let quotedFileName = "'" . a:newFileName . "'" + " 1. ensure that a new buffer is loaded + exec "badd " . quotedFileName + " 2. ensure that all windows which display the just deleted filename + " display a buffer for a new filename. + let s:originalTabNumber = tabpagenr() + let s:originalWindowNumber = winnr() + let editStr = g:NERDTreePath.New(a:newFileName).str({'format': 'Edit'}) + exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . editStr . "' | endif" + exec "tabnext " . s:originalTabNumber + exec s:originalWindowNumber . "wincmd w" + " 3. We don't need a previous buffer anymore + exec "bwipeout! " . a:bufnum + endif +endfunction +"FUNCTION: NERDTreeAddNode(){{{1 +function! NERDTreeAddNode() + let curDirNode = g:NERDTreeDirNode.GetSelected() + + let newNodeName = input("Add a childnode\n". + \ "==========================================================\n". + \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . + \ "", curDirNode.path.str() . g:NERDTreePath.Slash(), "file") + + if newNodeName ==# '' + call s:echo("Node Creation Aborted.") + return + endif + + try + let newPath = g:NERDTreePath.Create(newNodeName) + let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) + + let newTreeNode = g:NERDTreeFileNode.New(newPath) + if empty(parentNode) + call b:NERDTreeRoot.refresh() + call b:NERDTree.render() + elseif parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call NERDTreeRender() + call newTreeNode.putCursorHere(1, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Node Not Created.") + endtry +endfunction + +"FUNCTION: NERDTreeMoveNode(){{{1 +function! NERDTreeMoveNode() + let curNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Rename the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path for the node: \n" . + \ "", curNode.path.str(), "file") + + if newNodePath ==# '' + call s:echo("Node Renaming Aborted.") + return + endif + + try + let bufnum = bufnr("^".curNode.path.str()."$") + + call curNode.rename(newNodePath) + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + if bufnum != -1 + let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Replace this buffer with a new file? (yN)" + call s:promptToRenameBuffer(bufnum, prompt, newNodePath) + endif + + call curNode.putCursorHere(1, 0) + + redraw + catch /^NERDTree/ + call s:echoWarning("Node Not Renamed.") + endtry +endfunction + +" FUNCTION: NERDTreeDeleteNode() {{{1 +function! NERDTreeDeleteNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let confirmed = 0 + + if currentNode.path.isDirectory + let choice =input("Delete the current node\n" . + \ "==========================================================\n" . + \ "STOP! To delete this entire directory, type 'yes'\n" . + \ "" . currentNode.path.str() . ": ") + let confirmed = choice ==# 'yes' + else + echo "Delete the current node\n" . + \ "==========================================================\n". + \ "Are you sure you wish to delete the node:\n" . + \ "" . currentNode.path.str() . " (yN):" + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + + if confirmed + try + call currentNode.delete() + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr("^".currentNode.path.str()."$") + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove node") + endtry + else + call s:echo("delete aborted") + endif + +endfunction + +" FUNCTION: NERDTreeCopyNode() {{{1 +function! NERDTreeCopyNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Copy the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path to copy the node to: \n" . + \ "", currentNode.path.str(), "file") + + if newNodePath != "" + "strip trailing slash + let newNodePath = substitute(newNodePath, '\/$', '', '') + + let confirmed = 1 + if currentNode.path.copyingWillOverwrite(newNodePath) + call s:echo("Warning: copying may overwrite files! Continue? (yN)") + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + let newNode = currentNode.copy(newNodePath) + if empty(newNode) + call b:NERDTreeRoot.refresh() + call b:NERDTree.render() + else + call NERDTreeRender() + call newNode.putCursorHere(0, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Could not copy node") + endtry + endif + else + call s:echo("Copy aborted.") + endif + redraw +endfunction + +function! NERDTreeQuickLook() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'") + endif +endfunction + +function! NERDTreeRevealInFinder() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + let x = system("open -R '" . treenode.path.str() . "'") + endif +endfunction + +function! NERDTreeExecuteFile() + let treenode = g:NERDTreeFileNode.GetSelected() + if treenode != {} + let x = system("open '" . treenode.path.str() . "'") + endif +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/plugin/NERD_tree.vim b/config/home/vim/bundle/nerdtree/plugin/NERD_tree.vim new file mode 100644 index 0000000..966838c --- /dev/null +++ b/config/home/vim/bundle/nerdtree/plugin/NERD_tree.vim @@ -0,0 +1,210 @@ +" ============================================================================ +" File: NERD_tree.vim +" Description: vim global plugin that provides a nice tree explorer +" Maintainer: Martin Grenfell +" Last Change: 28 December, 2011 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +" +" 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:NERDTreeAutoCenter", 1) +call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) +call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) +call s:initVariable("g:NERDTreeSortHiddenFirst", 1) +call s:initVariable("g:NERDTreeChDirMode", 0) +call s:initVariable("g:NERDTreeMinimalUI", 0) +if !exists("g:NERDTreeIgnore") + let g:NERDTreeIgnore = ['\~$'] +endif +call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks') +call s:initVariable("g:NERDTreeBookmarksSort", 1) +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:NERDTreeRespectWildIgnore", 0) +call s:initVariable("g:NERDTreeShowBookmarks", 0) +call s:initVariable("g:NERDTreeShowFiles", 1) +call s:initVariable("g:NERDTreeShowHidden", 0) +call s:initVariable("g:NERDTreeShowLineNumbers", 0) +call s:initVariable("g:NERDTreeSortDirs", 1) +call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows()) +call s:initVariable("g:NERDTreeCascadeOpenSingleChildDir", 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 + +if !exists('g:NERDTreeStatusline') + + "the exists() crap here is a hack to stop vim spazzing out when + "loading a session that was created with an open nerd tree. It spazzes + "because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash) + let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}" + +endif +call s:initVariable("g:NERDTreeWinPos", "left") +call s:initVariable("g:NERDTreeWinSize", 31) + +"init the shell commands that will be used to copy nodes, and remove dir trees +" +"Note: the space after the command is important +if nerdtree#runningWindows() + 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") +call s:initVariable("g:NERDTreeMapCWD", "CD") + +"SECTION: Load class files{{{2 +call nerdtree#loadClassFiles() + +" SECTION: Commands {{{1 +"============================================================ +call nerdtree#ui_glue#setupCommands() + +" SECTION: Auto commands {{{1 +"============================================================ +augroup NERDTree + "Save the cursor position whenever we close the nerd tree + exec "autocmd BufLeave ". g:NERDTreeCreator.BufNamePrefix() ."* if g:NERDTree.IsOpen() | call b:NERDTree.ui.saveScreenState() | endif" + + "disallow insert mode in the NERDTree + exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert" +augroup END + +if g:NERDTreeHijackNetrw + augroup NERDTreeHijackNetrw + autocmd VimEnter * silent! autocmd! FileExplorer + au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand("")) + augroup END +endif + +" SECTION: Public API {{{1 +"============================================================ +function! NERDTreeAddMenuItem(options) + call g:NERDTreeMenuItem.Create(a:options) +endfunction + +function! NERDTreeAddMenuSeparator(...) + let opts = a:0 ? a:1 : {} + call g:NERDTreeMenuItem.CreateSeparator(opts) +endfunction + +function! NERDTreeAddSubmenu(options) + return g:NERDTreeMenuItem.Create(a:options) +endfunction + +function! NERDTreeAddKeyMap(options) + call g:NERDTreeKeyMap.Create(a:options) +endfunction + +function! NERDTreeRender() + call nerdtree#renderView() +endfunction + +function! NERDTreeFocus() + if g:NERDTree.IsOpen() + call g:NERDTree.CursorToTreeWin() + else + call g:NERDTreeCreator.TogglePrimary("") + endif +endfunction + +function! NERDTreeCWD() + call NERDTreeFocus() + call nerdtree#ui_glue#chRootCwd() +endfunction + +function! NERDTreeAddPathFilter(callback) + call g:NERDTree.AddPathFilter(a:callback) +endfunction + +" SECTION: Post Source Actions {{{1 +call nerdtree#postSourceActions() + +"reset &cpo back to users setting +let &cpo = s:old_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/nerdtree/syntax/nerdtree.vim b/config/home/vim/bundle/nerdtree/syntax/nerdtree.vim new file mode 100644 index 0000000..5f7b49c --- /dev/null +++ b/config/home/vim/bundle/nerdtree/syntax/nerdtree.vim @@ -0,0 +1,105 @@ +let s:tree_up_dir_line = '.. (up a dir)' +syn match NERDTreeIgnore #\~# +syn match NERDTreeIgnore #\[RO\]# + +"highlighting for the .. (up dir) line at the top of the tree +execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#" + +"quickhelp syntax elements +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#ms=s+2,me=e-1 +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#ms=s+2,me=e-1 +syn match NERDTreeHelpTitle #" .*\~#ms=s+2,me=e-1 +syn match NERDTreeToggleOn #(on)#ms=s+1,he=e-1 +syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1 +syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3 +syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeIgnore,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand + +"highlighting for sym links +syn match NERDTreeLinkTarget #->.*# containedin=NERDTreeDir,NERDTreeFile +syn match NERDTreeLinkFile #.* ->#me=e-3 containedin=NERDTreeFile +syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir + +"highlighing for directory nodes and file nodes +syn match NERDTreeDirSlash #/# containedin=NERDTreeDir + +if g:NERDTreeDirArrows + syn match NERDTreeClosable #▾# containedin=NERDTreeDir,NERDTreeFile + syn match NERDTreeOpenable #▸# containedin=NERDTreeDir,NERDTreeFile + + syn match NERDTreeDir #[^▾▸ ].*/# + syn match NERDTreeExecFile #^ .*\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmark + syn match NERDTreeFile #^[^"\.▾▸] *[^▾▸]*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile + + "highlighting for readonly files + syn match NERDTreeRO # *\zs.*\ze \[RO\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile + + syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile + syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir +else + "highlighting for the ~/+ symbols for the directory nodes + syn match NERDTreeClosable #\~\<# + syn match NERDTreeClosable #\~\.# + syn match NERDTreeOpenable #+\<# + syn match NERDTreeOpenable #+\.#he=e-1 + + "highlighting for the tree structural parts + syn match NERDTreePart #|# + syn match NERDTreePart #`# + syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart + + syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeOpenable,NERDTreeClosable + syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark + syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile + syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile + + "highlighting for readonly files + syn match NERDTreeRO #|-.*\[RO\]#he=e-5 contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreePart,NERDTreePartFile + + syn match NERDTreeFlags #-\[.\]# containedin=NERDTreeFile,NERDTreePartFile + syn match NERDTreeFlags #[+~]\zs\[.\]# containedin=NERDTreeDir +endif + +syn match NERDTreeCWD #^[# +syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader + +hi def link NERDTreePart Special +hi def link NERDTreePartFile Type +hi def link NERDTreeExecFile Title +hi def link NERDTreeDirSlash Identifier + +hi def link NERDTreeBookmarksHeader statement +hi def link NERDTreeBookmarksLeader ignore +hi def link NERDTreeBookmarkName Identifier +hi def link NERDTreeBookmark normal + +hi def link NERDTreeHelp String +hi def link NERDTreeHelpKey Identifier +hi def link NERDTreeHelpCommand Identifier +hi def link NERDTreeHelpTitle Macro +hi def link NERDTreeToggleOn Question +hi def link NERDTreeToggleOff WarningMsg + +hi def link NERDTreeLinkTarget Type +hi def link NERDTreeLinkFile Macro +hi def link NERDTreeLinkDir Macro + +hi def link NERDTreeDir Directory +hi def link NERDTreeUp Directory +hi def link NERDTreeFile Normal +hi def link NERDTreeCWD Statement +hi def link NERDTreeOpenable Title +hi def link NERDTreeClosable Title +hi def link NERDTreeIgnore ignore +hi def link NERDTreeRO WarningMsg +hi def link NERDTreeBookmark Statement +hi def link NERDTreeFlags Number + +hi def link NERDTreeCurrentNode Search diff --git a/config/home/vim/bundle/syntastic/.gitignore b/config/home/vim/bundle/syntastic/.gitignore new file mode 100644 index 0000000..cc07c93 --- /dev/null +++ b/config/home/vim/bundle/syntastic/.gitignore @@ -0,0 +1,4 @@ +*~ +*.swp +tags +.DS_Store diff --git a/config/home/vim/bundle/syntastic/CONTRIBUTING.md b/config/home/vim/bundle/syntastic/CONTRIBUTING.md new file mode 100644 index 0000000..378b53b --- /dev/null +++ b/config/home/vim/bundle/syntastic/CONTRIBUTING.md @@ -0,0 +1,105 @@ +# CONTRIBUTING +- - - +1\. [Bug reports / GitHub issues](#bugreps) +2\. [Submitting a patch](#patches) +3\. [General style notes](#generalstyle) +4\. [Syntax checker notes](#checkerstyle) +- - - + + + +## 1. Bug reports / GitHub issues + +Please note that the preferred channel for posting bug reports is the +[issue tracker at GitHub][0]. Reports posted elsewhere are less likely +to be seen by the core team. + +When reporting a bug make sure you search the existing GitHub issues +for the same/similar issues. If you find one, feel free to add a `+1` +comment with any additional information that may help us solve the +issue. + +When creating a new issue be sure to state the following: + +* steps to reproduce the bug; +* the version of Vim you are using (run `:ver` to find out); +* the version of syntastic you are using (see `:SyntasticInfo`). + +For syntax checker bugs also state the version of the checker executable +that you are using. Adding debugging information is typically useful +too: + +* open a file handled by your checker; +* set `g:syntastic_debug` to 1 or 3; +* run the checker; +* copy the output of `:mes`. + + + +## 2. Submitting a patch + +Before you consider adding features to syntastic, _please_ spend a few +minutes (re-)reading the latest version of the [manual][1]. Syntastic +is changing rapidly at times, and it's quite possible that some of the +features you want to add exist already. + +To submit a patch: + +* fork the [repo][2] on GitHub; +* make a [topic branch][3] and start hacking; +* submit a pull request based off your topic branch. + +Small, focused patches are preferred. + +Large changes to the code should be discussed with the core team first. +Create an issue and explain your plan and see what we say. + +Also make sure to update the manual whenever applicable. Nobody can use +features that aren't documented. + + + +## 3. General style notes + +Follow the coding conventions/styles used in the syntastic core: + +* use 4 space indents; +* don't use abbreviated keywords - e.g. use `endfunction`, not `endfun` +(there's always room for more fun!); +* don't use `l:` prefixes for variables unless actually required (i.e. +almost never); +* code for maintainability; we would rather a function be a couple of +lines longer and have (for example) some [explaining variables][4] to +aid readability. + + + +## 4. Syntax checker notes + +Make sure to read the [guide][5] if you plan to add new syntax checkers. + +Use the existing checkers as templates, rather than writing everything +from scratch. + +The preferred style for error format strings is one "clause" per line. +E.g. (from the `coffee` checker): + +```vim +let errorformat = + \ '%E%f:%l:%c: %trror: %m,' . + \ 'Syntax%trror: In %f\, %m on line %l,' . + \ '%EError: In %f\, Parse error on line %l: %m,' . + \ '%EError: In %f\, %m on line %l,' . + \ '%W%f(%l): lint warning: %m,' . + \ '%W%f(%l): warning: %m,' . + \ '%E%f(%l): SyntaxError: %m,' . + \ '%-Z%p^,' . + \ '%-G%.%#' +``` + +[0]: https://github.com/scrooloose/syntastic/issues +[1]: https://github.com/scrooloose/syntastic/blob/master/doc/syntastic.txt +[2]: https://github.com/scrooloose/syntastic +[3]: https://github.com/dchelimsky/rspec/wiki/Topic-Branches#using-topic-branches-when-contributing-patches +[4]: http://www.refactoring.com/catalog/extractVariable.html +[5]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide diff --git a/config/home/vim/bundle/syntastic/LICENCE b/config/home/vim/bundle/syntastic/LICENCE new file mode 100644 index 0000000..8b1a9d8 --- /dev/null +++ b/config/home/vim/bundle/syntastic/LICENCE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/config/home/vim/bundle/syntastic/README.markdown b/config/home/vim/bundle/syntastic/README.markdown new file mode 100644 index 0000000..72d54e8 --- /dev/null +++ b/config/home/vim/bundle/syntastic/README.markdown @@ -0,0 +1,462 @@ + , + / \,,_ .'| + ,{{| /}}}}/_.' _____________________________________________ + }}}}` '{{' '. / \ + {{{{{ _ ;, \ / Ladies and Gentlemen, \ + ,}}}}}} /o`\ ` ;) | | + {{{{{{ / ( | this is ... | + }}}}}} | \ | | + {{{{{{{{ \ \ | | + }}}}}}}}} '.__ _ | | _____ __ __ _ | + {{{{{{{{ /`._ (_\ / | / ___/__ ______ / /_____ ______/ /_(_)____ | + }}}}}}' | //___/ --=: \__ \/ / / / __ \/ __/ __ `/ ___/ __/ / ___/ | + jgs `{{{{` | '--' | ___/ / /_/ / / / / /_/ /_/ (__ ) /_/ / /__ | + }}}` | /____/\__, /_/ /_/\__/\__,_/____/\__/_/\___/ | + | /____/ | + | / + \_____________________________________________/ + + +- - - +1. [Introduction](#introduction) +2. [Installation](#installation) +2.1. [Requirements](#requirements) +2.2. [Installing syntastic with Pathogen](#installpathogen) +3. [Recommended settings](#settings) +4. [FAQ](#faq) +4.1. [I installed syntastic but it isn't reporting any errors...](#faqinfo) +4.2. [The `python` checker complains about syntactically valid Python 3 constructs...](#faqpython3) +4.3. [Are there any local checkers for HTML5 that I can use with syntastic?](#faqhtml5) +4.4. [The `perl` checker has stopped working...](#faqperl) +4.5. [What happened to the `rustc` checker?](#faqrust) +4.6. [What happened to the `xcrun` checker?](#faqxcrun) +4.7. [I run a checker and the location list is not updated...](#faqloclist) +4.7. [I run`:lopen` or `:lwindow` and the error window is empty...](#faqloclist) +4.8. [How can I pass additional arguments to a checker?](#faqargs) +4.9. [Syntastic supports several checkers for my filetype - how do I tell which one(s) to use?](#faqcheckers) +4.10. [What is the difference between syntax checkers and style checkers?](#faqstyle) +4.11. [I have enabled multiple checkers for the current filetype. How can I display all of the errors from all of the checkers together?](#faqaggregate) +4.12. [How can I jump between the different errors without using the location list at the bottom of the window?](#faqlnext) +4.13. [The error window is closed automatically when I :quit the current buffer but not when I :bdelete it?](#faqbdelete) +5. [Resources](#otherresources) + +- - - + + + +## 1\. Introduction + +Syntastic is a syntax checking plugin for [Vim][13] that runs files through +external syntax checkers and displays any resulting errors to the user. This +can be done on demand, or automatically as files are saved. If syntax errors +are detected, the user is notified and is happy because they didn't have to +compile their code or execute their script to find them. + +At the time of this writing, syntastic has checking plugins for ActionScript, +Ada, API Blueprint, AppleScript, AsciiDoc, ASM, BEMHTML, Bro, Bourne shell, +C, C++, C#, Cabal, Chef, CoffeeScript, Coco, Coq, CSS, Cucumber, CUDA, D, +Dart, DocBook, Dust, Elixir, Erlang, eRuby, Fortran, Gentoo metadata, GLSL, +Go, Haml, Haskell, Haxe, Handlebars, HSS, HTML, Java, JavaScript, JSON, JSX, +LESS, Lex, Limbo, LISP, LLVM intermediate language, Lua, Markdown, MATLAB, +Mercury, NASM, Objective-C, Objective-C++, OCaml, Perl, Perl POD, PHP, gettext +Portable Object, OS X and iOS property lists, Puppet, Python, R, Racket, Relax +NG, reStructuredText, RPM spec, Ruby, SASS/SCSS, Scala, Slim, SML, Tcl, TeX, +Texinfo, Twig, TypeScript, Vala, Verilog, VHDL, VimL, xHtml, XML, XSLT, YACC, +YAML, z80, Zope page templates, and zsh. See the [wiki][3] for details about +the corresponding supported checkers. + +A number of third-party Vim plugins also provide checkers for syntastic, +for example: [omnisharp-vim][25], [rust.vim][12], [syntastic-extras][26], +[syntastic-more][27], and [vim-swift][24]. + +Below is a screenshot showing the methods that Syntastic uses to display syntax +errors. Note that, in practise, you will only have a subset of these methods +enabled. + +![Screenshot 1][0] + +1. Errors are loaded into the location list for the corresponding window. +2. When the cursor is on a line containing an error, the error message is echoed in the command window. +3. Signs are placed beside lines with errors - note that warnings are displayed in a different color. +4. There is a configurable statusline flag you can include in your statusline config. +5. Hover the mouse over a line containing an error and the error message is displayed as a balloon. +6. (not shown) Highlighting errors with syntax highlighting. Erroneous parts of lines can be highlighted. + + + +## 2\. Installation + + + +### 2.1\. Requirements + +Syntastic itself has rather relaxed requirements: it doesn't have any external +dependencies, and it needs a version of [Vim][13] compiled with a few common +features: `autocmd`, `eval`, `file_in_path`, `modify_fname`, `quickfix`, +`reltime`, and `user_commands`. Not all possible combinations of features that +include the ones above make equal sense on all operating systems, but Vim +version 7 or later with the "normal", "big", or "huge" feature sets should be +fine. + +Syntastic should work with any modern plugin managers for Vim, such as +[NeoBundle][14], [Pathogen][1], [Vim-Addon-Manager][15], [Vim-Plug][16], or +[Vundle][17]. Instructions for installing syntastic with [Pathogen][1] are +included below for completeness. + +Last but not least: syntastic doesn't know how to do any syntax checks by +itself. In order to get meaningful results you need to install external +checkers corresponding to the types of files you use. Please consult the +[wiki][3] for a list of supported checkers. + + + +### 2.2\. Installing syntastic with Pathogen + +If you already have [Pathogen][1] working then skip [Step 1](#step1) and go to +[Step 2](#step2). + + + +#### 2.2.1\. Step 1: Install pathogen.vim + +First I'll show you how to install Tim Pope's [Pathogen][1] so that it's easy to +install syntastic. Do this in your terminal so that you get the `pathogen.vim` +file and the directories it needs: +```sh +mkdir -p ~/.vim/autoload ~/.vim/bundle && \ +curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim +``` +Next you *need* to add this to your `~/.vimrc`: +```vim +execute pathogen#infect() +``` + + + +#### 2.2.2\. Step 2: Install syntastic as a Pathogen bundle + +You now have pathogen installed and can put syntastic into `~/.vim/bundle` like +this: +```sh +cd ~/.vim/bundle && \ +git clone https://github.com/scrooloose/syntastic.git +``` +Quit vim and start it back up to reload it, then type: +```vim +:Helptags +``` +If you get an error when you do this, then you probably didn't install +[Pathogen][1] right. Go back to [Step 1](#step1) and make sure you did the +following: + +1. Created both the `~/.vim/autoload` and `~/.vim/bundle` directories. +2. Added the `execute pathogen#infect()` line to your `~/.vimrc` file +3. Did the `git clone` of syntastic inside `~/.vim/bundle` +4. Have permissions to access all of these directories. + + + +## 3\. Recommended settings + +Syntastic has a large number of options that can be configured, and the +defaults are not particularly well suitable for new users. It is recommended +that you start by adding the following lines to your `vimrc` file, and return +to them after reading the manual (see `:help syntastic` in Vim): +```vim +set statusline+=%#warningmsg# +set statusline+=%{SyntasticStatuslineFlag()} +set statusline+=%* + +let g:syntastic_always_populate_loc_list = 1 +let g:syntastic_auto_loc_list = 1 +let g:syntastic_check_on_open = 1 +let g:syntastic_check_on_wq = 0 +``` + + + +## 4\. FAQ + + + +__4.1. Q. I installed syntastic but it isn't reporting any errors...__ + +A. The most likely reason is that none of the syntax checkers that it requires +is installed. For example: by default, python requires either `flake8` or +`pylint` to be installed and in your `$PATH`. To see which executables are +supported, look at the [wiki][3]. Note that aliases do not work; the actual +executables must be available in your `$PATH`. Symbolic links are okay though. +You can see syntastic's idea of available checkers by running `:SyntasticInfo`. + +A second probable reason is that none of the available checkers are +enabled. Syntastic comes preconfigured with a default list of enabled checkers +per filetype, but this list is kept short in order to prevent slowing down Vim +or trying to run conflicting checks. The command `:SyntasticInfo` will show you +which checkers are enabled. You can tell syntastic which checkers (among the +available ones) you want to run by setting `g:syntastic__checkers` in +your `vimrc` (see [below](#faqcheckers)). + +A third possible reason is that the `$PATH` seen by syntastic might not be same +as the `$PATH` in your login shell. Syntastic runs checkers using the shell +pointed to by Vim's `shell` (or by `g:syntastic_shell`, if set), and that's the +shell you need to configure to set the proper `$PATH` and environment variables +for your checkers. You can see syntastic's idea of `$PATH` by running +```vim +:echo syntastic#util#system('echo "$PATH"') +``` +on UNIX and Mac OS-X systems, or +```vim +:echo syntastic#util#system('echo %PATH%') +``` +on Windows. + +Finally, another reason it could fail is that either the command line options +or the error output for a syntax checker may have changed. In this case, make +sure you have the latest version of the syntax checker installed. If it still +fails then post an [issue][4] - or better yet, create a pull request. + + + +__4.2. Q. The `python` checker complains about syntactically valid Python 3 constructs...__ + +A. Configure the `python` checker to call a Python 3 interpreter rather than +Python 2, e.g: +```vim +let g:syntastic_python_python_exec = '/path/to/python3' +``` + + + +__4.3. Q. Are there any local checkers for HTML5 that I can use with syntastic?__ + +[HTML Tidy][18] has a fork named [HTML Tidy for HTML5][19]. It's a drop +in replacement, and syntastic can use it without changes. Just install it +somewhere and point `g:syntastic_html_tidy_exec` to its executable: +```vim +let g:syntastic_html_tidy_exec = 'tidy5' +``` +Alternatively, you can install [vnu.jar][21] from the [validator.nu][20] +project and run it as a [HTTP server][23]: +```sh +$ java -Xss512k -cp /path/to/vnu.jar nu.validator.servlet.Main 8888 +``` +Then you can [configure][22] syntastic to use it: +```vim +let g:syntastic_html_validator_api = 'http://localhost:8888/' +``` + + + +__4.4. Q. The `perl` checker has stopped working...__ + +A. The `perl` checker runs `perl -c` against your file, which in turn +__executes__ any `BEGIN`, `UNITCHECK`, and `CHECK` blocks, and any `use` +statements in your file (cf. [perlrun][10]). This is probably fine if you +wrote the file yourself, but it's a security problem if you're checking third +party files. Since there is currently no way to disable this behaviour while +still producing useful results, the checker is now disabled by default. To +(re-)enable it, make sure the `g:syntastic_perl_checkers` list includes `perl`, +and set `g:syntastic_enable_perl_checker` to 1 in your `vimrc`: +```vim +let g:syntastic_enable_perl_checker = 1 +``` + + + +__4.5. Q. What happened to the `rustc` checker?__ + +A. It is now part of the [rust.vim][12] plugin. If you install this plugin the +checker should be picked up automatically by syntastic. + + + +__4.6. Q. What happened to the `xcrun` checker?__ + +A. The `xcrun` checker used to have a security problem and it has been removed. +A better checker for __Swift__ is part of the [vim-swift][24] plugin. If you +install this plugin the checker should be picked up automatically by syntastic. + + + +__4.7. Q. I run a checker and the location list is not updated...__ +__4.7. Q. I run`:lopen` or `:lwindow` and the error window is empty...__ + +A. By default the location list is changed only when you run the `:Errors` +command, in order to minimise conflicts with other plugins. If you want the +location list to always be updated when you run the checkers, add this line to +your `vimrc`: +```vim +let g:syntastic_always_populate_loc_list = 1 +``` + + + +__4.8. Q. How can I pass additional arguments to a checker?__ + +A. Almost all syntax checkers use the `makeprgBuild()` function. Those checkers +that do can be configured using global variables. The general form of the +global `args` variables is `syntastic___args`. + +So, If you wanted to pass `--my --args --here` to the ruby mri checker you +would add this line to your `vimrc`: +```vim +let g:syntastic_ruby_mri_args = "--my --args --here" +``` + +See `:help syntastic-checker-options` for more information. + + + +__4.9. Q. Syntastic supports several checkers for my filetype - how do I tell it +which one(s) to use?__ + +A. Stick a line like this in your `vimrc`: +```vim +let g:syntastic__checkers = [''] +``` + +To see the list of supported checkers for your filetype look at the +[wiki][3]. + +e.g. Python has the following checkers, among others: `flake8`, `pyflakes`, +`pylint` and a native `python` checker. + +To tell syntastic to use `pylint`, you would use this setting: +```vim +let g:syntastic_python_checkers = ['pylint'] +``` + +Checkers can be chained together like this: +```vim +let g:syntastic_php_checkers = ['php', 'phpcs', 'phpmd'] +``` + +This is telling syntastic to run the `php` checker first, and if no errors are +found, run `phpcs`, and then `phpmd`. + +You can also run checkers explicitly by calling `:SyntasticCheck `. + +e.g. to run `phpcs` and `phpmd`: +```vim +:SyntasticCheck phpcs phpmd +``` + +This works for any checkers available for the current filetype, even if they +aren't listed in `g:syntastic__checkers`. You can't run checkers for +"foreign" filetypes though (e.g. you can't run, say, a Python checker if the +filetype of the current file is `php`). + + + +__4.10. Q. What is the difference between syntax checkers and style checkers?__ + +A. The errors and warnings they produce are highlighted differently and can +be filtered by different rules, but otherwise the distinction is pretty much +arbitrary. There is an ongoing effort to keep things consistent, so you can +_generally_ expect messages produced by syntax checkers to be _mostly_ related +to syntax, and messages produced by style checkers to be _mostly_ about style. +But there can be no formal guarantee that, say, a style checker that runs into +a syntax error wouldn't die with a fatal message, nor that a syntax checker +wouldn't give you warnings against using some constructs as being bad practice. +There is also no guarantee that messages marked as "style" are less severe than +the ones marked as "syntax" (whatever that might mean). And there are even a +few Frankenstein checkers (for example `flake8` and `pylama`) that, by their +nature, produce both kinds of messages. Syntastic is not smart enough to be +able to sort out these things by itself. + +In fact it's more useful to look at this from the perspective of filtering +unwanted messages, rather than as an indicator of severity levels. The +distinction between syntax and style is orthogonal to the distinction between +errors and warnings, and thus you can turn off messages based on level, on +type, or both. + +e.g. To disable all style messages: +```vim +let g:syntastic_quiet_messages = { "type": "style" } +``` +See `:help syntastic_quiet_messages` for details. + + + +__4.11. Q. I have enabled multiple checkers for the current filetype. How can I +display all of the errors from all of the checkers together?__ + +A. Set `g:syntastic_aggregate_errors` to 1 in your `vimrc`: +```vim +let g:syntastic_aggregate_errors = 1 +``` + +See `:help syntastic-aggregating-errors` for more details. + + + +__4.12. Q. How can I jump between the different errors without using the location +list at the bottom of the window?__ + +A. Vim provides several built-in commands for this. See `:help :lnext` and +`:help :lprevious`. + +If you use these commands a lot then you may want to add shortcut mappings to +your `vimrc`, or install something like [unimpaired][2], which provides such +mappings (among other things). + + + +__4.13. Q. The error window is closed automatically when I :quit the current buffer +but not when I :bdelete it?__ + +A. There is no safe way to handle that situation automatically, but you can +work around it: + +```vim +nnoremap :lclose:bdelete +cabbrev bd lclose\|bdelete +``` + + + +## 5\. Resources + +The preferred place for posting suggestions, reporting bugs, and general +discussions related to syntastic is the [issue tracker at GitHub][4]. +A guide for writing syntax checkers can be found in the [wiki][11]. +There are also a dedicated [google group][5], and a +[syntastic tag at StackOverflow][6]. + +Syntastic aims to provide a common interface to syntax checkers for as many +languages as possible. For particular languages, there are, of course, other +plugins that provide more functionality than syntastic. You might want to take +a look at [jedi-vim][7], [python-mode][8], or [YouCompleteMe][9]. + +[0]: https://github.com/scrooloose/syntastic/raw/master/_assets/screenshot_1.png +[1]: https://github.com/tpope/vim-pathogen +[2]: https://github.com/tpope/vim-unimpaired +[3]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers +[4]: https://github.com/scrooloose/syntastic/issues +[5]: https://groups.google.com/group/vim-syntastic +[6]: http://stackoverflow.com/questions/tagged/syntastic +[7]: https://github.com/davidhalter/jedi-vim +[8]: https://github.com/klen/python-mode +[9]: http://valloric.github.io/YouCompleteMe/ +[10]: http://perldoc.perl.org/perlrun.html#*-c* +[11]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide +[12]: https://github.com/rust-lang/rust.vim +[13]: http://www.vim.org/ +[14]: https://github.com/Shougo/neobundle.vim +[15]: https://github.com/MarcWeber/vim-addon-manager +[16]: https://github.com/junegunn/vim-plug/ +[17]: https://github.com/gmarik/Vundle.vim +[18]: http://tidy.sourceforge.net/ +[19]: http://www.htacg.org/tidy-html5/ +[20]: http://about.validator.nu/ +[21]: https://github.com/validator/validator/releases/latest +[22]: https://github.com/scrooloose/syntastic/wiki/HTML%3A---validator +[23]: http://validator.github.io/validator/#standalone +[24]: https://github.com/kballard/vim-swift +[25]: https://github.com/OmniSharp/omnisharp-vim +[26]: https://github.com/myint/syntastic-extras +[27]: https://github.com/roktas/syntastic-more + + diff --git a/config/home/vim/bundle/syntastic/_assets/screenshot_1.png b/config/home/vim/bundle/syntastic/_assets/screenshot_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c1b69f4ba26a2092aa4e9d42d2fa3ee08c6ab28a GIT binary patch literal 92425 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', 's:_checkPhp', []) + call s:_registerHandler('\m\', 's:_checkPython', []) + call s:_registerHandler('\m\" + echohl ErrorMsg + echomsg 'syntastic: error: ' . a:msg + echohl None +endfunction " }}}2 + +function! syntastic#log#oneTimeWarn(msg) abort " {{{2 + if index(s:one_time_notices_issued, a:msg) >= 0 + return + endif + + call add(s:one_time_notices_issued, a:msg) + call syntastic#log#warn(a:msg) +endfunction " }}}2 + +" @vimlint(EVL102, 1, l:OLD_VAR) +function! syntastic#log#deprecationWarn(old, new, ...) abort " {{{2 + if exists('g:syntastic_' . a:old) && !exists('g:syntastic_' . a:new) + let msg = 'variable g:syntastic_' . a:old . ' is deprecated, please use ' + + if a:0 + let OLD_VAR = g:syntastic_{a:old} + try + let NEW_VAR = eval(a:1) + let msg .= 'in its stead: let g:syntastic_' . a:new . ' = ' . string(NEW_VAR) + let g:syntastic_{a:new} = NEW_VAR + catch + let msg .= 'g:syntastic_' . a:new . ' instead' + endtry + else + let msg .= 'g:syntastic_' . a:new . ' instead' + let g:syntastic_{a:new} = g:syntastic_{a:old} + endif + + call syntastic#log#oneTimeWarn(msg) + endif +endfunction " }}}2 +" @vimlint(EVL102, 0, l:OLD_VAR) + +function! syntastic#log#debug(level, msg, ...) abort " {{{2 + if !s:_isDebugEnabled(a:level) + return + endif + + let leader = s:_log_timestamp() + call s:_logRedirect(1) + + if a:0 > 0 + " filter out dictionary functions + echomsg leader . a:msg . ' ' . + \ strtrans(string(type(a:1) == type({}) || type(a:1) == type([]) ? + \ filter(copy(a:1), 'type(v:val) != type(function("tr"))') : a:1)) + else + echomsg leader . a:msg + endif + + call s:_logRedirect(0) +endfunction " }}}2 + +function! syntastic#log#debugShowOptions(level, names) abort " {{{2 + if !s:_isDebugEnabled(a:level) + return + endif + + let leader = s:_log_timestamp() + call s:_logRedirect(1) + + let vlist = copy(type(a:names) == type('') ? [a:names] : a:names) + if !empty(vlist) + call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))") + echomsg leader . join(vlist, ', ') + endif + call s:_logRedirect(0) +endfunction " }}}2 + +function! syntastic#log#debugShowVariables(level, names) abort " {{{2 + if !s:_isDebugEnabled(a:level) + return + endif + + let leader = s:_log_timestamp() + call s:_logRedirect(1) + + let vlist = type(a:names) == type('') ? [a:names] : a:names + for name in vlist + let msg = s:_format_variable(name) + if msg !=# '' + echomsg leader . msg + endif + endfor + + call s:_logRedirect(0) +endfunction " }}}2 + +function! syntastic#log#debugDump(level) abort " {{{2 + if !s:_isDebugEnabled(a:level) + return + endif + + call syntastic#log#debugShowVariables( a:level, sort(keys(g:_SYNTASTIC_DEFAULTS)) ) +endfunction " }}}2 + +" }}}1 + +" Private functions {{{1 + +function! s:_isDebugEnabled_smart(level) abort " {{{2 + return and(g:syntastic_debug, a:level) +endfunction " }}}2 + +function! s:_isDebugEnabled_dumb(level) abort " {{{2 + " poor man's bit test for bit N, assuming a:level == 2**N + return (g:syntastic_debug / a:level) % 2 +endfunction " }}}2 + +let s:_isDebugEnabled = function(exists('*and') ? 's:_isDebugEnabled_smart' : 's:_isDebugEnabled_dumb') +lockvar s:_isDebugEnabled + +function! s:_logRedirect(on) abort " {{{2 + if exists('g:syntastic_debug_file') + if a:on + try + execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file, 1)) + catch /\m^Vim\%((\a\+)\)\=:/ + silent! redir END + unlet g:syntastic_debug_file + endtry + else + silent! redir END + endif + endif +endfunction " }}}2 + +" }}}1 + +" Utilities {{{1 + +function! s:_log_timestamp() abort " {{{2 + return 'syntastic: ' . split(reltimestr(reltime(g:_SYNTASTIC_START)))[0] . ': ' +endfunction " }}}2 + +function! s:_format_variable(name) abort " {{{2 + let vals = [] + if exists('g:syntastic_' . a:name) + call add(vals, 'g:syntastic_' . a:name . ' = ' . strtrans(string(g:syntastic_{a:name}))) + endif + if exists('b:syntastic_' . a:name) + call add(vals, 'b:syntastic_' . a:name . ' = ' . strtrans(string(b:syntastic_{a:name}))) + endif + + return join(vals, ', ') +endfunction " }}}2 + +" }}}1 + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/syntastic/autoload/syntastic/postprocess.vim b/config/home/vim/bundle/syntastic/autoload/syntastic/postprocess.vim new file mode 100644 index 0000000..136fa58 --- /dev/null +++ b/config/home/vim/bundle/syntastic/autoload/syntastic/postprocess.vim @@ -0,0 +1,73 @@ +if exists('g:loaded_syntastic_postprocess_autoload') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_postprocess_autoload = 1 + +let s:save_cpo = &cpo +set cpo&vim + +" Public functions {{{1 + +" merge consecutive blanks +function! syntastic#postprocess#compressWhitespace(errors) abort " {{{2 + for e in a:errors + let e['text'] = substitute(e['text'], "\001", '', 'g') + let e['text'] = substitute(e['text'], '\n', ' ', 'g') + let e['text'] = substitute(e['text'], '\m\s\{2,}', ' ', 'g') + let e['text'] = substitute(e['text'], '\m^\s\+', '', '') + let e['text'] = substitute(e['text'], '\m\s\+$', '', '') + endfor + + return a:errors +endfunction " }}}2 + +" remove spurious CR under Cygwin +function! syntastic#postprocess#cygwinRemoveCR(errors) abort " {{{2 + if has('win32unix') + for e in a:errors + let e['text'] = substitute(e['text'], '\r', '', 'g') + endfor + endif + + return a:errors +endfunction " }}}2 + +" decode XML entities +function! syntastic#postprocess#decodeXMLEntities(errors) abort " {{{2 + for e in a:errors + let e['text'] = syntastic#util#decodeXMLEntities(e['text']) + endfor + + return a:errors +endfunction " }}}2 + +" filter out errors referencing other files +function! syntastic#postprocess#filterForeignErrors(errors) abort " {{{2 + return filter(copy(a:errors), 'get(v:val, "bufnr") == ' . bufnr('')) +endfunction " }}}2 + +" make sure line numbers are not past end of buffers +" XXX: this loads all referenced buffers in memory +function! syntastic#postprocess#guards(errors) abort " {{{2 + let buffers = syntastic#util#unique(map(filter(copy(a:errors), 'v:val["valid"]'), 'str2nr(v:val["bufnr"])')) + + let guards = {} + for b in buffers + let guards[b] = len(getbufline(b, 1, '$')) + endfor + + for e in a:errors + if e['valid'] && e['lnum'] > guards[e['bufnr']] + let e['lnum'] = guards[e['bufnr']] + endif + endfor + + return a:errors +endfunction " }}}2 + +" }}}1 + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/syntastic/autoload/syntastic/preprocess.vim b/config/home/vim/bundle/syntastic/autoload/syntastic/preprocess.vim new file mode 100644 index 0000000..6800295 --- /dev/null +++ b/config/home/vim/bundle/syntastic/autoload/syntastic/preprocess.vim @@ -0,0 +1,316 @@ +if exists('g:loaded_syntastic_preprocess_autoload') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_preprocess_autoload = 1 + +let s:save_cpo = &cpo +set cpo&vim + +" Public functions {{{1 + +function! syntastic#preprocess#cabal(errors) abort " {{{2 + let out = [] + let star = 0 + for err in a:errors + if star + if err ==# '' + let star = 0 + else + let out[-1] .= ' ' . err + endif + else + call add(out, err) + if err =~# '\m^*\s' + let star = 1 + endif + endif + endfor + return out +endfunction " }}}2 + +function! syntastic#preprocess#checkstyle(errors) abort " {{{2 + let out = [] + let fname = expand('%', 1) + for err in a:errors + if match(err, '\m') > -1 + let line = str2nr(matchstr(err, '\m\ \[[^]]+\])+\ze:'', "", "")') +endfunction " }}}2 + +" @vimlint(EVL102, 1, l:true) +" @vimlint(EVL102, 1, l:false) +" @vimlint(EVL102, 1, l:null) +function! syntastic#preprocess#flow(errors) abort " {{{2 + " JSON artifacts + let true = 1 + let false = 0 + let null = '' + + " A hat tip to Marc Weber for this trick + " http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763 + try + let errs = eval(join(a:errors, '')) + catch + let errs = {} + endtry + + let out = [] + if type(errs) == type({}) && has_key(errs, 'errors') && type(errs['errors']) == type([]) + for e in errs['errors'] + if type(e) == type({}) && has_key(e, 'message') && type(e['message']) == type([]) && len(e['message']) + let m = e['message'][0] + let t = e['message'][1:] + + try + let msg = + \ m['path'] . ':' . + \ m['line'] . ':' . + \ m['start'] . ':' . + \ (m['line'] ==# m['endline'] && str2nr(m['end']) > 0 ? m['end'] . ':' : '') . + \ ' ' . m['descr'] + + if len(t) + let msg .= ' ' . join(map(t, + \ 'v:val["descr"] . " (" . v:val["path"] . ":" . v:val["line"] . ":" . v:val["start"] . ' . + \ '"," . (v:val["line"] !=# v:val["endline"] ? v:val["endline"] . ":" : "") . ' . + \ 'v:val["end"] . ")"')) + endif + + let msg = substitute(msg, '\r', '', 'g') + let msg = substitute(msg, '\n', ' ', 'g') + + call add(out, msg) + catch /\m^Vim\%((\a\+)\)\=:E716/ + call syntastic#log#warn('checker javascript/flow: unknown error format') + let out = [] + break + endtry + else + call syntastic#log#warn('checker javascript/flow: unknown error format') + let out = [] + break + endif + endfor + else + call syntastic#log#warn('checker javascript/flow: unknown error format') + endif + + return out +endfunction " }}}2 +" @vimlint(EVL102, 0, l:true) +" @vimlint(EVL102, 0, l:false) +" @vimlint(EVL102, 0, l:null) + +function! syntastic#preprocess#killEmpty(errors) abort " {{{2 + return filter(copy(a:errors), 'v:val !=# ""') +endfunction " }}}2 + +function! syntastic#preprocess#perl(errors) abort " {{{2 + let out = [] + + for e in a:errors + let parts = matchlist(e, '\v^(.*)\sat\s(.{-})\sline\s(\d+)(.*)$') + if !empty(parts) + call add(out, parts[2] . ':' . parts[3] . ':' . parts[1] . parts[4]) + endif + endfor + + return syntastic#util#unique(out) +endfunction " }}}2 + +" @vimlint(EVL102, 1, l:true) +" @vimlint(EVL102, 1, l:false) +" @vimlint(EVL102, 1, l:null) +function! syntastic#preprocess#prospector(errors) abort " {{{2 + " JSON artifacts + let true = 1 + let false = 0 + let null = '' + + " A hat tip to Marc Weber for this trick + " http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763 + try + let errs = eval(join(a:errors, '')) + catch + let errs = {} + endtry + + let out = [] + if type(errs) == type({}) && has_key(errs, 'messages') + if type(errs['messages']) == type([]) + for e in errs['messages'] + if type(e) == type({}) + try + if e['source'] ==# 'pylint' + let e['location']['character'] += 1 + endif + + let msg = + \ e['location']['path'] . ':' . + \ e['location']['line'] . ':' . + \ e['location']['character'] . ': ' . + \ e['code'] . ' ' . + \ e['message'] . ' ' . + \ '[' . e['source'] . ']' + + call add(out, msg) + catch /\m^Vim\%((\a\+)\)\=:E716/ + call syntastic#log#warn('checker python/prospector: unknown error format') + let out = [] + break + endtry + else + call syntastic#log#warn('checker python/prospector: unknown error format') + let out = [] + break + endif + endfor + else + call syntastic#log#warn('checker python/prospector: unknown error format') + endif + endif + + return out +endfunction " }}}2 +" @vimlint(EVL102, 0, l:true) +" @vimlint(EVL102, 0, l:false) +" @vimlint(EVL102, 0, l:null) + +function! syntastic#preprocess#rparse(errors) abort " {{{2 + let errlist = copy(a:errors) + + " remove uninteresting lines and handle continuations + let i = 0 + while i < len(errlist) + if i > 0 && errlist[i][:1] ==# ' ' && errlist[i] !~# '\m\s\+\^$' + let errlist[i-1] .= errlist[i][1:] + call remove(errlist, i) + elseif errlist[i] !~# '\m^\(Lint:\|Lint checking:\|Error in\) ' + call remove(errlist, i) + else + let i += 1 + endif + endwhile + + let out = [] + let fname = '' + for e in errlist + if match(e, '\m^Lint: ') == 0 + let parts = matchlist(e, '\m^Lint: \(.*\): found on lines \([0-9, ]\+\)\(+\(\d\+\) more\)\=') + if len(parts) >= 3 + for line in split(parts[2], '\m,\s*') + call add(out, 'E:' . fname . ':' . line . ': ' . parts[1]) + endfor + endif + if len(parts) >= 5 && parts[4] !=# '' + call add(out, 'E:' . fname . ':0: ' . parts[1] . ' - ' . parts[4] . ' messages not shown') + endif + elseif match(e, '\m^Lint checking: ') == 0 + let fname = matchstr(e, '\m^Lint checking: \zs.*') + elseif match(e, '\m^Error in ') == 0 + call add(out, substitute(e, '\m^Error in .\+ : .\+\ze:\d\+:\d\+: ', 'E:' . fname, '')) + endif + endfor + + return out +endfunction " }}}2 + +function! syntastic#preprocess#tslint(errors) abort " {{{2 + return map(copy(a:errors), 'substitute(v:val, ''\m^\(([^)]\+)\)\s\(.\+\)$'', ''\2 \1'', "")') +endfunction " }}}2 + +function! syntastic#preprocess#validator(errors) abort " {{{2 + let out = [] + for e in a:errors + let parts = matchlist(e, '\v^"([^"]+)"(.+)') + if len(parts) >= 3 + " URL decode, except leave alone any "+" + let parts[1] = substitute(parts[1], '\m%\(\x\x\)', '\=nr2char("0x".submatch(1))', 'g') + let parts[1] = substitute(parts[1], '\m\\"', '"', 'g') + let parts[1] = substitute(parts[1], '\m\\\\', '\\', 'g') + call add(out, '"' . parts[1] . '"' . parts[2]) + endif + endfor + return out +endfunction " }}}2 + +" @vimlint(EVL102, 1, l:true) +" @vimlint(EVL102, 1, l:false) +" @vimlint(EVL102, 1, l:null) +function! syntastic#preprocess#vint(errors) abort " {{{2 + " JSON artifacts + let true = 1 + let false = 0 + let null = '' + + " A hat tip to Marc Weber for this trick + " http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763 + try + let errs = eval(join(a:errors, '')) + catch + let errs = [] + endtry + + let out = [] + if type(errs) == type([]) + for e in errs + if type(e) == type({}) + try + let msg = + \ e['file_path'] . ':' . + \ e['line_number'] . ':' . + \ e['column_number'] . ':' . + \ e['severity'][0] . ': ' . + \ e['description'] . ' (' . + \ e['policy_name'] . ')' + + call add(out, msg) + catch /\m^Vim\%((\a\+)\)\=:E716/ + call syntastic#log#warn('checker vim/vint: unknown error format') + let out = [] + break + endtry + else + call syntastic#log#warn('checker vim/vint: unknown error format') + let out = [] + break + endif + endfor + else + call syntastic#log#warn('checker vim/vint: unknown error format') + endif + + return out +endfunction " }}}2 +" @vimlint(EVL102, 0, l:true) +" @vimlint(EVL102, 0, l:false) +" @vimlint(EVL102, 0, l:null) + +" }}}1 + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/syntastic/autoload/syntastic/util.vim b/config/home/vim/bundle/syntastic/autoload/syntastic/util.vim new file mode 100644 index 0000000..4b652d2 --- /dev/null +++ b/config/home/vim/bundle/syntastic/autoload/syntastic/util.vim @@ -0,0 +1,414 @@ +if exists('g:loaded_syntastic_util_autoload') || !exists('g:loaded_syntastic_plugin') + finish +endif +let g:loaded_syntastic_util_autoload = 1 + +let s:save_cpo = &cpo +set cpo&vim + +" Public functions {{{1 + +function! syntastic#util#isRunningWindows() abort " {{{2 + return has('win16') || has('win32') || has('win64') +endfunction " }}}2 + +function! syntastic#util#DevNull() abort " {{{2 + if syntastic#util#isRunningWindows() + return 'NUL' + endif + return '/dev/null' +endfunction " }}}2 + +" Get directory separator +function! syntastic#util#Slash() abort " {{{2 + return (!exists('+shellslash') || &shellslash) ? '/' : '\' +endfunction " }}}2 + +function! syntastic#util#CygwinPath(path) abort " {{{2 + return substitute(syntastic#util#system('cygpath -m ' . syntastic#util#shescape(a:path)), "\n", '', 'g') +endfunction " }}}2 + +function! syntastic#util#system(command) abort " {{{2 + let old_shell = &shell + let old_lc_messages = $LC_MESSAGES + let old_lc_all = $LC_ALL + + let &shell = syntastic#util#var('shell') + let $LC_MESSAGES = 'C' + let $LC_ALL = '' + + let out = system(a:command) + + let $LC_ALL = old_lc_all + let $LC_MESSAGES = old_lc_messages + + let &shell = old_shell + + return out +endfunction " }}}2 + +" Create a temporary directory +function! syntastic#util#tmpdir() abort " {{{2 + let tempdir = '' + + if (has('unix') || has('mac')) && executable('mktemp') + " TODO: option "-t" to mktemp(1) is not portable + let tmp = $TMPDIR !=# '' ? $TMPDIR : $TMP !=# '' ? $TMP : '/tmp' + let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . getpid() . '-XXXXXXXX'), "\n") + if v:shell_error == 0 && len(out) == 1 + let tempdir = out[0] + endif + endif + + if tempdir ==# '' + if has('win32') || has('win64') + let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . getpid() + elseif has('win32unix') + let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid()) + elseif $TMPDIR !=# '' + let tempdir = $TMPDIR . '/vim-syntastic-' . getpid() + else + let tempdir = '/tmp/vim-syntastic-' . getpid() + endif + + try + call mkdir(tempdir, 'p', 0700) + catch /\m^Vim\%((\a\+)\)\=:E739/ + call syntastic#log#error(v:exception) + let tempdir = '.' + endtry + endif + + return tempdir +endfunction " }}}2 + +" Recursively remove a directory +function! syntastic#util#rmrf(what) abort " {{{2 + " try to make sure we don't delete directories we didn't create + if a:what !~? 'vim-syntastic-' + return + endif + + if getftype(a:what) ==# 'dir' + if !exists('s:rmrf') + let s:rmrf = + \ has('unix') || has('mac') ? 'rm -rf' : + \ has('win32') || has('win64') ? 'rmdir /S /Q' : + \ has('win16') || has('win95') || has('dos16') || has('dos32') ? 'deltree /Y' : '' + endif + + if s:rmrf !=# '' + silent! call syntastic#util#system(s:rmrf . ' ' . syntastic#util#shescape(a:what)) + else + call s:_rmrf(a:what) + endif + else + silent! call delete(a:what) + endif +endfunction " }}}2 + +"search the first 5 lines of the file for a magic number and return a map +"containing the args and the executable +" +"e.g. +" +"#!/usr/bin/perl -f -bar +" +"returns +" +"{'exe': '/usr/bin/perl', 'args': ['-f', '-bar']} +function! syntastic#util#parseShebang() abort " {{{2 + for lnum in range(1, 5) + let line = getline(lnum) + if line =~# '^#!' + let line = substitute(line, '\v^#!\s*(\S+/env(\s+-\S+)*\s+)?', '', '') + let exe = matchstr(line, '\m^\S*\ze') + let args = split(matchstr(line, '\m^\S*\zs.*')) + return { 'exe': exe, 'args': args } + endif + endfor + + return { 'exe': '', 'args': [] } +endfunction " }}}2 + +" Get the value of a variable. Allow local variables to override global ones. +function! syntastic#util#var(name, ...) abort " {{{2 + return + \ exists('b:syntastic_' . a:name) ? b:syntastic_{a:name} : + \ exists('g:syntastic_' . a:name) ? g:syntastic_{a:name} : + \ a:0 > 0 ? a:1 : '' +endfunction " }}}2 + +" Parse a version string. Return an array of version components. +function! syntastic#util#parseVersion(version, ...) abort " {{{2 + return map(split(matchstr( a:version, a:0 ? a:1 : '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)') +endfunction " }}}2 + +" Verify that the 'installed' version is at least the 'required' version. +" +" 'installed' and 'required' must be arrays. If they have different lengths, +" the "missing" elements will be assumed to be 0 for the purposes of checking. +" +" See http://semver.org for info about version numbers. +function! syntastic#util#versionIsAtLeast(installed, required) abort " {{{2 + return syntastic#util#compareLexi(a:installed, a:required) >= 0 +endfunction " }}}2 + +" Almost lexicographic comparison of two lists of integers. :) If lists +" have different lengths, the "missing" elements are assumed to be 0. +function! syntastic#util#compareLexi(a, b) abort " {{{2 + for idx in range(max([len(a:a), len(a:b)])) + let a_element = str2nr(get(a:a, idx, 0)) + let b_element = str2nr(get(a:b, idx, 0)) + if a_element != b_element + return a_element > b_element ? 1 : -1 + endif + endfor + " still here, thus everything matched + return 0 +endfunction " }}}2 + +" strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen() +" and hope for the best :) +let s:_width = function(exists('*strwidth') ? 'strwidth' : 'strlen') +lockvar s:_width + +function! syntastic#util#screenWidth(str, tabstop) abort " {{{2 + let chunks = split(a:str, "\t", 1) + let width = s:_width(chunks[-1]) + for c in chunks[:-2] + let cwidth = s:_width(c) + let width += cwidth + a:tabstop - cwidth % a:tabstop + endfor + return width +endfunction " }}}2 + +"print as much of a:msg as possible without "Press Enter" prompt appearing +function! syntastic#util#wideMsg(msg) abort " {{{2 + let old_ruler = &ruler + let old_showcmd = &showcmd + + "This is here because it is possible for some error messages to + "begin with \n which will cause a "press enter" prompt. + let msg = substitute(a:msg, "\n", '', 'g') + + "convert tabs to spaces so that the tabs count towards the window + "width as the proper amount of characters + let chunks = split(msg, "\t", 1) + let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &tabstop - s:_width(v:val) % &tabstop)'), '') . chunks[-1] + let msg = strpart(msg, 0, &columns - 1) + + set noruler noshowcmd + call syntastic#util#redraw(0) + + echo msg + + let &ruler = old_ruler + let &showcmd = old_showcmd +endfunction " }}}2 + +" Check whether a buffer is loaded, listed, and not hidden +function! syntastic#util#bufIsActive(buffer) abort " {{{2 + " convert to number, or hell breaks loose + let buf = str2nr(a:buffer) + + if !bufloaded(buf) || !buflisted(buf) + return 0 + endif + + " get rid of hidden buffers + for tab in range(1, tabpagenr('$')) + if index(tabpagebuflist(tab), buf) >= 0 + return 1 + endif + endfor + + return 0 +endfunction " }}}2 + +" start in directory a:where and walk up the parent folders until it +" finds a file matching a:what; return path to that file +function! syntastic#util#findInParent(what, where) abort " {{{2 + let here = fnamemodify(a:where, ':p') + + let root = syntastic#util#Slash() + if syntastic#util#isRunningWindows() && here[1] ==# ':' + " The drive letter is an ever-green source of fun. That's because + " we don't care about running syntastic on Amiga these days. ;) + let root = fnamemodify(root, ':p') + let root = here[0] . root[1:] + endif + + let old = '' + while here !=# '' + let p = split(globpath(here, a:what, 1), '\n') + + if !empty(p) + return fnamemodify(p[0], ':p') + elseif here ==? root || here ==? old + break + endif + + let old = here + + " we use ':h:h' rather than ':h' since ':p' adds a trailing '/' + " if 'here' is a directory + let here = fnamemodify(here, ':p:h:h') + endwhile + + return '' +endfunction " }}}2 + +" Returns unique elements in a list +function! syntastic#util#unique(list) abort " {{{2 + let seen = {} + let uniques = [] + for e in a:list + if !has_key(seen, e) + let seen[e] = 1 + call add(uniques, e) + endif + endfor + return uniques +endfunction " }}}2 + +" A less noisy shellescape() +function! syntastic#util#shescape(string) abort " {{{2 + return a:string =~# '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string) +endfunction " }}}2 + +" A less noisy shellescape(expand()) +function! syntastic#util#shexpand(string, ...) abort " {{{2 + return syntastic#util#shescape(a:0 ? expand(a:string, a:1) : expand(a:string, 1)) +endfunction " }}}2 + +" Escape arguments +function! syntastic#util#argsescape(opt) abort " {{{2 + if type(a:opt) == type('') && a:opt !=# '' + return [a:opt] + elseif type(a:opt) == type([]) + return map(copy(a:opt), 'syntastic#util#shescape(v:val)') + endif + + return [] +endfunction " }}}2 + +" decode XML entities +function! syntastic#util#decodeXMLEntities(string) abort " {{{2 + let str = a:string + let str = substitute(str, '\m<', '<', 'g') + let str = substitute(str, '\m>', '>', 'g') + let str = substitute(str, '\m"', '"', 'g') + let str = substitute(str, '\m'', "'", 'g') + let str = substitute(str, '\m&', '\&', 'g') + return str +endfunction " }}}2 + +function! syntastic#util#redraw(full) abort " {{{2 + if a:full + redraw! + else + redraw + endif +endfunction " }}}2 + +function! syntastic#util#dictFilter(errors, filter) abort " {{{2 + let rules = s:_translateFilter(a:filter) + " call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, "applying filter:", rules) + try + call filter(a:errors, rules) + catch /\m^Vim\%((\a\+)\)\=:E/ + let msg = matchstr(v:exception, '\m^Vim\%((\a\+)\)\=:\zs.*') + call syntastic#log#error('quiet_messages: ' . msg) + endtry +endfunction " }}}2 + +" Return a [seconds, fractions] list of strings, representing the +" (hopefully high resolution) time since program start +function! syntastic#util#stamp() abort " {{{2 + return split( split(reltimestr(reltime(g:_SYNTASTIC_START)))[0], '\.' ) +endfunction " }}}2 + +" }}}1 + +" Private functions {{{1 + +function! s:_translateFilter(filters) abort " {{{2 + let conditions = [] + for k in keys(a:filters) + if type(a:filters[k]) == type([]) + call extend(conditions, map(copy(a:filters[k]), 's:_translateElement(k, v:val)')) + else + call add(conditions, s:_translateElement(k, a:filters[k])) + endif + endfor + + if conditions == [] + let conditions = ['1'] + endif + return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ') +endfunction " }}}2 + +function! s:_translateElement(key, term) abort " {{{2 + let fkey = a:key + if fkey[0] ==# '!' + let fkey = fkey[1:] + let not = 1 + else + let not = 0 + endif + + if fkey ==? 'level' + let op = not ? ' ==? ' : ' !=? ' + let ret = 'v:val["type"]' . op . string(a:term[0]) + elseif fkey ==? 'type' + if a:term ==? 'style' + let op = not ? ' ==? ' : ' !=? ' + let ret = 'get(v:val, "subtype", "")' . op . '"style"' + else + let op = not ? '!' : '' + let ret = op . 'has_key(v:val, "subtype")' + endif + elseif fkey ==? 'regex' + let op = not ? ' =~? ' : ' !~? ' + let ret = 'v:val["text"]' . op . string(a:term) + elseif fkey ==? 'file' || fkey[:4] ==? 'file:' + let op = not ? ' =~# ' : ' !~# ' + let ret = 'bufname(str2nr(v:val["bufnr"]))' + let mod = fkey[4:] + if mod !=# '' + let ret = 'fnamemodify(' . ret . ', ' . string(mod) . ')' + endif + let ret .= op . string(a:term) + else + call syntastic#log#warn('quiet_messages: ignoring invalid key ' . strtrans(string(fkey))) + let ret = '1' + endif + return ret +endfunction " }}}2 + +function! s:_rmrf(what) abort " {{{2 + if !exists('s:rmdir') + let s:rmdir = syntastic#util#shescape(get(g:, 'netrw_localrmdir', 'rmdir')) + endif + + if getftype(a:what) ==# 'dir' + if filewritable(a:what) != 2 + return + endif + + for f in split(globpath(a:what, '*', 1), "\n") + call s:_rmrf(f) + endfor + silent! call syntastic#util#system(s:rmdir . ' ' . syntastic#util#shescape(a:what)) + else + silent! call delete(a:what) + endif +endfunction " }}}2 + +" }}}1 + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/config/home/vim/bundle/syntastic/doc/syntastic.txt b/config/home/vim/bundle/syntastic/doc/syntastic.txt new file mode 100644 index 0000000..c64b336 --- /dev/null +++ b/config/home/vim/bundle/syntastic/doc/syntastic.txt @@ -0,0 +1,956 @@ +*syntastic.txt* Syntax checking on the fly has never been so pimp. +*syntastic* + + + It's a bird! It's a plane! ZOMG It's ... ~ + + _____ __ __ _ ~ + / ___/__ ______ / /_____ ______/ /_(_)____ ~ + \__ \/ / / / __ \/ __/ __ `/ ___/ __/ / ___/ ~ + ___/ / /_/ / / / / /_/ /_/ (__ ) /_/ / /__ ~ + /____/\__, /_/ /_/\__/\__,_/____/\__/_/\___/ ~ + /____/ ~ + + + + Reference Manual~ + + +============================================================================== +CONTENTS *syntastic-contents* + + 1.Intro........................................|syntastic-intro| + 1.1.Quick start............................|syntastic-quickstart| + 1.2.Recommended settings...................|syntastic-recommended| + 2.Functionality provided.......................|syntastic-functionality| + 2.1.The statusline flag....................|syntastic-statusline-flag| + 2.2.Error signs............................|syntastic-error-signs| + 2.3.Error window...........................|syntastic-error-window| + 2.4.Error highlighting.....................|syntastic-highlighting| + 2.5.Aggregating errors.....................|syntastic-aggregating-errors| + 2.6.Filtering errors.......................|syntastic-filtering-errors| + 3.Commands.....................................|syntastic-commands| + 4.Global Options...............................|syntastic-global-options| + 5.Checker Options..............................|syntastic-checker-options| + 5.1.Choosing which checkers to use.........|syntastic-filetype-checkers| + 5.2.Choosing the executable................|syntastic-config-exec| + 5.3.Configuring specific checkers..........|syntastic-config-makeprg| + 5.4.Sorting errors.........................|syntastic-config-sort| + 6.Notes........................................|syntastic-notes| + 6.1.Handling of composite filetypes........|syntastic-composite| + 6.2.Editing files over network.............|syntastic-netrw| + 6.3.The 'shellslash' option................|syntastic-shellslash| + 7.Compatibility with other software............|syntastic-compatibility| + 7.1.The csh and tcsh shells................|syntastic-csh| + 7.2.Eclim..................................|syntastic-eclim| + 7.3.The fish shell.........................|syntastic-fish| + 7.4.The fizsh shell........................|syntastic-fizsh| + 7.5.powerline..............................|syntastic-powerline| + 7.6.The PowerShell shell...................|syntastic-powershell| + 7.7.python-mode............................|syntastic-pymode| + 7.8.vim-auto-save..........................|syntastic-vim-auto-save| + 7.9.vim-go.................................|syntastic-vim-go| + 7.10.vim-virtualenv........................|syntastic-vim-virtualenv| + 7.11.YouCompleteMe.........................|syntastic-ycm| + 8.About........................................|syntastic-about| + 9.License......................................|syntastic-license| + + +============================================================================== +1. Intro *syntastic-intro* + +Syntastic is a syntax checking plugin that runs files through external syntax +checkers. This can be done on demand, or automatically as files are saved and +opened. If syntax errors are detected, the user is notified and is happy +because they didn't have to compile their code or execute their script to find +them. + +Syntastic comes in two parts: the syntax checker plugins, and the core. The +syntax checker plugins are defined on a per-filetype basis where each one wraps +up an external syntax checking program. The core script delegates off to these +plugins and uses their output to provide the syntastic functionality. + +Take a look at the wiki for a list of supported filetypes and checkers: + + https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers + +Note: This doc only deals with using syntastic. To learn how to write syntax +checker integrations, see the guide on the GitHub wiki: + + https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide + +------------------------------------------------------------------------------ +1.1. Quick start *syntastic-quickstart* + +Syntastic comes preconfigured with a default list of enabled checkers per +filetype. This list is kept reasonably short to prevent slowing down Vim or +trying to use conflicting checkers. + +You can see the list of checkers available for the current filetype with the +|:SyntasticInfo| command. + +You probably want to override the configured list of checkers for the +filetypes you use, and also change the arguments passed to specific checkers +to suit your needs. See |syntastic-checker-options| below for details. + +Use |:SyntasticCheck| to manually check right now. Use |:Errors| to open the +|location-list| window, and |:lclose| to close it. You can clear the error +list with |:SyntasticReset|, and you can use |:SyntasticToggleMode| to switch +between active (checking on writing the buffer) and passive (manual) checking. + +You don't have to switch focus to the |location-list| window to jump to the +different errors. Vim provides several built-in commands for this, for +example |:lnext| and |:lprevious|. You may want to add shortcut mappings for +these commands, or perhaps install a plugin such as Tim Pope's 'unimpaired' +(see https://github.com/tpope/vim-unimpaired) that provides such mappings. + +------------------------------------------------------------------------------ +1.2. Recommended settings *syntastic-recommended* + +Syntastic has a large number of options that can be configured, and the +defaults are not particularly well suitable for new users. It is recommended +that you start by adding the following lines to your vimrc, and return to them +later as needed: > + set statusline+=%#warningmsg# + set statusline+=%{SyntasticStatuslineFlag()} + set statusline+=%* + + let g:syntastic_always_populate_loc_list = 1 + let g:syntastic_auto_loc_list = 1 + let g:syntastic_check_on_open = 1 + let g:syntastic_check_on_wq = 0 +< +============================================================================== +2. Functionality provided *syntastic-functionality* + +Syntax checking can be done automatically or on demand (see +|'syntastic_mode_map'| and |:SyntasticToggleMode| for configuring this). + +When syntax checking is done, the features below can be used to notify the +user of errors. See |syntastic-global-options| for how to configure and +activate/deactivate these features. + + * A statusline flag + * Signs beside lines with errors + * The |location-list| can be populated with the errors for the associated + buffer + * Erroneous parts of lines can be highlighted (this functionality is only + provided by some syntax checkers) + * Balloons (if the |+balloon_eval| feature is compiled in) can be used to + display error messages for erroneous lines when hovering the mouse over + them + * Error messages from multiple checkers can be aggregated in a single list + +------------------------------------------------------------------------------ +2.1. The statusline flag *syntastic-statusline-flag* + +To use the statusline flag, this must appear in your |'statusline'| setting > + %{SyntasticStatuslineFlag()} +< +Something like this could be more useful: > + set statusline+=%#warningmsg# + set statusline+=%{SyntasticStatuslineFlag()} + set statusline+=%* +< +When syntax errors are detected a flag will be shown. The content of the flag +is derived from the |syntastic_stl_format| option. + +------------------------------------------------------------------------------ +2.2. Error signs *syntastic-error-signs* + +Syntastic uses the |:sign| commands to mark lines with errors and warnings in +the sign column. To enable this feature, use the |'syntastic_enable_signs'| +option. + +Signs are colored using the Error and Todo syntax highlight groups by default. +If you wish to customize the colors for the signs, you can use the following +groups: + SyntasticErrorSign - For syntax errors, links to 'error' by default + SyntasticWarningSign - For syntax warnings, links to 'todo' by default + SyntasticStyleErrorSign - For style errors, links to 'SyntasticErrorSign' + by default + SyntasticStyleWarningSign - For style warnings, links to + 'SyntasticWarningSign' by default + +Example: > + highlight SyntasticErrorSign guifg=white guibg=red +< +To set up highlighting for the line where a sign resides, you can use the +following highlight groups: + SyntasticErrorLine + SyntasticWarningLine + SyntasticStyleErrorLine - Links to 'SyntasticErrorLine' by default + SyntasticStyleWarningLine - Links to 'SyntasticWarningLine' by default + +Example: > + highlight SyntasticErrorLine guibg=#2f0000 +< +------------------------------------------------------------------------------ +2.3. The error window *syntastic-error-window* + +You can use the |:Errors| command to display the errors for the current buffer +in the |location-list|. + +Note that when you use |:Errors| the current location list is overwritten with +Syntastic's own location list. The location list is also overwritten when +|syntastic_auto_jump| is non-zero and the cursor has to jump to an issue. + +By default syntastic doesn't fill the |location-list| with the errors found by +the checkers, in order to reduce clashes with other plugins. Consequently, if +you run |:lopen| or |:lwindow| rather than |:Errors| to open the error window you +wouldn't see syntastic's list of errors. If you insist on using |:lopen| or +|:lwindow| you should either run |:SyntasticSetLoclist| after running the checks, +or set |syntastic_always_populate_loc_list| which tells syntastic to update the +|location-list| automatically. + +------------------------------------------------------------------------------ +2.4. Error highlighting *syntastic-highlighting* + +Some checkers provide enough information for syntastic to be able to highlight +errors. By default the SpellBad syntax highlight group is used to color errors, +and the SpellCap group is used for warnings. If you wish to customize the +colors for highlighting you can use the following groups: + SyntasticError - Links to 'SpellBad' by default + SyntasticWarning - Links to 'SpellCap' by default + SyntasticStyleError - Links to SyntasticError by default + SyntasticStyleWarning - Links to SyntasticWarning by default + +Example: > + highlight SyntasticError guibg=#2f0000 +< +------------------------------------------------------------------------------ +2.5. Aggregating errors *syntastic-aggregating-errors* + +By default, namely if |'syntastic_aggregate_errors'| is unset, syntastic runs +in turn the checkers corresponding to the filetype of the current file (see +|syntastic-filetype-checkers|), and stops as soon as a checker reports any +errors. It then notifies you of the errors using the notification mechanisms +above. In this mode error lists are always produced by a single checker, and, +if you open the error window, the name of the checker that generated the errors +is shown on the statusline of the error window. + +If |'syntastic_aggregate_errors'| is set, syntastic runs all checkers that +apply (still cf. |syntastic-filetype-checkers|), then aggregates errors found +by all checkers in a single list, and notifies you. In this mode each error +message is labeled with the name of the checker that generated it, but you can +disable generation of these labels by turning off '|syntastic_id_checkers|'. + +If |'syntastic_sort_aggregated_errors'| is set (which is the default), messages +in the aggregated list are grouped by file, then sorted by line number, then +type, then column number. Otherwise messages produced by the same checker are +grouped together, and sorting within each group is decided by the variables +|'syntastic___sort'|. + +------------------------------------------------------------------------------ +2.6 Filtering errors *syntastic-filtering-errors* + +You can selectively disable some of the errors found by checkers either +using |'syntastic_quiet_messages'|, or by specifying a list of patterns in +|'syntastic_ignore_files'|. + +See also: |'syntastic___quiet_messages'|. + +============================================================================== +3. Commands *syntastic-commands* + +:Errors *:Errors* + +When errors have been detected, use this command to pop up the |location-list| +and display the error messages. + +Please note that the |:Errors| command overwrites the current location list with +syntastic's own location list. + +:SyntasticToggleMode *:SyntasticToggleMode* + +Toggles syntastic between active and passive mode. See |'syntastic_mode_map'| +for more info. + +:SyntasticCheck *:SyntasticCheck* + +Manually cause a syntax check to be done. By default the checkers in the +|'g:syntastic__checkers'| or |'b:syntastic_checkers'| lists are run, +cf. |syntastic-filetype-checkers|. If |syntastic_aggregate_errors| is unset +(which is the default), checking stops the first time a checker reports any +errors; if |syntastic_aggregate_errors| is set, all checkers that apply are run +in turn, and all errors found are aggregated in a single list. + +The command may be followed by a (space separated) list of checkers. In this +case |'g:syntastic__checkers'| and |'b:syntastic_checkers'| are +ignored, and the checkers named by the command's arguments are run instead, in +the order specified. The rules of |syntastic_aggregate_errors| still apply. + +Example: > + :SyntasticCheck flake8 pylint +< +:SyntasticInfo *:SyntasticInfo* + +The command takes an optional argument, and outputs information about the +checkers available for the filetype named by said argument, or for the current +filetype if no argument was provided. + +:SyntasticReset *:SyntasticReset* + +Resets the list of errors and turns off all error notifiers. + +:SyntasticSetLoclist *:SyntasticSetLoclist* + +If |'syntastic_always_populate_loc_list'| is not set, the |location-list| is +not filled in automatically with the list of errors detected by the checkers. +This is useful if you run syntastic along with other plugins that use location +lists. The |:SyntasticSetLoclist| command allows you to stick the errors into +the location list explicitly. + +============================================================================== +4. Global Options *syntastic-global-options* + + + *'syntastic_check_on_open'* +Default: 0 +If enabled, syntastic will do syntax checks when buffers are first loaded as +well as on saving > + let g:syntastic_check_on_open = 1 +< + *'syntastic_check_on_wq'* +Default: 1 +Normally syntastic runs syntax checks whenever buffers are written to disk. +If you want to skip these checks when you issue |:wq|, |:x|, and |:ZZ|, set this +variable to 0. > + let g:syntastic_check_on_wq = 0 +< + *'syntastic_aggregate_errors'* +Default: 0 +When enabled, syntastic runs all checkers that apply to the current filetype, +then aggregates errors found by all checkers and displays them. When disabled, +syntastic runs each checker in turn, and stops to display the results the first +time a checker finds any errors. > + let g:syntastic_aggregate_errors = 1 +< + *'syntastic_id_checkers'* +Default: 1 +When results from multiple checkers are aggregated in a single error list +(that is either when |syntastic_aggregate_errors| is enabled, or when checking +a file with a composite filetype), it might not be immediately obvious which +checker has produced a given error message. This variable instructs syntastic +to label error messages with the names of the checkers that created them. > + let g:syntastic_id_checkers = 0 +< + *'syntastic_sort_aggregated_errors'* +Default: 1 +By default, when results from multiple checkers are aggregated in a single +error list (that is either when |syntastic_aggregate_errors| is enabled, or +when checking a file with a composite filetype), errors are grouped by file, +then sorted by line number, then grouped by type (namely errors take precedence +over warnings), then they are sorted by column number. If you want to leave +messages grouped by checker output, set this variable to 0. > + let g:syntastic_sort_aggregated_errors = 0 +< + *'syntastic_echo_current_error'* +Default: 1 +If enabled, syntastic will echo current error to the command window. If +multiple errors are found on the same line, |syntastic_cursor_columns| is used +to decide which one is shown. > + let g:syntastic_echo_current_error = 1 +< + *'syntastic_cursor_columns'* +Default: 1 +This option controls which errors are echoed to the command window if +|syntastic_echo_current_error| is set and multiple errors are found on the same +line. When the option is enabled, the first error corresponding to the current +column is show. Otherwise, the first error on the current line is echoed, +regardless of the cursor position on the current line. + +When dealing with very large lists of errors, disabling this option can speed +up navigation significantly: > + let g:syntastic_cursor_column = 0 +< + *'syntastic_enable_signs'* +Default: 1 +Use this option to tell syntastic whether to use the |:sign| interface to mark +syntax errors: > + let g:syntastic_enable_signs = 1 +< + *'syntastic_error_symbol'* *'syntastic_style_error_symbol'* + *'syntastic_warning_symbol'* *'syntastic_style_warning_symbol'* +Use this option to control what the syntastic |:sign| text contains. Several +error symbols can be customized: + syntastic_error_symbol - For syntax errors, defaults to '>>' + syntastic_style_error_symbol - For style errors, defaults to 'S>' + syntastic_warning_symbol - For syntax warnings, defaults to '>>' + syntastic_style_warning_symbol - For style warnings, defaults to 'S>' + +Example: > + let g:syntastic_error_symbol = "✗" + let g:syntastic_warning_symbol = "⚠" +< + *'syntastic_enable_balloons'* +Default: 1 +Use this option to tell syntastic whether to display error messages in balloons +when the mouse is hovered over erroneous lines: > + let g:syntastic_enable_balloons = 1 +< +Note that Vim must be compiled with |+balloon_eval|. + + *'syntastic_enable_highlighting'* +Default: 1 +Use this option to tell syntastic whether to use syntax highlighting to mark +errors (where possible). Highlighting can be turned off with the following > + let g:syntastic_enable_highlighting = 0 +< + *'syntastic_always_populate_loc_list'* +Default: 0 +Enable this option to tell syntastic to always stick any detected errors into +the |location-list|: > + let g:syntastic_always_populate_loc_list = 1 +< + *'syntastic_auto_jump'* +Default: 0 +Enable this option if you want the cursor to jump to the first detected issue +when saving or opening a file. + +When set to 0 the cursor won't jump automatically. > + let g:syntastic_auto_jump = 0 +< +When set to 1 the cursor will always jump to the first issue detected, +regardless of type. > + let g:syntastic_auto_jump = 1 +< +When set to 2 the cursor will jump to the first issue detected, but only if +this issue is an error. > + let g:syntastic_auto_jump = 2 +< +When set to 3 the cursor will jump to the first error detected, if any. If +all issues detected are warnings, the cursor won't jump. > + let g:syntastic_auto_jump = 3 +< + *'syntastic_auto_loc_list'* +Default: 2 +Use this option to tell syntastic to automatically open and/or close the +|location-list| (see |syntastic-error-window|). + +When set to 0 the error window will not be opened or closed automatically. > + let g:syntastic_auto_loc_list = 0 +< +When set to 1 the error window will be automatically opened when errors are +detected, and closed when none are detected. > + let g:syntastic_auto_loc_list = 1 +< +When set to 2 the error window will be automatically closed when no errors are +detected, but not opened automatically. > + let g:syntastic_auto_loc_list = 2 +< + *'syntastic_loc_list_height'* +Default: 10 +Use this option to specify the height of the location lists that syntastic +opens. > + let g:syntastic_loc_list_height = 5 +< + *'syntastic_ignore_files'* +Default: [] +Use this option to specify files that syntastic should never check. It's a +list of |regular-expression| patterns. The full paths of files (see |::p|) are +matched against these patterns, and the matches are case sensitive. Use |\c| +to specify case insensitive patterns. Example: > + let g:syntastic_ignore_files = ['\m^/usr/include/', '\m\c\.h$'] +< + *'syntastic_filetype_map'* +Default: {} +Use this option to map non-standard filetypes to standard ones. Corresponding +checkers are mapped accordingly, which allows syntastic to check files with +non-standard filetypes: > + let g:syntastic_filetype_map = { + \ "latex": "tex", + \ "gentoo-metadata": "xml" } +< +Composite filetypes can also be mapped to simple types, which disables the +default behaviour of running both checkers against the input file: > + let g:syntastic_filetype_map = { "handlebars.html": "handlebars" } +< + *'syntastic_mode_map'* +Default: { "mode": "active", + "active_filetypes": [], + "passive_filetypes": [] } +Use this option to fine tune when automatic syntax checking is done (or not +done). + +The option should be set to something like: > + + let g:syntastic_mode_map = { + \ "mode": "active", + \ "active_filetypes": ["ruby", "php"], + \ "passive_filetypes": ["puppet"] } +< +"mode" can be mapped to one of two values - "active" or "passive". When set +to "active", syntastic does automatic checking whenever a buffer is saved or +initially opened. When set to "passive" syntastic only checks when the user +calls |:SyntasticCheck|. + +The exceptions to these rules are defined with "active_filetypes" and +"passive_filetypes". In passive mode, automatic checks are still done for +filetypes in the "active_filetypes" array (and "passive_filetypes" is +ignored). In active mode, automatic checks are not done for any filetypes in +the "passive_filetypes" array ("active_filetypes" is ignored). + +If any of "mode", "active_filetypes", or "passive_filetypes" are left +unspecified, they default to values above. + +If local variable |'b:syntastic_mode'| is defined its value takes precedence +over all calculations involving |'syntastic_mode_map'| for the corresponding +buffer. + +At runtime, the |:SyntasticToggleMode| command can be used to switch between +active and passive modes. + + *'b:syntastic_mode'* +Default: unset +Only the local form |'b:syntastic_mode'| is used. When set to either "active" +or "passive", it takes precedence over |'syntastic_mode_map'| when deciding +whether the corresponding buffer should be checked automatically. + + *'syntastic_quiet_messages'* +Default: {} +Use this option to filter out some of the messages produced by checkers. The +option should be set to something like: > + let g:syntastic_quiet_messages = { + \ "!level": "errors", + \ "type": "style", + \ "regex": '\m\[C03\d\d\]', + \ "file:p": ['\m^/usr/include/', '\m\c\.h$'] } +< +Each element turns off messages matching the patterns specified by the +corresponding value. Values are lists, but if a list consist of a single +element you may omit the brackets (e.g. you may write "style" instead of +["style"]). Elements with values [] or '' are ignored (this is useful for +overriding filters, cf. |filter-overrides|). + + "level" - takes one of two values, "warnings" or "errors" + "type" - can be either "syntax" or "style" + "regex" - is matched against the messages' text as a case insensitive + |regular-expression| + "file" - is matched against the filenames the messages refer to, as a + case sensitive |regular-expression|. + +If a key is prefixed by an exclamation mark "!", the corresponding filter is +negated (i.e. the above example silences all messages that are NOT errors). + +The "file" key may be followed by one or more filename modifiers (see +|filename-modifiers|). The modifiers are applied to the filenames the messages +refer to before matching against the value (i.e. in the above example the full +path of the issues are matched against '\m^/usr/include/' and '\m\c\.h$'). + +If |'syntastic_id_checkers'| is set, filters are applied before error messages +are labeled with the names of the checkers that created them. + +There are also checker-specific variants of this option, providing finer +control. They are named |'syntastic___quiet_messages'|. + +For a particular checker, if both a |'syntastic_quiet_messages'| filter and +a checker-specific filter are present, they are both applied (to the list of +errors produced by the said checker). In case of conflicting values for the +same keys, the values of the checker-specific filters take precedence. + + *filter-overrides* +Since filter elements with values [] or '' are ignored, you can disable global +filters for particular checkers, by setting the values of the corresponding +elements in |'syntastic___quiet_messages'| to [] or ''. For +example, the following setting will silence all warnings, except for the +ones produced by "pylint": > + let g:syntastic_quiet_messages = { "level": "warnings" } + let g:syntastic_python_pylint_quiet_messages = { "level" : [] } +< + *'syntastic_stl_format'* +Default: [Syntax: line:%F (%t)] +Use this option to control what the syntastic statusline text contains. Several +magic flags are available to insert information: + %e - number of errors + %w - number of warnings + %t - total number of warnings and errors + %fe - line number of first error + %fw - line number of first warning + %F - line number of first warning or error + +Several additional flags are available to hide text under certain conditions: + %E{...} - hide the text in the brackets unless there are errors + %W{...} - hide the text in the brackets unless there are warnings + %B{...} - hide the text in the brackets unless there are both warnings AND + errors +These flags can't be nested. + +Example: > + let g:syntastic_stl_format = '[%E{Err: %fe #%e}%B{, }%W{Warn: %fw #%w}]' +< +If this format is used and the current buffer has 5 errors and 1 warning +starting on lines 20 and 10 respectively then this would appear on the +statusline: > + [Err: 20 #5, Warn: 10 #1] +< +If the buffer had 2 warnings, starting on line 5 then this would appear: > + [Warn: 5 #2] +< + *'b:syntastic_skip_checks'* +Default: unset +Only the local form |'b:syntastic_skip_checks'| is used. When set to a true +value, no checks are run against the corresponding buffer. Example: > + let b:syntastic_skip_checks = 1 +< + *'syntastic_full_redraws'* +Default: 0 in GUI Vim and MacVim, 1 otherwise +Controls whether syntastic calls |:redraw| or |:redraw!| for screen redraws. +Changing it can in principle make screen redraws smoother, but it can also +cause screen to flicker, or cause ghost characters. Leaving it to the default +should be safe. + + *'syntastic_exit_checks'* +Default: 0 when running under "cmd.exe" on Windows, 1 otherwise +Syntastic attempts to catch abnormal termination conditions from checkers by +looking at their exit codes. The "cmd.exe" shell on Windows make these checks +meaningless, by returning 1 to Vim when the checkers exit with non-zero codes. +The above variable can be used to disable exit code checks in syntastic. + + *'syntastic_shell'* +Default: Vim's 'shell' + +This is the (full path to) the shell syntastic will use to run the checkers. +On UNIX and Mac OS-X this shell must accept Bourne-compatible syntax for +file "stdout" and "stderr" redirections ">file" and "2>file". Examples of +compatible shells are "zsh", "bash", "ksh", and of course the original Bourne +"sh". + +This shell is independent of Vim's 'shell', and it isn't used for interactive +operations. It must take care to initialize all environment variables needed +by the checkers you're using. Example: > + let g:syntastic_shell = "/bin/sh" +< + *'syntastic_debug'* +Default: 0 +Set this to the sum of one or more of the following flags to enable +debugging: + + 1 - trace general workflow + 2 - dump location lists + 4 - trace notifiers + 8 - trace autocommands + 16 - dump options + 32 - trace running of specific checkers + +Example: > + let g:syntastic_debug = 1 +< +Syntastic will then add debugging messages to Vim's |message-history|. You can +examine these messages with |:mes|. + + *'syntastic_debug_file'* +Default: unset +When set, debugging messages are written to the file named by its value, in +addition to being added to Vim's |message-history|: > + let g:syntastic_debug_file = '~/syntastic.log' +< + *'syntastic_extra_filetypes'* +Default: [] +List of filetypes handled by checkers external to syntastic. If you have a Vim +plugin that adds a checker for syntastic, and if the said checker deals with a +filetype that is unknown to syntastic, you might consider adding that filetype +to this list: > + let g:syntastic_extra_filetypes = [ "make", "gitcommit" ] +< +This will allow |:SyntasticInfo| to do proper tab completion for the new +filetypes. + +============================================================================== +5. Checker Options *syntastic-checker-options* + +------------------------------------------------------------------------------ +5.1 Choosing which checkers to use *syntastic-filetype-checkers* + + *'g:syntastic__checkers'* +You can tell syntastic which checkers to run for a given filetype by setting a +variable 'g:syntastic__checkers' to a list of checkers, e.g. > + let g:syntastic_php_checkers = ["php", "phpcs", "phpmd"] +< + *'b:syntastic_checkers'* +There is also a per-buffer version of this setting, 'b:syntastic_checkers'. +When set, it takes precedence over |'g:syntastic__checkers'|. You can +use this in an autocmd to configure specific checkers for particular paths: > + autocmd FileType python if stridx(expand("%:p"), "/some/path/") == 0 | + \ let b:syntastic_checkers = ["pylint"] | endif +< +If neither |'g:syntastic__checkers'| nor |'b:syntastic_checkers'| +is set, a default list of checker is used. Beware however that this list +deliberately kept minimal, for performance reasons. + +Take a look at the wiki to find out what checkers and filetypes are supported +by syntastic: + + https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers + +Use |:SyntasticInfo| to see which checkers are available for a given filetype. + +------------------------------------------------------------------------------ +5.2 Choosing the executable *syntastic-config-exec* + + *'syntastic___exec'* +The executable run by a checker is normally defined automatically, when the +checker is registered. You can however override it, by setting the variable +'g:syntastic___exec': > + let g:syntastic_ruby_mri_exec = '~/bin/ruby2' +< +This variable has a local version, 'b:syntastic___exec', +which takes precedence over the global one in the corresponding buffer. + + *'b:syntastic__exec'* +And there is also a local variable named 'b:syntastic__exec', which +takes precedence over both 'b:syntastic___exec' and +'g:syntastic___exec' in the buffers where it is defined. + +------------------------------------------------------------------------------ +5.3 Configuring specific checkers *syntastic-config-makeprg* + +Most checkers use the 'makeprgBuild()' function and provide many options by +default - in fact you can customise every part of the command that gets called. + + *'syntastic___