From b283c04879fc86bfdda0e9bd95b2c788285e448b Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Sat, 31 May 2014 10:16:16 -0700 Subject: [PATCH 001/177] syntastic, json syntax highlighting --- bundle/json/.gitignore | 10 ++ bundle/json/ftdetect/json.vim | 2 + bundle/json/ftplugin/json.vim | 33 +++++++ bundle/json/indent/json.vim | 169 ++++++++++++++++++++++++++++++++++ bundle/json/json-test.json | 77 ++++++++++++++++ bundle/json/jsonp-test.jsonp | 8 ++ bundle/json/license.md | 11 +++ bundle/json/readme.md | 53 +++++++++++ bundle/json/syntax/json.vim | 141 ++++++++++++++++++++++++++++ bundle/syntastic | 1 + vimrc | 4 + 11 files changed, 509 insertions(+) create mode 100644 bundle/json/.gitignore create mode 100644 bundle/json/ftdetect/json.vim create mode 100644 bundle/json/ftplugin/json.vim create mode 100644 bundle/json/indent/json.vim create mode 100644 bundle/json/json-test.json create mode 100644 bundle/json/jsonp-test.jsonp create mode 100644 bundle/json/license.md create mode 100644 bundle/json/readme.md create mode 100644 bundle/json/syntax/json.vim create mode 160000 bundle/syntastic diff --git a/bundle/json/.gitignore b/bundle/json/.gitignore new file mode 100644 index 0000000..8a94545 --- /dev/null +++ b/bundle/json/.gitignore @@ -0,0 +1,10 @@ +/index.php + +# Ignore vim files +*~ +*.swp +*.swo +*.fuse_hidden* +*.pxm +*.DS_Store +/video/* diff --git a/bundle/json/ftdetect/json.vim b/bundle/json/ftdetect/json.vim new file mode 100644 index 0000000..428f3f1 --- /dev/null +++ b/bundle/json/ftdetect/json.vim @@ -0,0 +1,2 @@ +autocmd BufNewFile,BufRead *.json set filetype=json +autocmd BufNewFile,BufRead *.jsonp set filetype=json diff --git a/bundle/json/ftplugin/json.vim b/bundle/json/ftplugin/json.vim new file mode 100644 index 0000000..e4863d2 --- /dev/null +++ b/bundle/json/ftplugin/json.vim @@ -0,0 +1,33 @@ +"uncomment to enable folding of `{...}` and `[...]` blocks +"setlocal foldmethod=syntax + +"conceal by default +if !exists("g:vim_json_syntax_conceal") + let g:vim_json_syntax_conceal = 1 +end + +"have warnings by default +if !exists("g:vim_json_warnings") + let g:vim_json_warnings = 1 +end + +"set concealcursor blank by default +"this should turn off the concealing in the current line (where the cursor is at), +"on all modes (normal, visual, insert) +if !exists("g:vim_json_syntax_concealcursor") + let g:vim_json_syntax_concealcursor = "" +end + +if has('conceal') + if (g:vim_json_syntax_conceal == 1) + "level 2 means concealed text gets completely hidden unless a + "replacement is defined (none is defined by us) + setlocal conceallevel=2 + let &l:concealcursor = g:vim_json_syntax_concealcursor + else + "level 0 means text is shown normally = no concealing + setlocal conceallevel=0 + endif + "maybe g:vim_json_syntax_conceal could be settable to 0,1,2 to map + "directly to vim's conceallevels? unsure if anyone cares +endif diff --git a/bundle/json/indent/json.vim b/bundle/json/indent/json.vim new file mode 100644 index 0000000..c9f2762 --- /dev/null +++ b/bundle/json/indent/json.vim @@ -0,0 +1,169 @@ +" Vim indent file +" Language: JSON +" Maintainer: Rogerz Zhang +" URL: http://github.com/rogerz/vim-json +" Version: 1.0.0 +" Last Change: Fix for square bracket matching by Jakar https://github.com/jakar/vim-json/commit/20b650e22aa750c4ab6a66aa646bdd95d7cd548a#diff-e81fc111b2052e306d126bd9989f7b7c +" Acknowledgement: Based off of vim-javascript maintained by Darrick Wiebe +" http://www.vim.org/scripts/script.php?script_id=2765 + +" 0. Initialization {{{1 +" ================= + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetJSONIndent() +setlocal indentkeys=0{,0},0),0[,0],!^F,o,O,e + +" Only define the function once. +if exists("*GetJSONIndent") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 1. Variables {{{1 +" ============ + +let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' +" Regex that defines blocks. +let s:block_regex = '\%({\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +" 2. Auxiliary Functions {{{1 +" ====================== + +" Check if the character at lnum:col is inside a string. +function s:IsInString(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') == jsonString +endfunction + +" Find line above 'lnum' that isn't empty, or in a string. +function s:PrevNonBlankNonString(lnum) + let lnum = prevnonblank(a:lnum) + while lnum > 0 + " If the line isn't empty or in a string, end search. + let line = getline(lnum) + if !(s:IsInString(lnum, 1) && s:IsInString(lnum, strlen(line))) + break + endif + let lnum = prevnonblank(lnum - 1) + endwhile + return lnum +endfunction + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:LineHasOpeningBrackets(lnum) + let open_0 = 0 + let open_2 = 0 + let open_4 = 0 + let line = getline(a:lnum) + let pos = match(line, '[][(){}]', 0) + while pos != -1 + let idx = stridx('(){}[]', line[pos]) + if idx % 2 == 0 + let open_{idx} = open_{idx} + 1 + else + let open_{idx - 1} = open_{idx - 1} - 1 + endif + let pos = match(line, '[][(){}]', pos + 1) + endwhile + return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) +endfunction + +function s:Match(lnum, regex) + let col = match(getline(a:lnum), a:regex) + 1 + return col > 0 && !s:IsInString(a:lnum, col) ? col : 0 +endfunction + +" 3. GetJSONIndent Function {{{1 +" ========================= + +function GetJSONIndent() + " 3.1. Setup {{{2 + " ---------- + + " Set up variables for restoring position in file. Could use v:lnum here. + let vcol = col('.') + + " 3.2. Work on the current line {{{2 + " ----------------------------- + + " Get the current line. + let line = getline(v:lnum) + let ind = -1 + + " If we got a closing bracket on an empty line, find its match and indent + " according to it. + let col = matchend(line, '^\s*[]}]') + + if col > 0 && !s:IsInString(v:lnum, col) + call cursor(v:lnum, col) + let bs = strpart('{}[]', stridx('}]', line[col - 1]) * 2, 2) + + let pairstart = escape(bs[0], '[') + let pairend = escape(bs[1], ']') + let pairline = searchpair(pairstart, '', pairend, 'bW') + + if pairline > 0 + let ind = indent(pairline) + else + let ind = virtcol('.') - 1 + endif + + return ind + endif + + " If we are in a multi-line string, don't do anything to it. + if s:IsInString(v:lnum, matchend(line, '^\s*') + 1) + return indent('.') + endif + + " 3.3. Work on the previous line. {{{2 + " ------------------------------- + + let lnum = prevnonblank(v:lnum - 1) + + if lnum == 0 + return 0 + endif + + " Set up variables for current line. + let line = getline(lnum) + let ind = indent(lnum) + + " If the previous line ended with a block opening, add a level of indent. + " if s:Match(lnum, s:block_regex) + " return indent(lnum) + &sw + " endif + + " If the previous line contained an opening bracket, and we are still in it, + " add indent depending on the bracket type. + if line =~ '[[({]' + let counts = s:LineHasOpeningBrackets(lnum) + if counts[0] == '1' || counts[1] == '1' || counts[2] == '1' + return ind + &sw + else + call cursor(v:lnum, vcol) + end + endif + + " }}}2 + + return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 noet: + diff --git a/bundle/json/json-test.json b/bundle/json/json-test.json new file mode 100644 index 0000000..e135fdf --- /dev/null +++ b/bundle/json/json-test.json @@ -0,0 +1,77 @@ +// this comment should be highlighted as an error + +{ + unquotedKeyword:'singleQuotedString', + 'singleQuotedKeyword':true, + "decimalCantStartWithPeriod":.1, + "semicolonAtEndOfThisObject":"trailingComma", +}; + +{ + "object1": "missingComma" + "object2": "value" +} + +// normative JSON examples from http://json.org/example.html + +{"menu": { + "id": "file", + "value": "File", + "popup": { + "menuitem": [ + {"value": "New", "onclick": "CreateNewDoc()"}, + {"value": "Open", "onclick": "OpenDoc()"}, + {"value": "Close", "onclick": "CloseDoc()"} + ] + } +}} + +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } +} + +{"widget": { + "debug": "on", + "window": { + "title": "Sample Konfabulator Widget", + "name": "main_window", + "width": 500, + "height": 500 + }, + "image": { + "src": "Images/Sun.png", + "name": "sun1", + "hOffset": 250, + "vOffset": 250, + "alignment": "center" + }, + "text": { + "data": "Click Here", + "size": 36, + "style": "bold", + "name": "text1", + "hOffset": 250, + "vOffset": 100, + "alignment": "center", + "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" + } +}} diff --git a/bundle/json/jsonp-test.jsonp b/bundle/json/jsonp-test.jsonp new file mode 100644 index 0000000..00eb307 --- /dev/null +++ b/bundle/json/jsonp-test.jsonp @@ -0,0 +1,8 @@ + +whañteverJavascriptName ( { + "success":true, + "url":"http://google.com/", + "shortUrl":"http://b1t.co/54" +}); + + diff --git a/bundle/json/license.md b/bundle/json/license.md new file mode 100644 index 0000000..a1836c5 --- /dev/null +++ b/bundle/json/license.md @@ -0,0 +1,11 @@ +MIT License +=========== + +Copyright (c) 2013, Jeroen Ruigrok van der Werven, Eli Parra + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +"THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +See https://twitter.com/elzr/status/294964017926119424 and https://twitter.com/ashemedai/status/295062705193246720 for public acknowledgement of the MIT license as prompted by this issue https://github.com/elzr/vim-json/issues/6 diff --git a/bundle/json/readme.md b/bundle/json/readme.md new file mode 100644 index 0000000..1501891 --- /dev/null +++ b/bundle/json/readme.md @@ -0,0 +1,53 @@ +Better JSON for VIM +=================== + +*Distinct highlighting of keywords vs values, JSON-specific (non-JS) warnings, quote concealing.* +![JSON syntax coloring](http://farm8.staticflickr.com/7234/7185560283_102f6b753d.jpg) +Customization of Jeroen Ruigrok van der Werven's [vim-json highlighting script](http://www.vim.org/scripts/script.php?script_id=1945) with Rogerz Zhang's [indent script](https://github.com/vim-scripts/vim-json-bundle). +[Pathogen-friendly.](https://github.com/tpope/vim-pathogen) [Vundle-friendly too](https://github.com/elzr/vim-json/issues/25). + +Specific customizations +----------------------- + +* Added distinct **highlighting** for keywords vs values! (This is what made me start this plugin.) +* Added **concealing** of double quotes, for a minimalist [CoffeeScript](http://coffeescript.org/)-inspired look ([CSON](https://github.com/bevry/cson)!). + * *This requires Vim 7.3+.* To disable it add `let g:vim_json_syntax_conceal = 0` to your `.vimrc`. +* Added **folding** of `{...}` and `[...]` blocks. To enable it `:setlocal foldmethod=syntax` (do it permanently on the `ftplugin/json.vim` file). +* **JSON-specific warnings** (red highlights): + * Warn about *no-quotes* in keywords and *single-quotes* in keywords and values. + * Warn about *decimals* smaller than 1 that don't start with a 0 (`.1` gives a warning, it should be `0.1`). + * Warn about *comments* `//` and *trailing semicolons* `;`. + * Warn about *[missing commas](https://github.com/elzr/vim-json/issues/18)* between elements of an object. + * Warn about *trailing commas* after the last element in arrays or objects. + * (All warnings can be turned off with a `let g:vim_json_warnings=0` in your `vimrc`.) +* Recognize `.jsonp` file type. In [JSONP](http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about), the wrapping function call at the beginning and the closing semicolon are recognized. + +Screenshots +----------- + +**No syntax coloring**: wall of text.
![No syntax coloring](http://farm8.staticflickr.com/7085/7370791592_fe85355c89.jpg) + +**Javascript (or for that matter, the standard json.vim) syntax coloring**: Barely an improvement from no syntax coloring.
![Javascript syntax coloring](http://farm8.staticflickr.com/7076/7370791528_664eb2da6d.jpg) + +**Better JSON syntax coloring**: a more meaningful, distinct and elegant presentation.
![JSON syntax coloring](http://farm8.staticflickr.com/7234/7185560283_102f6b753d.jpg) + +Why use separate JSON highlighting instead of just Javascript? +-------------------------------------------------------------- + +Here's 2 compelling reasons: + +1. **All JSON is Javascript but NOT all Javascript is JSON.** So `{property:1}` is invalid because `property` does not have double quotes around it. `{'property':1}` is also invalid, because it's single quoted while the only thing that can placate the JSON specification is double quoting. JSON is even fussy enough that `{"property":.1}` is invalid too, because you should have of course written `{"property":0.1}`. Also, don't even think about [having comments](http://stackoverflow.com/questions/244777/can-i-comment-a-json-file) or semicolons, you guessed it: they're invalid. The point being that your syntax highlighter should warn you about these errors, in realtime, which is something that the Javascript highlighter doesn't (because in Javacript they're not errors!). + +2. **Distinct highlighting for keywords.** JSON is an extremely lightweight data format but at its core lies an inescapable conceptual distinction: there are keywords and there are values. There's nothing much to the format besides that, so we might as well display keywords and values differently. This is something that gets lost with Javascript-inspired syntax highlighters, which see keywords as just another string since JSON requires them double quoted. So JSON files remain an impenetrable, indistinct wall of text. + +Common problems +--------------- + +This is the expected behavior of the plugin: +![showcase](http://i.imgur.com/cmL1GNc.gif) + +Most trouble, little as it is, has to do with Vim's newfangled concealing, which most people aren't yet familiar with, as it was introduced as recently as Vim 7.3+. If you just don't care for concealing you can easily disable it adding `let g:vim_json_syntax_conceal = 0` to your `.vimrc`. + +Concealing is nice for viewing but when you want to edit it should get out of your way seamlessly so you can see the actual code. Thus the **default behavior** *should* be text shown normally on the line your cursor is at, on all modes (normal, visual, insert). If this isn't the case and the concealing doesn't go away (not even in insert mode), you most likely have **an interfering plugin**. You need to look at your `concealcursor` setting (which can be set through this plugin with `g:vim_json_syntax_concealcursor`). The specially overeager [**indentLine**](https://github.com/Yggdroot/indentLine), plugin would require _yet_ an additional `let g:indentLine_noConcealCursor=""` in your `.vimrc` as detailed [here](https://github.com/elzr/vim-json/issues/23#issuecomment-40293049). + +It's a good idea to test drive with the files `json-test.json` and `jsonp-test.jsonp` first thing. diff --git a/bundle/json/syntax/json.vim b/bundle/json/syntax/json.vim new file mode 100644 index 0000000..8409679 --- /dev/null +++ b/bundle/json/syntax/json.vim @@ -0,0 +1,141 @@ +" Vim syntax file +" Language: JSON +" Maintainer: Eli Parra +" Last Change: 2013-02-01 +" Version: 0.12 + +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish + endif + let main_syntax = 'json' +endif + +syntax match jsonNoise /\%(:\|,\)/ + +" NOTE that for the concealing to work your conceallevel should be set to 2 + +" Syntax: Strings +" Separated into a match and region because a region by itself is always greedy +syn match jsonStringMatch /"[^\"]\+"\ze[[:blank:]\r\n]*[,}\]]/ contains=jsonString +if has('conceal') + syn region jsonString oneline matchgroup=jsonQuote start=/"/ skip=/\\\\\|\\"/ end=/"/ concealends contains=jsonEscape contained +else + syn region jsonString oneline matchgroup=jsonQuote start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=jsonEscape contained +endif + +" Syntax: JSON does not allow strings with single quotes, unlike JavaScript. +syn region jsonStringSQError oneline start=+'+ skip=+\\\\\|\\"+ end=+'+ + +" Syntax: JSON Keywords +" Separated into a match and region because a region by itself is always greedy +syn match jsonKeywordMatch /"[^\"]\+"[[:blank:]\r\n]*\:/ contains=jsonKeyword +if has('conceal') + syn region jsonKeyword matchgroup=jsonQuote start=/"/ end=/"\ze[[:blank:]\r\n]*\:/ concealends contained +else + syn region jsonKeyword matchgroup=jsonQuote start=/"/ end=/"\ze[[:blank:]\r\n]*\:/ contained +endif + +" Syntax: Escape sequences +syn match jsonEscape "\\["\\/bfnrt]" contained +syn match jsonEscape "\\u\x\{4}" contained + +" Syntax: Numbers +syn match jsonNumber "-\=\<\%(0\|[1-9]\d*\)\%(\.\d\+\)\=\%([eE][-+]\=\d\+\)\=\>\ze[[:blank:]\r\n]*[,}\]]" + +" ERROR WARNINGS ********************************************** +if (!exists("g:vim_json_warnings") || g:vim_json_warnings==1) + " Syntax: Strings should always be enclosed with quotes. + syn match jsonNoQuotesError "\<[[:alpha:]]\+\>" + + " Syntax: An integer part of 0 followed by other digits is not allowed. + syn match jsonNumError "-\=\<0\d\.\d*\>" + + " Syntax: Decimals smaller than one should begin with 0 (so .1 should be 0.1). + syn match jsonNumError "\:\@<=[[:blank:]\r\n]*\zs\.\d\+" + + " Syntax: No comments in JSON, see http://stackoverflow.com/questions/244777/can-i-comment-a-json-file + syn match jsonCommentError "//.*" + syn match jsonCommentError "\(/\*\)\|\(\*/\)" + + " Syntax: No semicolons in JSON + syn match jsonSemicolonError ";" + + " Syntax: No trailing comma after the last element of arrays or objects + syn match jsonTrailingCommaError ",\_s*[}\]]" + + " Syntax: Watch out for missing commas between elements + syn match jsonMissingCommaError /\("\|\d\)\zs\_s\+\ze"/ +endif + +" ********************************************** END OF ERROR WARNINGS +" Allowances for JSONP: function call at the beginning of the file, +" parenthesis and semicolon at the end. +" Function name validation based on +" http://stackoverflow.com/questions/2008279/validate-a-javascript-function-name/2008444#2008444 +syn match jsonPadding "\%^[[:blank:]\r\n]*[_$[:alpha:]][_$[:alnum:]]*[[:blank:]\r\n]*(" +syn match jsonPadding ");[[:blank:]\r\n]*\%$" + +" Syntax: Boolean +syn keyword jsonBooleanTrue true +syn keyword jsonBooleanFalse false + +" Syntax: Null +syn keyword jsonNull null + +" Syntax: Braces +syn region jsonFold matchgroup=jsonBraces start="{" end="}" transparent fold +syn region jsonFold matchgroup=jsonBraces start="\[" end="]" transparent fold + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_json_syn_inits") + if version < 508 + let did_json_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + HiLink jsonPadding Operator + HiLink jsonString String + HiLink jsonTest Label + HiLink jsonEscape Special + HiLink jsonNumber Number + HiLink jsonBraces Delimiter + HiLink jsonNull Function + HiLink jsonBooleanTrue jsonBoolean + HiLink jsonBooleanFalse jsonBoolean + HiLink jsonBoolean Boolean + HiLink jsonKeyword Label + + if (!exists("g:vim_json_warnings") || g:vim_json_warnings==1) + HiLink jsonNumError Error + HiLink jsonCommentError Error + HiLink jsonSemicolonError Error + HiLink jsonTrailingCommaError Error + HiLink jsonMissingCommaError Error + HiLink jsonStringSQError Error + HiLink jsonNoQuotesError Error + endif + HiLink jsonQuote Quote + HiLink jsonNoise Noise + delcommand HiLink +endif + +let b:current_syntax = "json" +if main_syntax == 'json' + unlet main_syntax +endif + +" Vim settings +" vim: ts=8 fdm=marker + +" MIT License +" Copyright (c) 2013, Jeroen Ruigrok van der Werven, Eli Parra +"Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +"THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"See https://twitter.com/elzr/status/294964017926119424 diff --git a/bundle/syntastic b/bundle/syntastic new file mode 160000 index 0000000..50518b3 --- /dev/null +++ b/bundle/syntastic @@ -0,0 +1 @@ +Subproject commit 50518b335d6bc486c895d4cb34c29417238cbe81 diff --git a/vimrc b/vimrc index f7ad977..0a63eda 100644 --- a/vimrc +++ b/vimrc @@ -28,6 +28,10 @@ set autoindent "Autoindent "Ignore these files when completing names set wildignore=.svn,CVS,.git,*.o,*.a,*.class,*.mo,*.la,*.so,*.obj,*.swp,*.jpg,*.png,*.xpm,*.gif,node_modules/* +"------ JSON magic ------ +au BufRead,BufNewFile *.json set filetype=json +let g:vim_json_syntax_conceal = 0 + "------ Special Coffee Behavior ------ au BufNewFile,BufReadPost *.coffee set shiftwidth=2 softtabstop=2 expandtab autocmd BufNewFile,BufRead *.coffee set filetype=coffee From fe75be3a3b32c2f13c89157e8c06032b071a0455 Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Mon, 2 Jun 2014 13:20:44 -0700 Subject: [PATCH 002/177] less annoying CtrlP --- vimrc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vimrc b/vimrc index 0a63eda..32ba7ee 100644 --- a/vimrc +++ b/vimrc @@ -87,6 +87,9 @@ cmap w!! %!sudo tee > /dev/null % " Closes the current window nnoremap Q c +" CtrlP will load from the CWD, makes it easier with all these nested repos +let g:ctrlp_working_path_mode = '' + "------ Fugitive ------ "https://github.com/tpope/vim-fugitive%20nnoremap%20%3CLeader%3Egs%20:Gstatus%3CCR%3EFrom%2049ce05bf922da769e7b3fa293811efcb1f12c8aa%20Mon%20Sep%2017%2000:00:00%202001From:%20Thomas%20Hunter%20II%20%3Cthomas.hunter@dena.com%3EDate:%20Tue,%203%20Jun%202014%2018:21:37%20-0700Subject:%20[PATCH%20003/177]%20if%20pressing%20,Q%20and%20ONLY%20nerdtree%20would%20remain%20open,%20VIM%20quits---%20vimrc%20|%201%20+%201%20file%20changed,%201%20insertion(+)diff%20--git%20a/vimrc%20b/vimrcindex%2032ba7ee..83c9b4c%20100644---%20a/vimrc+++%20b/vimrc@@%20-65,6%20+65,7%20@@%20autocmd%20FileType%20nerdtree%20noremap%20%3Cbuffer%3E%20%3Cc-h%3E%20%3Cnop%3E%20autocmd%20FileType%20nerdtree%20noremap%20%3Cbuffer%3E%20%3Cc-right%3E%20%3Cnop%3E%20autocmd%20FileType%20nerdtree%20noremap%20%3Cbuffer%3E%20%3Cc-l%3E%20%3Cnop%3E%20autocmd%20vimenter%20*%20if%20!argc()%20|%20NERDTree%20|%20endif" Open NERDTree if we're simply launching vim +autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif " close if only nerdtree open "------ Tagbar Options ------ " http://adamyoung.net/Exuberant-Ctags-OS-X From 87d58d3c9f4f6d4a5fa68050b54ddde96d2c51c3 Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Tue, 10 Jun 2014 16:15:13 -0700 Subject: [PATCH 004/177] no more shift+K man entry accidents. no more seeing :nohlsearch in bar --- vimrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vimrc b/vimrc index 83c9b4c..fa29b5c 100644 --- a/vimrc +++ b/vimrc @@ -44,7 +44,7 @@ set ignorecase "Case Insensitive Searching set smartcase "Lowercase = case insensitive, any uppercase = case sensitive set hlsearch "Highlight all search results "Following line clears the search highlights when pressing Lb -nnoremap b :nohlsearch +nnoremap b :nohlsearch " http://www.vim.org/scripts/script.php?script_id=2572 noremap a :Ack noremap A jcl @@ -151,6 +151,9 @@ map c "+y " Deletes trailing space in file upon write " autocmd BufWritePre * :%s/\s\+$//e +" Accidentally pressing Shift K will no longer open stupid man entry +noremap K + map ? :Helptags if has("gui_running") From 46110757b10a799bceab9c0614776e09d89a1ad6 Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Tue, 17 Jun 2014 14:16:12 -0700 Subject: [PATCH 005/177] better javascript syntax highlighter --- bundle/javascript/CONTRIBUTING.md | 13 + bundle/javascript/README.md | 82 ++++ bundle/javascript/ftdetect/javascript.vim | 10 + bundle/javascript/indent/javascript.vim | 439 ++++++++++++++++++++++ bundle/javascript/syntax/javascript.vim | 320 ++++++++++++++++ 5 files changed, 864 insertions(+) create mode 100755 bundle/javascript/CONTRIBUTING.md create mode 100755 bundle/javascript/README.md create mode 100755 bundle/javascript/ftdetect/javascript.vim create mode 100755 bundle/javascript/indent/javascript.vim create mode 100755 bundle/javascript/syntax/javascript.vim diff --git a/bundle/javascript/CONTRIBUTING.md b/bundle/javascript/CONTRIBUTING.md new file mode 100755 index 0000000..1128b9b --- /dev/null +++ b/bundle/javascript/CONTRIBUTING.md @@ -0,0 +1,13 @@ +## Contributing + +This project uses the [git +flow](http://nvie.com/posts/a-successful-git-branching-model/) model for +development. There's [a handy git module for git +flow](//github.com/nvie/gitflow). If you'd like to be added as a contributor, +the price of admission is 1 pull request. Please follow the general code style +guides (read the code) and in your pull request explain the reason for the +proposed change and how it is valuable. + +## Bug report + +Report a bug on [GitHub Issues](https://github.com/pangloss/vim-javascript/issues). diff --git a/bundle/javascript/README.md b/bundle/javascript/README.md new file mode 100755 index 0000000..3987b97 --- /dev/null +++ b/bundle/javascript/README.md @@ -0,0 +1,82 @@ +# vim-javascript v0.9.0 + +JavaScript bundle for vim, this bundle provides syntax and indent plugins. + +## A Quick Note on Regexes + +Vim 7.4 was released recently, and unfortunately broke how this plugin +handles regexes. There was no real easy way for us to fix this unless we +completely rewrote how regexes work. + +Good News: There was a recent update to Vim 7.4 that fixes this issue. + +Make sure you are at least using Vim 7.4, with patches 1-7. + +If you are stuck on an older version of Vim 7.4 with no way to update, +then simply perform the following commands to fix your current buffer: + +``` +:set regexpengine=1 +:syntax enable +``` + +## Installation + +### Install with [Vundle](https://github.com/gmarik/vundle) + +Add to vimrc: + + Bundle "pangloss/vim-javascript" + +And install it: + + :so ~/.vimrc + :BundleInstall + +### Install with [pathogen](https://github.com/tpope/vim-pathogen) + + cd ~/.vim/bundle + git clone https://github.com/pangloss/vim-javascript.git + +## Configuration + +The following variables control certain syntax highlighting features. You can +add them to your `.vimrc` to enable/disable their features. + +#### javascript_enable_domhtmlcss + +Enables HTML/CSS syntax highlighting in your JavaScript file. + +Default Value: 0 + +#### b:javascript_fold + +Enables JavaScript code folding. + +Default Value: 1 + +#### g:javascript_conceal + +Enables concealing characters. For example, `function` is replaced with `ƒ` + +Default Value: 0 + +#### javascript_ignore_javaScriptdoc + +Disables JSDoc syntax highlighting + +Default Value: 0 + +## Contributing + +This project uses the [git +flow](http://nvie.com/posts/a-successful-git-branching-model/) model for +development. There's [a handy git module for git +flow](//github.com/nvie/gitflow). If you'd like to be added as a contributor, +the price of admission is 1 pull request. Please follow the general code style +guides (read the code) and in your pull request explain the reason for the +proposed change and how it is valuable. + +## Bug report + +Report a bug on [GitHub Issues](https://github.com/pangloss/vim-javascript/issues). diff --git a/bundle/javascript/ftdetect/javascript.vim b/bundle/javascript/ftdetect/javascript.vim new file mode 100755 index 0000000..036b352 --- /dev/null +++ b/bundle/javascript/ftdetect/javascript.vim @@ -0,0 +1,10 @@ +au BufNewFile,BufRead *.js setf javascript +au BufNewFile,BufRead *.jsm setf javascript +au BufNewFile,BufRead Jakefile setf javascript + +fun! s:SelectJavascript() + if getline(1) =~# '^#!.*/bin/env\s\+node\>' + set ft=javascript + endif +endfun +au BufNewFile,BufRead * call s:SelectJavascript() diff --git a/bundle/javascript/indent/javascript.vim b/bundle/javascript/indent/javascript.vim new file mode 100755 index 0000000..29fba2b --- /dev/null +++ b/bundle/javascript/indent/javascript.vim @@ -0,0 +1,439 @@ +" Vim indent file +" Language: Javascript +" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org + +" 0. Initialization {{{1 +" ================= + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetJavascriptIndent() +setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e + +" Only define the function once. +if exists("*GetJavascriptIndent") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 1. Variables {{{1 +" ============ + +let s:js_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' + +" Regex of syntax group names that are or delimit string or are comments. +let s:syng_strcom = 'string\|regex\|comment\c' + +" Regex of syntax group names that are strings. +let s:syng_string = 'regex\c' + +" Regex of syntax group names that are strings or documentation. +let s:syng_multiline = 'comment\c' + +" Regex of syntax group names that are line comment. +let s:syng_linecom = 'linecomment\c' + +" Expression used to check whether we should skip a match with searchpair(). +let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" + +let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' + +" Regex that defines continuation lines, not including (, {, or [. +let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@[^{;]*' . s:line_term + +" Regex that defines blocks. +let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +let s:var_stmt = '^\s*var' + +let s:comma_first = '^\s*,' +let s:comma_last = ',\s*$' + +let s:ternary = '^\s\+[?|:]' +let s:ternary_q = '^\s\+?' + +" 2. Auxiliary Functions {{{1 +" ====================== + +" Check if the character at lnum:col is inside a string, comment, or is ascii. +function s:IsInStringOrComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom +endfunction + +" Check if the character at lnum:col is inside a string. +function s:IsInString(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string +endfunction + +" Check if the character at lnum:col is inside a multi-line comment. +function s:IsInMultilineComment(lnum, col) + return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline +endfunction + +" Check if the character at lnum:col is a line comment. +function s:IsLineComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom +endfunction + +" Find line above 'lnum' that isn't empty, in a comment, or in a string. +function s:PrevNonBlankNonString(lnum) + let in_block = 0 + let lnum = prevnonblank(a:lnum) + while lnum > 0 + " Go in and out of blocks comments as necessary. + " If the line isn't empty (with opt. comment) or in a string, end search. + let line = getline(lnum) + if line =~ '/\*' + if in_block + let in_block = 0 + else + break + endif + elseif !in_block && line =~ '\*/' + let in_block = 1 + elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line))) + break + endif + let lnum = prevnonblank(lnum - 1) + endwhile + return lnum +endfunction + +" Find line above 'lnum' that started the continuation 'lnum' may be part of. +function s:GetMSL(lnum, in_one_line_scope) + " Start on the line we're at and use its indent. + let msl = a:lnum + let lnum = s:PrevNonBlankNonString(a:lnum - 1) + while lnum > 0 + " If we have a continuation line, or we're in a string, use line as MSL. + " Otherwise, terminate search as we have found our MSL already. + let line = getline(lnum) + let col = match(line, s:msl_regex) + 1 + if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line)) + let msl = lnum + else + " Don't use lines that are part of a one line scope as msl unless the + " flag in_one_line_scope is set to 1 + " + if a:in_one_line_scope + break + end + let msl_one_line = s:Match(lnum, s:one_line_scope_regex) + if msl_one_line == 0 + break + endif + endif + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + return msl +endfunction + +function s:RemoveTrailingComments(content) + let single = '\/\/\(.*\)\s*$' + let multi = '\/\*\(.*\)\*\/\s*$' + return substitute(substitute(a:content, single, '', ''), multi, '', '') +endfunction + +" Find if the string is inside var statement (but not the first string) +function s:InMultiVarStatement(lnum) + let lnum = s:PrevNonBlankNonString(a:lnum - 1) + +" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name') + + " loop through previous expressions to find a var statement + while lnum > 0 + let line = getline(lnum) + + " if the line is a js keyword + if (line =~ s:js_keywords) + " check if the line is a var stmt + " if the line has a comma first or comma last then we can assume that we + " are in a multiple var statement + if (line =~ s:var_stmt) + return lnum + endif + + " other js keywords, not a var + return 0 + endif + + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + + " beginning of program, not a var + return 0 +endfunction + +" Find line above with beginning of the var statement or returns 0 if it's not +" this statement +function s:GetVarIndent(lnum) + let lvar = s:InMultiVarStatement(a:lnum) + let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1) + + if lvar + let line = s:RemoveTrailingComments(getline(prev_lnum)) + + " if the previous line doesn't end in a comma, return to regular indent + if (line !~ s:comma_last) + return indent(prev_lnum) - &sw + else + return indent(lvar) + &sw + endif + endif + + return -1 +endfunction + + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:LineHasOpeningBrackets(lnum) + let open_0 = 0 + let open_2 = 0 + let open_4 = 0 + let line = getline(a:lnum) + let pos = match(line, '[][(){}]', 0) + while pos != -1 + if !s:IsInStringOrComment(a:lnum, pos + 1) + let idx = stridx('(){}[]', line[pos]) + if idx % 2 == 0 + let open_{idx} = open_{idx} + 1 + else + let open_{idx - 1} = open_{idx - 1} - 1 + endif + endif + let pos = match(line, '[][(){}]', pos + 1) + endwhile + return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) +endfunction + +function s:Match(lnum, regex) + let col = match(getline(a:lnum), a:regex) + 1 + return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 +endfunction + +function s:IndentWithContinuation(lnum, ind, width) + " Set up variables to use and search for MSL to the previous line. + let p_lnum = a:lnum + let lnum = s:GetMSL(a:lnum, 1) + let line = getline(lnum) + + " If the previous line wasn't a MSL and is continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + if p_lnum != lnum + if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line)) + return a:ind + endif + endif + + " Set up more variables now that we know we aren't continuation bound. + let msl_ind = indent(lnum) + + " If the previous line ended with [*+/.-=], start a continuation that + " indents an extra level. + if s:Match(lnum, s:continuation_regex) + if lnum == p_lnum + return msl_ind + a:width + else + return msl_ind + endif + endif + + return a:ind +endfunction + +function s:InOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 && s:Match(msl, s:one_line_scope_regex) + return msl + endif + return 0 +endfunction + +function s:ExitingOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 + " if the current line is in a one line scope .. + if s:Match(msl, s:one_line_scope_regex) + return 0 + else + let prev_msl = s:GetMSL(msl - 1, 1) + if s:Match(prev_msl, s:one_line_scope_regex) + return prev_msl + endif + endif + endif + return 0 +endfunction + +" 3. GetJavascriptIndent Function {{{1 +" ========================= + +function GetJavascriptIndent() + " 3.1. Setup {{{2 + " ---------- + + " Set up variables for restoring position in file. Could use v:lnum here. + let vcol = col('.') + + " 3.2. Work on the current line {{{2 + " ----------------------------- + + let ind = -1 + " Get the current line. + let line = getline(v:lnum) + " previous nonblank line number + let prevline = prevnonblank(v:lnum - 1) + + " If we got a closing bracket on an empty line, find its match and indent + " according to it. For parentheses we indent to its column - 1, for the + " others we indent to the containing line's MSL's level. Return -1 if fail. + let col = matchend(line, '^\s*[],})]') + if col > 0 && !s:IsInStringOrComment(v:lnum, col) + call cursor(v:lnum, col) + + let lvar = s:InMultiVarStatement(v:lnum) + if lvar + let prevline_contents = s:RemoveTrailingComments(getline(prevline)) + + " check for comma first + if (line[col - 1] =~ ',') + " if the previous line ends in comma or semicolon don't indent + if (prevline_contents =~ '[;,]\s*$') + return indent(s:GetMSL(line('.'), 0)) + " get previous line indent, if it's comma first return prevline indent + elseif (prevline_contents =~ s:comma_first) + return indent(prevline) + " otherwise we indent 1 level + else + return indent(lvar) + &sw + endif + endif + endif + + + let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) + if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 + if line[col-1]==')' && col('.') != col('$') - 1 + let ind = virtcol('.')-1 + else + let ind = indent(s:GetMSL(line('.'), 0)) + endif + endif + return ind + endif + + " If the line is comma first, dedent 1 level + if (getline(prevline) =~ s:comma_first) + return indent(prevline) - &sw + endif + + if (line =~ s:ternary) + if (getline(prevline) =~ s:ternary_q) + return indent(prevline) + else + return indent(prevline) + &sw + endif + endif + + " If we are in a multi-line comment, cindent does the right thing. + if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1) + return cindent(v:lnum) + endif + + " Check for multiple var assignments +" let var_indent = s:GetVarIndent(v:lnum) +" if var_indent >= 0 +" return var_indent +" endif + + " 3.3. Work on the previous line. {{{2 + " ------------------------------- + + " If the line is empty and the previous nonblank line was a multi-line + " comment, use that comment's indent. Deduct one char to account for the + " space in ' */'. + if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1) + return indent(prevline) - 1 + endif + + " Find a non-blank, non-multi-line string line above the current line. + let lnum = s:PrevNonBlankNonString(v:lnum - 1) + + " If the line is empty and inside a string, use the previous line. + if line =~ '^\s*$' && lnum != prevline + return indent(prevnonblank(v:lnum)) + endif + + " At the start of the file use zero indent. + if lnum == 0 + return 0 + endif + + " Set up variables for current line. + let line = getline(lnum) + let ind = indent(lnum) + + " If the previous line ended with a block opening, add a level of indent. + if s:Match(lnum, s:block_regex) + return indent(s:GetMSL(lnum, 0)) + &sw + endif + + " If the previous line contained an opening bracket, and we are still in it, + " add indent depending on the bracket type. + if line =~ '[[({]' + let counts = s:LineHasOpeningBrackets(lnum) + if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + if col('.') + 1 == col('$') + return ind + &sw + else + return virtcol('.') + endif + elseif counts[1] == '1' || counts[2] == '1' + return ind + &sw + else + call cursor(v:lnum, vcol) + end + endif + + " 3.4. Work on the MSL line. {{{2 + " -------------------------- + + let ind_con = ind + let ind = s:IndentWithContinuation(lnum, ind_con, &sw) + + " }}}2 + " + " + let ols = s:InOneLineScope(lnum) + if ols > 0 + let ind = ind + &sw + else + let ols = s:ExitingOneLineScope(lnum) + while ols > 0 && ind > 0 + let ind = ind - &sw + let ols = s:InOneLineScope(ols - 1) + endwhile + endif + + return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/bundle/javascript/syntax/javascript.vim b/bundle/javascript/syntax/javascript.vim new file mode 100755 index 0000000..7d27707 --- /dev/null +++ b/bundle/javascript/syntax/javascript.vim @@ -0,0 +1,320 @@ +" Vim syntax file +" Language: JavaScript +" Maintainer: vim-javascript community +" URL: https://github.com/pangloss/vim-javascript + +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish + endif + let main_syntax = 'javascript' +endif + +if !exists('g:javascript_conceal') + let g:javascript_conceal = 0 +endif + +"" Drop fold if it is set but VIM doesn't support it. +let b:javascript_fold='true' +if version < 600 " Don't support the old version + unlet! b:javascript_fold +endif + +"" dollar sign is permittd anywhere in an identifier +setlocal iskeyword+=$ + +syntax sync fromstart + +syntax match jsNoise /\%(:\|,\|\;\|\.\)/ + +"" Program Keywords +syntax keyword jsStorageClass const var let +syntax keyword jsOperator delete instanceof typeof void new in +syntax match jsOperator /\(!\||\|&\|+\|-\|<\|>\|=\|%\|\/\|*\|\~\|\^\)/ +syntax keyword jsBooleanTrue true +syntax keyword jsBooleanFalse false + +"" JavaScript comments +syntax keyword jsCommentTodo TODO FIXME XXX TBD contained +syntax region jsLineComment start=+\/\/+ end=+$+ keepend contains=jsCommentTodo,@Spell +syntax region jsEnvComment start="\%^#!" end="$" display +syntax region jsLineComment start=+^\s*\/\/+ skip=+\n\s*\/\/+ end=+$+ keepend contains=jsCommentTodo,@Spell fold +syntax region jsCvsTag start="\$\cid:" end="\$" oneline contained +syntax region jsComment start="/\*" end="\*/" contains=jsCommentTodo,jsCvsTag,@Spell fold + +"" JSDoc / JSDoc Toolkit +if !exists("javascript_ignore_javaScriptdoc") + syntax case ignore + + "" syntax coloring for javadoc comments (HTML) + "syntax include @javaHtml :p:h/html.vim + "unlet b:current_syntax + + syntax region jsDocComment matchgroup=jsComment start="/\*\*\s*" end="\*/" contains=jsDocTags,jsCommentTodo,jsCvsTag,@jsHtml,@Spell fold + + " tags containing a param + syntax match jsDocTags contained "@\(alias\|augments\|borrows\|class\|constructs\|default\|defaultvalue\|emits\|exception\|exports\|extends\|file\|fires\|kind\|listens\|member\|member[oO]f\|mixes\|module\|name\|namespace\|requires\|throws\|var\|variation\|version\)\>" nextgroup=jsDocParam skipwhite + " tags containing type and param + syntax match jsDocTags contained "@\(arg\|argument\|param\|property\)\>" nextgroup=jsDocType skipwhite + " tags containing type but no param + syntax match jsDocTags contained "@\(callback\|enum\|external\|this\|type\|typedef\|return\|returns\)\>" nextgroup=jsDocTypeNoParam skipwhite + " tags containing references + syntax match jsDocTags contained "@\(lends\|see\|tutorial\)\>" nextgroup=jsDocSeeTag skipwhite + " other tags (no extra syntax) + syntax match jsDocTags contained "@\(abstract\|access\|author\|classdesc\|constant\|const\|constructor\|copyright\|deprecated\|desc\|description\|event\|example\|file[oO]verview\|function\|global\|ignore\|inner\|instance\|license\|method\|mixin\|overview\|private\|protected\|public\|readonly\|since\|static\|todo\|summary\|undocumented\|virtual\)\>" + + syntax region jsDocType start="{" end="}" oneline contained nextgroup=jsDocParam skipwhite + syntax match jsDocType contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" nextgroup=jsDocParam skipwhite + syntax region jsDocTypeNoParam start="{" end="}" oneline contained + syntax match jsDocTypeNoParam contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" + syntax match jsDocParam contained "\%(#\|\"\|{\|}\|\w\|\.\|:\|\/\)\+" + syntax region jsDocSeeTag contained matchgroup=jsDocSeeTag start="{" end="}" contains=jsDocTags + + syntax case match +endif "" JSDoc end + +syntax case match + +"" Syntax in the JavaScript code +syntax match jsFuncCall /\k\+\%(\s*(\)\@=/ +syntax match jsSpecial "\v\\%(0|\\x\x\{2\}\|\\u\x\{4\}\|\c[A-Z]|.)" contained +syntax match jsTemplateVar "\${.\{-}}" contained +syntax region jsStringD start=+"+ skip=+\\\\\|\\$"+ end=+"+ contains=jsSpecial,@htmlPreproc,@Spell +syntax region jsStringS start=+'+ skip=+\\\\\|\\$'+ end=+'+ contains=jsSpecial,@htmlPreproc,@Spell +syntax region jsTemplateString start=+`+ skip=+\\\\\|\\$`+ end=+`+ contains=jsTemplateVar,jsSpecial,@htmlPreproc +syntax region jsRegexpCharClass start=+\[+ skip=+\\.+ end=+\]+ contained +syntax match jsRegexpBoundary "\v%(\<@![\^$]|\\[bB])" contained +syntax match jsRegexpBackRef "\v\\[1-9][0-9]*" contained +syntax match jsRegexpQuantifier "\v\\@]" contained +syntax cluster jsRegexpSpecial contains=jsSpecial,jsRegexpBoundary,jsRegexpBackRef,jsRegexpQuantifier,jsRegexpOr,jsRegexpMod +syntax region jsRegexpGroup start="\\\@\|\<0[xX]\x\+\>/ +syntax keyword jsNumber Infinity +syntax match jsFloat /\<-\=\%(\d\+\.\d\+\|\d\+\.\|\.\d\+\)\%([eE][+-]\=\d\+\)\=\>/ +syntax match jsObjectKey /\<[a-zA-Z_$][0-9a-zA-Z_$]*\(\s*:\)\@=/ contains=jsFunctionKey contained +syntax match jsFunctionKey /\<[a-zA-Z_$][0-9a-zA-Z_$]*\(\s*:\s*function\s*\)\@=/ contained + +if g:javascript_conceal == 1 + syntax keyword jsNull null conceal cchar=ø + syntax keyword jsThis this conceal cchar=@ + syntax keyword jsReturn return conceal cchar=⇚ + syntax keyword jsUndefined undefined conceal cchar=¿ + syntax keyword jsNan NaN conceal cchar=ℕ + syntax keyword jsPrototype prototype conceal cchar=¶ +else + syntax keyword jsNull null + syntax keyword jsThis this + syntax keyword jsReturn return + syntax keyword jsUndefined undefined + syntax keyword jsNan NaN + syntax keyword jsPrototype prototype +endif + +"" Statement Keywords +syntax keyword jsStatement break continue with +syntax keyword jsConditional if else switch +syntax keyword jsRepeat do while for +syntax keyword jsLabel case default +syntax keyword jsKeyword yield +syntax keyword jsException try catch throw finally + +syntax keyword jsGlobalObjects Array Boolean Date Function Iterator Number Object RegExp String Proxy ParallelArray ArrayBuffer DataView Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray Intl JSON Math console document window +syntax match jsGlobalObjects /\%(Intl\.\)\@<=\(Collator\|DateTimeFormat\|NumberFormat\)/ + +syntax keyword jsExceptions Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError + +syntax keyword jsBuiltins decodeURI decodeURIComponent encodeURI encodeURIComponent eval isFinite isNaN parseFloat parseInt uneval + +syntax keyword jsFutureKeys abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws goto private transient debugger implements protected volatile double import public + +"" DOM/HTML/CSS specified things + +" DOM2 Objects +syntax keyword jsGlobalObjects DOMImplementation DocumentFragment Document Node NodeList NamedNodeMap CharacterData Attr Element Text Comment CDATASection DocumentType Notation Entity EntityReference ProcessingInstruction +syntax keyword jsExceptions DOMException + +" DOM2 CONSTANT +syntax keyword jsDomErrNo INDEX_SIZE_ERR DOMSTRING_SIZE_ERR HIERARCHY_REQUEST_ERR WRONG_DOCUMENT_ERR INVALID_CHARACTER_ERR NO_DATA_ALLOWED_ERR NO_MODIFICATION_ALLOWED_ERR NOT_FOUND_ERR NOT_SUPPORTED_ERR INUSE_ATTRIBUTE_ERR INVALID_STATE_ERR SYNTAX_ERR INVALID_MODIFICATION_ERR NAMESPACE_ERR INVALID_ACCESS_ERR +syntax keyword jsDomNodeConsts ELEMENT_NODE ATTRIBUTE_NODE TEXT_NODE CDATA_SECTION_NODE ENTITY_REFERENCE_NODE ENTITY_NODE PROCESSING_INSTRUCTION_NODE COMMENT_NODE DOCUMENT_NODE DOCUMENT_TYPE_NODE DOCUMENT_FRAGMENT_NODE NOTATION_NODE + +" HTML events and internal variables +syntax case ignore +syntax keyword jsHtmlEvents onblur onclick oncontextmenu ondblclick onfocus onkeydown onkeypress onkeyup onmousedown onmousemove onmouseout onmouseover onmouseup onresize +syntax case match + +" Follow stuff should be highligh within a special context +" While it can't be handled with context depended with Regex based highlight +" So, turn it off by default +if exists("javascript_enable_domhtmlcss") + + " DOM2 things + syntax match jsDomElemAttrs contained /\%(nodeName\|nodeValue\|nodeType\|parentNode\|childNodes\|firstChild\|lastChild\|previousSibling\|nextSibling\|attributes\|ownerDocument\|namespaceURI\|prefix\|localName\|tagName\)\>/ + syntax match jsDomElemFuncs contained /\%(insertBefore\|replaceChild\|removeChild\|appendChild\|hasChildNodes\|cloneNode\|normalize\|isSupported\|hasAttributes\|getAttribute\|setAttribute\|removeAttribute\|getAttributeNode\|setAttributeNode\|removeAttributeNode\|getElementsByTagName\|getAttributeNS\|setAttributeNS\|removeAttributeNS\|getAttributeNodeNS\|setAttributeNodeNS\|getElementsByTagNameNS\|hasAttribute\|hasAttributeNS\)\>/ nextgroup=jsParen skipwhite + " HTML things + syntax match jsHtmlElemAttrs contained /\%(className\|clientHeight\|clientLeft\|clientTop\|clientWidth\|dir\|id\|innerHTML\|lang\|length\|offsetHeight\|offsetLeft\|offsetParent\|offsetTop\|offsetWidth\|scrollHeight\|scrollLeft\|scrollTop\|scrollWidth\|style\|tabIndex\|title\)\>/ + syntax match jsHtmlElemFuncs contained /\%(blur\|click\|focus\|scrollIntoView\|addEventListener\|dispatchEvent\|removeEventListener\|item\)\>/ nextgroup=jsParen skipwhite + + " CSS Styles in JavaScript + syntax keyword jsCssStyles contained color font fontFamily fontSize fontSizeAdjust fontStretch fontStyle fontVariant fontWeight letterSpacing lineBreak lineHeight quotes rubyAlign rubyOverhang rubyPosition + syntax keyword jsCssStyles contained textAlign textAlignLast textAutospace textDecoration textIndent textJustify textJustifyTrim textKashidaSpace textOverflowW6 textShadow textTransform textUnderlinePosition + syntax keyword jsCssStyles contained unicodeBidi whiteSpace wordBreak wordSpacing wordWrap writingMode + syntax keyword jsCssStyles contained bottom height left position right top width zIndex + syntax keyword jsCssStyles contained border borderBottom borderLeft borderRight borderTop borderBottomColor borderLeftColor borderTopColor borderBottomStyle borderLeftStyle borderRightStyle borderTopStyle borderBottomWidth borderLeftWidth borderRightWidth borderTopWidth borderColor borderStyle borderWidth borderCollapse borderSpacing captionSide emptyCells tableLayout + syntax keyword jsCssStyles contained margin marginBottom marginLeft marginRight marginTop outline outlineColor outlineStyle outlineWidth padding paddingBottom paddingLeft paddingRight paddingTop + syntax keyword jsCssStyles contained listStyle listStyleImage listStylePosition listStyleType + syntax keyword jsCssStyles contained background backgroundAttachment backgroundColor backgroundImage gackgroundPosition backgroundPositionX backgroundPositionY backgroundRepeat + syntax keyword jsCssStyles contained clear clip clipBottom clipLeft clipRight clipTop content counterIncrement counterReset cssFloat cursor direction display filter layoutGrid layoutGridChar layoutGridLine layoutGridMode layoutGridType + syntax keyword jsCssStyles contained marks maxHeight maxWidth minHeight minWidth opacity MozOpacity overflow overflowX overflowY verticalAlign visibility zoom cssText + syntax keyword jsCssStyles contained scrollbar3dLightColor scrollbarArrowColor scrollbarBaseColor scrollbarDarkShadowColor scrollbarFaceColor scrollbarHighlightColor scrollbarShadowColor scrollbarTrackColor + + " Highlight ways + syntax match jsDotNotation "\." nextgroup=jsPrototype,jsDomElemAttrs,jsDomElemFuncs,jsHtmlElemAttrs,jsHtmlElemFuncs + syntax match jsDotNotation "\.style\." nextgroup=jsCssStyles + +endif "DOM/HTML/CSS + +"" end DOM/HTML/CSS specified things + + +"" Code blocks +syntax cluster jsExpression contains=jsComment,jsLineComment,jsDocComment,jsTemplateString,jsStringD,jsStringS,jsRegexpString,jsNumber,jsFloat,jsThis,jsOperator,jsBooleanTrue,jsBooleanFalse,jsNull,jsFunction,jsArrowFunction,jsGlobalObjects,jsExceptions,jsFutureKeys,jsDomErrNo,jsDomNodeConsts,jsHtmlEvents,jsDotNotation,jsBracket,jsParen,jsBlock,jsFuncCall,jsUndefined,jsNan,jsKeyword,jsStorageClass,jsPrototype,jsBuiltins,jsNoise +syntax cluster jsAll contains=@jsExpression,jsLabel,jsConditional,jsRepeat,jsReturn,jsStatement,jsTernaryIf,jsException +syntax region jsBracket matchgroup=jsBrackets start="\[" end="\]" contains=@jsAll,jsParensErrB,jsParensErrC,jsBracket,jsParen,jsBlock,@htmlPreproc fold +syntax region jsParen matchgroup=jsParens start="(" end=")" contains=@jsAll,jsParensErrA,jsParensErrC,jsParen,jsBracket,jsBlock,@htmlPreproc fold +syntax region jsBlock matchgroup=jsBraces start="{" end="}" contains=@jsAll,jsParensErrA,jsParensErrB,jsParen,jsBracket,jsBlock,jsObjectKey,@htmlPreproc fold +syntax region jsFuncBlock matchgroup=jsFuncBraces start="{" end="}" contains=@jsAll,jsParensErrA,jsParensErrB,jsParen,jsBracket,jsBlock,@htmlPreproc contained fold +syntax region jsTernaryIf matchgroup=jsTernaryIfOperator start=+?+ end=+:+ contains=@jsExpression,jsTernaryIf + +"" catch errors caused by wrong parenthesis +syntax match jsParensError ")\|}\|\]" +syntax match jsParensErrA contained "\]" +syntax match jsParensErrB contained ")" +syntax match jsParensErrC contained "}" + +if main_syntax == "javascript" + syntax sync clear + syntax sync ccomment jsComment minlines=200 + syntax sync match jsHighlight grouphere jsBlock /{/ +endif + +if g:javascript_conceal == 1 + syntax match jsFunction /\/ nextgroup=jsFuncName,jsFuncArgs skipwhite conceal cchar=ƒ +else + syntax match jsFunction /\/ nextgroup=jsFuncName,jsFuncArgs skipwhite +endif + +syntax match jsFuncName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*/ nextgroup=jsFuncArgs skipwhite +syntax region jsFuncArgs contained matchgroup=jsFuncParens start='(' end=')' contains=jsFuncArgCommas,jsFuncArgRest nextgroup=jsFuncBlock keepend skipwhite skipempty +syntax match jsFuncArgCommas contained ',' +syntax match jsFuncArgRest contained /\%(\.\.\.[a-zA-Z_$][0-9a-zA-Z_$]*\))/ +syntax keyword jsArgsObj arguments contained containedin=jsFuncBlock + +syntax match jsArrowFunction /=>/ + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_javascript_syn_inits") + if version < 508 + let did_javascript_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + HiLink jsFuncArgRest Special + HiLink jsComment Comment + HiLink jsLineComment Comment + HiLink jsEnvComment PreProc + HiLink jsDocComment Comment + HiLink jsCommentTodo Todo + HiLink jsCvsTag Function + HiLink jsDocTags Special + HiLink jsDocSeeTag Function + HiLink jsDocType Type + HiLink jsDocTypeNoParam Type + HiLink jsDocParam Label + HiLink jsStringS String + HiLink jsStringD String + HiLink jsTemplateString String + HiLink jsTernaryIfOperator Conditional + HiLink jsRegexpString String + HiLink jsRegexpBoundary SpecialChar + HiLink jsRegexpQuantifier SpecialChar + HiLink jsRegexpOr Conditional + HiLink jsRegexpMod SpecialChar + HiLink jsRegexpBackRef SpecialChar + HiLink jsRegexpGroup jsRegexpString + HiLink jsRegexpCharClass Character + HiLink jsCharacter Character + HiLink jsPrototype Special + HiLink jsConditional Conditional + HiLink jsBranch Conditional + HiLink jsLabel Label + HiLink jsReturn Statement + HiLink jsRepeat Repeat + HiLink jsStatement Statement + HiLink jsException Exception + HiLink jsKeyword Keyword + HiLink jsArrowFunction Type + HiLink jsFunction Type + HiLink jsFuncName Function + HiLink jsArgsObj Special + HiLink jsError Error + HiLink jsParensError Error + HiLink jsParensErrA Error + HiLink jsParensErrB Error + HiLink jsParensErrC Error + HiLink jsOperator Operator + HiLink jsStorageClass StorageClass + HiLink jsThis Special + HiLink jsNan Number + HiLink jsNull Type + HiLink jsUndefined Type + HiLink jsNumber Number + HiLink jsFloat Float + HiLink jsBooleanTrue Boolean + HiLink jsBooleanFalse Boolean + HiLink jsNoise Noise + HiLink jsBrackets Noise + HiLink jsParens Noise + HiLink jsBraces Noise + HiLink jsFuncBraces Noise + HiLink jsFuncParens Noise + HiLink jsSpecial Special + HiLink jsTemplateVar Special + HiLink jsGlobalObjects Special + HiLink jsExceptions Special + HiLink jsFutureKeys Special + HiLink jsBuiltins Special + + HiLink jsDomErrNo Constant + HiLink jsDomNodeConsts Constant + HiLink jsDomElemAttrs Label + HiLink jsDomElemFuncs PreProc + + HiLink jsHtmlEvents Special + HiLink jsHtmlElemAttrs Label + HiLink jsHtmlElemFuncs PreProc + + HiLink jsCssStyles Label + + delcommand HiLink +endif + +" Define the htmlJavaScript for HTML syntax html.vim +"syntax clear htmlJavaScript +"syntax clear jsExpression +syntax cluster htmlJavaScript contains=@jsAll,jsBracket,jsParen,jsBlock +syntax cluster javaScriptExpression contains=@jsAll,jsBracket,jsParen,jsBlock,@htmlPreproc +" Vim's default html.vim highlights all javascript as 'Special' +hi! def link javaScript NONE + +let b:current_syntax = "javascript" +if main_syntax == 'javascript' + unlet main_syntax +endif From e3d309b9cf8dfd70b7bbf4c9b884c8a062c0ebdb Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Mon, 4 Aug 2014 15:42:56 -0700 Subject: [PATCH 006/177] H for home, L for end, J retains cursor position --- vimrc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vimrc b/vimrc index fa29b5c..adfdca7 100644 --- a/vimrc +++ b/vimrc @@ -147,6 +147,12 @@ map L :set invnumber map v "+gP " ,c = Copy map c "+y +" Keep the cursor in place while joining lines +nnoremap J mzJ`z +" H = Home, L = End +noremap H ^ +noremap L $ +vnoremap L g_ " Deletes trailing space in file upon write " autocmd BufWritePre * :%s/\s\+$//e From e172f3d490c27391b570107a94b9d97d52da833e Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Tue, 5 Aug 2014 11:13:11 -0700 Subject: [PATCH 007/177] keep search lines centered vertically --- vimrc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/vimrc b/vimrc index adfdca7..1633865 100644 --- a/vimrc +++ b/vimrc @@ -43,13 +43,26 @@ set incsearch "Search while typing set ignorecase "Case Insensitive Searching set smartcase "Lowercase = case insensitive, any uppercase = case sensitive set hlsearch "Highlight all search results + "Following line clears the search highlights when pressing Lb nnoremap b :nohlsearch + " http://www.vim.org/scripts/script.php?script_id=2572 +" ,a will open a prmompt for a term to search for noremap a :Ack + +" ,A will close the new window created for that ack search noremap A jcl let g:ackprg="ack -H --nocolor --nogroup --column --type-add php=.tpl" +" WHen searching for words with * and navigating with N/n, keep line centered vertically +:nnoremap n nzz +:nnoremap N Nzz +:nnoremap * *zz +:nnoremap # #zz +:nnoremap g* g*zz +:nnoremap g# g#zz + "------ Replacing ------ "type S, then type what you're looking for, a /, and what to replace it with nmap S :%s//g From 3ffac82f3a337e27fdc15ba5cafcacb6d487d1f1 Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Wed, 27 Aug 2014 17:24:22 -0700 Subject: [PATCH 008/177] autocomplete pluging (and L9 dependency) --- bundle/autocomplpop/.hg_archival.txt | 5 + bundle/autocomplpop/.hgtags | 15 + bundle/autocomplpop/autoload/acp.vim | 422 ++++++++++++++++++ bundle/autocomplpop/doc/acp.jax | 302 +++++++++++++ bundle/autocomplpop/doc/acp.txt | 519 +++++++++++++++++++++ bundle/autocomplpop/plugin/acp.vim | 164 +++++++ bundle/l9/.hg_archival.txt | 5 + bundle/l9/.hgtags | 3 + bundle/l9/autoload/l9.vim | 570 ++++++++++++++++++++++++ bundle/l9/autoload/l9/async.py | 92 ++++ bundle/l9/autoload/l9/async.vim | 67 +++ bundle/l9/autoload/l9/quickfix.vim | 107 +++++ bundle/l9/autoload/l9/tempbuffer.vim | 112 +++++ bundle/l9/autoload/l9/tempvariables.vim | 60 +++ bundle/l9/doc/l9.jax | 55 +++ bundle/l9/doc/l9.txt | 73 +++ bundle/l9/plugin/l9.vim | 108 +++++ 17 files changed, 2679 insertions(+) create mode 100644 bundle/autocomplpop/.hg_archival.txt create mode 100644 bundle/autocomplpop/.hgtags create mode 100644 bundle/autocomplpop/autoload/acp.vim create mode 100644 bundle/autocomplpop/doc/acp.jax create mode 100644 bundle/autocomplpop/doc/acp.txt create mode 100644 bundle/autocomplpop/plugin/acp.vim create mode 100644 bundle/l9/.hg_archival.txt create mode 100644 bundle/l9/.hgtags create mode 100644 bundle/l9/autoload/l9.vim create mode 100644 bundle/l9/autoload/l9/async.py create mode 100644 bundle/l9/autoload/l9/async.vim create mode 100644 bundle/l9/autoload/l9/quickfix.vim create mode 100644 bundle/l9/autoload/l9/tempbuffer.vim create mode 100644 bundle/l9/autoload/l9/tempvariables.vim create mode 100644 bundle/l9/doc/l9.jax create mode 100644 bundle/l9/doc/l9.txt create mode 100644 bundle/l9/plugin/l9.vim diff --git a/bundle/autocomplpop/.hg_archival.txt b/bundle/autocomplpop/.hg_archival.txt new file mode 100644 index 0000000..4c3134c --- /dev/null +++ b/bundle/autocomplpop/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: ff67c023fb3e2ce489f284a244e18dbb62a3000c +node: 13fe3d8064647e2cdf07e12840108c3f917f5636 +branch: default +latesttag: 2.14.1 +latesttagdistance: 9 diff --git a/bundle/autocomplpop/.hgtags b/bundle/autocomplpop/.hgtags new file mode 100644 index 0000000..b50731c --- /dev/null +++ b/bundle/autocomplpop/.hgtags @@ -0,0 +1,15 @@ +ff67c023fb3e2ce489f284a244e18dbb62a3000c 2.4 +98e1d4500a5bfcd6865216acffde4e9d99823be5 2.5 +c009f261897d73a4a8245aa65782c1aa4a9fd663 2.6 +87ee87ff9c82e12698c5765b5949523ae58b209a 2.7 +69618b0e126c4bb4dab20811a4ba27744268461a 2.8 +5953b890146a7a550d2c2b98dd757afe4d023b7f 2.8.1 +996112fae9dc5dfd49788d652ff757b6664fa61a 2.9 +cb7f232160e9bfb65b0624f3fcb8c1e115165134 2.10 +4f1373dd63c197d06173ed51a4f73d2432b0d228 2.11 +8d917429d79da8c998942c1c32c0a8681834893a 2.11.1 +c213673f79d1031d327a7b2b45a7144cc966fadc 2.12 +117cbade6abb27c0128397b0626576efc1e7b656 2.12.1 +a9c3d9285c214cf0b9804cf295f7a41139f9606c 2.13 +97404067dc5e8e51f676aaf2918f53f134e7e459 2.14 +1f5b001e7facc6b88b46d41268c4275a0961f972 2.14.1 diff --git a/bundle/autocomplpop/autoload/acp.vim b/bundle/autocomplpop/autoload/acp.vim new file mode 100644 index 0000000..faa53e8 --- /dev/null +++ b/bundle/autocomplpop/autoload/acp.vim @@ -0,0 +1,422 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 0, 0, []) + finish +endif + +" }}}1 +"============================================================================= +" GLOBAL FUNCTIONS: {{{1 + +" +function acp#enable() + call acp#disable() + + augroup AcpGlobalAutoCommand + autocmd! + autocmd InsertEnter * unlet! s:posLast s:lastUncompletable + autocmd InsertLeave * call s:finishPopup(1) + augroup END + + if g:acp_mappingDriven + call s:mapForMappingDriven() + else + autocmd AcpGlobalAutoCommand CursorMovedI * call s:feedPopup() + endif + + nnoremap i i=feedPopup() + nnoremap a a=feedPopup() + nnoremap R R=feedPopup() +endfunction + +" +function acp#disable() + call s:unmapForMappingDriven() + augroup AcpGlobalAutoCommand + autocmd! + augroup END + nnoremap i | nunmap i + nnoremap a | nunmap a + nnoremap R | nunmap R +endfunction + +" +function acp#lock() + let s:lockCount += 1 +endfunction + +" +function acp#unlock() + let s:lockCount -= 1 + if s:lockCount < 0 + let s:lockCount = 0 + throw "AutoComplPop: not locked" + endif +endfunction + +" +function acp#meetsForSnipmate(context) + if g:acp_behaviorSnipmateLength < 0 + return 0 + endif + let matches = matchlist(a:context, '\(^\|\s\|\<\)\(\u\{' . + \ g:acp_behaviorSnipmateLength . ',}\)$') + return !empty(matches) && !empty(s:getMatchingSnipItems(matches[2])) +endfunction + +" +function acp#meetsForKeyword(context) + if g:acp_behaviorKeywordLength < 0 + return 0 + endif + let matches = matchlist(a:context, '\(\k\{' . g:acp_behaviorKeywordLength . ',}\)$') + if empty(matches) + return 0 + endif + for ignore in g:acp_behaviorKeywordIgnores + if stridx(ignore, matches[1]) == 0 + return 0 + endif + endfor + return 1 +endfunction + +" +function acp#meetsForFile(context) + if g:acp_behaviorFileLength < 0 + return 0 + endif + if has('win32') || has('win64') + let separator = '[/\\]' + else + let separator = '\/' + endif + if a:context !~ '\f' . separator . '\f\{' . g:acp_behaviorFileLength . ',}$' + return 0 + endif + return a:context !~ '[*/\\][/\\]\f*$\|[^[:print:]]\f*$' +endfunction + +" +function acp#meetsForRubyOmni(context) + if !has('ruby') + return 0 + endif + if g:acp_behaviorRubyOmniMethodLength >= 0 && + \ a:context =~ '[^. \t]\(\.\|::\)\k\{' . + \ g:acp_behaviorRubyOmniMethodLength . ',}$' + return 1 + endif + if g:acp_behaviorRubyOmniSymbolLength >= 0 && + \ a:context =~ '\(^\|[^:]\):\k\{' . + \ g:acp_behaviorRubyOmniSymbolLength . ',}$' + return 1 + endif + return 0 +endfunction + +" +function acp#meetsForPythonOmni(context) + return has('python') && g:acp_behaviorPythonOmniLength >= 0 && + \ a:context =~ '\k\.\k\{' . g:acp_behaviorPythonOmniLength . ',}$' +endfunction + +" +function acp#meetsForPerlOmni(context) + return g:acp_behaviorPerlOmniLength >= 0 && + \ a:context =~ '\w->\k\{' . g:acp_behaviorPerlOmniLength . ',}$' +endfunction + +" +function acp#meetsForXmlOmni(context) + return g:acp_behaviorXmlOmniLength >= 0 && + \ a:context =~ '\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{' . + \ g:acp_behaviorXmlOmniLength . ',}$' +endfunction + +" +function acp#meetsForHtmlOmni(context) + return g:acp_behaviorHtmlOmniLength >= 0 && + \ a:context =~ '\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{' . + \ g:acp_behaviorHtmlOmniLength . ',}$' +endfunction + +" +function acp#meetsForCssOmni(context) + if g:acp_behaviorCssOmniPropertyLength >= 0 && + \ a:context =~ '\(^\s\|[;{]\)\s*\k\{' . + \ g:acp_behaviorCssOmniPropertyLength . ',}$' + return 1 + endif + if g:acp_behaviorCssOmniValueLength >= 0 && + \ a:context =~ '[:@!]\s*\k\{' . + \ g:acp_behaviorCssOmniValueLength . ',}$' + return 1 + endif + return 0 +endfunction + +" +function acp#completeSnipmate(findstart, base) + if a:findstart + let s:posSnipmateCompletion = len(matchstr(s:getCurrentText(), '.*\U')) + return s:posSnipmateCompletion + endif + let lenBase = len(a:base) + let items = filter(GetSnipsInCurrentScope(), + \ 'strpart(v:key, 0, lenBase) ==? a:base') + return map(sort(items(items)), 's:makeSnipmateItem(v:val[0], v:val[1])') +endfunction + +" +function acp#onPopupCloseSnipmate() + let word = s:getCurrentText()[s:posSnipmateCompletion :] + for trigger in keys(GetSnipsInCurrentScope()) + if word ==# trigger + call feedkeys("\=TriggerSnippet()\", "n") + return 0 + endif + endfor + return 1 +endfunction + +" +function acp#onPopupPost() + " to clear = expression on command-line + echo '' + if pumvisible() + inoremap acp#onBs() + inoremap acp#onBs() + " a command to restore to original text and select the first match + return (s:behavsCurrent[s:iBehavs].command =~# "\" ? "\\" + \ : "\\") + endif + let s:iBehavs += 1 + if len(s:behavsCurrent) > s:iBehavs + call s:setCompletefunc() + return printf("\%s\=acp#onPopupPost()\", + \ s:behavsCurrent[s:iBehavs].command) + else + let s:lastUncompletable = { + \ 'word': s:getCurrentWord(), + \ 'commands': map(copy(s:behavsCurrent), 'v:val.command')[1:], + \ } + call s:finishPopup(0) + return "\" + endif +endfunction + +" +function acp#onBs() + " using "matchstr" and not "strpart" in order to handle multi-byte + " characters + if call(s:behavsCurrent[s:iBehavs].meets, + \ [matchstr(s:getCurrentText(), '.*\ze.')]) + return "\" + endif + return "\\" +endfunction + +" }}}1 +"============================================================================= +" LOCAL FUNCTIONS: {{{1 + +" +function s:mapForMappingDriven() + call s:unmapForMappingDriven() + let s:keysMappingDriven = [ + \ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + \ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + \ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + \ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + \ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + \ '-', '_', '~', '^', '.', ',', ':', '!', '#', '=', '%', '$', '@', '<', '>', '/', '\', + \ '', '', '', ] + for key in s:keysMappingDriven + execute printf('inoremap %s %s=feedPopup()', + \ key, key) + endfor +endfunction + +" +function s:unmapForMappingDriven() + if !exists('s:keysMappingDriven') + return + endif + for key in s:keysMappingDriven + execute 'iunmap ' . key + endfor + let s:keysMappingDriven = [] +endfunction + +" +function s:getCurrentWord() + return matchstr(s:getCurrentText(), '\k*$') +endfunction + +" +function s:getCurrentText() + return strpart(getline('.'), 0, col('.') - 1) +endfunction + +" +function s:getPostText() + return strpart(getline('.'), col('.') - 1) +endfunction + +" +function s:isModifiedSinceLastCall() + if exists('s:posLast') + let posPrev = s:posLast + let nLinesPrev = s:nLinesLast + let textPrev = s:textLast + endif + let s:posLast = getpos('.') + let s:nLinesLast = line('$') + let s:textLast = getline('.') + if !exists('posPrev') + return 1 + elseif posPrev[1] != s:posLast[1] || nLinesPrev != s:nLinesLast + return (posPrev[1] - s:posLast[1] == nLinesPrev - s:nLinesLast) + elseif textPrev ==# s:textLast + return 0 + elseif posPrev[2] > s:posLast[2] + return 1 + elseif has('gui_running') && has('multi_byte') + " NOTE: auto-popup causes a strange behavior when IME/XIM is working + return posPrev[2] + 1 == s:posLast[2] + endif + return posPrev[2] != s:posLast[2] +endfunction + +" +function s:makeCurrentBehaviorSet() + let modified = s:isModifiedSinceLastCall() + if exists('s:behavsCurrent[s:iBehavs].repeat') && s:behavsCurrent[s:iBehavs].repeat + let behavs = [ s:behavsCurrent[s:iBehavs] ] + elseif exists('s:behavsCurrent[s:iBehavs]') + return [] + elseif modified + let behavs = copy(exists('g:acp_behavior[&filetype]') + \ ? g:acp_behavior[&filetype] + \ : g:acp_behavior['*']) + else + return [] + endif + let text = s:getCurrentText() + call filter(behavs, 'call(v:val.meets, [text])') + let s:iBehavs = 0 + if exists('s:lastUncompletable') && + \ stridx(s:getCurrentWord(), s:lastUncompletable.word) == 0 && + \ map(copy(behavs), 'v:val.command') ==# s:lastUncompletable.commands + let behavs = [] + else + unlet! s:lastUncompletable + endif + return behavs +endfunction + +" +function s:feedPopup() + " NOTE: CursorMovedI is not triggered while the popup menu is visible. And + " it will be triggered when popup menu is disappeared. + if s:lockCount > 0 || pumvisible() || &paste + return '' + endif + if exists('s:behavsCurrent[s:iBehavs].onPopupClose') + if !call(s:behavsCurrent[s:iBehavs].onPopupClose, []) + call s:finishPopup(1) + return '' + endif + endif + let s:behavsCurrent = s:makeCurrentBehaviorSet() + if empty(s:behavsCurrent) + call s:finishPopup(1) + return '' + endif + " In case of dividing words by symbols (e.g. "for(int", "ab==cd") while a + " popup menu is visible, another popup is not available unless input + " or try popup once. So first completion is duplicated. + call insert(s:behavsCurrent, s:behavsCurrent[s:iBehavs]) + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&spell', 0) + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&completeopt', 'menuone' . (g:acp_completeoptPreview ? ',preview' : '')) + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&complete', g:acp_completeOption) + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&ignorecase', g:acp_ignorecaseOption) + " NOTE: With CursorMovedI driven, Set 'lazyredraw' to avoid flickering. + " With Mapping driven, set 'nolazyredraw' to make a popup menu visible. + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&lazyredraw', !g:acp_mappingDriven) + " NOTE: 'textwidth' must be restored after . + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP1, + \ '&textwidth', 0) + call s:setCompletefunc() + call feedkeys(s:behavsCurrent[s:iBehavs].command . "\=acp#onPopupPost()\", 'n') + return '' " this function is called by = +endfunction + +" +function s:finishPopup(fGroup1) + inoremap | iunmap + inoremap | iunmap + let s:behavsCurrent = [] + call l9#tempvariables#end(s:TEMP_VARIABLES_GROUP0) + if a:fGroup1 + call l9#tempvariables#end(s:TEMP_VARIABLES_GROUP1) + endif +endfunction + +" +function s:setCompletefunc() + if exists('s:behavsCurrent[s:iBehavs].completefunc') + call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP0, + \ '&completefunc', s:behavsCurrent[s:iBehavs].completefunc) + endif +endfunction + +" +function s:makeSnipmateItem(key, snip) + if type(a:snip) == type([]) + let descriptions = map(copy(a:snip), 'v:val[0]') + let snipFormatted = '[MULTI] ' . join(descriptions, ', ') + else + let snipFormatted = substitute(a:snip, '\(\n\|\s\)\+', ' ', 'g') + endif + return { + \ 'word': a:key, + \ 'menu': strpart(snipFormatted, 0, 80), + \ } +endfunction + +" +function s:getMatchingSnipItems(base) + let key = a:base . "\n" + if !exists('s:snipItems[key]') + let s:snipItems[key] = items(GetSnipsInCurrentScope()) + call filter(s:snipItems[key], 'strpart(v:val[0], 0, len(a:base)) ==? a:base') + call map(s:snipItems[key], 's:makeSnipmateItem(v:val[0], v:val[1])') + endif + return s:snipItems[key] +endfunction + +" }}}1 +"============================================================================= +" INITIALIZATION {{{1 + +let s:TEMP_VARIABLES_GROUP0 = "AutoComplPop0" +let s:TEMP_VARIABLES_GROUP1 = "AutoComplPop1" +let s:lockCount = 0 +let s:behavsCurrent = [] +let s:iBehavs = 0 +let s:snipItems = {} + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/bundle/autocomplpop/doc/acp.jax b/bundle/autocomplpop/doc/acp.jax new file mode 100644 index 0000000..2e6e435 --- /dev/null +++ b/bundle/autocomplpop/doc/acp.jax @@ -0,0 +1,302 @@ +*acp.txt* 補完メニューの自動ポップアップ + + Copyright (c) 2007-2009 Takeshi NISHIDA + +AutoComplPop *autocomplpop* *acp* + +概要 |acp-introduction| +インストール |acp-installation| +使い方 |acp-usage| +コマンド |acp-commands| +オプション |acp-options| +SPECIAL THANKS |acp-thanks| +CHANGELOG |acp-changelog| +あばうと |acp-about| + + +============================================================================== +概要 *acp-introduction* + +このプラグインは、インサートモードで文字を入力したりカーソルを動かしたときに補 +完メニューを自動的に開くようにします。しかし、続けて文字を入力するのを妨げたり +はしません。 + + +============================================================================== +インストール *acp-installation* + +ZIPファイルをランタイムディレクトリに展開します。 + +以下のようにファイルが配置されるはずです。 +> + /plugin/acp.vim + /doc/acp.txt + ... +< +もしランタイムディレクトリが多数のプラグインでごちゃごちゃになるのが嫌なら、各 +プラグインを個別のディレクトリに配置し、そのディレクトリのパスを 'runtimepath' +に追加してください。アンインストールも楽になります。 + +その後、ヘルプを有効にするためにタグファイルを更新してください。詳しくは +|add-local-help|を参照してください。 + +必要なもの: ~ + +- L9 library (vimscript #3252) + + +============================================================================== +使い方 *acp-usage* + +このプラグインがインストールされていれば、自動ポップアップは vim の開始時から +有効になります。 + +カーソル直前のテキストに応じて、利用する補完の種類を切り替えます。デフォルトの +補完動作は次の通りです: + + 補完モード filetype カーソル直前のテキスト ~ + キーワード補完 * 2文字のキーワード文字 + ファイル名補完 * ファイル名文字 + パスセパレータ + + 0文字以上のファイル名文字 + オムニ補完 ruby ".", "::" or 単語を構成する文字以外 + ":" + オムニ補完 python "." + オムニ補完 xml "<", ""以外の文字列 + " ") + オムニ補完 html/xhtml "<", ""以外の文字列 + " ") + オムニ補完 css (":", ";", "{", "^", "@", or "!") + + 0個または1個のスペース + +さらに、設定を行うことで、ユーザー定義補完と snipMate トリガー補完 +(|acp-snipMate|) を自動ポップアップさせることができます。 + +これらの補完動作はカスタマイズ可能です。 + + *acp-snipMate* +snipMate トリガー補完 ~ + +snipMate トリガー補完では、snipMate プラグイン +(http://www.vim.org/scripts/script.php?script_id=2540) が提供するスニペットの +トリガーを補完してそれを展開することができます。 + +この自動ポップアップを有効にするには、次の関数を plugin/snipMate.vim に追加す +る必要があります: +> + fun! GetSnipsInCurrentScope() + let snips = {} + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + call extend(snips, get(s:snippets, scope, {}), 'keep') + call extend(snips, get(s:multi_snips, scope, {}), 'keep') + endfor + return snips + endf +< +そして|g:acp_behaviorSnipmateLength|オプションを 1 にしてください。 + +この自動ポップアップには制限があり、カーソル直前の単語は大文字英字だけで構成さ +れていなければなりません。 + + *acp-perl-omni* +Perl オムニ補完 ~ + +AutoComplPop は perl-completion.vim +(http://www.vim.org/scripts/script.php?script_id=2852) をサポートしています。 + +この自動ポップアップを有効にするには、|g:acp_behaviorPerlOmniLength|オプション +を 0 以上にしてください。 + + +============================================================================== +コマンド *acp-commands* + + *:AcpEnable* +:AcpEnable + 自動ポップアップを有効にします。 + + *:AcpDisable* +:AcpDisable + 自動ポップアップを無効にします。 + + *:AcpLock* +:AcpLock + 自動ポップアップを一時的に停止します。 + + 別のスクリプトへの干渉を回避する目的なら、このコマンドと|:AcpUnlock| + を利用することを、|:AcpDisable|と|:AcpEnable| を利用するよりも推奨しま + す。 + + *:AcpUnlock* +:AcpUnlock + |:AcpLock| で停止された自動ポップアップを再開します。 + + +============================================================================== +オプション *acp-options* + + *g:acp_enableAtStartup* > + let g:acp_enableAtStartup = 1 +< + 真なら vim 開始時から自動ポップアップが有効になります。 + + *g:acp_mappingDriven* > + let g:acp_mappingDriven = 0 +< + 真なら|CursorMovedI|イベントではなくキーマッピングで自動ポップアップを + 行うようにします。カーソルを移動するたびに補完が行われることで重いなど + の不都合がある場合に利用してください。ただし他のプラグインとの相性問題 + や日本語入力での不具合が発生する可能性があります。(逆も然り。) + + *g:acp_ignorecaseOption* > + let g:acp_ignorecaseOption = 1 +< + 自動ポップアップ時に、'ignorecase' に一時的に設定する値 + + *g:acp_completeOption* > + let g:acp_completeOption = '.,w,b,k' +< + 自動ポップアップ時に、'complete' に一時的に設定する値 + + *g:acp_completeoptPreview* > + let g:acp_completeoptPreview = 0 +< + 真なら自動ポップアップ時に、 'completeopt' へ "preview" を追加します。 + + *g:acp_behaviorUserDefinedFunction* > + let g:acp_behaviorUserDefinedFunction = '' +< + ユーザー定義補完の|g:acp_behavior-completefunc|。空ならこの補完は行わ + れません。。 + + *g:acp_behaviorUserDefinedMeets* > + let g:acp_behaviorUserDefinedMeets = '' +< + ユーザー定義補完の|g:acp_behavior-meets|。空ならこの補完は行われません + 。 + + *g:acp_behaviorSnipmateLength* > + let g:acp_behaviorSnipmateLength = -1 +< + snipMate トリガー補完の自動ポップアップを行うのに必要なカーソルの直前 + のパターン。 + + *g:acp_behaviorKeywordCommand* > + let g:acp_behaviorKeywordCommand = "\" +< + キーワード補完のコマンド。このオプションには普通 "\" か "\" + を設定します。 + + *g:acp_behaviorKeywordLength* > + let g:acp_behaviorKeywordLength = 2 +< + キーワード補完の自動ポップアップを行うのに必要なカーソルの直前のキーワ + ード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorKeywordIgnores* > + let g:acp_behaviorKeywordIgnores = [] +< + 文字列のリスト。カーソル直前の単語がこれらの内いずれかの先頭部分にマッ + チする場合、この補完は行われません。 + + 例えば、 "get" で始まる補完キーワードが多過ぎて、"g", "ge", "get" を入 + 力したときの自動ポップアップがレスポンスの低下を引き起こしている場合、 + このオプションに ["get"] を設定することでそれを回避することができます。 + + *g:acp_behaviorFileLength* > + let g:acp_behaviorFileLength = 0 +< + ファイル名補完の自動ポップアップを行うのに必要なカーソルの直前のキーワ + ード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorRubyOmniMethodLength* > + let g:acp_behaviorRubyOmniMethodLength = 0 +< + メソッド補完のための、Ruby オムニ補完の自動ポップアップを行うのに必要 + なカーソルの直前のキーワード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorRubyOmniSymbolLength* > + let g:acp_behaviorRubyOmniSymbolLength = 1 +< + シンボル補完のための、Ruby オムニ補完の自動ポップアップを行うのに必要 + なカーソルの直前のキーワード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorPythonOmniLength* > + let g:acp_behaviorPythonOmniLength = 0 +< + Python オムニ補完の自動ポップアップを行うのに必要なカーソルの直前のキ + ーワード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorPerlOmniLength* > + let g:acp_behaviorPerlOmniLength = -1 +< + Perl オムニ補完の自動ポップアップを行うのに必要なカーソルの直前のキー + ワード文字数。負数ならこの補完は行われません。 + + See also: |acp-perl-omni| + + *g:acp_behaviorXmlOmniLength* > + let g:acp_behaviorXmlOmniLength = 0 +< + XML オムニ補完の自動ポップアップを行うのに必要なカーソルの直前のキーワ + ード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorHtmlOmniLength* > + let g:acp_behaviorHtmlOmniLength = 0 +< + HTML オムニ補完の自動ポップアップを行うのに必要なカーソルの直前のキー + ワード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorCssOmniPropertyLength* > + let g:acp_behaviorCssOmniPropertyLength = 1 +< + プロパティ補完のための、CSS オムニ補完の自動ポップアップを行うのに必要 + なカーソルの直前のキーワード文字数。負数ならこの補完は行われません。 + + *g:acp_behaviorCssOmniValueLength* > + let g:acp_behaviorCssOmniValueLength = 0 +< + 値補完のための、CSS オムニ補完の自動ポップアップを行うのに必要なカーソ + ルの直前のキーワード文字数。負数ならこの補完は行われません。 + + *g:acp_behavior* > + let g:acp_behavior = {} +< + + これは内部仕様がわかっている人向けのオプションで、他のオプションでの設 + 定より優先されます。 + + |Dictionary|型で、キーはファイルタイプに対応します。 '*' はデフォルト + を表します。値はリスト型です。補完候補が得られるまでリストの先頭アイテ + ムから順に評価します。各要素は|Dictionary|で詳細は次の通り: + + "command": *g:acp_behavior-command* + 補完メニューをポップアップするためのコマンド。 + + "completefunc": *g:acp_behavior-completefunc* + 'completefunc' に設定する関数。 "command" が "" のときだけ + 意味があります。 + + "meets": *g:acp_behavior-meets* + この補完を行うかどうかを判断する関数の名前。この関数はカーソル直前の + テキストを引数に取り、補完を行うなら非 0 の値を返します。 + + "onPopupClose": *g:acp_behavior-onPopupClose* + この補完のポップアップメニューが閉じられたときに呼ばれる関数の名前。 + この関数が 0 を返した場合、続いて行われる予定の補完は抑制されます。 + + "repeat": *g:acp_behavior-repeat* + 真なら最後の補完が自動的に繰り返されます。 + + +============================================================================== +あばうと *acp-about* *acp-contact* *acp-author* + +作者: Takeshi NISHIDA +ライセンス: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=1879 + http://bitbucket.org/ns9tks/vim-autocomplpop/ + +バグや要望など ~ + +こちらへどうぞ: http://bitbucket.org/ns9tks/vim-autocomplpop/issues/ + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: + diff --git a/bundle/autocomplpop/doc/acp.txt b/bundle/autocomplpop/doc/acp.txt new file mode 100644 index 0000000..a9c40e8 --- /dev/null +++ b/bundle/autocomplpop/doc/acp.txt @@ -0,0 +1,519 @@ +*acp.txt* Automatically opens popup menu for completions. + + Copyright (c) 2007-2009 Takeshi NISHIDA + +AutoComplPop *autocomplpop* *acp* + +INTRODUCTION |acp-introduction| +INSTALLATION |acp-installation| +USAGE |acp-usage| +COMMANDS |acp-commands| +OPTIONS |acp-options| +SPECIAL THANKS |acp-thanks| +CHANGELOG |acp-changelog| +ABOUT |acp-about| + + +============================================================================== +INTRODUCTION *acp-introduction* + +With this plugin, your vim comes to automatically opens popup menu for +completions when you enter characters or move the cursor in Insert mode. It +won't prevent you continuing entering characters. + + +============================================================================== +INSTALLATION *acp-installation* + +Put all files into your runtime directory. If you have the zip file, extract +it to your runtime directory. + +You should place the files as follows: +> + /plugin/acp.vim + /doc/acp.txt + ... +< +If you are disgusted to make your runtime directory confused with a lot of +plugins, put each of the plugins into a directory individually and just add +the directory path to 'runtimepath'. It's easy to uninstall plugins. + +Then update your help tags files to enable help for this plugin. See +|add-local-help| for details. + +Requirements: ~ + +- L9 library (vimscript #3252) + + +============================================================================== +USAGE *acp-usage* + +Once this plugin is installed, auto-popup is enabled at startup by default. + +Which completion method is used depends on the text before the cursor. The +default behavior is as follows: + + kind filetype text before the cursor ~ + Keyword * two keyword characters + Filename * a filename character + a path separator + + 0 or more filename character + Omni ruby ".", "::" or non-word character + ":" + (|+ruby| required.) + Omni python "." (|+python| required.) + Omni xml "<", "" characters + " ") + Omni html/xhtml "<", "" characters + " ") + Omni css (":", ";", "{", "^", "@", or "!") + + 0 or 1 space + +Also, you can make user-defined completion and snipMate's trigger completion +(|acp-snipMate|) auto-popup if the options are set. + +These behavior are customizable. + + *acp-snipMate* +snipMate's Trigger Completion ~ + +snipMate's trigger completion enables you to complete a snippet trigger +provided by snipMate plugin +(http://www.vim.org/scripts/script.php?script_id=2540) and expand it. + + +To enable auto-popup for this completion, add following function to +plugin/snipMate.vim: +> + fun! GetSnipsInCurrentScope() + let snips = {} + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + call extend(snips, get(s:snippets, scope, {}), 'keep') + call extend(snips, get(s:multi_snips, scope, {}), 'keep') + endfor + return snips + endf +< +And set |g:acp_behaviorSnipmateLength| option to 1. + +There is the restriction on this auto-popup, that the word before cursor must +consist only of uppercase characters. + + *acp-perl-omni* +Perl Omni-Completion ~ + +AutoComplPop supports perl-completion.vim +(http://www.vim.org/scripts/script.php?script_id=2852). + +To enable auto-popup for this completion, set |g:acp_behaviorPerlOmniLength| +option to 0 or more. + + +============================================================================== +COMMANDS *acp-commands* + + *:AcpEnable* +:AcpEnable + enables auto-popup. + + *:AcpDisable* +:AcpDisable + disables auto-popup. + + *:AcpLock* +:AcpLock + suspends auto-popup temporarily. + + For the purpose of avoiding interruption to another script, it is + recommended to insert this command and |:AcpUnlock| than |:AcpDisable| + and |:AcpEnable| . + + *:AcpUnlock* +:AcpUnlock + resumes auto-popup suspended by |:AcpLock| . + + +============================================================================== +OPTIONS *acp-options* + + *g:acp_enableAtStartup* > + let g:acp_enableAtStartup = 1 +< + If non-zero, auto-popup is enabled at startup. + + *g:acp_mappingDriven* > + let g:acp_mappingDriven = 0 +< + If non-zero, auto-popup is triggered by key mappings instead of + |CursorMovedI| event. This is useful to avoid auto-popup by moving + cursor in Insert mode. + + *g:acp_ignorecaseOption* > + let g:acp_ignorecaseOption = 1 +< + Value set to 'ignorecase' temporarily when auto-popup. + + *g:acp_completeOption* > + let g:acp_completeOption = '.,w,b,k' +< + Value set to 'complete' temporarily when auto-popup. + + *g:acp_completeoptPreview* > + let g:acp_completeoptPreview = 0 +< + If non-zero, "preview" is added to 'completeopt' when auto-popup. + + *g:acp_behaviorUserDefinedFunction* > + let g:acp_behaviorUserDefinedFunction = '' +< + |g:acp_behavior-completefunc| for user-defined completion. If empty, + this completion will be never attempted. + + *g:acp_behaviorUserDefinedMeets* > + let g:acp_behaviorUserDefinedMeets = '' +< + |g:acp_behavior-meets| for user-defined completion. If empty, this + completion will be never attempted. + + *g:acp_behaviorSnipmateLength* > + let g:acp_behaviorSnipmateLength = -1 +< + Pattern before the cursor, which are needed to attempt + snipMate-trigger completion. + + *g:acp_behaviorKeywordCommand* > + let g:acp_behaviorKeywordCommand = "\" +< + Command for keyword completion. This option is usually set "\" or + "\". + + *g:acp_behaviorKeywordLength* > + let g:acp_behaviorKeywordLength = 2 +< + Length of keyword characters before the cursor, which are needed to + attempt keyword completion. If negative value, this completion will be + never attempted. + + *g:acp_behaviorKeywordIgnores* > + let g:acp_behaviorKeywordIgnores = [] +< + List of string. If a word before the cursor matches to the front part + of one of them, keyword completion won't be attempted. + + E.g., when there are too many keywords beginning with "get" for the + completion and auto-popup by entering "g", "ge", or "get" causes + response degradation, set ["get"] to this option and avoid it. + + *g:acp_behaviorFileLength* > + let g:acp_behaviorFileLength = 0 +< + Length of filename characters before the cursor, which are needed to + attempt filename completion. If negative value, this completion will + be never attempted. + + *g:acp_behaviorRubyOmniMethodLength* > + let g:acp_behaviorRubyOmniMethodLength = 0 +< + Length of keyword characters before the cursor, which are needed to + attempt ruby omni-completion for methods. If negative value, this + completion will be never attempted. + + *g:acp_behaviorRubyOmniSymbolLength* > + let g:acp_behaviorRubyOmniSymbolLength = 1 +< + Length of keyword characters before the cursor, which are needed to + attempt ruby omni-completion for symbols. If negative value, this + completion will be never attempted. + + *g:acp_behaviorPythonOmniLength* > + let g:acp_behaviorPythonOmniLength = 0 +< + Length of keyword characters before the cursor, which are needed to + attempt python omni-completion. If negative value, this completion + will be never attempted. + + *g:acp_behaviorPerlOmniLength* > + let g:acp_behaviorPerlOmniLength = -1 +< + Length of keyword characters before the cursor, which are needed to + attempt perl omni-completion. If negative value, this completion will + be never attempted. + + See also: |acp-perl-omni| + + *g:acp_behaviorXmlOmniLength* > + let g:acp_behaviorXmlOmniLength = 0 +< + Length of keyword characters before the cursor, which are needed to + attempt XML omni-completion. If negative value, this completion will + be never attempted. + + *g:acp_behaviorHtmlOmniLength* > + let g:acp_behaviorHtmlOmniLength = 0 +< + Length of keyword characters before the cursor, which are needed to + attempt HTML omni-completion. If negative value, this completion will + be never attempted. + + *g:acp_behaviorCssOmniPropertyLength* > + let g:acp_behaviorCssOmniPropertyLength = 1 +< + Length of keyword characters before the cursor, which are needed to + attempt CSS omni-completion for properties. If negative value, this + completion will be never attempted. + + *g:acp_behaviorCssOmniValueLength* > + let g:acp_behaviorCssOmniValueLength = 0 +< + Length of keyword characters before the cursor, which are needed to + attempt CSS omni-completion for values. If negative value, this + completion will be never attempted. + + *g:acp_behavior* > + let g:acp_behavior = {} +< + This option is for advanced users. This setting overrides other + behavior options. This is a |Dictionary|. Each key corresponds to a + filetype. '*' is default. Each value is a list. These are attempted in + sequence until completion item is found. Each element is a + |Dictionary| which has following items: + + "command": *g:acp_behavior-command* + Command to be fed to open popup menu for completions. + + "completefunc": *g:acp_behavior-completefunc* + 'completefunc' will be set to this user-provided function during the + completion. Only makes sense when "command" is "". + + "meets": *g:acp_behavior-meets* + Name of the function which dicides whether or not to attempt this + completion. It will be attempted if this function returns non-zero. + This function takes a text before the cursor. + + "onPopupClose": *g:acp_behavior-onPopupClose* + Name of the function which is called when popup menu for this + completion is closed. Following completions will be suppressed if + this function returns zero. + + "repeat": *g:acp_behavior-repeat* + If non-zero, the last completion is automatically repeated. + + +============================================================================== +SPECIAL THANKS *acp-thanks* + +- Daniel Schierbeck +- Ingo Karkat + + +============================================================================== +CHANGELOG *acp-changelog* + +3.0: [TODO] + - From this version, L9 library (vimscript #3252) is required. + +2.14.1 + - Changed the way of auto-popup for avoiding an issue about filename + completion. + - Fixed a bug that popup menu was opened twice when auto-popup was done. + +2.14 + - Added the support for perl-completion.vim. + +2.13 + - Changed to sort snipMate's triggers. + - Fixed a bug that a wasted character was inserted after snipMate's trigger + completion. + +2.12.1 + - Changed to avoid a strange behavior with Microsoft IME. + +2.12 + - Added g:acp_behaviorKeywordIgnores option. + - Added g:acp_behaviorUserDefinedMeets option and removed + g:acp_behaviorUserDefinedPattern. + - Changed to do auto-popup only when a buffer is modified. + - Changed the structure of g:acp_behavior option. + - Changed to reflect a change of behavior options (named g:acp_behavior*) + any time it is done. + - Fixed a bug that completions after omni completions or snipMate's trigger + completion were never attempted when no candidate for the former + completions was found. + +2.11.1 + - Fixed a bug that a snipMate's trigger could not be expanded when it was + completed. + +2.11 + - Implemented experimental feature which is snipMate's trigger completion. + +2.10 + - Improved the response by changing not to attempt any completion when + keyword characters are entered after a word which has been found that it + has no completion candidate at the last attempt of completions. + - Improved the response by changing to close popup menu when was + pressed and the text before the cursor would not match with the pattern of + current behavior. + +2.9 + - Changed default behavior to support XML omni completion. + - Changed default value of g:acp_behaviorKeywordCommand option. + The option with "\" cause a problem which inserts a match without + when 'dictionary' has been set and keyword completion is done. + - Changed to show error message when incompatible with a installed vim. + +2.8.1 + - Fixed a bug which inserted a selected match to the next line when + auto-wrapping (enabled with 'formatoptions') was performed. + +2.8 + - Added g:acp_behaviorUserDefinedFunction option and + g:acp_behaviorUserDefinedPattern option for users who want to make custom + completion auto-popup. + - Fixed a bug that setting 'spell' on a new buffer made typing go crazy. + +2.7 + - Changed naming conventions for filenames, functions, commands, and options + and thus renamed them. + - Added g:acp_behaviorKeywordCommand option. If you prefer the previous + behavior for keyword completion, set this option "\". + - Changed default value of g:acp_ignorecaseOption option. + + The following were done by Ingo Karkat: + + - ENH: Added support for setting a user-provided 'completefunc' during the + completion, configurable via g:acp_behavior. + - BUG: When the configured completion is or , the command to + restore the original text (in on_popup_post()) must be reverted, too. + - BUG: When using a custom completion function () that also uses + an s:...() function name, the s:GetSidPrefix() function dynamically + determines the wrong SID. Now calling s:DetermineSidPrefix() once during + sourcing and caching the value in s:SID. + - BUG: Should not use custom defined completion mappings. Now + consistently using unmapped completion commands everywhere. (Beforehand, + s:PopupFeeder.feed() used mappings via feedkeys(..., 'm'), but + s:PopupFeeder.on_popup_post() did not due to its invocation via + :map-expr.) + +2.6: + - Improved the behavior of omni completion for HTML/XHTML. + +2.5: + - Added some options to customize behavior easily: + g:AutoComplPop_BehaviorKeywordLength + g:AutoComplPop_BehaviorFileLength + g:AutoComplPop_BehaviorRubyOmniMethodLength + g:AutoComplPop_BehaviorRubyOmniSymbolLength + g:AutoComplPop_BehaviorPythonOmniLength + g:AutoComplPop_BehaviorHtmlOmniLength + g:AutoComplPop_BehaviorCssOmniPropertyLength + g:AutoComplPop_BehaviorCssOmniValueLength + +2.4: + - Added g:AutoComplPop_MappingDriven option. + +2.3.1: + - Changed to set 'lazyredraw' while a popup menu is visible to avoid + flickering. + - Changed a behavior for CSS. + - Added support for GetLatestVimScripts. + +2.3: + - Added a behavior for Python to support omni completion. + - Added a behavior for CSS to support omni completion. + +2.2: + - Changed not to work when 'paste' option is set. + - Fixed AutoComplPopEnable command and AutoComplPopDisable command to + map/unmap "i" and "R". + +2.1: + - Fixed the problem caused by "." command in Normal mode. + - Changed to map "i" and "R" to feed completion command after starting + Insert mode. + - Avoided the problem caused by Windows IME. + +2.0: + - Changed to use CursorMovedI event to feed a completion command instead of + key mapping. Now the auto-popup is triggered by moving the cursor. + - Changed to feed completion command after starting Insert mode. + - Removed g:AutoComplPop_MapList option. + +1.7: + - Added behaviors for HTML/XHTML. Now supports the omni completion for + HTML/XHTML. + - Changed not to show expressions for CTRL-R =. + - Changed not to set 'nolazyredraw' while a popup menu is visible. + +1.6.1: + - Changed not to trigger the filename completion by a text which has + multi-byte characters. + +1.6: + - Redesigned g:AutoComplPop_Behavior option. + - Changed default value of g:AutoComplPop_CompleteOption option. + - Changed default value of g:AutoComplPop_MapList option. + +1.5: + - Implemented continuous-completion for the filename completion. And added + new option to g:AutoComplPop_Behavior. + +1.4: + - Fixed the bug that the auto-popup was not suspended in fuzzyfinder. + - Fixed the bug that an error has occurred with Ruby-omni-completion unless + Ruby interface. + +1.3: + - Supported Ruby-omni-completion by default. + - Supported filename completion by default. + - Added g:AutoComplPop_Behavior option. + - Added g:AutoComplPop_CompleteoptPreview option. + - Removed g:AutoComplPop_MinLength option. + - Removed g:AutoComplPop_MaxLength option. + - Removed g:AutoComplPop_PopupCmd option. + +1.2: + - Fixed bugs related to 'completeopt'. + +1.1: + - Added g:AutoComplPop_IgnoreCaseOption option. + - Added g:AutoComplPop_NotEnableAtStartup option. + - Removed g:AutoComplPop_LoadAndEnable option. +1.0: + - g:AutoComplPop_LoadAndEnable option for a startup activation is added. + - AutoComplPopLock command and AutoComplPopUnlock command are added to + suspend and resume. + - 'completeopt' and 'complete' options are changed temporarily while + completing by this script. + +0.4: + - The first match are selected when the popup menu is Opened. You can insert + the first match with CTRL-Y. + +0.3: + - Fixed the problem that the original text is not restored if 'longest' is + not set in 'completeopt'. Now the plugin works whether or not 'longest' is + set in 'completeopt', and also 'menuone'. + +0.2: + - When completion matches are not found, insert CTRL-E to stop completion. + - Clear the echo area. + - Fixed the problem in case of dividing words by symbols, popup menu is + not opened. + +0.1: + - First release. + + +============================================================================== +ABOUT *acp-about* *acp-contact* *acp-author* + +Author: Takeshi NISHIDA +Licence: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=1879 + http://bitbucket.org/ns9tks/vim-autocomplpop/ + +Bugs/Issues/Suggestions/Improvements ~ + +Please submit to http://bitbucket.org/ns9tks/vim-autocomplpop/issues/ . + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: + diff --git a/bundle/autocomplpop/plugin/acp.vim b/bundle/autocomplpop/plugin/acp.vim new file mode 100644 index 0000000..8138de8 --- /dev/null +++ b/bundle/autocomplpop/plugin/acp.vim @@ -0,0 +1,164 @@ +"============================================================================= +" Copyright (c) 2007-2009 Takeshi NISHIDA +" +" GetLatestVimScripts: 1879 1 :AutoInstall: AutoComplPop +"============================================================================= +" LOAD GUARD {{{1 + +try + if !l9#guardScriptLoading(expand(':p'), 702, 101, []) + finish + endif +catch /E117/ + echoerr '***** L9 library must be installed! *****' + finish +endtry + +" }}}1 +"============================================================================= +" FUNCTION: {{{1 + +" +function s:makeDefaultBehavior() + let behavs = { + \ '*' : [], + \ 'ruby' : [], + \ 'python' : [], + \ 'perl' : [], + \ 'xml' : [], + \ 'html' : [], + \ 'xhtml' : [], + \ 'css' : [], + \ } + "--------------------------------------------------------------------------- + if !empty(g:acp_behaviorUserDefinedFunction) && + \ !empty(g:acp_behaviorUserDefinedMeets) + for key in keys(behavs) + call add(behavs[key], { + \ 'command' : "\\", + \ 'completefunc' : g:acp_behaviorUserDefinedFunction, + \ 'meets' : g:acp_behaviorUserDefinedMeets, + \ 'repeat' : 0, + \ }) + endfor + endif + "--------------------------------------------------------------------------- + for key in keys(behavs) + call add(behavs[key], { + \ 'command' : "\\", + \ 'completefunc' : 'acp#completeSnipmate', + \ 'meets' : 'acp#meetsForSnipmate', + \ 'onPopupClose' : 'acp#onPopupCloseSnipmate', + \ 'repeat' : 0, + \ }) + endfor + "--------------------------------------------------------------------------- + for key in keys(behavs) + call add(behavs[key], { + \ 'command' : g:acp_behaviorKeywordCommand, + \ 'meets' : 'acp#meetsForKeyword', + \ 'repeat' : 0, + \ }) + endfor + "--------------------------------------------------------------------------- + for key in keys(behavs) + call add(behavs[key], { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForFile', + \ 'repeat' : 1, + \ }) + endfor + "--------------------------------------------------------------------------- + call add(behavs.ruby, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForRubyOmni', + \ 'repeat' : 0, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.python, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForPythonOmni', + \ 'repeat' : 0, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.perl, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForPerlOmni', + \ 'repeat' : 0, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.xml, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForXmlOmni', + \ 'repeat' : 1, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.html, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForHtmlOmni', + \ 'repeat' : 1, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.xhtml, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForHtmlOmni', + \ 'repeat' : 1, + \ }) + "--------------------------------------------------------------------------- + call add(behavs.css, { + \ 'command' : "\\", + \ 'meets' : 'acp#meetsForCssOmni', + \ 'repeat' : 0, + \ }) + "--------------------------------------------------------------------------- + return behavs +endfunction + +" }}}1 +"============================================================================= +" INITIALIZATION {{{1 + +"----------------------------------------------------------------------------- +call l9#defineVariableDefault('g:acp_enableAtStartup', 1) +call l9#defineVariableDefault('g:acp_mappingDriven', 0) +call l9#defineVariableDefault('g:acp_ignorecaseOption', 1) +call l9#defineVariableDefault('g:acp_completeOption', '.,w,b,k') +call l9#defineVariableDefault('g:acp_completeoptPreview', 0) +call l9#defineVariableDefault('g:acp_behaviorUserDefinedFunction', '') +call l9#defineVariableDefault('g:acp_behaviorUserDefinedMeets', '') +call l9#defineVariableDefault('g:acp_behaviorSnipmateLength', -1) +call l9#defineVariableDefault('g:acp_behaviorKeywordCommand', "\") +call l9#defineVariableDefault('g:acp_behaviorKeywordLength', 2) +call l9#defineVariableDefault('g:acp_behaviorKeywordIgnores', []) +call l9#defineVariableDefault('g:acp_behaviorFileLength', 0) +call l9#defineVariableDefault('g:acp_behaviorRubyOmniMethodLength', 0) +call l9#defineVariableDefault('g:acp_behaviorRubyOmniSymbolLength', 1) +call l9#defineVariableDefault('g:acp_behaviorPythonOmniLength', 0) +call l9#defineVariableDefault('g:acp_behaviorPerlOmniLength', -1) +call l9#defineVariableDefault('g:acp_behaviorXmlOmniLength', 0) +call l9#defineVariableDefault('g:acp_behaviorHtmlOmniLength', 0) +call l9#defineVariableDefault('g:acp_behaviorCssOmniPropertyLength', 1) +call l9#defineVariableDefault('g:acp_behaviorCssOmniValueLength', 0) +call l9#defineVariableDefault('g:acp_behavior', {}) +"----------------------------------------------------------------------------- +call extend(g:acp_behavior, s:makeDefaultBehavior(), 'keep') +"----------------------------------------------------------------------------- +command! -bar -narg=0 AcpEnable call acp#enable() +command! -bar -narg=0 AcpDisable call acp#disable() +command! -bar -narg=0 AcpLock call acp#lock() +command! -bar -narg=0 AcpUnlock call acp#unlock() +"----------------------------------------------------------------------------- +" legacy commands +command! -bar -narg=0 AutoComplPopEnable AcpEnable +command! -bar -narg=0 AutoComplPopDisable AcpDisable +command! -bar -narg=0 AutoComplPopLock AcpLock +command! -bar -narg=0 AutoComplPopUnlock AcpUnlock +"----------------------------------------------------------------------------- +if g:acp_enableAtStartup + AcpEnable +endif +"----------------------------------------------------------------------------- + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/bundle/l9/.hg_archival.txt b/bundle/l9/.hg_archival.txt new file mode 100644 index 0000000..2aa4d3f --- /dev/null +++ b/bundle/l9/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: 4d5305d0e643bf0b1deca1e9270d2db044d07b2d +node: 3bb534a720fa762aa01d2df2d5d41bd3c4122169 +branch: default +latesttag: 1.1 +latesttagdistance: 2 diff --git a/bundle/l9/.hgtags b/bundle/l9/.hgtags new file mode 100644 index 0000000..2d251b1 --- /dev/null +++ b/bundle/l9/.hgtags @@ -0,0 +1,3 @@ +f6420a42fc69dd7fc08aa5426c4b3fb10e78020d 1.0 +f6f3e9bae8770abb41259d42ab65721f6915fe22 1.0.1 +c3f242518bd4b8131a2c277a7f8c492b56375dff 1.1 diff --git a/bundle/l9/autoload/l9.vim b/bundle/l9/autoload/l9.vim new file mode 100644 index 0000000..b6a0ae7 --- /dev/null +++ b/bundle/l9/autoload/l9.vim @@ -0,0 +1,570 @@ +"============================================================================= +" Copyright (c) 2009-2010 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if exists('g:loaded_autoload_l9') + finish +endif +let g:loaded_autoload_l9 = 1 + +" }}}1 +"============================================================================= +" COMPATIBILITY TEST {{{1 + +" +let s:L9_VERSION_CURRENT = 101 +let s:L9_VERSION_PASSABLE = 101 + +" returns true if given version is compatible. +function l9#isCompatible(ver) + return +endfunction + +let s:VERSION_FACTOR = str2float('0.01') + +" returns false if the caller script should finish. +" a:vimVersion: if 0, don't check vim version +" a:l9Version: same rule as v:version +function l9#guardScriptLoading(path, vimVersion, l9Version, exprs) + let loadedVarName = 'g:loaded_' . substitute(a:path, '\W', '_', 'g') + if exists(loadedVarName) + return 0 + elseif a:vimVersion > 0 && a:vimVersion > v:version + echoerr a:path . ' requires Vim version ' . string(a:vimVersion * s:VERSION_FACTOR) + return 0 + elseif a:l9Version > 0 && (a:l9Version > s:L9_VERSION_CURRENT || + \ a:l9Version < s:L9_VERSION_PASSABLE) + echoerr a:path . ' requires L9 library version ' . string(a:l9Version * s:VERSION_FACTOR) + return 0 + endif + for expr in a:exprs + if !eval(expr) + echoerr a:path . ' requires: ' . expr + return 0 + endif + endfor + let {loadedVarName} = 1 + return 1 +endfunction + +" +function l9#getVersion() + return s:L9_VERSION_CURRENT +endfunction + +" }}}1 +"============================================================================= +" LIST {{{1 + +" Removes duplicates (unstable) +" This function doesn't change the list of argument. +function l9#unique(items) + let sorted = sort(a:items) + if len(sorted) < 2 + return sorted + endif + let last = remove(sorted, 0) + let result = [last] + for item in sorted + if item != last + call add(result, item) + let last = item + endif + endfor + return result +endfunction + +" Removes duplicates (stable) +" This function doesn't change the list of argument. +function l9#uniqueStably(items) + let result = [] + for item in a:items + if count(result, item, &ignorecase) == 0 + call add(result, item) + endif + endfor + return result +endfunction + +" [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ] +" This function doesn't change the list of argument. +function l9#concat(items) + let result = [] + for l in a:items + let result += l + endfor + return result +endfunction + +" [ [0,1,2], [3,4], [5,6,7,8] ] -> [ [0,3,5],[1,4,6] ] +" This function doesn't change the list of argument. +function l9#zip(items) + let result = [] + for i in range(min(map(copy(a:items), 'len(v:val)'))) + call add(result, map(copy(a:items), 'v:val[i]')) + endfor + return result +endfunction + +" filter() with the maximum number of items +" This function doesn't change the list of argument. +function l9#filterWithLimit(items, expr, limit) + if a:limit <= 0 + return filter(copy(a:items), a:expr) + endif + let result = [] + let stride = a:limit * 3 / 2 " x1.5 + for i in range(0, len(a:items) - 1, stride) + let result += filter(a:items[i : i + stride - 1], a:expr) + if len(result) >= a:limit + return remove(result, 0, a:limit - 1) + endif + endfor + return result +endfunction + +" Removes if a:expr is evaluated as non-zero and returns removed items. +" This function change the list of argument. +function l9#removeIf(items, expr) + let removed = filter(copy(a:items), a:expr) + call filter(a:items, '!( ' . a:expr . ')') + return removed +endfunction + +" }}}1 +"============================================================================= +" NUMERIC {{{1 + +" }}}1 +"============================================================================= +" STRING {{{1 + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function l9#snipHead(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + return a:mask . a:str[-a:len + len(a:mask):] +endfunction + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function l9#snipTail(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + return a:str[:a:len - 1 - len(a:mask)] . a:mask +endfunction + +" Snips a:str and add a:mask if the length of a:str is more than a:len +function l9#snipMid(str, len, mask) + if a:len >= len(a:str) + return a:str + elseif a:len <= len(a:mask) + return a:mask + endif + let len_head = (a:len - len(a:mask)) / 2 + let len_tail = a:len - len(a:mask) - len_head + return (len_head > 0 ? a:str[: len_head - 1] : '') . a:mask . + \ (len_tail > 0 ? a:str[-len_tail :] : '') +endfunction + +" +function l9#hash224(str) + let a = 0x00000800 " shift 11 bit (if unsigned) + let b = 0x001fffff " extract 11 bit (if unsigned) + let nHash = 7 + let hashes = repeat([0], nHash) + for i in range(len(a:str)) + let iHash = i % nHash + let hashes[iHash] = hashes[iHash] * a + hashes[iHash] / b + let hashes[iHash] += char2nr(a:str[i]) + endfor + return join(map(hashes, 'printf("%08x", v:val)'), '') +endfunction + +" wildcard -> regexp +function l9#convertWildcardToRegexp(expr) + let re = escape(a:expr, '\') + for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ] + let re = substitute(re, pat, sub, 'g') + endfor + return '\V' . re +endfunction + +" }}}1 +"============================================================================= +" LINES {{{1 + +" Removes from the line matching with a:begin first to the line matching with +" a:end next and returns removed lines. +" If matching range is not found, returns [] +function l9#removeLinesBetween(lines, begin, end) + for i in range(len(a:lines) - 1) + if a:lines[i] =~ a:begin + break + endif + endfor + for j in range(i + 1, len(a:lines) - 1) + if a:lines[j] =~ a:end + let g:l0 += [a:lines[i : j]] + return remove(a:lines, i, j) + endif + endfor + return [] +endfunction + +" }}}1 +"============================================================================= +" PATH {{{1 + +" returns the path separator charactor. +function l9#getPathSeparator() + return (!&shellslash && (has('win32') || has('win64')) ? '\' : '/') +endfunction + +" [ 'a', 'b/', '/c' ] -> 'a/b/c' +function l9#concatPaths(paths) + let result = '' + for p in a:paths + if empty(p) + continue + elseif empty(result) + let result = p + else + let result = substitute(result, '[/\\]$', '', '') . l9#getPathSeparator() + \ . substitute(p, '^[/\\]', '', '') + endif + endfor + return result +endfunction + +" path: '/a/b/c/d', dir: '/a/b' => 'c/d' +function l9#modifyPathRelativeToDir(path, dir) + let pathFull = fnamemodify(a:path, ':p') + let dirFull = fnamemodify(a:dir, ':p') + if len(pathFull) < len(dirFull) || pathFull[:len(dirFull) - 1] !=# dirFull + return pathFull + endif + return pathFull[len(dirFull):] +endfunction + +" }}}1 +"============================================================================= +" FILE {{{1 + +" Almost same as readfile(). +function l9#readFile(...) + let args = copy(a:000) + let args[0] = expand(args[0]) + try + return call('readfile', args) + catch + endtry + return [] +endfunction + +" Almost same as writefile(). +function l9#writeFile(...) + let args = copy(a:000) + let args[1] = expand(args[1]) + let dir = fnamemodify(args[1], ':h') + try + if !isdirectory(dir) + call mkdir(dir, 'p') + endif + return call('writefile', args) + catch + endtry + return -1 " -1 is error code. +endfunction + +" }}}1 +"============================================================================= +" BUFFER {{{1 + +" :wall/:wall! wrapper. Useful for writing readonly buffers. +function l9#writeAll() + try + silent update " NOTE: avoiding a problem with a buftype=acwrite buffer. + silent wall + catch /^Vim/ " E45, E505 + if l9#inputHl('Question', v:exception . "\nWrite readonly files? (Y/N) : ", 'Y') ==? 'y' + redraw + :wall! + endif + endtry +endfunction + +" Loads given files with :edit command +function l9#loadFilesToBuffers(files) + for file in filter(copy(a:files), '!bufloaded(v:val)') + execute 'edit ' . fnameescape(file) + if !exists('bufNrFirst') + let bufNrFirst = bufnr('%') + endif + endfor + if exists('bufNrFirst') + execute bufNrFirst . 'buffer' + endif +endfunction + +" Deletes all buffers except given files with :bdelete command +function l9#deleteAllBuffersExcept(files) + let bufNrExcepts = map(copy(a:files), 'bufnr("^" . v:val . "$")') + for bufNr in filter(range(1, bufnr('$')), 'bufloaded(v:val)') + if count(bufNrExcepts, bufNr) == 0 + execute bufNr . 'bdelete' + endif + endfor +endfunction + +" }}}1 +"============================================================================= +" WINDOW {{{1 + +" move current window to next tabpage. +function l9#shiftWinNextTabpage() + if tabpagenr('$') < 2 + return + endif + let bufnr = bufnr('%') + tabnext + execute bufnr . 'sbuffer' + tabprevious + if winnr('$') > 1 + close + tabnext + else + close " if tabpage is closed, next tabpage will become current + endif +endfunction + +" move current window to previous tabpage. +function l9#shiftWinPrevTabpage() + if tabpagenr('$') < 2 + return + endif + let bufnr = bufnr('%') + tabprevious + execute bufnr . 'sbuffer' + tabnext + close + tabprevious +endfunction + +" move to a window containing specified buffer. +" returns 0 if the buffer is not found. +function l9#moveToBufferWindowInCurrentTabpage(bufNr) + if bufnr('%') == a:bufNr + return 1 + elseif count(tabpagebuflist(), a:bufNr) == 0 + return 0 + endif + execute bufwinnr(a:bufNr) . 'wincmd w' + return 1 +endfunction + +" returns 0 if the buffer is not found. +function s:moveToOtherTabpageOpeningBuffer(bufNr) + for tabNr in range(1, tabpagenr('$')) + if tabNr != tabpagenr() && count(tabpagebuflist(tabNr), a:bufNr) > 0 + execute 'tabnext ' . tabNr + return 1 + endif + endfor + return 0 +endfunction + +" move to a window containing specified buffer. +" returns 0 if the buffer is not found. +function l9#moveToBufferWindowInOtherTabpage(bufNr) + if !s:moveToOtherTabpageOpeningBuffer(a:bufNr) + return 0 + endif + return l9#moveToBufferWindowInCurrentTabpage(a:bufNr) +endfunction + +" }}}1 +"============================================================================= +" COMMAND LINE {{{1 + +" echo/echomsg with highlighting. +function l9#echoHl(hl, msg, prefix, addingHistory) + let echoCmd = (a:addingHistory ? 'echomsg' : 'echo') + execute "echohl " . a:hl + try + for l in (type(a:msg) == type([]) ? a:msg : split(a:msg, "\n")) + execute echoCmd . ' a:prefix . l' + endfor + finally + echohl None + endtry +endfunction + +" input() with highlighting. +" This function can take list as {completion} argument. +function l9#inputHl(hl, ...) + execute "echohl " . a:hl + try + let args = copy(a:000) + if len(args) > 2 && type(args[2]) == type([]) + let s:candidatesForInputHl = args[2] + let args[2] = 'custom,l9#completeForInputHl' + endif + let s = call('input', args) + unlet! s:candidatesForInputHl + finally + echohl None + endtry + redraw " needed to show following echo to next line. + return s +endfunction + +" only called by l9#inputHl() for completion. +function l9#completeForInputHl(lead, line, pos) + return join(s:candidatesForInputHl, "\n") +endfunction + +" }}}1 +"============================================================================= +" VISUAL MODE {{{1 + +" returns last selected text in Visual mode. +function l9#getSelectedText() + let reg_ = [@", getregtype('"')] + let regA = [@a, getregtype('a')] + if mode() =~# "[vV\]" + silent normal! "aygv + else + let pos = getpos('.') + silent normal! gv"ay + call setpos('.', pos) + endif + let text = @a + call setreg('"', reg_[0], reg_[1]) + call setreg('a', regA[0], regA[1]) + return text +endfunction + + +" }}}1 +"============================================================================= +" EVAL {{{1 + +" loads given text as Vim script with :source command +function l9#loadScript(text) + let lines = (type(a:text) == type([]) ? a:text : split(a:text, "\n")) + let fname = tempname() + call writefile(lines, fname) + source `=fname` + call delete(fname) +endfunction + + +" }}}1 +"============================================================================= +" VARIABLES {{{1 + +" +function l9#defineVariableDefault(name, default) + if !exists(a:name) + let {a:name} = a:default + endif +endfunction + +" }}}1 +"============================================================================= +" GREP {{{1 + +" Execute :vimgrep and opens the quickfix window if matches are found. +" +" a:pattern: search pattern. If ommitted, last search pattern (@/) is used. +" a:files: List of files +function l9#grepFiles(pattern, files) + let target = join(map(a:files, 'escape(v:val, " ")'), ' ') + let pattern = (a:pattern[0] ==# '/' ? a:pattern[1:] : a:pattern) + let pattern = (empty(pattern) ? @/ : pattern) + try + execute printf('vimgrep/%s/j %s', pattern, target) + catch /^Vim/ + call setqflist([]) + endtry + call l9#quickfix#sort() + call l9#quickfix#openIfNotEmpty(1, 0) +endfunction + +" Execute :vimgrep for buffers using l9#grepFiles() +" See also: :L9GrepBuffer :L9GrepBufferAll +function l9#grepBuffers(pattern, bufNrs) + let files = map(filter(a:bufNrs, 'bufloaded(v:val)'), 'bufname(v:val)') + call l9#grepFiles(a:pattern, files) +endfunction + +" }}}1 +"============================================================================= +" SIGN {{{1 + +" Highlights lines using :sign define and :sign place. +" +" a:linehl, a:text, a:texthl: See |signs|. Ignored if empty string. +" a:locations: List of [{buffer number}, {line number}] for highlighting +function l9#placeSign(linehl, text, texthl, locations) + let argLinehl = (empty(a:linehl) ? '' : 'linehl=' . a:linehl) + let argText = (empty(a:text) ? '' : 'text=' . a:text) + let argTexthl = (empty(a:texthl) ? '' : 'texthl=' . a:texthl) + let name = 'l9--' . a:linehl . '--' . a:text . '--' . a:texthl + execute printf('sign define %s linehl=%s text=%s texthl=%s', + \ name, a:linehl, a:text, a:texthl) + for [bufNr, lnum] in a:locations + execute printf('sign place 1 line=%d name=%s buffer=%d', lnum, name, bufNr) + endfor +endfunction + +" }}}1 +"============================================================================= +" NOTIFY EXTERNALLY {{{1 + +" Notify a message using an external program. +" Currently supports Balloonly, Screen, and Tmux. +function l9#notifyExternally(msg) + return l9#notifyBalloonly(a:msg) + \ || l9#notifyScreen(a:msg) + \ || l9#notifyTmux(a:msg) +endfunction + +" +function l9#notifyBalloonly(msg) + if !(has('win32') || has('win64')) || !executable(g:l9_balloonly) + return 0 + endif + execute 'silent !start ' . shellescape(g:l9_balloonly) . ' 4000 "l9" ' . shellescape(a:msg) + return 1 +endfunction + +" +function l9#notifyScreen(msg) + if !has('unix') || has('gui_running') || $WINDOW !~ '\d' || !executable('screen') + return 0 + endif + call system('screen -X wall ' . shellescape('l9: ' . a:msg)) + return 1 +endfunction + +" +function l9#notifyTmux(msg) + if !has('unix') || has('gui_running') || empty($TMUX) || !executable('tmux') + return 0 + endif + call system('tmux display-message ' . shellescape('l9: ' . a:msg)) + return 1 +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: diff --git a/bundle/l9/autoload/l9/async.py b/bundle/l9/autoload/l9/async.py new file mode 100644 index 0000000..eeb0cc3 --- /dev/null +++ b/bundle/l9/autoload/l9/async.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +from __future__ import with_statement +import vim +import os +import subprocess +import threading +import Queue + + +class Asyncer: + + def __init__(self): + self._workers = {} + + def execute(self, var_key, var_command, var_cwd, var_input, var_appends): + key = vim.eval(var_key) + command = vim.eval(var_command) + cwd = vim.eval(var_cwd) + input = vim.eval(var_input) + appends = vim.eval(var_appends) + if key not in self._workers: + self._workers[key] = Worker() + self._workers[key].start() + self._workers[key].put(Executor(command, cwd, input, appends)) + + def print_output(self, var_key): + key = vim.eval(var_key) + if key not in self._workers: + return + for l in self._workers[key].copy_outputs(): + print l, + + def print_worker_keys(self): + for k in self._workers.keys(): + print k + + def print_active_worker_keys(self): + for k in self._workers.keys(): + print k + + +class Worker(threading.Thread): + + def __init__(self): + threading.Thread.__init__(self) + self._queue = Queue.Queue() + self._lines = [] + self._lock = threading.Lock() + + def run(self): + while True: + self._queue.get().execute(self) + self._queue.task_done() + + def put(self, executor): + self._queue.put(executor) + + def clear_outputs(self): + with self._lock: + self._lines = [] + + def record_output(self, line): + with self._lock: + self._lines.append(line) + + def copy_outputs(self): + with self._lock: + return self._lines[:] + + +class Executor: + + def __init__(self, command, cwd, input, appends): + self._command = command + self._cwd = cwd + self._input = input + self._appends = appends + + def execute(self, worker): + if not self._appends: + worker.clear_outputs() + os.chdir(self._cwd) + p = subprocess.Popen(self._command, shell=True, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + p.stdin.write(self._input) + line = p.stdout.readline() + while line: + worker.record_output(line) + line = p.stdout.readline() + + diff --git a/bundle/l9/autoload/l9/async.vim b/bundle/l9/autoload/l9/async.vim new file mode 100644 index 0000000..fa66e9f --- /dev/null +++ b/bundle/l9/autoload/l9/async.vim @@ -0,0 +1,67 @@ +"============================================================================= +" Copyright (C) 2009-2010 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 0, 0, ['has("python")']) + finish +endif + +" }}}1 +"============================================================================= +" ASYNC EXECUTE {{{1 + +" +function s:checkKey(key) + if a:key =~ '\n' || a:key !~ '\S' + throw "Asyncer: Invalid key: " . a:key + endif +endfunction + +" +function l9#async#execute(key, cmd, cwd, input, appends) + call s:checkKey(a:key) + python asyncer.execute('a:key', 'a:cmd', 'a:cwd', 'a:input', 'a:appends') +endfunction + +" +function l9#async#read(key) + call s:checkKey(a:key) + redir => result + silent python asyncer.print_output('a:key') + redir END + " NOTE: "\n" is somehow inserted by redir. + return (result[0] ==# "\n" ? result[1:] : result) +endfunction + +" +function l9#async#listWorkers() + redir => result + silent python asyncer.print_worker_keys() + redir END + return split(result, "\n") +endfunction + +" +function l9#async#listActiveWorkers() + redir => result + silent python asyncer.print_active_worker_keys() + redir END + return split(result, "\n") +endfunction + +" }}}1 +"============================================================================= +" INITIALIZATION {{{1 + +let s:ASYNC_PY_PATH = fnamemodify(expand(':p:h'), ':p') . 'async.py' + +pyfile `=s:ASYNC_PY_PATH` +python asyncer = Asyncer() + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + + diff --git a/bundle/l9/autoload/l9/quickfix.vim b/bundle/l9/autoload/l9/quickfix.vim new file mode 100644 index 0000000..1758b39 --- /dev/null +++ b/bundle/l9/autoload/l9/quickfix.vim @@ -0,0 +1,107 @@ +"============================================================================= +" Copyright (C) 2009-2010 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 0, 0, []) + finish +endif + +" }}}1 +"============================================================================= +" QUICKFIX {{{1 + +" Returns non-zero if quickfix window is opened. +function l9#quickfix#isWindowOpened() + return count(map(range(1, winnr('$')), 'getwinvar(v:val, "&buftype")'), 'quickfix') > 0 +endfunction + +" Opens quickfix window if quickfix is not empty, and echo the number of errors. +" +" a:onlyRecognized: if non-zero, opens only if quickfix has recognized errors. +" a:holdCursor: if non-zero, the cursor won't move to quickfix window. +function l9#quickfix#openIfNotEmpty(onlyRecognized, holdCursor) + let numErrors = len(filter(getqflist(), 'v:val.valid')) + let numOthers = len(getqflist()) - numErrors + if numErrors > 0 || (!a:onlyRecognized && numOthers > 0) + copen + if a:holdCursor + wincmd p + endif + else + cclose + endif + redraw + if numOthers > 0 + echo printf('Quickfix: %d(+%d)', numErrors, numOthers) + else + echo printf('Quickfix: %d', numErrors) + endif +endfunction + +" Toggles Quickfix window +function l9#quickfix#toggleWindow() + if l9#quickfix#isWindowOpened() + cclose + else + call l9#quickfix#openIfNotEmpty(0, 0) + endif +endfunction + +" Creates quickfix list form given lines and opens the quickfix window if +" errors exists. +" +" a:lines: +" a:jump: if non-zero, jump to the first error. +function l9#quickfix#setMakeResult(lines) + cexpr a:lines + call l9#quickfix#openIfNotEmpty(0, 1) +endfunction + +" Compares quickfix entries for sorting. +function l9#quickfix#compareEntries(e0, e1) + if a:e0.bufnr != a:e1.bufnr + let i0 = bufname(a:e0.bufnr) + let i1 = bufname(a:e1.bufnr) + elseif a:e0.lnum != a:e1.lnum + let i0 = a:e0.lnum + let i1 = a:e1.lnum + elseif a:e0.col != a:e1.col + let i0 = a:e0.col + let i1 = a:e1.col + else + return 0 + endif + return (i0 > i1 ? +1 : -1) +endfunction + +" Sorts quickfix +function l9#quickfix#sort() + call setqflist(sort(getqflist(), 'l9#quickfix#compareEntries'), 'r') +endfunction + +" Highlights Quickfix lines by :sign. +" Inspired by errormarker plugin. +" +" You can customize the highlighting via L9ErrorLine and L9WarningLine +" highlight groups. +function l9#quickfix#placeSign() + let warnings = [] + let errors = [] + for e in filter(getqflist(), 'v:val.valid') + let warning = (e.type ==? 'w' || e.text =~? '^\s*warning:') + call add((warning ? warnings : errors), [e.bufnr, e.lnum]) + endfor + sign unplace * + call l9#placeSign('L9WarningLine', '>>', '', warnings) + call l9#placeSign('L9ErrorLine', '>>', '', errors) +endfunction + +highlight default L9ErrorLine ctermfg=white ctermbg=52 guibg=#5F0000 +highlight default L9WarningLine ctermfg=white ctermbg=17 guibg=#00005F + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/bundle/l9/autoload/l9/tempbuffer.vim b/bundle/l9/autoload/l9/tempbuffer.vim new file mode 100644 index 0000000..6f11a78 --- /dev/null +++ b/bundle/l9/autoload/l9/tempbuffer.vim @@ -0,0 +1,112 @@ +"============================================================================= +" Copyright (C) 2009-2010 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 0, 0, []) + finish +endif + +" }}}1 +"============================================================================= +" TEMPORARY BUFFER {{{1 + +" each key is a buffer name. +let s:dataMap = {} + +" +function s:onBufDelete(bufname) + if exists('s:dataMap[a:bufname].listener.onClose') + call s:dataMap[a:bufname].listener.onClose(s:dataMap[a:bufname].written) + endif + if bufnr('%') == s:dataMap[a:bufname].bufNr && winnr('#') != 0 + " if winnr('#') returns 0, "wincmd p" causes ringing the bell. + wincmd p + endif +endfunction + +" +function s:onBufWriteCmd(bufname) + if !exists('s:dataMap[a:bufname].listener.onWrite') || + \ s:dataMap[a:bufname].listener.onWrite(getline(1, '$')) + setlocal nomodified + let s:dataMap[a:bufname].written = 1 + call l9#tempbuffer#close(a:bufname) + else + endif +endfunction + +" a:bufname: +" a:height: Window height. If 0, default height is used. +" If less than 0, the window becomes full-screen. +" a:listener: +" a:listener.onClose(written) +function l9#tempbuffer#openScratch(bufname, filetype, lines, topleft, vertical, height, listener) + let openCmdPrefix = (a:topleft ? 'topleft ' : '') + \ . (a:vertical ? 'vertical ' : '') + \ . (a:height > 0 ? a:height : '') + if !exists('s:dataMap[a:bufname]') || !bufexists(s:dataMap[a:bufname].bufNr) + execute openCmdPrefix . 'new' + else + call l9#tempbuffer#close(a:bufname) + execute openCmdPrefix . 'split' + execute 'silent ' . s:dataMap[a:bufname].bufNr . 'buffer' + endif + if a:height < 0 + only + endif + setlocal buflisted noswapfile bufhidden=delete modifiable noreadonly buftype=nofile + let &l:filetype = a:filetype + silent file `=a:bufname` + call setline(1, a:lines) + setlocal nomodified + augroup L9TempBuffer + autocmd! * + execute printf('autocmd BufDelete call s:onBufDelete (%s)', string(a:bufname)) + execute printf('autocmd BufWriteCmd nested call s:onBufWriteCmd(%s)', string(a:bufname)) + augroup END + let s:dataMap[a:bufname] = { + \ 'bufNr': bufnr('%'), + \ 'written': 0, + \ 'listener': a:listener, + \ } +endfunction + +" +function l9#tempbuffer#openReadOnly(bufname, filetype, lines, topleft, vertical, height, listener) + call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener) + setlocal nomodifiable readonly +endfunction + +" a:listener: +" a:listener.onClose(written) +" a:listener.onWrite(lines) +function l9#tempbuffer#openWritable(bufname, filetype, lines, topleft, vertical, height, listener) + call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener) + setlocal buftype=acwrite +endfunction + +" makes specified temp buffer current. +function l9#tempbuffer#moveTo(bufname) + return l9#moveToBufferWindowInCurrentTabpage(s:dataMap[a:bufname].bufNr) || + \ l9#moveToBufferWindowInOtherTabpage(s:dataMap[a:bufname].bufNr) +endfunction + +" +function l9#tempbuffer#close(bufname) + if !l9#tempbuffer#isOpen(a:bufname) + return + endif + execute printf('%dbdelete!', s:dataMap[a:bufname].bufNr) +endfunction + +" +function l9#tempbuffer#isOpen(bufname) + return exists('s:dataMap[a:bufname]') && bufloaded(s:dataMap[a:bufname].bufNr) +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/bundle/l9/autoload/l9/tempvariables.vim b/bundle/l9/autoload/l9/tempvariables.vim new file mode 100644 index 0000000..ee847ee --- /dev/null +++ b/bundle/l9/autoload/l9/tempvariables.vim @@ -0,0 +1,60 @@ +"============================================================================= +" Copyright (C) 2010 Takeshi NISHIDA +" +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 0, 0, []) + finish +endif + +" }}}1 +"============================================================================= +" TEMPORARY VARIABLES {{{1 + +" +let s:origMap = {} + +" set temporary variables +function l9#tempvariables#set(group, name, value) + if !exists('s:origMap[a:group]') + let s:origMap[a:group] = {} + endif + if !exists('s:origMap[a:group][a:name]') + let s:origMap[a:group][a:name] = eval(a:name) + endif + execute 'let ' . a:name . ' = a:value' +endfunction + +" set temporary variables +function l9#tempvariables#setList(group, variables) + for [name, value] in a:variables + call l9#tempvariables#set(a:group, name, value) + unlet value " to avoid E706 + endfor +endfunction + +" get temporary variables +function l9#tempvariables#getList(group) + if !exists('s:origMap[a:group]') + return [] + endif + return map(keys(s:origMap[a:group]), '[v:val, eval(v:val)]') +endfunction + +" restore original variables and clean up. +function l9#tempvariables#end(group) + if !exists('s:origMap[a:group]') + return + endif + for [name, value] in items(s:origMap[a:group]) + execute 'let ' . name . ' = value' + unlet value " to avoid E706 + endfor + unlet s:origMap[a:group] +endfunction + +" }}}1 +"============================================================================= +" vim: set fdm=marker: + diff --git a/bundle/l9/doc/l9.jax b/bundle/l9/doc/l9.jax new file mode 100644 index 0000000..c84d45f --- /dev/null +++ b/bundle/l9/doc/l9.jax @@ -0,0 +1,55 @@ +*l9.txt* Vimスクリプトライブラリ + + Copyright (c) 2009-2010 Takeshi NISHIDA + +l9 *l9* + +概要 |l9-introduction| +インストール |l9-installation| +使い方 |l9-usage| +CHANGELOG |l9-changelog| +あばうと |l9-about| + +============================================================================== +概要 *l9-introduction* + +l9はVimスクリプトの関数やコマンドを提供するライブラリです。 + + +============================================================================== + インストール *l9-installation* + +ZIPファイルをランタイムディレクトリに展開します。 + +以下のようにファイルが配置されるはずです。 +> + /plugin/l9.vim + /doc/l9.txt + ... +< +もしランタイムディレクトリが多数のプラグインでごちゃごちゃになるのが嫌なら、各 +プラグインを個別のディレクトリに配置し、そのディレクトリのパスを 'runtimepath' +に追加してください。アンインストールも楽になります。 + +その後、ヘルプを有効にするためにタグファイルを更新してください。詳しくは +|add-local-help|を参照してください。 + +============================================================================== +使い方 *l9-usage* + +ソースコードを参照してください。 + +============================================================================== +あばうと *l9-about* *l9-contact* *l9-author* + +作者: Takeshi NISHIDA +ライセンス: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=3252 + http://bitbucket.org/ns9tks/vim-l9/ + +バグや要望など ~ + +こちらへどうぞ: http://bitbucket.org/ns9tks/vim-l9/issues/ + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/bundle/l9/doc/l9.txt b/bundle/l9/doc/l9.txt new file mode 100644 index 0000000..c2906e6 --- /dev/null +++ b/bundle/l9/doc/l9.txt @@ -0,0 +1,73 @@ +*l9.txt* Vim-script library + + Copyright (c) 2009-2010 Takeshi NISHIDA + +l9 *l9* + +INTRODUCTION |l9-introduction| +INSTALLATION |l9-installation| +USAGE |l9-usage| +CHANGELOG |l9-changelog| +ABOUT |l9-about| + +============================================================================== +INTRODUCTION *l9-introduction* + +l9 is a Vim-script library, which provides some utility functions and commands +for programming in Vim. + +============================================================================== + INSTALLATION *l9-installation* + +Put all files into your runtime directory. If you have the zip file, extract +it to your runtime directory. + +You should place the files as follows: +> + /plugin/l9.vim + /doc/l9.txt + ... +< +If you are disgusted to make your runtime directory confused with a lot of +plugins, put each of the plugins into a directory individually and just add +the directory path to 'runtimepath'. It's easy to uninstall plugins. + +Then update your help tags files to enable help for this plugin. See +|add-local-help| for details. + +============================================================================== +USAGE *l9-usage* + +See source code. + +============================================================================== +CHANGELOG *l9-changelog* + +1.1: + - Added l9#zip() + - Added l9#tempvariables#getList() + - Changed l9#guardScriptLoading() + - Removed l9#tempvariables#swap() + +1.0.1: + - Fixed a bug that floating point numbers weren't evaluated correctly and + caused errors on some non-English locales. + +1.0: + - First release. + + +============================================================================== +ABOUT *l9-about* *l9-contact* *l9-author* + +Author: Takeshi NISHIDA +Licence: MIT Licence +URL: http://www.vim.org/scripts/script.php?script_id=3252 + http://bitbucket.org/ns9tks/vim-l9/ + +Bugs/Issues/Suggestions/Improvements ~ + +Please submit to http://bitbucket.org/ns9tks/vim-l9/issues/ . + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/bundle/l9/plugin/l9.vim b/bundle/l9/plugin/l9.vim new file mode 100644 index 0000000..03613e4 --- /dev/null +++ b/bundle/l9/plugin/l9.vim @@ -0,0 +1,108 @@ +"============================================================================= +" Copyright (C) 2009-2010 Takeshi NISHIDA +" +" GetLatestVimScripts: 3252 1 :AutoInstall: L9 +"============================================================================= +" LOAD GUARD {{{1 + +if !l9#guardScriptLoading(expand(':p'), 702, 0, []) + finish +endif + +" }}}1 +"============================================================================= +" OPTIONS: {{{1 + +call l9#defineVariableDefault('g:l9_balloonly', 'balloonly.exe') + +" }}}1 +"============================================================================= +" ASSERTION: {{{1 + +" This command has effect only if $L9_DEBUG is non-zero. +" Used as follows: +" L9Assert a:i > 0 +" This command can't interpret script-local variables directly. +" NG: L9Assert s:a == 1 +" OK: execute 'L9Assert ' . s:a . ' == 1' +" +if $L9_DEBUG + command -nargs=* L9Assert call eval(() ? 0 : s:handleFailedAssersion()) + + function s:handleFailedAssersion(expr) + echoerr '[L9Assert] Assersion failure: ' . a:expr + if input('[L9Assert] Continue? (Y/N) ', 'Y') !=? 'Y' + throw 'L9Assert ' . a:expr + endif + endfunction + +else + command -nargs=* L9Assert : +endif + +" }}}1 +"============================================================================= +" TIMER: {{{1 + +" These commands have effect only if $L9_TIMER is non-zero. +" Used as follows: +" L9Timer foo +" ... (1) +" L9Timer bar +" ... (2) +" L9TimerStop +" ... +" L9TimerDump <- shows each elapsed time of (1) and (2) +" +if $L9_TIMER + command -nargs=1 L9Timer call s:timerBegin() + command -nargs=0 L9TimerStop call s:timerStop() + command -nargs=0 L9TimerDump call s:timerDump() + + let s:timerData = [] + let s:timerTagMaxLen = 0 + + function s:timerBegin(tag) + L9TimerStop + let s:timerCurrent = {'tag': strftime('%c ') . a:tag . ' ', 'time': reltime()} + let s:timerTagMaxLen = max([len(s:timerCurrent.tag), s:timerTagMaxLen]) + endfunction + + function s:timerStop() + if !exists('s:timerCurrent') + return + endif + let s:timerCurrent.time = reltimestr(reltime(s:timerCurrent.time)) + call add(s:timerData, s:timerCurrent) + unlet s:timerCurrent + endfunction + + function s:timerDump() + L9TimerStop + let lines = map(s:timerData, 'v:val.tag . repeat(" ", s:timerTagMaxLen - len(v:val.tag)) . v:val.time') + call l9#tempbuffer#openReadOnly('[l9-timer]', '', lines, 0, 0, 0, {}) + let s:timerData = [] + let s:timerTagMaxLen = 0 + endfunction + +else + command -nargs=1 L9Timer : + command -nargs=0 L9TimerStop : + command -nargs=0 L9TimerDump : +endif + +" }}}1 +"============================================================================= +" GREP BUFFER: {{{1 + +" Grep for current buffer by l9#grepBuffers() +" Used as :L9GrepBuffer/pattern +command -nargs=? L9GrepBuffer call l9#grepBuffers(, [bufnr('%')]) + +" Grep for all buffers by l9#grepBuffers() +" Used as :L9GrepBufferAll/pattern +command -nargs=? L9GrepBufferAll call l9#grepBuffers(, range(1, bufnr('$'))) + +" }}}1 +"============================================================================= +" vim: set fdm=marker: From 6b9734a567a10ecfd5e975898beb5288d33415ad Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Thu, 28 Aug 2014 10:48:15 -0700 Subject: [PATCH 009/177] use =j to reformat a JSON file --- vimrc | 1 + 1 file changed, 1 insertion(+) diff --git a/vimrc b/vimrc index 1633865..f3c7d5d 100644 --- a/vimrc +++ b/vimrc @@ -31,6 +31,7 @@ set wildignore=.svn,CVS,.git,*.o,*.a,*.class,*.mo,*.la,*.so,*.obj,*.swp,*.jpg,*. "------ JSON magic ------ au BufRead,BufNewFile *.json set filetype=json let g:vim_json_syntax_conceal = 0 +nmap =j :%!python -m json.tool "------ Special Coffee Behavior ------ au BufNewFile,BufReadPost *.coffee set shiftwidth=2 softtabstop=2 expandtab From bf130c9f8f13617cc573f5439824fcc74c108daf Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Mon, 1 Sep 2014 13:57:34 -0700 Subject: [PATCH 010/177] keep cursor horizontal position when moving between buffers --- vimrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vimrc b/vimrc index f3c7d5d..78f37d3 100644 --- a/vimrc +++ b/vimrc @@ -167,6 +167,8 @@ nnoremap J mzJ`z noremap H ^ noremap L $ vnoremap L g_ +" Prevent cursor from moving to beginning of line when switching buffers +:se nostartofline " Deletes trailing space in file upon write " autocmd BufWritePre * :%s/\s\+$//e From 1ec720f5dfed3701385649f7d0ab0e9cc62d383c Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Tue, 16 Sep 2014 16:16:14 -0700 Subject: [PATCH 011/177] backspace in insert mode, Cmd+Shift+N new doc --- vimrc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vimrc b/vimrc index 78f37d3..5d9b97c 100644 --- a/vimrc +++ b/vimrc @@ -200,6 +200,7 @@ else set t_Co=256 colorscheme Mustang "This theme works great in 256 colors set mouse=a "This allows mouse scrolling in terminal, and selection of text + set backspace=indent,eol,start "Delete existing characters in insert mode (MacVim defaut) endif if has("gui_macvim") "Use Experimental Renderer option must be enabled for transparency @@ -210,6 +211,10 @@ if has("gui_macvim") "Use Experimental Renderer option must be enabled for trans " Swipe to move between bufers :D map :bprev map :bnext + + " Cmd+Shift+N = new buffer + map :enew + " OS X probably has ctags in a weird place let g:tagbar_ctags_bin='/usr/local/bin/ctags' endif From 6ecdead68a006526a1ddb9b0490cabbb3b1570ff Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Sun, 21 Sep 2014 17:10:12 -0700 Subject: [PATCH 012/177] Scala support --- bundle/scala/.gitignore | 6 + bundle/scala/.travis.yml | 11 + bundle/scala/Gemfile | 5 + bundle/scala/Gemfile.lock | 20 + bundle/scala/LICENSE.TXT | 201 ++++++ bundle/scala/README.md | 36 ++ bundle/scala/Rakefile | 6 + bundle/scala/after/plugin/help.vim | 50 ++ bundle/scala/after/syntax/help.vim | 8 + bundle/scala/doc/scala.txt | 44 ++ bundle/scala/ftdetect/scala.vim | 8 + bundle/scala/ftplugin/scala.vim | 195 ++++++ bundle/scala/ftplugin/scala.xpt.vim | 29 + bundle/scala/indent/README | 78 +++ bundle/scala/indent/scala.vim | 601 ++++++++++++++++++ bundle/scala/indent/testfile.scala | 380 +++++++++++ bundle/scala/plugin/scala.vim | 132 ++++ .../fixtures/multiple_newlines.expected.scala | 11 + .../spec/fixtures/multiple_newlines.scala | 12 + .../spec/fixtures/no_newline.expected.scala | 9 + bundle/scala/spec/fixtures/no_newline.scala | 8 + .../fixtures/no_newline_after.expected.scala | 8 + .../spec/fixtures/no_newline_after.scala | 7 + .../spec/fixtures/no_package.expected.scala | 7 + bundle/scala/spec/fixtures/no_package.scala | 6 + .../spec/fixtures/vanilla.expected.scala | 9 + bundle/scala/spec/fixtures/vanilla.scala | 9 + bundle/scala/spec/import_sorting_spec.rb | 16 + bundle/scala/spec/spec_helper.rb | 44 ++ bundle/scala/syntax/scala.vim | 180 ++++++ bundle/scala/syntax/testfile.scala | 173 +++++ 31 files changed, 2309 insertions(+) create mode 100644 bundle/scala/.gitignore create mode 100644 bundle/scala/.travis.yml create mode 100644 bundle/scala/Gemfile create mode 100644 bundle/scala/Gemfile.lock create mode 100644 bundle/scala/LICENSE.TXT create mode 100644 bundle/scala/README.md create mode 100644 bundle/scala/Rakefile create mode 100644 bundle/scala/after/plugin/help.vim create mode 100644 bundle/scala/after/syntax/help.vim create mode 100644 bundle/scala/doc/scala.txt create mode 100644 bundle/scala/ftdetect/scala.vim create mode 100644 bundle/scala/ftplugin/scala.vim create mode 100644 bundle/scala/ftplugin/scala.xpt.vim create mode 100644 bundle/scala/indent/README create mode 100644 bundle/scala/indent/scala.vim create mode 100644 bundle/scala/indent/testfile.scala create mode 100644 bundle/scala/plugin/scala.vim create mode 100644 bundle/scala/spec/fixtures/multiple_newlines.expected.scala create mode 100644 bundle/scala/spec/fixtures/multiple_newlines.scala create mode 100644 bundle/scala/spec/fixtures/no_newline.expected.scala create mode 100644 bundle/scala/spec/fixtures/no_newline.scala create mode 100644 bundle/scala/spec/fixtures/no_newline_after.expected.scala create mode 100644 bundle/scala/spec/fixtures/no_newline_after.scala create mode 100644 bundle/scala/spec/fixtures/no_package.expected.scala create mode 100644 bundle/scala/spec/fixtures/no_package.scala create mode 100644 bundle/scala/spec/fixtures/vanilla.expected.scala create mode 100644 bundle/scala/spec/fixtures/vanilla.scala create mode 100644 bundle/scala/spec/import_sorting_spec.rb create mode 100644 bundle/scala/spec/spec_helper.rb create mode 100644 bundle/scala/syntax/scala.vim create mode 100644 bundle/scala/syntax/testfile.scala diff --git a/bundle/scala/.gitignore b/bundle/scala/.gitignore new file mode 100644 index 0000000..01716d2 --- /dev/null +++ b/bundle/scala/.gitignore @@ -0,0 +1,6 @@ +# Ignore Vim tag files +tags + +# Ignore Vim swap files +.*.swp +.*.swo diff --git a/bundle/scala/.travis.yml b/bundle/scala/.travis.yml new file mode 100644 index 0000000..c1ac6c5 --- /dev/null +++ b/bundle/scala/.travis.yml @@ -0,0 +1,11 @@ +language: ruby +rvm: + - 1.9.3 +before_install: sudo apt-get install vim-gtk +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" +notifications: + email: + on_success: never + on_failure: change diff --git a/bundle/scala/Gemfile b/bundle/scala/Gemfile new file mode 100644 index 0000000..414fd03 --- /dev/null +++ b/bundle/scala/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org/' +gem 'vimrunner', '0.3.0' +gem 'rake', '10.0.4' +gem 'rspec', '~> 2.13.0' + diff --git a/bundle/scala/Gemfile.lock b/bundle/scala/Gemfile.lock new file mode 100644 index 0000000..ea5528e --- /dev/null +++ b/bundle/scala/Gemfile.lock @@ -0,0 +1,20 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.1.3) + rake (0.9.2.2) + rspec (2.9.0) + rspec-core (~> 2.9.0) + rspec-expectations (~> 2.9.0) + rspec-mocks (~> 2.9.0) + rspec-core (2.9.0) + rspec-expectations (2.9.1) + diff-lcs (~> 1.1.3) + rspec-mocks (2.9.0) + +PLATFORMS + ruby + +DEPENDENCIES + rake + rspec diff --git a/bundle/scala/LICENSE.TXT b/bundle/scala/LICENSE.TXT new file mode 100644 index 0000000..66b0c46 --- /dev/null +++ b/bundle/scala/LICENSE.TXT @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright {yyyy} {name of copyright owner} + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/bundle/scala/README.md b/bundle/scala/README.md new file mode 100644 index 0000000..c786a1c --- /dev/null +++ b/bundle/scala/README.md @@ -0,0 +1,36 @@ +vim-scala [![Build Status](https://secure.travis-ci.org/lenniboy/vim-scala.png)](http://travis-ci.org/lenniboy/vim-scala) +========== + +This is a "bundle" for Vim that builds off of the initial Scala plugin modules +by Stefan Matthias Aust and adds some more "stuff" that I find useful, including +all of my notes and customizations. + +##Installation + +You really should be using Tim Pope's [Pathogen](https://github.com/tpope/vim-pathogen) module for Vim (http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen) if you're going to clone this repository because, well... you should. + +###Vundle +Alternatively, you can use [Vundle](https://github.com/gmarik/vundle) to +manage your plugins. + +If you have Vundle installed, simply add the following to your .vimrc: + +```vim +Bundle 'derekwyatt/vim-scala' +``` + +and then run + +```vim +:BundleInstall +``` + +to install it. + +##Sorting of import statements + :SortScalaImports + +There are different modes for import sorting available. For details, please +consult the vimdoc help with + + :help :SortScalaImports diff --git a/bundle/scala/Rakefile b/bundle/scala/Rakefile new file mode 100644 index 0000000..7c84562 --- /dev/null +++ b/bundle/scala/Rakefile @@ -0,0 +1,6 @@ +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new + +task :test => :spec +task :default => :spec diff --git a/bundle/scala/after/plugin/help.vim b/bundle/scala/after/plugin/help.vim new file mode 100644 index 0000000..785160a --- /dev/null +++ b/bundle/scala/after/plugin/help.vim @@ -0,0 +1,50 @@ + +function! FixTOCLine(beginning, colonCol) + let l = strlen(a:beginning) + let c = 0 + let dots = "" + while c < (a:colonCol - l) + let dots = dots . "." + let c += 1 + endwhile + return (a:beginning . dots . ":") +endfunction + +function! BuildTOC() + let lnum = getpos(".")[1] + call append(lnum - 1, "<<<") + call append(lnum, ">>>") + :g/^\d\+\./co/>>>/- + :g/^<<>>/s/ {{{\d\s*// + :g/^<<>>/s/\*/|/g + :g/^<<>>/s/^\ze\d\.\d\+\./ / + :g/^<<>>/s/^\ze\d\d\.\d\+\./ / + :g/^<<>>/s/^\ze\d\.\d\+/ / + :g/^<<>>/s/^\ze\d\d\.\d\+/ / + :g/^<<>>/s/^\ze\d\./ / + :g/^<<>>/s/^\ze\d\d\./ / + :g/^\s\+0\. Content/d + :g/<<>>/-s/^\(.\{-}\)\(\s\+\)\ze |/\=FixTOCLine(submatch(1), 45)/ + :g/<<>>/d +endfunction + +command! BuildNewTableOfContents silent! call BuildTOC() + +function! JustifyCurrentLine() + let cline = getline('.') + let matches = matchlist(cline, '^\(.*\)\s\+\(\*.*\)$') + let st = matches[1] + let fin = matches[2] + let spcnum = 78 - strlen(st) - strlen(fin) + let c = 0 + let spcs = "" + while c < spcnum + let spcs = spcs . " " + let c = c + 1 + endwhile + let newline = st . spcs . fin + :norm dd + let lnum = getpos('.')[1] + call append(lnum - 1, newline) +endfunction diff --git a/bundle/scala/after/syntax/help.vim b/bundle/scala/after/syntax/help.vim new file mode 100644 index 0000000..b352a1e --- /dev/null +++ b/bundle/scala/after/syntax/help.vim @@ -0,0 +1,8 @@ +let b:current_syntax = '' +unlet b:current_syntax +syntax include @ScalaCode syntax/scala.vim +if has('conceal') + syntax region rgnScala matchgroup=Ignore concealends start='!sc!' end='!/sc!' contains=@ScalaCode +else + syntax region rgnScala matchgroup=Ignore start='!sc!' end='!/sc!' contains=@ScalaCode +endif diff --git a/bundle/scala/doc/scala.txt b/bundle/scala/doc/scala.txt new file mode 100644 index 0000000..d3277b4 --- /dev/null +++ b/bundle/scala/doc/scala.txt @@ -0,0 +1,44 @@ +*scala.txt* Syntax highlighting and helper functions for the Scala language. + +INTRODUCTION *scala* + +Syntax highlighting and helper functions for the scala language. + +COMMANDS *scala-commands* + + *:SortScalaImports* +:SortScalaImports There are two modes in which this command can operate. + By default it walks all import groups at the top of + the Scala file and orders their lines alphabetically. + A group is a series of lines starting with the + import keyword separated by one or more blank lines. + + The second, more advanced mode, can be activated by + setting + + let g:scala_sort_across_groups=1 + + This makes this command include all imports in the + sorting regardless of blank lines in between them and + puts them in three predefined groups instead. + The three groups in which the imports can fall are: + + 1. Scala and Java core + 2. Third party libraries + 3. First party code (ie. your own) + + Java and Scala core imports are identified by the + java(x) and scala namespaces. + Everything else that isn't a first party namespace + will be a third party import. + You can define a regex that matches first party + namespaces by setting + + g:scala_first_party_namespaces + + For example in a standard Play app this would be + set to + g:scala_first_party_namespaces= + \ '\(controllers\|views\|models\)' + + diff --git a/bundle/scala/ftdetect/scala.vim b/bundle/scala/ftdetect/scala.vim new file mode 100644 index 0000000..997a701 --- /dev/null +++ b/bundle/scala/ftdetect/scala.vim @@ -0,0 +1,8 @@ +fun! s:DetectScala() + if getline(1) == '#!/usr/bin/env scala' + set filetype=scala + endif +endfun + +au BufRead,BufNewFile *.scala,*.sbt set filetype=scala +au BufRead,BufNewFile * call s:DetectScala() diff --git a/bundle/scala/ftplugin/scala.vim b/bundle/scala/ftplugin/scala.vim new file mode 100644 index 0000000..3f0de96 --- /dev/null +++ b/bundle/scala/ftplugin/scala.vim @@ -0,0 +1,195 @@ +setlocal formatoptions+=ro +setlocal commentstring=//%s +let &l:include = '^\s*import' +let &l:includeexpr = 'substitute(v:fname,"\\.","/","g")' +setlocal path+=src/main/scala,src/test/scala +setlocal suffixesadd=.scala + +set makeprg=sbt\ -Dsbt.log.noformat=true\ compile +set efm=%E\ %#[error]\ %f:%l:\ %m,%C\ %#[error]\ %p^,%-C%.%#,%Z, + \%W\ %#[warn]\ %f:%l:\ %m,%C\ %#[warn]\ %p^,%-C%.%#,%Z, + \%-G%.%# + +if globpath(&rtp, 'plugin/fuf.vim') != '' + " + " FuzzyFinder stuff + " + " + " SanitizeDirForFuzzyFinder() + " + " This is really just a convenience function to clean up any stray '/' + " characters in the path, should they be there. + " + function! scala#SanitizeDirForFuzzyFinder(dir) + let dir = expand(a:dir) + let dir = substitute(dir, '/\+$', '', '') + let dir = substitute(dir, '/\+', '/', '') + + return dir + endfunction + + " + " GetDirForFuzzyFinder() + " + " Given a directory to start 'from', walk up the hierarchy, looking for a path + " that matches the 'addon' you want to see. + " + " If nothing can be found, then we just return the 'from' so we don't really get + " the advantage of a hint, but just let the user start from wherever he was + " starting from anyway. + " + function! scala#GetDirForFuzzyFinder(from, addon) + let from = scala#SanitizeDirForFuzzyFinder(a:from) + let addon = expand(a:addon) + let addon = substitute(addon, '^/\+', '', '') + let found = '' + " If the addon is right here, then we win + if isdirectory(from . '/' . addon) + let found = from . '/' . addon + else + let dirs = split(from, '/') + if !has('win32') && !has('win64') + let dirs[0] = '/' . dirs[0] + endif + " Walk up the tree and see if it's anywhere there + for n in range(len(dirs) - 1, 0, -1) + let path = join(dirs[0:n], '/') + if isdirectory(path . '/' . addon) + let found = path . '/' . addon + break + endif + endfor + endif + " If we found it, then let's see if we can go deeper + " + " For example, we may have found component_name/include + " but what if that directory only has a single directory + " in it, and that subdirectory only has a single directory + " in it, etc... ? This can happen when you're segmenting + " by namespace like this: + " + " component_name/include/org/vim/CoolClass.h + " + " You may find yourself always typing '' from the + " 'include' directory just to go into 'org/vim' so let's + " just eliminate the need to hit the ''. + if found != '' + let tempfrom = found + let globbed = globpath(tempfrom, '*') + while len(split(globbed, "\n")) == 1 + let tempfrom = globbed + let globbed = globpath(tempfrom, '*') + endwhile + let found = scala#SanitizeDirForFuzzyFinder(tempfrom) . '/' + else + let found = from + endif + + return found + endfunction + + " + " GetTestDirForFuzzyFinder() + " + " Now overload GetDirForFuzzyFinder() specifically for the test directory (I'm + " really only interested in going down into test/src 90% of the time, so let's + " hit that 90% and leave the other 10% to couple of extra keystrokes) + " + function! scala#GetTestDirForFuzzyFinder(from) + return scala#GetDirForFuzzyFinder(a:from, 'src/test/scala/') + endfunction + + " + " GetMainDirForFuzzyFinder() + " + " Now overload GetDirForFuzzyFinder() specifically for the main directory. + " + function! scala#GetMainDirForFuzzyFinder(from) + return scala#GetDirForFuzzyFinder(a:from, 'src/main/scala/') + endfunction + + " + " GetRootDirForFuzzyFinder() + " + " Now overload GetDirForFuzzyFinder() specifically for the root directory. + " + function! scala#GetRootDirForFuzzyFinder(from) + return scala#GetDirForFuzzyFinder(a:from, 'src/../') + endfunction + + " If you want to disable the default key mappings, write the following line in + " your ~/.vimrc + " let g:scala_use_default_keymappings = 0 + if get(g:, 'scala_use_default_keymappings', 1) + nnoremap ft :FufFile =scala#GetTestDirForFuzzyFinder('%:p:h') + nnoremap fs :FufFile =scala#GetMainDirForFuzzyFinder('%:p:h') + nnoremap fr :FufFile =scala#GetRootDirForFuzzyFinder('%:p:h') + endif +endif + +" If you want to disable the default key mappings, write the following line in +" your ~/.vimrc +" let g:scala_use_default_keymappings = 0 +if get(g:, 'scala_use_default_keymappings', 1) + nnoremap jt :call JustifyCurrentLine() +endif + +" +" TagBar +" +let g:tagbar_type_scala = { + \ 'ctagstype' : 'scala', + \ 'kinds' : [ + \ 'p:packages:1', + \ 'V:values', + \ 'v:variables', + \ 'T:types', + \ 't:traits', + \ 'o:objects', + \ 'a:aclasses', + \ 'c:classes', + \ 'r:cclasses', + \ 'm:methods' + \ ], + \ 'sro' : '.', + \ 'kind2scope' : { + \ 'T' : 'type', + \ 't' : 'trait', + \ 'o' : 'object', + \ 'a' : 'abstract class', + \ 'c' : 'class', + \ 'r' : 'case class' + \ }, + \ 'scope2kind' : { + \ 'type' : 'T', + \ 'trait' : 't', + \ 'object' : 'o', + \ 'abstract class' : 'a', + \ 'class' : 'c', + \ 'case class' : 'r' + \ } +\ } + +function! s:CreateOrExpression(keywords) + return '('.join(a:keywords, '|').')' +endfunction + +function! s:NextSection(backwards) + if a:backwards + let dir = '?' + else + let dir = '/' + endif + let keywords = [ 'def', 'class', 'trait', 'object' ] + let keywordsOrExpression = s:CreateOrExpression(keywords) + + let modifiers = [ 'public', 'private', 'private\[\w*\]', 'protected', 'abstract', 'case', 'override', 'implicit', 'final', 'sealed'] + let modifierOrExpression = s:CreateOrExpression(modifiers) + + let regex = '^ *('.modifierOrExpression.' )* *'.keywordsOrExpression."\r" + execute 'silent normal! ' . dir . '\v'.regex +endfunction + +noremap +me=s-1 keepend +\ contains=mustacheInside,@htmlMustacheContainer,htmlTag,htmlEndTag,htmlTagName,htmlSpecialChar + +let b:current_syntax = "mustache" +delcommand HtmlHiLink From 28cf88434f83a8263d1fed68ef7a3156fefa8f7d Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Tue, 27 Dec 2016 14:53:33 -0800 Subject: [PATCH 106/177] Jenkinsfile, Dockerfile support --- bundle/Dockerfile/LICENSE | 20 + bundle/Dockerfile/Makefile | 15 + bundle/Dockerfile/README.md | 47 ++ bundle/Dockerfile/ftdetect/Dockerfile.vim | 5 + bundle/Dockerfile/ftdetect/docker-compose.vim | 4 + bundle/Dockerfile/ftplugin/Dockerfile.vim | 27 ++ bundle/Dockerfile/indent/Dockerfile.vim | 23 + .../Dockerfile/snippets/Dockerfile.snippets | 66 +++ .../snippets/docker-compose.snippets | 163 +++++++ bundle/Dockerfile/syntax/Dockerfile.vim | 64 +++ bundle/Dockerfile/syntax/docker-compose.vim | 74 +++ bundle/Dockerfile/vim-dockerfile-example.png | Bin 0 -> 57722 bytes bundle/groovy/syntax/groovy.vim | 450 ++++++++++++++++++ vimrc | 9 + 14 files changed, 967 insertions(+) create mode 100644 bundle/Dockerfile/LICENSE create mode 100644 bundle/Dockerfile/Makefile create mode 100644 bundle/Dockerfile/README.md create mode 100644 bundle/Dockerfile/ftdetect/Dockerfile.vim create mode 100644 bundle/Dockerfile/ftdetect/docker-compose.vim create mode 100644 bundle/Dockerfile/ftplugin/Dockerfile.vim create mode 100644 bundle/Dockerfile/indent/Dockerfile.vim create mode 100644 bundle/Dockerfile/snippets/Dockerfile.snippets create mode 100644 bundle/Dockerfile/snippets/docker-compose.snippets create mode 100644 bundle/Dockerfile/syntax/Dockerfile.vim create mode 100644 bundle/Dockerfile/syntax/docker-compose.vim create mode 100644 bundle/Dockerfile/vim-dockerfile-example.png create mode 100644 bundle/groovy/syntax/groovy.vim diff --git a/bundle/Dockerfile/LICENSE b/bundle/Dockerfile/LICENSE new file mode 100644 index 0000000..27856ca --- /dev/null +++ b/bundle/Dockerfile/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Eugene Kalinin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/bundle/Dockerfile/Makefile b/bundle/Dockerfile/Makefile new file mode 100644 index 0000000..a7c1fdf --- /dev/null +++ b/bundle/Dockerfile/Makefile @@ -0,0 +1,15 @@ +install: + @echo "Installation:" + @mkdir -p ~/.vim/syntax + @mkdir -p ~/.vim/ftdetect + @mkdir -p ~/.vim/snippets + @echo " * Dirs ... success." + @cp ./syntax/Dockerfile.vim ~/.vim/syntax/ + @cp ./syntax/docker-compose.vim ~/.vim/syntax/ + @echo " * Syntax ... success." + @cp ./ftdetect/Dockerfile.vim ~/.vim/ftdetect/ + @cp ./ftdetect/docker-compose.vim ~/.vim/ftdetect/ + @echo " * Filetype ... success." + @cp ./snippets/Dockerfile.snippets ~/.vim/snippets/ + @cp ./snippets/docker-compose.snippets ~/.vim/snippets/ + @echo " * Snippets ... success." diff --git a/bundle/Dockerfile/README.md b/bundle/Dockerfile/README.md new file mode 100644 index 0000000..d97461a --- /dev/null +++ b/bundle/Dockerfile/README.md @@ -0,0 +1,47 @@ +Dockerfile.vim +============== + +Vim syntax file for [Docker](http://docker.io/)'s [Dockerfile](http://docs.docker.com/reference/builder/) +and snippets for [snipMate](http://www.vim.org/scripts/script.php?script_id=2540). + +Screenshot +========== + +Here is an example in gnome-terminal with [vim-monokai](https://github.com/sickill/vim-monokai) color scheme: + + +![Vim & Dockerfile.vim ](https://raw.github.com/ekalinin/Dockerfile.vim/master/vim-dockerfile-example.png) + + + +Installation +============ + +```bash +$ git clone https://github.com/ekalinin/Dockerfile.vim.git +$ cd Dockerfile.vim +$ make install +``` + +####Or using Pathogen: +```bash +# Clone directly into the bundle folder. +git clone https://github.com/ekalinin/Dockerfile.vim.git bundle/Dockerfile +``` + +####Or using Vundle: +```bash +# near the top of your .vimrc +Plugin 'ekalinin/Dockerfile.vim' +``` + +####Or using NeoBundle: + +```bash +NeoBundle 'ekalinin/Dockerfile.vim' +``` + +License +======= + +See [LICENSE](https://github.com/ekalinin/Dockerfile.vim/blob/master/LICENSE) file. diff --git a/bundle/Dockerfile/ftdetect/Dockerfile.vim b/bundle/Dockerfile/ftdetect/Dockerfile.vim new file mode 100644 index 0000000..7293a26 --- /dev/null +++ b/bundle/Dockerfile/ftdetect/Dockerfile.vim @@ -0,0 +1,5 @@ +" Dockerfile +autocmd BufRead,BufNewFile Dockerfile set ft=Dockerfile +autocmd BufRead,BufNewFile Dockerfile* setf Dockerfile +autocmd BufRead,BufNewFile *.dock setf Dockerfile +autocmd BufRead,BufNewFile *.[Dd]ockerfile setf Dockerfile diff --git a/bundle/Dockerfile/ftdetect/docker-compose.vim b/bundle/Dockerfile/ftdetect/docker-compose.vim new file mode 100644 index 0000000..0214497 --- /dev/null +++ b/bundle/Dockerfile/ftdetect/docker-compose.vim @@ -0,0 +1,4 @@ +" docker-compose.yml +autocmd BufRead,BufNewFile docker-compose.yml set ft=docker-compose +autocmd BufRead,BufNewFile docker-compose.yml* setf docker-compose +autocmd BufRead,BufNewFile docker-compose* setf docker-compose diff --git a/bundle/Dockerfile/ftplugin/Dockerfile.vim b/bundle/Dockerfile/ftplugin/Dockerfile.vim new file mode 100644 index 0000000..ff6ab7b --- /dev/null +++ b/bundle/Dockerfile/ftplugin/Dockerfile.vim @@ -0,0 +1,27 @@ +function! DockerfileReplaceInstruction(original, replacement) + let syn = synIDtrans(synID(line("."), col(".") - 1, 0)) + if syn != hlID("Comment") && syn != hlID("Constant") && strlen(getline(".")) == 0 + let word = a:replacement + else + let word = a:original + endif + let g:UnduBuffer = a:original + return word +endfunction + +inoreabbr from =DockerfileReplaceInstruction("from", "FROM") +inoreabbr maintainer =DockerfileReplaceInstruction("maintainer", "MAINTAINER") +inoreabbr run =DockerfileReplaceInstruction("run", "RUN") +inoreabbr cmd =DockerfileReplaceInstruction("cmd", "CMD") +inoreabbr label =DockerfileReplaceInstruction("label", "LABEL") +inoreabbr expose =DockerfileReplaceInstruction("expose", "EXPOSE") +inoreabbr env =DockerfileReplaceInstruction("env", "ENV") +inoreabbr add =DockerfileReplaceInstruction("add", "ADD") +inoreabbr copy =DockerfileReplaceInstruction("copy", "COPY") +inoreabbr entrypoint =DockerfileReplaceInstruction("entrypoint", "ENTRYPOINT") +inoreabbr volume =DockerfileReplaceInstruction("volume", "VOLUME") +inoreabbr user =DockerfileReplaceInstruction("user", "USER") +inoreabbr workdir =DockerfileReplaceInstruction("workdir", "WORKDIR") +inoreabbr arg =DockerfileReplaceInstruction("arg", "ARG") +inoreabbr onbuild =DockerfileReplaceInstruction("onbuild", "ONBUILD") +inoreabbr stopsignal =DockerfileReplaceInstruction("stopsignal", "STOPSIGNAL") diff --git a/bundle/Dockerfile/indent/Dockerfile.vim b/bundle/Dockerfile/indent/Dockerfile.vim new file mode 100644 index 0000000..e7b5058 --- /dev/null +++ b/bundle/Dockerfile/indent/Dockerfile.vim @@ -0,0 +1,23 @@ +if exists('b:did_indent') | finish | endif +let b:did_indent = 1 + + +function! DockerfileIndent(line) + let prev_line = getline(a:line - 1) + if a:line > 1 && prev_line =~ '\\\s*$' + let i = indent(a:line - 1) + if i == 0 + let i += &l:shiftwidth + if &l:expandtab && prev_line =~# '^RUN\s' + " Overindent past RUN + let i = 4 + &l:shiftwidth + endif + endif + return i + endif + + return -1 +endfunction + + +set indentexpr=DockerfileIndent(v:lnum) diff --git a/bundle/Dockerfile/snippets/Dockerfile.snippets b/bundle/Dockerfile/snippets/Dockerfile.snippets new file mode 100644 index 0000000..5f97a51 --- /dev/null +++ b/bundle/Dockerfile/snippets/Dockerfile.snippets @@ -0,0 +1,66 @@ +snippet F + FROM ${1:ubuntu} +snippet f + FROM ${1:ubuntu} +snippet M + MAINTAINER ${1:name} +snippet m + MAINTAINER ${1:name} +snippet R + RUN ${1:command} +snippet r + RUN ${1:command} +snippet C + CMD ${1:command} +snippet c + CMD ${1:command} +snippet CP + COPY ${1:src} ${2:dest} +snippet cp + COPY ${1:src} ${2:dest} +snippet EXP + EXPOSE ${1:port} +snippet exp + EXPOSE ${1:port} +snippet E + ENV ${1:key} ${2:value} +snippet e + ENV ${1:key} ${2:value} +snippet A + ADD ${1:src} ${2:dst} +snippet a + ADD ${1:src} ${2:dst} +snippet ENT + ENTRYPOINT ${1:command} +snippet ent + ENTRYPOINT ${1:command} +snippet V + VOLUME ["${1:path}"] +snippet v + VOLUME ["${1:path}"] +snippet U + USER ${1:name} +snippet u + USER ${1:name} +snippet W + WORKDIR ${1:path} +snippet w + WORKDIR ${1:path} +snippet upd + # update packages + RUN echo "deb http://archive.ubuntu.com/ubuntu ${1:precise} main universe" > /etc/apt/sources.list; \ + apt-get update && apt-get -y upgrade; \ + ${2} +snippet head + # ${1:Description} + # + # VERSION ${2:0.1.0} + ${3} +snippet O + ONBUILD ${1} +snippet o + ONBUILD ${1} +snippet L + LABEL ${1:label}="${2:value}" +snippet l + LABEL ${1:label}="${2:value}" diff --git a/bundle/Dockerfile/snippets/docker-compose.snippets b/bundle/Dockerfile/snippets/docker-compose.snippets new file mode 100644 index 0000000..8cab91d --- /dev/null +++ b/bundle/Dockerfile/snippets/docker-compose.snippets @@ -0,0 +1,163 @@ +snippet ve + version: ${1:2} +snippet volumes + volumes: + - ${1:value} +snippet volume_ + volume_driver: ${1:driver} +snippet volumes_ + volumes_from: + - ${1:name} +snippet exter + external: ${1:boolean} +snippet ser + services: + ${1:name} +snippet bu + build: + ${1:value} +snippet conte + context: ${1:dir} +snippet com + command: ${1:command} +snippet dep + depends_on: + ${1:value} +snippet env + environment: + ${1:name}: ${2:value} +snippet doc + dockerfile: ${1:file} +snippet ar + args: + ${1:name}: ${2:value} +snippet cap_a + cap_add: + - ${1:value} +snippet cap_d + cap_drop: + - ${1:value} +snippet cgr + cgroup_parent: ${1:cgroup} +snippet conta + container_name: ${1:name} +snippet dev + devices: + - ${1:value} +snippet dn + dns: + - ${1:ip} +snippet dns_ + dns_search: + - ${1:ip} +snippet tm + tmpfs: + - ${1:dir} +snippet ent + entrypoint: ${1:command} +snippet env_ + env_file: + - ${1:file} +snippet exp + expose: + - ${1:port} +snippet exten + extends: + file: ${1:file} + service: ${2:name} +snippet exter + extra_hosts: + - ${1:host}:${2:ip} +snippet gr + group_add: + - ${1:name} +snippet im + image: ${1:image} +snippet la + labels: + ${1:dns}: ${2:label} +snippet links + links: + - ${1:name} +snippet logg + logging: + driver: ${1:driver} + options: + ${2:value} +snippet log_d + log_driver: ${1:driver} +snippet log_o + log_opt: + ${1:value} +snippet net + net: ${1:value} +snippet network_ + network_mode: ${1:value} +snippet networks + networks: + - ${1:value} +snippet al + networks: + - ${1:name} +snippet ipv4 + ipv4_address: ${1:ip} +snippet ipv6 + ipv6_address: ${1:ip} +snippet link_ + link_local_ips: + - ${1:ip} +snippet pi + pid: ${1:host} +snippet po + ports: + - ${1:value} +snippet sec + security_opt: + - ${1:value} +snippet sto + stop_signal: ${1:signal} +snippet ul + ulimits: + ${1:value} +snippet cpu_s + cpu_shares: ${1:value} +snippet cpu_q + cpu_quota: ${1:value} +snippet cpus + cpuset: ${1:value} +snippet dom + domainname: ${1:name} +snippet ho + hostname: ${1:name} +snippet ipc + ipc: ${1:host} +snippet mem_ + mem_limit: ${1:value} +snippet mems + memswap_limit: ${1:value} +snippet pr + privileged: ${1:boolean} +snippet oom + oom_score_adj: ${1:value} +snippet res + restart: ${1:value} +snippet us + user: ${1:value} +snippet wo + working_dir: ${1:dir} +snippet rea + read_only: ${1:boolean} +snippet sh + shm_size: ${1:value} +snippet std + stdin_open: ${1:boolean} +snippet tt + tty: ${1:boolean} +snippet driver + driver: ${1:value} +snippet driver_ + driver_opts: + ${1:key}: ${2:value} +snippet ipa + ipam: + ${1:value} diff --git a/bundle/Dockerfile/syntax/Dockerfile.vim b/bundle/Dockerfile/syntax/Dockerfile.vim new file mode 100644 index 0000000..f94e6a2 --- /dev/null +++ b/bundle/Dockerfile/syntax/Dockerfile.vim @@ -0,0 +1,64 @@ +" Vim syntax file +" Language: Dockerfile +" Maintainer: Eugene Kalinin +" Latest Revision: 11 September 2013 +" Source: http://docs.docker.io/en/latest/use/builder/ + +if exists("b:current_syntax") + finish +endif + +" case sensitivity (fix #17) +" syn case ignore + +" Keywords +syn keyword dockerfileKeywords FROM MAINTAINER RUN CMD COPY +syn keyword dockerfileKeywords EXPOSE ADD ENTRYPOINT +syn keyword dockerfileKeywords VOLUME USER WORKDIR ONBUILD +syn keyword dockerfileKeywords LABEL ARG HEALTHCHECK SHELL + +" Bash statements +setlocal iskeyword+=- +syn keyword bashStatement add-apt-repository adduser apk apt-get aptitude apt-key autoconf bundle +syn keyword bashStatement cd chgrp chmod chown clear complete composer cp curl du echo egrep +syn keyword bashStatement expr fgrep find gem gnufind gnugrep gpg grep groupadd head less ln +syn keyword bashStatement ls make mkdir mv node npm pacman pip pip3 php python rails rm rmdir rpm ruby +syn keyword bashStatement sed sleep sort strip tar tail tailf touch useradd virtualenv yum +syn keyword bashStatement usermod bash cat a2ensite a2dissite a2enmod a2dismod apache2ctl +syn keyword bashStatement wget gzip + +" Strings +syn region dockerfileString start=/"/ skip=/\\"/ end=/"/ +syn region dockerfileString1 start=/'/ skip=/\\'/ end=/'/ + +" Emails +syn region dockerfileEmail start=// contains=@ oneline + +" Urls +syn match dockerfileUrl /\(http\|https\|ssh\|hg\|git\)\:\/\/[a-zA-Z0-9\/\-\.]\+/ + +" Task tags +syn keyword dockerfileTodo contained TODO FIXME XXX + +" Comments +syn region dockerfileComment start="#" end="\n" contains=dockerfileTodo +syn region dockerfileEnvWithComment start="^\s*ENV\>" end="\n" contains=dockerfileEnv +syn match dockerfileEnv contained /\/ + +" Highlighting +hi link dockerfileKeywords Keyword +hi link dockerfileEnv Keyword +hi link dockerfileString String +hi link dockerfileString1 String +hi link dockerfileComment Comment +hi link dockerfileEmail Identifier +hi link dockerfileUrl Identifier +hi link dockerfileTodo Todo +hi link bashStatement Function + +let b:current_syntax = "dockerfile" + +set commentstring=#\ %s + +" Enable automatic comment insertion +setlocal fo+=cro diff --git a/bundle/Dockerfile/syntax/docker-compose.vim b/bundle/Dockerfile/syntax/docker-compose.vim new file mode 100644 index 0000000..cdfb84f --- /dev/null +++ b/bundle/Dockerfile/syntax/docker-compose.vim @@ -0,0 +1,74 @@ +" Vim syntax file +" Language: Dockerfile +" Maintainer: Eugene Kalinin +" Latest Revision: 11 September 2013 +" Source: http://docs.docker.io/en/latest/use/builder/ + +if exists("b:current_syntax") + finish +endif + +" case sensitivity (fix #17) +" syn case ignore + +" Keywords +syn keyword dockercomposeKeywords build context dockerfile args cap_add cap_drop +syn keyword dockercomposeKeywords command cgroup_parent container_name devices depends_on +syn keyword dockercomposeKeywords dns dns_search tmpfs entrypoint env_file environment +syn keyword dockercomposeKeywords expose extends extends external_links extra_hosts +syn keyword dockercomposeKeywords group_add image isolation labels links logging log_driver +syn keyword dockercomposeKeywords log_opt net network_mode networks aliases +syn keyword dockercomposeKeywords ipv4_address ipv6_address link_local_ips pid ports +syn keyword dockercomposeKeywords security_opt stop_signal ulimits volumes volume_driver +syn keyword dockercomposeKeywords volumes_from cpu_shares cpu_quota cpuset domainname hostname +syn keyword dockercomposeKeywords ipc mac_address mem_limit memswap_limit oom_score_adj privileged +syn keyword dockercomposeKeywords read_only restart shm_size stdin_open tty user working_dir +"" Volume configuration reference +syn keyword dockercomposeKeywords driver driver_opts external labels +"" Network configuration reference +syn keyword dockercomposeKeywords driver driver_opts enable_ipv6 ipam internal labels external +"" Versioning +syn keyword dockercomposeKeywords version services + +" Bash statements +setlocal iskeyword+=- +syn keyword bashStatement add-apt-repository adduser apk apt-get aptitude apt-key autoconf bundle +syn keyword bashStatement cd chgrp chmod chown clear complete composer cp curl du echo egrep +syn keyword bashStatement expr fgrep find gem gnufind gnugrep gpg grep groupadd head less ln +syn keyword bashStatement ls make mkdir mv node npm pacman pip pip3 php python rails rm rmdir rpm ruby +syn keyword bashStatement sed sleep sort strip tar tail tailf touch useradd virtualenv yum +syn keyword bashStatement usermod bash cat a2ensite a2dissite a2enmod a2dismod apache2ctl +syn keyword bashStatement wget gzip + +" Strings +syn region dockercomposeString start=/"/ skip=/\\"/ end=/"/ +syn region dockercomposeString1 start=/'/ skip=/\\'/ end=/'/ + +" Emails +syn region dockercomposeEmail start=// contains=@ oneline + +" Urls +syn match dockercomposeUrl /\(http\|https\|ssh\|hg\|git\)\:\/\/[a-zA-Z0-9\/\-\.]\+/ + +" Task tags +syn keyword dockercomposeTodo contained TODO FIXME XXX + +" Comments +syn region dockercomposeComment start="#" end="\n" contains=dockercomposeTodo + +" Highlighting +hi link dockercomposeKeywords Keyword +hi link dockercomposeString String +hi link dockercomposeString1 String +hi link dockercomposeComment Comment +hi link dockercomposeEmail Identifier +hi link dockercomposeUrl Identifier +hi link dockercomposeTodo Todo +hi link bashStatement Function + +let b:current_syntax = "dockercompose" + +set commentstring=#\ %s + +" Enable automatic comment insertion +setlocal fo+=cro diff --git a/bundle/Dockerfile/vim-dockerfile-example.png b/bundle/Dockerfile/vim-dockerfile-example.png new file mode 100644 index 0000000000000000000000000000000000000000..c82f871f84f7a27ee90783ac65a997708e0f033f GIT binary patch literal 57722 zcmaI71#n!uwk>MMF;mP;am>u@j+vR6VrJ$xGsev9n3>s*DQ0G7X2$+W_CBx9{r|pS zU0q$J)>@M0oRY>I8VZw_6+?u>g#!ZvLzEB~Rs;ispala17l(oRT~h1h@%Z}(%1}y7 z7!361lhaWY|GNa%PF%wg3=AIa&lemlEd%>^A+(c(j0p4^EIbMdMtYEJ=I>Sf&Q_R}fPo-HQuCN&H&B z**~`j`g}S4@&M)k@vT#@s$DlQ{vg9N>&5HBF?id)P1$#7D*uxp3`yW8!O(Z%rU!pRK8WzY~V!i~dvp6!K<)6oc`2b#?DD?`B-3( z)|6EH=f5?dLo2%m6z2VmxPaQMg&ST%0-nUPI4nCBgI5=-y+DxdL1)j3n_AStUTsgt z=0%FaO9PUsnChjx6)8q$yj2AtW8?(NK59%7oxd?e?eeQ2B3=V^F=izL!H7yQudJla z4@82QGK$NzvLr`l$t9q&^lZbIjQdXv49mkoEF3e32?E6bb{Y1&|2*zQj=>-!Eg1sh z8FUk#H(Ny9amiAL79dd*BT7v!9MF9L(RdRsAQVRvoqiI04W*TeXF6DzmZHZNx6(1j zo1{JL!WJoY%<{NV3RZ+%UZ_3y{Tw=iC3?!wWM1E(QV6~@OdTUO5%P~oVMv~pL9Jh; zr%-vUSWBKQ8m%aMN(fhNl%vu=XcT z%@?M9c6;M8jiifgxfgON`JSLGmCh0r!HbKoB8Q5kYTlcAGOzD4$fU3$*l9@2^+~Ya zFsm=$^2QD1Uoh^eeEW_5Iir2fm1(%1!VJ%Cea5SWEc^9!%q(ybML%l4PzffvhjYrS=w}#t!uik&=0rSnfF5~^xb++=(InVAKWyGGzelQ% zmvUgT?c!`g&jP4D!4ayfcV;iQ&~~jecy0r0%NQ++bpLWaGG3g;ig?1PsFV@8a3Jj1 z+Qd|V{|VX~IRex1Cvj~Y?IMkqxwYMh8S3AzqE-hA>-Dn@-6^}iAJ4VgpV60RNe%z7 zlQ?Kht2V?OSh5SWbIu^o8T3ak>I|D;HD4`Nz4Ybp?l%iXDh?^6yeHUD`pFe3$0p!z ztK?};X(P~iEo}4)4V=CV?(kuOw;(N! z%HQGUO}xTw^yW>Q*~OY#Y)*mSrD#Dp))bLanz1%162O=?n#wh(ui8t)Hb3?3iX1HD zk@*r~w5`iluFHX4Qo<$qqP~(Cyt7+a!@>5V3AO78lQ@i8197VdKyeSCAN34;r9V%S&|s zQ-uNwA70kr^S1?h4i`S%(qqa&(sY#=O!Yt5zcdy-<{{LI3ZG*gQVK_<48RUjSqliE@TCq7qS1GF{FAs1Xx+a+k@U+N?p(eRLQTV z3|O%erw+q06n3GqN;pSjuE4imXgnj zBdapJ22NM94)pWOJ=%KC2q=$KFbsPSunh@RZ~+jw=puZ?lvh-6Kfc0%!^<}Eb%cf( z67CJW=V=-jGxmhgMpW4uSIB_++f0_AbRX#`ul{Er>-_P1e+m&jS3~)Cru;32Apr(CDMEf$ zb{JZisyLB)F7OWe9oth~LvRuQtX6^_FiC^~033B_WNFLkt8NQF5O&c@b(zCeZO=sBT})^ zRkjb^hjk(e;Q+lMsz1QtNxbNs|GkDS-mT1fL#?|>WY=!nm)$E1oqshonA`;3w4cik zLR0TEh)QC+?zZA}fh~@WZA-_*`oarVU@m%RqvEBjs51(W#qp6k zwtK`lfU9Ri0R>nQF!vpU7kx!sL_A)ZW#{}Q+(!?)X#-SsFffF5<9?#RkNZ=0H<3uM z=X!8R``R5Z$7u6aP5oV;+4kLqP|n8r_EDNuZ>dY2^MOX%K*`PQ=xhzCC1n(0)Pz8z z#-n@fgv8VA=#RmFBLXhBWf*3$9|mTNJ^Q>o!atZC7S+kQwA2$fM2XG1^GMf_F-`IF zA;!vkerktcDx=j<6I3AxkSsI#?yy>0$@ex-<{reu$Q{5FsnqT?GBHR_?6w*`vhcL9 z_K4P1vTz>qN{c!|nF?DUc(1L`s3n@5AdO4RGaj5Q}8?+P9vy!iEbs<2tVv}`xG*ihP5C$`wTXy-O6Jpt66PC{l+J)}%>GHdVk zmM7&IW7^Y9&(j63ly2Pk#j8K$c%)I%nfYISvs!aeg|`1d;(>k$JoeliT2XBNj@E$Eo2Q9DXg`)pek!6EVtdPc^u=`v@qS+7(hbP95x4bVexr7)QclN|Snj z=HEDQ(dKUOev@4H+{K4-2_6sUil|F&9}1^?+C8u}np=_LWa+q>rdazr?!8OU`N-6^ zQ(N{Q08vwf_mI-bQRBEud+z;2uGrNQkEc7fK`@FVw%Xk_Z*|gsYKf-T>4L|CCKU1F zs>7Vr}apfPp;w!Kj@w%-YQHL=MmVLj&^baj; z@sl?Mu?%2JXt|;BV9;GQ2-m*`@I()F>T1_lxjivg;+kr4-?Vph zErP^}e7cqg3SoUq-`tay>mgEJ`qF8+S`u9^n!`sbo3pwq8<p5JTd!6B%=x_xo?-a3e2Ly(Y=rGTFKV2g+c`pHXMlu*f%fGh@)|Ta>+rkV<2av}LkW^V&pD=T> zAgBE#wuaLnvNG7>*E%f_JIQeZq3hy?<0(u;_Ld@&@MXn@tG&HZe<;ctrEALWmuvF= z+F~llXf({3sg_|N!J zsS)RI!=&*D1je2(epTKC@}^FgYD&9Z(a^6;E)6#|Q%pM9*vTx~V_v?`)~k-WoRO=i_P|1*H|Ivl%t?9SFxNL&^gAtz>*+IA(U6{B zp*q>a5GXB6%4_!;MpnO9g#Gxn?83vP!pw>C<0aIr%?PABFYwB+(_Gj_V-r!zhpvrC8{-&b#+(G+&acY^N>DCBBhsD1cc`%ZpN+;jRA7Tz@-WX%dAkk}5yne6>E! znypgT`^NItatgIOCS1psqRHqzOiZErBf4}J_75m4-dNR9xy*Q{exflnjIhyL3w2Y3 zKpj=MD=0dnK%Uevd#_Nv0UI@U{7#K7I7+Kv^*VWAxgFXobwy z?p7Ffu|9~VV0Er#)&XhIRO8X@%n!{-?TA~lCD;fp&E3em*Do17&4b@-@-`PMaK1s# zevb(C=`yIu&2S}^)~zVx>!Tfcp_{tn#!UNz4o^<5fg6k88wBQD$Y2o}^{Vgm6yyWE zb_XY~<~C`hSvAU`_5JVg@17Hkr%7^)C-U@096OK3_uwUz@2Gb-?hyG0*Eq4ja>Q|Z zF=A?wEV)2zeGgtk6HgwC=9#<^9>$)`p#=AOk(uP9#D3F+^2isTT)63&syWC)ROxkH zRyJ8g{0$NFA5yVTXW|LvCk?*^(nOkM27F%goB63KMFyH1sO`p5+!A+rz_bi`2lrcJK6is62D*P#@quqD95l$7T)SDM^ zv2$-NcO`=JEh=>N?X0uyvg?%xBxwV@wx=e1L5580$#4)oK0jN}1nn&`U|r6l*}KfW`smoj{ATkmdJ&>mUx ztD>@*i)H3L?#5u3L*!zETcB%Bb38k_Bnwoyy#jqVIyvn+cVJhee6`gSLIG`Qh!Vv72M>EA zDBGm7yX^r8q@&G^DHqJy5C@sWED6BERfj~oeB*>Ozm>G+;NA;hP0hZJw=pZ7TCrtx ztq(1?^0Gj;2mV5*=HlI!FFJzX#$;tC!i{oY!KNJ~LjTcjw&v}GSJT_q7TTxl9_lku zN5l!}K;-ruHyqc`mq-Qj)!EBq<%yDmehazFCxzuRy4_sO-rCCJMD3>!(fUW8ZFV`! z>Y!6pe$E{>oA(`9+AentIo%iHB+sh-_XSKtsMm2($$8A_R@b5%^txNW1wd-FI zYMYcA;~iyy&x7+%Vx11_9T!|b0L}!+d_J(_nIkO+>Bd%;a7=n3X~2sdGM1=cj1V&P zEl0Y4qV_HRKeSZ}aL+uXzAg%ngK+96D=Vvb1fj~Pw3`{E)L?rb)xoRuGl9}jOYaE^|ekcY^J?7Qf35VSVo(KsarpDho;@u9)C(m)oe7kYUq@#5K3s~dZ z&Lv@_g3n!l+#fB9Tk_%0yM9;xNc)ysJ?|HZohT70@I49ZFD4ZHkOUO9B&S^s*WJeW zr(!hR+iCxI?$3&1%+!{|HL7%vI;@GdrcyR!XF&I~?|qJKe|ygS=5W-rkuj2X(P`@KLKXdJFO3&3evu`-`rq5oYAwS*J(w!e ztE?^tQZ$-SH13n9d2MAdv&T2Da+mVv1`*&|qNYlyqIajUCQM0q+BQg)!T-|=xYUNc zGFZ?$ZS_ZOI@T7$Fpj61g@wt}a~LOHLgZrI<@Vb3e}?$mmPCcw;XwT`yZ$L_G&CTUGOD1!Z>cU2K*xdtBUcBw+&?FI(_&loF?;3 zC<4pmZe05L--ISG)^|_-afNdIlCIyovCE|tt}$TM;omVT9I0LUqr$5Gn4UkJKZd5> zU3>dJ~R|{ydJITJN}Br5uHjA^I4N7YE4Zb zn&}Fg96vr%|nDk1QY|{UsSTP>#51QJKS71mY`m z9bnvU{%+>r^JNgT=NA>Jf}_uurge#55wzfV#w|gM9}EhRh<*lM5zd#>_2&8?mll2V zWYJAVj;#5H&k|UZuc^^dgBfE%Y_N;XEUmI@wHQ2BmctQZVCTW@kJ0~iyVwYaU`bfu zo?Fuk6E!4K|JIGDk;r8dSnTK#m35f{!y2`+q;4Zt^M%oDQ9PRMS);B6mjiQpK$dt$ zTW%}qtlsh`4x<~)e8>Ef2W@s&Y6cPT3#~f>8dPI^hXJ%T5DY+XdwETu&P$h+qKscwY&7#iir!Gx)ct zhw)>>;nK5@#YJbaEs%3OR*I`u?vmNzT*$x2qC|)&MNs4j*iLS{E}7Zb z^rL_+YuZQUAQV?T)&-Z6+q-$OYgm!j2Ew@6)i+%@mSh^9wRoxc zd9N)0SDLWOjQe+93xkl<(H*Jtp#+A~;P8)o&V-D@`_Rpb*7EbB!uxh@2lrKxx#c?V z$xpwaSjuUX^=AGd@}CIdAxdb{;D;o)UV9Z07+I5Ni=ke15rX(RnXoZPOdgs zu4@@JP?`eEV}ptFLI^ox;GR$w-qeufB8p-?CtoRQ^ix);t?DJVrsx_Ho+BV}qQSPB z`OA=hers$T6h~>K$lsYb)dhhGsbq-D^lWEnlF?J$!9l`MBW6MM|WyorUY8yPn^$ujz?h^!KXAu!dbQuQ!be-?M zrA|NAm3}~wM(gjLSbtgIPR)JioyTfKW7<{^c5_&ipADYa+14jS z{}Cfii~!AZ29B=7IkgWKwGvTmbqNl4&d6{KMDv(ikoDF8zuW8YL&zQ|$PEZBA1fT2 ziVP4C#^Xz1_w?v0&3U%-?7_AX7BYL-J^Z;-y?gLiu zQUB6U>qop-clyku1}{^ozAXbhy<=l_t@L&OA3$30w#^sv10fIl#QKy!PIl?G<6?D) zol@h*iI}Opohqw=qgg16Z(S*@mgfaM*L27rDxRgFkp!`k+2>j7{ArZ0bBpGVmg0o0 zDPNAOJ-hL9H_-H{L{USK$jdwY$lLH#jL6uvp>?tNF+M~~h95IyvplPdYPl%R?0?9_ ziTIIPOU)x7g>9#(cVTF^EFRp5p?Cmh+5GMcsQZFU-m4Qr_i3QpK;lsIy0{h^Mqa}H zjaW2>aN^QGbC&Bv;8~*X9VC^Wss2&j%B5NS5PnAFkExLHyg>ye3Cq~)GxOsAjZ6Og z?*u_qM@pTSt{;jS+ZUJ{_+)%-Sob1`tolLMN`@Wk3xcWF=gb($aRVIzHXDq~CdFnd z>a%4*In}c(TLg(|f;}pIvB}@0D-=c|G-msw# z!MoDuhpm+ZQL8tL8q8SSgB89-Varhy99cVCyFr`+%c4sI<`2Z==Y~dc?PWfE zY$;i9#5|isK_FyLQbyc-&@ZcVE>H_dtYX2c;Q6&=Zv5?;a=_GgLU-)`nOd`hFWGh@ z&k5@P%{*^^4IeyH1Sc1ZF?>!eBA6a$w^?-)hM$?7ygadyvHsXwL?ovDgxkr0L%aOwffv4bwZlWN#K=|ct9Viqy60N2s! zvkbYKUoA(aQ+)7~2}~2CpDfF}gw6nh$7(PneNzut-~Iy@VAZ4HJcxSbEDe-3!S?J3 zdK3Drr5N@qVLfQkOs>wSaUz+ViK>O8aC=tcw_#_3<9uk)Ch&W1oqBtmX*&{Oix5pM z(mDrkTMs$OWo3ya9qm?Ls(Y{xH?OxH@drT3M(0Az-~_{GkeK`1{qfD69lX&osGRfxfEBwMQ93&qvtN+96FNtj zy7Qp(jx=!uQeaBSi z-@1c;v;Y^?_@Ki*ninkigRFmfz&6;PEg=d~lrGO@B&s*U>S zxchOAut%Lt2L97j(Yg3-9c#7vq;oE{|GpMa>8liUhXe0tvGem!zM zU;891*aDut*kU--(MVk`hnv_Q_a3`EN{hm#{mEhE2IkM8g993*#!c4oa3vd?9@?01 zyNUvj5X|gnmS+XaZuCVxd_4j(t(1JNlz8s4%-*ddNciSuHN=njtY$+TrHnZBzBF!~ zT6Y`YGQMAP%VwStFBeay;SEtt^wqVrItGcN5gWTe6lGhIvMj~;`*%>rH6?$M-#vMZ zZ@w9B0T}{3SZ9G)BW(=AN>eztRH|5mdO9QJXlv>!bcq`S*Y7k6ZB5X7t_o|rUpMv# zrSN2AfSM1uV`;_cz=x0>PFKZ`qA{7*m?QkjMN|WnvaMd!SQCU_{io!FY`{S;qui=$ z7t3LS+ow3~UO-lRQKC7#TKA{aF)It$20Dzm37&vLEIh{T+|#x(-Wx&sAQz1Cl2y>Y z)qpv;q1)+NZl?LM+jXs+`X1im&AkgvolVA&h>~F_3(aOto%f!JE-*hfuH!k)P-6EX z<}G+8(d)d;n{LUaVI-I3u+L9edAGWf{?oNfZ;m~$-3GR(usJx7=!+Y(~A_30y? z&NeZ9rxj?uE+p2V+)RN zM~Z`2tByMo$DH0ZM?HnBP3v`S>qaJ7WWmVA6v5*QOZFdr7qx&_U|Z|K#QDlpILKS zsdVas4s?GN5+}UxNFKU_&Of!<%AFahO{wp2z8&v8t%cPH7t@D#u8qQ1?bh^G8sfXq zBCm4AZ7EDDst=fm@y-n3mgwD)BJ*mAH*ko9o(mVM*l7oL$AoY|M0#XGHmaiN?->Z&7Vx@|emJO8*Q^L*wnqzcQ+k(eS8i!|lUN zMUKpNvaxr?0~)?o_7P&h7Qy7YPjIUzQ4PTLB39S)Sri|_nwh;InpgYitGh=)qS zUD@!GJG$RuI>fSc5b1mbqN}9R`st82#)D?2Yd&<|!*zOYOWLSwhGR_%NA7QvA=|yB zl7^|K|I&Epec)|Qu+jn>jdydJ(?amR{sw%JWdr^egJ_NqVwLZ|DiM*dKtB5wInHcH zq&T07Pw$kQfy-S1TAbEtxtV_I!~jbeH>`KDF0Ek z18tsNrPI}iftd*l0j}JElDQJaU`MGZSKQ1BF5i%grF?a5tj&j|T*Sgap5El?NR~1` zSe!nR3YZ-=l`B--zGc3j)}+_YE4=@qUfMw|(M5L<9MP`qg*no-!Dx5`85%h+fANu9 zZ8L*w%By-ckY`|=YGKaNy)1Q5k7;Y_F{QfMzpi%F>*^c+9xfIIZTU`GKW>&Aqkoco zr^y|U`dgC~`{Q;HsC%y6X7|<_SYXpkXZ1Ga}1s4`2TmH=S z5Y?NBB7TwuoSs{$qU%92!eN``U*l^ki+zI=w)#bYw3*7ZUwp1D8n*}9r9!;+O$Xm@ zwy(J}n9Q}E*1nxvRqQOQ9ozF*x}EPMOYpcuJ-q%%ExK3{u7QSmEVfk>K&;gy;Cj1a=q?Wj}BW1N7SQ)MaSgK{$kIYA(KX zL0E{~$Qsze5>dQeBF_Tmr;=w!FPbqV$~wD(jw;`I+1yusjHpDVP!|9Wr{G3~WNj&# z(k9EFAoSRp<-w))iGxql+-X)MzFO`-W-WKcbbdN(1byU7PsQe?2e%xTd)=Ec`EX_a zdcHigYHYiihGk(7c>-t^0%YDV^5fF5U``kqs3J;bzxoTxd@!ZsjqakouRZJ`;56F7 z&Z9Y4;(^1iK13f^;<(;~fWum63L5F8+N+7mnta({r~wLLckxAM>mM-KPMjTF*uR2> zhfytL_qAN{xSg-hCDhXdB8Pr1U0%9Ew4L06rUJse5ly_j+W z?iK;hd2b%iUWn}8p})ReUl4A6U%4QE>0NN&n`?S1%{kjtg_aiLbX3JJ1ZfVPKee() zD-mf88yNw2!&c}`I`}eYY&&8obZzo4%ZrAZs`k$74!%2&E44qjeRyx*)Ns)G+AW|` z2A6{Eat3g__#yDE>xQ-okR;c!AZXa08TZEEcXa&dTjfENeP#ViV=p32tQ;LnK1=tn{RZ z8Miwh8MoG@7(Rx`(3at!God@47Rjv1WRp=fmDXQ4~)d+EWh9GV?&~e5~CIUz=+n ziS8Cd5VmVzOAsa(l#cHd_2vVo4~6bpN~o<(4)`~Qp_VF77Q4Jn5w&WyE{zuyCoT38 zc?OwS%qcEZoDgt*tVt$1zJ04z>@l6wLH^R)Eg&6cZqzT=NH2%EX8o{&tI^eXlbmOw zsmPq_H4cV)M^=A2T(&$OoJeN1c=4q?kj(MQy@s_NgyIUag*ew;$c{Kx#8U5VZSP~A zR3Bd?TU3D%G9@#jT^fD%U~_x9IE@H;AbggSF*{m`C|j&9%zv#2U~%)B z{u+1Nkl-eCL=<9o4mZu;I!g=WA?a>%wcFa%Q~^=t ziGDoX=8J7zRJO$+qqi?1UDjHBvi{pevU*orG?CS-3kR^Citk}#I+%EeX7c7yAfJp^ zFrp~;d&a6qDPMOqAH`xPHbCG-Eao7Y_z8Kr(|ZQEb^$Ww1~|_EChtXFoIy{xw{3l` z6Hhl8VeNLW?%Ke;MBclpG1l@oEFYgI=k=FP1XG5}7gm$3p3^|)bx`T=h47-a-hGv` zEwd{dM4>z841O|HBDGb3JYhJVgEchKq@h>xs3~1*xtwL$LHp33qOMqUtsK(ZCvIz2RhWI$?BS zf?<30cEYWs`QR0juX8|LxgN#U8R=x+Hg^{Bo9!|S2*-(jA!~DQrwsGvXOnetxq;LP zv1+>q-GPbMD7;Fp%ax=m-AkZ~%!@Y=x&*M6Lwr`3fAC6lFE!vlOXQceGFYou{oh>s zdF=J##Rp8E8P(1wFB(dZa(i=p7K1N?GEP@_F?-E|;TpHvitIsB+&*QnG$sZah|u~- z?)zI?CyO3771+NbL-%8EY{cz9Ro%rsDwD9>!)F2uo3i~nJ=LE8MX7mVX3(73~pdoK-=L?T^1ilAaFZ>%;;OYsSQ zaSdpQVWRpjtm#&?xWWZg!57&}h#&v;g<$02DAn_QPYpb(b^!!=;?p(yjOhOA@=)j) z`(Czi>*7Vw?9s6wWj)$yip%h3#JS<4+g+4>s;||7%$9ItS|z!z0^+Q{8JXDV>{tbD z@dMr>&lbEBIjLUG=?GtKsN@Q=yD=VK6WestCnOeR4SFQCinrhbZ7hSfkY8{Iw5leCL zzo>SmL+8}wai*ywV&tH$4#)z+MoMc_%A1saEP29E9zFmC{Y!I1`nxVNaXF*r+D))W z1k>x1V-#7ghX^Eg&s=Tn=gsvu--*}-NGX(waugm$*0xG-z^IoAAF8JN0O#ss&)$`4 zi2BG5I^iDjq>?0?N&@*#b!_U#ll;#rv+Hvu{Qf&JP1Bb`Oe$HrRvZI%Q*RVZMRdu@ zL{HIq>_NM!6!t5T@?}CtDi^S-KG2xlU(b-A(DnHJltS>9a&g9mjR>kLozFW)OUc%!Rie1sY_IWpxEp^;8x z*JR9w_lw#86ij5?ak3s>%&t?Iv2y-mVY@u^^%$iKXlcIr-p5~&t{NG6eSTy|Zi_AP zSUi2+1ofj?gK$OAQ0hZ~&}cx@vLGoT)Sy{01BZOuf?PV@tFws(AHS%qqa&l7*GdBj zCDrpM&CDmBFl@?7{#(WY9UUn)CVar^qVeG2B4JN4HkQgBUBbn?d49==ST1ECq6}#i zdu`dX4d;_K5Ir6?{(iIZA`>9>{1s|i7C5#pN65&0S`VwuP2qP*f1fKQc@PLLI}co0 z-s7lQvtCd)#7^Bby_t^kYAMOu&hv1P(k20H4QZ)~r4A17nk!%<7k+>M*VcuMQ1SfA z1AXjztx%a1=E#z2ugZKJY&Fjg>9O#>HmBDu6R$&J5{uy-YC7uuELS!2Q0o)e3bGmg zjhVQQ8N!WN?lO1Odbqztv0CjazuZ6hF2BF>XkY3>M(f^I=}EucZ=*GgT&?UpRlL08 zT|XWhyn;QR(UpVT2x8W+>81FCj*?@@N8A_>CeFJOPD*_Oy@0TBpa4MCt-=f8`HfOF zLmaZ_i}Osn3>Ci55nub&9XG$v9d2-P*O0SgwDG;a*i!-X?a9^cQIUg(1)rXeV*7-* zSmm^HLfm)_>{!C-Vo&rMfTzUq9QLXGui$wExU-MxckrpCLg- zIM4gWdg0v^w3;zywYa|8dyp--SdE4wO_n~QBXEOt`q;Lz&=_F5?hy&dUy*I1TF)+{qXttD&c4#AzXi?nuO0ZviHI?u`)f7d z{k#%(RuL;jj**LCTb*>4N4ea-G=q&e^dMZkxe92K`=eoj?~du{jQcIcrlzK*q^JMU zT(iJwWBjk z4xvO_FS#e_(F3l=&PIn9B^a)Ay6hB`67;WFg}AS!v5VTD!N+Pl51?u%;DDeNUSEvK zVDACHQN_4fr}1Q%>W6orW+x+zuu;Wk2>&rORINk>kM{dcxG z1GE*Y1A^g|BJt^8sbE~6w=%7IoLFJLlcqb*fh$6t9nE%@3cla%P};og;M+*74>XA& zDNA7wJ!|r7Oij1slz-yqOocV7I8;>RdI(2IXeiTASW`pRRjEnlm^Q@!3E4F!*ftj6 z>>GBh5|k-ddt~5wpj00xOW4~!peXq^mGS%{P3sP*&2yLt6ieq!z^lZQ!o_KBq+4;c z_A-qG=wIu{X%0VXl~j#ffVHj=+SM!0mK*Os8Kt67=GW?wko00-7YH<{T;JE4WMu$C zLP*(fhL%kVX5;o3&}4bSm#XZ7v7*4k)r!C$2P zRN;I&jka*{PQ})Id64&6cbTtfVgcQjyms0_0F;H6H{aya_-=`OD36c}L4l2+^WooH zP$`_d?HjgDi!+o;m9=RIxgQHK+t1{Uy0a4QtA)5;m&*nSNOFfqD-O#J^yKckTl5KN z*r*J#b>aYOoBYt_Pl~LCYfR+1!X?E?Hvnrx3jy3-IZocZ%10Rs%gFE>$o3ksJOjd&yz-5J)!Hk}(-p}2ta&5@%JR1l7ww3!=peMY- znD&15F;4oo8*{TxjnNmLj?F6lJq|Y7)<=GujeB&x1cCX`Uz2LC0dsoQ_rF(|wfN`R zjqAy`1?E5{`&XxVzvO9mi(e%Q%{D!A8J2n>3?z|xF`$?X9f%>F@qM@;0DXJ(%_(48 zA~eVC>BXvUFvRZle8qIIvg_)9Q9{9JhP=`0PZ=@}GI2V>V0L@}QjDo^y~b*d3-E2J z{|~{ED0J1A3*uV#M1TtU@7qp^EolIx;sW`tZrdPqXi#)xT@HUARiWPCJjKjro`)<~ zTX2nmua?*n7SwzN>!uP0^@hY=P!g0ZPg&Sg9S=G8{WMHc6?{=1-Qzn4fa}xETtkL~ z5eCbYVhgojvTiiY+f*3e`9{w%1^w9;9jhu$)u|4p(M9D^u3m+pB z?0C8GzQ(PWH=9RfgSNIT4x(q288#zzrwy}6-;J{Z=C;)P*ljK%kqfWkGrIWZ)AE{C zRxRX@W;AqL4bCFyjX}%f?EF6VEIT%My@;;S-8w3x@F%YFW)~@T%Z*k$C&5np+zwC0 z-A!_!!_QGmM8kXOv_q)(wsfMQ=@z*g>{DeJ|y`d-PC5I_&v zL6VlLhJ5hBNX(mkH}P_NhbvQ0G>9FD^xlWP{Z!cY+C*@i+G6`W@f$bap(79t-NVoN z^!-dFau7!rog-s$JlEG$U31(-JbLHm?>O^Hz)QXi*#L~$* zHt`MWRGD6NUl8r=1?e+9hkB~DPt3DZa82m`ghY&Z+QC@3I($;?mUHYG<`6@(Acb7YD=;;zj@4mS+ zjwQ#vbbtGqFx))>@51LhJUG6y6^J`#K6YHM=a@nK<>Q!-=^LAk$rus?PTIwy`i95= zZ$GW~CR;S1150=(iLb}2^9vTgeUB1vWLHzM|ioi#V5E=x|E34q;g=*SC`avu)zjZna$?ng>zYc_G&`kO^ z*INTV3<_9bZQI=gNcyTCUt@p4n#OcL^+H=&C+|e)5w?7h4*lfZQP3hrDV6q*e#-T~ z^ivU>+!~_nj{AGoeTUDc4^e4uT&}C^$;#eCM)Cza|BCpoM+&1{n7nEu zs_C`F$n1eQ$emilB>}U)?}p(~8{})I0^{0NlEDbJ(muNki)iz^B7E=omCX-ir5M8( zv(ihJ_-_ecsGeJQo>|S8Z_M}2I2j(#IHR}(GL()|6&!wDSOj9g9_4HJA8}f&Ny)f| zIE!3W96T&fCHe?h&-bI04V}XLl$=RjoNR}DR9>2li4%CVZ5vMIcVyQBe@-G_wd>>) zL(Lns?S*J+o^AX?{Rk068DJHT1qwiOApw8yvjV&b&7n#V{~SSwzE^^D4)d`k@Yxb! zC3H(&lBz2fgL_R#6CRGumHDXN!LpGT$7!GtB`P^>D)EN#tc-264`W(J%*Hn(i_hAt zlwJ(t%_)KWnWpc^$5P+?r2k_uM^T!TxIrfR&a8%w-Dx-Zs%S)c+v<30xL9k8qII;f zE^DTO!DT9Vs*aGTXFD5ngoB7a_Kc2-Nr5QZ_NuT*N{q?LW~%VLiGjG4V&D0Z0=zOV zDZceie zj|%r;6nv3g?a@l6JfZB=_4}gNLo8QTl}HAV!@OZ)Y90NP6mt7b7s@+ga{GCEUS2&G zviR-e#mEWAGfnX5pzs5A9oz3!$ruj9(;>b!S?{1%D||CckQ zrVP5j8Z+P>c*KC@@#M!_T$UZvtZ0pcqK?YIj0(uv79?^vg}*mzg&2yr_ePpM=!<1d zb*0&DAFd^l|{BUp`YnC4A#ysVd!T z#SWq%49l4_-v@9M#k)CRsJ##TYJ2Ec+ynoBo3=u-8M@to*UPA$k?|n@<_C=&$8Sbv z)*;>mZHd@x2Zghfz9`o}R&i}e|b4?A@CJgjr_C@K3Tt4My!6_1=bmJ-g| zZhXE^lC*&<&u$#JyVc;BjE{1$n2y_ybFoBJvsdirDi|F)4LPlAlJ4$cN{HtS@^HYV}h`n zvegWgjv7$}(u$_Cw<7FIzAF(_)~U(SM4NqmiA*ucdSW-73xo=aD%|oXH%>&1cC$i8 zGv)ti0b~s=tT}Itma(f@v6nhq_ryB=sua&|oBJfn>HYaOm>tg9>sYj604vfpYa<=V zi`cRFJ=3U&&LSS@Wl(cPg+C_0KD{H~ziE~SX;wdSTD@Yz)B2SLv=}NMIblC?}^<}1u#E3NKvL;XTkc?TiPQh` zisA@IMo^UwOLdZDpHa3L)FtI({JZ@7`1$sS>e?$QX$z`U5LL(5v4tfF5QsCQD{dkb zCW{Qti3Bva?x~49(v$abY=TLXT!e;PY?rpweTl03Y`Nlu(3$`>-Zmwu z1Tkx^El7C4$k_Xfw~(mhbU!FlEG?!$f3!K4YR1O6&lkavO=fZRJEet-I7KU!{ed#$eL3-?rz-wL)lx#MfL4{!y*WRgwlULw9#~cMUNN zaF71axt?=B&$(VaFL=X;Vb9)c?X`ZtZ!PJ!&ot9&U(de0X1HbP`3YZ_YAKQ)Y z6fU@V7*9M{mrO?sLy6KUJZ^`SF;lV@Jxq_5naY&0c=HZqbTSE3Iyq$6zxLzfwnZ=f z(CtS-=J`8l8@GH}x*WNUB<5FELGtC*M~R;_+}|U^$4X#Iyd_xmRKKYrAa6m{sPM3F zE?yn`zS{PPaBqKkR-fCmQ>sTI={ob=G&tplgUkDA>It^49K5Q)q0c{>JQBYCPUQd4kInZ&Zi13d3$|36i$Uoc1$da-j@8J$+VAj=xTmYXu|N-?Qwh?(d#U%0fGn;{{@V zk^A9srUGmEcs{m~YTsSy`QreW3Pm?b=Ybq`v++@H%d`WNWJ#8$*(O|;U|TYvul$M2 zBauia?qg1?znu#MDLe|m_QN)g4e6#2Wq>rM5Ooa$;)kknfPPlt8$)(X8(43e&9@VXihS_eWU?YCQ&68Qjvyr7)%#@BiMZ7uc(4bpl!L0n@6N) z{jKnnirxaPwl&?xs*}*u0FPk1J4y#Li0tM#1I!d{H#=8W=kZH=2a)yyYX&sO6VXHrYK3l6-B~; zU)8z#WAKzr>NY?kNpG#a2sltQXuCCUwtF@@O^)v{^$~bIo)pAFY%E@nl1Crz||Dz984)WVQ-g!`moZ1*4YM$nt4!5 z3v8^*kRhSUYHdiA_q@J?PAj)}9T8?=ojgtcP|q+zrrx7ZwuYJQoojGz(2d)@om90}d+!FfZ== zw8z}dpx$nLg2&mhyrAQQ?2hcW-!K+;_x(KU(lW#GslhKa3Y)cu6uZA9UudgZL+u$T zSo#30Zx?Z@ja}X{Xh#fF$NXc;0Ad99F2h<2eA$Hfe3tHdt1BRfvrnZc%F4=4hP$=x z-F>scdr%kTD!|lc!sY45o^-+bTcZGP`!`g&!@XYLkJIO^g_o$2nEf7e0{@yaHg01S za$h;f8n*`jbvPjX^%KEsZ18&`Y??0AjWf}a>nKXIKa=8?F`E1z4d@@=&nFljOW7X6 zti#h(h((zIrdCzXc#9c+g{N4h+MjnDyZq;B1b2^Eo$rSZF3|AR(`Ra_rOcxGlZ}z>=~yg-)LNMs5Z&! zZ4w7>58z%X}-uW5y;c9k+#;{OxyfOXd*TWqN8+{cFnGnZ|Eyn;1$2T_51r3gL z@q53!{i1Vw9#3O?t3aPt^UT)vZfvDe6^BB5F&*Q2ZJ!aJz|XGOa4&L)QpYkTJUY%{ z$cq{~g#y`*w*8?U7xc`Y!i5x2sUPzu1g!i2s!-XTYg1y zYke-arR_wctd8RGDt_NMUGtn=$24Pj6+qV;5nil?f3c0X>NJ1W+kc(Qw$o3LBv>ub zkB?D5_!YdSYB~h_c`P@)8$nY^pf1GerzM{HITimohKVtYhcEpk{+A6zorNDuz#CO` zp&)jAT8vd#=BXjC2#!3V1 zrmN?44F=2gXYm643r-gnn?%A+I+ppYL%oQ)++o8!X6tzTgT;6?#@Hm_D>It*N3y+-T8|uPhV( zzgPbP)mMJoO(WRh7NhT-z%e~EEC|mOC|5re8E@Qm_Oq9oh73y1BrT8av~=L#pA!S~ zlroxv_0)DZby@=CYH?e=w(-UDK*QQDxI7rBXTx1^O=&eI9vRnzWkcO=dkURN_xCal z0|Dm@n2Xle*6Quv8SP>x7K6Qdk!l{MUs(^-+KYAR3S}(`d_}~*akzEh&?xn4ZELa~ z*1IL~mBu6Tl_3WNt9i}1fuxLxt?xs#?%B6(`rWaKQhCN4a=ETYToZ^?e~N2V4f(gk zOa)1wy#{X^Doa`z`Aa_#cTF>c89Ln9C|eOw^wIb6^wxS6(_*cZHkzC_|HW^akM&U<#C*+&)1tftz1 zu@-ggh98kDl4-0@ByqV?Sli}W|7k}8GgwRpNI(DPj+4LSVO#%3Etk{lUr`p4%crrQ zYTculE+G;|k|g)nLkfR1`R?7aj+(qD!E#e~3yqZ#V#l@TjVpaMCTWEER=*^xKsah5 zc_*_lWxVSATdY)zZ-$6imH3eL*g2WO;6cD22B>k5>I5)|lfk zNK^hoS>R9{PsR_ES%>lNH1};l3!gwq^7dfJd4TH~((}yensu^v%WpehWJSjPvtGB6 z@DA*ND^TjdLMcU-tJ_ghH&r!iGSEFUcc8J1lI1hJ7h#TD-%x5Vhvu5T>gJK#kIW=A zeq`g$c#Jo$jAo|$M&0nLB^nFe_HP>oPqRy-4{(oW7A~HLR6n#g{nMaCO+%sn#a2w5i z7Q)ZErBFOZG9xZnB#!vn%di8rNvz}tTZT$?MTea26G355K!n4rUVmf4~*;0GB4kBr^2M( zS~dj<0tVNzC2BPiQ)vemt|L|FefL>6_9EroVl#{e-o$LD)o=x-E}A;Y4DA+n?gUe{ z@8uOVe%Ew!vfn&+{|He!jeGoC2}!nHG);)pV2dC&9YolqerYN2PY8Xeuj3DYQNX2g zXziVAH(H`fWG$UfgT;|ug#B|W;jBb{d#xAd>O`MmzDY=7$P#fdrmR%NzQ#@h&ps$5 zrljcv^?fX=uPRBk2+Qm^H64RM2y1C8OPyDr9PvmjIOq6oP9f&C=4`c>20CxV93r`E z%jkkto2>XwPtdGSKPzU{@AGx}eR6UOg?A^^j5gXX>Zs~DU6u5DA(q$JWgM56NB5$zh4@o=DmhID{!D5uh_Ayya`}+v8nX1PN{3Hx+-; zYLuWOYFW3}B4od^oN;kbN#b!m&nI|wrNzW}6*X_O`sm>X>X4D?xm+r~ai`goYaJ+k z_c}^C0ElrqI=afjYL#PcChR=$j*=#I0rsi*172V!C0G2PY85_lA1qkKlgHf;?Qg@+ zr7AZ}4YaxH5~_DK>%zVwquAvfy)Ud3x`~CS^nFY!NNrk(i_ZIY5(y!LvHT7?pQgl2 za3r~dR(!tVnI{xl4j_M7U!!71Vvnq^FsSzbZcAn!3^^2ZnJAd;IZRbv%tj!%IlRAA zmrz>5&9OM1uG*-;9ja4zI7tgL7cx+pN5E6TI}5Dva7C#vOg6}7*u%lB@1)Z#HXCMt zSjjS$NCWt9iSphW~j7vjZ_E<<$4%C28qZ7S^;)02f?O8 zdwfS1S^8%@dYg&2~k~A1)<2QT`0UOBm2B z6tsW3wHa3>@fQ>Izse)V#<%VZMKAcrS-cS;M)mcdIL<%z`p>)?GQ`VXrf-VWbGH7+ zbdQwH^@iL)g!cTOhU_)yCGAp0mJJ|9vq{QF+^ zx{^Dw%`^3t$%Ek8J$z;=Uv|nPv8{{-vBY>6VC{Cyzq@4lsZ%T%YK+PpWGw#av(8bR zzPkv~nTMI8w`xicSe{$pat0txD0Ph2T42gJl~3@^hh_^#d?)59jIH_Gk-i4;(yCyE z7@A9*3I|Pmh+#s^FjN zQ6dbEBQYs{HebT!^JW%$hoH?(@_}D}hW@o-8@Bzlfm3&s{?(+4jz~$9hfqW>VqwDn zU{fzC5oAaTMu>}71~t{`X@HXV*WUDK~N9zB>B+G}-iv^4p-U_;q2)oVU%=TzV#T5u)O{r}c*<=YJv< z;0<*ze&t#bvwkPm3u|8TluI6^S|gIaSg$`7^h?Ue$j9dtbW!?$oAy7|-QVBB-$&k8 z_Z(!QvW0eO^Vab&oWCOtqMPXaS6Bpmnw3e35G?za>O`|WAUJ9oNo9MDG8saGant@j z-amivx_r+_ATpiw$BBFIvjy|Ubk`4NSdyL2&9xn9&GdsDq486%L0a1?K;Sp6DV7}t#5@>G@ml)r#N5RPGn97 zWKVvZWTCD4_jT26{Zpg>9&dHfO{~AxM2YLX(}7-Xs!X?ESd(P=2q^i{3lqyd$P>df zna&mIAd42TDz3d2I6&e-O#`CBz%Ksxvj+ME7m)2&0HxJ!4cuz5@^hu&wuxl{?5bt) znli{oYG_UsQDULh-Ev4(!133az)1zo;Tx^Pv$|HqoU1*t-Y&@@evGx;3P%Dhr{Hq0 z6fbvNo%hF0kheuT@A(C%)Q{eoX|X|CuJFUY~fuK3c#nPuUWk z#^#y24XTHh+n1A<{`lcy&g)n0M1(hw-R&b8AX9atOK32g?+C36HS>rpAw1q;YOBOZ zxuO~2-_)a{HQaHaKnPq~5$Xi12ww9GE@-?9BQ7M-vYJB4AALwVb?cpYm?AfKRI99^ zj3)Q<%-kt{pSK`27XC6UyzkcBx%Swa&H~Bk-Ph%&iMpyZ3a5iJM)7E`v`=;Uny$8A z19gHZv$c5S_m4O8Fih%MC$khlm9o=YHVfj}G~Zpx1dQf6lqJVwrY>W9%eih|^T}Ggud@qMA1W}WhR(Gxq%1>#nem==LH_Oi z)f}gWW|D70NF=hG_*#_&N$pjFk<)ZTR;NGOl#oe0%P$k?2&hiP=Gc$5{#`H?-qOST z|J(yaGAkez(!^`h_H0DT>MjNCOUNLJW?L4UxB)un#Gc}~xP-wK&%~Nqgk#|I`V_&) zVu_+}J-B{BG#4b-VRDyTDwC4fj>+8`|20?TGNuM;}|MT`EF^Om`)fd)Ybj~iaC5M_n2M+0s z8ry%zXrk4K(G+#Q;UJo8^%#+Satb)ral9CFtq)PZ+^pqa5CrI`BK$z?K;4$~DywZI zRYf44t1x}VwStI9RmNejeKBe^Xaos%+)!4MlsX*hPa-QA(jDGm-)&8;d><2MErP(* zud^4|{KTESRrq&=;c#E|%E|SnBk!2F%f{9<|IuQw`OAfLtg%RNI_coY#@o6o?y{)9 zlf1F{syLTB$gSXqaEOT}f&?=ryX4Q8*-OhyA-_Uo-;<&=ks&;v+ISn2Lnnl%nl9?e zoIE@FzGn>{Gvu_Tiy66$p!IGR9U-@-rI+ z)*qBNY)G;~EecCBYjaTsHqXBuuj1Bs!!z z^zL6ZC4V~dQAB_5vM=dwgi%YwQ`qxK`!k`t4k_!8-v6?-G)w(^shB`xb`Vl9)BjE( zp@V^!0x~vpV5U?M8BhMn2DLCh%d|8K;`X#KzaRtO5f!EcGh2A)UuB!(!zD_$8-^Ig*a8X)-aB~f~bvMXc-^gFYG@9lX&gpOJBdzP*EV8 z>3L?F8^G_T6%b5sUcH{;rRJIRA@` z>}0Z(ON%p^nSbvLU8iyo!(px72oH(6M)W&)%JjLq^DX7LBM5gR;?sW=V`48ItgBH| z+0HYTxQfX%`!OiPFPFz85(bOv*Hki=2qVNbh_f?p2}bo+9AVHz2x=HW?LS|Z&^ z#~c5>4UVHC&-f5Tsjl07HWClG{!tWWur^#)Za=N&=;SmHyG&>XDr3p^YP4?D)wcp4 z4)5KHR-J_#)AS@pF%fe5Jvk9%IECZ^aVO_cfa#-!++SRM{T00OdFlt8 zF9|EY5+%wKIYU)3Kgw*}MX>Fj%j{>`Ehe}AdSYMShzf1KaNsVoOi6eWcN@+YZUvw@ zJry*wn*E^uw-$icgmuQ_hW+Hgs(yQ&N29uecvNreR^d!dD-!lpQ+5jQdVm)s8+)1w zVEPv&)V@QdwBuY{q!?j=OHA2~=s6%1Kod_{Rx-R!IT(El!eMkgczMmv6jn$zO|g~& zrCb5Uftz#Eas)dmokHA z-&cp(Y1lvTGLOwoNGpUPpKf6QN*1QUZ~TVD(Ht*RbMRJx#shucM_4gTbf!;zXb#rD;WX_v&w4HXGn&qrxzw{=}B2p;mw!9WvH~ z9n*R%mK*#(3zEB62DkPfI7op;BMXm763+MYLOd+`L_`ZaCI}z4P?&U+mIaS2?=4&1 zA1SVamfVN~sIg2A7DK+SvU6G;Hl8Lrsq*uG`&s27KpU8gJumJ|xSlrzs#}B0q@JWFcwaMdq63v87?w~fq`*yk`Ac}@m+xQ)yN!R*tI9Hh@ zAn17-8T5yNV0Xh9Mdu83_RfrCTSuJP*@;eR3ivVl`D*VQUB0 zk*A<1H!3tJ+V_+hIH!4sBm>^Qjh8$1#pX)Bxh7pzz?$sEE%v73GdnSz5fq3-T!k3@ zI=!Npznz)??EmGlvHDfR{oRem)ugARX1KxNFO>a7M~pw@Lh?05yzKxrkJ~H8m5iRB z&YceQPhTdm)PU`^6xL5#a)7=&f-5K{<%9mN!eNE&AtaBcAznau&IbC8nXL`Oi6{g!WwRO>DxcHFt9+3Zn(j1U)Tk&y{WQN^PaOlDSl7>mU_% z!7@0{R7s$|47%}M>P})F{6>aV9^f#l_UByq@hyfO7SkV7V>s+eOpk1k)4kt+?_mYd zw`lLp&|X}td&b7nj5K6L2UVa|rH6K%aGsx&?Y~dc>8Za&_vRG}XUBRy_Jw4iQ??`m z=oZIXm=cxCl2bYPJDUAh^c$b$#Ll*Wh;%nxCl3M~J-}@G^SlJ%Srx}^PUg6}UPWN& zJ`Yv_6yNCfEqRLDsliCCxo7H3L?2g#(;(>bWlrjF3D)Xp5k!mddentCRwF=|KjobM zmAmbvbuU_)fRq>$cv|gADCDmej znFvWw==T7)<90Lpc8*X(${!b6Xbi@kDV(tbC`?(`AG|qumWC6W^Mw!UkDGb;_L zWkOuExvF3N?k;l3d_Dev&hE|E+&oDHyVcZmfmrQcoHeDGOADs-bDZp|9wG+-8d3AO zlN76-Iz@%lFE^Gq=Zp780p!U&UKL^5_LI*C{I)@3R#cMk+5YshH_y`=x8YfC&E`$C z>e4qhMr1Oy#(ZP!YPA6y&37@wQv{ml0bd^fD-Se?VgA39I&Wv4Lbp$`;(=!uRxbBQ zt50f^Zgs%NJ7PcW)%J@~k}Vjjr_YN5fYp$7(HA1YKED$J9P+lQiXbF#lwAnd>tdi) zgA{LF4=X6^jhi)2Cykm@+Hx0%9pSmT_Z7IwKPpX@DVE;7-5yZ);cNw zj^7%Ax>c_ZIzbJ|N&xaO{%K|E}eGwl}{vFvBfLXu#jqKC7y2))s5d{5pH z^LaK~?To+AZNi@B%F5ot+7D($J9wCP=6J8dxTZXEWOU#S_re51Hb+)x$YfEw@l3X| zthu+m;2vw82Tf{#yZZCGISdss4SMs=19{OGEXgs6nj|BzL~djz4Ds4B+q)>cwIUS( zp$`t&MImzn&qf*+heoW09<4dLU0H5~^^HC{BFV^bPT}n<789#v#3z43+&<}Cnw3Sk zN{-i!`i7jKEb^lI_<+yrnYD*tQg=~JemucMR0&Id0l0UE|3%ye;UNO%{CDc>unFzX^(!^bD205y z1DBSzc;(1Z0QV_g?cDTQZ=Tgkt4$|%JS;LIA#CcV^(R(9s+iXU4H|#w&JIVjw@2r4 zGgMTF0Z`GO-ao-(XX@OO(5y-P{z+(fHta7e=Wq2dR!;74J9`j48VHQsRMyfe&E*Fp z%ga+~610Cy3UTLyQ3k+_nCVe9iy1A?0yG~j=^638yU|iSzntz7(qt_5X(cRortp2x zXVxlG;=8%v(OpIPzF8kjr0t3ISz#1!kRO zo@fkR#0wYa`SJkP$>ZUL^GHk7>F#ciDgwjp<5*kKElIZM+=x(Z0(D6W=90vCK`eh6C81|Ch&|({UiBzD6fr8BVp9me*A4rnU za#;KV1dCVd4%12)pFn?k$M;5^0Au4IUJq}*De?8{w@ubj^>9)?kJ}HW$pSJHyo{B# zHVOqw#Js2CaA}tNOZ93_PZ%9x#4WL=ge`BJ$^@I3iG|cl#kiiqwWJr?sVf&vtiDNZ zUHY%SeV7&z^o&0pBj*NR6<}gl>qe&!ZWjC5K6i*>fbE>Ro-0)i2J^oo55YfExquAu z)E^B?e1&bsd0(zSCEh$fSBq=-!~}X_)bm3&$(4}`+4yylMaNF~XT>T|9*)q*uGnulC8BQik9j%pb0>UX91!Ln6kO%KMxk92`u`zPw(4gnuSl z9S~;20!FNR5~e(QDx))hyo-Q9G1Wkp`P$^Z4;$j1d4;jK_j^;F5jG7(_lm+F%UCc) zA5yTgk)8YH4acjDXIr7uaduhJ$m}ty`TW(wmUQF4FwYHM8cgM~IsJ<~?c53U7-Ldv z7Wm%R0`iCmOW@o+<(bWB_j#1i)Dgbh9ouz4R>8x4@p298+b_jW#d>(`wyB*s$t8k5 z>#h3KTZfE^YGnZRB1q9m=6|3N#e-+KcUe!2!po_+wv|vI}5&xm>;tMlLT)AI8fAjSyvj*q#_XU0>x{ z>iBhEx^Z$xjeMP#(@jAU?1a2E~Pggrf)t2!rEInR{ zL$9d4(cK?1$4T9`c%WA4DYtPu5Rz9%7acZTbHz8=S@$Z}l5O7c<>eX%Y3p-08(=)6c&i8@jpxc8{>|lko}rPRpbV%X?S~r3wvE>e z_FMZipufA%SI})}M~s9+Zw!uxTc?%v(ju7~>B#8YSv@Pr;fjar|4kXE|50`!m4%RU zAFX_N-$gP$#r5W+A3f!pn9=azHwRSgcttDiu0~V}H6ezI77{(;HtTXN!3u{x@}xp7 znqyq69ic1s(dQMCUSrpIJg+tn61C$c{fQT1q`HqNITR^RA?|8+=9tfj*=zDkkeC9T zQG)hv8w^)-EdM2OE!7hLLmnFehThqQAqYU6Z7K9)9>$(^Y1#G!$AwoA1N%^^?EO=m zi}nLmB6Ug0nNg#VIXTB>0#hCX(wIPYG=sY>Jq1s&Xwa$;;uF-9pCoN~`_RSxi!56r z)&fB8GmpGHaz55xRRs{>J;Ea=k}>sE{%o!N{6GWMR9EQm*)J`s8tAIf7!+KYiC-wQ-Vs*dMQg${>n`PO0&JW|FRC1LoLE9CoN%P}zA6Hb6dRia1EoK#+ocV8H$cY%oZ7z1 z18w>A-&Kx;B)t2BLL}I<#|IAdLoM>gDc&-*gh7g=JAd;eo^?s5C*Hh&0xoy2+9eKR zn(giOvP~<99IC(kPXKOaS-aEgPrB%oS1wo#UQ0cr9+LGJ3*_$jCXU)kNF)~916eA+O}v8{u`qg{zxo&fs~C zU-q;9LD~z|*b0X4oA7}H@%j!K+)?Ywc3Fobr(bKTh$HCzz%F6_0hYu*_vBx>|Eqx4 zc8In~b967o)>LIpz;&K0$2CN_I&et2eFp7E(59WS^CYo%(E1kWj!27SYAhbbBIkER zavug>$o%?g$M#M5d+*NdA(pcvpJa{ZGn*NCV5-Eaa(>1WlRzqpaJ10I`HOzQ>4}1e z&0Uz_<*Y8TI7PwDYh42@@FvIm`)`U3s(mVQa8)G6%zN9@mY_g8 zmaH#L-v;g}awJwJaU0&QVO78)53fIqT0lI zm0tj6E(9*FTMo|Wp42Wt3hF0OrKkFL1QQT4ZFuMW{Wy>it+a4$!eLE2`D3>T3a|^x z+$VfH`0mcOB#iNdsh6K8*)S|*vefQlRV~@!K&(+~O5>&QI;df@-sqYmb_kY8mK=`W zl>dNw`KIS%K7^6sq(dQzUu~2zV@Ur5@QUzZOvy5Q5P~OL4#hizvuqp`{3cPaapY}) zlxlwtIe;^v2!pLio1SdO`Wq|KygqIFIYvguJOIU$bLBc8Jd)~%y>YL%N%aMc3vB~S z3)x=8+4Wxu)rXI%j~ixejN;qdN$3TF3a#OB7eR!mUrZTxOI>rf=mRZA=`kM(CcADA zUZ)7!Qt1KWe?HQXWall8AtKbpA6O%fJoD0fS7N!G%3tA2m-cD6k#_~ihIR-<+3OG4 z&VFIr6I!?iWn23YZv1#48JzNcsj=BpO)&oZ-8I8VOVyha+E4~BCj#HX=Z~!1qbJYQ zRXMCxUifq%xDoy%a$XgPJ<6Y4^%|wy>D*^=f;!=N9K{tmoapue5?J&@n9VsuR_2n% zv2^<1D__R6USQ~5oW+93SRdLOwoS;rn{Xnu0Wo|yne(_lp|P8l6U8=PIau1{q{N=y&%26;oeZq2DnQ zTwZi|x!)+!Qh=I|BWW`w1Y7lObV1awPFs`vK*BvX3ave#E$5+k=%v7|!5u#KUgB~j zX1Jv{5b6zIX!Z2ke=pH2Z9lCyp#gyKP{XpOKriXqFWZRTl<`k*F3W<&lvzZR1j80f zL8&3{@a$D9_B#u_o8MBn{lwDsi+iewUyZ5*d0#*E-JRM!KufWrfj?*6#!y5>4o1Im zrP_gK9XA`$tl|kVlZYI;pe2;%?UfF$#J@=xiMSg=oyL?J-$l*te&){5>-FS;9Bq}P z(7u68`7J?@toD}hwzPb|Wgvo$4h?Sd6fQZNB3KWp<}R|g&>elqoKu`nA0wOWPP-GF zGPcJvSo9|d;(E7X=s=9U|5SnVj{iM2?!V#cw63-!+M(VhKTGw@Snow26fx(` zCpp+AXz^GpoR}08EYcHMfMWlbBz(8ehLxGD^dWJSC8vtu=EA-a$_$0l`jCiQ>}0)Gv5X;zJf8Wr)eUaarj!RK+LV{K;Til zzSz&rPe$jF@x*W82dBK5y`6)~;&Op<^uu0Q!K-YfTXm2du_D2UYG zRxi{uflJo^h|Jf+k7;f6nRhYI44+Mj3pKn_N_?8P8&9G7UUAhD#%GtVAge6AI+Whl zIcOEdtMqfTb8L73@HqdiyTEJ^G?55ayYICOw=~-0b0&=m$T2{8e(eo(_rjiBy?b^2 zTM7;}^ZrCfg){38LzsXqQwkzSxWID5+~WPKe{t~eFVV?Ot#rjBl%1Z*~WrP-P| z*nVhefP4_qagR?GL8LP8ry}kNYz&44)W;s(Ux;ertiQo` z#x8@iB)3LLOvFqU4}{zsq>ZGts)W{eZ%zVNKCcV_;+Dw#`j^=fQ(?l*x;PS=GEGxk zLx$7gE86>uZoN~`=tS@)Zo0kYn1|BWY9rRwsYJFTuwWSrkH;f}+t;|hNrt=L_W}-$ zfZg*Sc^+dV&F{sFK<%4=@gHwe;(YsKMe;VapZ#B)0Jz=RS_bO_5w`rvcZ$U;vSb`z zL&+TF^sQe{-|yZgfzbV ztwE)cssg$#+p3MvN>Zbdt&4h7@|?Jsg3gipVeYj zJGr2bjS^yKS;=Njy6wgzBK_aGuaL!+r-LCQd)-TLg209aZ5NI9Zt%y;nIEg)s_h zCY)Kg+zOE;Uq~|!L0;M});nY1Fa>s9({SB7w*6P}|8^^u8r?c#{f!@pP3;n4^9i1V z#dAbZZ}pCEzmi^-4DelqD9ZfIa1jbPsXt*;^GLbmGU`AnZV|$!f^0E+{X#Z7815i#SJZ39H2P_isqYjuhOb(k4W$Jq|_Hepwq=D&?0iF_vhVoLSib6 zD1@vkzA%61HC9qGxS0O-gWNL}n?005_pjJ`!+6{Kp+Unt58UBMuckCKu7gqYR1qEI zN1AJrE9!{cFQQ%&gQHWU^bnV3R~UfYen)InDAq;`HnoMgq^G7e#~^>iFf(tERqyp z40?`Y`Cox%(Y<5Tkl**2F|06FKh)FR?0&+5VJyLc=FhYQOVAf_?eX{R>aC%ClQRZo z#S&7)L$|%ZFJL(HsX_*CX5w{GY`g&@d&Lr?MCg()ja)j@zqCotraW~^)R{#;w970B za3olkCFS_jppi0EhprXs2_yurE`L_un3qj=0F-I+u)@aWcoBS{KeT;B_*X|#dzAU& zIFUoU{1@l8S2&ChwL;hZ+^tty0vouEh@gAcJ$X!PSq{qcrn9e?TRG0f)WQdE5NgiR zGx#EsTGZLC4m4)CbDh@HCX=}G(wn1LA`elSpOUKzIi5yW(t0ISm!Bv=%MDd#qsCa2 z2+xs_=5eKK(C9SdR3ENs4Qqn)GhKc(PWcqns4;2QHM%$y)qZ09F7u+=(qt9;t+DUX zp)7mSQ0vkv1?ua!k*IX_-suq%3PNbOx8grQc5g{ zA%jCBHEApZvP`3{?9KrR#-gOH=(KrQGZl{~=xR2T2x_GJHlYXJu&~zAsDx81WQ})( zE@@y-3Fq79fmW0pvI1C3QfE`Iv_)2weO4TUS>)oWBP$I@c-%BU`~V<2S29h>+=hfIHWndC$|t|T$N`?t;_G)04WZJ)xZ`qsK_Qd84pb(W**PL;d+ zbH>ZJebLoyRmOj2!81R}Zukjf$a-mOh-cixzEmY$9Ge~?WLC>8yegbyRQZXzerQ{* zx7BxFwsZ9b80XmaKx>#|o|Z0^*C5I9HUC;dl4Mh&pjz=bSlGV~uWTJ;HTberrx#xW zKSPisBdLMn%-aTQ5Wd4{g=n-?I;o0v&*`PNe^n2o>aBk6WyYeGe?YP10}_mJ&bUzP zepD-shBv{jJMRy48xtAHS6$6dv$L|jdw)mV-GWV!=4BWA3C?DSaQfJ64b=5dKTMtN zPi%W1@b106;xv{qd&k!A4=(-ba#;6e9R-bt%yF5-(6HjD1y$%McbP2o0KpO3O5nIT zf86YRUgqx5gr%XNXvA&y=taB>@e1GA_^1Lw(I>V?Fw0ZDH~}$W?cbfp_kL;amLz<2 z{GhXBA54i8(YP3wjMdA@SW^!fkbG&~i^W~DK%1piYvRIa10HK8UQ@HiNwE%Sx zFrZjt0veTJ(XF%DHGh-^lKfxU*Kg;S>n z_lA4RoJx;6I-GF1ieqBDF3PV)>7YwgL=X*#cpn-|zB7B39`D9U{5=$8&7P%}TA+h~9i?Sbskd~g@&XgC)?R19L{I$WmCoOUXkC=-Z!SjX4dF4By>5NaE z2fV4ui+p@q*^LaJAIDh3r`1v=Ac)TXGs6_h9q)T~k^~S3-^3>bvhJphGT&&A#3=AS5H{=LChn>Vvu_>_{J`tS=I* z4NeebmbPg2ef6CofkBVE8KUCHj>3g6Nzc9QRg28c{8{%sg~6>V;jo9XO~{Xn;aN~Z zIXmlQa9*kZ@-T4A_9OiL#@4`mZ79}*na-2k(9E4tfy@)vSSrW+LUfksJLe0$FhB9{ zn_Sc9l@3TwIxBm5N*s5*yT1HAb<`JS5*+y!ljU-SX0B$3B9k9Q1+1&G^0vwBCaR7L zggLvMPa+m2Q}A`}0(DI6l5r#$0FBaycWFsSg835di}@j*_u(pll@8qW7WQ-zoYYiL zd7N2obF;$@(iLqB-YfO%Y-=!?Ocjd;(df=^eDPGGHNapqy3}lyQOo+C-N4K{XHK!W z^n{c^$4SPJ`s(d6LHEuy+?xEY5${xhY=~=b+)6t0=kEq%`{AV{v7(5HPRH*)@I9=; zjGeN>oVW?y9S-Vo5moKxp1l6g=K^XD7-c8~0>BV@vWQ zO!v^g{Uh@AJoMs~iw;=cGstU5S~cY~us9w)8levoEu^5O33zeyv}A?Z6D{>q6OySG zwqcf35_dJj36+@tq+E;u&83fRj_O#DGqoIGI+|~Jnw`*3!xKOVz;gys`6vwDATya2 z#6>fcflP8eKWRE|yDc{NLm~rw2Ru#moam2~zYH13TAmJ^R#dDsfF5F8I8})(_AX|3 zPCf3gfxy0R4-g~rJsL8qZ5>;N@cOVLZ$KP)c_IQ(@-3#!JWF9#!t*mOOa#M8)-4R& zc?zoDrci9_Tey*XFKcdcMo3^$Qej=dzwk2WwZJVpRJn79K`&y^#o0kIwnw= zQyn;%CErZofM7kh~BVk50uBrU}DMR!Lf!o1I6wi#y24@iJK%PR5O6r z=QSH=2>uQ{(_eISIo4oQ&H1?^^#_M{Qluv z?>0?7q`8@AfoWRMhP?Y&jyv9zXVTcdd?~RL66RqoW%CP(k%L4zh)3;`!mp>@Z#Zp+ z__1Ii5oepMCAnA9C8Q@Yge)|?Yitfv%Hy7dV12>;v1+8fSj#H$ao4zZR>Ts#mq1~4 z=QU5Wz&A-Q;WIZ{&$!5XENdh>{OER9I8>dIn)(2;*{dx`%()>#JW5VX=3^MEz;cey5FIqPy_d)3s==!*Xz{WZX!vg?i&y$*8_) z$%Mn?Ii4#!qY+)v1P=QPqC^7Zx?r#sf%r!S6U0=vs5IpkwNL$Thyfw1JUEjEH{ja9 zi)?hF@F$vz`w7nvjcCn`$_1y>XTTpz`XEa> zD$W@j@6^n)303jzgs$+hLGZ+1%WKMILK&@OkhJ7sV9KUq}7wmh)}U&CVZ0O_4E3e7#69xRp3 zYN+qP|6JGPCN z#{Z0S?mZXp(|cp&Q?Ro4TD9v}v*xT>H~Qc7r#^2lDOf#Gn3tD_^?HD zT%1HE*=;|rJI}i|q%KYU7{KNqWNk>Zo3jE#S=I+ zO2!c6-%i+=IF0aAAZC386eeG*Wv+AN2@}OLKqI$s!iNFK=f=eGJ19UdG{sep9028^ zA+f4Jz?w-E_Z~c{&6$O6ZnWckUR;@u-k}Omu{*0iscm`@51k&(8=w+sc)?XFJrl!x9sNgxF4ioMYIkaTpaZT2FdyL{L%rPbr~dYNTT#lhg5*LRUa$Pra;e&X$m{ zc|Yf$Sep*lO{`tSG~hBx*4o~kBVV^!vD|ilv^d9Eo*m|zTc9G6dkCCLhsIpNwGJ*96q~* znm9V+yeTUCy>DZEIjByct>q|9UlXaUznkxWubI-?Il>%V4cRc)vD{6WwO>@4+&oXA z$blcDV2yh=qknJi#9+hUI7^^3G?}6jZ$HfMuc><9C7U*pYG`H_hwFq#fIXd7ta}dX z_#R64C(a40^{!8C^k{X3u`4d(7!s>dqBExaS5$58Pn@QUZN_D^n5!v&xZ+oMt~RE{9-f!cFG#j{JR9Mls`L~_4JwJ^wAWj$g0 z{V51I(~rR($&h8-u(I|qJ|*!;Q?6$>aQC53qi(-?ts}Z3cLybMRhw_;ZG4cgKHGfzy|*@^<9m<2Utz}><*Dsg0A1CIxvOH8dhG7X9Z7l4RrCSR`Kvj# z%5uB+a(Q(`lvGEIh+F5)1<45_>BGyYyKb`tbm_aN1-yu#5BOx^6At;)V8rkF%>aM| zq1-Z}`M5zHwxgrPloZmY>UIP?@C-rK)-qy?NgYfgTh)<=lW7uBBl zSgMV=Tf>!NwacVRWlJJM$>={VaEmVFd)HThBCA}A!s5L;d!HU6Yt72&%ZcQ86eS2b^j2ar2*aaG`^fX8 zT@zpBc%n=nSED(I+DZIiDP>w9P7{F{cCN*bgM70(CRS%>h2iZmi{;&jtdck%)&Cji z0afj{+ByLKA@_6IeOm&*oKGF>kGt5ytriAl;ft{$DB*`8`RV=U>)L7$8tUVrY%&+d%+I5tC zSp!vm-)x{@q%2DSAuUkTeI|m<&NtSJ%Gbx~+ATILo4$RY}>G?A$rj;s4NG5lVP{`e3a= z$rEpnG{1TSYo6oCboO{>AZeBOG7`KJQ5(d^z`mtHuJJnwJrWk1q$HM&gft6NqFRPu zTHWWW!Vok_u2Kom0LRCteCOv$hmJ!@V_k8IadqpO4b#iMa1RExVV`&CX?3qxaQTvCCFiT_k5t^aNbEZ_avdWUNU*$wTWtY)(^1Zh# zAkZ@OYN#zCO`P$f!{>?&3>qM0DF)6;B17m2!ly3|yhP>WNj-eg1R^?vml>H@5}Vj2 zW8FgvW9zo)p3O~BJ8O>?wg$GM^>=A#?ts-N$2Tq`OJNTF-nwMP6BledUO)D=i5Lsly)yGknT-caePActqyo-nNl}guHuyf#0ZIy#-_1~a5gngX@6yw_6 z39rHGGc~@bwnkeUqnB9imfI^KoCf`s` zb$TS8l7WTJD}I{z`CXd1jXdf3+Q1UciKY@M8Ocd7>MGi&7nGJ_W@Ae`=VFpP|^sdx})An_mV1o!s|5+z*Rw9Ng z{)JbrN*ii|QY>@(0b$PU5bQ&l8_CjFpkU&89yE})5`|m3qHgxjy%>EnYRwul7IDf4 zr>}RK)!>AtkRyQ=y^aPSz~_`Ib@JV-!rsj0r(e`i*<#%BHtEq+A>hAEQA=a?`h13{ z^d8UPpleaz=|)x(_&jehR)Dwmv|u@Kd$0w;h|ki2d`G#PI==i7bM!MgZyu(@vv=Bu zAbjv6uI1n8Zr;jB`Ad13IlFE`=IjzGkZUQU3%&HH){59o%{|Ll7w5Y{U_@QUU$;6J zbKrNgCpcss&QO|6nd<}qyx_#=^M;jA)RF2F*u}*@-1U(SKCLiQU;yjJ3jwEjNt0^X zs~SgydWJ>Cq*c-A&Q2>G=y`_SO8nYDxRMbQQT#Q!|WZ?&1r zdD>%OT5q(TMObbtFmePHdJ!^hr*teQg(( z$pkm|ag}JDl;z+^+WX#_G11c5M=F7@d3I^-o`IKWANSa3;l!q(4)$8)5LXhKKeXD- zM!^T?eMsZCbE$&YH+Wk_nuF1r1C|kDa4NjN4j*Yf5+mXH07cepiWJ9k zy7$PErd{{-oUZx`FgEUASGC{dU$JHn1=GTc`~~)QX|c8LlYac;mDv++yBmHwXt_%W z@~&6&G25xi1BJ@_dalZI?RPWp&3Fa&uFn?`_h^fkx7@FlH6g%O2Wt~QGAO|-`7ziV z57d9<`z>BcAh&c7Dtbede2trF9p%NoP;`m?FHY*A4+=>1dN8zuXsOD-NG5W*MrxVPZCC>dmm=1w9cY~}*s zIVt7N*|Pi&I2QR_sw3m<0#G-$R;s&Z+OfQ4uyCzn{#il{PPTQF`DI$)8*f9u_x$OWedO%a~g8y8tsQAfxO5L(Pt%oLRq7jEIHxCAi6f#@ z)yh!Ya&_*pdE5LXqkjVnE^olWVF~Qn39LWiyqoHR5ZNwVC3gFx$Mg?p3Psu6f8;}* z@syyceG!7nyO3TCCt9OR+foB8s?&SzC7WI!r0frFVRj^`5z>&>xVst=rQ$b>?=Yxi z`f<{e+J)|Q>yhS_4U6zwnQl1LPSI{j7;hjmFjl5UXv~J!y08rbUsfny4!rT(apIrk z!(4UYB2UgQG)wrAtm~f67>Xv}fT_@x&JVYXAjqISxQ6uHok@6!mi|H&0cRC}l^7{W z9q9vxdpr>R{;cemjJhh2BEM?wFF(s*AAKPYU&KisM^{V#c~)5?q$G8n-GkIK6+gYxye11lTX95}PfZa{ zTo<=_(-Q}U2IXy}KE*-*cL>6ct(lDzrgCiQ60_!4Uyr!-{{aFS*+IW7-+Q?;$E&|m zbaOjl+%2)QElgn_aoN8cNoEXL!2>oBw{txwvtNHwsH?HXP;=c?TDcrJ8DS=mNBK6R zKDsBN+6!ea3mcL=Kx&+}M~j%@QBVI?V%?jpNacof#zZU1W419)sW!ZifV+`-dBxyx zT}G(12+ItuAT$1yAB;VA?2NVjNX#QNg@His?B|T_gD;}e}xP75F0_Nlu5TQ*)GzyTam!oOz7#ZqajA5p&%A=+F znS))7h2eu@XN|~#uDj_?XuWU(^XFDcWVW4 zq5VKTI_*|sRQEBf-SV!YmbF$BTE#Z|p?CG}T-l0cPpvtI89#n;yk!7NsaVnGiU;B7 z3#0pMDdd9lWf5`8)dD)J-K7F+r3L-bYGaD~(F^MZH#+__k_?6i=R>h7)6IGU0u^*a z)LuHq>dp$g)e9E0hr~ZHi8GD$mk&q)HurlSpDo>IaeGe&$(i9sgMR2DaM5CkN!%v8 z%OXbGx45_(ys=3)dlf^M>PucpCUp2y(=u_fvF?g5F>q&5+;8kW$|PW!;ltSf6+^44 z9jG~DJ15BNKVF>i(TE=%zQ3bR;KzeOX^@{^G3Sog^BCHofzBl(W;(@yu5BZbVu9r+ z)Rufw~ve*3Nis! zz?VA4r^?ITqlCmecFIDU1{YoQGj%r>$`V7+wk(o8?L4(9N44wL2=sBYz1(2;-r!}| z4yPcrYNo68X~yz(YXoG_iRaPd#n}ti@6lu88Ara^N11Lg5TtQ6Zrl3Gmh+63^iMm> ze^cEp9kWW^Rqvj2fY=Cu`+%T03sXnF3L3PD3uc_>FiF3q(q8f7g4J$b!}*6e0|rj; z^T5(TmEtEVoVHwrWwU|*ks@VU!IMbaQbaSzaF6R7IwX>gr5L#Hx1*t}zp~{c313a| z!3FX&fgwgwY85%5-$1Qq%PHcTN+;9m;@TWTD*xE;{Fwi3bjPlSn7F5aGs6=G>j@sY z{T>$El|2|{{guVMr7ec8b`nJXv-R4;iq-gyC~CAo)mUgZc6b(IS_b?}#|zCJn=i)D zJ-|+3@7188t~@KonhAe?#CV9PYO#B3>h!F>>Ka{ugD&|QUnRl01CF6l$m!cew=bgU zi=9ubXQDi-E&j3DEv~)wZwF8y5oG0s;Nsr*FHc;A{_U^8f{SZ{rm}(fJwYLutmd@V zj;8E7P-Y~}qP$34ofEboL}FZgxGo#1Kn`NIEhZS9s__hug)^e;V~!bN7p8&FN0X37 zOSC4@hly;N{x2tD){@iz#!ss3^&@^pK;RZoO%2?!*Q=Vg-FUm9cLRp+Bc8-K0wZb~ ztLL{UQ|rOce@jjmZ4U@`yCr?Kx^aydUBn)xl@Hqq;m2Tqw2IrDt9RH`?!9tRG_+ z9HymGHMJCoi#41>G{zD-5Y0&fnyMlG(E_B@Zy5P0-D0n25PE0}bvaG^3*`kPUybdl zEU4EcLa``Ary|*#x1ncgdAP zLsGcxbflOzTxdvsOhKM&v%Zdn)*4w}=!Uap+`9=31~4niY-&n6JTw{_9ww$N&Lb!K zV-;Wsbcn%&Wb@T|xgy~16?DRmdd0z6k0H>d&m4*KldW~U0$Znm|be=)hy~=ZP097YT7y; zY4!UE{&Lf-RGJgZ8UL4%<|?S^FRC@j3@?$^+Xbb^q``&D=v400c}_z z+2ron?ug07h-S$w;lV2!Uj>8nT^5^7jt55LS7p$1soY?Z?(Et)V79n5#Z94w}u@=N)Xu}4p0cP)?8p0}7U}eHDSb6^niqvY# zs2?J>JP$UEY0ccosQ9*tJmV`DVu^Y^PT7$Kqy-bU#ND={9(rc56!fdvL10!iwrSPw zO(=@>8Y3sn%>&(DB-AbHqb!11|8qt%%Z5fIYHRaM$ZVIEZ&6}{;i|LS5T)Ff>dFn2 z|J#;=AqnkfXhk`Ph|J5gL0a%9Z|*A)^m5i%kJe#Y1J5YkHKoJ7u7ev@N1XfOEu|{@ zG!lE5_B+r}mq!bvxnwk^r#ZVBk2HS53|rPMzlyZd;K#09G0`;j@c_k+^88C&+#`9^ zyPFvd+lQwp8AS8-Hvw^XD=ZieYt%Ki;RgE~={hDS(Q1@Y;6%qeGP8;g4u#9t?02h| z`a?}VLT7axmq!Yhj^{)D4q6lq!)t)H*t4oyGt%HPXRssJ`SXrp>&g#W<*BR2A{KV3 zdK8jl=rC;~;qLZ`;p}%`SexT5*Y(e&wjl)SpACG`73(&BY@N9#Xs|zGTp48Uuftd@ zdY?_hf*5EnnpRh=SaQs-Um#S6dXy)oVxRS(0(Jeb2{H|qy2o0Z)(^LSaUWfU0_e8R z2gUAwJwrz77>{;bh!8Qfz5|7q>je2aOF$od6V2%8==$jr{X@d7D!wkB43R1D=*>bc?4UJL&&^2L5hQua(vJO8EuP9_p7fgogCRO&eJk>NQM&Y zhYQ_t`%MN3YJSx~R!d;lQDJlzg@wWy-L-SjONSOQeK$YsoMO-Mh@#Ehs<1mj2adL$U<*si;qoiO4huwCA zpoyeYKO0DfVBq|&-*MbJ!pz@Opf);d3I-3R3jOi>l%xP_0r*3TQ&b|`QBcM370;i` zMZ63C3~hoNSy<)Rr()`p?63g7N|X_rO2_MrWh)~a{F&OBwD7qKX2b< z&m}l-U79NY4u26=;L_&{%8Kn|_?S-DZLEv@ZdlPgA9D1d#|R3-Hv((eZklEa+hM7H z?wp9Z;k_|K#Zu-ec3W<}X$@z!%FGt3=A350G(tPpPkVL*m`?7?t404T+ zGZ)ak7oYuSn^KQ`2;BJ-tw*I$H{(lDI@a_Mz1fNbw|(9d7Q$y{^Tzmp9Q@l<+&;h% zMLx;>^ML*u2EuC4yxbY;>kiCEDwWC?a{PW37pdRb{w@Z1M{Qfl8JdE}!y85n8~4^d!=?f5R`B@wP)-^i;%54+!M*M555(i3oqnYXQ)g zBHx9EgfQFR6&lzDxrNuM)-RIu69-lzZ|~vkvC-M3q@XJ^z@0fRrYv;#Hnrrj#^;tO z9kWmZYfOUwaN%(gDJ2k>Nyi~TEFEzQE)JOD&s+Hv*Dd`YU5E+$0ub3ziP=2cd;fH9n>#-%|L2;B@H#)~It&rKV;S z76MITw?ytYe9qoFC=;R*f&}S~LPC9Q`46d{_c6SXVQMBz6=`C8w!G4yG*+5GBp%uX zI`@SLIUt1;D;IJMyxGmzs+E0)mH5k{2p+ zQ*IkxL$G4KYnO{;D+%%=4PsOhe?O$2`sw;pCbFO+LX;q#g~Vu7@r2t)xH>c9&?5hD zaF+lE6e?2o!xXIN94+~l8Ai5yp2-_3gRj_Sbx5qGTvlSHj3?@7tuF%=hf*&}*Ajt} z?OLQex3HT1s5Mr7`);}_N5ogQCAj-lI`z$g8+fqsV+}L1B~9`xaiWj;2DBz?!iGAq z6Ppr{KN#C+*!nOWUz%e@9|`;llr#p+1i%bBbq;v+#yp=kN=fsp#>9LGQn*Mtm~tr- zsb^>SpdtSg$Qk`MOnc8}PH=W6KX3e1xTs;Hr{bgeVRi&`TwE^Y5Zj1;_>ZM{FinX& zzt1C!c3_zG@0`6@5J8!~xf^<9WmMy7b&4gD)||QGD8QfOL>tU{o<)H9u48(L;uZll zCE%6RR5#Pjywu%QxW(d)G+5U7XRU=xHUl##;VH=;u7LXe8)yRV`{!e%j_>#FG|#FI zA(zHcSHr~5$S7=KI1ATuATeb0pdnx9I>-8!oN1>7@>$OK!9{>nYTdbf@~dpqbaJE- zrXlEONoIi!KBpj1VHlhuh8_Dh1)1CU!r(z&PCZBn*l4DJ%|tbhjkw}Ji9%2_u&opO z1Rb|wh`x$VkIcJ^MM+~y{5e7f6@^HfM+rUCgYvP0J7MmmSP48s@h*PDu#*R?(9-Gf z8M76`@19osqN0ELDrHzp1Kq8vqW7@S9%D&lYWfkkW+M~(0G$629au^(6esiQ>hxt9 z`Iks?2HVCR5!;K-O1GXunBx#FklTRV++m{_{Czi&}R!p0w|2XhX@5 z)Gqg6ti7>}vAkBGx!JU)*?sT_mJr^8&g8Qvj@vNUVfG486eT(OidpLJKCQz7QWeH9 zp=n^1mVP`u!YNS6qakBS{A(FD2FLd;P4xx;?X*z+Ys%}7sd!ztnLaY z34rGp z_nHkLfBQcjT8)hlEb=cTfrKwUmEb$ickZzc?VFK`^2N2yG9Imf)4xk>xLua_b0Na? zS!ttY2r;Y6G0kBiFO(oheoUzw^}BbOq5tcc`-C)!st6~2wV$rd1!KU)a2qsgQf>hs z`PbC=y;=fCG}IsOd#l>}ghFCfCYYI`@he8}^$v0%{(LsxKdkRl3{ArvmLrHO zjTR(KAe>^G*NyGFyVX-t;d-Xjt|&iDJ`D2n75!O-qu4h7f59Cr7SV5Oj0^PkA|NBn zsJ5iW6ZYH~J=~p(cGI6qmnAs;04LEL*ceHFOSuB+$67`9{`b1heWYa3iCoKB!W`dVkCTps_M zLJt6(F|ON`zl)Ei%+G}&$HMpooEgliBiT(@vuV6%P8Ub(tdOzdNsE+fY?3^WEqq{T z?9K_Z!$dV87#N_pN6v^73tiC-I~wF8GZys zY{r0%_a&Wr+WB)3K4B>$ATDogZlf42RB=gk?$7W5g)$lA;mRZ{HaoH0c1(Wq0~6zC z@ZAOT-L*>s5_(>Z6)hVT`zf0aQ!xqKPkzhDE^OYtybN)ouYdXieF;a$>F+A@eK@VI za<$9@Z94}2D1miMAnP;O{$lk|-;@G;!4(j-S=p-!6tLU}j;nP$yRz9XmH54iK~z4( z{(BU6FO)ECZ#@p8=ml-V+h*lGVnn3pt1c>l;`-4COKWiV+wr_OIfadlxn8RM+MDp-xF zO8Gl*z&=aG56^+c4V$45UY78VKS!@p@_-P|=XTR=%N*dp^o?(^`TH3TKs`U?8l$Fa ze`1w&dj$z!yTKzx=U%@*Fhy;QP)Kj|k|KV0bYi^D$g%rLfpwPt{CSFez;%q)Jcn7U$4h}(f@kv=P3|Pg>ece}5L>_yT%b4eT zmhYAepgw%XB%idAFTmknl^?wZq9H}rmpPmmNSf-1iF7M*vVhfI7?pcAiSUI<8_}v~ z7zjvbpgO{e^-DIH!PI%c3t%!-{#7kLdO=D#J2gb}QrtYm@yi|wGz^ebhBN|?I$2SA&!%}^Z7OES4Nu`4pu74t?%Z>wD+AI@}^ek2- zyjt9EfYM&f(a|(2dKbfEDb@Q&TJ9X{b_Z@`;@DD+#{-T#< zDtAW2EH^)rNtp}&hYk$%f6{@uEC>O!_EyqPaK4d+#?DIRkf=pmgrDdcne80~$znA# zfeU0}krTqS69_adwdEMH|07nU@2b4de;J?r!vf9?ZaVedQ`{mr2O^|NwI&n zXBF=@Xr@O+(hoVC3EVaGZs?lU1ZT(a6xrPRtBknt1|v&C;_CJgYH#1fxOD`J@>tB^ zl=b{Suo9d)YMsVKfS&-c-KLgFiCn!)%Q0Zv5Oa}jjc`55={&7u+41A|c|CjcBS5s}B-*N)r1<^LFG;_Qhu zm-`h#E~Ra9<64u?6ieMCfrZqm=y@68q5U}z77y8`GsX*{SawOt52pO^adWRDrzug4 zIgggw+KLwL?*2?DA_O=_v)+AF#P358%0lL1+3qoXq;nr$rVxbJ1hq~GXy|?--5$$_ zqX>vLVogy=DwQ7_2l%@}1TlpaHk+Y}bt)O<>WcJhC>6SCaDvk(Tfk{*ir)b$y=>)= zKkcWNWETzz^2E2(b4IQ}FTb1Q`pF5hJosEf)mr<7&Q;~dB`5kdLOs8!B9oRtD zS2Xwahd+gD22@9&xwF1V2;;9*gym%?P?wBKk52DOt*q(l7~0W@fq)K&GO4a7^vBH* z2v_{5rjB*cp?jk?fMq?u5;ul=lQkU)wDKYz)yZk%(;4Z7<`>X5F!9f6ImZcAU*=`e zUjh`sJfYhEM9)h#G$~koqtJ*=w2O|eek+GsrAM^p2Ybo~m%TX$*cSZoq;pngwC7?A zd#|Syo*`LqJ-7wzMH_D4>h1S7rR44a{pM8(o zcmMXYhBOV<7d*P~_EGUwi?L=#=k@!krM7hYhwjT{hr>eTha32}{>!2dj@bYhM`1Bh~|FOuxZ{myc3RClse`x#|jAfF#{@cJgqinC_3x2zghdAr*iYj_RwNba2-^Q%K)Eg9#X} zu98gLwoL)`ddQSNWntG7Mk$SD0>AUB*|6C|mFB7*09>RjFYb5=8E6F>#5Y2>0KSC@ zZcBYTSIbl%amv$nrD;xKpXRD%TjObVmjW3`YDy$_WB0ZU*)|F*+b;25D|?1h7NMRU zpdE?<4(4JQv*MxaPcH=Q8VQ~|dtxch`M|B?oHB$NUPVA$z{%-jp2kT`=61jUoe$-n zY{Q}@YGzCI(li@q>+wu-S98yMiI*d)NEA&-cc;0m4cg!;OSIKWqEfgG&+`h_DzqNS zk5Jg>6PWH@cAP&B)-GA^+NC?XIowi^%|GRzxMDpXtI^M!?;a#$cV142k=+AAd4aj? zNt@?lrX4qA99?5uF3z!;jslMyO)lQHmTF`C+Z@t=I8#+!dP2}w*{s#}ur)-av(+Uu z*2vtJe^z}u2c-p>6jeNzJ9lST=YKXo-J8ot(z&MBH2%!pnf5xnz#dB0dSsO4PM5CY zeuKe5^)U^p&b=yi>;os^^1R7jmi3wb#lvdgvLAl?ZqhngE;U%|ob4?E`2$l=e}ci) zz+XOv86my?$+5FH5RhQ?GQwqAl9RKoVk#;kGJJt)TJ5hCd`EQ%&|-aw3(S7g3x;j1 zKhZu7z)Ne$e(H0v{1K=()iv$_h(TsNyX25@jRB46otn=zSiNibP}TLT{V6EVUQY8gB97SQxFX z_Ktbzh2$5)i}2y&6-LG@Zb-G3xX}TT^$)}p`QdPu-mgt3fbrskA8AQbwpUlEr06M` zA4;jw82V7Y1l{%`{Hs&Hm18Nb2A5|m6r@`9rv=^<$VZ6trzgiP*k#2^JD0?_+29f- z8g$+A=i5;g82Zs4}tI10uodYfoPkO=KXd8ZGlS zlfu7#UG@r*Z7@4%fPSvZu+?)iTG}bT_#+19lZJm;^|n-kVUFV!fzirk8|d$jJr150 zQ_{=_G5qwYPy1VaRLmw;I@$vTk$8>v7mlU+9_9JdIzqyI+Xk84gy!N1e{eFd^~$?w zpI4uXL`GsdOl<))#&|zad^G!;Gtr+l|~P&(5;^R!q7&I22&> zrR>qluGS&)%h0c*=ADSUKnWXGJ|N4{@7*w6;O+l_1({c!7oBd#_p#&vmspsiVurZ& zZ_6H!3^+f*Kf(-ZLV2l|GYtyq(q>{;hyb4?pt{l1&iw8%XnYTNRw5Is^5GvXK)lA> z?=$V!)6Xr}?a{=UGvdWI=Fdk72nr@t-|PNqU&RnU(Vq(!oH|tYk$s5qzhtnS{@=vf z`z7#4kO}_eFtPK-d~uw3`ni`U(nHq|%voDx`_GsSK;DYri^(w%LStiMT#7>voImqcQ}@cv;_ zEPYVL^ZK6aH7N&oq|kYbPJ#Nr$oME_2-t~A~s^)okI+}lz{5&$JC zigVr3Gb~{w+n5&p-(KLQ9!%uTjgk~$~36xeL6Bnj=_%WB)qI(Tiu$NE(6Nv0ScKfHaB&*S;?F21Bx``O-djh>4!>$@qxod3s4pLlFUiklNZFBsVoVU z!9sW|K`P?=rX&NXp6EE;9+~#gs48Yv98PSW#{h1KAMk;5{^vFGlInHQPVpr(zj6;Z zn2;if0Mvx+C9#+Xg&AZv3tfpG3*x{XY!>z08W#g%P4YlG!d%~ zWK(G|QFTAH-X+RRY4O6+vED>588dFBkmbH|y_EC`Z)HvtgArtYvbRfZC6;+bYL&VC z*Jw+K=qikuvhoa4FxVb|zhs7ARC)3QY80vp>*a*Y7=}d46!+p1T2{a4cZt%B9NtXL zE(87P*GgAvM9K@wBjzfy;*EB@o^>rJgslXwN8ybTh(UqH3 ziVM`P+$rX;c(D3x1_nt0B#YpdpRlR;haTkSW?-#dQvN&?!~gQ!{0`B(zZ5_ZI_q-^0!~PPq>( zEc0fWz3!S^VC^hEYb)^J#>@`~@(3MC>`__Qz;C58{D1iJ_ZOfEF2Y*LOzEuZnHK#3 zn^s59x~)k~0!yz2{$7(-%qouzY}n1kvILN_rhaYvF}K_VcF($WS5fe>#f_>zY4YnL z8>Qa@j-sW^$=X{vPbcht=zi>Lb)=?Xr|v{H>^`m~_*A9s=k$+6?_TD%wSe#8yw%}F zcI!Cl%TJU%Y0yiogE_pPE$JC1)~dU{>9mRd zI1G$35Teo0?3RjE9}>5D$k57@Zq8wVqgoeIKcODnnaHn1>HvkgPNx3d4k*@RI!q#+ z>-8Mcrt~8u5^kBFGV@(o&?hyUrp#}Y;USvnIMrYEdB`bB4;zgt>7W2HS<}Q-$9b8< zz`nBe=L1>{29oe)Kl=yt{FxyotHZXyP3uU z<<9)mL5-gr|;3CIf6(dtUPp1Cir`+v+V zsI`wRka(Fs_d>CV`G^!9sHZe%{K|lyEpQZDU{Ve{?SOV`a(&ht*O5oh zn7dxy>$}&^?fNxbmT?z{lW?lGm%DLEILZec9xEM2YP*A%9))zl6}e!PxA`Aq&wJ1W zZx6uy8cZNB)P>P@Z%}iU$=JZC?cSwtli}-=X6qZb?u3?4;mt31_1JGT>B_@%_3aXU z?*`%2xdCV5>6}$E3ZWDj>&ef z*s>c|wfZo$9=j4^F2KghXA-|SUQCh>P~WV!G1v6d_vbL) zdC9Q}+e-D&O{4fo7=X*Ck9>4d$Y51A`|sv1$&9^`W8+7CG;YQcKdJL$}-%@{v`VOU$ z>w}f-N#4gJ3r+xs=&h)%A3cnKkhs~U>H#4)*s5YV7ni4{BPtK@GzTYaor^GTzxRMg?sF6#r>)Wd*oU0LdCZ*>N(yzT3QQT>Reer! z87!E2_W4&w6Q0U&>AC#dpW&HR^CMW2R$(4QK=kzKQ(6C-E4qIM(jEq~v&c|kk$Ivv0qa4Ycc`FQWM z+-?-QE-qL7Mhn1}zkk3Um`Q6_?vL*lR6ubZq=hqe*LE}=zYk^)U3Ym^;AeM*R%lg{ zfW>{NC)@EpbMK7Z;}ACd7R(gR)_+0+Ayj|Zp&~ID#Zj?w;a;&?$bHPzQuX+G>@@H! z8U3!`el1bq%5sX_<-GG``?kh>M}pA0JLu&kIL(5goT4c#kjJLR?7=5COs3&{g!gdG z-6#3f*`EZPX!7$&(j6>EdsV^+5jND(+ScGxnx>%~UOQwj)z6FhXUj*fi**-lnb$o` zX1{f`IyV&BCCc}--5-ILQMfIW^g(R}g&#X=Jb?hws3^&Y)dI z9lX!7v48xj(5$YIyru>wlX0Sl1IktG{#)+F=<$Id;Cp%+oZ9{6tW;#`49L){;Leno zPt+KW^J#0y;YvqeJpEUj^2|$Q>j3sWR0zriq2A|p!1YHQWOjduBK}64kH(Y#Pg`gH z4F&tZacy=Esh!UU;g=qcDPu-*KCtKC;tAk*Ye7H2Lr*WR0Fszox=-t!~E^s8P zdUpZG1AZ;t>U>}Bf5I%2nx!il1mls8*^`nT5;Ar}|FJ&fk_D#_mh8xXPBM-Nd@#N! z+r-}zoHR%m=;WWWVeSfD56FjO7(P;DAv=&$!3a0_Ltlc=GpY$GciP8UL2IOM#*6UA&@<63aeeplO z5`QDjd#c0Kcf878>oG)PjE<^`D!5;YdQAdk8-3IET!3CJDRi3IhVMPEKeXPUNRi1W zLu0(3f`ZQyFe7bcJq&yW?hiizWa10;Q_I>-1713dPOb8aiCrkN*b!b=Ux`z32EoL0 z!I)?_I*3!`mv*z@mBsu=VViriH~%`5I5s|odWs-JCf*?3daZfEzj>NzVn(K2V-w?x zGCPd4WOZU`RsD&3AWs{T{e?F$H$sUI5!}!NIldW@--}x`Z)Ahnv$RHgyq} zTc670j>qXQZkx}Y$Z0%E7{i`vn7(7Wocq;IB290 zH;Ck!^wr^#V~vq)>VS8=JMAX9rv#5)hA+O6PW{AW_5i=K$T6%7d&qg42XSpdXS2jv zFJFHGR@RJPztCN1GA!mnZi|wC1Y7*t0q2#c2YyjFc=F&{M*b_6A4T6{G43OyZnAIdA@Q`0^vc%{3`s~K@7uGE4s>^p1o$yH78Iu z-z^jD?DU%t-ifjEePCS#-S4#DVXR5-2~dR$&Yxg39nLqKB{MNZmk-I7b(I-zynPy3 zWD>aM?u?1fCkf26qc*Ch#?cI;Io-)lDfS#4grGLnl!jz*bjh9)a6|lCDT~2$)F>&k z_{G{^-$u0)Ah;=pfCMtOhjq^*=5n6M6b?u81>EQyVe_s-*o1jNfaTzUM9{N8vWv_S zSq5Ai*An_^tw2+Y;XC!EQaQm|V&Us58bC2D%WBynT@reB7p98|+jNCv_8C=kv)rF0 zXN;Id9uugxU}X%jF=*kXnikY$s9ZA$eeI%n(2)Fh&K_wtW+%6`wE+YBmalfOiF+L2 zw&)(}{rJjx=MXU>*Dfb**YEV<2lI#5Al=Mb5IVOfFwL5lioB>aRvB@o)X9G;bbNNj zghNAK$ioDjEG}y^C+zZy8z8Ksq;Q6h@sQ%5)b1zMZn@*kv|h8Z^Ww7}$%v=D(Sy=I zJM9;adX>EcUCsdVip-GtR6dC2ikLjLl&h}A8vjYixJI_N#~*It@U-RAI+)rr9oOE) zIA%#Xo!0$$X*uba;<|?q>t$mkxNG%r(EYt)d8pSkpXie7-gGlMedgVrx0!XnY^}T9 zpOrE{?ig54?fx!z>oE-}i)ME$HJ$@XoGOqFX@8XR_Wk?!T<7nKjVkgKIy~tHCm3Y^ zbdvQ*UJv;u&gNlb!KPxtk`kFg`0BqiB$Mt0tn7CmDPtD4(#X^GUnkBVONVTY_;$m6 z*l$gZe$E3tq4XjcOHS(xT?)`L*zd5L=TJOr%-tr6{&oG>54`u%GL^lIVBZ)SaTTgY zW@k~_22wtMdYeTqwW|L?8&K1`aZRv==}57bGw9&muVo@ek~cs%nZs-kP3({$?iVy^ zD!T7WRmV{63k1?;I5-t9)sOeG-Ck69rdI(A6csLk z?N$ytbM`Z09Sv9wxp-NJ z-{n&BqlqwW^)iGN__&>#=dxi_+^(xgfzHYAaeu2`o*3>iFmUI0Fz+0xijl=s+^bPM zb-bu1L-c61-SeBs^r;}oKO-GLn?sE<5KDp&U-Q>01FZIVSh?OHN@x{1X^gc~UwajN zpBoD?=pyN+2X@Ea;=P9;7TjIst;g9z?@gS##LaXgwr6jSnAm!ituM)D%01>iq+3*zXc7hC>xye5C zfpLuhAc-ZGi_|yJu9v9K8DI8s?=#2jgjNF3+xaNT ztf!?x)5X^;DtOL8pyq{=Unu^=3M#Tw%=K49eIjqS`ac9hI+cy@rovD32b|+5$ zQB^O`os?g@#}v2Pdewhg$>%!~h3H`wRj7EXu&md*41VS?({LvQbbhU!&J{xL8g5M} z6u9XAi=g{@mm;ZFpVxR*iO!I3!0p%!+=mLv8O*;A5Zo2r*%)&giYB6j%b7foCIO^f z$Ln12<@Wp6(m87^?gdXqXb?nw=3)ncuS-#8yJ)5>(^2otOAai7(d8byzT=N##_{L@ zsU}{iwalxBt(;mqmYdTV5W+3U>y*QxMU`+QKf+zo(zz;Q7+75Pq*I}=5it|i0Ejs% z-pD?bcmU-#09`=9aAcW2nzkp)ls)jz?{_lQOTb~M@cUo0sh*Z#&%F~ zQ#8;8Lixec1Vl5_|MwN!$Chz>wWCwwdKXC3sgP1K9}YGtg`C@)Ht^ZUu}=co!Y~#! z8al?({{dC`_G}F=tn_=Y(p3Txnm94`Q)P{_58K6Vh&Ae*I!3gP1%~Ll$ST6KE97njfREdf1cb+Wk26q>L{|eCPuV> zJz`>xZw_M#wy<_Aij@L(^_w&{Bx;za{?%8G@UHmPlzsS+l%FqkSxKp~esc6*8W#|# zv!-+<^?#7KuG-6IKLvC>@G!sG|M%6aVs=4_N@3a;t_Rrl`OClb@mupneO!Na?Vrid zw#Xrk@|1P=maLcW7SAdi-%AhhRIBZ5&wVoaX^h0|C}DGwX~uOeg1Cs2v-U1Y&nzSk z-}Q$Zz@*`JLSXE^qTc$TJSs$T_{Yuh7(Ibbs+o7qUI>`qe?i%S3ccYKqFxnomfX40 zK6`sRRu1(lRIGD-F+GvO_be}D)E1Xnv67bZhnAjGg;jaKfzzvBm&p$WTT@#vlCg(c zR*$at+o6OPp4Up5l^9aRg3JSI4J}hUncWzXMvx#(h_oTq*Wzt}UL6^|FFe*s5Z31v z1{FLf|Nf;`o<+txT* zpQ(keWL=mU6~In40>2531%m4l?OzyH-g!0LG zp9S5!wJmX(Va)9K^xP*6nsM@3mk5qh2BV^cHE5@fO7s0g}K}-7q?ho z^>lHmEfP}eu>%C!?2gj!#NV1qS)E`O!q)15TUq; zr+dl1b4N_*`%c2achst64k<4FD=nc1X}C#5bMh9Fx(RXzi~6YK*=^n}(i{j!Y*cf6 zzwSRjlJ1Rjvms{}1u+6lYS&9VGUf+*Y<)Xv+Hkd={Uj_l&<= z@rJXEvWDM7bCVD{D@B&-U9zrWcBbZ%E`n$Ch?ubN;N@xEm76d2Q1h-oUL}2YHcalR z2xS%C=}1$3cr^9~A2_D;_yDrEu{3rW1@PKE$EjK#snOh8@#pT$o!{4Lcv+9mbysU4 ze}WZ19bs0}`RpT)r9L^X2z0T`LDO^p-l7UuKzFR0PkP7Bp)-elKx5x-5lK7^w~;r- z!{DM0?7xPwn*;&-&Dyu2%TLe7#DE@zshE;Ae{2#Ts&4Gr+12GIb&rU`_MLaOFgZ30 zwtgEq#@|^ibU0EPfFqJHldJh82@?A%u5%Jo*%>v!m@k!IwW*HIQXaR6rdTgf6y z|42ET)*OJ1P%e|9^yO*h#s^jZ^YWib9^ym#)pNt9j!3L{r=>tYHd>W?E&z&+{UQNs zm-zb&aLl(GL_`~ErF8#xy?N2AWBwi7ydGaiX8*w1v#-yhq*M5i8rA(FAmNN2r`tq5V zjNH#`Yb`s30ucjG7lN)h)9Vibqyw=~Mwn0_<9b5uEm!=2Mnj=>%f`sWRN}Qh z?Ma_z(LwQtW`PwO5O%31o0&NTt|rT{xR4#Y7H~ZIAfXMCyd?>8DsD?mG{-GdPo$xx z+9$gjt())>?F@b?esp9@-0Q)PbhS2t?=`#gZt_qoS>jC+k+rJuBPziZBC=aV!W<%0&rgY^TtV+Ws zwpQ?^n0UZAhxT_JflCi&J@yEInPd+|&{hvUSB48xD$CB*9uqu3_2p$IZ|r4jCcLHXklu+?(i*yo>Gp-j92W>QWBcAlI~mLq{)5ZFbtiOsl(oS~C^ z@KY;&I+ZGXc*oP(^8Ycja#Frmbok=_BisG^N)X f$@Tu53}yo=*NS|(q0*I{lX01wSQ*zCy2k$>5ue^S literal 0 HcmV?d00001 diff --git a/bundle/groovy/syntax/groovy.vim b/bundle/groovy/syntax/groovy.vim new file mode 100644 index 0000000..5f96dfb --- /dev/null +++ b/bundle/groovy/syntax/groovy.vim @@ -0,0 +1,450 @@ +" Vim syntax file +" Language: Groovy +" Maintainer: Alessio Pace +" Version: 0.1.9b +" URL: http://www.vim.org/scripts/script.php?script_id=945 +" Last Change: 6/4/2004 + +" This is my very first vim script, I hope to have +" done it the right way. +" +" I must directly or indirectly thank the author of java.vim and ruby.vim: +" I copied from them most of the stuff :-) +" +" Relies on html.vim + +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +" +" HOWTO USE IT (INSTALL): +" [groovy is still not recognized by vim! :-( ] +" +" 1) copy the file in the (global or user's $HOME/.vim/syntax/) syntax folder +" +" 2) add this line to recognize groovy files by filename extension: +" +" au BufNewFile,BufRead *.groovy setf groovy +" in the global vim filetype.vim file or inside $HOME/.vim/filetype.vim +" +" 3) add this part to recognize by content groovy script (no extension needed :-) +" +" if did_filetype() +" finish +" endif +" if getline(1) =~ '^#!.*[/\\]groovy\>' +" setf groovy +" endif +" +" in the global scripts.vim file or in $HOME/.vim/scripts.vim +" +" 4) open/write a .groovy file or a groovy script :-) +" +" Let me know if you like it or send me patches, so that I can improve it +" when I have time + +" Quit when a syntax file was already loaded +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish + endif + " we define it here so that included files can test for it + let main_syntax='groovy' +endif + +" don't use standard HiLink, it will not work with included syntax files +if version < 508 + command! -nargs=+ GroovyHiLink hi link +else + command! -nargs=+ GroovyHiLink hi def link +endif + +" ########################## +" Java stuff taken from java.vim +" some characters that cannot be in a groovy program (outside a string) +" syn match groovyError "[\\@`]" +"syn match groovyError "<<<\|\.\.\|=>\|<>\|||=\|&&=\|[^-]->\|\*\/" +"syn match groovyOK "\.\.\." + +" keyword definitions +syn keyword groovyExternal native package +syn match groovyExternal "\\)\?" +syn keyword groovyError goto const +syn keyword groovyConditional if else switch +syn keyword groovyRepeat while for do +syn keyword groovyBoolean true false +syn keyword groovyConstant null +syn keyword groovyTypedef this super +syn keyword groovyOperator new instanceof +syn keyword groovyType boolean char byte short int long float double +syn keyword groovyType void +syn keyword groovyType Integer Double Date Boolean Float String Array Vector List +syn keyword groovyStatement return +syn keyword groovyStorageClass static synchronized transient volatile final strictfp serializable +syn keyword groovyExceptions throw try catch finally +syn keyword groovyAssert assert +syn keyword groovyMethodDecl synchronized throws +syn keyword groovyClassDecl extends implements interface +" to differentiate the keyword class from MyClass.class we use a match here +syn match groovyTypedef "\.\s*\"ms=s+1 +syn keyword groovyClassDecl enum +syn match groovyClassDecl "^class\>" +syn match groovyClassDecl "[^.]\s*\"ms=s+1 +syn keyword groovyBranch break continue nextgroup=groovyUserLabelRef skipwhite +syn match groovyUserLabelRef "\k\+" contained +syn keyword groovyScopeDecl public protected private abstract + + +if exists("groovy_highlight_groovy_lang_ids") || exists("groovy_highlight_groovy_lang") || exists("groovy_highlight_all") + " groovy.lang.* + syn keyword groovyLangClass Closure MetaMethod GroovyObject + + syn match groovyJavaLangClass "\" + syn keyword groovyJavaLangClass Cloneable Comparable Runnable Serializable Boolean Byte Class Object + syn keyword groovyJavaLangClass Character CharSequence ClassLoader Compiler + " syn keyword groovyJavaLangClass Integer Double Float Long + syn keyword groovyJavaLangClass InheritableThreadLocal Math Number Object Package Process + syn keyword groovyJavaLangClass Runtime RuntimePermission InheritableThreadLocal + syn keyword groovyJavaLangClass SecurityManager Short StrictMath StackTraceElement + syn keyword groovyJavaLangClass StringBuffer Thread ThreadGroup + syn keyword groovyJavaLangClass ThreadLocal Throwable Void ArithmeticException + syn keyword groovyJavaLangClass ArrayIndexOutOfBoundsException AssertionError + syn keyword groovyJavaLangClass ArrayStoreException ClassCastException + syn keyword groovyJavaLangClass ClassNotFoundException + syn keyword groovyJavaLangClass CloneNotSupportedException Exception + syn keyword groovyJavaLangClass IllegalAccessException + syn keyword groovyJavaLangClass IllegalArgumentException + syn keyword groovyJavaLangClass IllegalMonitorStateException + syn keyword groovyJavaLangClass IllegalStateException + syn keyword groovyJavaLangClass IllegalThreadStateException + syn keyword groovyJavaLangClass IndexOutOfBoundsException + syn keyword groovyJavaLangClass InstantiationException InterruptedException + syn keyword groovyJavaLangClass NegativeArraySizeException NoSuchFieldException + syn keyword groovyJavaLangClass NoSuchMethodException NullPointerException + syn keyword groovyJavaLangClass NumberFormatException RuntimeException + syn keyword groovyJavaLangClass SecurityException StringIndexOutOfBoundsException + syn keyword groovyJavaLangClass UnsupportedOperationException + syn keyword groovyJavaLangClass AbstractMethodError ClassCircularityError + syn keyword groovyJavaLangClass ClassFormatError Error ExceptionInInitializerError + syn keyword groovyJavaLangClass IllegalAccessError InstantiationError + syn keyword groovyJavaLangClass IncompatibleClassChangeError InternalError + syn keyword groovyJavaLangClass LinkageError NoClassDefFoundError + syn keyword groovyJavaLangClass NoSuchFieldError NoSuchMethodError + syn keyword groovyJavaLangClass OutOfMemoryError StackOverflowError + syn keyword groovyJavaLangClass ThreadDeath UnknownError UnsatisfiedLinkError + syn keyword groovyJavaLangClass UnsupportedClassVersionError VerifyError + syn keyword groovyJavaLangClass VirtualMachineError + + syn keyword groovyJavaLangObject clone equals finalize getClass hashCode + syn keyword groovyJavaLangObject notify notifyAll toString wait + + GroovyHiLink groovyLangClass groovyConstant + GroovyHiLink groovyJavaLangClass groovyExternal + GroovyHiLink groovyJavaLangObject groovyConstant + syn cluster groovyTop add=groovyJavaLangObject,groovyJavaLangClass,groovyLangClass + syn cluster groovyClasses add=groovyJavaLangClass,groovyLangClass +endif + + +" Groovy stuff +syn match groovyOperator "\.\." +syn match groovyOperator "<\{2,3}" +syn match groovyOperator ">\{2,3}" +syn match groovyOperator "->" +syn match groovyExternal '^#!.*[/\\]groovy\>' +syn match groovyExceptions "\\|\<[A-Z]\{1,}[a-zA-Z0-9]*Exception\>" + +" Groovy JDK stuff +syn keyword groovyJDKBuiltin as def in +syn keyword groovyJDKOperOverl div minus plus abs round power multiply +syn keyword groovyJDKMethods each call inject sort print println +syn keyword groovyJDKMethods getAt putAt size push pop toList getText writeLine eachLine readLines +syn keyword groovyJDKMethods withReader withStream withWriter withPrintWriter write read leftShift +syn keyword groovyJDKMethods withWriterAppend readBytes splitEachLine +syn keyword groovyJDKMethods newInputStream newOutputStream newPrintWriter newReader newWriter +syn keyword groovyJDKMethods compareTo next previous isCase +syn keyword groovyJDKMethods times step toInteger upto any collect dump every find findAll grep +syn keyword groovyJDKMethods inspect invokeMethods join +syn keyword groovyJDKMethods getErr getIn getOut waitForOrKill +syn keyword groovyJDKMethods count tokenize asList flatten immutable intersect reverse reverseEach +syn keyword groovyJDKMethods subMap append asWritable eachByte eachLine eachFile +syn cluster groovyTop add=groovyJDKBuiltin,groovyJDKOperOverl,groovyJDKMethods + +" no useful I think, so I comment it.. +"if filereadable(expand(":p:h")."/groovyid.vim") + " source :p:h/groovyid.vim +"endif + +if exists("groovy_space_errors") + if !exists("groovy_no_trail_space_error") + syn match groovySpaceError "\s\+$" + endif + if !exists("groovy_no_tab_space_error") + syn match groovySpaceError " \+\t"me=e-1 + endif +endif + +" it is a better case construct than java.vim to match groovy syntax +syn region groovyLabelRegion transparent matchgroup=groovyLabel start="\" matchgroup=NONE end=":\|$" contains=groovyNumber,groovyString,groovyLangClass,groovyJavaLangClass +syn match groovyUserLabel "^\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\s*:"he=e-1 contains=groovyLabel +syn keyword groovyLabel default + +if !exists("groovy_allow_cpp_keywords") + syn keyword groovyError auto delete extern friend inline redeclared + syn keyword groovyError register signed sizeof struct template typedef union + syn keyword groovyError unsigned operator +endif + +" The following cluster contains all groovy groups except the contained ones +syn cluster groovyTop add=groovyExternal,groovyError,groovyError,groovyBranch,groovyLabelRegion,groovyLabel,groovyConditional,groovyRepeat,groovyBoolean,groovyConstant,groovyTypedef,groovyOperator,groovyType,groovyType,groovyStatement,groovyStorageClass,groovyAssert,groovyExceptions,groovyMethodDecl,groovyClassDecl,groovyClassDecl,groovyClassDecl,groovyScopeDecl,groovyError,groovyError2,groovyUserLabel,groovyLangObject + + +" Comments +syn keyword groovyTodo contained TODO FIXME XXX +if exists("groovy_comment_strings") + syn region groovyCommentString contained start=+"+ end=+"+ end=+$+ end=+\*/+me=s-1,he=s-1 contains=groovySpecial,groovyCommentStar,groovySpecialChar,@Spell + syn region groovyComment2String contained start=+"+ end=+$\|"+ contains=groovySpecial,groovySpecialChar,@Spell + syn match groovyCommentCharacter contained "'\\[^']\{1,6\}'" contains=groovySpecialChar + syn match groovyCommentCharacter contained "'\\''" contains=groovySpecialChar + syn match groovyCommentCharacter contained "'[^\\]'" + syn cluster groovyCommentSpecial add=groovyCommentString,groovyCommentCharacter,groovyNumber + syn cluster groovyCommentSpecial2 add=groovyComment2String,groovyCommentCharacter,groovyNumber +endif +syn region groovyComment start="/\*" end="\*/" contains=@groovyCommentSpecial,groovyTodo,@Spell +syn match groovyCommentStar contained "^\s*\*[^/]"me=e-1 +syn match groovyCommentStar contained "^\s*\*$" +syn match groovyLineComment "//.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell +syn match groovyLineComment "#.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell +GroovyHiLink groovyCommentString groovyString +GroovyHiLink groovyComment2String groovyString +GroovyHiLink groovyCommentCharacter groovyCharacter + +syn cluster groovyTop add=groovyComment,groovyLineComment + +if !exists("groovy_ignore_groovydoc") && main_syntax != 'jsp' + syntax case ignore + " syntax coloring for groovydoc comments (HTML) + " syntax include @groovyHtml :p:h/html.vim + syntax include @groovyHtml runtime! syntax/html.vim + unlet b:current_syntax + syn region groovyDocComment start="/\*\*" end="\*/" keepend contains=groovyCommentTitle,@groovyHtml,groovyDocTags,groovyTodo,@Spell + syn region groovyCommentTitle contained matchgroup=groovyDocComment start="/\*\*" matchgroup=groovyCommentTitle keepend end="\.$" end="\.[ \t\r<&]"me=e-1 end="[^{]@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@groovyHtml,groovyCommentStar,groovyTodo,@Spell,groovyDocTags + + syn region groovyDocTags contained start="{@\(link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}" + syn match groovyDocTags contained "@\(see\|param\|exception\|throws\|since\)\s\+\S\+" contains=groovyDocParam + syn match groovyDocParam contained "\s\S\+" + syn match groovyDocTags contained "@\(version\|author\|return\|deprecated\|serial\|serialField\|serialData\)\>" + syntax case match +endif + +" match the special comment /**/ +syn match groovyComment "/\*\*/" + +" Strings and constants +syn match groovySpecialError contained "\\." +syn match groovySpecialCharError contained "[^']" +syn match groovySpecialChar contained "\\\([4-9]\d\|[0-3]\d\d\|[\"\\'ntbrf]\|u\x\{4\}\)" +syn region groovyString start=+"+ end=+"+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr +syn region groovyString start=+'+ end=+'+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr +" syn region groovyELExpr start=+${+ end=+}+ keepend contained + syn match groovyELExpr /\${.\{-}}/ contained +GroovyHiLink groovyELExpr Identifier + +" TODO: better matching. I am waiting to understand how it really works in groovy +" syn region groovyClosureParamsBraces start=+|+ end=+|+ contains=groovyClosureParams +" syn match groovyClosureParams "[ a-zA-Z0-9_*]\+" contained +" GroovyHiLink groovyClosureParams Identifier + +" next line disabled, it can cause a crash for a long line +"syn match groovyStringError +"\([^"\\]\|\\.\)*$+ + +" disabled: in groovy strings or characters are written the same +" syn match groovyCharacter "'[^']*'" contains=groovySpecialChar,groovySpecialCharError +" syn match groovyCharacter "'\\''" contains=groovySpecialChar +" syn match groovyCharacter "'[^\\]'" +syn match groovyNumber "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>" +syn match groovyNumber "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\=" +syn match groovyNumber "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>" +syn match groovyNumber "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>" + +" unicode characters +syn match groovySpecial "\\u\d\{4\}" + +syn cluster groovyTop add=groovyString,groovyCharacter,groovyNumber,groovySpecial,groovyStringError + +if exists("groovy_highlight_functions") + if groovy_highlight_functions == "indent" + syn match groovyFuncDef "^\(\t\| \{8\}\)[_$a-zA-Z][_$a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses + syn region groovyFuncDef start=+^\(\t\| \{8\}\)[$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses + syn match groovyFuncDef "^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses + syn region groovyFuncDef start=+^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses + else + " This line catches method declarations at any indentation>0, but it assumes + " two things: + " 1. class names are always capitalized (ie: Button) + " 2. method names are never capitalized (except constructors, of course) + syn region groovyFuncDef start=+^\s\+\(\(public\|protected\|private\|static\|abstract\|final\|native\|synchronized\)\s\+\)*\(\(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^>]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*([^0-9]+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,groovyComment,groovyLineComment,@groovyClasses + endif + syn match groovyBraces "[{}]" + syn cluster groovyTop add=groovyFuncDef,groovyBraces +endif + +if exists("groovy_highlight_debug") + + " Strings and constants + syn match groovyDebugSpecial contained "\\\d\d\d\|\\." + syn region groovyDebugString contained start=+"+ end=+"+ contains=groovyDebugSpecial + syn match groovyDebugStringError +"\([^"\\]\|\\.\)*$+ + syn match groovyDebugCharacter contained "'[^\\]'" + syn match groovyDebugSpecialCharacter contained "'\\.'" + syn match groovyDebugSpecialCharacter contained "'\\''" + syn match groovyDebugNumber contained "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>" + syn match groovyDebugNumber contained "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\=" + syn match groovyDebugNumber contained "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>" + syn match groovyDebugNumber contained "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>" + syn keyword groovyDebugBoolean contained true false + syn keyword groovyDebugType contained null this super + syn region groovyDebugParen start=+(+ end=+)+ contained contains=groovyDebug.*,groovyDebugParen + + " to make this work you must define the highlighting for these groups + syn match groovyDebug "\= 508 || !exists("did_c_syn_inits") + GroovyHiLink groovyDebug Debug + GroovyHiLink groovyDebugString DebugString + GroovyHiLink groovyDebugStringError groovyError + GroovyHiLink groovyDebugType DebugType + GroovyHiLink groovyDebugBoolean DebugBoolean + GroovyHiLink groovyDebugNumber Debug + GroovyHiLink groovyDebugSpecial DebugSpecial + GroovyHiLink groovyDebugSpecialCharacter DebugSpecial + GroovyHiLink groovyDebugCharacter DebugString + GroovyHiLink groovyDebugParen Debug + + GroovyHiLink DebugString String + GroovyHiLink DebugSpecial Special + GroovyHiLink DebugBoolean Boolean + GroovyHiLink DebugType Type + endif +endif + +" Match all Exception classes +syn match groovyExceptions "\\|\<[A-Z]\{1,}[a-zA-Z0-9]*Exception\>" + + +if !exists("groovy_minlines") + let groovy_minlines = 10 +endif +exec "syn sync ccomment groovyComment minlines=" . groovy_minlines + + +" ################### +" Groovy stuff +" syn match groovyOperator "|[ ,a-zA-Z0-9_*]\+|" + +" All groovy valid tokens +" syn match groovyTokens ";\|,\|<=>\|<>\|:\|:=\|>\|>=\|=\|==\|<\|<=\|!=\|/\|/=\|\.\.|\.\.\.\|\~=\|\~==" +" syn match groovyTokens "\*=\|&\|&=\|\*\|->\|\~\|+\|-\|/\|?\|<<<\|>>>\|<<\|>>" + +" Must put explicit these ones because groovy.vim mark them as errors otherwise +" syn match groovyTokens "<=>\|<>\|==\~" +"syn cluster groovyTop add=groovyTokens + +" Mark these as operators + +" Hightlight brackets +" syn match groovyBraces "[{}]" +" syn match groovyBraces "[\[\]]" +" syn match groovyBraces "[\|]" + +if exists("groovy_mark_braces_in_parens_as_errors") + syn match groovyInParen contained "[{}]" + GroovyHiLink groovyInParen groovyError + syn cluster groovyTop add=groovyInParen +endif + +" catch errors caused by wrong parenthesis +syn region groovyParenT transparent matchgroup=groovyParen start="(" end=")" contains=@groovyTop,groovyParenT1 +syn region groovyParenT1 transparent matchgroup=groovyParen1 start="(" end=")" contains=@groovyTop,groovyParenT2 contained +syn region groovyParenT2 transparent matchgroup=groovyParen2 start="(" end=")" contains=@groovyTop,groovyParenT contained +syn match groovyParenError ")" +GroovyHiLink groovyParenError groovyError + +" catch errors caused by wrong square parenthesis +syn region groovyParenT transparent matchgroup=groovyParen start="\[" end="\]" contains=@groovyTop,groovyParenT1 +syn region groovyParenT1 transparent matchgroup=groovyParen1 start="\[" end="\]" contains=@groovyTop,groovyParenT2 contained +syn region groovyParenT2 transparent matchgroup=groovyParen2 start="\[" end="\]" contains=@groovyTop,groovyParenT contained +syn match groovyParenError "\]" + +" ############################### +" java.vim default highlighting +if version >= 508 || !exists("did_groovy_syn_inits") + if version < 508 + let did_groovy_syn_inits = 1 + endif + GroovyHiLink groovyFuncDef Function + GroovyHiLink groovyBraces Function + GroovyHiLink groovyBranch Conditional + GroovyHiLink groovyUserLabelRef groovyUserLabel + GroovyHiLink groovyLabel Label + GroovyHiLink groovyUserLabel Label + GroovyHiLink groovyConditional Conditional + GroovyHiLink groovyRepeat Repeat + GroovyHiLink groovyExceptions Exception + GroovyHiLink groovyAssert Statement + GroovyHiLink groovyStorageClass StorageClass + GroovyHiLink groovyMethodDecl groovyStorageClass + GroovyHiLink groovyClassDecl groovyStorageClass + GroovyHiLink groovyScopeDecl groovyStorageClass + GroovyHiLink groovyBoolean Boolean + GroovyHiLink groovySpecial Special + GroovyHiLink groovySpecialError Error + GroovyHiLink groovySpecialCharError Error + GroovyHiLink groovyString String + GroovyHiLink groovyCharacter Character + GroovyHiLink groovySpecialChar SpecialChar + GroovyHiLink groovyNumber Number + GroovyHiLink groovyError Error + GroovyHiLink groovyStringError Error + GroovyHiLink groovyStatement Statement + GroovyHiLink groovyOperator Operator + GroovyHiLink groovyComment Comment + GroovyHiLink groovyDocComment Comment + GroovyHiLink groovyLineComment Comment + GroovyHiLink groovyConstant Constant + GroovyHiLink groovyTypedef Typedef + GroovyHiLink groovyTodo Todo + + GroovyHiLink groovyCommentTitle SpecialComment + GroovyHiLink groovyDocTags Special + GroovyHiLink groovyDocParam Function + GroovyHiLink groovyCommentStar groovyComment + + GroovyHiLink groovyType Type + GroovyHiLink groovyExternal Include + + GroovyHiLink htmlComment Special + GroovyHiLink htmlCommentPart Special + GroovyHiLink groovySpaceError Error + GroovyHiLink groovyJDKBuiltin Special + GroovyHiLink groovyJDKOperOverl Operator + GroovyHiLink groovyJDKMethods Function +endif + +delcommand GroovyHiLink + + +let b:current_syntax = "groovy" +if main_syntax == 'groovy' + unlet main_syntax +endif + +let b:spell_options="contained" + +" vim: ts=8 diff --git a/vimrc b/vimrc index 561751b..40e8e57 100644 --- a/vimrc +++ b/vimrc @@ -240,6 +240,15 @@ let g:airline#extensions#tabline#left_sep = ' ' let g:airline#extensions#tabline#left_alt_sep = ' ' +"------ Text File Settings ------ +:autocmd! BufNewFile,BufRead *.txt,*.md,*.tex set wrap + + +"------ Jenkins Settings ------ +au BufReadPost Jenkinsfile set syntax=groovy +au BufReadPost Jenkinsfile set filetype=groovy + + "------ GUI Options ------ if has("gui_running") " Hides toolbar and scrollbars and File menu From 02a002ef898d42085d879ba5f44fdd1bf17fa93d Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Wed, 8 Feb 2017 14:08:22 -0800 Subject: [PATCH 107/177] gitgutter and nerdtree-git-plugin --- bundle/gitgutter/.gitignore | 5 + bundle/gitgutter/LICENCE | 22 + bundle/gitgutter/README.mkd | 499 ++++++++++++++++++ bundle/gitgutter/autoload/gitgutter.vim | 259 +++++++++ bundle/gitgutter/autoload/gitgutter/async.vim | 207 ++++++++ bundle/gitgutter/autoload/gitgutter/debug.vim | 119 +++++ bundle/gitgutter/autoload/gitgutter/diff.vim | 342 ++++++++++++ .../autoload/gitgutter/highlight.vim | 115 ++++ bundle/gitgutter/autoload/gitgutter/hunk.vim | 137 +++++ bundle/gitgutter/autoload/gitgutter/sign.vim | 179 +++++++ .../gitgutter/autoload/gitgutter/utility.vim | 208 ++++++++ bundle/gitgutter/doc/gitgutter.txt | 341 ++++++++++++ bundle/gitgutter/plugin/gitgutter.vim | 241 +++++++++ bundle/gitgutter/screenshot.png | Bin 0 -> 16191 bytes bundle/gitgutter/test/fixture.txt | 11 + bundle/gitgutter/test/runner.vim | 162 ++++++ bundle/gitgutter/test/test | 19 + bundle/gitgutter/test/test_gitgutter.vim | 400 ++++++++++++++ bundle/nerdtree-git-plugin/README.md | 65 +++ .../nerdtree_plugin/git_status.vim | 340 ++++++++++++ vimrc | 6 +- 21 files changed, 3676 insertions(+), 1 deletion(-) create mode 100644 bundle/gitgutter/.gitignore create mode 100644 bundle/gitgutter/LICENCE create mode 100644 bundle/gitgutter/README.mkd create mode 100644 bundle/gitgutter/autoload/gitgutter.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/async.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/debug.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/diff.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/highlight.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/hunk.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/sign.vim create mode 100644 bundle/gitgutter/autoload/gitgutter/utility.vim create mode 100644 bundle/gitgutter/doc/gitgutter.txt create mode 100644 bundle/gitgutter/plugin/gitgutter.vim create mode 100644 bundle/gitgutter/screenshot.png create mode 100644 bundle/gitgutter/test/fixture.txt create mode 100644 bundle/gitgutter/test/runner.vim create mode 100755 bundle/gitgutter/test/test create mode 100644 bundle/gitgutter/test/test_gitgutter.vim create mode 100644 bundle/nerdtree-git-plugin/README.md create mode 100644 bundle/nerdtree-git-plugin/nerdtree_plugin/git_status.vim diff --git a/bundle/gitgutter/.gitignore b/bundle/gitgutter/.gitignore new file mode 100644 index 0000000..82fb253 --- /dev/null +++ b/bundle/gitgutter/.gitignore @@ -0,0 +1,5 @@ +/doc/tags +/misc +/test/*.actual +*.log + diff --git a/bundle/gitgutter/LICENCE b/bundle/gitgutter/LICENCE new file mode 100644 index 0000000..38e2dc2 --- /dev/null +++ b/bundle/gitgutter/LICENCE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) Andrew Stewart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/bundle/gitgutter/README.mkd b/bundle/gitgutter/README.mkd new file mode 100644 index 0000000..19ed387 --- /dev/null +++ b/bundle/gitgutter/README.mkd @@ -0,0 +1,499 @@ +## vim-gitgutter + +A Vim plugin which shows a git diff in the 'gutter' (sign column). It shows whether each line has been added, modified, and where lines have been removed. You can also stage and undo individual hunks. + +Features: + +* Shows signs for added, modified, and removed lines. +* Runs the diffs asynchronously in terminal Vim/MacVim (7.4.1826+), gVim (7.4.1850+), MacVim GUI (7.4.1832+), and NeoVim. +* Ensures signs are always as up to date as possible (but without running more than necessary). +* Quick jumping between blocks of changed lines ("hunks"). +* Stage/undo/preview individual hunks. +* Provides a hunk text object. +* Diffs against index (default) or any commit. +* Handles line endings correctly, even with repos that do CRLF conversion. +* Optional line highlighting. +* Fully customisable (signs, sign column, line highlights, mappings, extra git-diff arguments, etc). +* Can be toggled on/off. +* Preserves signs from other plugins. +* Easy to integrate diff stats into status line; built-in integration with [vim-airline](https://github.com/bling/vim-airline/). +* Works with fish shell (in addition to the usual shells). + +Constraints: + +* Supports git only. + +If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify). + + +### Screenshot + +![screenshot](https://raw.github.com/airblade/vim-gitgutter/master/screenshot.png) + +In the screenshot above you can see: + +* Line 15 has been modified. +* Lines 21-24 are new. +* A line or lines were removed between lines 25 and 26. + + +### Installation + +Before installation, please check your Vim supports signs by running `:echo has('signs')`. `1` means you're all set; `0` means you need to install a Vim with signs support. If you're compiling Vim yourself you need the 'big' or 'huge' feature set. [MacVim][] supports signs. + +You install vim-gitgutter like any other vim plugin. + +##### Pathogen + +``` +cd ~/.vim/bundle +git clone git://github.com/airblade/vim-gitgutter.git +``` + +##### Voom + +Edit your plugin manifest (`voom edit`) and add: + +``` +airblade/vim-gitgutter +``` + +##### VimPlug + +Place this in your .vimrc: + +```viml +Plug 'airblade/vim-gitgutter' +``` + +Then run the following in Vim: + +``` +:source % +:PlugInstall +``` + +##### NeoBundle + +Place this in your .vimrc: + +```viml +NeoBundle 'airblade/vim-gitgutter' +``` + +Then run the following in Vim: + +``` +:source % +:NeoBundleInstall +``` + +##### No plugin manager + +Copy vim-gitgutter's subdirectories into your vim configuration directory: + +``` +cd /tmp && git clone git://github.com/airblade/vim-gitgutter.git +cp -r vim-gitgutter/* ~/.vim/ +``` + +See `:help add-global-plugin`. + + +If you are on Windows you may find the command prompt pops up briefly every time vim-gitgutter runs. You can avoid this by installing both [vim-misc](https://github.com/xolox/vim-misc) and [vim-shell](https://github.com/xolox/vim-shell). If you have those two plugins but don't want vim-gitgutter to use them, you can opt out with `let g:gitgutter_avoid_cmd_prompt_on_windows = 0` in your `~/.vimrc`. + + +### Getting started + +When you make a change to a file tracked by git, the diff markers should appear automatically. The delay is governed by vim's `updatetime` option; the default value is 4 seconds but I suggest reducing it to around 250ms (add `set updatetime=250` to your vimrc). + +You can jump between hunks with `[c` and `]c`. You can preview, stage, and undo hunks with `hp`, `hs`, and `hu` respectively. + +You cannot currently unstage a staged hunk. + + +#### Activation + +You can explicitly turn vim-gitgutter off and on (defaults to on): + +* turn off with `:GitGutterDisable` +* turn on with `:GitGutterEnable` +* toggle with `:GitGutterToggle`. + +You can turn the signs on and off (defaults to on): + +* turn on with `:GitGutterSignsEnable` +* turn off with `:GitGutterSignsDisable` +* toggle with `:GitGutterSignsToggle`. + +And you can turn line highlighting on and off (defaults to off): + +* turn on with `:GitGutterLineHighlightsEnable` +* turn off with `:GitGutterLineHighlightsDisable` +* toggle with `:GitGutterLineHighlightsToggle`. + +Note that if you have line highlighting on and signs off, you will have an empty sign column – more accurately, a sign column with invisible signs. This is because line highlighting requires signs and Vim always shows the sign column even if the signs are invisible. + +If you switch off both line highlighting and signs, you won't see the sign column. That is unless you have set `let g:gitgutter_sign_column_always = 1` so it's always there. + +To keep your Vim snappy, vim-gitgutter will suppress itself when a file has more than 500 changes. As soon as the number of changes falls below the limit vim-gitgutter will show the signs again. You can configure the threshold with: + +```viml +let g:gitgutter_max_signs = 500 " default value +``` + +#### Hunks + +You can jump between hunks: + +* jump to next hunk (change): `]c` +* jump to previous hunk (change): `[c`. + +Both of those take a preceding count. + +To set your own mappings for these, for example `]h` and `[h`: + +```viml +nmap ]h GitGutterNextHunk +nmap [h GitGutterPrevHunk +``` + +You can stage or undo an individual hunk when your cursor is in it: + +* stage the hunk with `hs` or +* undo it with `hu`. + +See the FAQ if you want to unstage staged changes. + +The `.` command will work with both these if you install [repeat.vim](https://github.com/tpope/vim-repeat). + +To set your own mappings for these, for example if you prefer the mnemonics hunk-add and hunk-revert: + +```viml +nmap ha GitGutterStageHunk +nmap hr GitGutterUndoHunk +``` + +And you can preview a hunk's changes with `hp`. You can of course change this mapping, e.g: + +```viml +nmap hv GitGutterPreviewHunk +``` + +A hunk text object is provided which works in visual and operator-pending modes. + +- `ic` operates on all lines in the current hunk. +- `ac` operates on all lines in the current hunk and any trailing empty lines. + +To re-map these, for example to `ih` and `ah`: + +```viml +omap ih GitGutterTextObjectInnerPending +omap ah GitGutterTextObjectOuterPending +xmap ih GitGutterTextObjectInnerVisual +xmap ah GitGutterTextObjectOuterVisual +``` + +If you don't want vim-gitgutter to set up any mappings at all, use this: + +```viml +let g:gitgutter_map_keys = 0 +``` + +Finally, you can force vim-gitgutter to update its signs across all visible buffers with `:GitGutterAll`. + +See the customisation section below for how to change the defaults. + + +### When are the signs updated? + +By default the signs are updated as follows: + +| Event | Reason for update | Configuration | +|---------------------------|--------------------------------------|------------------------| +| Stop typing | So the signs are real time | `g:gitgutter_realtime` | +| Switch buffer | To notice change to git index | `g:gitgutter_eager` | +| Switch tab | To notice change to git index | `g:gitgutter_eager` | +| Focus the GUI | To notice change to git index | `g:gitgutter_eager` (not gVim on Windows) | +| Read a file into a buffer | To display initial signs | [always] | +| Save a buffer | So non-realtime signs are up to date | [always] | +| Change a file outside Vim | To notice `git stash` | [always] | + +The length of time Vim waits after you stop typing before it triggers the plugin is governed by the setting `updatetime`. This defaults to `4000` milliseconds which is rather too long. I recommend around `250` milliseconds but it depends on your system and your preferences. Note that in terminal Vim pre-7.4.427 an `updatetime` of less than approximately `1000` milliseconds can lead to random highlighting glitches; the lower the `updatetime`, the more glitches. + +If you experience a lag, you can trade speed for accuracy: + +```viml +let g:gitgutter_realtime = 0 +let g:gitgutter_eager = 0 +``` + +Note the realtime updating requires Vim 7.3.105 or higher. + + +### Customisation + +You can customise: + +* The sign column's colours +* Whether or not the sign column is shown when there aren't any signs (defaults to no) +* The signs' colours and symbols +* Line highlights +* The base of the diff +* Extra arguments for `git diff` +* Key mappings +* Whether or not vim-gitgutter is on initially (defaults to on) +* Whether or not signs are shown (defaults to yes) +* Whether or not line highlighting is on initially (defaults to off) +* Whether or not vim-gitgutter runs in "realtime" (defaults to yes) +* Whether or not vim-gitgutter runs eagerly (defaults to yes) +* Whether or not vim-gitgutter runs asynchronously (defaults to yes) + +Please note that vim-gitgutter won't override any colours or highlights you've set in your colorscheme. + + +#### Sign column + +By default vim-gitgutter will make the sign column look like the line number column. + +To customise your sign column's background color, first tell vim-gitgutter to leave it alone: + +```viml +let g:gitgutter_override_sign_column_highlight = 0 +``` + +And then either update your colorscheme's `SignColumn` highlight group or set it in your vimrc: + +```viml +highlight SignColumn ctermbg=whatever " terminal Vim +highlight SignColumn guibg=whatever " gVim/MacVim +``` + +By default the sign column will appear when there are signs to show and disappear when there aren't. If you would always like the sign column to be there, add `let g:gitgutter_sign_column_always = 1` to your `~/.vimrc`. + + +#### Signs' colours and symbols + +To customise the colours, set up the following highlight groups in your colorscheme or `~/.vimrc`: + +```viml +GitGutterAdd " an added line +GitGutterChange " a changed line +GitGutterDelete " at least one removed line +GitGutterChangeDelete " a changed line followed by at least one removed line +``` + +You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd DiffAdd`. + +To customise the symbols, add the following to your `~/.vimrc`: + +```viml +let g:gitgutter_sign_added = 'xx' +let g:gitgutter_sign_modified = 'yy' +let g:gitgutter_sign_removed = 'zz' +let g:gitgutter_sign_removed_first_line = '^^' +let g:gitgutter_sign_modified_removed = 'ww' +``` + + +#### Line highlights + +Similarly to the signs' colours, set up the following highlight groups in your colorscheme or `~/.vimrc`: + +```viml +GitGutterAddLine " default: links to DiffAdd +GitGutterChangeLine " default: links to DiffChange +GitGutterDeleteLine " default: links to DiffDelete +GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault, i.e. DiffChange +``` + + +#### The base of the diff + +By default buffers are diffed against the index. However you can diff against any commit by setting: + +```viml +let g:gitgutter_diff_base = '' +``` + + +#### Extra arguments for `git diff` + +If you want to pass extra arguments to `git diff`, for example to ignore whitespace, do so like this: + +```viml +let g:gitgutter_diff_args = '-w' +``` + +#### Key mappings + +To disable all key mappings: + +```viml +let g:gitgutter_map_keys = 0 +``` + +See above for configuring maps for hunk-jumping and staging/undoing. + + +#### Use a custom `grep` command + +If you use an alternative to grep, or your grep does not support the `color` flag, you can tell vim-gitgutter to use it here. It only needs to support extended POSIX regex. + +```viml +" Default: +let g:gitgutter_grep_command = 'grep --color=never -e' +``` + +#### To turn off vim-gitgutter by default + +Add `let g:gitgutter_enabled = 0` to your `~/.vimrc`. + + +#### To turn off signs by default + +Add `let g:gitgutter_signs = 0` to your `~/.vimrc`. + + +#### To turn on line highlighting by default + +Add `let g:gitgutter_highlight_lines = 1` to your `~/.vimrc`. + + +#### To turn off asynchronous updates + +By default diffs are run asynchronously. To run diffs synchronously instead: + +```viml +let g:gitgutter_async = 0 +``` + + +### Extensions + +#### Operate on every line in a hunk + +You can map an operator to do whatever you want to every line in a hunk. + +Let's say, for example, you want to remove trailing whitespace. + +```viml +function! CleanUp(...) + if a:0 " opfunc + let [first, last] = [line("'["), line("']")] + else + let [first, last] = [line("'<"), line("'>")] + endif + for lnum in range(first, last) + let line = getline(lnum) + + " clean up the text, e.g.: + let line = substitute(line, '\s\+$', '', '') + + call setline(lnum, line) + endfor +endfunction + +nmap x :set opfunc=CleanUpg@ +``` + +Then place your cursor in a hunk and type `\xic` (assuming a leader of `\`). + +Alternatively you could place your cursor in a hunk, type `vic` to select it, then `:call CleanUp()`. + + +#### Operate on every changed line in a file + +You can write a command to do whatever you want to every changed line in a file. + +```viml +function! GlobalChangedLines(ex_cmd) + for hunk in GitGutterGetHunks() + for lnum in range(hunk[2], hunk[2]+hunk[3]-1) + let cursor = getcurpos() + silent! execute lnum.a:ex_cmd + call setpos('.', cursor) + endfor + endfor +endfunction + +command -nargs=1 Glines call GlobalChangedLines() +``` + +Let's say, for example, you want to remove trailing whitespace from all changed lines: + +```viml +:Glines s/\s\+$// +``` + + +### FAQ + +> Why can't I unstage staged changes? + +Unstaging staged hunks is feasible but not quite as easy as it sounds. There are three relevant versions of a file at any one time: + +1. The version at HEAD in the repo. +2. The version staged in the index. +3. The version in the working tree, in your vim buffer. + +`git-diff` without arguments shows you how 3 and 2 differ; this is what vim-gitgutter shows too. + +`git-diff --staged` shows you how 2 and 1 differ. + +Let's say you are looking at a file in vim which has some unstaged changes. Now you stage a hunk, either via vim-gitgutter or another means. The hunk is no longer marked in vim-gitgutter because it is the same in 3 and 2. + +Now you want to unstage that hunk. To see it, you need the difference between 2 and 1. For vim-gitgutter to show those differences, it would need to show you 2 instead of 3 in your vim buffer. But 2 is virtual so vim-gitgutter would need to handle it without touching 3. + +I intend to implement this but I can't commit to any deadline. + +> Why are the colours in the sign column weird? + +Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column. + +> There's a noticeable lag when vim-gitter runs; how can I avoid it? + +By default vim-gitgutter runs often so the signs are as accurate as possible. The delay is governed by `updatetime`; see [above](#when-are-the-signs-updated) for more information. + +If you don't want realtime updates and would like to trade a little accuracy for speed, add this to your `~/.vimrc`: + +```viml +let g:gitgutter_realtime = 0 +let g:gitgutter_eager = 0 +``` + +> What happens if I also use another plugin which uses signs (e.g. Syntastic)? + +Vim only allows one sign per line. Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else. If so it doesn't do anything. In other words vim-gitgutter won't overwrite another plugin's signs. It also won't remove another plugin's signs. + +> Why aren't any signs showing at all? + +Here are some things you can check: + +* `:echo system("git --version")` succeeds. +* Your git config is compatible with the version of git returned by the command above. +* Your Vim supports signs (`:echo has('signs')` should give `1`). +* Your file is being tracked by git and has unstaged changes. +* If your grep does not support the `color` flag, add `let g:gitgutter_grep_command = 'grep -e'` to your `~/.vimrc`. + + +### Shameless Plug + +If this plugin has helped you, or you'd like to learn more about Vim, why not check out this screencast I wrote for PeepCode: + +* [Smash Into Vim][siv] + +This was one of PeepCode's all-time top three bestsellers and is now available at Pluralsight. + +You can read reviews on my [website][airblade]. + + +### Intellectual Property + +Copyright Andrew Stewart, AirBlade Software Ltd. Released under the MIT licence. + + + [pathogen]: https://github.com/tpope/vim-pathogen + [siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim + [airblade]: http://airbladesoftware.com/peepcode-vim + [macvim]: http://code.google.com/p/macvim/ diff --git a/bundle/gitgutter/autoload/gitgutter.vim b/bundle/gitgutter/autoload/gitgutter.vim new file mode 100644 index 0000000..0a05a6a --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter.vim @@ -0,0 +1,259 @@ +let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '' : '' + +" Primary functions {{{ + +function! gitgutter#all() abort + for buffer_id in gitgutter#utility#dedup(tabpagebuflist()) + let file = expand('#' . buffer_id . ':p') + if !empty(file) + call gitgutter#process_buffer(buffer_id, 0) + endif + endfor +endfunction + +" bufnr: (integer) the buffer to process. +" realtime: (boolean) when truthy, do a realtime diff; otherwise do a disk-based diff. +function! gitgutter#process_buffer(bufnr, realtime) abort + call gitgutter#utility#use_known_shell() + + call gitgutter#utility#set_buffer(a:bufnr) + if gitgutter#utility#is_active() + if g:gitgutter_sign_column_always + call gitgutter#sign#add_dummy_sign() + endif + try + if !a:realtime || gitgutter#utility#has_fresh_changes() + let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(), 0) + if diff != 'async' + call gitgutter#handle_diff(diff) + endif + endif + catch /diff failed/ + call gitgutter#debug#log('diff failed') + call gitgutter#hunk#reset() + endtry + execute "silent doautocmd" s:nomodeline "User GitGutter" + else + call gitgutter#hunk#reset() + endif + + call gitgutter#utility#restore_shell() +endfunction + + +function! gitgutter#handle_diff(diff) abort + call gitgutter#debug#log(a:diff) + + call setbufvar(gitgutter#utility#bufnr(), 'gitgutter_tracked', 1) + + call gitgutter#hunk#set_hunks(gitgutter#diff#parse_diff(a:diff)) + let modified_lines = gitgutter#diff#process_hunks(gitgutter#hunk#hunks()) + + if len(modified_lines) > g:gitgutter_max_signs + call gitgutter#utility#warn_once('exceeded maximum number of signs (configured by g:gitgutter_max_signs).', 'max_signs') + call gitgutter#sign#clear_signs() + return + endif + + if g:gitgutter_signs || g:gitgutter_highlight_lines + call gitgutter#sign#update_signs(modified_lines) + endif + + call gitgutter#utility#save_last_seen_change() +endfunction + +function! gitgutter#disable() abort + " get list of all buffers (across all tabs) + let buflist = [] + for i in range(tabpagenr('$')) + call extend(buflist, tabpagebuflist(i + 1)) + endfor + + for buffer_id in gitgutter#utility#dedup(buflist) + let file = expand('#' . buffer_id . ':p') + if !empty(file) + call gitgutter#utility#set_buffer(buffer_id) + call gitgutter#sign#clear_signs() + call gitgutter#sign#remove_dummy_sign(1) + call gitgutter#hunk#reset() + endif + endfor + + let g:gitgutter_enabled = 0 +endfunction + +function! gitgutter#enable() abort + let g:gitgutter_enabled = 1 + call gitgutter#all() +endfunction + +function! gitgutter#toggle() abort + if g:gitgutter_enabled + call gitgutter#disable() + else + call gitgutter#enable() + endif +endfunction + +" }}} + +" Line highlights {{{ + +function! gitgutter#line_highlights_disable() abort + let g:gitgutter_highlight_lines = 0 + call gitgutter#highlight#define_sign_line_highlights() + + if !g:gitgutter_signs + call gitgutter#sign#clear_signs() + call gitgutter#sign#remove_dummy_sign(0) + endif + + redraw! +endfunction + +function! gitgutter#line_highlights_enable() abort + let old_highlight_lines = g:gitgutter_highlight_lines + + let g:gitgutter_highlight_lines = 1 + call gitgutter#highlight#define_sign_line_highlights() + + if !old_highlight_lines && !g:gitgutter_signs + call gitgutter#all() + endif + + redraw! +endfunction + +function! gitgutter#line_highlights_toggle() abort + if g:gitgutter_highlight_lines + call gitgutter#line_highlights_disable() + else + call gitgutter#line_highlights_enable() + endif +endfunction + +" }}} + +" Signs {{{ + +function! gitgutter#signs_enable() abort + let old_signs = g:gitgutter_signs + + let g:gitgutter_signs = 1 + call gitgutter#highlight#define_sign_text_highlights() + + if !old_signs && !g:gitgutter_highlight_lines + call gitgutter#all() + endif +endfunction + +function! gitgutter#signs_disable() abort + let g:gitgutter_signs = 0 + call gitgutter#highlight#define_sign_text_highlights() + + if !g:gitgutter_highlight_lines + call gitgutter#sign#clear_signs() + call gitgutter#sign#remove_dummy_sign(0) + endif +endfunction + +function! gitgutter#signs_toggle() abort + if g:gitgutter_signs + call gitgutter#signs_disable() + else + call gitgutter#signs_enable() + endif +endfunction + +" }}} + +" Hunks {{{ + +function! gitgutter#stage_hunk() abort + call gitgutter#utility#use_known_shell() + if gitgutter#utility#is_active() + " Ensure the working copy of the file is up to date. + " It doesn't make sense to stage a hunk otherwise. + noautocmd silent write + let diff = gitgutter#diff#run_diff(0, 1) + call gitgutter#handle_diff(diff) + + if empty(gitgutter#hunk#current_hunk()) + call gitgutter#utility#warn('cursor is not in a hunk') + else + let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'stage') + call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --cached --unidiff-zero - '), diff_for_hunk) + + " refresh gitgutter's view of buffer + silent execute "GitGutter" + endif + + silent! call repeat#set("\GitGutterStageHunk", -1) + endif + call gitgutter#utility#restore_shell() +endfunction + +function! gitgutter#undo_hunk() abort + call gitgutter#utility#use_known_shell() + if gitgutter#utility#is_active() + " Ensure the working copy of the file is up to date. + " It doesn't make sense to stage a hunk otherwise. + noautocmd silent write + let diff = gitgutter#diff#run_diff(0, 1) + call gitgutter#handle_diff(diff) + + if empty(gitgutter#hunk#current_hunk()) + call gitgutter#utility#warn('cursor is not in a hunk') + else + let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'undo') + call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --reverse --unidiff-zero - '), diff_for_hunk) + + " reload file preserving screen line position + " CTRL-Y and CTRL-E treat negative counts as positive counts. + let x = line('w0') + silent edit + let y = line('w0') + let z = x - y + if z > 0 + execute "normal! ".z."\" + else + execute "normal! ".z."\" + endif + endif + + silent! call repeat#set("\GitGutterUndoHunk", -1) + endif + call gitgutter#utility#restore_shell() +endfunction + +function! gitgutter#preview_hunk() abort + call gitgutter#utility#use_known_shell() + if gitgutter#utility#is_active() + " Ensure the working copy of the file is up to date. + " It doesn't make sense to stage a hunk otherwise. + noautocmd silent write + let diff = gitgutter#diff#run_diff(0, 1) + call gitgutter#handle_diff(diff) + + if empty(gitgutter#hunk#current_hunk()) + call gitgutter#utility#warn('cursor is not in a hunk') + else + let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'preview') + + silent! wincmd P + if !&previewwindow + noautocmd execute 'bo' &previewheight 'new' + set previewwindow + endif + + setlocal noro modifiable filetype=diff buftype=nofile bufhidden=delete noswapfile + execute "%delete_" + call append(0, split(diff_for_hunk, "\n")) + + noautocmd wincmd p + endif + endif + call gitgutter#utility#restore_shell() +endfunction + +" }}} diff --git a/bundle/gitgutter/autoload/gitgutter/async.vim b/bundle/gitgutter/autoload/gitgutter/async.vim new file mode 100644 index 0000000..5b2428b --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/async.vim @@ -0,0 +1,207 @@ +let s:jobs = {} + +" Nvim has always supported async commands. +" +" Vim introduced async in 7.4.1826. +" +" gVim didn't support aync until 7.4.1850 (though I haven't been able to +" verify this myself). +" +" MacVim-GUI didn't support async until 7.4.1832 (actually commit +" 88f4fe0 but 7.4.1832 was the first subsequent patch release). +let s:available = has('nvim') || ( + \ has('job') && ( + \ (has('patch-7-4-1826') && !has('gui_running')) || + \ (has('patch-7-4-1850') && has('gui_running')) || + \ (has('patch-7-4-1832') && has('gui_macvim')) + \ ) + \ ) + +function! gitgutter#async#available() + return s:available +endfunction + +function! gitgutter#async#execute(cmd) abort + let bufnr = gitgutter#utility#bufnr() + + if has('nvim') + if has('unix') + let command = ["sh", "-c", a:cmd] + elseif has('win32') + let command = ["cmd.exe", "/c", a:cmd] + else + throw 'unknown os' + endif + " Make the job use a shell while avoiding (un)quoting problems. + let job_id = jobstart(command, { + \ 'buffer': bufnr, + \ 'on_stdout': function('gitgutter#async#handle_diff_job_nvim'), + \ 'on_stderr': function('gitgutter#async#handle_diff_job_nvim'), + \ 'on_exit': function('gitgutter#async#handle_diff_job_nvim') + \ }) + call gitgutter#debug#log('[nvim job: '.job_id.', buffer: '.bufnr.'] '.a:cmd) + if job_id < 1 + throw 'diff failed' + endif + + " Note that when `cmd` doesn't produce any output, i.e. the diff is empty, + " the `stdout` event is not fired on the job handler. Therefore we keep + " track of the jobs ourselves so we can spot empty diffs. + call s:job_started(job_id) + + else + " Make the job use a shell. + " + " Pass a handler for stdout but not for stderr so that errors are + " ignored (and thus signs are not updated; this assumes that an error + " only occurs when a file is not tracked by git). + + if has('unix') + let command = ["sh", "-c", a:cmd] + elseif has('win32') + let command = "cmd.exe /c ".a:cmd + else + throw 'unknown os' + endif + + let job = job_start(command, { + \ 'out_cb': 'gitgutter#async#handle_diff_job_vim', + \ 'close_cb': 'gitgutter#async#handle_diff_job_vim_close' + \ }) + call gitgutter#debug#log('[vim job: '.string(job_info(job)).', buffer: '.bufnr.'] '.a:cmd) + + call s:job_started(s:channel_id(job_getchannel(job)), bufnr) + endif +endfunction + + +function! gitgutter#async#handle_diff_job_nvim(job_id, data, event) dict abort + call gitgutter#debug#log('job_id: '.a:job_id.', event: '.a:event.', buffer: '.self.buffer) + + let job_bufnr = self.buffer + if bufexists(job_bufnr) + let current_buffer = gitgutter#utility#bufnr() + call gitgutter#utility#set_buffer(job_bufnr) + + if a:event == 'stdout' + " a:data is a list + call s:job_finished(a:job_id) + if gitgutter#utility#is_active() + call gitgutter#handle_diff(gitgutter#utility#stringify(a:data)) + endif + + elseif a:event == 'exit' + " If the exit event is triggered without a preceding stdout event, + " the diff was empty. + if s:is_job_started(a:job_id) + if gitgutter#utility#is_active() + call gitgutter#handle_diff("") + endif + call s:job_finished(a:job_id) + endif + + else " a:event is stderr + call gitgutter#hunk#reset() + call s:job_finished(a:job_id) + + endif + + call gitgutter#utility#set_buffer(current_buffer) + else + call s:job_finished(a:job_id) + endif +endfunction + + +" Channel is in NL mode. +function! gitgutter#async#handle_diff_job_vim(channel, line) abort + call gitgutter#debug#log('channel: '.a:channel.', line: '.a:line) + + call s:accumulate_job_output(s:channel_id(a:channel), a:line) +endfunction + +function! gitgutter#async#handle_diff_job_vim_close(channel) abort + call gitgutter#debug#log('channel: '.a:channel) + + let channel_id = s:channel_id(a:channel) + let job_bufnr = s:job_buffer(channel_id) + + if bufexists(job_bufnr) + let current_buffer = gitgutter#utility#bufnr() + call gitgutter#utility#set_buffer(job_bufnr) + + if gitgutter#utility#is_active() + call gitgutter#handle_diff(s:job_output(channel_id)) + endif + + call gitgutter#utility#set_buffer(current_buffer) + endif + call s:job_finished(channel_id) +endfunction + + +function! s:channel_id(channel) abort + return ch_info(a:channel)['id'] +endfunction + + +" +" Keep track of jobs. +" +" nvim: receives all the job's output at once so we don't need to accumulate +" it ourselves. We can pass the buffer number into the job so we don't need +" to track that either. +" +" s:jobs {} -> key: job's id, value: anything truthy +" +" vim: receives the job's output line by line so we need to accumulate it. +" We also need to keep track of the buffer the job is running for. +" Vim job's don't have an id. Instead we could use the external process's id +" or the channel's id (there seems to be 1 channel per job). Arbitrarily +" choose the channel's id. +" +" s:jobs {} -> key: channel's id, value: {} key: output, value: [] job's output +" key: buffer: value: buffer number + + +" nvim: +" id: job's id +" +" vim: +" id: channel's id +" arg: buffer number +function! s:job_started(id, ...) abort + if a:0 " vim + let s:jobs[a:id] = {'output': [], 'buffer': a:1} + else " nvim + let s:jobs[a:id] = 1 + endif +endfunction + +function! s:is_job_started(id) abort + return has_key(s:jobs, a:id) +endfunction + +function! s:accumulate_job_output(id, line) abort + call add(s:jobs[a:id].output, a:line) +endfunction + +" Returns a string +function! s:job_output(id) abort + if has_key(s:jobs, a:id) + return gitgutter#utility#stringify(s:jobs[a:id].output) + else + return "" + endif +endfunction + +function! s:job_buffer(id) abort + return s:jobs[a:id].buffer +endfunction + +function! s:job_finished(id) abort + if has_key(s:jobs, a:id) + unlet s:jobs[a:id] + endif +endfunction + diff --git a/bundle/gitgutter/autoload/gitgutter/debug.vim b/bundle/gitgutter/autoload/gitgutter/debug.vim new file mode 100644 index 0000000..594f044 --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/debug.vim @@ -0,0 +1,119 @@ +let s:plugin_dir = expand(':p:h:h:h').'/' +let s:log_file = s:plugin_dir.'gitgutter.log' +let s:channel_log = s:plugin_dir.'channel.log' +let s:new_log_session = 1 + + +function! gitgutter#debug#debug() + " Open a scratch buffer + vsplit __GitGutter_Debug__ + normal! ggdG + setlocal buftype=nofile + setlocal bufhidden=delete + setlocal noswapfile + + call gitgutter#debug#vim_version() + call gitgutter#debug#separator() + + call gitgutter#debug#git_version() + call gitgutter#debug#separator() + + call gitgutter#debug#grep_version() + call gitgutter#debug#separator() + + call gitgutter#debug#option('updatetime') + call gitgutter#debug#option('shell') + call gitgutter#debug#option('shellcmdflag') + call gitgutter#debug#option('shellpipe') + call gitgutter#debug#option('shellquote') + call gitgutter#debug#option('shellredir') + call gitgutter#debug#option('shellslash') + call gitgutter#debug#option('shelltemp') + call gitgutter#debug#option('shelltype') + call gitgutter#debug#option('shellxescape') + call gitgutter#debug#option('shellxquote') +endfunction + + +function! gitgutter#debug#separator() + call gitgutter#debug#output('') +endfunction + +function! gitgutter#debug#vim_version() + redir => version_info + silent execute 'version' + redir END + call gitgutter#debug#output(split(version_info, '\n')[0:2]) +endfunction + +function! gitgutter#debug#git_version() + let v = system(g:gitgutter_git_executable.' --version') + call gitgutter#debug#output( substitute(v, '\n$', '', '') ) +endfunction + +function! gitgutter#debug#grep_version() + let v = system('grep --version') + call gitgutter#debug#output( substitute(v, '\n$', '', '') ) + + let v = system('grep --help') + call gitgutter#debug#output( substitute(v, '\%x00', '', 'g') ) +endfunction + +function! gitgutter#debug#option(name) + if exists('+' . a:name) + let v = eval('&' . a:name) + call gitgutter#debug#output(a:name . '=' . v) + " redir => output + " silent execute "verbose set " . a:name . "?" + " redir END + " call gitgutter#debug#output(a:name . '=' . output) + else + call gitgutter#debug#output(a:name . ' [n/a]') + end +endfunction + +function! gitgutter#debug#output(text) + call append(line('$'), a:text) +endfunction + +" assumes optional args are calling function's optional args +function! gitgutter#debug#log(message, ...) abort + if g:gitgutter_log + if s:new_log_session && gitgutter#async#available() + if exists('*ch_logfile') + call ch_logfile(s:channel_log, 'w') + endif + endif + + execute 'redir >> '.s:log_file + if s:new_log_session + let s:start = reltime() + silent echo "\n==== start log session ====" + endif + + let elapsed = reltimestr(reltime(s:start)).' ' + silent echo '' + " callers excluding this function + silent echo elapsed.expand('')[:-22].':' + silent echo elapsed.s:format_for_log(a:message) + if a:0 && !empty(a:1) + for msg in a:000 + silent echo elapsed.s:format_for_log(msg) + endfor + endif + redir END + + let s:new_log_session = 0 + endif +endfunction + +function! s:format_for_log(data) abort + if type(a:data) == 1 + return join(split(a:data,'\n'),"\n") + elseif type(a:data) == 3 + return '['.join(a:data,"\n").']' + else + return a:data + endif +endfunction + diff --git a/bundle/gitgutter/autoload/gitgutter/diff.vim b/bundle/gitgutter/autoload/gitgutter/diff.vim new file mode 100644 index 0000000..170193b --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/diff.vim @@ -0,0 +1,342 @@ +if exists('g:gitgutter_grep_command') + let s:grep_available = 1 + let s:grep_command = g:gitgutter_grep_command +else + let s:grep_available = executable('grep') + if s:grep_available + let s:grep_command = 'grep --color=never -e' + endif +endif +let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@' + +let s:c_flag = gitgutter#utility#git_supports_command_line_config_override() + +let s:temp_index = tempname() +let s:temp_buffer = tempname() + +" Returns a diff of the buffer. +" +" The way to get the diff depends on whether the buffer is saved or unsaved. +" +" * Saved: the buffer contents is the same as the file on disk in the working +" tree so we simply do: +" +" git diff myfile +" +" * Unsaved: the buffer contents is not the same as the file on disk so we +" need to pass two instances of the file to git-diff: +" +" git diff myfileA myfileB +" +" The first instance is the file in the index which we obtain with: +" +" git show :myfile > myfileA +" +" The second instance is the buffer contents. Ideally we would pass this to +" git-diff on stdin via the second argument to vim's system() function. +" Unfortunately git-diff does not do CRLF conversion for input received on +" stdin, and git-show never performs CRLF conversion, so repos with CRLF +" conversion report that every line is modified due to mismatching EOLs. +" +" Instead, we write the buffer contents to a temporary file - myfileB in this +" example. Note the file extension must be preserved for the CRLF +" conversion to work. +" +" Before diffing a buffer for the first time, we check whether git knows about +" the file: +" +" git ls-files --error-unmatch myfile +" +" After running the diff we pass it through grep where available to reduce +" subsequent processing by the plugin. If grep is not available the plugin +" does the filtering instead. +function! gitgutter#diff#run_diff(realtime, preserve_full_diff) abort + " Wrap compound commands in parentheses to make Windows happy. + " bash doesn't mind the parentheses. + let cmd = '(' + + let bufnr = gitgutter#utility#bufnr() + let tracked = getbufvar(bufnr, 'gitgutter_tracked') " i.e. tracked by git + if !tracked + " Don't bother trying to realtime-diff an untracked file. + " NOTE: perhaps we should pull this guard up to the caller? + if a:realtime + throw 'diff failed' + else + let cmd .= g:gitgutter_git_executable.' ls-files --error-unmatch '.gitgutter#utility#shellescape(gitgutter#utility#filename()).' && (' + endif + endif + + if a:realtime + let blob_name = g:gitgutter_diff_base.':'.gitgutter#utility#shellescape(gitgutter#utility#file_relative_to_repo_root()) + let blob_file = s:temp_index + let buff_file = s:temp_buffer + let extension = gitgutter#utility#extension() + if !empty(extension) + let blob_file .= '.'.extension + let buff_file .= '.'.extension + endif + let cmd .= g:gitgutter_git_executable.' show '.blob_name.' > '.blob_file.' && ' + + " Writing the whole buffer resets the '[ and '] marks and also the + " 'modified' flag (if &cpoptions includes '+'). These are unwanted + " side-effects so we save and restore the values ourselves. + let modified = getbufvar(bufnr, "&mod") + let op_mark_start = getpos("'[") + let op_mark_end = getpos("']") + + execute 'keepalt noautocmd silent write!' buff_file + + call setbufvar(bufnr, "&mod", modified) + call setpos("'[", op_mark_start) + call setpos("']", op_mark_end) + endif + + let cmd .= g:gitgutter_git_executable + if s:c_flag + let cmd .= ' -c "diff.autorefreshindex=0"' + endif + let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' ' + + if a:realtime + let cmd .= ' -- '.blob_file.' '.buff_file + else + let cmd .= g:gitgutter_diff_base.' -- '.gitgutter#utility#shellescape(gitgutter#utility#filename()) + endif + + if !a:preserve_full_diff && s:grep_available + let cmd .= ' | '.s:grep_command.' '.gitgutter#utility#shellescape('^@@ ') + endif + + if (!a:preserve_full_diff && s:grep_available) || a:realtime + " grep exits with 1 when no matches are found; diff exits with 1 when + " differences are found. However we want to treat non-matches and + " differences as non-erroneous behaviour; so we OR the command with one + " which always exits with success (0). + let cmd .= ' || exit 0' + endif + + let cmd .= ')' + + if !tracked + let cmd .= ')' + endif + + let cmd = gitgutter#utility#command_in_directory_of_file(cmd) + + if g:gitgutter_async && gitgutter#async#available() && !a:preserve_full_diff + call gitgutter#async#execute(cmd) + return 'async' + + else + let diff = gitgutter#utility#system(cmd) + + if gitgutter#utility#shell_error() + " A shell error indicates the file is not tracked by git (unless something bizarre is going on). + throw 'diff failed' + endif + + return diff + endif +endfunction + +function! gitgutter#diff#parse_diff(diff) abort + let hunks = [] + for line in split(a:diff, '\n') + let hunk_info = gitgutter#diff#parse_hunk(line) + if len(hunk_info) == 4 + call add(hunks, hunk_info) + endif + endfor + return hunks +endfunction + +function! gitgutter#diff#parse_hunk(line) abort + let matches = matchlist(a:line, s:hunk_re) + if len(matches) > 0 + let from_line = str2nr(matches[1]) + let from_count = (matches[2] == '') ? 1 : str2nr(matches[2]) + let to_line = str2nr(matches[3]) + let to_count = (matches[4] == '') ? 1 : str2nr(matches[4]) + return [from_line, from_count, to_line, to_count] + else + return [] + end +endfunction + +function! gitgutter#diff#process_hunks(hunks) abort + call gitgutter#hunk#reset() + let modified_lines = [] + for hunk in a:hunks + call extend(modified_lines, gitgutter#diff#process_hunk(hunk)) + endfor + return modified_lines +endfunction + +" Returns [ [, ], ...] +function! gitgutter#diff#process_hunk(hunk) abort + let modifications = [] + let from_line = a:hunk[0] + let from_count = a:hunk[1] + let to_line = a:hunk[2] + let to_count = a:hunk[3] + + if gitgutter#diff#is_added(from_count, to_count) + call gitgutter#diff#process_added(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_added(to_count) + + elseif gitgutter#diff#is_removed(from_count, to_count) + call gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_removed(from_count) + + elseif gitgutter#diff#is_modified(from_count, to_count) + call gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_modified(to_count) + + elseif gitgutter#diff#is_modified_and_added(from_count, to_count) + call gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_added(to_count - from_count) + call gitgutter#hunk#increment_lines_modified(from_count) + + elseif gitgutter#diff#is_modified_and_removed(from_count, to_count) + call gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) + call gitgutter#hunk#increment_lines_modified(to_count) + call gitgutter#hunk#increment_lines_removed(from_count - to_count) + + endif + return modifications +endfunction + +function! gitgutter#diff#is_added(from_count, to_count) abort + return a:from_count == 0 && a:to_count > 0 +endfunction + +function! gitgutter#diff#is_removed(from_count, to_count) abort + return a:from_count > 0 && a:to_count == 0 +endfunction + +function! gitgutter#diff#is_modified(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count +endfunction + +function! gitgutter#diff#is_modified_and_added(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count +endfunction + +function! gitgutter#diff#is_modified_and_removed(from_count, to_count) abort + return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count +endfunction + +function! gitgutter#diff#process_added(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'added']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) abort + if a:to_line == 0 + call add(a:modifications, [1, 'removed_first_line']) + else + call add(a:modifications, [a:to_line, 'removed']) + endif +endfunction + +function! gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:from_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'added']) + let offset += 1 + endwhile +endfunction + +function! gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) abort + let offset = 0 + while offset < a:to_count + let line_number = a:to_line + offset + call add(a:modifications, [line_number, 'modified']) + let offset += 1 + endwhile + let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed'] +endfunction + +" Generates a zero-context diff for the current hunk. +" +" diff - the full diff for the buffer +" type - stage | undo | preview +function! gitgutter#diff#generate_diff_for_hunk(diff, type) abort + let diff_for_hunk = gitgutter#diff#discard_hunks(a:diff, a:type == 'stage' || a:type == 'undo') + + if a:type == 'stage' || a:type == 'undo' + let diff_for_hunk = gitgutter#diff#adjust_hunk_summary(diff_for_hunk, a:type == 'stage') + endif + + return diff_for_hunk +endfunction + +" Returns the diff with all hunks discarded except the current. +" +" diff - the diff to process +" keep_header - truthy to keep the diff header and hunk summary, falsy to discard it +function! gitgutter#diff#discard_hunks(diff, keep_header) abort + let modified_diff = [] + let keep_line = a:keep_header + for line in split(a:diff, '\n') + let hunk_info = gitgutter#diff#parse_hunk(line) + if len(hunk_info) == 4 " start of new hunk + let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info) + endif + if keep_line + call add(modified_diff, line) + endif + endfor + + if a:keep_header + return gitgutter#utility#stringify(modified_diff) + else + " Discard hunk summary too. + return gitgutter#utility#stringify(modified_diff[1:]) + endif +endfunction + +" Adjust hunk summary (from's / to's line number) to ignore changes above/before this one. +" +" diff_for_hunk - a diff containing only the hunk of interest +" staging - truthy if the hunk is to be staged, falsy if it is to be undone +" +" TODO: push this down to #discard_hunks? +function! gitgutter#diff#adjust_hunk_summary(diff_for_hunk, staging) abort + let line_adjustment = gitgutter#hunk#line_adjustment_for_current_hunk() + let adj_diff = [] + for line in split(a:diff_for_hunk, '\n') + if match(line, s:hunk_re) != -1 + if a:staging + " increment 'to' line number + let line = substitute(line, '+\@<=\(\d\+\)', '\=submatch(1)+line_adjustment', '') + else + " decrement 'from' line number + let line = substitute(line, '-\@<=\(\d\+\)', '\=submatch(1)-line_adjustment', '') + endif + endif + call add(adj_diff, line) + endfor + return gitgutter#utility#stringify(adj_diff) +endfunction + diff --git a/bundle/gitgutter/autoload/gitgutter/highlight.vim b/bundle/gitgutter/autoload/gitgutter/highlight.vim new file mode 100644 index 0000000..e3b774b --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/highlight.vim @@ -0,0 +1,115 @@ +function! gitgutter#highlight#define_sign_column_highlight() abort + if g:gitgutter_override_sign_column_highlight + highlight! link SignColumn LineNr + else + highlight default link SignColumn LineNr + endif +endfunction + +function! gitgutter#highlight#define_highlights() abort + let [guibg, ctermbg] = gitgutter#highlight#get_background_colors('SignColumn') + + " Highlights used by the signs. + + execute "highlight GitGutterAddDefault guifg=#009900 guibg=" . guibg . " ctermfg=2 ctermbg=" . ctermbg + execute "highlight GitGutterChangeDefault guifg=#bbbb00 guibg=" . guibg . " ctermfg=3 ctermbg=" . ctermbg + execute "highlight GitGutterDeleteDefault guifg=#ff2222 guibg=" . guibg . " ctermfg=1 ctermbg=" . ctermbg + highlight default link GitGutterChangeDeleteDefault GitGutterChangeDefault + + execute "highlight GitGutterAddInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + execute "highlight GitGutterChangeInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + execute "highlight GitGutterDeleteInvisible guifg=bg guibg=" . guibg . " ctermfg=" . ctermbg . " ctermbg=" . ctermbg + highlight default link GitGutterChangeDeleteInvisible GitGutterChangeInvisble + + highlight default link GitGutterAdd GitGutterAddDefault + highlight default link GitGutterChange GitGutterChangeDefault + highlight default link GitGutterDelete GitGutterDeleteDefault + highlight default link GitGutterChangeDelete GitGutterChangeDeleteDefault + + " Highlights used for the whole line. + + highlight default link GitGutterAddLine DiffAdd + highlight default link GitGutterChangeLine DiffChange + highlight default link GitGutterDeleteLine DiffDelete + highlight default link GitGutterChangeDeleteLine GitGutterChangeLine +endfunction + +function! gitgutter#highlight#define_signs() abort + sign define GitGutterLineAdded + sign define GitGutterLineModified + sign define GitGutterLineRemoved + sign define GitGutterLineRemovedFirstLine + sign define GitGutterLineModifiedRemoved + sign define GitGutterDummy + + call gitgutter#highlight#define_sign_text() + call gitgutter#highlight#define_sign_text_highlights() + call gitgutter#highlight#define_sign_line_highlights() +endfunction + +function! gitgutter#highlight#define_sign_text() abort + execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added + execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified + execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed + execute "sign define GitGutterLineRemovedFirstLine text=" . g:gitgutter_sign_removed_first_line + execute "sign define GitGutterLineModifiedRemoved text=" . g:gitgutter_sign_modified_removed +endfunction + +function! gitgutter#highlight#define_sign_text_highlights() abort + " Once a sign's text attribute has been defined, it cannot be undefined or + " set to an empty value. So to make signs' text disappear (when toggling + " off or disabling) we make them invisible by setting their foreground colours + " to the background's. + if g:gitgutter_signs + sign define GitGutterLineAdded texthl=GitGutterAdd + sign define GitGutterLineModified texthl=GitGutterChange + sign define GitGutterLineRemoved texthl=GitGutterDelete + sign define GitGutterLineRemovedFirstLine texthl=GitGutterDelete + sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDelete + else + sign define GitGutterLineAdded texthl=GitGutterAddInvisible + sign define GitGutterLineModified texthl=GitGutterChangeInvisible + sign define GitGutterLineRemoved texthl=GitGutterDeleteInvisible + sign define GitGutterLineRemovedFirstLine texthl=GitGutterDeleteInvisible + sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDeleteInvisible + endif +endfunction + +function! gitgutter#highlight#define_sign_line_highlights() abort + if g:gitgutter_highlight_lines + sign define GitGutterLineAdded linehl=GitGutterAddLine + sign define GitGutterLineModified linehl=GitGutterChangeLine + sign define GitGutterLineRemoved linehl=GitGutterDeleteLine + sign define GitGutterLineRemovedFirstLine linehl=GitGutterDeleteLine + sign define GitGutterLineModifiedRemoved linehl=GitGutterChangeDeleteLine + else + sign define GitGutterLineAdded linehl= + sign define GitGutterLineModified linehl= + sign define GitGutterLineRemoved linehl= + sign define GitGutterLineRemovedFirstLine linehl= + sign define GitGutterLineModifiedRemoved linehl= + endif +endfunction + +function! gitgutter#highlight#get_background_colors(group) abort + redir => highlight + silent execute 'silent highlight ' . a:group + redir END + + let link_matches = matchlist(highlight, 'links to \(\S\+\)') + if len(link_matches) > 0 " follow the link + return gitgutter#highlight#get_background_colors(link_matches[1]) + endif + + let ctermbg = gitgutter#highlight#match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)') + let guibg = gitgutter#highlight#match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)') + return [guibg, ctermbg] +endfunction + +function! gitgutter#highlight#match_highlight(highlight, pattern) abort + let matches = matchlist(a:highlight, a:pattern) + if len(matches) == 0 + return 'NONE' + endif + return matches[1] +endfunction diff --git a/bundle/gitgutter/autoload/gitgutter/hunk.vim b/bundle/gitgutter/autoload/gitgutter/hunk.vim new file mode 100644 index 0000000..0fd0246 --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/hunk.vim @@ -0,0 +1,137 @@ +let s:hunks = [] + +function! gitgutter#hunk#set_hunks(hunks) abort + let s:hunks = a:hunks +endfunction + +function! gitgutter#hunk#hunks() abort + return s:hunks +endfunction + +function! gitgutter#hunk#summary(bufnr) abort + return get(getbufvar(a:bufnr,''), 'gitgutter_summary', [0,0,0]) +endfunction + +function! gitgutter#hunk#reset() abort + call setbufvar(gitgutter#utility#bufnr(), 'gitgutter_summary', [0,0,0]) +endfunction + +function! gitgutter#hunk#increment_lines_added(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[0] += a:count + call setbufvar(bufnr, 'gitgutter_summary', summary) +endfunction + +function! gitgutter#hunk#increment_lines_modified(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[1] += a:count + call setbufvar(bufnr, 'gitgutter_summary', summary) +endfunction + +function! gitgutter#hunk#increment_lines_removed(count) abort + let bufnr = gitgutter#utility#bufnr() + let summary = gitgutter#hunk#summary(bufnr) + let summary[2] += a:count + call setbufvar(bufnr, 'gitgutter_summary', summary) +endfunction + +function! gitgutter#hunk#next_hunk(count) abort + if gitgutter#utility#is_active() + let current_line = line('.') + let hunk_count = 0 + for hunk in s:hunks + if hunk[2] > current_line + let hunk_count += 1 + if hunk_count == a:count + execute 'normal!' hunk[2] . 'G' + return + endif + endif + endfor + call gitgutter#utility#warn('No more hunks') + endif +endfunction + +function! gitgutter#hunk#prev_hunk(count) abort + if gitgutter#utility#is_active() + let current_line = line('.') + let hunk_count = 0 + for hunk in reverse(copy(s:hunks)) + if hunk[2] < current_line + let hunk_count += 1 + if hunk_count == a:count + let target = hunk[2] == 0 ? 1 : hunk[2] + execute 'normal!' target . 'G' + return + endif + endif + endfor + call gitgutter#utility#warn('No previous hunks') + endif +endfunction + +" Returns the hunk the cursor is currently in or an empty list if the cursor +" isn't in a hunk. +function! gitgutter#hunk#current_hunk() abort + let current_hunk = [] + + for hunk in s:hunks + if gitgutter#hunk#cursor_in_hunk(hunk) + let current_hunk = hunk + break + endif + endfor + + return current_hunk +endfunction + +function! gitgutter#hunk#cursor_in_hunk(hunk) abort + let current_line = line('.') + + if current_line == 1 && a:hunk[2] == 0 + return 1 + endif + + if current_line >= a:hunk[2] && current_line < a:hunk[2] + (a:hunk[3] == 0 ? 1 : a:hunk[3]) + return 1 + endif + + return 0 +endfunction + +" Returns the number of lines the current hunk is offset from where it would +" be if any changes above it in the file didn't exist. +function! gitgutter#hunk#line_adjustment_for_current_hunk() abort + let adj = 0 + for hunk in s:hunks + if gitgutter#hunk#cursor_in_hunk(hunk) + break + else + let adj += hunk[1] - hunk[3] + endif + endfor + return adj +endfunction + +function! gitgutter#hunk#text_object(inner) abort + let hunk = gitgutter#hunk#current_hunk() + + if empty(hunk) + return + endif + + let [first_line, last_line] = [hunk[2], hunk[2] + hunk[3] - 1] + + if ! a:inner + let lnum = last_line + let eof = line('$') + while lnum < eof && empty(getline(lnum + 1)) + let lnum +=1 + endwhile + let last_line = lnum + endif + + execute 'normal! 'first_line.'GV'.last_line.'G' +endfunction diff --git a/bundle/gitgutter/autoload/gitgutter/sign.vim b/bundle/gitgutter/autoload/gitgutter/sign.vim new file mode 100644 index 0000000..7e1218d --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/sign.vim @@ -0,0 +1,179 @@ +" Vim doesn't namespace sign ids so every plugin shares the same +" namespace. Sign ids are simply integers so to avoid clashes with other +" signs we guess at a clear run. +" +" Note also we currently never reset s:next_sign_id. +let s:first_sign_id = 3000 +let s:next_sign_id = s:first_sign_id +let s:dummy_sign_id = s:first_sign_id - 1 +" Remove-all-signs optimisation requires Vim 7.3.596+. +let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596")) + + +" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed. +function! gitgutter#sign#clear_signs() abort + let bufnr = gitgutter#utility#bufnr() + call gitgutter#sign#find_current_signs() + + let sign_ids = map(values(getbufvar(bufnr, 'gitgutter_gitgutter_signs')), 'v:val.id') + call gitgutter#sign#remove_signs(sign_ids, 1) + call setbufvar(bufnr, 'gitgutter_gitgutter_signs', {}) +endfunction + + +" Updates gitgutter's signs in the buffer being processed. +" +" modified_lines: list of [, ] +" where name = 'added|removed|modified|modified_removed' +function! gitgutter#sign#update_signs(modified_lines) abort + call gitgutter#sign#find_current_signs() + + let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]') + let obsolete_signs = gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) + + let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines) + if flicker_possible + call gitgutter#sign#add_dummy_sign() + endif + + call gitgutter#sign#remove_signs(obsolete_signs, s:remove_all_old_signs) + call gitgutter#sign#upsert_new_gitgutter_signs(a:modified_lines) + + if flicker_possible + call gitgutter#sign#remove_dummy_sign(0) + endif +endfunction + + +function! gitgutter#sign#add_dummy_sign() abort + let bufnr = gitgutter#utility#bufnr() + if !getbufvar(bufnr, 'gitgutter_dummy_sign') + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr + call setbufvar(bufnr, 'gitgutter_dummy_sign', 1) + endif +endfunction + +function! gitgutter#sign#remove_dummy_sign(force) abort + let bufnr = gitgutter#utility#bufnr() + if getbufvar(bufnr, 'gitgutter_dummy_sign') && (a:force || !g:gitgutter_sign_column_always) + execute "sign unplace" s:dummy_sign_id "buffer=" . bufnr + call setbufvar(bufnr, 'gitgutter_dummy_sign', 0) + endif +endfunction + + +" +" Internal functions +" + + +function! gitgutter#sign#find_current_signs() abort + let bufnr = gitgutter#utility#bufnr() + let gitgutter_signs = {} " : {'id': , 'name': } + let other_signs = [] " [ signs + silent execute "sign place buffer=" . bufnr + redir END + + for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="') + " Typical sign line: line=88 id=1234 name=GitGutterLineAdded + " We assume splitting is faster than a regexp. + let components = split(sign_line) + let name = split(components[2], '=')[1] + if name =~# 'GitGutterDummy' + let dummy_sign_placed = 1 + else + let line_number = str2nr(split(components[0], '=')[1]) + if name =~# 'GitGutter' + let id = str2nr(split(components[1], '=')[1]) + " Remove orphaned signs (signs placed on lines which have been deleted). + " (When a line is deleted its sign lingers. Subsequent lines' signs' + " line numbers are decremented appropriately.) + if has_key(gitgutter_signs, line_number) + execute "sign unplace" gitgutter_signs[line_number].id + endif + let gitgutter_signs[line_number] = {'id': id, 'name': name} + else + call add(other_signs, line_number) + endif + end + endfor + + call setbufvar(bufnr, 'gitgutter_dummy_sign', dummy_sign_placed) + call setbufvar(bufnr, 'gitgutter_gitgutter_signs', gitgutter_signs) + call setbufvar(bufnr, 'gitgutter_other_signs', other_signs) +endfunction + + +" Returns a list of [, ...] +" Sets `s:remove_all_old_signs` as a side-effect. +function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) abort + let bufnr = gitgutter#utility#bufnr() + let signs_to_remove = [] " list of [, ...] + let remove_all_signs = 1 + let old_gitgutter_signs = getbufvar(bufnr, 'gitgutter_gitgutter_signs') + for line_number in keys(old_gitgutter_signs) + if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1 + call add(signs_to_remove, old_gitgutter_signs[line_number].id) + else + let remove_all_signs = 0 + endif + endfor + let s:remove_all_old_signs = remove_all_signs + return signs_to_remove +endfunction + + +function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort + let bufnr = gitgutter#utility#bufnr() + if a:all_signs && s:supports_star && empty(getbufvar(bufnr, 'gitgutter_other_signs')) + let dummy_sign_present = getbufvar(bufnr, 'gitgutter_dummy_sign') + execute "sign unplace * buffer=" . bufnr + if dummy_sign_present + execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr + endif + else + for id in a:sign_ids + execute "sign unplace" id + endfor + endif +endfunction + + +function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort + let bufnr = gitgutter#utility#bufnr() + let other_signs = getbufvar(bufnr, 'gitgutter_other_signs') + let old_gitgutter_signs = getbufvar(bufnr, 'gitgutter_gitgutter_signs') + + for line in a:modified_lines + let line_number = line[0] " + if index(other_signs, line_number) == -1 " don't clobber others' signs + let name = gitgutter#utility#highlight_name_for_change(line[1]) + if !has_key(old_gitgutter_signs, line_number) " insert + let id = gitgutter#sign#next_sign_id() + execute "sign place" id "line=" . line_number "name=" . name "buffer=" . bufnr + else " update if sign has changed + let old_sign = old_gitgutter_signs[line_number] + if old_sign.name !=# name + execute "sign place" old_sign.id "name=" . name "buffer=" . bufnr + end + endif + endif + endfor + " At this point b:gitgutter_gitgutter_signs is out of date. +endfunction + + +function! gitgutter#sign#next_sign_id() abort + let next_id = s:next_sign_id + let s:next_sign_id += 1 + return next_id +endfunction + + +" Only for testing. +function! gitgutter#sign#reset() + let s:next_sign_id = s:first_sign_id +endfunction diff --git a/bundle/gitgutter/autoload/gitgutter/utility.vim b/bundle/gitgutter/autoload/gitgutter/utility.vim new file mode 100644 index 0000000..684f92a --- /dev/null +++ b/bundle/gitgutter/autoload/gitgutter/utility.vim @@ -0,0 +1,208 @@ +let s:file = '' +let s:using_xolox_shell = -1 +let s:exit_code = 0 + +function! gitgutter#utility#warn(message) abort + echohl WarningMsg + echo 'vim-gitgutter: ' . a:message + echohl None + let v:warningmsg = a:message +endfunction + +function! gitgutter#utility#warn_once(message, key) abort + if empty(getbufvar(s:bufnr, a:key)) + call setbufvar(s:bufnr, a:key, '1') + echohl WarningMsg + redraw | echo 'vim-gitgutter: ' . a:message + echohl None + let v:warningmsg = a:message + endif +endfunction + +" Returns truthy when the buffer's file should be processed; and falsey when it shouldn't. +" This function does not and should not make any system calls. +function! gitgutter#utility#is_active() abort + return g:gitgutter_enabled && + \ !pumvisible() && + \ gitgutter#utility#is_file_buffer() && + \ gitgutter#utility#exists_file() && + \ gitgutter#utility#not_git_dir() +endfunction + +function! gitgutter#utility#not_git_dir() abort + return gitgutter#utility#full_path_to_directory_of_file() !~ '[/\\]\.git\($\|[/\\]\)' +endfunction + +function! gitgutter#utility#is_file_buffer() abort + return empty(getbufvar(s:bufnr, '&buftype')) +endfunction + +" A replacement for the built-in `shellescape(arg)`. +" +" Recent versions of Vim handle shell escaping pretty well. However older +" versions aren't as good. This attempts to do the right thing. +" +" See: +" https://github.com/tpope/vim-fugitive/blob/8f0b8edfbd246c0026b7a2388e1d883d579ac7f6/plugin/fugitive.vim#L29-L37 +function! gitgutter#utility#shellescape(arg) abort + if a:arg =~ '^[A-Za-z0-9_/.-]\+$' + return a:arg + elseif &shell =~# 'cmd' || gitgutter#utility#using_xolox_shell() + return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"' + else + return shellescape(a:arg) + endif +endfunction + +function! gitgutter#utility#set_buffer(bufnr) abort + let s:bufnr = a:bufnr + let s:file = resolve(bufname(a:bufnr)) +endfunction + +function! gitgutter#utility#bufnr() + return s:bufnr +endfunction + +function! gitgutter#utility#file() + return s:file +endfunction + +function! gitgutter#utility#filename() abort + return fnamemodify(s:file, ':t') +endfunction + +function! gitgutter#utility#extension() abort + return fnamemodify(s:file, ':e') +endfunction + +function! gitgutter#utility#full_path_to_directory_of_file() abort + return fnamemodify(s:file, ':p:h') +endfunction + +function! gitgutter#utility#directory_of_file() abort + return fnamemodify(s:file, ':h') +endfunction + +function! gitgutter#utility#exists_file() abort + return filereadable(s:file) +endfunction + +function! gitgutter#utility#has_unsaved_changes() abort + return getbufvar(s:bufnr, "&mod") +endfunction + +function! gitgutter#utility#has_fresh_changes() abort + return getbufvar(s:bufnr, 'changedtick') != getbufvar(s:bufnr, 'gitgutter_last_tick') +endfunction + +function! gitgutter#utility#save_last_seen_change() abort + call setbufvar(s:bufnr, 'gitgutter_last_tick', getbufvar(s:bufnr, 'changedtick')) +endfunction + +function! gitgutter#utility#shell_error() abort + return gitgutter#utility#using_xolox_shell() ? s:exit_code : v:shell_error +endfunction + +function! gitgutter#utility#using_xolox_shell() abort + if s:using_xolox_shell == -1 + if !g:gitgutter_avoid_cmd_prompt_on_windows + let s:using_xolox_shell = 0 + " Although xolox/vim-shell works on both windows and unix we only want to use + " it on windows. + elseif has('win32') || has('win64') || has('win32unix') + let s:using_xolox_shell = exists('g:xolox#misc#version') && exists('g:xolox#shell#version') + else + let s:using_xolox_shell = 0 + endif + endif + return s:using_xolox_shell +endfunction + +function! gitgutter#utility#system(cmd, ...) abort + call gitgutter#debug#log(a:cmd, a:000) + + if gitgutter#utility#using_xolox_shell() + let options = {'command': a:cmd, 'check': 0} + if a:0 > 0 + let options['stdin'] = a:1 + endif + let ret = xolox#misc#os#exec(options) + let output = join(ret.stdout, "\n") + let s:exit_code = ret.exit_code + else + silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1) + endif + return output +endfunction + +function! gitgutter#utility#file_relative_to_repo_root() abort + let file_path_relative_to_repo_root = getbufvar(s:bufnr, 'gitgutter_repo_relative_path') + if empty(file_path_relative_to_repo_root) + let dir_path_relative_to_repo_root = gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' rev-parse --show-prefix')) + let dir_path_relative_to_repo_root = gitgutter#utility#strip_trailing_new_line(dir_path_relative_to_repo_root) + let file_path_relative_to_repo_root = dir_path_relative_to_repo_root . gitgutter#utility#filename() + call setbufvar(s:bufnr, 'gitgutter_repo_relative_path', file_path_relative_to_repo_root) + endif + return file_path_relative_to_repo_root +endfunction + +function! gitgutter#utility#command_in_directory_of_file(cmd) abort + return 'cd '.gitgutter#utility#shellescape(gitgutter#utility#directory_of_file()).' && '.a:cmd +endfunction + +function! gitgutter#utility#highlight_name_for_change(text) abort + if a:text ==# 'added' + return 'GitGutterLineAdded' + elseif a:text ==# 'removed' + return 'GitGutterLineRemoved' + elseif a:text ==# 'removed_first_line' + return 'GitGutterLineRemovedFirstLine' + elseif a:text ==# 'modified' + return 'GitGutterLineModified' + elseif a:text ==# 'modified_removed' + return 'GitGutterLineModifiedRemoved' + endif +endfunction + +" Dedups list in-place. +" Assumes list has no empty entries. +function! gitgutter#utility#dedup(list) + return filter(sort(a:list), 'index(a:list, v:val, v:key + 1) == -1') +endfunction + +function! gitgutter#utility#strip_trailing_new_line(line) abort + return substitute(a:line, '\n$', '', '') +endfunction + +" True for git v1.7.2+. +function! gitgutter#utility#git_supports_command_line_config_override() abort + call system(g:gitgutter_git_executable.' -c foo.bar=baz --version') + return !v:shell_error +endfunction + +function! gitgutter#utility#stringify(list) abort + return join(a:list, "\n")."\n" +endfunction + +function! gitgutter#utility#use_known_shell() abort + if has('unix') + if &shell !=# 'sh' + let s:shell = &shell + let s:shellcmdflag = &shellcmdflag + let s:shellredir = &shellredir + let &shell = 'sh' + set shellcmdflag=-c + set shellredir=>%s\ 2>&1 + endif + endif +endfunction + +function! gitgutter#utility#restore_shell() abort + if has('unix') + if exists('s:shell') + let &shell = s:shell + let &shellcmdflag = s:shellcmdflag + let &shellredir = s:shellredir + endif + endif +endfunction diff --git a/bundle/gitgutter/doc/gitgutter.txt b/bundle/gitgutter/doc/gitgutter.txt new file mode 100644 index 0000000..6524564 --- /dev/null +++ b/bundle/gitgutter/doc/gitgutter.txt @@ -0,0 +1,341 @@ +*gitgutter.txt* A Vim plugin which shows a git diff in the gutter. + + + Vim Git Gutter + + +Author: Andy Stewart +Plugin Homepage: + +=============================================================================== +CONTENTS *GitGutterContents* + + 1. Introduction ................. |GitGutterIntroduction| + 2. Installation ................. |GitGutterInstallation| + 3. Usage ........................ |GitGutterUsage| + 4. Commands ..................... |GitGutterCommands| + 5. Autocommand .................. |GitGutterAutocmd| + 6. CUSTOMISATION................. |GitGutterCustomisation| + 7. FAQ .......................... |GitGutterFAQ| + +=============================================================================== +1. INTRODUCTION *GitGutterIntroduction* + *GitGutter* + +Vim Git Gutter is a Vim plugin which shows a git diff in the 'gutter' (sign +column). It shows whether each line has been added, modified, and where lines +have been removed. + +This is a port of the Git Gutter plugin for Sublime Text 2. + +=============================================================================== +2. INSTALLATION *GitGutterInstallation* + +* Pathogen: +> + cd ~/.vim/bundle + git clone git://github.com/airblade/vim-gitgutter.git +< +* Voom: + +Edit your plugin manifest (`voom edit`) and add: +> + airblade/vim-gitgutter +< +* VimPlug: + +Place this in your .vimrc: +> + Plug 'airblade/vim-gitgutter' +< +Then run the following in Vim: +> + :source % + :PlugInstall +< +* NeoBundle: + +Place this in your .vimrc: +> + NeoBundle 'airblade/vim-gitgutter' +< +Then run the following in Vim: +> + :source % + :NeoBundleInstall +< +* No plugin manager: + +Copy vim-gitgutter's subdirectories into your vim configuration directory: +> + cd tmp && git clone git://github.com/airblade/vim-gitgutter.git + cp vim-gitgutter/* ~/.vim/ +< +See |add-global-plugin|. + +=============================================================================== +3. USAGE *GitGutterUsage* + +You don't have to do anything: it just works. + +=============================================================================== +4. COMMANDS *GitGutterCommands* + +Commands for turning Git Gutter on and off: + + :GitGutterDisable *:GitGutterDisable* + Explicitly turn Git Gutter off. + + :GitGutterEnable *:GitGutterEnable* + Explicitly turn Git Gutter on. + + :GitGutterToggle *:GitGutterToggle* + Explicitly turn Git Gutter on if it was off and vice versa. + + :GitGutter *:GitGutter* + Update signs for the current buffer. + + :GitGutterAll *:GitGutterAll* + Update signs across all buffers. + +Commands for turning signs on and off (defaults to on): + + :GitGutterSignsEnable *:GitGutterSignsEnable* + Explicitly turn line signs on. + + :GitGutterSignsDisable *:GitGutterSignsDisable* + Explicitly turn line signs off. + + :GitGutterSignsToggle *:GitGutterSignsToggle* + Explicitly turn line signs on if it was off and vice versa. + +Commands for turning line highlighting on and off (defaults to off): + + :GitGutterLineHighlightsEnable *:GitGutterLineHighlightsEnable* + Explicitly turn line highlighting on. + + :GitGutterLineHighlightsDisable *:GitGutterLineHighlightsDisable* + Explicitly turn line highlighting off. + + :GitGutterLineHighlightsToggle *:GitGutterLineHighlightsToggle* + Explicitly turn line highlighting on if it was off and vice versa. + +Commands for jumping between marked hunks: + + :GitGutterNextHunk *:GitGutterNextHunk* + Jump to the next marked hunk. Takes a count. + + :GitGutterPrevHunk *:GitGutterPrevHunk* + Jump to the previous marked hunk. Takes a count. + +Commands for staging or undoing individual hunks: + + :GitGutterStageHunk *:GitGutterStageHunk* + Stage the hunk the cursor is in. + + :GitGutterUndoHunk *:GitGutterUndoHunk* + Undo the hunk the cursor is in. + + :GitGutterPreviewHunk *:GitGutterPreviewHunk* + Preview the hunk the cursor is in. + Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview window. + +=============================================================================== +5. AUTOCOMMAND *GitGutterAutocmd* + +After updating a buffer's signs vim-gitgutter fires a |User| |autocmd| with the +event GitGutter. You can listen for this event, for example: +> + autocmd User GitGutter call updateMyStatusLine() +< + +=============================================================================== +6. CUSTOMISATION *GitGutterCustomisation* + +You can customise: + +- The sign column's colours +- The signs' colours and symbols +- Line highlights +- The base of the diff +- Extra arguments for git-diff +- Key mappings +- The grep executable used +- Whether or not vim-gitgutter is on initially (defaults to on) +- Whether or not signs are shown (defaults to yes) +- Whether or not line highlighting is on initially (defaults to off) +- Whether or not vim-gitgutter runs in realtime (defaults to yes) +- Whether or not vim-gitgutter runs eagerly (defaults to yes) +- Whether or not vim-gitgutter runs asynchronously (defaults to yes) + +Please note that vim-gitgutter won't override any colours or highlights you've +set in your colorscheme. + +SIGN COLUMN + +By default vim-gitgutter will make the sign column look like the line number +column (i.e. the |hl-LineNr| highlight group). + +To customise your sign column's background color, first tell vim-gitgutter to +leave it alone: +> + let g:gitgutter_override_sign_column_highlight = 0 +< + +And then either update your colorscheme's |hlSignColumn| highlight group or set +it in your |vimrc|: + + Desired appearance Command ~ + Same as line number column highlight clear SignColumn + User-defined (terminal Vim) highlight SignColumn ctermbg={whatever} + User-defined (graphical Vim) highlight SignColumn guibg={whatever} + +SIGNS' COLOURS AND SYMBOLS + +To customise the colours, set up the following highlight groups in your +colorscheme or |vimrc|: + +> + GitGutterAdd " an added line + GitGutterChange " a changed line + GitGutterDelete " at least one removed line + GitGutterChangeDelete " a changed line followed by at least one removed line +< + +You can either set these with `highlight GitGutterAdd {key}={arg}...` or link +them to existing highlight groups with, say: +> + highlight link GitGutterAdd DiffAdd +< + +To customise the symbols, add the following to your |vimrc|: +> + let g:gitgutter_sign_added = 'xx' + let g:gitgutter_sign_modified = 'yy' + let g:gitgutter_sign_removed = 'zz' + let g:gitgutter_sign_modified_removed = 'ww' +< + +LINE HIGHLIGHTS + +Similarly to the signs' colours, set up the following highlight groups in your +colorscheme or |vimrc|: +> + GitGutterAddLine " default: links to DiffAdd + GitGutterChangeLine " default: links to DiffChange + GitGutterDeleteLine " default: links to DiffDelete + GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault +< + +THE BASE OF THE DIFF + +By default buffers are diffed against the index. To diff against a commit +instead: +> + let g:gitgutter_diff_base = '' +< + +EXTRA ARGUMENTS FOR GIT-DIFF + +To pass extra arguments to git-diff, add this to your |vimrc|: +> + let g:gitgutter_diff_args = '-w' +< + +KEY MAPPINGS + +To disable all key maps: +> + let g:gitgutter_map_keys = 0 +< + +To change the hunk-jumping maps (defaults shown): +> + nmap [c GitGutterPrevHunk + nmap ]c GitGutterNextHunk +< + +To change the hunk-staging/undoing/previewing maps (defaults shown): +> + nmap hs GitGutterStageHunk + nmap hu GitGutterUndoHunk + nmap hp GitGutterPreviewHunk +< + +To change the hunk text object maps (defaults shown): +> + omap ic GitGutterTextObjectInnerPending + omap ac GitGutterTextObjectOuterPending + xmap ic GitGutterTextObjectInnerVisual + xmap ac GitGutterTextObjectOuterVisual +< + +TO USE A CUSTOM GREP COMMAND + +To use a custom invocation for grep, use this: +> + let g:gitgutter_grep_command = 'grep --color=never -e' +< + +TO TURN OFF VIM-GITGUTTER BY DEFAULT + +Add to your |vimrc| +> + let g:gitgutter_enabled = 0 +< + +TO TURN OFF SIGNS BY DEFAULT + +Add to your |vimrc| +> + let g:gitgutter_signs = 0 +< + +Note that the sign column will still be present if you have line highlighting +switched on. + +TO TURN ON LINE HIGHLIGHTING BY DEFAULT + +Add to your |vimrc| +> + let g:gitgutter_highlight_lines = 1 +< + +TO STOP VIM-GITGUTTER RUNNING IN REALTIME + +Add to your |vimrc| +> + let g:gitgutter_realtime = 0 +< + +TO STOP VIM-GITGUTTER RUNNING EAGERLY + +Add to your |vimrc| +> + let g:gitgutter_eager = 0 +< + +TO TURN OFF ASYNCHRONOUS UPDATES + +By default diffs are run asynchronously. To run diffs synchronously +instead: + +Add to your |vimrc| +> +let g:gitgutter_async = 0 +< + +=============================================================================== +7. FAQ *GitGutterFAQ* + +a. Why are the colours in the sign column weird? + + Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly. + Please see |GitGutterCustomisation| on customising the sign column. + +b. What happens if I also use another plugin which uses signs (e.g. Syntastic)? + + Vim only allows one sign per line. Before adding a sign to a line, + vim-gitgutter checks whether a sign has already been added by somebody else. + If so it doesn't do anything. In other words vim-gitgutter won't overwrite + another plugin's signs. It also won't remove another plugin's signs. diff --git a/bundle/gitgutter/plugin/gitgutter.vim b/bundle/gitgutter/plugin/gitgutter.vim new file mode 100644 index 0000000..eeaffb1 --- /dev/null +++ b/bundle/gitgutter/plugin/gitgutter.vim @@ -0,0 +1,241 @@ +scriptencoding utf-8 + +if exists('g:loaded_gitgutter') || !has('signs') || &cp + finish +endif +let g:loaded_gitgutter = 1 + +" Initialisation {{{ + +" Realtime sign updates require Vim 7.3.105+. +if v:version < 703 || (v:version == 703 && !has("patch105")) + let g:gitgutter_realtime = 0 +endif + +" Eager updates require gettabvar()/settabvar(). +if !exists("*gettabvar") + let g:gitgutter_eager = 0 +endif + +function! s:set(var, default) abort + if !exists(a:var) + if type(a:default) + execute 'let' a:var '=' string(a:default) + else + execute 'let' a:var '=' a:default + endif + endif +endfunction + +call s:set('g:gitgutter_enabled', 1) +call s:set('g:gitgutter_max_signs', 500) +call s:set('g:gitgutter_signs', 1) +call s:set('g:gitgutter_highlight_lines', 0) +call s:set('g:gitgutter_sign_column_always', 0) +call s:set('g:gitgutter_override_sign_column_highlight', 1) +call s:set('g:gitgutter_realtime', 1) +call s:set('g:gitgutter_eager', 1) +call s:set('g:gitgutter_sign_added', '+') +call s:set('g:gitgutter_sign_modified', '~') +call s:set('g:gitgutter_sign_removed', '_') +try + call s:set('g:gitgutter_sign_removed_first_line', '‾') +catch /E239/ + let g:gitgutter_sign_removed_first_line = '_^' +endtry + +call s:set('g:gitgutter_sign_modified_removed', '~_') +call s:set('g:gitgutter_diff_args', '') +call s:set('g:gitgutter_diff_base', '') +call s:set('g:gitgutter_map_keys', 1) +call s:set('g:gitgutter_avoid_cmd_prompt_on_windows', 1) +call s:set('g:gitgutter_async', 1) +call s:set('g:gitgutter_log', 0) +call s:set('g:gitgutter_git_executable', 'git') + +if !executable(g:gitgutter_git_executable) + call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.') +endif + +call gitgutter#highlight#define_sign_column_highlight() +call gitgutter#highlight#define_highlights() +call gitgutter#highlight#define_signs() + +" }}} + +" Primary functions {{{ + +command -bar GitGutterAll call gitgutter#all() +command -bar GitGutter call gitgutter#process_buffer(bufnr(''), 0) + +command -bar GitGutterDisable call gitgutter#disable() +command -bar GitGutterEnable call gitgutter#enable() +command -bar GitGutterToggle call gitgutter#toggle() + +" }}} + +" Line highlights {{{ + +command -bar GitGutterLineHighlightsDisable call gitgutter#line_highlights_disable() +command -bar GitGutterLineHighlightsEnable call gitgutter#line_highlights_enable() +command -bar GitGutterLineHighlightsToggle call gitgutter#line_highlights_toggle() + +" }}} + +" Signs {{{ + +command -bar GitGutterSignsEnable call gitgutter#signs_enable() +command -bar GitGutterSignsDisable call gitgutter#signs_disable() +command -bar GitGutterSignsToggle call gitgutter#signs_toggle() + +" }}} + +" Hunks {{{ + +command -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk() +command -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk() + +command -bar GitGutterStageHunk call gitgutter#stage_hunk() +command -bar GitGutterUndoHunk call gitgutter#undo_hunk() +command -bar GitGutterRevertHunk echomsg 'GitGutterRevertHunk is deprecated. Use GitGutterUndoHunk'call gitgutter#undo_hunk() +command -bar GitGutterPreviewHunk call gitgutter#preview_hunk() + +" Hunk text object +onoremap GitGutterTextObjectInnerPending :call gitgutter#hunk#text_object(1) +onoremap GitGutterTextObjectOuterPending :call gitgutter#hunk#text_object(0) +xnoremap GitGutterTextObjectInnerVisual :call gitgutter#hunk#text_object(1) +xnoremap GitGutterTextObjectOuterVisual :call gitgutter#hunk#text_object(0) + + +" Returns the git-diff hunks for the file or an empty list if there +" aren't any hunks. +" +" The return value is a list of lists. There is one inner list per hunk. +" +" [ +" [from_line, from_count, to_line, to_count], +" [from_line, from_count, to_line, to_count], +" ... +" ] +" +" where: +" +" `from` - refers to the staged file +" `to` - refers to the working tree's file +" `line` - refers to the line number where the change starts +" `count` - refers to the number of lines the change covers +function! GitGutterGetHunks() + return gitgutter#utility#is_active() ? gitgutter#hunk#hunks() : [] +endfunction + +" Returns an array that contains a summary of the hunk status for the current +" window. The format is [ added, modified, removed ], where each value +" represents the number of lines added/modified/removed respectively. +function! GitGutterGetHunkSummary() + return gitgutter#hunk#summary(winbufnr(0)) +endfunction + +" }}} + +command -bar GitGutterDebug call gitgutter#debug#debug() + +" Maps {{{ + +nnoremap GitGutterNextHunk &diff ? ']c' : ":\execute v:count1 . 'GitGutterNextHunk'\" +nnoremap GitGutterPrevHunk &diff ? '[c' : ":\execute v:count1 . 'GitGutterPrevHunk'\" + +if g:gitgutter_map_keys + if !hasmapto('GitGutterPrevHunk') && maparg('[c', 'n') ==# '' + nmap [c GitGutterPrevHunk + endif + if !hasmapto('GitGutterNextHunk') && maparg(']c', 'n') ==# '' + nmap ]c GitGutterNextHunk + endif +endif + + +nnoremap GitGutterStageHunk :GitGutterStageHunk +nnoremap GitGutterUndoHunk :GitGutterUndoHunk +nnoremap GitGutterPreviewHunk :GitGutterPreviewHunk + +if g:gitgutter_map_keys + if !hasmapto('GitGutterStageHunk') && maparg('hs', 'n') ==# '' + nmap hs GitGutterStageHunk + endif + if !hasmapto('GitGutterUndoHunk') && maparg('hu', 'n') ==# '' + nmap hu GitGutterUndoHunk + nmap hr GitGutterUndoHunk:echomsg 'hr is deprecated. Use hu' + endif + if !hasmapto('GitGutterPreviewHunk') && maparg('hp', 'n') ==# '' + nmap hp GitGutterPreviewHunk + endif + + if !hasmapto('GitGutterTextObjectInnerPending') && maparg('ic', 'o') ==# '' + omap ic GitGutterTextObjectInnerPending + endif + if !hasmapto('GitGutterTextObjectOuterPending') && maparg('ac', 'o') ==# '' + omap ac GitGutterTextObjectOuterPending + endif + if !hasmapto('GitGutterTextObjectInnerVisual') && maparg('ic', 'x') ==# '' + xmap ic GitGutterTextObjectInnerVisual + endif + if !hasmapto('GitGutterTextObjectOuterVisual') && maparg('ac', 'x') ==# '' + xmap ac GitGutterTextObjectOuterVisual + endif +endif + +" }}} + +" Autocommands {{{ + +augroup gitgutter + autocmd! + + if g:gitgutter_realtime + autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 1) + endif + + if g:gitgutter_eager + autocmd BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 0) + + " When you enter a new tab, BufEnter is only fired if the buffer you enter + " is not the one you came from. + " + " For example: + " + " `:tab split` fires TabEnter but not BufEnter. + " `:tab new` fires TabEnter and BufEnter. + " + " As and when both TabEnter and BufEnter are fired, we do not want to + " process the entered buffer twice. We avoid this by setting and clearing + " a flag. + + autocmd BufEnter * + \ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') | + \ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) | + \ else | + \ call gitgutter#process_buffer(bufnr(''), 0) | + \ endif + + autocmd TabEnter * + \ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1) | + \ call gitgutter#all() + + if !has('gui_win32') + autocmd FocusGained * call gitgutter#all() + endif + + else + autocmd BufRead,BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 0) + endif + + autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights() + + " Disable during :vimgrep + autocmd QuickFixCmdPre *vimgrep* let g:gitgutter_enabled = 0 + autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = 1 +augroup END + +" }}} + +" vim:set et sw=2 fdm=marker: diff --git a/bundle/gitgutter/screenshot.png b/bundle/gitgutter/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..6b50f839ec91fd623e1191f8ada8c823740be041 GIT binary patch literal 16191 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 P9zj7?MW#y1H01vSr(8@| literal 0 HcmV?d00001 diff --git a/bundle/gitgutter/test/fixture.txt b/bundle/gitgutter/test/fixture.txt new file mode 100644 index 0000000..f5c6aff --- /dev/null +++ b/bundle/gitgutter/test/fixture.txt @@ -0,0 +1,11 @@ +a +b +c +d +e +f +g +h +i +j + diff --git a/bundle/gitgutter/test/runner.vim b/bundle/gitgutter/test/runner.vim new file mode 100644 index 0000000..630693c --- /dev/null +++ b/bundle/gitgutter/test/runner.vim @@ -0,0 +1,162 @@ +" +" Adapted from https://github.com/vim/vim/blob/master/src/testdir/runtest.vim +" +" When debugging tests it can help to write debug output: +" call Log('oh noes') +" + +function RunTest(test) + if exists("*SetUp") + call SetUp() + endif + + try + execute 'call '.a:test + catch + call Exception() + let s:errored = 1 + endtry + + if exists("*TearDown") + call TearDown() + endif +endfunction + +function Log(msg) + if type(a:msg) == type('') + call add(s:messages, a:msg) + elseif type(a:msg) == type([]) + call extend(s:messages, a:msg) + else + call add(v:errors, 'Exception: unsupported type: '.type(a:msg)) + endif +endfunction + +function Exception() + call add(v:errors, v:throwpoint.'..'.'Exception: '.v:exception) +endfunction + +" Shuffles list in place. +function Shuffle(list) + " Fisher-Yates-Durstenfeld-Knuth + let n = len(a:list) + if n < 2 + return a:list + endif + for i in range(0, n-2) + let j = Random(0, n-i-1) + let e = a:list[i] + let a:list[i] = a:list[i+j] + let a:list[i+j] = e + endfor + return a:list +endfunction + +" Returns a pseudorandom integer i such that 0 <= i <= max +function Random(min, max) + if has('unix') + let i = system('echo $RANDOM') " 0 <= i <= 32767 + else + let i = system('echo %RANDOM%') " 0 <= i <= 32767 + endif + return i * (a:max - a:min + 1) / 32768 + a:min +endfunction + +function FriendlyName(test_name) + return substitute(a:test_name[5:-3], '_', ' ', 'g') +endfunction + +function Align(left, right) + if type(a:right) == type([]) + let result = [] + for s in a:right + if empty(result) + call add(result, printf('%-'.s:indent.'S', a:left).s) + else + call add(result, printf('%-'.s:indent.'S', '').s) + endif + endfor + return result + endif + + return printf('%-'.s:indent.'S', a:left).a:right +endfunction + +let g:testname = expand('%') +let s:errored = 0 +let s:done = 0 +let s:fail = 0 +let s:errors = 0 +let s:messages = [] +let s:indent = '' + +call Log(g:testname.':') + +" Source the test script. +try + source % +catch + let s:errors += 1 + call Exception() +endtry + +" Locate the test functions. +set nomore +redir @q +silent function /^Test_ +redir END +let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) + +" If there is another argument, filter test-functions' names against it. +if argc() > 1 + let s:tests = filter(s:tests, 'v:val =~ argv(1)') +endif + +let s:indent = max(map(copy(s:tests), {_, val -> len(FriendlyName(val))})) + +" Run the tests in random order. +for test in Shuffle(s:tests) + call RunTest(test) + let s:done += 1 + + let friendly_name = FriendlyName(test) + if len(v:errors) == 0 + call Log(Align(friendly_name, ' - ok')) + else + if s:errored + let s:errors += 1 + let s:errored = 0 + else + let s:fail += 1 + endif + call Log(Align(friendly_name, ' - not ok')) + + let i = 0 + for error in v:errors + if i != 0 + call Log(Align('',' ! ----')) + endif + for trace in reverse(split(error, '\.\.')) + call Log(Align('', ' ! '.trace)) + endfor + let i += 1 + endfor + + let v:errors = [] + endif +endfor + +let summary = [ + \ s:done.( s:done == 1 ? ' test' : ' tests'), + \ s:errors.(s:errors == 1 ? ' error' : ' errors'), + \ s:fail.( s:fail == 1 ? ' failure' : ' failures'), + \ ] +call Log('') +call Log(join(summary, ', ')) + +split messages.log +call append(line('$'), s:messages) +write + +qall! + diff --git a/bundle/gitgutter/test/test b/bundle/gitgutter/test/test new file mode 100755 index 0000000..6247a05 --- /dev/null +++ b/bundle/gitgutter/test/test @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +VIM="/Applications/MacVim.app/Contents/MacOS/Vim -v" + +$VIM -u NONE -U NONE -N \ + --cmd 'set rtp+=../' \ + --cmd 'let g:gitgutter_async=0' \ + --cmd 'source ../plugin/gitgutter.vim' \ + -S runner.vim \ + test_*.vim \ + $* + +cat messages.log + +grep -q "0 errors, 0 failures" messages.log +status=$? +rm messages.log +exit $status + diff --git a/bundle/gitgutter/test/test_gitgutter.vim b/bundle/gitgutter/test/test_gitgutter.vim new file mode 100644 index 0000000..1a65ed8 --- /dev/null +++ b/bundle/gitgutter/test/test_gitgutter.vim @@ -0,0 +1,400 @@ +let s:current_dir = expand('%:p:h') +let s:test_repo = s:current_dir.'/test-repo' +let s:bufnr = bufnr('') + +" +" Helpers +" + +function s:signs(filename) + redir => signs + silent execute 'sign place' + redir END + + let signs = split(signs, '\n') + + " filter out signs for this test file + " assumes a:filename's signs are last set listed + let i = index(signs, 'Signs for '.a:filename.':') + let signs = (i > -1 ? signs[i+1:] : []) + + call map(signs, {_, v -> substitute(v, ' ', '', '')}) + + return signs +endfunction + +function s:git_diff() + return split(system('git diff -U0 fixture.txt'), '\n') +endfunction + +function s:git_diff_staged() + return split(system('git diff -U0 --staged fixture.txt'), '\n') +endfunction + + +" +" SetUp / TearDown +" + +function SetUp() + call system("git init ".s:test_repo. + \ " && cd ".s:test_repo. + \ " && cp ../fixture.txt .". + \ " && git add . && git commit -m 'initial'") + execute ':cd' s:test_repo + edit! fixture.txt + call gitgutter#sign#reset() +endfunction + +function TearDown() + " delete all buffers except this one + " TODO: move to runner.vim, accounting for multiple test files + if s:bufnr > 1 + silent! execute '1,'.s:bufnr-1.'bdelete!' + endif + silent! execute s:bufnr+1.',$bdelete!' + + execute ':cd' s:current_dir + call system("rm -rf ".s:test_repo) +endfunction + +" +" The tests +" + +function Test_add_lines() + normal ggo* + write + + let expected = ["line=2 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_add_lines_fish() + let _shell = &shell + set shell=/usr/local/bin/fish + + normal ggo* + write + + let expected = ["line=2 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fixture.txt')) + + let &shell = _shell +endfunction + + +function Test_modify_lines() + normal ggi* + write + + let expected = ["line=1 id=3000 name=GitGutterLineModified"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_remove_lines() + execute '5d' + write + + let expected = ["line=4 id=3000 name=GitGutterLineRemoved"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_remove_first_lines() + execute '1d' + write + + let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_edit_file_with_same_name_as_a_branch() + normal 5Gi* + call system('git checkout -b fixture.txt') + write + + let expected = ["line=5 id=3000 name=GitGutterLineModified"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_file_added_to_git() + let tmpfile = 'fileAddedToGit.tmp' + call system('touch '.tmpfile.' && git add '.tmpfile) + execute 'edit '.tmpfile + normal ihello + write + + let expected = ["line=1 id=3000 name=GitGutterLineAdded"] + call assert_equal(expected, s:signs('fileAddedToGit.tmp')) +endfunction + + +function Test_filename_with_equals() + call system('touch =fixture=.txt && git add =fixture=.txt') + edit =fixture=.txt + normal ggo* + write + + let expected = [ + \ 'line=1 id=3000 name=GitGutterLineAdded', + \ 'line=2 id=3001 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('=fixture=.txt')) +endfunction + + +function Test_filename_with_square_brackets() + call system('touch fix[tu]re.txt && git add fix[tu]re.txt') + edit fix[tu]re.txt + normal ggo* + write + + let expected = [ + \ 'line=1 id=3000 name=GitGutterLineAdded', + \ 'line=2 id=3001 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fix[tu]re.txt')) +endfunction + + +" FIXME: this test fails when it is the first (or only) test to be run +function Test_follow_symlink() + let tmp = 'symlink' + call system('ln -nfs fixture.txt '.tmp) + execute 'edit '.tmp + 6d + write + + let expected = ['line=5 id=3000 name=GitGutterLineRemoved'] + call assert_equal(expected, s:signs('symlink')) +endfunction + + +function Test_keep_alt() + enew + execute "normal! \" + + call assert_equal('fixture.txt', bufname('')) + call assert_equal('', bufname('#')) + + normal ggx + doautocmd CursorHold + + call assert_equal('', bufname('#')) +endfunction + + +function Test_keep_modified() + normal 5Go* + call assert_equal(1, getbufvar('', '&modified')) + + doautocmd CursorHold + + call assert_equal(1, getbufvar('', '&modified')) +endfunction + + +function Test_keep_op_marks() + normal 5Go* + call assert_equal([0,6,1,0], getpos("'[")) + call assert_equal([0,6,2,0], getpos("']")) + + doautocmd CursorHold + + call assert_equal([0,6,1,0], getpos("'[")) + call assert_equal([0,6,2,0], getpos("']")) +endfunction + + +function Test_no_modifications() + call assert_equal([], s:signs('fixture.txt')) +endfunction + + +function Test_orphaned_signs() + execute "normal 5GoX\Y" + write + 6d + write + + let expected = ['line=6 id=3001 name=GitGutterLineAdded'] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + +function Test_sign_column_always() + let g:gitgutter_sign_column_always=1 + write + + let expected = ['line=9999 id=2999 name=GitGutterDummy'] + call assert_equal(expected, s:signs('fixture.txt')) + + let g:gitgutter_sign_column_always=0 +endfunction + + +function Test_untracked_file_outside_repo() + let tmp = tempname() + call system('touch '.tmp) + execute 'edit '.tmp + + call assert_equal([], s:signs(tmp)) +endfunction + + +function Test_untracked_file_within_repo() + let tmp = 'untrackedFileWithinRepo.tmp' + call system('touch '.tmp) + execute 'edit '.tmp + normal ggo* + doautocmd CursorHold + + call assert_equal([], s:signs(tmp)) + + call system('rm '.tmp) +endfunction + + +function Test_untracked_file_square_brackets_within_repo() + let tmp = '[un]trackedFileWithinRepo.tmp' + call system('touch '.tmp) + execute 'edit '.tmp + normal ggo* + doautocmd CursorHold + + call assert_equal([], s:signs(tmp)) + + call system('rm '.tmp) +endfunction + + +function Test_hunk_outside_noop() + normal 5G + GitGutterStageHunk + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) + + GitGutterUndoHunk + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) +endfunction + + +function Test_hunk_stage() + let _shell = &shell + set shell=foo + + normal 5Gi* + GitGutterStageHunk + + call assert_equal('foo', &shell) + let &shell = _shell + + call assert_equal([], s:signs('fixture.txt')) + + call assert_equal([], s:git_diff()) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index f5c6aff..ae8e546 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -5 +5 @@ d', + \ '-e', + \ '+*e' + \ ] + call assert_equal(expected, s:git_diff_staged()) +endfunction + + +function Test_hunk_stage_nearby_hunk() + execute "normal! 2Gox\y\z" + normal 2jdd + normal k + GitGutterStageHunk + + let expected = [ + \ 'line=3 id=3000 name=GitGutterLineAdded', + \ 'line=4 id=3001 name=GitGutterLineAdded', + \ 'line=5 id=3002 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fixture.txt')) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index 53b13df..8fdfda7 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -2,0 +3,3 @@ b', + \ '+x', + \ '+y', + \ '+z', + \ ] + call assert_equal(expected, s:git_diff()) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index f5c6aff..53b13df 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -4 +3,0 @@ c', + \ '-d', + \ ] + call assert_equal(expected, s:git_diff_staged()) +endfunction + + +function Test_hunk_undo() + let _shell = &shell + set shell=foo + + normal 5Gi* + GitGutterUndoHunk + write " write file so we can verify git diff (--staged) + + call assert_equal('foo', &shell) + let &shell = _shell + + call assert_equal([], s:signs('fixture.txt')) + call assert_equal([], s:git_diff()) + call assert_equal([], s:git_diff_staged()) +endfunction + + +function Test_undo_nearby_hunk() + execute "normal! 2Gox\y\z" + normal 2jdd + normal k + GitGutterUndoHunk + write " write file so we can verify git diff (--staged) + + let expected = [ + \ 'line=3 id=3000 name=GitGutterLineAdded', + \ 'line=4 id=3001 name=GitGutterLineAdded', + \ 'line=5 id=3002 name=GitGutterLineAdded' + \ ] + call assert_equal(expected, s:signs('fixture.txt')) + + let expected = [ + \ 'diff --git a/fixture.txt b/fixture.txt', + \ 'index f5c6aff..3fbde56 100644', + \ '--- a/fixture.txt', + \ '+++ b/fixture.txt', + \ '@@ -2,0 +3,3 @@ b', + \ '+x', + \ '+y', + \ '+z', + \ ] + call assert_equal(expected, s:git_diff()) + + call assert_equal([], s:git_diff_staged()) +endfunction diff --git a/bundle/nerdtree-git-plugin/README.md b/bundle/nerdtree-git-plugin/README.md new file mode 100644 index 0000000..e60ff2f --- /dev/null +++ b/bundle/nerdtree-git-plugin/README.md @@ -0,0 +1,65 @@ +nerdtree-git-plugin +=================== + +A plugin of NERDTree showing git status flags. Works with the **LATEST** version of NERDTree. + +The original project [git-nerdtree](https://github.com/Xuyuanp/git-nerdtree) will not be maintained any longer. + + +![Imgur](http://i.imgur.com/jSCwGjU.gif?1) + +## Installation + +For Vundle + +`Plugin 'scrooloose/nerdtree'` + +`Plugin 'Xuyuanp/nerdtree-git-plugin'` + +For NeoBundle + +`NeoBundle 'scrooloose/nerdtree'` + +`NeoBundle 'Xuyuanp/nerdtree-git-plugin'` + +For Plug + +`Plug 'scrooloose/nerdtree'` + +`Plug 'Xuyuanp/nerdtree-git-plugin'` + + +## FAQ + +> Got error message like `Error detected while processing function +177[2]..178[22]..181[7]..144[9]..142[36]..238[4]..NERDTreeGitStatusRefreshListener[2]..NERDTreeGitStatusRefresh: +line 6: +E484: Can't open file /tmp/vZEZ6gM/1` while nerdtree opening in fish, how to resolve this problem? + +This was because that vim couldn't execute `system` function in `fish`. Add `set shell=sh` in your vimrc. + +This issue has been fixed. + +> How to config custom symbols? + +Use this variable to change symbols. + + ```vimscript + let g:NERDTreeIndicatorMapCustom = { + \ "Modified" : "✹", + \ "Staged" : "✚", + \ "Untracked" : "✭", + \ "Renamed" : "➜", + \ "Unmerged" : "═", + \ "Deleted" : "✖", + \ "Dirty" : "✗", + \ "Clean" : "✔︎", + \ "Unknown" : "?" + \ } + ``` + +## Credits + +* [scrooloose](https://github.com/scrooloose): Open API for me. +* [git_nerd](https://github.com/swerner/git_nerd): Where my idea comes from. +* [PickRelated](https://github.com/PickRelated): Add custom indicators & Review code. diff --git a/bundle/nerdtree-git-plugin/nerdtree_plugin/git_status.vim b/bundle/nerdtree-git-plugin/nerdtree_plugin/git_status.vim new file mode 100644 index 0000000..073f38c --- /dev/null +++ b/bundle/nerdtree-git-plugin/nerdtree_plugin/git_status.vim @@ -0,0 +1,340 @@ +" ============================================================================ +" File: git_status.vim +" Description: plugin for NERD Tree that provides git status support +" Maintainer: Xuyuan Pang +" Last Change: 4 Apr 2014 +" 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_git_status') + finish +endif +let g:loaded_nerdtree_git_status = 1 + +if !exists('g:NERDTreeShowGitStatus') + let g:NERDTreeShowGitStatus = 1 +endif + +if g:NERDTreeShowGitStatus == 0 + finish +endif + +if !exists('g:NERDTreeMapNextHunk') + let g:NERDTreeMapNextHunk = ']c' +endif + +if !exists('g:NERDTreeMapPrevHunk') + let g:NERDTreeMapPrevHunk = '[c' +endif + +if !exists('g:NERDTreeUpdateOnWrite') + let g:NERDTreeUpdateOnWrite = 1 +endif + +if !exists('g:NERDTreeUpdateOnCursorHold') + let g:NERDTreeUpdateOnCursorHold = 1 +endif + +if !exists('s:NERDTreeIndicatorMap') + let s:NERDTreeIndicatorMap = { + \ 'Modified' : '✹', + \ 'Staged' : '✚', + \ 'Untracked' : '✭', + \ 'Renamed' : '➜', + \ 'Unmerged' : '═', + \ 'Deleted' : '✖', + \ 'Dirty' : '✗', + \ 'Clean' : '✔︎', + \ 'Unknown' : '?' + \ } +endif + + +function! NERDTreeGitStatusRefreshListener(event) + if !exists('b:NOT_A_GIT_REPOSITORY') + call g:NERDTreeGitStatusRefresh() + endif + let l:path = a:event.subject + let l:flag = g:NERDTreeGetGitStatusPrefix(l:path) + call l:path.flagSet.clearFlags('git') + if l:flag !=# '' + call l:path.flagSet.addFlag('git', l:flag) + endif +endfunction + +" FUNCTION: g:NERDTreeGitStatusRefresh() {{{2 +" refresh cached git status +function! g:NERDTreeGitStatusRefresh() + let b:NERDTreeCachedGitFileStatus = {} + let b:NERDTreeCachedGitDirtyDir = {} + let b:NOT_A_GIT_REPOSITORY = 1 + + let l:root = b:NERDTree.root.path.str() + let l:gitcmd = 'git -c color.status=false status -s' + if exists('g:NERDTreeGitStatusIgnoreSubmodules') + let l:gitcmd = l:gitcmd . ' --ignore-submodules' + if g:NERDTreeGitStatusIgnoreSubmodules ==# 'all' || g:NERDTreeGitStatusIgnoreSubmodules ==# 'dirty' || g:NERDTreeGitStatusIgnoreSubmodules ==# 'untracked' + let l:gitcmd = l:gitcmd . '=' . g:NERDTreeGitStatusIgnoreSubmodules + endif + endif + let l:statusesStr = system(l:gitcmd . ' ' . l:root) + let l:statusesSplit = split(l:statusesStr, '\n') + if l:statusesSplit != [] && l:statusesSplit[0] =~# 'fatal:.*' + let l:statusesSplit = [] + return + endif + let b:NOT_A_GIT_REPOSITORY = 0 + + for l:statusLine in l:statusesSplit + " cache git status of files + let l:pathStr = substitute(l:statusLine, '...', '', '') + let l:pathSplit = split(l:pathStr, ' -> ') + if len(l:pathSplit) == 2 + call s:NERDTreeCacheDirtyDir(l:pathSplit[0]) + let l:pathStr = l:pathSplit[1] + else + let l:pathStr = l:pathSplit[0] + endif + let l:pathStr = s:NERDTreeTrimDoubleQuotes(l:pathStr) + if l:pathStr =~# '\.\./.*' + continue + endif + let l:statusKey = s:NERDTreeGetFileGitStatusKey(l:statusLine[0], l:statusLine[1]) + let b:NERDTreeCachedGitFileStatus[fnameescape(l:pathStr)] = l:statusKey + + call s:NERDTreeCacheDirtyDir(l:pathStr) + endfor +endfunction + +function! s:NERDTreeCacheDirtyDir(pathStr) + " cache dirty dir + let l:dirtyPath = s:NERDTreeTrimDoubleQuotes(a:pathStr) + if l:dirtyPath =~# '\.\./.*' + return + endif + let l:dirtyPath = substitute(l:dirtyPath, '/[^/]*$', '/', '') + while l:dirtyPath =~# '.\+/.*' && has_key(b:NERDTreeCachedGitDirtyDir, fnameescape(l:dirtyPath)) == 0 + let b:NERDTreeCachedGitDirtyDir[fnameescape(l:dirtyPath)] = 'Dirty' + let l:dirtyPath = substitute(l:dirtyPath, '/[^/]*/$', '/', '') + endwhile +endfunction + +function! s:NERDTreeTrimDoubleQuotes(pathStr) + let l:toReturn = substitute(a:pathStr, '^"', '', '') + let l:toReturn = substitute(l:toReturn, '"$', '', '') + return l:toReturn +endfunction + +" FUNCTION: g:NERDTreeGetGitStatusPrefix(path) {{{2 +" return the indicator of the path +" Args: path +let s:GitStatusCacheTimeExpiry = 2 +let s:GitStatusCacheTime = 0 +function! g:NERDTreeGetGitStatusPrefix(path) + if localtime() - s:GitStatusCacheTime > s:GitStatusCacheTimeExpiry + let s:GitStatusCacheTime = localtime() + call g:NERDTreeGitStatusRefresh() + endif + let l:pathStr = a:path.str() + let l:cwd = b:NERDTree.root.path.str() . a:path.Slash() + if nerdtree#runningWindows() + let l:pathStr = a:path.WinToUnixPath(l:pathStr) + let l:cwd = a:path.WinToUnixPath(l:cwd) + endif + let l:pathStr = substitute(l:pathStr, fnameescape(l:cwd), '', '') + let l:statusKey = '' + if a:path.isDirectory + let l:statusKey = get(b:NERDTreeCachedGitDirtyDir, fnameescape(l:pathStr . '/'), '') + else + let l:statusKey = get(b:NERDTreeCachedGitFileStatus, fnameescape(l:pathStr), '') + endif + return s:NERDTreeGetIndicator(l:statusKey) +endfunction + +" FUNCTION: s:NERDTreeGetCWDGitStatus() {{{2 +" return the indicator of cwd +function! g:NERDTreeGetCWDGitStatus() + if b:NOT_A_GIT_REPOSITORY + return '' + elseif b:NERDTreeCachedGitDirtyDir == {} && b:NERDTreeCachedGitFileStatus == {} + return s:NERDTreeGetIndicator('Clean') + endif + return s:NERDTreeGetIndicator('Dirty') +endfunction + +function! s:NERDTreeGetIndicator(statusKey) + if exists('g:NERDTreeIndicatorMapCustom') + let l:indicator = get(g:NERDTreeIndicatorMapCustom, a:statusKey, '') + if l:indicator !=# '' + return l:indicator + endif + endif + let l:indicator = get(s:NERDTreeIndicatorMap, a:statusKey, '') + if l:indicator !=# '' + return l:indicator + endif + return '' +endfunction + +function! s:NERDTreeGetFileGitStatusKey(us, them) + if a:us ==# '?' && a:them ==# '?' + return 'Untracked' + elseif a:us ==# ' ' && a:them ==# 'M' + return 'Modified' + elseif a:us =~# '[MAC]' + return 'Staged' + elseif a:us ==# 'R' + return 'Renamed' + elseif a:us ==# 'U' || a:them ==# 'U' || a:us ==# 'A' && a:them ==# 'A' || a:us ==# 'D' && a:them ==# 'D' + return 'Unmerged' + elseif a:them ==# 'D' + return 'Deleted' + else + return 'Unknown' + endif +endfunction + +" FUNCTION: s:jumpToNextHunk(node) {{{2 +function! s:jumpToNextHunk(node) + let l:position = search('\[[^{RO}].*\]', '') + if l:position + call nerdtree#echo('Jump to next hunk ') + endif +endfunction + +" FUNCTION: s:jumpToPrevHunk(node) {{{2 +function! s:jumpToPrevHunk(node) + let l:position = search('\[[^{RO}].*\]', 'b') + if l:position + call nerdtree#echo('Jump to prev hunk ') + endif +endfunction + +" Function: s:SID() {{{2 +function s:SID() + if !exists('s:sid') + let s:sid = matchstr(expand(''), '\zs\d\+\ze_SID$') + endif + return s:sid +endfun + +" FUNCTION: s:NERDTreeGitStatusKeyMapping {{{2 +function! s:NERDTreeGitStatusKeyMapping() + let l:s = '' . s:SID() . '_' + + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapNextHunk, + \ 'scope': 'Node', + \ 'callback': l:s.'jumpToNextHunk', + \ 'quickhelpText': 'Jump to next git hunk' }) + + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapPrevHunk, + \ 'scope': 'Node', + \ 'callback': l:s.'jumpToPrevHunk', + \ 'quickhelpText': 'Jump to prev git hunk' }) + +endfunction + +augroup nerdtreegitplugin + autocmd CursorHold * silent! call s:CursorHoldUpdate() +augroup END +" FUNCTION: s:CursorHoldUpdate() {{{2 +function! s:CursorHoldUpdate() + if g:NERDTreeUpdateOnCursorHold != 1 + return + endif + + if !g:NERDTree.IsOpen() + return + endif + + " Do not update when a special buffer is selected + if !empty(&l:buftype) + return + endif + + let l:winnr = winnr() + let l:altwinnr = winnr('#') + + call g:NERDTree.CursorToTreeWin() + call b:NERDTree.root.refreshFlags() + call NERDTreeRender() + + exec l:altwinnr . 'wincmd w' + exec l:winnr . 'wincmd w' +endfunction + +augroup nerdtreegitplugin + autocmd BufWritePost * call s:FileUpdate(expand('%:p')) +augroup END +" FUNCTION: s:FileUpdate(fname) {{{2 +function! s:FileUpdate(fname) + if g:NERDTreeUpdateOnWrite != 1 + return + endif + + if !g:NERDTree.IsOpen() + return + endif + + let l:winnr = winnr() + let l:altwinnr = winnr('#') + + call g:NERDTree.CursorToTreeWin() + let l:node = b:NERDTree.root.findNode(g:NERDTreePath.New(a:fname)) + if l:node == {} + return + endif + call l:node.refreshFlags() + let l:node = l:node.parent + while !empty(l:node) + call l:node.refreshDirFlags() + let l:node = l:node.parent + endwhile + + call NERDTreeRender() + + exec l:altwinnr . 'wincmd w' + exec l:winnr . 'wincmd w' +endfunction + +augroup AddHighlighting + autocmd FileType nerdtree call s:AddHighlighting() +augroup END +function! s:AddHighlighting() + let l:synmap = { + \ 'NERDTreeGitStatusModified' : s:NERDTreeGetIndicator('Modified'), + \ 'NERDTreeGitStatusStaged' : s:NERDTreeGetIndicator('Staged'), + \ 'NERDTreeGitStatusUntracked' : s:NERDTreeGetIndicator('Untracked'), + \ 'NERDTreeGitStatusRenamed' : s:NERDTreeGetIndicator('Renamed'), + \ 'NERDTreeGitStatusDirDirty' : s:NERDTreeGetIndicator('Dirty'), + \ 'NERDTreeGitStatusDirClean' : s:NERDTreeGetIndicator('Clean') + \ } + + for l:name in keys(l:synmap) + exec 'syn match ' . l:name . ' #' . escape(l:synmap[l:name], '~') . '# containedin=NERDTreeFlags' + endfor + + hi def link NERDTreeGitStatusModified Special + hi def link NERDTreeGitStatusStaged Function + hi def link NERDTreeGitStatusRenamed Title + hi def link NERDTreeGitStatusUnmerged Label + hi def link NERDTreeGitStatusUntracked Comment + hi def link NERDTreeGitStatusDirDirty Tag + hi def link NERDTreeGitStatusDirClean DiffAdd +endfunction + +function! s:SetupListeners() + call g:NERDTreePathNotifier.AddListener('init', 'NERDTreeGitStatusRefreshListener') + call g:NERDTreePathNotifier.AddListener('refresh', 'NERDTreeGitStatusRefreshListener') + call g:NERDTreePathNotifier.AddListener('refreshFlags', 'NERDTreeGitStatusRefreshListener') +endfunction + +if g:NERDTreeShowGitStatus && executable('git') + call s:NERDTreeGitStatusKeyMapping() + call s:SetupListeners() +endif diff --git a/vimrc b/vimrc index 40e8e57..ed095ee 100644 --- a/vimrc +++ b/vimrc @@ -188,6 +188,10 @@ nnoremap gg :Git nnoremap gd :Gdiff +"------ Git Gutter Options ------ +"Disable h* commands as they show down movement +let g:gitgutter_map_keys = 0 + "------ Text Editing Utilities ------ " T = Delete all Trailing space in file map T :%s/\s\+$// @@ -337,7 +341,7 @@ if has("gui_running") endfunction elseif has("gui_gtk2") " Linux - set guifont=monospace\ 9 + set guifont=monospace\ 10 " Alt+n = new buffer map :enew From fa8b8a1ff45f9194175bb5dab310d6f1b8aff81c Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Sun, 27 Aug 2017 11:45:09 -0700 Subject: [PATCH 108/177] async/await syntax --- bundle/javascript/ISSUE_TEMPLATE.md | 12 + bundle/javascript/README.md | 117 +++++ .../javascript/after/ftplugin/javascript.vim | 12 + bundle/javascript/compiler/eslint.vim | 16 + bundle/javascript/extras/ctags | 8 + bundle/javascript/extras/flow.vim | 105 ++++ bundle/javascript/extras/jsdoc.vim | 39 ++ bundle/javascript/extras/ngdoc.vim | 3 + bundle/javascript/ftdetect/javascript.vim | 17 + bundle/javascript/indent/javascript.vim | 496 ++++++++++++++++++ bundle/javascript/syntax/javascript.vim | 394 ++++++++++++++ 11 files changed, 1219 insertions(+) create mode 100644 bundle/javascript/ISSUE_TEMPLATE.md create mode 100644 bundle/javascript/README.md create mode 100644 bundle/javascript/after/ftplugin/javascript.vim create mode 100644 bundle/javascript/compiler/eslint.vim create mode 100644 bundle/javascript/extras/ctags create mode 100644 bundle/javascript/extras/flow.vim create mode 100644 bundle/javascript/extras/jsdoc.vim create mode 100644 bundle/javascript/extras/ngdoc.vim create mode 100644 bundle/javascript/ftdetect/javascript.vim create mode 100644 bundle/javascript/indent/javascript.vim create mode 100644 bundle/javascript/syntax/javascript.vim diff --git a/bundle/javascript/ISSUE_TEMPLATE.md b/bundle/javascript/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..155ea8d --- /dev/null +++ b/bundle/javascript/ISSUE_TEMPLATE.md @@ -0,0 +1,12 @@ +If you are reporting an issue that involves any JSX (e.g. +
{`${example}`}
), PLEASE PLEASE PLEASE make sure you have properly +setup and are sourcing this plugin https://github.com/mxw/vim-jsx + +WE DO NOT support JSX automatically, you need another plugin to add get this +functionality. + +If applicable, include a snippet of code that we can easily copy and paste that +replicates your bug. + +Make sure the bug still exists if you disable all other javascript plugins +except the one noted above, mxw/vim-jsx diff --git a/bundle/javascript/README.md b/bundle/javascript/README.md new file mode 100644 index 0000000..b60614f --- /dev/null +++ b/bundle/javascript/README.md @@ -0,0 +1,117 @@ +# vim-javascript + +JavaScript bundle for vim, this bundle provides syntax highlighting and +improved indentation. + + +## Installation + +### Install with [pathogen](https://github.com/tpope/vim-pathogen) + + git clone https://github.com/pangloss/vim-javascript.git ~/.vim/bundle/vim-javascript + +alternatively, use a package manager like [vim-plug](https://github.com/junegunn/vim-plug) + + +## Configuration Variables + +The following variables control certain syntax highlighting plugins. You can +add them to your `.vimrc` to enable their features. + +----------------- + +``` +let g:javascript_plugin_jsdoc = 1 +``` + +Enables syntax highlighting for [JSDocs](http://usejsdoc.org/). + +Default Value: 0 + +----------------- + +``` +let g:javascript_plugin_ngdoc = 1 +``` + +Enables some additional syntax highlighting for NGDocs. Requires JSDoc plugin +to be enabled as well. + +Default Value: 0 + +----------------- + +``` +let g:javascript_plugin_flow = 1 +``` + +Enables syntax highlighting for [Flow](https://flowtype.org/). + +Default Value: 0 + +----------------- + +``` +set foldmethod=syntax +``` + +Enables code folding based on our syntax file. + +Please note this can have a dramatic effect on performance and because it is a +global vim option, we do not set it ourselves. + + +## Concealing Characters + +You can customize concealing characters, if your font provides the glyph you want, by defining one or more of the following +variables: + + let g:javascript_conceal_function = "ƒ" + let g:javascript_conceal_null = "ø" + let g:javascript_conceal_this = "@" + let g:javascript_conceal_return = "⇚" + let g:javascript_conceal_undefined = "¿" + let g:javascript_conceal_NaN = "ℕ" + let g:javascript_conceal_prototype = "¶" + let g:javascript_conceal_static = "•" + let g:javascript_conceal_super = "Ω" + let g:javascript_conceal_arrow_function = "⇒" + let g:javascript_conceal_noarg_arrow_function = "🞅" + let g:javascript_conceal_underscore_arrow_function = "🞅" + + +You can enable concealing within VIM with: + + set conceallevel=1 + +OR if you wish to toggle concealing you may wish to bind a command such as the following which will map `l` (leader is usually the `\` key) to toggling conceal mode: + + map l :exec &conceallevel ? "set conceallevel=0" : "set conceallevel=1" + + +## Indentation Specific + +* `:h cino-:` +* `:h cino-=` +* `:h cino-star` +* `:h cino-(` +* `:h cino-w` +* `:h cino-W` +* `:h cino-U` +* `:h cino-m` +* `:h cino-M` +* `:h 'indentkeys'` + +## Contributing + +Please follow the general code style +guides (read the code) and in your pull request explain the reason for the +proposed change and how it is valuable. All p.r.'s will be reviewed by a +maintainer(s) then, hopefully, merged. + +Thank you! + + +## License + +Distributed under the same terms as Vim itself. See `:help license`. diff --git a/bundle/javascript/after/ftplugin/javascript.vim b/bundle/javascript/after/ftplugin/javascript.vim new file mode 100644 index 0000000..c6c42d6 --- /dev/null +++ b/bundle/javascript/after/ftplugin/javascript.vim @@ -0,0 +1,12 @@ +" Vim filetype plugin file +" Language: JavaScript +" Maintainer: vim-javascript community +" URL: https://github.com/pangloss/vim-javascript + +setlocal iskeyword+=$ suffixesadd+=.js + +if exists('b:undo_ftplugin') + let b:undo_ftplugin .= ' | setlocal iskeyword< suffixesadd<' +else + let b:undo_ftplugin = 'setlocal iskeyword< suffixesadd<' +endif diff --git a/bundle/javascript/compiler/eslint.vim b/bundle/javascript/compiler/eslint.vim new file mode 100644 index 0000000..7695a07 --- /dev/null +++ b/bundle/javascript/compiler/eslint.vim @@ -0,0 +1,16 @@ +" Vim compiler plugin +" Language: JavaScript +" Maintainer: vim-javascript community +" URL: https://github.com/pangloss/vim-javascript + +if exists("current_compiler") + finish +endif +let current_compiler = "eslint" + +if exists(":CompilerSet") != 2 + command! -nargs=* CompilerSet setlocal +endif + +CompilerSet makeprg=eslint\ -f\ compact\ % +CompilerSet errorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %m diff --git a/bundle/javascript/extras/ctags b/bundle/javascript/extras/ctags new file mode 100644 index 0000000..cdc4edc --- /dev/null +++ b/bundle/javascript/extras/ctags @@ -0,0 +1,8 @@ +--langdef=js +--langmap=js:.js +--regex-js=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\{/\1/,object/ +--regex-js=/([A-Za-z0-9._$()]+)[ \t]*[:=][ \t]*function[ \t]*\(/\1/,function/ +--regex-js=/function[ \t]+([A-Za-z0-9._$]+)[ \t]*([^)])/\1/,function/ +--regex-js=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\[/\1/,array/ +--regex-js=/([^= ]+)[ \t]*=[ \t]*[^"]'[^']*/\1/,string/ +--regex-js=/([^= ]+)[ \t]*=[ \t]*[^']"[^"]*/\1/,string/ diff --git a/bundle/javascript/extras/flow.vim b/bundle/javascript/extras/flow.vim new file mode 100644 index 0000000..204fdbe --- /dev/null +++ b/bundle/javascript/extras/flow.vim @@ -0,0 +1,105 @@ +syntax region jsFlowDefinition contained start=/:/ end=/\%(\s*[,=;)\n]\)\@=/ contains=@jsFlowCluster containedin=jsParen +syntax region jsFlowArgumentDef contained start=/:/ end=/\%(\s*[,)]\|=>\@!\)\@=/ contains=@jsFlowCluster +syntax region jsFlowArray contained matchgroup=jsFlowNoise start=/\[/ end=/\]/ contains=@jsFlowCluster,jsComment fold +syntax region jsFlowObject contained matchgroup=jsFlowNoise start=/{/ end=/}/ contains=@jsFlowCluster,jsComment fold +syntax region jsFlowExactObject contained matchgroup=jsFlowNoise start=/{|/ end=/|}/ contains=@jsFlowCluster,jsComment fold +syntax region jsFlowParens contained matchgroup=jsFlowNoise start=/(/ end=/)/ contains=@jsFlowCluster keepend fold +syntax match jsFlowNoise contained /[:;,<>]/ +syntax keyword jsFlowType contained boolean number string null void any mixed JSON array Function object array bool class +syntax keyword jsFlowTypeof contained typeof skipempty skipempty nextgroup=jsFlowTypeCustom,jsFlowType +syntax match jsFlowTypeCustom contained /[0-9a-zA-Z_.]*/ skipwhite skipempty nextgroup=jsFlowGroup +syntax region jsFlowGroup contained matchgroup=jsFlowNoise start=// contains=@jsFlowCluster +syntax region jsFlowArrowArguments contained matchgroup=jsFlowNoise start=/(/ end=/)\%(\s*=>\)\@=/ oneline skipwhite skipempty nextgroup=jsFlowArrow contains=@jsFlowCluster +syntax match jsFlowArrow contained /=>/ skipwhite skipempty nextgroup=jsFlowType,jsFlowTypeCustom,jsFlowParens +syntax match jsFlowObjectKey contained /[0-9a-zA-Z_$?]*\(\s*:\)\@=/ contains=jsFunctionKey,jsFlowMaybe skipwhite skipempty nextgroup=jsObjectValue containedin=jsObject +syntax match jsFlowOrOperator contained /|/ skipwhite skipempty nextgroup=@jsFlowCluster +syntax keyword jsFlowImportType contained type skipwhite skipempty nextgroup=jsModuleAsterisk,jsModuleKeyword,jsModuleGroup +syntax match jsFlowWildcard contained /*/ + +syntax match jsFlowReturn contained /:\s*/ contains=jsFlowNoise skipwhite skipempty nextgroup=@jsFlowReturnCluster,jsFlowArrow,jsFlowReturnParens +syntax region jsFlowReturnObject contained matchgroup=jsFlowNoise start=/{/ end=/}/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp fold +syntax region jsFlowReturnArray contained matchgroup=jsFlowNoise start=/\[/ end=/\]/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp fold +syntax region jsFlowReturnParens contained matchgroup=jsFlowNoise start=/(/ end=/)/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp,jsFlowReturnArrow fold +syntax match jsFlowReturnArrow contained /=>/ skipwhite skipempty nextgroup=@jsFlowReturnCluster +syntax match jsFlowReturnKeyword contained /\k\+/ contains=jsFlowType,jsFlowTypeCustom skipwhite skipempty nextgroup=jsFlowReturnGroup,jsFuncBlock,jsFlowReturnOrOp +syntax match jsFlowReturnMaybe contained /?/ skipwhite skipempty nextgroup=jsFlowReturnKeyword,jsFlowReturnObject +syntax region jsFlowReturnGroup contained matchgroup=jsFlowNoise start=// contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp +syntax match jsFlowReturnOrOp contained /\s*|\s*/ skipwhite skipempty nextgroup=@jsFlowReturnCluster +syntax match jsFlowWildcardReturn contained /*/ skipwhite skipempty nextgroup=jsFuncBlock + +syntax region jsFlowFunctionGroup contained matchgroup=jsFlowNoise start=// contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncArgs +syntax region jsFlowClassGroup contained matchgroup=jsFlowNoise start=// contains=@jsFlowCluster skipwhite skipempty nextgroup=jsClassBlock + +syntax region jsFlowTypeStatement start=/type\%(\s\+\k\)\@=/ end=/=\@=/ contains=jsFlowTypeOperator oneline skipwhite skipempty nextgroup=jsFlowTypeValue keepend +syntax region jsFlowTypeValue contained matchgroup=jsFlowNoise start=/=/ end=/[\n;]/ contains=@jsFlowCluster,jsFlowGroup,jsFlowMaybe +syntax match jsFlowTypeOperator contained /=/ containedin=jsFlowTypeValue +syntax match jsFlowTypeOperator contained /=/ +syntax keyword jsFlowTypeKeyword contained type + +syntax keyword jsFlowDeclare declare skipwhite skipempty nextgroup=jsFlowTypeStatement,jsClassDefinition,jsStorageClass,jsFlowModule,jsFlowInterface +syntax match jsFlowClassProperty contained /\<[0-9a-zA-Z_$]*\>:\@=/ skipwhite skipempty nextgroup=jsFlowClassDef containedin=jsClassBlock +syntax region jsFlowClassDef contained start=/:/ end=/\%(\s*[,=;)\n]\)\@=/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsClassValue + +syntax region jsFlowModule contained start=/module/ end=/{\@=/ skipempty skipempty nextgroup=jsFlowDeclareBlock contains=jsString +syntax region jsFlowInterface contained start=/interface/ end=/{\@=/ skipempty skipempty nextgroup=jsFlowInterfaceBlock contains=@jsFlowCluster +syntax region jsFlowDeclareBlock contained matchgroup=jsFlowNoise start=/{/ end=/}/ contains=jsFlowDeclare,jsFlowNoise fold + +" NOTE: It appears the nextgroup was causing a ton of breakages... testing it +" witout a nextgroup, but keeping this arround for reference incase something breaks +" syntax match jsFlowMaybe contained /?/ nextgroup=jsFlowType,jsFlowTypeCustom,jsFlowParens,jsFlowArrowArguments,jsFlowObject,jsFlowReturnObject extend keepend +syntax match jsFlowMaybe contained /?/ +syntax region jsFlowInterfaceBlock contained matchgroup=jsFlowNoise start=/{/ end=/}/ contains=jsObjectKey,jsObjectKeyString,jsObjectKeyComputed,jsObjectSeparator,jsObjectFuncName,jsObjectMethodType,jsGenerator,jsComment,jsObjectStringKey,jsSpreadExpression,jsFlowNoise keepend fold + +syntax region jsFlowParenAnnotation contained start=/:/ end=/[,=)]\@=/ containedin=jsParen contains=@jsFlowCluster + +syntax cluster jsFlowReturnCluster contains=jsFlowNoise,jsFlowReturnObject,jsFlowReturnArray,jsFlowReturnKeyword,jsFlowReturnGroup,jsFlowReturnMaybe,jsFlowReturnOrOp,jsFlowWildcardReturn,jsFlowReturnArrow +syntax cluster jsFlowCluster contains=jsFlowArray,jsFlowObject,jsFlowExactObject,jsFlowNoise,jsFlowTypeof,jsFlowType,jsFlowGroup,jsFlowArrowArguments,jsFlowMaybe,jsFlowParens,jsFlowOrOperator,jsFlowWildcard + +if version >= 508 || !exists("did_javascript_syn_inits") + if version < 508 + let did_javascript_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + HiLink jsFlowDefinition PreProc + HiLink jsFlowClassDef jsFlowDefinition + HiLink jsFlowArgumentDef jsFlowDefinition + HiLink jsFlowType Type + HiLink jsFlowTypeCustom PreProc + HiLink jsFlowTypeof PreProc + HiLink jsFlowArray PreProc + HiLink jsFlowObject PreProc + HiLink jsFlowExactObject PreProc + HiLink jsFlowParens PreProc + HiLink jsFlowGroup PreProc + HiLink jsFlowReturn PreProc + HiLink jsFlowParenAnnotation PreProc + HiLink jsFlowReturnObject jsFlowReturn + HiLink jsFlowReturnArray jsFlowArray + HiLink jsFlowReturnParens jsFlowParens + HiLink jsFlowReturnGroup jsFlowGroup + HiLink jsFlowFunctionGroup PreProc + HiLink jsFlowClassGroup PreProc + HiLink jsFlowArrowArguments PreProc + HiLink jsFlowArrow PreProc + HiLink jsFlowReturnArrow PreProc + HiLink jsFlowTypeStatement PreProc + HiLink jsFlowTypeKeyword PreProc + HiLink jsFlowTypeOperator Operator + HiLink jsFlowMaybe PreProc + HiLink jsFlowReturnMaybe PreProc + HiLink jsFlowClassProperty jsClassProperty + HiLink jsFlowDeclare PreProc + HiLink jsFlowModule PreProc + HiLink jsFlowInterface PreProc + HiLink jsFlowNoise Noise + HiLink jsFlowObjectKey jsObjectKey + HiLink jsFlowOrOperator jsOperator + HiLink jsFlowReturnOrOp jsFlowOrOperator + HiLink jsFlowWildcard PreProc + HiLink jsFlowWildcardReturn PreProc + HiLink jsFlowImportType PreProc + HiLink jsFlowTypeValue PreProc + delcommand HiLink +endif diff --git a/bundle/javascript/extras/jsdoc.vim b/bundle/javascript/extras/jsdoc.vim new file mode 100644 index 0000000..a19f3a3 --- /dev/null +++ b/bundle/javascript/extras/jsdoc.vim @@ -0,0 +1,39 @@ +"" syntax coloring for javadoc comments (HTML) +syntax region jsComment matchgroup=jsComment start="/\*\s*" end="\*/" contains=jsDocTags,jsCommentTodo,jsCvsTag,@jsHtml,@Spell fold + +" tags containing a param +syntax match jsDocTags contained "@\(alias\|api\|augments\|borrows\|class\|constructs\|default\|defaultvalue\|emits\|exception\|exports\|extends\|fires\|kind\|link\|listens\|member\|member[oO]f\|mixes\|module\|name\|namespace\|requires\|template\|throws\|var\|variation\|version\)\>" skipwhite nextgroup=jsDocParam +" tags containing type and param +syntax match jsDocTags contained "@\(arg\|argument\|cfg\|param\|property\|prop\|typedef\)\>" skipwhite nextgroup=jsDocType +" tags containing type but no param +syntax match jsDocTags contained "@\(callback\|define\|enum\|external\|implements\|this\|type\|return\|returns\)\>" skipwhite nextgroup=jsDocTypeNoParam +" tags containing references +syntax match jsDocTags contained "@\(lends\|see\|tutorial\)\>" skipwhite nextgroup=jsDocSeeTag +" other tags (no extra syntax) +syntax match jsDocTags contained "@\(abstract\|access\|accessor\|async\|author\|classdesc\|constant\|const\|constructor\|copyright\|deprecated\|desc\|description\|dict\|event\|example\|file\|file[oO]verview\|final\|function\|global\|ignore\|inheritDoc\|inner\|instance\|interface\|license\|localdoc\|method\|mixin\|nosideeffects\|override\|overview\|preserve\|private\|protected\|public\|readonly\|since\|static\|struct\|todo\|summary\|undocumented\|virtual\)\>" + +syntax region jsDocType contained matchgroup=jsDocTypeBrackets start="{" end="}" contains=jsDocTypeRecord oneline skipwhite nextgroup=jsDocParam +syntax match jsDocType contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" skipwhite nextgroup=jsDocParam +syntax region jsDocTypeRecord contained start=/{/ end=/}/ contains=jsDocTypeRecord extend +syntax region jsDocTypeRecord contained start=/\[/ end=/\]/ contains=jsDocTypeRecord extend +syntax region jsDocTypeNoParam contained start="{" end="}" oneline +syntax match jsDocTypeNoParam contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" +syntax match jsDocParam contained "\%(#\|\$\|-\|'\|\"\|{.\{-}}\|\w\|\.\|:\|\/\|\[.\{-}]\|=\)\+" +syntax region jsDocSeeTag contained matchgroup=jsDocSeeTag start="{" end="}" contains=jsDocTags + +if version >= 508 || !exists("did_javascript_syn_inits") + if version < 508 + let did_javascript_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + HiLink jsDocTags Special + HiLink jsDocSeeTag Function + HiLink jsDocType Type + HiLink jsDocTypeBrackets jsDocType + HiLink jsDocTypeRecord jsDocType + HiLink jsDocTypeNoParam Type + HiLink jsDocParam Label + delcommand HiLink +endif diff --git a/bundle/javascript/extras/ngdoc.vim b/bundle/javascript/extras/ngdoc.vim new file mode 100644 index 0000000..c513d87 --- /dev/null +++ b/bundle/javascript/extras/ngdoc.vim @@ -0,0 +1,3 @@ +syntax match jsDocTags contained /@\(link\|method[oO]f\|ngdoc\|ng[iI]nject\|restrict\)/ nextgroup=jsDocParam skipwhite +syntax match jsDocType contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|\/\)\+" nextgroup=jsDocParam skipwhite +syntax match jsDocParam contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|{\|}\|\/\|\[\|]\|=\)\+" diff --git a/bundle/javascript/ftdetect/javascript.vim b/bundle/javascript/ftdetect/javascript.vim new file mode 100644 index 0000000..ff07f4d --- /dev/null +++ b/bundle/javascript/ftdetect/javascript.vim @@ -0,0 +1,17 @@ +au BufNewFile,BufRead *.{js,mjs,jsm,es,es6},Jakefile setf javascript + +fun! s:SourceFlowSyntax() + if !exists('javascript_plugin_flow') && !exists('b:flow_active') && + \ search('\v\C%^\_s*%(//\s*|/\*[ \t\n*]*)\@flow>','nw') + runtime extras/flow.vim + let b:flow_active = 1 + endif +endfun +au FileType javascript au BufRead,BufWritePost call s:SourceFlowSyntax() + +fun! s:SelectJavascript() + if getline(1) =~# '^#!.*/bin/\%(env\s\+\)\?node\>' + set ft=javascript + endif +endfun +au BufNewFile,BufRead * call s:SelectJavascript() diff --git a/bundle/javascript/indent/javascript.vim b/bundle/javascript/indent/javascript.vim new file mode 100644 index 0000000..ce91645 --- /dev/null +++ b/bundle/javascript/indent/javascript.vim @@ -0,0 +1,496 @@ +" Vim indent file +" Language: Javascript +" Maintainer: Chris Paul ( https://github.com/bounceme ) +" URL: https://github.com/pangloss/vim-javascript +" Last Change: August 12, 2017 + +" Only load this indent file when no other was loaded. +if exists('b:did_indent') + finish +endif +let b:did_indent = 1 + +" indent correctly if inside -``` - -blocks in html files. - -## CoffeeScript in Haml - -CoffeeScript is highlighted within the `:coffeescript` filter in haml files: - -```haml -:coffeescript - console.log "hullo" -``` - -At this time, coffee indenting doesn't work in these blocks. - -## Custom Autocmds - -You can [define commands][autocmd-explain] to be ran automatically on these -custom events. - -In all cases, the name of the command running the event (`CoffeeCompile`, -`CoffeeWatch`, or `CoffeeRun`) is matched by the [`{pat}`][autocmd] argument. -You can match all commands with a `*` or only specific commands by separating -them with a comma: `CoffeeCompile,CoffeeWatch`. - -[autocmd-explain]: http://vimdoc.sourceforge.net/htmldoc/usr_40.html#40.3 -[autocmd]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#:autocmd - -#### CoffeeBufNew - -CoffeeBufNew is ran when a new scratch buffer is created. It's called from the -new buffer, so it can be used to do additional set up. - -```vim -augroup CoffeeBufNew - autocmd User * set wrap -augroup END -``` - -*Used By*: CoffeeCompile, CoffeeWatch, CoffeeRun - -#### CoffeeBufUpdate - -CoffeeBufUpdate is ran when a scratch buffer is updated with output from -`coffee`. It's called from the scratch buffer, so it can be used to alter the -compiled output. - -```vim -" Switch back to the source buffer after updating. -augroup CoffeeBufUpdate - autocmd User CoffeeCompile,CoffeeRun exec bufwinnr(b:coffee_src_buf) 'wincmd w' -augroup END -``` - -For example, to strip off the "Generated by" comment on the first line, put this -in your vimrc: - -```vim -function! s:RemoveGeneratedBy() - " If there was an error compiling, there's no comment to remove. - if v:shell_error - return - endif - - " Save cursor position. - let pos = getpos('.') - - " Remove first line. - set modifiable - 1 delete _ - set nomodifiable - - " Restore cursor position. - call setpos('.', pos) -endfunction - -augroup CoffeeBufUpdate - autocmd User CoffeeCompile,CoffeeWatch call s:RemoveGeneratedBy() -augroup END -``` - -*Used By*: CoffeeCompile, CoffeeWatch, CoffeeRun - -## Configuration Variables - -This is the full list of configuration variables available, with example -settings and default values. Use these in your vimrc to control the default -behavior. - -#### coffee\_indent\_keep\_current - -By default, the indent function matches the indent of the previous line if it -doesn't find a reason to indent or outdent. To change this behavior so it -instead keeps the [current indent of the cursor][98], use - - let coffee_indent_keep_current = 1 - -[98]: https://github.com/kchmck/vim-coffee-script/pull/98 - -*Default*: `unlet coffee_indent_keep_current` - -Note that if you change this after a coffee file has been loaded, you'll have to -reload the indent script for the change to take effect: - - unlet b:did_indent | runtime indent/coffee.vim - -#### coffee\_compiler - -Path to the `coffee` executable used by the `Coffee` commands: - - let coffee_compiler = '/usr/bin/coffee' - -*Default*: `'coffee'` (search `$PATH` for executable) - -#### coffee\_make\_options - -Options to pass to `coffee` with `:make`: - - let coffee_make_options = '--bare' - -*Default*: `''` (nothing) - -Note that `coffee_make_options` is embedded into `'makeprg'`, so `:compiler -coffee` must be ran after changing `coffee_make_options` for the changes to take -effect. - -#### coffee\_cake - -Path to the `cake` executable: - - let coffee_cake = '/opt/bin/cake' - -*Default*: `'cake'` (search `$PATH` for executable) - -#### coffee\_cake\_options - -Options to pass to `cake` with `:make`: - - let coffee_cake_options = 'build' - -*Default*: `''` (nothing) - -#### coffee\_linter - -Path to the `coffeelint` executable: - - let coffee_linter = '/opt/bin/coffeelint' - -*Default*: `'coffeelint'` (search `$PATH` for executable) - -#### coffee\_lint\_options - -Options to pass to `coffeelint`: - - let coffee_lint_options = '-f lint.json' - -*Default*: `''` (nothing) - -#### coffee\_compile\_vert - -Open the CoffeeCompile buffer with a vertical split instead of a horizontal -one: - - let coffee_compile_vert = 1 - -*Default*: `unlet coffee_compile_vert` - -#### coffee\_watch\_vert - -Open the CoffeeWatch buffer with a vertical split instead of a horizontal -one: - - let coffee_watch_vert = 1 - -*Default*: `unlet coffee_watch_vert` - -#### coffee\_run\_vert - -Open the CoffeeRun buffer with a vertical split instead of a horizontal -one: - - let coffee_run_vert = 1 - -*Default*: `unlet coffee_run_vert` - -## Configure Syntax Highlighting - -Add these lines to your vimrc to disable the relevant syntax group. - -#### Disable trailing whitespace error - -Trailing whitespace is highlighted as an error by default. This can be disabled -with: - - hi link coffeeSpaceError NONE - -#### Disable trailing semicolon error - -Trailing semicolons are considered an error (for help transitioning from -JavaScript.) This can be disabled with: - - hi link coffeeSemicolonError NONE - -#### Disable reserved words error - -Reserved words like `function` and `var` are highlighted as an error where -they're not allowed in CoffeeScript. This can be disabled with: - - hi link coffeeReservedError NONE - -## Tune Vim for CoffeeScript - -Changing these core settings can make vim more CoffeeScript friendly. - -#### Fold by indentation - -Folding by indentation works well for CoffeeScript functions and classes: - - ![Folding](http://i.imgur.com/gDgUBdO.png) - -To fold by indentation in CoffeeScript files, add this line to your vimrc: - - autocmd BufNewFile,BufReadPost *.coffee setl foldmethod=indent nofoldenable - -With this, folding is disabled by default but can be quickly toggled per-file -by hitting `zi`. To enable folding by default, remove `nofoldenable`: - - autocmd BufNewFile,BufReadPost *.coffee setl foldmethod=indent - -#### Two-space indentation - -To get standard two-space indentation in CoffeeScript files, add this line to -your vimrc: - - autocmd BufNewFile,BufReadPost *.coffee setl shiftwidth=2 expandtab diff --git a/bundle/coffee-script/Thanks.md b/bundle/coffee-script/Thanks.md deleted file mode 100755 index 8ddcf23..0000000 --- a/bundle/coffee-script/Thanks.md +++ /dev/null @@ -1,44 +0,0 @@ -Thanks to all bug reporters, and special thanks to those who have contributed -code: - - Brian Egan (brianegan): - Initial compiling support - - Ches Martin (ches): - Initial vim docs - - Chris Hoffman (cehoffman): - Add new keywoards from, to, and do - Highlight the - in negative integers - Add here regex highlighting, increase fold level for here docs - - David Wilhelm (bigfish): - CoffeeRun command - - Jay Adkisson (jayferd): - Support for eco templates - - Karl Guertin (grayrest) - Cakefiles are coffeescript - - Maciej Konieczny (narfdotpl): - Fix funny typo - - Matt Sacks (mattsa): - Javascript omni-completion - coffee_compile_vert option - - Nick Stenning (nickstenning): - Fold by indentation for coffeescript - - Simon Lipp (sloonz): - Trailing spaces are not error on lines containing only spaces - - Stéphan Kochen (stephank): - Initial HTML CoffeeScript highlighting - - Sven Felix Oberquelle (Svelix): - Haml CoffeeScript highlighting - - Wei Dai (clvv): - Fix the use of Vim built-in make command. diff --git a/bundle/coffee-script/Todo.md b/bundle/coffee-script/Todo.md deleted file mode 100755 index 3d4ffaa..0000000 --- a/bundle/coffee-script/Todo.md +++ /dev/null @@ -1 +0,0 @@ -- Don't highlight bad operator combinations diff --git a/bundle/coffee-script/after/indent/html.vim b/bundle/coffee-script/after/indent/html.vim deleted file mode 100755 index 2fa8637..0000000 --- a/bundle/coffee-script/after/indent/html.vim +++ /dev/null @@ -1,33 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" Load the coffee and html indent functions. -silent! unlet b:did_indent -runtime indent/coffee.vim -let s:coffeeIndentExpr = &l:indentexpr - -" Load html last so it can overwrite coffee settings. -silent! unlet b:did_indent -runtime indent/html.vim -let s:htmlIndentExpr = &l:indentexpr - -" Inject our wrapper indent function. -setlocal indentexpr=GetCoffeeHtmlIndent(v:lnum) - -function! GetCoffeeHtmlIndent(curlinenum) - " See if we're inside a coffeescript block. - let scriptlnum = searchpair('', 'bWn') - let prevlnum = prevnonblank(a:curlinenum) - - " If we're in the script block and the previous line isn't the script tag - " itself, use coffee indenting. - if scriptlnum && scriptlnum != prevlnum - exec 'return ' s:coffeeIndentExpr - endif - - " Otherwise use html indenting. - exec 'return ' s:htmlIndentExpr -endfunction diff --git a/bundle/coffee-script/after/syntax/haml.vim b/bundle/coffee-script/after/syntax/haml.vim deleted file mode 100755 index 4c517eb..0000000 --- a/bundle/coffee-script/after/syntax/haml.vim +++ /dev/null @@ -1,13 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Sven Felix Oberquelle -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" Inherit coffee from html so coffeeComment isn't redefined and given higher -" priority than hamlInterpolation. -syn cluster hamlCoffeescript contains=@htmlCoffeeScript -syn region hamlCoffeescriptFilter matchgroup=hamlFilter -\ start="^\z(\s*\):coffee\z(script\)\?\s*$" -\ end="^\%(\z1 \| *$\)\@!" -\ contains=@hamlCoffeeScript,hamlInterpolation -\ keepend diff --git a/bundle/coffee-script/after/syntax/html.vim b/bundle/coffee-script/after/syntax/html.vim deleted file mode 100755 index 82b44f1..0000000 --- a/bundle/coffee-script/after/syntax/html.vim +++ /dev/null @@ -1,11 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" Syntax highlighting for text/coffeescript script tags -syn include @htmlCoffeeScript syntax/coffee.vim -syn region coffeeScript start=##me=s-1 keepend -\ contains=@htmlCoffeeScript,htmlScriptTag,@htmlPreproc -\ containedin=htmlHead diff --git a/bundle/coffee-script/autoload/coffee.vim b/bundle/coffee-script/autoload/coffee.vim deleted file mode 100755 index 8d72795..0000000 --- a/bundle/coffee-script/autoload/coffee.vim +++ /dev/null @@ -1,54 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" Set up some common global/buffer variables. -function! coffee#CoffeeSetUpVariables() - " Path to coffee executable - if !exists('g:coffee_compiler') - let g:coffee_compiler = 'coffee' - endif - - " Options passed to coffee with make - if !exists('g:coffee_make_options') - let g:coffee_make_options = '' - endif - - " Path to cake executable - if !exists('g:coffee_cake') - let g:coffee_cake = 'cake' - endif - - " Extra options passed to cake - if !exists('g:coffee_cake_options') - let g:coffee_cake_options = '' - endif - - " Path to coffeelint executable - if !exists('g:coffee_linter') - let g:coffee_linter = 'coffeelint' - endif - - " Options passed to CoffeeLint - if !exists('g:coffee_lint_options') - let g:coffee_lint_options = '' - endif - - " Pass the litcoffee flag to tools in this buffer if a litcoffee file is open. - " Let the variable be overwritten so it can be updated if a different filetype - " is set. - if &filetype == 'litcoffee' - let b:coffee_litcoffee = '--literate' - else - let b:coffee_litcoffee = '' - endif -endfunction - -function! coffee#CoffeeSetUpErrorFormat() - CompilerSet errorformat=Error:\ In\ %f\\,\ %m\ on\ line\ %l, - \Error:\ In\ %f\\,\ Parse\ error\ on\ line\ %l:\ %m, - \SyntaxError:\ In\ %f\\,\ %m, - \%f:%l:%c:\ error:\ %m, - \%-G%.%# -endfunction diff --git a/bundle/coffee-script/compiler/cake.vim b/bundle/coffee-script/compiler/cake.vim deleted file mode 100755 index b49638e..0000000 --- a/bundle/coffee-script/compiler/cake.vim +++ /dev/null @@ -1,15 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -if exists('current_compiler') - finish -endif - -let current_compiler = 'cake' -call coffee#CoffeeSetUpVariables() - -exec 'CompilerSet makeprg=' . escape(g:coffee_cake . ' ' . -\ g:coffee_cake_options . ' $*', ' ') -call coffee#CoffeeSetUpErrorFormat() diff --git a/bundle/coffee-script/compiler/coffee.vim b/bundle/coffee-script/compiler/coffee.vim deleted file mode 100755 index 5a91457..0000000 --- a/bundle/coffee-script/compiler/coffee.vim +++ /dev/null @@ -1,82 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" All this is needed to support compiling filenames with spaces, quotes, and -" such. The filename is escaped and embedded into the `makeprg` setting. -" -" Because of this, `makeprg` must be updated on every file rename. And because -" of that, `CompilerSet` can't be used because it doesn't exist when the -" rename autocmd is ran. So, we have to do some checks to see whether `compiler` -" was called locally or globally, and respect that in the rest of the script. - -if exists('current_compiler') - finish -endif - -let current_compiler = 'coffee' -call coffee#CoffeeSetUpVariables() - -" Pattern to check if coffee is the compiler -let s:pat = '^' . current_compiler - -" Get a `makeprg` for the current filename. -function! s:GetMakePrg() - return g:coffee_compiler . - \ ' -c' . - \ ' ' . b:coffee_litcoffee . - \ ' ' . g:coffee_make_options . - \ ' $*' . - \ ' ' . fnameescape(expand('%')) -endfunction - -" Set `makeprg` and return 1 if coffee is still the compiler, else return 0. -function! s:SetMakePrg() - if &l:makeprg =~ s:pat - let &l:makeprg = s:GetMakePrg() - elseif &g:makeprg =~ s:pat - let &g:makeprg = s:GetMakePrg() - else - return 0 - endif - - return 1 -endfunction - -" Set a dummy compiler so we can check whether to set locally or globally. -exec 'CompilerSet makeprg=' . current_compiler -" Then actually set the compiler. -call s:SetMakePrg() -call coffee#CoffeeSetUpErrorFormat() - -function! s:CoffeeMakeDeprecated(bang, args) - echoerr 'CoffeeMake is deprecated! Please use :make instead, its behavior ' . - \ 'is identical.' - sleep 5 - exec 'make' . a:bang a:args -endfunction - -" Compile the current file. -command! -bang -bar -nargs=* CoffeeMake -\ call s:CoffeeMakeDeprecated(, ) - -" Set `makeprg` on rename since we embed the filename in the setting. -augroup CoffeeUpdateMakePrg - autocmd! - - " Update `makeprg` if coffee is still the compiler, else stop running this - " function. - function! s:UpdateMakePrg() - if !s:SetMakePrg() - autocmd! CoffeeUpdateMakePrg - endif - endfunction - - " Set autocmd locally if compiler was set locally. - if &l:makeprg =~ s:pat - autocmd BufWritePre,BufFilePost call s:UpdateMakePrg() - else - autocmd BufWritePre,BufFilePost call s:UpdateMakePrg() - endif -augroup END diff --git a/bundle/coffee-script/doc/coffee-script.txt b/bundle/coffee-script/doc/coffee-script.txt deleted file mode 100755 index 1b43cf3..0000000 --- a/bundle/coffee-script/doc/coffee-script.txt +++ /dev/null @@ -1,4 +0,0 @@ -Please see the project readme for up-to-date docs: -https://github.com/kchmck/vim-coffee-script - - vim:tw=78:ts=8:ft=help:norl: diff --git a/bundle/coffee-script/ftdetect/coffee.vim b/bundle/coffee-script/ftdetect/coffee.vim deleted file mode 100755 index e6c4d69..0000000 --- a/bundle/coffee-script/ftdetect/coffee.vim +++ /dev/null @@ -1,17 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -autocmd BufNewFile,BufRead *.coffee set filetype=coffee -autocmd BufNewFile,BufRead *Cakefile set filetype=coffee -autocmd BufNewFile,BufRead *.coffeekup,*.ck set filetype=coffee -autocmd BufNewFile,BufRead *._coffee set filetype=coffee - -function! s:DetectCoffee() - if getline(1) =~ '^#!.*\' - set filetype=coffee - endif -endfunction - -autocmd BufNewFile,BufRead * call s:DetectCoffee() diff --git a/bundle/coffee-script/ftplugin/coffee.vim b/bundle/coffee-script/ftplugin/coffee.vim deleted file mode 100755 index 347155a..0000000 --- a/bundle/coffee-script/ftplugin/coffee.vim +++ /dev/null @@ -1,405 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -if exists('b:did_ftplugin') - finish -endif - -let b:did_ftplugin = 1 -call coffee#CoffeeSetUpVariables() - -setlocal formatoptions-=t formatoptions+=croql -setlocal comments=:# commentstring=#\ %s -setlocal omnifunc=javascriptcomplete#CompleteJS -setlocal suffixesadd+=coffee - -" Create custom augroups. -augroup CoffeeBufUpdate | augroup END -augroup CoffeeBufNew | augroup END - -" Enable coffee compiler if a compiler isn't set already. -if !len(&l:makeprg) - compiler coffee -endif - -" Switch to the window for buf. -function! s:SwitchWindow(buf) - exec bufwinnr(a:buf) 'wincmd w' -endfunction - -" Create a new scratch buffer and return the bufnr of it. After the function -" returns, vim remains in the scratch buffer so more set up can be done. -function! s:ScratchBufBuild(src, vert, size) - if a:size <= 0 - if a:vert - let size = winwidth(bufwinnr(a:src)) / 2 - else - let size = winheight(bufwinnr(a:src)) / 2 - endif - endif - - if a:vert - vertical belowright new - exec 'vertical resize' size - else - belowright new - exec 'resize' size - endif - - setlocal bufhidden=wipe buftype=nofile nobuflisted noswapfile nomodifiable - nnoremap q :hide - - return bufnr('%') -endfunction - -" Replace buffer contents with text and delete the last empty line. -function! s:ScratchBufUpdate(buf, text) - " Move to the scratch buffer. - call s:SwitchWindow(a:buf) - - " Double check we're in the scratch buffer before overwriting. - if bufnr('%') != a:buf - throw 'unable to change to scratch buffer' - endif - - setlocal modifiable - silent exec '% delete _' - silent put! =a:text - silent exec '$ delete _' - setlocal nomodifiable -endfunction - -" Parse the output of coffee into a qflist entry for src buffer. -function! s:ParseCoffeeError(output, src, startline) - " Coffee error is always on first line? - let match = matchlist(a:output, - \ '^\(\f\+\|\[stdin\]\):\(\d\):\(\d\): error: \(.\{-}\)' . "\n") - - if !len(match) - return - endif - - " Consider the line number from coffee as relative and add it to the beginning - " line number of the range the command was called on, then subtract one for - " zero-based relativity. - call setqflist([{'bufnr': a:src, 'lnum': a:startline + str2nr(match[2]) - 1, - \ 'type': 'E', 'col': str2nr(match[3]), 'text': match[4]}], 'r') -endfunction - -" Reset source buffer variables. -function! s:CoffeeCompileResetVars() - " Variables defined in source buffer: - " b:coffee_compile_buf: bufnr of output buffer - " Variables defined in output buffer: - " b:coffee_src_buf: bufnr of source buffer - " b:coffee_compile_pos: previous cursor position in output buffer - - let b:coffee_compile_buf = -1 -endfunction - -function! s:CoffeeWatchResetVars() - " Variables defined in source buffer: - " b:coffee_watch_buf: bufnr of output buffer - " Variables defined in output buffer: - " b:coffee_src_buf: bufnr of source buffer - " b:coffee_watch_pos: previous cursor position in output buffer - - let b:coffee_watch_buf = -1 -endfunction - -function! s:CoffeeRunResetVars() - " Variables defined in CoffeeRun source buffer: - " b:coffee_run_buf: bufnr of output buffer - " Variables defined in CoffeeRun output buffer: - " b:coffee_src_buf: bufnr of source buffer - " b:coffee_run_pos: previous cursor position in output buffer - - let b:coffee_run_buf = -1 -endfunction - -" Clean things up in the source buffers. -function! s:CoffeeCompileClose() - " Switch to the source buffer if not already in it. - silent! call s:SwitchWindow(b:coffee_src_buf) - call s:CoffeeCompileResetVars() -endfunction - -function! s:CoffeeWatchClose() - silent! call s:SwitchWindow(b:coffee_src_buf) - silent! autocmd! CoffeeAuWatch * - call s:CoffeeWatchResetVars() -endfunction - -function! s:CoffeeRunClose() - silent! call s:SwitchWindow(b:coffee_src_buf) - call s:CoffeeRunResetVars() -endfunction - -" Compile the lines between startline and endline and put the result into buf. -function! s:CoffeeCompileToBuf(buf, startline, endline) - let src = bufnr('%') - let input = join(getline(a:startline, a:endline), "\n") - - " Coffee doesn't like empty input. - if !len(input) - " Function should still return within output buffer. - call s:SwitchWindow(a:buf) - return - endif - - " Pipe lines into coffee. - let output = system(g:coffee_compiler . - \ ' -scb' . - \ ' ' . b:coffee_litcoffee . - \ ' 2>&1', input) - - " Paste output into output buffer. - call s:ScratchBufUpdate(a:buf, output) - - " Highlight as JavaScript if there were no compile errors. - if v:shell_error - call s:ParseCoffeeError(output, src, a:startline) - setlocal filetype= - else - " Clear the quickfix list. - call setqflist([], 'r') - setlocal filetype=javascript - endif -endfunction - -" Peek at compiled CoffeeScript in a scratch buffer. We handle ranges like this -" to prevent the cursor from being moved (and its position saved) before the -" function is called. -function! s:CoffeeCompile(startline, endline, args) - if a:args =~ '\' - echoerr 'CoffeeCompile watch is deprecated! Please use CoffeeWatch instead' - sleep 5 - call s:CoffeeWatch(a:args) - return - endif - - " Switch to the source buffer if not already in it. - silent! call s:SwitchWindow(b:coffee_src_buf) - - " Bail if not in source buffer. - if !exists('b:coffee_compile_buf') - return - endif - - " Build the output buffer if it doesn't exist. - if bufwinnr(b:coffee_compile_buf) == -1 - let src = bufnr('%') - - let vert = exists('g:coffee_compile_vert') || a:args =~ '\' - let size = str2nr(matchstr(a:args, '\<\d\+\>')) - - " Build the output buffer and save the source bufnr. - let buf = s:ScratchBufBuild(src, vert, size) - let b:coffee_src_buf = src - - " Set the buffer name. - exec 'silent! file [CoffeeCompile ' . src . ']' - - " Clean up the source buffer when the output buffer is closed. - autocmd BufWipeout call s:CoffeeCompileClose() - " Save the cursor when leaving the output buffer. - autocmd BufLeave let b:coffee_compile_pos = getpos('.') - - " Run user-defined commands on new buffer. - silent doautocmd CoffeeBufNew User CoffeeCompile - - " Switch back to the source buffer and save the output bufnr. This also - " triggers BufLeave above. - call s:SwitchWindow(src) - let b:coffee_compile_buf = buf - endif - - " Fill the scratch buffer. - call s:CoffeeCompileToBuf(b:coffee_compile_buf, a:startline, a:endline) - " Reset cursor to previous position. - call setpos('.', b:coffee_compile_pos) - - " Run any user-defined commands on the scratch buffer. - silent doautocmd CoffeeBufUpdate User CoffeeCompile -endfunction - -" Update the scratch buffer and switch back to the source buffer. -function! s:CoffeeWatchUpdate() - call s:CoffeeCompileToBuf(b:coffee_watch_buf, 1, '$') - call setpos('.', b:coffee_watch_pos) - silent doautocmd CoffeeBufUpdate User CoffeeWatch - call s:SwitchWindow(b:coffee_src_buf) -endfunction - -" Continually compile a source buffer. -function! s:CoffeeWatch(args) - silent! call s:SwitchWindow(b:coffee_src_buf) - - if !exists('b:coffee_watch_buf') - return - endif - - if bufwinnr(b:coffee_watch_buf) == -1 - let src = bufnr('%') - - let vert = exists('g:coffee_watch_vert') || a:args =~ '\' - let size = str2nr(matchstr(a:args, '\<\d\+\>')) - - let buf = s:ScratchBufBuild(src, vert, size) - let b:coffee_src_buf = src - - exec 'silent! file [CoffeeWatch ' . src . ']' - - autocmd BufWipeout call s:CoffeeWatchClose() - autocmd BufLeave let b:coffee_watch_pos = getpos('.') - - silent doautocmd CoffeeBufNew User CoffeeWatch - - call s:SwitchWindow(src) - let b:coffee_watch_buf = buf - endif - - " Make sure only one watch autocmd is defined on this buffer. - silent! autocmd! CoffeeAuWatch * - - augroup CoffeeAuWatch - autocmd InsertLeave call s:CoffeeWatchUpdate() - autocmd BufWritePost call s:CoffeeWatchUpdate() - augroup END - - call s:CoffeeWatchUpdate() -endfunction - -" Run a snippet of CoffeeScript between startline and endline. -function! s:CoffeeRun(startline, endline, args) - silent! call s:SwitchWindow(b:coffee_src_buf) - - if !exists('b:coffee_run_buf') - return - endif - - if bufwinnr(b:coffee_run_buf) == -1 - let src = bufnr('%') - - let buf = s:ScratchBufBuild(src, exists('g:coffee_run_vert'), 0) - let b:coffee_src_buf = src - - exec 'silent! file [CoffeeRun ' . src . ']' - - autocmd BufWipeout call s:CoffeeRunClose() - autocmd BufLeave let b:coffee_run_pos = getpos('.') - - silent doautocmd CoffeeBufNew User CoffeeRun - - call s:SwitchWindow(src) - let b:coffee_run_buf = buf - endif - - if a:startline == 1 && a:endline == line('$') - let output = system(g:coffee_compiler . - \ ' ' . b:coffee_litcoffee . - \ ' ' . fnameescape(expand('%')) . - \ ' ' . a:args) - else - let input = join(getline(a:startline, a:endline), "\n") - - if !len(input) - return - endif - - let output = system(g:coffee_compiler . - \ ' -s' . - \ ' ' . b:coffee_litcoffee . - \ ' ' . a:args, input) - endif - - call s:ScratchBufUpdate(b:coffee_run_buf, output) - call setpos('.', b:coffee_run_pos) - - silent doautocmd CoffeeBufUpdate User CoffeeRun -endfunction - -" Run coffeelint on a file, and add any errors between startline and endline -" to the quickfix list. -function! s:CoffeeLint(startline, endline, bang, args) - let input = join(getline(a:startline, a:endline), "\n") - - if !len(input) - return - endif - - let output = system(g:coffee_linter . - \ ' -s --reporter csv' . - \ ' ' . b:coffee_litcoffee . - \ ' ' . g:coffee_lint_options . - \ ' ' . a:args . - \ ' 2>&1', input) - - " Convert output into an array and strip off the csv header. - let lines = split(output, "\n")[1:] - let buf = bufnr('%') - let qflist = [] - - for line in lines - let match = matchlist(line, '^stdin,\(\d\+\),\d*,\(error\|warn\),\(.\+\)$') - - " Ignore unmatched lines. - if !len(match) - continue - endif - - " The 'type' will result in either 'E' or 'W'. - call add(qflist, {'bufnr': buf, 'lnum': a:startline + str2nr(match[1]) - 1, - \ 'type': toupper(match[2][0]), 'text': match[3]}) - endfor - - " Replace the quicklist with our items. - call setqflist(qflist, 'r') - - " If not given a bang, jump to first error. - if !len(a:bang) - silent! cc 1 - endif -endfunction - -" Complete arguments for Coffee* commands. -function! s:CoffeeComplete(cmd, cmdline, cursor) - let args = ['vertical'] - - " If no partial command, return all possibilities. - if !len(a:cmd) - return args - endif - - let pat = '^' . a:cmd - - for arg in args - if arg =~ pat - return [arg] - endif - endfor -endfunction - -" Set initial state variables if they don't exist -if !exists('b:coffee_compile_buf') - call s:CoffeeCompileResetVars() -endif - -if !exists('b:coffee_watch_buf') - call s:CoffeeWatchResetVars() -endif - -if !exists('b:coffee_run_buf') - call s:CoffeeRunResetVars() -endif - -command! -buffer -range=% -bar -nargs=* -complete=customlist,s:CoffeeComplete -\ CoffeeCompile call s:CoffeeCompile(, , ) -command! -buffer -bar -nargs=* -complete=customlist,s:CoffeeComplete -\ CoffeeWatch call s:CoffeeWatch() -command! -buffer -range=% -bar -nargs=* CoffeeRun -\ call s:CoffeeRun(, , ) -command! -buffer -range=% -bang -bar -nargs=* CoffeeLint -\ call s:CoffeeLint(, , , ) diff --git a/bundle/coffee-script/indent/coffee.vim b/bundle/coffee-script/indent/coffee.vim deleted file mode 100755 index 4f4570a..0000000 --- a/bundle/coffee-script/indent/coffee.vim +++ /dev/null @@ -1,428 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -if exists('b:did_indent') - finish -endif - -let b:did_indent = 1 - -setlocal autoindent -setlocal indentexpr=GetCoffeeIndent(v:lnum) -" Make sure GetCoffeeIndent is run when these are typed so they can be -" indented or outdented. -setlocal indentkeys+=0],0),0.,=else,=when,=catch,=finally - -" If no indenting or outdenting is needed, either keep the indent of the cursor -" (use autoindent) or match the indent of the previous line. -if exists('g:coffee_indent_keep_current') - let s:DEFAULT_LEVEL = '-1' -else - let s:DEFAULT_LEVEL = 'indent(prevnlnum)' -endif - -" Only define the function once. -if exists('*GetCoffeeIndent') - finish -endif - -" Keywords that begin a block -let s:BEGIN_BLOCK_KEYWORD = '\C^\%(if\|unless\|else\|for\|while\|until\|' -\ . 'loop\|switch\|when\|try\|catch\|finally\|' -\ . 'class\)\>\%(\s*:\)\@!' - -" An expression that uses the result of a statement -let s:COMPOUND_EXPRESSION = '\C\%([^-]-\|[^+]+\|[^/]/\|[:=*%&|^<>]\)\s*' -\ . '\%(if\|unless\|for\|while\|until\|loop\|switch\|' -\ . 'try\|class\)\>' - -" Combine the two above -let s:BEGIN_BLOCK = s:BEGIN_BLOCK_KEYWORD . '\|' . s:COMPOUND_EXPRESSION - -" Operators that begin a block but also count as a continuation -let s:BEGIN_BLOCK_OP = '[([{:=]$' - -" Begins a function block -let s:FUNCTION = '[-=]>$' - -" Operators that continue a line onto the next line -let s:CONTINUATION_OP = '\C\%(\<\%(is\|isnt\|and\|or\)\>\|' -\ . '[^-]-\|[^+]+\|[^-=]>\|[^.]\.\|[<*/%&|^,]\)$' - -" Ancestor operators that prevent continuation indenting -let s:CONTINUATION = s:CONTINUATION_OP . '\|' . s:BEGIN_BLOCK_OP - -" A closing bracket by itself on a line followed by a continuation -let s:BRACKET_CONTINUATION = '^\s*[}\])]\s*' . s:CONTINUATION_OP - -" A continuation dot access -let s:DOT_ACCESS = '^\.' - -" Keywords that break out of a block -let s:BREAK_BLOCK_OP = '\C^\%(return\|break\|continue\|throw\)\>' - -" A condition attached to the end of a statement -let s:POSTFIX_CONDITION = '\C\S\s\+\zs\<\%(if\|unless\|when\|while\|until\)\>' - -" A then contained in brackets -let s:CONTAINED_THEN = '\C[(\[].\{-}\.\{-\}[)\]]' - -" An else with a condition attached -let s:ELSE_COND = '\C^\s*else\s\+\<\%(if\|unless\)\>' - -" A single-line else statement (without a condition attached) -let s:SINGLE_LINE_ELSE = '\C^else\s\+\%(\<\%(if\|unless\)\>\)\@!' - -" Pairs of starting and ending keywords, with an initial pattern to match -let s:KEYWORD_PAIRS = [ -\ ['\C^else\>', '\C\<\%(if\|unless\|when\|else\s\+\%(if\|unless\)\)\>', -\ '\C\'], -\ ['\C^catch\>', '\C\', '\C\'], -\ ['\C^finally\>', '\C\', '\C\'] -\] - -" Pairs of starting and ending brackets -let s:BRACKET_PAIRS = {']': '\[', '}': '{', ')': '('} - -" Max lines to look back for a match -let s:MAX_LOOKBACK = 50 - -" Syntax names for strings -let s:SYNTAX_STRING = 'coffee\%(String\|AssignString\|Embed\|Regex\|Heregex\|' -\ . 'Heredoc\)' - -" Syntax names for comments -let s:SYNTAX_COMMENT = 'coffee\%(Comment\|BlockComment\|HeregexComment\)' - -" Syntax names for strings and comments -let s:SYNTAX_STRING_COMMENT = s:SYNTAX_STRING . '\|' . s:SYNTAX_COMMENT - -" Compatibility code for shiftwidth() as recommended by the docs, but modified -" so there isn't as much of a penalty if shiftwidth() exists. -if exists('*shiftwidth') - let s:ShiftWidth = function('shiftwidth') -else - function! s:ShiftWidth() - return &shiftwidth - endfunction -endif - -" Get the linked syntax name of a character. -function! s:SyntaxName(lnum, col) - return synIDattr(synID(a:lnum, a:col, 1), 'name') -endfunction - -" Check if a character is in a comment. -function! s:IsComment(lnum, col) - return s:SyntaxName(a:lnum, a:col) =~ s:SYNTAX_COMMENT -endfunction - -" Check if a character is in a string. -function! s:IsString(lnum, col) - return s:SyntaxName(a:lnum, a:col) =~ s:SYNTAX_STRING -endfunction - -" Check if a character is in a comment or string. -function! s:IsCommentOrString(lnum, col) - return s:SyntaxName(a:lnum, a:col) =~ s:SYNTAX_STRING_COMMENT -endfunction - -" Search a line for a regex until one is found outside a string or comment. -function! s:SearchCode(lnum, regex) - " Start at the first column and look for an initial match (including at the - " cursor.) - call cursor(a:lnum, 1) - let pos = search(a:regex, 'c', a:lnum) - - while pos - if !s:IsCommentOrString(a:lnum, col('.')) - return 1 - endif - - " Move to the match and continue searching (don't accept matches at the - " cursor.) - let pos = search(a:regex, '', a:lnum) - endwhile - - return 0 -endfunction - -" Search for the nearest previous line that isn't a comment. -function! s:GetPrevNormalLine(startlnum) - let curlnum = a:startlnum - - while curlnum - let curlnum = prevnonblank(curlnum - 1) - - " Return the line if the first non-whitespace character isn't a comment. - if !s:IsComment(curlnum, indent(curlnum) + 1) - return curlnum - endif - endwhile - - return 0 -endfunction - -function! s:SearchPair(startlnum, lookback, skip, open, close) - " Go to the first column so a:close will be matched even if it's at the - " beginning of the line. - call cursor(a:startlnum, 1) - return searchpair(a:open, '', a:close, 'bnW', a:skip, max([1, a:lookback])) -endfunction - -" Skip if a match -" - is in a string or comment -" - is a single-line statement that isn't immediately -" adjacent -" - has a postfix condition and isn't an else statement or compound -" expression -function! s:ShouldSkip(startlnum, lnum, col) - return s:IsCommentOrString(a:lnum, a:col) || - \ s:SearchCode(a:lnum, '\C\') && a:startlnum - a:lnum > 1 || - \ s:SearchCode(a:lnum, s:POSTFIX_CONDITION) && - \ getline(a:lnum) !~ s:ELSE_COND && - \ !s:SearchCode(a:lnum, s:COMPOUND_EXPRESSION) -endfunction - -" Search for the nearest and farthest match for a keyword pair. -function! s:SearchMatchingKeyword(startlnum, open, close) - let skip = 's:ShouldSkip(' . a:startlnum . ", line('.'), line('.'))" - - " Search for the nearest match. - let nearestlnum = s:SearchPair(a:startlnum, a:startlnum - s:MAX_LOOKBACK, - \ skip, a:open, a:close) - - if !nearestlnum - return [] - endif - - " Find the nearest previous line with indent less than or equal to startlnum. - let ind = indent(a:startlnum) - let lookback = s:GetPrevNormalLine(a:startlnum) - - while lookback && indent(lookback) > ind - let lookback = s:GetPrevNormalLine(lookback) - endwhile - - " Search for the farthest match. If there are no other matches, then the - " nearest match is also the farthest one. - let matchlnum = nearestlnum - - while matchlnum - let lnum = matchlnum - let matchlnum = s:SearchPair(matchlnum, lookback, skip, a:open, a:close) - endwhile - - return [nearestlnum, lnum] -endfunction - -" Strip a line of a trailing comment and surrounding whitespace. -function! s:GetTrimmedLine(lnum) - " Try to find a comment starting at the first column. - call cursor(a:lnum, 1) - let pos = search('#', 'c', a:lnum) - - " Keep searching until a comment is found or search returns 0. - while pos - if s:IsComment(a:lnum, col('.')) - break - endif - - let pos = search('#', '', a:lnum) - endwhile - - if !pos - " No comment was found so use the whole line. - let line = getline(a:lnum) - else - " Subtract 1 to get to the column before the comment and another 1 for - " column indexing -> zero-based indexing. - let line = getline(a:lnum)[:col('.') - 2] - endif - - return substitute(substitute(line, '^\s\+', '', ''), - \ '\s\+$', '', '') -endfunction - -" Get the indent policy when no special rules are used. -function! s:GetDefaultPolicy(curlnum) - " Check whether equalprg is being ran on existing lines. - if strlen(getline(a:curlnum)) == indent(a:curlnum) - " If not indenting an existing line, use the default policy. - return s:DEFAULT_LEVEL - else - " Otherwise let autoindent determine what to do with an existing line. - return '-1' - endif -endfunction - -function! GetCoffeeIndent(curlnum) - " Get the previous non-blank line (may be a comment.) - let prevlnum = prevnonblank(a:curlnum - 1) - - " Bail if there's no code before. - if !prevlnum - return -1 - endif - - " Bail if inside a multiline string. - if s:IsString(a:curlnum, 1) - let prevnlnum = prevlnum - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - - " Get the code part of the current line. - let curline = s:GetTrimmedLine(a:curlnum) - " Get the previous non-comment line. - let prevnlnum = s:GetPrevNormalLine(a:curlnum) - - " Check if the current line is the closing bracket in a bracket pair. - if has_key(s:BRACKET_PAIRS, curline[0]) - " Search for a matching opening bracket. - let matchlnum = s:SearchPair(a:curlnum, a:curlnum - s:MAX_LOOKBACK, - \ "s:IsCommentOrString(line('.'), col('.'))", - \ s:BRACKET_PAIRS[curline[0]], curline[0]) - - if matchlnum - " Match the indent of the opening bracket. - return indent(matchlnum) - else - " No opening bracket found (bad syntax), so bail. - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - endif - - " Check if the current line is the closing keyword in a keyword pair. - for pair in s:KEYWORD_PAIRS - if curline =~ pair[0] - " Find the nearest and farthest matches within the same indent level. - let matches = s:SearchMatchingKeyword(a:curlnum, pair[1], pair[2]) - - if len(matches) - " Don't force indenting/outdenting as long as line is already lined up - " with a valid match - return max([min([indent(a:curlnum), indent(matches[0])]), - \ indent(matches[1])]) - else - " No starting keyword found (bad syntax), so bail. - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - endif - endfor - - " Check if the current line is a `when` and not the first in a switch block. - if curline =~ '\C^when\>' && !s:SearchCode(prevnlnum, '\C\') - " Look back for a `when`. - while prevnlnum - if getline(prevnlnum) =~ '\C^\s*when\>' - " Indent to match the found `when`, but don't force indenting (for when - " indenting nested switch blocks.) - return min([indent(a:curlnum), indent(prevnlnum)]) - endif - - let prevnlnum = s:GetPrevNormalLine(prevnlnum) - endwhile - - " No matching `when` found (bad syntax), so bail. - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - - " If the previous line is a comment, use its indentation, but don't force - " indenting. - if prevlnum != prevnlnum - return min([indent(a:curlnum), indent(prevlnum)]) - endif - - let prevline = s:GetTrimmedLine(prevnlnum) - - " Always indent after these operators. - if prevline =~ s:BEGIN_BLOCK_OP - return indent(prevnlnum) + s:ShiftWidth() - endif - - " Indent if the previous line starts a function block, but don't force - " indenting if the line is non-blank (for empty function bodies.) - if prevline =~ s:FUNCTION - if strlen(getline(a:curlnum)) > indent(a:curlnum) - return min([indent(prevnlnum) + s:ShiftWidth(), indent(a:curlnum)]) - else - return indent(prevnlnum) + s:ShiftWidth() - endif - endif - - " Check if continuation indenting is needed. If the line ends in a slash, make - " sure it isn't a regex. - if prevline =~ s:CONTINUATION_OP && - \ !(prevline =~ '/$' && s:IsString(prevnlnum, col([prevnlnum, '$']) - 1)) - " Don't indent if the continuation follows a closing bracket. - if prevline =~ s:BRACKET_CONTINUATION - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - - let prevprevnlnum = s:GetPrevNormalLine(prevnlnum) - - " Don't indent if not the first continuation. - if prevprevnlnum && s:GetTrimmedLine(prevprevnlnum) =~ s:CONTINUATION - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - - " Continuation indenting seems to vary between programmers, so if the line - " is non-blank, don't override the indentation - if strlen(getline(a:curlnum)) > indent(a:curlnum) - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - - " Otherwise indent a level. - return indent(prevnlnum) + s:ShiftWidth() - endif - - " Check if the previous line starts with a keyword that begins a block. - if prevline =~ s:BEGIN_BLOCK - " Indent if the current line doesn't start with `then` and the previous line - " isn't a single-line statement. - if curline !~ '\C^\' && !s:SearchCode(prevnlnum, '\C\') && - \ prevline !~ s:SINGLE_LINE_ELSE - return indent(prevnlnum) + s:ShiftWidth() - else - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - endif - - " Indent a dot access if it's the first. - if curline =~ s:DOT_ACCESS - if prevline !~ s:DOT_ACCESS - return indent(prevnlnum) + s:ShiftWidth() - else - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - endif - - " Outdent if a keyword breaks out of a block as long as it doesn't have a - " postfix condition (and the postfix condition isn't a single-line statement.) - if prevline =~ s:BREAK_BLOCK_OP - if !s:SearchCode(prevnlnum, s:POSTFIX_CONDITION) || - \ s:SearchCode(prevnlnum, '\C\') && - \ !s:SearchCode(prevnlnum, s:CONTAINED_THEN) - " Don't force indenting. - return min([indent(a:curlnum), indent(prevnlnum) - s:ShiftWidth()]) - else - exec 'return' s:GetDefaultPolicy(a:curlnum) - endif - endif - - " Check if inside brackets. - let matchlnum = s:SearchPair(a:curlnum, a:curlnum - s:MAX_LOOKBACK, - \ "s:IsCommentOrString(line('.'), col('.'))", - \ '\[\|(\|{', '\]\|)\|}') - - " If inside brackets, indent relative to the brackets, but don't outdent an - " already indented line. - if matchlnum - return max([indent(a:curlnum), indent(matchlnum) + s:ShiftWidth()]) - endif - - " No special rules applied, so use the default policy. - exec 'return' s:GetDefaultPolicy(a:curlnum) -endfunction diff --git a/bundle/coffee-script/syntax/coffee.vim b/bundle/coffee-script/syntax/coffee.vim deleted file mode 100755 index bfb252f..0000000 --- a/bundle/coffee-script/syntax/coffee.vim +++ /dev/null @@ -1,221 +0,0 @@ -" Language: CoffeeScript -" Maintainer: Mick Koch -" URL: http://github.com/kchmck/vim-coffee-script -" License: WTFPL - -" Bail if our syntax is already loaded. -if exists('b:current_syntax') && b:current_syntax == 'coffee' - finish -endif - -" Include JavaScript for coffeeEmbed. -syn include @coffeeJS syntax/javascript.vim -silent! unlet b:current_syntax - -" Highlight long strings. -syntax sync fromstart - -" These are `matches` instead of `keywords` because vim's highlighting -" priority for keywords is higher than matches. This causes keywords to be -" highlighted inside matches, even if a match says it shouldn't contain them -- -" like with coffeeAssign and coffeeDot. -syn match coffeeStatement /\<\%(return\|break\|continue\|throw\)\>/ display -hi def link coffeeStatement Statement - -syn match coffeeRepeat /\<\%(for\|while\|until\|loop\)\>/ display -hi def link coffeeRepeat Repeat - -syn match coffeeConditional /\<\%(if\|else\|unless\|switch\|when\|then\)\>/ -\ display -hi def link coffeeConditional Conditional - -syn match coffeeException /\<\%(try\|catch\|finally\)\>/ display -hi def link coffeeException Exception - -syn match coffeeKeyword /\<\%(new\|in\|of\|by\|and\|or\|not\|is\|isnt\|class\|extends\|super\|do\|yield\)\>/ -\ display -" The `own` keyword is only a keyword after `for`. -syn match coffeeKeyword /\/ contained containedin=coffeeRepeat -\ display -hi def link coffeeKeyword Keyword - -syn match coffeeOperator /\<\%(instanceof\|typeof\|delete\)\>/ display -hi def link coffeeOperator Operator - -" The first case matches symbol operators only if they have an operand before. -syn match coffeeExtendedOp /\%(\S\s*\)\@<=[+\-*/%&|\^=!<>?.]\{-1,}\|[-=]>\|--\|++\|:/ -\ display -syn match coffeeExtendedOp /\<\%(and\|or\)=/ display -hi def link coffeeExtendedOp coffeeOperator - -" This is separate from `coffeeExtendedOp` to help differentiate commas from -" dots. -syn match coffeeSpecialOp /[,;]/ display -hi def link coffeeSpecialOp SpecialChar - -syn match coffeeBoolean /\<\%(true\|on\|yes\|false\|off\|no\)\>/ display -hi def link coffeeBoolean Boolean - -syn match coffeeGlobal /\<\%(null\|undefined\)\>/ display -hi def link coffeeGlobal Type - -" A special variable -syn match coffeeSpecialVar /\<\%(this\|prototype\|arguments\)\>/ display -hi def link coffeeSpecialVar Special - -" An @-variable -syn match coffeeSpecialIdent /@\%(\%(\I\|\$\)\%(\i\|\$\)*\)\?/ display -hi def link coffeeSpecialIdent Identifier - -" A class-like name that starts with a capital letter -syn match coffeeObject /\<\u\w*\>/ display -hi def link coffeeObject Structure - -" A constant-like name in SCREAMING_CAPS -syn match coffeeConstant /\<\u[A-Z0-9_]\+\>/ display -hi def link coffeeConstant Constant - -" A variable name -syn cluster coffeeIdentifier contains=coffeeSpecialVar,coffeeSpecialIdent, -\ coffeeObject,coffeeConstant - -" A non-interpolated string -syn cluster coffeeBasicString contains=@Spell,coffeeEscape -" An interpolated string -syn cluster coffeeInterpString contains=@coffeeBasicString,coffeeInterp - -" Regular strings -syn region coffeeString start=/"/ skip=/\\\\\|\\"/ end=/"/ -\ contains=@coffeeInterpString -syn region coffeeString start=/'/ skip=/\\\\\|\\'/ end=/'/ -\ contains=@coffeeBasicString -hi def link coffeeString String - -" A integer, including a leading plus or minus -syn match coffeeNumber /\%(\i\|\$\)\@/ display -syn match coffeeNumber /\<0[bB][01]\+\>/ display -syn match coffeeNumber /\<0[oO][0-7]\+\>/ display -syn match coffeeNumber /\<\%(Infinity\|NaN\)\>/ display -hi def link coffeeNumber Number - -" A floating-point number, including a leading plus or minus -syn match coffeeFloat /\%(\i\|\$\)\@/ -\ display -hi def link coffeeReservedError Error - -" A normal object assignment -syn match coffeeObjAssign /@\?\%(\I\|\$\)\%(\i\|\$\)*\s*\ze::\@!/ contains=@coffeeIdentifier display -hi def link coffeeObjAssign Identifier - -syn keyword coffeeTodo TODO FIXME XXX contained -hi def link coffeeTodo Todo - -syn match coffeeComment /#.*/ contains=@Spell,coffeeTodo -hi def link coffeeComment Comment - -syn region coffeeBlockComment start=/####\@!/ end=/###/ -\ contains=@Spell,coffeeTodo -hi def link coffeeBlockComment coffeeComment - -" A comment in a heregex -syn region coffeeHeregexComment start=/#/ end=/\ze\/\/\/\|$/ contained -\ contains=@Spell,coffeeTodo -hi def link coffeeHeregexComment coffeeComment - -" Embedded JavaScript -syn region coffeeEmbed matchgroup=coffeeEmbedDelim -\ start=/`/ skip=/\\\\\|\\`/ end=/`/ keepend -\ contains=@coffeeJS -hi def link coffeeEmbedDelim Delimiter - -syn region coffeeInterp matchgroup=coffeeInterpDelim start=/#{/ end=/}/ contained -\ contains=@coffeeAll -hi def link coffeeInterpDelim PreProc - -" A string escape sequence -syn match coffeeEscape /\\\d\d\d\|\\x\x\{2\}\|\\u\x\{4\}\|\\./ contained display -hi def link coffeeEscape SpecialChar - -" A regex -- must not follow a parenthesis, number, or identifier, and must not -" be followed by a number -syn region coffeeRegex start=#\%(\%()\|\%(\i\|\$\)\@> #{ == { { { } } } == } << " -" >> #{ == { abc: { def: 42 } } == } << " diff --git a/bundle/coffee-script/test/test-ops.coffee b/bundle/coffee-script/test/test-ops.coffee deleted file mode 100755 index 54be8db..0000000 --- a/bundle/coffee-script/test/test-ops.coffee +++ /dev/null @@ -1,90 +0,0 @@ -# Various operators -abc instanceof def -typeof abc -delete abc -abc::def - -abc + def -abc - def -abc * def -abc / def -abc % def -abc & def -abc | def -abc ^ def -abc >> def -abc << def -abc >>> def -abc ? def -abc && def -abc and def -abc || def -abc or def - -abc += def -abc -= def -abc *= def -abc /= def -abc %= def -abc &= def -abc |= def -abc ^= def -abc >>= def -abc <<= def -abc >>>= def -abc ?= def -abc &&= def -abc ||= def - -abc and= def -abc or= def - -abc.def.ghi -abc?.def?.ghi - -abc < def -abc > def -abc = def -abc == def -abc != def -abc <= def -abc >= def - -abc++ -abc-- -++abc ---abc - -# Nested operators -abc[def] = ghi -abc[def[ghi: jkl]] = 42 -@abc[def] = ghi - -abc["#{def = 42}"] = 42 -abc["#{def.ghi = 42}"] = 42 -abc["#{def[ghi] = 42}"] = 42 -abc["#{def['ghi']}"] = 42 - -# Object assignments -abc = - def: 123 - DEF: 123 - @def: 123 - Def: 123 - 'def': 123 - 42: 123 - -# Operators shouldn't be highlighted -vector= -wand= - -abc+++ -abc--- -abc ** def -abc &&& def -abc ^^ def -abc ===== def -abc <==== def -abc >==== def -abc +== def -abc =^= def diff --git a/bundle/coffee-script/test/test-reserved.coffee b/bundle/coffee-script/test/test-reserved.coffee deleted file mode 100755 index b841760..0000000 --- a/bundle/coffee-script/test/test-reserved.coffee +++ /dev/null @@ -1,27 +0,0 @@ -# Should be an error -function = 42 -var = 42 - -# Shouldn't be an error -abc.with = 42 -function: 42 -var: 42 - -# Keywords shouldn't be highlighted -abc.function -abc.do -abc.break -abc.true - -abc::function -abc::do -abc::break -abc::true - -abc:: function -abc. function - -# Numbers should be highlighted -def.42 -def .42 -def::42 diff --git a/bundle/coffee-script/test/test.haml b/bundle/coffee-script/test/test.haml deleted file mode 100755 index ae19fba..0000000 --- a/bundle/coffee-script/test/test.haml +++ /dev/null @@ -1,3 +0,0 @@ -:coffeescript - class Hello - # test diff --git a/bundle/coffee-script/test/test.html b/bundle/coffee-script/test/test.html deleted file mode 100755 index 3479145..0000000 --- a/bundle/coffee-script/test/test.html +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/bundle/elixir/.travis.yml b/bundle/elixir/.travis.yml deleted file mode 100755 index 3e67b0c..0000000 --- a/bundle/elixir/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: ruby -rvm: - - 1.9.3 -before_install: sudo apt-get install vim-gtk -before_script: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" -script: "bundle exec rspec --color -f d" diff --git a/bundle/elixir/Gemfile b/bundle/elixir/Gemfile deleted file mode 100755 index c543a5d..0000000 --- a/bundle/elixir/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'http://rubygems.org/' - -gem 'rspec' -gem 'vimrunner' diff --git a/bundle/elixir/Gemfile.lock b/bundle/elixir/Gemfile.lock deleted file mode 100755 index 8d4d64f..0000000 --- a/bundle/elixir/Gemfile.lock +++ /dev/null @@ -1,20 +0,0 @@ -GEM - remote: http://rubygems.org/ - specs: - diff-lcs (1.2.4) - rspec (2.13.0) - rspec-core (~> 2.13.0) - rspec-expectations (~> 2.13.0) - rspec-mocks (~> 2.13.0) - rspec-core (2.13.1) - rspec-expectations (2.13.0) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.13.1) - vimrunner (0.3.0) - -PLATFORMS - ruby - -DEPENDENCIES - rspec - vimrunner diff --git a/bundle/elixir/README.md b/bundle/elixir/README.md deleted file mode 100755 index 7ed3b46..0000000 --- a/bundle/elixir/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# vim-elixir - -[![Build Status](https://travis-ci.org/elixir-lang/vim-elixir.png?branch=master)](https://travis-ci.org/elixir-lang/vim-elixir) - -This project contains some Vim configuration files to work with [Elixir](http://elixir-lang.org). - -So far it's included: - -* Syntax highlighting - -* Filetype detection - -* Auto indentation - -## Install - -* Copy the files to your `~/.vim` directory. - -* If you use vim-pathogen you can clone this repo into `~/.vim/bundle` - -## Snippets - -If you are looking for snipmate snippets take a look at: [elixir-snippets](https://github.com/carlosgaldino/elixir-snippets) diff --git a/bundle/elixir/compiler/exunit.vim b/bundle/elixir/compiler/exunit.vim deleted file mode 100755 index 2c9fb29..0000000 --- a/bundle/elixir/compiler/exunit.vim +++ /dev/null @@ -1,24 +0,0 @@ -" Vim compiler file -" Language: ExUnit -" Maintainer: Rein Henrichs -" URL: https://github.com/elixir-lang/vim-elixir - -if exists("current_compiler") - finish -endif -let current_compiler = "exunit" - -if exists(":CompilerSet") != 2 " older Vim always used :setlocal - command -nargs=* CompilerSet setlocal -endif - -let s:cpo_save = &cpo -set cpo-=C - -CompilerSet makeprg=mix\ test -CompilerSet errorformat=%A\ \ %.)\ %m(%.%#),%C\ \ \ \ \ **%m,%C\ \ \ \ \ \ \ %m,%Z\ \ \ \ \ at\ %f:%l,%-G%.%# - -let &cpo = s:cpo_save -unlet s:cpo_save - -" vim: nowrap sw=2 sts=2 ts=8: diff --git a/bundle/elixir/ftdetect/elixir.vim b/bundle/elixir/ftdetect/elixir.vim deleted file mode 100755 index df413e1..0000000 --- a/bundle/elixir/ftdetect/elixir.vim +++ /dev/null @@ -1,2 +0,0 @@ -au BufRead,BufNewFile *.ex,*.exs set filetype=elixir -au FileType elixir setl sw=2 sts=2 et iskeyword+=!,? diff --git a/bundle/elixir/ftplugin/elixir.vim b/bundle/elixir/ftplugin/elixir.vim deleted file mode 100755 index 5571fcf..0000000 --- a/bundle/elixir/ftplugin/elixir.vim +++ /dev/null @@ -1,25 +0,0 @@ -" Vim filetype plugin -" Language: Elixir -" Maintainer: Carlos Galdino -" URL: https://github.com/elixir-lang/vim-elixir - -if (exists("b:did_ftplugin")) - finish -endif -let b:did_ftplugin = 1 - - -" Matchit support -if exists("loaded_matchit") && !exists("b:match_words") - let b:match_ignorecase = 0 - - let b:match_words = '\<\%(do\|fn\)\:\@!\>' . - \ ':' . - \ '\<\%(else\|elsif\|catch\|after\|rescue\)\:\@!\>' . - \ ':' . - \ '\:\@' . - \ ',{:},\[:\],(:)' -endif - -setlocal comments=:# -setlocal commentstring=#\ %s diff --git a/bundle/elixir/indent/elixir.vim b/bundle/elixir/indent/elixir.vim deleted file mode 100755 index fababe4..0000000 --- a/bundle/elixir/indent/elixir.vim +++ /dev/null @@ -1,107 +0,0 @@ -" Vim indent file -" Language: Elixir -" Maintainer: Carlos Galdino -" Last Change: 2013 Apr 24 - -if exists("b:did_indent") - finish -endif -let b:did_indent = 1 - -setlocal nosmartindent - -setlocal indentexpr=GetElixirIndent() -setlocal indentkeys+==end,=else:,=match:,=elsif:,=catch:,=after:,=rescue: - -if exists("*GetElixirIndent") - finish -endif - -let s:cpo_save = &cpo -set cpo&vim - -let s:skip_syntax = '\%(Comment\|String\)$' -let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . s:skip_syntax . "'" -let s:block_start = 'do\|fn' -let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue' -let s:block_end = 'end' -let s:arrow = '^.*->$' -let s:pipeline = '^\s*|>.*$' - -let s:indent_keywords = '\<\%(' . s:block_start . '\|' . s:block_middle . '\)$' . '\|' . s:arrow -let s:deindent_keywords = '^\s*\<\%(' . s:block_end . '\|' . s:block_middle . '\)\>' . '\|' . s:arrow - -function! GetElixirIndent() - let lnum = prevnonblank(v:lnum - 1) - let ind = indent(lnum) - - " At the start of the file use zero indent. - if lnum == 0 - return 0 - endif - - " TODO: Remove these 2 lines - " I don't know why, but for the test on spec/indent/lists_spec.rb:24. - " Vim is making some mess on parsing the syntax of 'end', it is being - " recognized as 'elixirString' when should be recognized as 'elixirBlock'. - " This forces vim to sync the syntax. - call synID(v:lnum, 1, 1) - syntax sync fromstart - - if synIDattr(synID(v:lnum, 1, 1), "name") !~ s:skip_syntax - let current_line = getline(v:lnum) - let last_line = getline(lnum) - - let splited_line = split(last_line, '\zs') - let opened_symbol = 0 - let opened_symbol += count(splited_line, '[') - count(splited_line, ']') - let opened_symbol += count(splited_line, '{') - count(splited_line, '}') - - let ind += opened_symbol * &sw - - if current_line =~ '^\s*\(\]\|}\)' - let ind -= &sw - endif - - if last_line =~ s:indent_keywords - let ind += &sw - endif - - " if line starts with pipeline - " and last line is an attribution - " indents pipeline in same level as attribution - if current_line =~ s:pipeline && - \ last_line =~ '^[^=]\+=.\+$' - let b:old_ind = ind - let ind = float2nr(matchend(last_line, '=\s*[^ ]') / &sw) * &sw - endif - - " if last line starts with pipeline - " and current line doesn't start with pipeline - " returns the indentation before the pipeline - if last_line =~ s:pipeline && - \ current_line !~ s:pipeline - let ind = b:old_ind - endif - - if current_line =~ s:deindent_keywords - let bslnum = searchpair( '\<\%(' . s:block_start . '\):\@!\>', - \ '\<\%(' . s:block_middle . '\):\@!\>\zs', - \ '\<:\@\zs', - \ 'nbW', - \ s:block_skip ) - - let ind = indent(bslnum) - endif - - " indent case statements '->' - if current_line =~ s:arrow - let ind += &sw - endif - endif - - return ind -endfunction - -let &cpo = s:cpo_save -unlet s:cpo_save diff --git a/bundle/elixir/spec/indent/anonymous_functions_spec.rb b/bundle/elixir/spec/indent/anonymous_functions_spec.rb deleted file mode 100755 index e3dd40f..0000000 --- a/bundle/elixir/spec/indent/anonymous_functions_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - context "single body functions inside do block" do - it "is declared with fn syntax" do - assert_correct_indenting <<-EOF - def do - some_func = fn x -> x end - end - EOF - end - - it "is declared with function syntax" do - assert_correct_indenting <<-EOF - def do - some_func = function do x -> x end - end - EOF - end - - it "spans in multiple lines" do - assert_correct_indenting <<-EOF - def test do - assert_raise Queue.Empty, fn -> - Q.new |> Q.deq! - end - end - EOF - end - - it "spans in multiple lines inside parentheses" do - assert_correct_indenting <<-EOF - defmodule Test do - def lol do - Enum.map([1,2,3], fn x -> - x * 3 - end) - end - end - EOF - end - end - - context "multiple body functions declaring" do - it "it with fn syntax" do - assert_correct_indenting <<-EOF - fizzbuzz = fn - 0, 0, _ -> "FizzBuzz" - 0, _, _ -> "Fizz" - _, 0, _ -> "Buzz" - _, _, x -> x - end - EOF - end - - it "it with function syntax" do - assert_correct_indenting <<-EOF - fizzbuzz = function do - 0, 0, _ -> "FizzBuzz" - 0, _, _ -> "Fizz" - _, 0, _ -> "Buzz" - _, _, x -> x - end - EOF - end - end -end diff --git a/bundle/elixir/spec/indent/blocks_spec.rb b/bundle/elixir/spec/indent/blocks_spec.rb deleted file mode 100755 index cbc0c82..0000000 --- a/bundle/elixir/spec/indent/blocks_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - specify "'do' indenting" do - assert_correct_indenting <<-EOF - do - something - end - EOF - end - - it "does not consider :end as end" do - assert_correct_indenting <<-EOF - defmodule Test do - def lol do - IO.inspect :end - end - end - EOF - end - - it "does not consider do: as the start of a block" do - assert_correct_indenting <<-EOF - def f do - if true do: 42 - end - EOF - end -end diff --git a/bundle/elixir/spec/indent/case_spec.rb b/bundle/elixir/spec/indent/case_spec.rb deleted file mode 100755 index e0df5d6..0000000 --- a/bundle/elixir/spec/indent/case_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - specify "case statements" do - assert_correct_indenting <<-EOF - case some_function do - :ok -> - :ok - { :error, :message } -> - { :error, :message } - end - EOF - end -end diff --git a/bundle/elixir/spec/indent/cond_spec.rb b/bundle/elixir/spec/indent/cond_spec.rb deleted file mode 100755 index d3534d1..0000000 --- a/bundle/elixir/spec/indent/cond_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - it "conditional" do - assert_correct_indenting <<-EOF - cond do - foo -> 1 - bar -> 2 - end - EOF - end -end diff --git a/bundle/elixir/spec/indent/documentation_spec.rb b/bundle/elixir/spec/indent/documentation_spec.rb deleted file mode 100755 index 72d0c7d..0000000 --- a/bundle/elixir/spec/indent/documentation_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - context "documentation" do - it "with end keyword" do - assert_correct_indenting <<-EOF - defmodule Test do - @doc """ - end - """ - end - EOF - end - end -end diff --git a/bundle/elixir/spec/indent/if_spec.rb b/bundle/elixir/spec/indent/if_spec.rb deleted file mode 100755 index 0d0970a..0000000 --- a/bundle/elixir/spec/indent/if_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - it "if-clauses" do - assert_correct_indenting <<-EOF - if foo do - bar - end - EOF - end - - it "if-else-clauses" do - assert_correct_indenting <<-EOF - if foo do - bar - else - baz - end - EOF - end -end diff --git a/bundle/elixir/spec/indent/lists_spec.rb b/bundle/elixir/spec/indent/lists_spec.rb deleted file mode 100755 index 895c07f..0000000 --- a/bundle/elixir/spec/indent/lists_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - specify "lists" do - assert_correct_indenting <<-EOF - def example do - [ :foo, - :bar, - :baz ] - end - EOF - end - - specify "keyword list" do - assert_correct_indenting <<-EOF - def project do - [ name: "mix", - version: "0.1.0", - deps: deps ] - end - EOF - end - - specify "keyword" do - assert_correct_indenting <<-EOF - def config do - [ name: - "John" ] - end - EOF - end - - specify "list of tuples" do - assert_correct_indenting <<-EOF - def test do - [ { :cowboy, github: "extend/cowboy" }, - { :dynamo, "0.1.0-dev", github: "elixir-lang/dynamo" }, - { :ecto, github: "elixir-lang/ecto" }, - { :pgsql, github: "semiocast/pgsql" } ] - end - EOF - end - - specify "list of lists" do - assert_correct_indenting <<-EOF - def test do - [ [:a, :b, :c], - [:d, :e, :f] ] - end - EOF - end - - specify "complex list" do - assert_correct_indenting <<-EOF - def test do - [ app: :first, - version: "0.0.1", - dynamos: [First.Dynamo], - compilers: [:elixir, :dynamo, :ecto, :app], - env: [prod: [compile_path: "ebin"]], - compile_path: "tmp/first/ebin", - deps: deps ] - end - EOF - end - - specify "lists with break line after square brackets" do - assert_correct_indenting <<-EOF - def project do - deps: [ - { :bar, path: "deps/umbrella/apps/bar" }, - { :umbrella, path: "deps/umbrella" } - ] - end - EOF - end -end diff --git a/bundle/elixir/spec/indent/pipeline_spec.rb b/bundle/elixir/spec/indent/pipeline_spec.rb deleted file mode 100755 index 26db511..0000000 --- a/bundle/elixir/spec/indent/pipeline_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - it "using multiline pipeline" do - assert_correct_indenting <<-EOF - "a,b,c,d" - |> String.split(",") - |> Enum.reverse - EOF - end - - it "attribuition using multline pipeline operator" do - assert_correct_indenting <<-EOF - [ h | t ] = "a,b,c,d" - |> String.split(",") - |> Enum.reverse - EOF - end - - it "function with pipeline operator" do - assert_correct_indenting <<-EOF - def test do - [ h | t ] = "a,b,c,d" - |> String.split(",") - |> Enum.reverse - - { :ok, h } - end - EOF - end - - it "pipeline operator with block open" do - assert_correct_indenting <<-EOF - def test do - "a,b,c,d" - |> String.split(",") - |> Enum.first - |> case do - "a" -> "A" - _ -> "Z" - end - end - EOF - end - - it "using a record with pipeline" do - assert_correct_indenting <<-EOF - defrecord RECORD, field_a: nil, field_b: nil - - rec = RECORD.new - |> IO.inspect - EOF - end -end diff --git a/bundle/elixir/spec/indent/tuples_spec.rb b/bundle/elixir/spec/indent/tuples_spec.rb deleted file mode 100755 index 5464704..0000000 --- a/bundle/elixir/spec/indent/tuples_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'spec_helper' - -describe "Indenting" do - specify "multiline tuple" do - assert_correct_indenting <<-EOF - def xpto do - { :a, - :b, - :c } - end - EOF - end - - specify "tuples with break line after square brackets" do - assert_correct_indenting <<-EOF - def method do - { - :bar, - path: "deps/umbrella/apps/bar" - } - end - EOF - end -end diff --git a/bundle/elixir/spec/spec_helper.rb b/bundle/elixir/spec/spec_helper.rb deleted file mode 100755 index ab86908..0000000 --- a/bundle/elixir/spec/spec_helper.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'tmpdir' -require 'vimrunner' - -module Support - def assert_correct_indenting(string) - content = write_file(string) - - @vim.edit file - # remove all indentation - @vim.normal 'ggVG999<<' - # force vim to indent the file - @vim.normal 'gg=G' - @vim.write - - read_file.should eq(content) - end - - def assert_correct_syntax(syntax, cursor, string) - write_file(string) - - @vim.edit file - @vim.search cursor - - cursor_syntax_stack.should include(syntax) - end - - def assert_incorrect_syntax(type, cursor, string) - write_file(string) - - @vim.edit file - @vim.search cursor - - cursor_syntax_stack.should_not include(type) - end - - private - - def write_file(string) - content = file_content(string) - File.open file, 'w' do |f| - f.write content - end - - content - end - - def file_content(string) - whitespace = string.scan(/^\s*/).first - string.split("\n").map { |line| - line.gsub(/^#{whitespace}/, '') - }.join("\n").strip - end - - def cursor_syntax_stack - @vim.echo <<-EOF - map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")') - EOF - end - - def read_file - IO.read(file).strip - end - - def file; 'test.exs'; end -end - -RSpec.configure do |config| - include Support - - config.before(:suite) do - VIM = Vimrunner.start_gvim - VIM.prepend_runtimepath(File.expand_path('../..', __FILE__)) - VIM.command('runtime ftdetect/elixir.vim') - end - - config.after(:suite) do - VIM.kill - end - - config.around(:each) do |example| - @vim = VIM - - # cd into a temporary directory for every example. - Dir.mktmpdir do |dir| - Dir.chdir(dir) do - @vim.command("cd #{dir}") - example.call - end - end - end -end diff --git a/bundle/elixir/spec/syntax/default_argument_spec.rb b/bundle/elixir/spec/syntax/default_argument_spec.rb deleted file mode 100755 index ec69a3e..0000000 --- a/bundle/elixir/spec/syntax/default_argument_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'spec_helper' - -describe "Default argument syntax" do - it "default argument" do - assert_correct_syntax 'elixirOperator', '\\', <<-'EOF' - def foo(bar \\ :baz) - EOF - - assert_correct_syntax 'elixirOperator', '\/', <<-EOF - def foo(bar // :baz) - EOF - end -end diff --git a/bundle/elixir/spec/syntax/heredoc_spec.rb b/bundle/elixir/spec/syntax/heredoc_spec.rb deleted file mode 100755 index eb50a4f..0000000 --- a/bundle/elixir/spec/syntax/heredoc_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'spec_helper' - -describe "Heredoc syntax" do - describe "binary" do - it "with multiline content" do - assert_correct_syntax 'elixirDocString', 'foo', <<-EOF - @doc """ - foo - """ - EOF - end - - it "escapes quotes unless only preceded by whitespace" do - assert_correct_syntax 'elixirDocString', %q(^\s*\zs"""), <<-EOF - @doc """ - foo """ - """ - EOF - end - - it "does not include content on initial line", focus: true do - assert_correct_syntax 'elixirNumber', '0', <<-EOF - String.at """, 0 - foo - end - EOF - end - - it "with interpolation" do - assert_correct_syntax 'elixirInterpolation', 'bar', <<-EOF - @doc """ - foo \#{bar} - """ - EOF - end - end - - describe "character list" do - it "with multiline content" do - assert_correct_syntax 'elixirDocString', 'foo', <<-EOF - @doc """ - foo - """ - EOF - end - - it "escapes quotes unless only preceded by whitespace" do - assert_correct_syntax 'elixirDocString', %q(^\s*\zs'''), <<-EOF - @doc ''' - foo ''' - ''' - EOF - end - - it "with interpolation" do - assert_correct_syntax 'elixirInterpolation', 'bar', <<-EOF - @doc ''' - foo \#{bar} - ''' - EOF - end - end -end diff --git a/bundle/elixir/spec/syntax/records_spec.rb b/bundle/elixir/spec/syntax/records_spec.rb deleted file mode 100755 index b68814a..0000000 --- a/bundle/elixir/spec/syntax/records_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -# encoding: utf-8 -require 'spec_helper' - -describe "Record syntax" do - it "private record symbol" do - assert_correct_syntax 'elixirSymbol', ':user', <<-EOF - defrecordp :user, name: "José", age: 25 - EOF - end -end diff --git a/bundle/elixir/spec/syntax/sigil_spec.rb b/bundle/elixir/spec/syntax/sigil_spec.rb deleted file mode 100755 index ef68304..0000000 --- a/bundle/elixir/spec/syntax/sigil_spec.rb +++ /dev/null @@ -1,109 +0,0 @@ -require 'spec_helper' - -describe "Sigil syntax" do - describe "upper case" do - it "string" do - assert_correct_syntax 'elixirDelimiter', 'S', '~S(string)' - assert_correct_syntax 'elixirSigil', 'foo', '~S(string)' - end - - it "character list" do - assert_correct_syntax 'elixirDelimiter', 'C', '~C(charlist)' - assert_correct_syntax 'elixirSigil', 'charlist', '~C(charlist)' - end - - it "regular expression" do - assert_correct_syntax 'elixirDelimiter', 'R', '~R(regex)' - assert_correct_syntax 'elixirSigil', 'regex', '~R(regex)' - end - - it "list of words" do - assert_correct_syntax 'elixirDelimiter', 'W', '~W(list of words)' - assert_correct_syntax 'elixirSigil', 'list', '~W(list of words)' - end - - it "delimited with parans" do - assert_correct_syntax 'elixirDelimiter', '(', '~S(foo bar)' - assert_correct_syntax 'elixirDelimiter', ')', '~S(foo bar)' - end - - it "delimited with braces" do - assert_correct_syntax 'elixirDelimiter', '{', '~S{foo bar}' - assert_correct_syntax 'elixirDelimiter', '}', '~S{foo bar}' - end - - it "delimited with brackets" do - assert_correct_syntax 'elixirDelimiter', '[', '~S[foo bar]' - assert_correct_syntax 'elixirDelimiter', ']', '~S[foo bar]' - end - - it "escapes double quotes unless only preceded by whitespace" do - assert_correct_syntax 'elixirDelimiter', %q(^\s*\zs"""), <<-EOF - ~r""" - foo """ - """ - EOF - end - - it "escapes single quotes unless only preceded by whitespace" do - assert_correct_syntax 'elixirDelimiter', %q(^\s*\zs'''), <<-EOF - ~r''' - foo ''' - ''' - EOF - end - - it "without escapes" do - assert_incorrect_syntax 'elixirRegexEscape', '\\', '~S(foo \n bar)' - end - - it "without interpolation" do - assert_incorrect_syntax 'elixirInterpolation', 'bar', '~S(foo #{bar})' - end - - it "without escaped parans" do - assert_incorrect_syntax 'elixirRegexEscapePunctuation', '( ', '~S(\( )' - end - end - - describe "lower case" do - it "string" do - assert_correct_syntax 'elixirDelimiter', 's', '~s(string)' - assert_correct_syntax 'elixirSigil', 'foo', '~s(string)' - end - - it "character list" do - assert_correct_syntax 'elixirDelimiter', 'c', '~c(charlist)' - assert_correct_syntax 'elixirSigil', 'charlist', '~c(charlist)' - end - - it "regular expression" do - assert_correct_syntax 'elixirDelimiter', 'r', '~r(regex)' - assert_correct_syntax 'elixirSigil', 'regex', '~r(regex)' - end - - it "list of words" do - assert_correct_syntax 'elixirDelimiter', 'w', '~w(list of words)' - assert_correct_syntax 'elixirSigil', 'list', '~w(list of words)' - end - - it "with escapes" do - assert_correct_syntax 'elixirRegexEscape', '\\', '~s(foo \n bar)' - end - - it "with interpolation" do - assert_correct_syntax 'elixirInterpolation', 'bar', '~s(foo #{bar})' - end - - it "with escaped parans" do - assert_correct_syntax 'elixirRegexEscapePunctuation', '( ', '~s(\( )' - end - end - - describe "old syntax" do - it "string" do - assert_correct_syntax 'elixirDelimiter', 's', '%s(string)' - assert_correct_syntax 'elixirSigil', 'foo', '%s(string)' - end - end -end diff --git a/bundle/elixir/spec/syntax/variable_spec.rb b/bundle/elixir/spec/syntax/variable_spec.rb deleted file mode 100755 index 2877e7f..0000000 --- a/bundle/elixir/spec/syntax/variable_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "Variable syntax" do - it "unused" do - assert_correct_syntax 'elixirUnusedVariable', '_from', <<-EOF - def handle_call(:pop, _from, [h|stack]) do - { :reply, h, stack } - end - EOF - end -end diff --git a/bundle/elixir/syntax/elixir.vim b/bundle/elixir/syntax/elixir.vim deleted file mode 100755 index ff58d55..0000000 --- a/bundle/elixir/syntax/elixir.vim +++ /dev/null @@ -1,166 +0,0 @@ -" Vim syntax file -" Language: Elixir -" Maintainer: Carlos Galdino -" Last Change: 2013 Apr 24 - -if exists("b:current_syntax") - finish -endif - -" syncing starts 2000 lines before top line so docstrings don't screw things up -syn sync minlines=2000 - -syn cluster elixirNotTop contains=@elixirRegexSpecial,@elixirStringContained,@elixirDeclaration,elixirTodo,elixirArguments - -syn match elixirComment '#.*' contains=elixirTodo -syn keyword elixirTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained - -syn keyword elixirKeyword is_atom is_binary is_bitstring is_boolean is_float is_function is_integer is_list is_number is_pid is_port is_record is_reference is_tuple is_exception -syn keyword elixirKeyword case cond bc lc inlist inbits if unless try receive -syn keyword elixirKeyword exit raise throw after rescue catch else do end -syn keyword elixirKeyword quote unquote super -syn match elixirKeyword '\<\%(->\)\>\s*' - -syn keyword elixirInclude import require alias use - -syn keyword elixirOperator and not or when xor in -syn match elixirOperator '%=\|\*=\|\*\*=\|+=\|-=\|\^=\|||=' -syn match elixirOperator "\%(<=>\|<\%(<\|=\)\@!\|>\%(<\|=\|>\)\@!\|<=\|>=\|===\|==\|=\~\|!=\|!\~\|\s?[ \t]\@=\)" -syn match elixirOperator "!+[ \t]\@=\|&&\|||\|\^\|\*\|+\|-\|/" -syn match elixirOperator "|\|++\|--\|\*\*\|\/\/\|\\\\\|<-\|<>\|<<\|>>\|=\|\.\|::" - -syn match elixirSymbol '\(:\)\@=]\@!\)\?\|<>\|===\?\|>=\?\|<=\?\)' -syn match elixirSymbol '\(:\)\@\|&&\?\|%\(()\|\[\]\|{}\)\|++\?\|--\?\|||\?\|!\|//\|[%&`/|]\)' -syn match elixirSymbol "\%([a-zA-Z_]\w*\([?!]\)\?\):\(:\)\@!" - -syn keyword elixirName nil -syn match elixirName '\<[A-Z]\w*\>' - -syn match elixirUnusedVariable '\<_\w*\>' - -syn keyword elixirBoolean true false - -syn match elixirVariable '@[a-zA-Z_]\w*\|&\d' - -syn keyword elixirPseudoVariable __FILE__ __DIR__ __MODULE__ __ENV__ __CALLER__ - -syn match elixirNumber '\<\d\(_\?\d\)*\(\.[^[:space:][:digit:]]\@!\(_\?\d\)*\)\?\([eE][-+]\?\d\(_\?\d\)*\)\?\>' -syn match elixirNumber '\<0[xX][0-9A-Fa-f]\+\>' -syn match elixirNumber '\<0[bB][01]\+\>' - -syn match elixirRegexEscape "\\\\\|\\[aAbBcdDefGhHnrsStvVwW]\|\\\d\{3}\|\\x[0-9a-fA-F]\{2}" contained -syn match elixirRegexEscapePunctuation "?\|\\.\|*\|\\\[\|\\\]\|+\|\\^\|\\\$\|\\|\|\\(\|\\)\|\\{\|\\}" contained -syn match elixirRegexQuantifier "[*?+][?+]\=" contained display -syn match elixirRegexQuantifier "{\d\+\%(,\d*\)\=}?\=" contained display -syn match elixirRegexCharClass "\[:\(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained display - -syn region elixirRegex matchgroup=elixirDelimiter start="%r/" end="/[uiomxfr]*" skip="\\\\" contains=@elixirRegexSpecial - -syn cluster elixirRegexSpecial contains=elixirRegexEscape,elixirRegexCharClass,elixirRegexQuantifier,elixirRegexEscapePunctuation -syn cluster elixirStringContained contains=elixirInterpolation,elixirRegexEscape,elixirRegexCharClass - -syn region elixirString matchgroup=elixirDelimiter start="'" end="'" skip="\\'" -syn region elixirString matchgroup=elixirDelimiter start='"' end='"' skip='\\"' contains=@elixirStringContained -syn region elixirInterpolation matchgroup=elixirDelimiter start="#{" end="}" contained contains=ALLBUT,elixirComment,@elixirNotTop - -syn region elixirDocStringStart matchgroup=elixirDocString start=+"""+ end=+$+ oneline contains=ALLBUT,@elixirNotTop -syn region elixirDocStringStart matchgroup=elixirDocString start=+'''+ end=+$+ oneline contains=ALLBUT,@elixirNotTop -syn region elixirDocString start=+\z("""\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo,elixirInterpolation fold keepend -syn region elixirDocString start=+\z('''\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo,elixirInterpolation fold keepend - -syn match elixirSymbolInterpolated ':\("\)\@=' contains=elixirString -syn match elixirString "\(\w\)\@\|0[0-7]{0,2}[0-7]\@!\>\|[^x0MC]\)\|(\\[MC]-)+\w\|[^\s\\]\)" - -syn region elixirBlock matchgroup=elixirKeyword start="\\(:\)\@!" end="\" contains=ALLBUT,@elixirNotTop fold -syn region elixirAnonymousFunction matchgroup=elixirKeyword start="\" end="\" contains=ALLBUT,@elixirNotTop fold - -syn region elixirArguments start="(" end=")" contained contains=elixirOperator,elixirSymbol,elixirPseudoVariable,elixirName,elixirBoolean,elixirVariable,elixirUnusedVariable,elixirNumber,elixirDocString,elixirSymbolInterpolated,elixirRegex,elixirString,elixirDelimiter - -syn match elixirDelimEscape "\\[(<{\[)>}\]]" transparent display contained contains=NONE - -syn region elixirSigil matchgroup=elixirDelimiter start="[%~]\z([~`!@#$%^&*_\-+|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][SCRW]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][SCRW]\={" end="}" skip="\\\\\|\\}" contains=elixirDelimEscape fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][SCRW]\=<" end=">" skip="\\\\\|\\>" contains=elixirDelimEscape fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][SCRW]\=\[" end="\]" skip="\\\\\|\\\]" contains=elixirDelimEscape fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][SCRW]\=(" end=")" skip="\\\\\|\\)" contains=elixirDelimEscape fold - -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][scrw]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][scrw]{" end="}" skip="\\\\\|\\}" fold contains=@elixirStringContained,elixirRegexEscapePunctuation -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][scrw]<" end=">" skip="\\\\\|\\>" fold contains=@elixirStringContained,elixirRegexEscapePunctuation -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][scrw]\[" end="\]" skip="\\\\\|\\\]" fold contains=@elixirStringContained,elixirRegexEscapePunctuation -syn region elixirSigil matchgroup=elixirDelimiter start="[%~][scrw](" end=")" skip="\\\\\|\\)" fold contains=@elixirStringContained,elixirRegexEscapePunctuation - -" Sigils surrounded with docString -syn region elixirSigil matchgroup=elixirDelimiter start=+[%~][SCRWscrw]\z("""\)+ end=+^\s*\zs\z1+ skip=+\\"+ fold -syn region elixirSigil matchgroup=elixirDelimiter start=+[%~][SCRWscrw]\z('''\)+ end=+^\s*\zs\z1+ skip=+\\'+ fold - -" Defines -syn keyword elixirDefine def nextgroup=elixirFunctionDeclaration skipwhite skipnl -syn keyword elixirDefine def nextgroup=elixirFunctionDeclaration skipwhite skipnl -syn keyword elixirPrivateDefine defp nextgroup=elixirFunctionDeclaration skipwhite skipnl -syn keyword elixirModuleDefine defmodule nextgroup=elixirModuleDeclaration skipwhite skipnl -syn keyword elixirProtocolDefine defprotocol nextgroup=elixirProtocolDeclaration skipwhite skipnl -syn keyword elixirImplDefine defimpl nextgroup=elixirImplDeclaration skipwhite skipnl -syn keyword elixirRecordDefine defrecord nextgroup=elixirRecordDeclaration skipwhite skipnl -syn keyword elixirPrivateRecordDefine defrecordp nextgroup=elixirRecordDeclaration skipwhite skipnl -syn keyword elixirMacroDefine defmacro nextgroup=elixirMacroDeclaration skipwhite skipnl -syn keyword elixirPrivateMacroDefine defmacrop nextgroup=elixirMacroDeclaration skipwhite skipnl -syn keyword elixirDelegateDefine defdelegate nextgroup=elixirDelegateDeclaration skipwhite skipnl -syn keyword elixirOverridableDefine defoverridable nextgroup=elixirOverridableDeclaration skipwhite skipnl -syn keyword elixirExceptionDefine defexception nextgroup=elixirExceptionDeclaration skipwhite skipnl -syn keyword elixirCallbackDefine defcallback nextgroup=elixirCallbackDeclaration skipwhite skipnl - -" Declarations -syn match elixirModuleDeclaration "[^[:space:];#<]\+" contained contains=elixirName nextgroup=elixirBlock skipwhite skipnl -syn match elixirFunctionDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl -syn match elixirProtocolDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl -syn match elixirImplDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl -syn match elixirRecordDeclaration "[^[:space:];#<]\+" contained contains=elixirName,elixirSymbol skipwhite skipnl -syn match elixirMacroDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl -syn match elixirDelegateDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl -syn region elixirDelegateDeclaration start='\[' end='\]' contained contains=elixirFunctionDeclaration skipwhite skipnl -syn match elixirOverridableDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl -syn match elixirExceptionDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl -syn match elixirCallbackDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl - -syn cluster elixirDeclaration contains=elixirFunctionDeclaration,elixirModuleDeclaration,elixirProtocolDeclaration,elixirImplDeclaration,elixirRecordDeclaration,elixirMacroDeclaration,elixirDelegateDeclaration,elixirOverridableDeclaration,elixirExceptionDeclaration,elixirCallbackDeclaration - -hi def link elixirDefine Define -hi def link elixirPrivateDefine Define -hi def link elixirModuleDefine Define -hi def link elixirProtocolDefine Define -hi def link elixirImplDefine Define -hi def link elixirRecordDefine Define -hi def link elixirPrivateRecordDefine Define -hi def link elixirMacroDefine Define -hi def link elixirPrivateMacroDefine Define -hi def link elixirDelegateDefine Define -hi def link elixirOverridableDefine Define -hi def link elixirExceptionDefine Define -hi def link elixirCallbackDefine Define -hi def link elixirFunctionDeclaration Function -hi def link elixirMacroDeclaration Macro -hi def link elixirInclude Include -hi def link elixirComment Comment -hi def link elixirTodo Todo -hi def link elixirKeyword Keyword -hi def link elixirOperator Operator -hi def link elixirSymbol Constant -hi def link elixirPseudoVariable Constant -hi def link elixirName Type -hi def link elixirBoolean Boolean -hi def link elixirVariable Identifier -hi def link elixirUnusedVariable Comment -hi def link elixirNumber Number -hi def link elixirDocString String -hi def link elixirSymbolInterpolated elixirSymbol -hi def link elixirRegex elixirString -hi def link elixirRegexEscape elixirSpecial -hi def link elixirRegexEscapePunctuation elixirSpecial -hi def link elixirRegexCharClass elixirSpecial -hi def link elixirRegexQuantifier elixirSpecial -hi def link elixirSpecial Special -hi def link elixirString String -hi def link elixirSigil String -hi def link elixirDelimiter Delimiter diff --git a/bundle/groovy/syntax/groovy.vim b/bundle/groovy/syntax/groovy.vim deleted file mode 100644 index 5f96dfb..0000000 --- a/bundle/groovy/syntax/groovy.vim +++ /dev/null @@ -1,450 +0,0 @@ -" Vim syntax file -" Language: Groovy -" Maintainer: Alessio Pace -" Version: 0.1.9b -" URL: http://www.vim.org/scripts/script.php?script_id=945 -" Last Change: 6/4/2004 - -" This is my very first vim script, I hope to have -" done it the right way. -" -" I must directly or indirectly thank the author of java.vim and ruby.vim: -" I copied from them most of the stuff :-) -" -" Relies on html.vim - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -" -" HOWTO USE IT (INSTALL): -" [groovy is still not recognized by vim! :-( ] -" -" 1) copy the file in the (global or user's $HOME/.vim/syntax/) syntax folder -" -" 2) add this line to recognize groovy files by filename extension: -" -" au BufNewFile,BufRead *.groovy setf groovy -" in the global vim filetype.vim file or inside $HOME/.vim/filetype.vim -" -" 3) add this part to recognize by content groovy script (no extension needed :-) -" -" if did_filetype() -" finish -" endif -" if getline(1) =~ '^#!.*[/\\]groovy\>' -" setf groovy -" endif -" -" in the global scripts.vim file or in $HOME/.vim/scripts.vim -" -" 4) open/write a .groovy file or a groovy script :-) -" -" Let me know if you like it or send me patches, so that I can improve it -" when I have time - -" Quit when a syntax file was already loaded -if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") - finish - endif - " we define it here so that included files can test for it - let main_syntax='groovy' -endif - -" don't use standard HiLink, it will not work with included syntax files -if version < 508 - command! -nargs=+ GroovyHiLink hi link -else - command! -nargs=+ GroovyHiLink hi def link -endif - -" ########################## -" Java stuff taken from java.vim -" some characters that cannot be in a groovy program (outside a string) -" syn match groovyError "[\\@`]" -"syn match groovyError "<<<\|\.\.\|=>\|<>\|||=\|&&=\|[^-]->\|\*\/" -"syn match groovyOK "\.\.\." - -" keyword definitions -syn keyword groovyExternal native package -syn match groovyExternal "\\)\?" -syn keyword groovyError goto const -syn keyword groovyConditional if else switch -syn keyword groovyRepeat while for do -syn keyword groovyBoolean true false -syn keyword groovyConstant null -syn keyword groovyTypedef this super -syn keyword groovyOperator new instanceof -syn keyword groovyType boolean char byte short int long float double -syn keyword groovyType void -syn keyword groovyType Integer Double Date Boolean Float String Array Vector List -syn keyword groovyStatement return -syn keyword groovyStorageClass static synchronized transient volatile final strictfp serializable -syn keyword groovyExceptions throw try catch finally -syn keyword groovyAssert assert -syn keyword groovyMethodDecl synchronized throws -syn keyword groovyClassDecl extends implements interface -" to differentiate the keyword class from MyClass.class we use a match here -syn match groovyTypedef "\.\s*\"ms=s+1 -syn keyword groovyClassDecl enum -syn match groovyClassDecl "^class\>" -syn match groovyClassDecl "[^.]\s*\"ms=s+1 -syn keyword groovyBranch break continue nextgroup=groovyUserLabelRef skipwhite -syn match groovyUserLabelRef "\k\+" contained -syn keyword groovyScopeDecl public protected private abstract - - -if exists("groovy_highlight_groovy_lang_ids") || exists("groovy_highlight_groovy_lang") || exists("groovy_highlight_all") - " groovy.lang.* - syn keyword groovyLangClass Closure MetaMethod GroovyObject - - syn match groovyJavaLangClass "\" - syn keyword groovyJavaLangClass Cloneable Comparable Runnable Serializable Boolean Byte Class Object - syn keyword groovyJavaLangClass Character CharSequence ClassLoader Compiler - " syn keyword groovyJavaLangClass Integer Double Float Long - syn keyword groovyJavaLangClass InheritableThreadLocal Math Number Object Package Process - syn keyword groovyJavaLangClass Runtime RuntimePermission InheritableThreadLocal - syn keyword groovyJavaLangClass SecurityManager Short StrictMath StackTraceElement - syn keyword groovyJavaLangClass StringBuffer Thread ThreadGroup - syn keyword groovyJavaLangClass ThreadLocal Throwable Void ArithmeticException - syn keyword groovyJavaLangClass ArrayIndexOutOfBoundsException AssertionError - syn keyword groovyJavaLangClass ArrayStoreException ClassCastException - syn keyword groovyJavaLangClass ClassNotFoundException - syn keyword groovyJavaLangClass CloneNotSupportedException Exception - syn keyword groovyJavaLangClass IllegalAccessException - syn keyword groovyJavaLangClass IllegalArgumentException - syn keyword groovyJavaLangClass IllegalMonitorStateException - syn keyword groovyJavaLangClass IllegalStateException - syn keyword groovyJavaLangClass IllegalThreadStateException - syn keyword groovyJavaLangClass IndexOutOfBoundsException - syn keyword groovyJavaLangClass InstantiationException InterruptedException - syn keyword groovyJavaLangClass NegativeArraySizeException NoSuchFieldException - syn keyword groovyJavaLangClass NoSuchMethodException NullPointerException - syn keyword groovyJavaLangClass NumberFormatException RuntimeException - syn keyword groovyJavaLangClass SecurityException StringIndexOutOfBoundsException - syn keyword groovyJavaLangClass UnsupportedOperationException - syn keyword groovyJavaLangClass AbstractMethodError ClassCircularityError - syn keyword groovyJavaLangClass ClassFormatError Error ExceptionInInitializerError - syn keyword groovyJavaLangClass IllegalAccessError InstantiationError - syn keyword groovyJavaLangClass IncompatibleClassChangeError InternalError - syn keyword groovyJavaLangClass LinkageError NoClassDefFoundError - syn keyword groovyJavaLangClass NoSuchFieldError NoSuchMethodError - syn keyword groovyJavaLangClass OutOfMemoryError StackOverflowError - syn keyword groovyJavaLangClass ThreadDeath UnknownError UnsatisfiedLinkError - syn keyword groovyJavaLangClass UnsupportedClassVersionError VerifyError - syn keyword groovyJavaLangClass VirtualMachineError - - syn keyword groovyJavaLangObject clone equals finalize getClass hashCode - syn keyword groovyJavaLangObject notify notifyAll toString wait - - GroovyHiLink groovyLangClass groovyConstant - GroovyHiLink groovyJavaLangClass groovyExternal - GroovyHiLink groovyJavaLangObject groovyConstant - syn cluster groovyTop add=groovyJavaLangObject,groovyJavaLangClass,groovyLangClass - syn cluster groovyClasses add=groovyJavaLangClass,groovyLangClass -endif - - -" Groovy stuff -syn match groovyOperator "\.\." -syn match groovyOperator "<\{2,3}" -syn match groovyOperator ">\{2,3}" -syn match groovyOperator "->" -syn match groovyExternal '^#!.*[/\\]groovy\>' -syn match groovyExceptions "\\|\<[A-Z]\{1,}[a-zA-Z0-9]*Exception\>" - -" Groovy JDK stuff -syn keyword groovyJDKBuiltin as def in -syn keyword groovyJDKOperOverl div minus plus abs round power multiply -syn keyword groovyJDKMethods each call inject sort print println -syn keyword groovyJDKMethods getAt putAt size push pop toList getText writeLine eachLine readLines -syn keyword groovyJDKMethods withReader withStream withWriter withPrintWriter write read leftShift -syn keyword groovyJDKMethods withWriterAppend readBytes splitEachLine -syn keyword groovyJDKMethods newInputStream newOutputStream newPrintWriter newReader newWriter -syn keyword groovyJDKMethods compareTo next previous isCase -syn keyword groovyJDKMethods times step toInteger upto any collect dump every find findAll grep -syn keyword groovyJDKMethods inspect invokeMethods join -syn keyword groovyJDKMethods getErr getIn getOut waitForOrKill -syn keyword groovyJDKMethods count tokenize asList flatten immutable intersect reverse reverseEach -syn keyword groovyJDKMethods subMap append asWritable eachByte eachLine eachFile -syn cluster groovyTop add=groovyJDKBuiltin,groovyJDKOperOverl,groovyJDKMethods - -" no useful I think, so I comment it.. -"if filereadable(expand(":p:h")."/groovyid.vim") - " source :p:h/groovyid.vim -"endif - -if exists("groovy_space_errors") - if !exists("groovy_no_trail_space_error") - syn match groovySpaceError "\s\+$" - endif - if !exists("groovy_no_tab_space_error") - syn match groovySpaceError " \+\t"me=e-1 - endif -endif - -" it is a better case construct than java.vim to match groovy syntax -syn region groovyLabelRegion transparent matchgroup=groovyLabel start="\" matchgroup=NONE end=":\|$" contains=groovyNumber,groovyString,groovyLangClass,groovyJavaLangClass -syn match groovyUserLabel "^\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\s*:"he=e-1 contains=groovyLabel -syn keyword groovyLabel default - -if !exists("groovy_allow_cpp_keywords") - syn keyword groovyError auto delete extern friend inline redeclared - syn keyword groovyError register signed sizeof struct template typedef union - syn keyword groovyError unsigned operator -endif - -" The following cluster contains all groovy groups except the contained ones -syn cluster groovyTop add=groovyExternal,groovyError,groovyError,groovyBranch,groovyLabelRegion,groovyLabel,groovyConditional,groovyRepeat,groovyBoolean,groovyConstant,groovyTypedef,groovyOperator,groovyType,groovyType,groovyStatement,groovyStorageClass,groovyAssert,groovyExceptions,groovyMethodDecl,groovyClassDecl,groovyClassDecl,groovyClassDecl,groovyScopeDecl,groovyError,groovyError2,groovyUserLabel,groovyLangObject - - -" Comments -syn keyword groovyTodo contained TODO FIXME XXX -if exists("groovy_comment_strings") - syn region groovyCommentString contained start=+"+ end=+"+ end=+$+ end=+\*/+me=s-1,he=s-1 contains=groovySpecial,groovyCommentStar,groovySpecialChar,@Spell - syn region groovyComment2String contained start=+"+ end=+$\|"+ contains=groovySpecial,groovySpecialChar,@Spell - syn match groovyCommentCharacter contained "'\\[^']\{1,6\}'" contains=groovySpecialChar - syn match groovyCommentCharacter contained "'\\''" contains=groovySpecialChar - syn match groovyCommentCharacter contained "'[^\\]'" - syn cluster groovyCommentSpecial add=groovyCommentString,groovyCommentCharacter,groovyNumber - syn cluster groovyCommentSpecial2 add=groovyComment2String,groovyCommentCharacter,groovyNumber -endif -syn region groovyComment start="/\*" end="\*/" contains=@groovyCommentSpecial,groovyTodo,@Spell -syn match groovyCommentStar contained "^\s*\*[^/]"me=e-1 -syn match groovyCommentStar contained "^\s*\*$" -syn match groovyLineComment "//.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell -syn match groovyLineComment "#.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell -GroovyHiLink groovyCommentString groovyString -GroovyHiLink groovyComment2String groovyString -GroovyHiLink groovyCommentCharacter groovyCharacter - -syn cluster groovyTop add=groovyComment,groovyLineComment - -if !exists("groovy_ignore_groovydoc") && main_syntax != 'jsp' - syntax case ignore - " syntax coloring for groovydoc comments (HTML) - " syntax include @groovyHtml :p:h/html.vim - syntax include @groovyHtml runtime! syntax/html.vim - unlet b:current_syntax - syn region groovyDocComment start="/\*\*" end="\*/" keepend contains=groovyCommentTitle,@groovyHtml,groovyDocTags,groovyTodo,@Spell - syn region groovyCommentTitle contained matchgroup=groovyDocComment start="/\*\*" matchgroup=groovyCommentTitle keepend end="\.$" end="\.[ \t\r<&]"me=e-1 end="[^{]@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@groovyHtml,groovyCommentStar,groovyTodo,@Spell,groovyDocTags - - syn region groovyDocTags contained start="{@\(link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}" - syn match groovyDocTags contained "@\(see\|param\|exception\|throws\|since\)\s\+\S\+" contains=groovyDocParam - syn match groovyDocParam contained "\s\S\+" - syn match groovyDocTags contained "@\(version\|author\|return\|deprecated\|serial\|serialField\|serialData\)\>" - syntax case match -endif - -" match the special comment /**/ -syn match groovyComment "/\*\*/" - -" Strings and constants -syn match groovySpecialError contained "\\." -syn match groovySpecialCharError contained "[^']" -syn match groovySpecialChar contained "\\\([4-9]\d\|[0-3]\d\d\|[\"\\'ntbrf]\|u\x\{4\}\)" -syn region groovyString start=+"+ end=+"+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr -syn region groovyString start=+'+ end=+'+ end=+$+ contains=groovySpecialChar,groovySpecialError,@Spell,groovyELExpr -" syn region groovyELExpr start=+${+ end=+}+ keepend contained - syn match groovyELExpr /\${.\{-}}/ contained -GroovyHiLink groovyELExpr Identifier - -" TODO: better matching. I am waiting to understand how it really works in groovy -" syn region groovyClosureParamsBraces start=+|+ end=+|+ contains=groovyClosureParams -" syn match groovyClosureParams "[ a-zA-Z0-9_*]\+" contained -" GroovyHiLink groovyClosureParams Identifier - -" next line disabled, it can cause a crash for a long line -"syn match groovyStringError +"\([^"\\]\|\\.\)*$+ - -" disabled: in groovy strings or characters are written the same -" syn match groovyCharacter "'[^']*'" contains=groovySpecialChar,groovySpecialCharError -" syn match groovyCharacter "'\\''" contains=groovySpecialChar -" syn match groovyCharacter "'[^\\]'" -syn match groovyNumber "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>" -syn match groovyNumber "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\=" -syn match groovyNumber "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>" -syn match groovyNumber "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>" - -" unicode characters -syn match groovySpecial "\\u\d\{4\}" - -syn cluster groovyTop add=groovyString,groovyCharacter,groovyNumber,groovySpecial,groovyStringError - -if exists("groovy_highlight_functions") - if groovy_highlight_functions == "indent" - syn match groovyFuncDef "^\(\t\| \{8\}\)[_$a-zA-Z][_$a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses - syn region groovyFuncDef start=+^\(\t\| \{8\}\)[$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses - syn match groovyFuncDef "^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*)" contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses - syn region groovyFuncDef start=+^ [$_a-zA-Z][$_a-zA-Z0-9_. \[\]]*([^-+*/()]*,\s*+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,@groovyClasses - else - " This line catches method declarations at any indentation>0, but it assumes - " two things: - " 1. class names are always capitalized (ie: Button) - " 2. method names are never capitalized (except constructors, of course) - syn region groovyFuncDef start=+^\s\+\(\(public\|protected\|private\|static\|abstract\|final\|native\|synchronized\)\s\+\)*\(\(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^>]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*([^0-9]+ end=+)+ contains=groovyScopeDecl,groovyType,groovyStorageClass,groovyComment,groovyLineComment,@groovyClasses - endif - syn match groovyBraces "[{}]" - syn cluster groovyTop add=groovyFuncDef,groovyBraces -endif - -if exists("groovy_highlight_debug") - - " Strings and constants - syn match groovyDebugSpecial contained "\\\d\d\d\|\\." - syn region groovyDebugString contained start=+"+ end=+"+ contains=groovyDebugSpecial - syn match groovyDebugStringError +"\([^"\\]\|\\.\)*$+ - syn match groovyDebugCharacter contained "'[^\\]'" - syn match groovyDebugSpecialCharacter contained "'\\.'" - syn match groovyDebugSpecialCharacter contained "'\\''" - syn match groovyDebugNumber contained "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>" - syn match groovyDebugNumber contained "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\=" - syn match groovyDebugNumber contained "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>" - syn match groovyDebugNumber contained "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>" - syn keyword groovyDebugBoolean contained true false - syn keyword groovyDebugType contained null this super - syn region groovyDebugParen start=+(+ end=+)+ contained contains=groovyDebug.*,groovyDebugParen - - " to make this work you must define the highlighting for these groups - syn match groovyDebug "\= 508 || !exists("did_c_syn_inits") - GroovyHiLink groovyDebug Debug - GroovyHiLink groovyDebugString DebugString - GroovyHiLink groovyDebugStringError groovyError - GroovyHiLink groovyDebugType DebugType - GroovyHiLink groovyDebugBoolean DebugBoolean - GroovyHiLink groovyDebugNumber Debug - GroovyHiLink groovyDebugSpecial DebugSpecial - GroovyHiLink groovyDebugSpecialCharacter DebugSpecial - GroovyHiLink groovyDebugCharacter DebugString - GroovyHiLink groovyDebugParen Debug - - GroovyHiLink DebugString String - GroovyHiLink DebugSpecial Special - GroovyHiLink DebugBoolean Boolean - GroovyHiLink DebugType Type - endif -endif - -" Match all Exception classes -syn match groovyExceptions "\\|\<[A-Z]\{1,}[a-zA-Z0-9]*Exception\>" - - -if !exists("groovy_minlines") - let groovy_minlines = 10 -endif -exec "syn sync ccomment groovyComment minlines=" . groovy_minlines - - -" ################### -" Groovy stuff -" syn match groovyOperator "|[ ,a-zA-Z0-9_*]\+|" - -" All groovy valid tokens -" syn match groovyTokens ";\|,\|<=>\|<>\|:\|:=\|>\|>=\|=\|==\|<\|<=\|!=\|/\|/=\|\.\.|\.\.\.\|\~=\|\~==" -" syn match groovyTokens "\*=\|&\|&=\|\*\|->\|\~\|+\|-\|/\|?\|<<<\|>>>\|<<\|>>" - -" Must put explicit these ones because groovy.vim mark them as errors otherwise -" syn match groovyTokens "<=>\|<>\|==\~" -"syn cluster groovyTop add=groovyTokens - -" Mark these as operators - -" Hightlight brackets -" syn match groovyBraces "[{}]" -" syn match groovyBraces "[\[\]]" -" syn match groovyBraces "[\|]" - -if exists("groovy_mark_braces_in_parens_as_errors") - syn match groovyInParen contained "[{}]" - GroovyHiLink groovyInParen groovyError - syn cluster groovyTop add=groovyInParen -endif - -" catch errors caused by wrong parenthesis -syn region groovyParenT transparent matchgroup=groovyParen start="(" end=")" contains=@groovyTop,groovyParenT1 -syn region groovyParenT1 transparent matchgroup=groovyParen1 start="(" end=")" contains=@groovyTop,groovyParenT2 contained -syn region groovyParenT2 transparent matchgroup=groovyParen2 start="(" end=")" contains=@groovyTop,groovyParenT contained -syn match groovyParenError ")" -GroovyHiLink groovyParenError groovyError - -" catch errors caused by wrong square parenthesis -syn region groovyParenT transparent matchgroup=groovyParen start="\[" end="\]" contains=@groovyTop,groovyParenT1 -syn region groovyParenT1 transparent matchgroup=groovyParen1 start="\[" end="\]" contains=@groovyTop,groovyParenT2 contained -syn region groovyParenT2 transparent matchgroup=groovyParen2 start="\[" end="\]" contains=@groovyTop,groovyParenT contained -syn match groovyParenError "\]" - -" ############################### -" java.vim default highlighting -if version >= 508 || !exists("did_groovy_syn_inits") - if version < 508 - let did_groovy_syn_inits = 1 - endif - GroovyHiLink groovyFuncDef Function - GroovyHiLink groovyBraces Function - GroovyHiLink groovyBranch Conditional - GroovyHiLink groovyUserLabelRef groovyUserLabel - GroovyHiLink groovyLabel Label - GroovyHiLink groovyUserLabel Label - GroovyHiLink groovyConditional Conditional - GroovyHiLink groovyRepeat Repeat - GroovyHiLink groovyExceptions Exception - GroovyHiLink groovyAssert Statement - GroovyHiLink groovyStorageClass StorageClass - GroovyHiLink groovyMethodDecl groovyStorageClass - GroovyHiLink groovyClassDecl groovyStorageClass - GroovyHiLink groovyScopeDecl groovyStorageClass - GroovyHiLink groovyBoolean Boolean - GroovyHiLink groovySpecial Special - GroovyHiLink groovySpecialError Error - GroovyHiLink groovySpecialCharError Error - GroovyHiLink groovyString String - GroovyHiLink groovyCharacter Character - GroovyHiLink groovySpecialChar SpecialChar - GroovyHiLink groovyNumber Number - GroovyHiLink groovyError Error - GroovyHiLink groovyStringError Error - GroovyHiLink groovyStatement Statement - GroovyHiLink groovyOperator Operator - GroovyHiLink groovyComment Comment - GroovyHiLink groovyDocComment Comment - GroovyHiLink groovyLineComment Comment - GroovyHiLink groovyConstant Constant - GroovyHiLink groovyTypedef Typedef - GroovyHiLink groovyTodo Todo - - GroovyHiLink groovyCommentTitle SpecialComment - GroovyHiLink groovyDocTags Special - GroovyHiLink groovyDocParam Function - GroovyHiLink groovyCommentStar groovyComment - - GroovyHiLink groovyType Type - GroovyHiLink groovyExternal Include - - GroovyHiLink htmlComment Special - GroovyHiLink htmlCommentPart Special - GroovyHiLink groovySpaceError Error - GroovyHiLink groovyJDKBuiltin Special - GroovyHiLink groovyJDKOperOverl Operator - GroovyHiLink groovyJDKMethods Function -endif - -delcommand GroovyHiLink - - -let b:current_syntax = "groovy" -if main_syntax == 'groovy' - unlet main_syntax -endif - -let b:spell_options="contained" - -" vim: ts=8 diff --git a/bundle/jade/README.markdown b/bundle/jade/README.markdown deleted file mode 100755 index 2c2222e..0000000 --- a/bundle/jade/README.markdown +++ /dev/null @@ -1,19 +0,0 @@ -# vim-jade # - -Vim syntax highlighting for Jade templates. - -Installation ------------- - -I prefer to install plugins using Tim Pope's -[pathogen.vim](https://github.com/tpope/vim-pathogen). Installation using -pathogen is quite simple. - - cd ~/.vim/bundle - git clone git://github.com/digitaltoad/vim-jade.git - -If you do not want to use pathogen. You can always install vim-jade in the -normal manner by copying each directory to your ~/.vim directory. Make sure -not to overwrite any existing directory of the same name and instead copy only -the contents of the source directory to the directory of the same name in your -~/.vim directory. diff --git a/bundle/jade/ftdetect/jade.vim b/bundle/jade/ftdetect/jade.vim deleted file mode 100755 index c21dcff..0000000 --- a/bundle/jade/ftdetect/jade.vim +++ /dev/null @@ -1,2 +0,0 @@ -" Jade -autocmd BufNewFile,BufReadPost *.jade set filetype=jade diff --git a/bundle/jade/ftplugin/jade.vim b/bundle/jade/ftplugin/jade.vim deleted file mode 100755 index 577f554..0000000 --- a/bundle/jade/ftplugin/jade.vim +++ /dev/null @@ -1,57 +0,0 @@ -" Vim filetype plugin -" Language: Jade -" Maintainer: Joshua Borton -" Credits: Tim Pope - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif - -let s:save_cpo = &cpo -set cpo-=C - -setlocal iskeyword+=- - -" Define some defaults in case the included ftplugins don't set them. -let s:undo_ftplugin = "" -let s:browsefilter = "All Files (*.*)\t*.*\n" -let s:match_words = "" - -runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim -unlet! b:did_ftplugin - -" Override our defaults if these were set by an included ftplugin. -if exists("b:undo_ftplugin") - let s:undo_ftplugin = b:undo_ftplugin - unlet b:undo_ftplugin -endif -if exists("b:browsefilter") - let s:browsefilter = b:browsefilter - unlet b:browsefilter -endif -if exists("b:match_words") - let s:match_words = b:match_words - unlet b:match_words -endif - -" Change the browse dialog on Win32 to show mainly Haml-related files -if has("gui_win32") - let b:browsefilter="Jade Files (*.jade)\t*.jade\n" . s:browsefilter -endif - -" Load the combined list of match_words for matchit.vim -if exists("loaded_matchit") - let b:match_words = s:match_words -endif - -setlocal comments=://-,:// commentstring=//\ %s - -setlocal suffixesadd+=.jade - -let b:undo_ftplugin = "setl cms< com< " - \ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin - -let &cpo = s:save_cpo - -" vim:set sw=2: diff --git a/bundle/jade/indent/jade.vim b/bundle/jade/indent/jade.vim deleted file mode 100755 index 8cfa656..0000000 --- a/bundle/jade/indent/jade.vim +++ /dev/null @@ -1,70 +0,0 @@ -" Vim indent file -" Language: Jade -" Maintainer: Joshua Borton -" Credits: Tim Pope (vim-jade) -" Last Change: 2010 Sep 22 - -if exists("b:did_indent") - finish -endif - -unlet! b:did_indent -let b:did_indent = 1 - -setlocal autoindent -setlocal indentexpr=GetJadeIndent() -setlocal indentkeys=o,O,*,},],0),!^F - -" Only define the function once. -if exists("*GetJadeIndent") - finish -endif - -let s:attributes = '\%((.\{-\})\)' -let s:tag = '\([%.#][[:alnum:]_-]\+\|'.s:attributes.'\)*[<>]*' - -if !exists('g:jade_self_closing_tags') - let g:jade_self_closing_tags = 'meta|link|img|hr|br|input' -endif - -setlocal formatoptions+=r -setlocal comments+=n:\| - -function! GetJadeIndent() - let lnum = prevnonblank(v:lnum-1) - if lnum == 0 - return 0 - endif - let line = substitute(getline(lnum),'\s\+$','','') - let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','') - let lastcol = strlen(line) - let line = substitute(line,'^\s\+','','') - let indent = indent(lnum) - let cindent = indent(v:lnum) - let increase = indent + &sw - if indent == indent(lnum) - let indent = cindent <= indent ? -1 : increase - endif - - let group = synIDattr(synID(lnum,lastcol,1),'name') - - if line =~ '^!!!' - return indent - elseif line =~ '^/\%(\[[^]]*\]\)\=$' - return increase - elseif line =~ '^\%(if\|else\|unless\|for\|each\|block\|mixin\|append\|case\|when\)' - return increase - elseif line =~ '^'.s:tag.'[&!]\=[=~-].*,\s*$' - return increase - elseif line == '-#' - return increase - elseif line =~? '^\v%('.g:jade_self_closing_tags.')>' - return indent - elseif group =~? '\v^%(jadeAttributesDelimiter|jadeClass|jadeId|htmlTagName|htmlSpecialTagName|jadeFilter|jadeTagBlockChar)$' - return increase - else - return indent - endif -endfunction - -" vim:set sw=2: diff --git a/bundle/jade/syntax/jade.vim b/bundle/jade/syntax/jade.vim deleted file mode 100755 index 360c876..0000000 --- a/bundle/jade/syntax/jade.vim +++ /dev/null @@ -1,102 +0,0 @@ -" Vim syntax file -" Language: Jade -" Maintainer: Joshua Borton -" Credits: Tim Pope -" Filenames: *.jade - -if exists("b:current_syntax") - finish -endif - -if !exists("main_syntax") - let main_syntax = 'jade' -endif - -silent! syntax include @htmlCoffeescript syntax/coffee.vim -unlet! b:current_syntax -silent! syntax include @htmlStylus syntax/stylus.vim -unlet! b:current_syntax -silent! syntax include @htmlMarkdown syntax/markdown.vim -unlet! b:current_syntax - -syn case match - -syn region javascriptParenthesisBlock start="(" end=")" contains=@htmlJavascript contained keepend -syn cluster htmlJavascript add=javascriptParenthesisBlock - -syn region jadeJavascript matchgroup=jadeJavascriptOutputChar start="[!&]\==\|\~" skip=",\s*$" end="$" contained contains=@htmlJavascript keepend -syn region jadeJavascript matchgroup=jadeJavascriptChar start="-" skip=",\s*$" end="$" contained contains=@htmlJavascript keepend -syn cluster jadeTop contains=jadeBegin,jadeComment,jadeHtmlComment,jadeJavascript -syn match jadeBegin "^\s*\%([<>]\|&[^=~ ]\)\@!" nextgroup=jadeTag,jadeClassChar,jadeIdChar,jadePlainChar,jadeJavascript,jadeScriptConditional,jadeScriptStatement,jadePipedText -syn match jadeTag "+\?\w\+\%(:\w\+\)\=" contained contains=htmlTagName,htmlSpecialTagName nextgroup=@jadeComponent -syn cluster jadeComponent contains=jadeAttributes,jadeIdChar,jadeBlockExpansionChar,jadeClassChar,jadePlainChar,jadeJavascript,jadeTagBlockChar,jadeTagInlineText -syn match jadeComment '\s*\/\/.*$' -syn region jadeCommentBlock start="\z(\s*\)\/\/.*$" end="^\%(\z1\s\|\s*$\)\@!" keepend -syn region jadeHtmlConditionalComment start="" -syn region jadeAttributes matchgroup=jadeAttributesDelimiter start="(" end=")" contained contains=@htmlJavascript,jadeHtmlArg,htmlArg,htmlEvent,htmlCssDefinition nextgroup=@jadeComponent -syn match jadeClassChar "\." contained nextgroup=jadeClass -syn match jadeBlockExpansionChar ":\s\+" contained nextgroup=jadeTag -syn match jadeIdChar "#[[{]\@!" contained nextgroup=jadeId -syn match jadeClass "\%(\w\|-\)\+" contained nextgroup=@jadeComponent -syn match jadeId "\%(\w\|-\)\+" contained nextgroup=@jadeComponent -syn region jadeDocType start="^\s*\(!!!\|doctype\)" end="$" -" Unless I'm mistaken, syntax/html.vim requires -" that the = sign be present for these matches. -" This adds the matches back for jade. -syn keyword jadeHtmlArg contained href title - -syn match jadePlainChar "\\" contained -syn region jadeInterpolation matchgroup=jadeInterpolationDelimiter start="[#!]{" end="}" contains=@htmlJavascript -syn match jadeInterpolationEscape "\\\@[?!]\@!" -syn match jadeScriptStatement "^\s*\<\%(each\|for\|block\|prepend\|append\|mixin\|extends\|include\)\>[?!]\@!" -syn region jadeScriptLoopRegion start="^\s*\(for \)" end="$" contains=jadeScriptLoopKeywords -syn keyword jadeScriptLoopKeywords for in contained - -syn region jadeJavascript start="^\z(\s*\)script\%(:\w\+\)\=" end="^\%(\z1\s\|\s*$\)\@!" contains=@htmlJavascript,jadeJavascriptTag,jadeCoffeescriptFilter keepend - -syn region jadeCoffeescriptFilter matchgroup=jadeFilter start="^\z(\s*\):coffee-\?script\s*$" end="^\%(\z1\s\|\s*$\)\@!" contains=@htmlCoffeescript contained -syn region jadeJavascriptTag contained start="^\z(\s*\)script\%(:\w\+\)\=" end="$" contains=jadeBegin,jadeTag -syn region jadeCssBlock start="^\z(\s*\)style" nextgroup=@jadeComponent,jadeError end="^\%(\z1\s\|\s*$\)\@!" contains=@htmlCss keepend - -syn match jadeError "\$" contained - -hi def link jadePlainChar Special -hi def link jadeScriptConditional PreProc -hi def link jadeScriptLoopKeywords PreProc -hi def link jadeScriptStatement PreProc -hi def link jadeHtmlArg htmlArg -hi def link jadeAttributeString String -hi def link jadeAttributesDelimiter Identifier -hi def link jadeIdChar Special -hi def link jadeClassChar Special -hi def link jadeBlockExpansionChar Special -hi def link jadePipeChar Special -hi def link jadeTagBlockChar Special -hi def link jadeId Identifier -hi def link jadeClass Type -hi def link jadeInterpolationDelimiter Delimiter -hi def link jadeInlineDelimiter Delimiter -hi def link jadeFilter PreProc -hi def link jadeDocType PreProc -hi def link jadeComment Comment -hi def link jadeCommentBlock Comment -hi def link jadeHtmlConditionalComment jadeComment - -let b:current_syntax = "jade" - -if main_syntax == "jade" - unlet main_syntax -endif diff --git a/bundle/jsx/README.md b/bundle/jsx/README.md deleted file mode 100644 index 9362651..0000000 --- a/bundle/jsx/README.md +++ /dev/null @@ -1,56 +0,0 @@ -vim-jsx -======= - -Syntax highlighting and indenting for JSX. JSX is a JavaScript syntax -transformer which translates inline XML document fragments into JavaScript -objects. It was developed by Facebook alongside [React][1]. - -This bundle requires pangloss's [vim-javascript][2] syntax highlighting. - -Vim support for inline XML in JS is remarkably similar to the same for PHP, -which you can find [here][3]. - -Usage ------ - -By default, JSX syntax highlighting and indenting will be enabled only for -files with the `.jsx` extension. If you would like JSX in `.js` files, add - - let g:jsx_ext_required = 0 - -to your .vimrc or somewhere in your include path. If you wish to restrict JSX -to files with the pre-v0.12 `@jsx React.DOM` pragma, add - - let g:jsx_pragma_required = 1 - -to your .vimrc or somewhere in your include path. - -Installation ------------- - -### Pathogen - -The recommended installation method is via [Pathogen][4]. Then simply execute - - cd ~/.vim/bundle - git clone https://github.com/mxw/vim-jsx.git - -### Manual Installation - -If you have no `~/.vim/after` directory, you can download the tarball or zip -and copy the contents to `~/.vim`. - -If you have existing `~/.vim/after` files, copy the syntax and indent files -directly into their respective destinations. If you have existing after syntax -or indent files for Javascript, you'll probably want to do something like - - mkdir -p ~/.vim/after/syntax/javascript - cp path/to/vim-jsx/after/syntax/javascript.vim ~/.vim/after/syntax/javascript/javascript.vim - mkdir -p ~/.vim/after/indent/javascript - cp path/to/vim-jsx/after/indent/javascript.vim ~/.vim/after/indent/javascript/javascript.vim - - -[1]: http://facebook.github.io/react/ "React" -[2]: https://github.com/pangloss/vim-javascript "pangloss: vim-javascript" -[3]: https://github.com/mxw/vim-xhp "mxw: vim-xhp" -[4]: https://github.com/tpope/vim-pathogen "tpope: vim-pathogen" diff --git a/bundle/jsx/after/ftdetect/javascript.vim b/bundle/jsx/after/ftdetect/javascript.vim deleted file mode 100644 index 7cd1f9d..0000000 --- a/bundle/jsx/after/ftdetect/javascript.vim +++ /dev/null @@ -1,10 +0,0 @@ -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Vim ftdetect file -" -" Language: JSX (JavaScript) -" Maintainer: Max Wang -" -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -autocmd BufNewFile,BufRead *.jsx let b:jsx_ext_found = 1 -autocmd BufNewFile,BufRead *.jsx set filetype=javascript diff --git a/bundle/jsx/after/ftplugin/javascript.vim b/bundle/jsx/after/ftplugin/javascript.vim deleted file mode 100644 index 1a8da4d..0000000 --- a/bundle/jsx/after/ftplugin/javascript.vim +++ /dev/null @@ -1,15 +0,0 @@ -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Vim ftplugin file -" -" Language: JSX (JavaScript) -" Maintainer: Max Wang -" Depends: pangloss/vim-javascript -" -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -" modified from html.vim -if exists("loaded_matchit") - let b:match_ignorecase = 0 - let b:match_words = '(:),\[:\],{:},<:>,' . - \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>' -endif diff --git a/bundle/jsx/after/indent/javascript.vim b/bundle/jsx/after/indent/javascript.vim deleted file mode 100644 index d0b4d4e..0000000 --- a/bundle/jsx/after/indent/javascript.vim +++ /dev/null @@ -1,98 +0,0 @@ -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Vim indent file -" -" Language: JSX (JavaScript) -" Maintainer: Max Wang -" Depends: pangloss/vim-javascript -" -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -" Do nothing if we don't find the @jsx pragma (and we care). -exec 'source '.fnameescape(expand(':p:h:h').'/jsx-config.vim') -if g:jsx_pragma_required && !b:jsx_pragma_found | finish | endif - -" Do nothing if we don't have the .jsx extension (and we care). -if g:jsx_ext_required && !exists('b:jsx_ext_found') | finish | endif - -" Prologue; load in XML indentation. -if exists('b:did_indent') - let s:did_indent=b:did_indent - unlet b:did_indent -endif -exe 'runtime! indent/xml.vim' -if exists('s:did_indent') - let b:did_indent=s:did_indent -endif - -setlocal indentexpr=GetJsxIndent() - -" JS indentkeys -setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e -" XML indentkeys -setlocal indentkeys+=*,<>>,<<>,/ - -" Self-closing tag regex. -let s:sctag = '^\s*\/>\s*;\=' - -" Get all syntax types at the beginning of a given line. -fu! SynSOL(lnum) - return map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') -endfu - -" Get all syntax types at the end of a given line. -fu! SynEOL(lnum) - let lnum = prevnonblank(a:lnum) - let col = strlen(getline(lnum)) - return map(synstack(lnum, col), 'synIDattr(v:val, "name")') -endfu - -" Check if a syntax attribute is XMLish. -fu! SynAttrXMLish(synattr) - return a:synattr =~ "^xml" || a:synattr =~ "^jsx" -endfu - -" Check if a synstack is XMLish (i.e., has an XMLish last attribute). -fu! SynXMLish(syns) - return SynAttrXMLish(get(a:syns, -1)) -endfu - -" Check if a synstack has any XMLish attribute. -fu! SynXMLishAny(syns) - for synattr in a:syns - if SynAttrXMLish(synattr) - return 1 - endif - endfor - return 0 -endfu - -" Check if a synstack denotes the end of a JSX block. -fu! SynJSXBlockEnd(syns) - return get(a:syns, -1) == 'jsBraces' && SynAttrXMLish(get(a:syns, -2)) -endfu - -" Cleverly mix JS and XML indentation. -fu! GetJsxIndent() - let cursyn = SynSOL(v:lnum) - let prevsyn = SynEOL(v:lnum - 1) - - " Use XML indenting if the syntax at the end of the previous line was either - " JSX or was the closing brace of a jsBlock whose parent syntax was JSX. - if (SynXMLish(prevsyn) || SynJSXBlockEnd(prevsyn)) && SynXMLishAny(cursyn) - let ind = XmlIndentGet(v:lnum, 0) - - " Align '/>' with '<' for multiline self-closing tags. - if getline(v:lnum) =~? s:sctag - let ind = ind - &sw - endif - - " Then correct the indentation of any JSX following '/>'. - if getline(v:lnum - 1) =~? s:sctag - let ind = ind + &sw - endif - else - let ind = GetJavascriptIndent() - endif - - return ind -endfu diff --git a/bundle/jsx/after/jsx-config.vim b/bundle/jsx/after/jsx-config.vim deleted file mode 100644 index a1d4cbe..0000000 --- a/bundle/jsx/after/jsx-config.vim +++ /dev/null @@ -1,33 +0,0 @@ -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Vimscript file -" -" Set up a bunch of configuration variables. -" -" Also check (if desired) whether or not the @jsx pragma is correctly included -" in '%'. Set the result in b:jsx_pragma_found. -" -" Language: JSX (JavaScript) -" Maintainer: Max Wang -" -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -" Only check once. -if exists('b:jsx_pragma_found') - finish -endif - -" Whether the .jsx extension is required to enable JSX syntax/indent. -if !exists('g:jsx_ext_required') - let g:jsx_ext_required = 1 -endif - -" Whether the @jsx pragma is required to enable JSX syntax/indent. -if !exists('g:jsx_pragma_required') - let g:jsx_pragma_required = 0 -endif -if !g:jsx_pragma_required | finish | endif - -" Look for the @jsx pragma. It must be included in a docblock comment before -" anything else in the file (except whitespace). -let s:jsx_pragma_pattern = '\%^\_s*\/\*\*\%(\_.\%(\*\/\)\@!\)*@jsx\_.\{-}\*\/' -let b:jsx_pragma_found = search(s:jsx_pragma_pattern, 'npw') diff --git a/bundle/jsx/after/syntax/javascript.vim b/bundle/jsx/after/syntax/javascript.vim deleted file mode 100644 index 5bebc94..0000000 --- a/bundle/jsx/after/syntax/javascript.vim +++ /dev/null @@ -1,43 +0,0 @@ -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Vim syntax file -" -" Language: JSX (JavaScript) -" Maintainer: Max Wang -" Depends: pangloss/vim-javascript -" -" CREDITS: Inspired by Facebook. -" -""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -" Do nothing if we don't find the @jsx pragma (and we care). -exec 'source '.fnameescape(expand(':p:h:h').'/jsx-config.vim') -if g:jsx_pragma_required && !b:jsx_pragma_found | finish | endif - -" Do nothing if we don't have the .jsx extension (and we care). -if g:jsx_ext_required && !exists('b:jsx_ext_found') | finish | endif - -" Prologue; load in XML syntax. -if exists('b:current_syntax') - let s:current_syntax=b:current_syntax - unlet b:current_syntax -endif -syn include @XMLSyntax syntax/xml.vim -if exists('s:current_syntax') - let b:current_syntax=s:current_syntax -endif - -" Highlight JSX regions as XML; recursively match. -syn region jsxRegion contains=@XMLSyntax,jsxRegion,jsBlock,jsStringD,jsStringS - \ start=+<\@+ - \ end=++ - \ end=+/>+ - \ keepend - \ extend - -" JSX attributes should color as JS. Note the trivial end pattern; we let -" jsBlock take care of ending the region. -syn region xmlString contained start=+{+ end=++ contains=jsBlock - -" Add jsxRegion to the lowest-level JS syntax cluster. -syn cluster jsExpression add=jsxRegion diff --git a/bundle/less/.gitignore b/bundle/less/.gitignore deleted file mode 100644 index 1377554..0000000 --- a/bundle/less/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.swp diff --git a/bundle/less/README.md b/bundle/less/README.md deleted file mode 100644 index 697ad12..0000000 --- a/bundle/less/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# VIM-LESS - -This vim bundle adds syntax highlighting, indenting and autocompletion for the dynamic stylesheet language [LESS](http://lesscss.org). - -This bundle is compatible with [vim-css-color](https://github.com/skammer/vim-css-color), -[vim-css3-syntax](https://github.com/hail2u/vim-css3-syntax) and possibly other plugins that place code -in `after/syntax/css.vim` or `after/syntax/css/*.vim`. - -![vim-less with vim-css-color and vim-css3-syntax (colorscheme solarized)](https://github.com/lenniboy/vim-less/raw/master/screenshot.png) - - -## Installing and Using - -- Install [pathogen](http://www.vim.org/scripts/script.php?script_id=2332) into `~/.vim/autoload/` and add the - following line to your `~/.vimrc`: - - call pathogen#infect() - -- Make a clone of the `vim-less` repository: - - $ mkdir -p ~/.vim/bundle - $ cd ~/.vim/bundle - $ git clone https://github.com/groenewege/vim-less - -- OR use [vundle](https://github.com/gmarik/vundle), adding this line to your `~/.vimrc`: - - Bundle 'groenewege/vim-less' - -- OR use git submodules: - - $ git submodule add https://github.com/groenewege/vim-less.git bundle/vim-less - $ git submodule init - - -### Map -.less to .css , lessc is required. - - nnoremap ,m :w !lessc % > %:t:r.css - - -## Credits - -Inspiration from [vim-haml](https://github.com/tpope/vim-haml), -[scss-syntax.vim](https://github.com/cakebaker/scss-syntax.vim) and -[vim-less](https://github.com/lunaru/vim-less) - -## License ## - -MIT : [groenewege.mit-license.org](http://groenewege.mit-license.org/) diff --git a/bundle/less/ftdetect/less.vim b/bundle/less/ftdetect/less.vim deleted file mode 100644 index f1cb1d7..0000000 --- a/bundle/less/ftdetect/less.vim +++ /dev/null @@ -1 +0,0 @@ -autocmd BufNewFile,BufRead *.less setf less diff --git a/bundle/less/ftplugin/less.vim b/bundle/less/ftplugin/less.vim deleted file mode 100644 index b6eaf6a..0000000 --- a/bundle/less/ftplugin/less.vim +++ /dev/null @@ -1,25 +0,0 @@ -" Vim filetype plugin -" Language: LessCSS -" Author: Tim Pope -" Maintainer: Leonard Ehrenfried -" Last Change: 2011 Sep 30 - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif -let b:did_ftplugin = 1 - -let b:undo_ftplugin = "setl cms< def< inc< inex< ofu< sua<" - -setlocal iskeyword+=- -setlocal commentstring=//\ %s -setlocal define=^\\s*\\%(@mixin\\\|=\\) -setlocal includeexpr=substitute(v:fname,'\\%(.*/\\\|^\\)\\zs','_','') -setlocal omnifunc=csscomplete#CompleteCSS -setlocal suffixesadd=.less -setlocal comments=s1:/*,mb:*,ex:*/ - -let &l:include = '^\s*@import\s\+\%(url(http://github.com/)\=["'']\=' - -" vim:set sw=2: diff --git a/bundle/less/indent/less.vim b/bundle/less/indent/less.vim deleted file mode 100644 index fea8846..0000000 --- a/bundle/less/indent/less.vim +++ /dev/null @@ -1,11 +0,0 @@ -" Vim indent file -" Language: LessCSS -" Maintainer: Leonard Ehrenfried -" Last Change: 2011 Sep 26 - -if exists("b:did_indent") - finish -endif - -runtime! indent/css.vim - diff --git a/bundle/less/screenshot.png b/bundle/less/screenshot.png deleted file mode 100644 index ce25624a83a2a34c2c91a0df3eaff57a86d0e815..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52352 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 `{{_}}` - - `{{{` => `{{{_}}}` - - `{{!` => `{{!_}}` - - `{{>` => `{{>_}}` - - `{{<` => `{{<_}}` - - `{{#` produces - - ``` - {{# _}} - {{/}} - ``` - - `{{if` produces - - ``` - {{#if _}} - {{/if}} - ``` - - `{{ife` produces - - ``` - {{#if _}} - {{else}} - {{/if}} - ``` - -### Section movement mappings - -Following the vim convention of jumping from section to section, `[[` and `]]` -mappings are implemented for easier movement between mustache tags. - - - `]]` jumps to the first following tag - - `[[` jumps to the first previous tag - -Count with section movements is supported: - - - `2]]` jumps to the second next tag - -### Text objects - -Vim has a very powerful concept of "text objects". If you aren't using text objects, -you can get familiar with it on [this vim help -link](http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects). Learning -text objects really speeds up the vim workflow. - -In that spirit, this plugin defines 2 text objects: - - `ie` a mnemonic for `inside element`, selects all the text inside the - mustache tag. - For example, when used with `vie` it will visually select the - bold text in the following snippets: {{**some_variable**}}, - {{{**different_variable**}}}. - - `ae` a mnemonic for `around element`, selects the whole mustache tag, - including the curly braces. - Example, `vae` visually selects the bold text in the following - snippets: **{{some_variable}}** or **{{{another_variable}}}**. - -Here are other usage examples: - - `dae` - deletes the whole mustache tag, including the curly braces - - `die` - deletes **inside** the mustache tag, leaving only curly braces - - `yae` - "yanks" the whole mustache tag - with curly braces - - `cie` - deletes **inside** the mustache tag and goes in insert mode - -`ie` and `ae` text objects are enabled by default. To disable them, put the -following in your `.vimrc`: - - let g:mustache_operators = 0 - -## Maintainers - -* [Bruno Michel](http://github.com/nono) -* [Bruno Sutic](http://github.com/bruno-) -* [Juvenn Woo](http://github.com/juvenn) - -This is combined work from -[juvenn/mustache.vim](http://github.com/juvenn/mustache.vim) and -[nono/vim-handlebars](http://github.com/nono/vim-handlebars). - ----- - -Thanks [@5long](http://github.com/5long) for adding matchit support. - -You're encouraged to propose ideas or have discussions via github -issues. - -[mustache]: http://mustache.github.io -[handlebars]: http://handlebarsjs.com -[pathogen]: https://github.com/tpope/vim-pathogen diff --git a/bundle/mustache-handlebars/example.mustache b/bundle/mustache-handlebars/example.mustache deleted file mode 100644 index 1390231..0000000 --- a/bundle/mustache-handlebars/example.mustache +++ /dev/null @@ -1,66 +0,0 @@ - - - - - {{title}} - - {{!}} - - -
-

Mustache Showdown

- - Basic mustache {{hello}} - {{ hello}}, {{hello }} and {{ hello }} are OK - - {{d d d}} - - {{Everything will be highlighted here}} - - Mustaches highlighted in - attribute value - - {{#repo}} - This is a mustache [enumerable] section -
  • {{ name }}
  • - {{/repo}} - - Inverted sections are supported too - {{^repo}} - No repos :( - {{/repo}} - - You can {{{yield}}} here - - {{! <> this is a comment TODO:}} - - Another {{!-- comment --}}, this one is a block comment. - - {{!-- TODO: some remark -
    - Multiline {{comments}} with - {{variables}} -
    --}} - - This is a partial {{> partial1 }} - Yet another partial {{< partial2 }}, for ctemplate - - {{=<% %>=}}Sorry, customized delimiter not handled yet<%={{}}=%> - - {{#if some_helper}} - And here is an example of handlebars if... - {{else}} - ... with optional else added. Try matchit `%` command over if/else/if. - {{/if}} - - Thanks goes to {{@defunkt}} - Feedback/blames go to {{@juvenn}} - {{Frustrations}} go to /dev/null - - Multiline {{comments}} with - {{variables}} -
    - - - - diff --git a/bundle/mustache-handlebars/ftdetect/mustache.vim b/bundle/mustache-handlebars/ftdetect/mustache.vim deleted file mode 100644 index 8a6981e..0000000 --- a/bundle/mustache-handlebars/ftdetect/mustache.vim +++ /dev/null @@ -1,4 +0,0 @@ -if has("autocmd") - au BufNewFile,BufRead *.mustache,*.hogan,*.hulk,*.hjs set filetype=html.mustache syntax=mustache | runtime! ftplugin/mustache.vim ftplugin/mustache*.vim ftplugin/mustache/*.vim - au BufNewFile,BufRead *.handlebars,*.hbs set filetype=html.handlebars syntax=mustache | runtime! ftplugin/mustache.vim ftplugin/mustache*.vim ftplugin/mustache/*.vim -endif diff --git a/bundle/mustache-handlebars/ftplugin/mustache.vim b/bundle/mustache-handlebars/ftplugin/mustache.vim deleted file mode 100644 index 61b5896..0000000 --- a/bundle/mustache-handlebars/ftplugin/mustache.vim +++ /dev/null @@ -1,120 +0,0 @@ -if exists('g:loaded_mustache_handlebars') && g:loaded_mustache_handlebars - finish -endif -let g:loaded_mustache_handlebars = 1 - -let s:cpo_save = &cpo -set cpo&vim - -" Matchit support for Mustache & Handlebars -" extending HTML matchit groups -if exists("loaded_matchit") && exists("b:match_words") - let b:match_words = b:match_words - \ . ',{:},[:],(:),' - \ . '\%({{\)\@<=#\s*\%(if\|unless\)\s*.\{-}}}' - \ . ':' - \ . '\%({{\)\@<=\s*else\s*}}' - \ . ':' - \ . '\%({{\)\@<=/\s*\%(if\|unless\)\s*}},' - \ . '\%({{\)\@<=[#^]\s*\([-0-9a-zA-Z_?!/.]\+\).\{-}}}' - \ . ':' - \ . '\%({{\)\@<=/\s*\1\s*}}' -endif - -if exists("g:mustache_abbreviations") - inoremap {{{ {{{}}} - inoremap {{ {{}} - inoremap {{! {{!}} - inoremap {{< {{<}} - inoremap {{> {{>}} - inoremap {{# {{#}}{{/}} - inoremap {{if {{#if }}{{/if}} - inoremap {{ife {{#if }}{{else}}{{/if}} -endif - - -" Section movement -" Adapted from vim-ruby - many thanks to the maintainers of that plugin - -function! s:sectionmovement(pattern,flags,mode,count) - norm! m' - if a:mode ==# 'v' - norm! gv - endif - let i = 0 - while i < a:count - let i = i + 1 - " saving current position - let line = line('.') - let col = col('.') - let pos = search(a:pattern,'W'.a:flags) - " if there's no more matches, return to last position - if pos == 0 - call cursor(line,col) - return - endif - endwhile -endfunction - -nnoremap [[ :call sectionmovement('{{','b','n',v:count1) -nnoremap ]] :call sectionmovement('{{','' ,'n',v:count1) -xnoremap [[ :call sectionmovement('{{','b','v',v:count1) -xnoremap ]] :call sectionmovement('{{','' ,'v',v:count1) - - -" Operator pending mappings - -" Operators are available by default. Set `let g:mustache_operators = 0` in -" your .vimrc to disable them. -if ! exists("g:mustache_operators") - let g:mustache_operators = 1 -endif - -if exists("g:mustache_operators") && g:mustache_operators - onoremap ie :call wrap_inside() - onoremap ae :call wrap_around() - xnoremap ie :call wrap_inside() - xnoremap ae :call wrap_around() -endif - -function! s:wrap_around() - " If the cursor is at the end of the tag element, move back - " so that the end tag can be detected. - while getline('.')[col('.')-1] ==# '}' - execute 'norm h' - endwhile - - " Moves to the end of the closing tag - let pos = search('}}','We') - if pos != 0 - if getline('.')[col('.')] ==# '}' - " Ending tag contains 3 closing brackets '}}}', - " move to the last bracket. - execute 'norm l' - endif - - " select the whole tag - execute 'norm v%' - endif -endfunction - -function! s:wrap_inside() - " If the cursor is at the end of the tag element, move back - " so that the end tag can be detected. - while getline('.')[col('.')-1] ==# '}' - execute 'norm h' - endwhile - - " Moves to the end of the closing tag - let pos = search('}}','W') - if pos != 0 - " select only inside the tag - execute 'norm v%loho' - endif -endfunction - - -let &cpo = s:cpo_save -unlet s:cpo_save - -" vim: nofoldenable diff --git a/bundle/mustache-handlebars/indent/handlebars.vim b/bundle/mustache-handlebars/indent/handlebars.vim deleted file mode 100644 index 74b0c45..0000000 --- a/bundle/mustache-handlebars/indent/handlebars.vim +++ /dev/null @@ -1,100 +0,0 @@ -" Mustache & Handlebars syntax -" Language: Mustache, Handlebars -" Maintainer: Juvenn Woo -" Screenshot: http://imgur.com/6F408 -" Version: 2 -" Last Change: Oct 10th 2015 -" Remarks: based on eruby indent plugin by tpope -" References: -" [Mustache](http://github.com/defunkt/mustache) -" [Handlebars](https://github.com/wycats/handlebars.js) -" [ctemplate](http://code.google.com/p/google-ctemplate/) -" [ctemplate doc](http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html) -" [et](http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html) - -if exists("b:did_indent_hbs") - finish -endif - -unlet! b:did_indent -setlocal indentexpr= - -runtime! indent/html.vim -unlet! b:did_indent - -" Force HTML indent to not keep state. -let b:html_indent_usestate = 0 - -if &l:indentexpr == '' - if &l:cindent - let &l:indentexpr = 'cindent(v:lnum)' - else - let &l:indentexpr = 'indent(prevnonblank(v:lnum-1))' - endif -endif -let b:handlebars_subtype_indentexpr = &l:indentexpr - -let b:did_indent = 1 -let b:did_indent_hbs = 1 - -setlocal indentexpr=GetHandlebarsIndent() -setlocal indentkeys=o,O,*,<>>,{,},0),0],o,O,!^F,=end,=else,=elsif,=rescue,=ensure,=when - -" Only define the function once. -if exists("*GetHandlebarsIndent") - finish -endif - -function! GetHandlebarsIndent(...) - " The value of a single shift-width - if exists('*shiftwidth') - let sw = shiftwidth() - else - let sw = &sw - endif - - if a:0 && a:1 == '.' - let v:lnum = line('.') - elseif a:0 && a:1 =~ '^\d' - let v:lnum = a:1 - endif - let vcol = col('.') - call cursor(v:lnum,1) - call cursor(v:lnum,vcol) - exe "let ind = ".b:handlebars_subtype_indentexpr - - " Workaround for Andy Wokula's HTML indent. This should be removed after - " some time, since the newest version is fixed in a different way. - if b:handlebars_subtype_indentexpr =~# '^HtmlIndent(' - \ && exists('b:indent') - \ && type(b:indent) == type({}) - \ && has_key(b:indent, 'lnum') - " Force HTML indent to not keep state - let b:indent.lnum = -1 - endif - let lnum = prevnonblank(v:lnum-1) - let line = getline(lnum) - let cline = getline(v:lnum) - - " all indent rules only apply if the block opening/closing - " tag is on a separate line - - " indent after block {{#block - if line =~# '\v\s*\{\{\#.*\s*' - let ind = ind + sw - endif - " unindent after block close {{/block}} - if cline =~# '\v^\s*\{\{\/\S*\}\}\s*' - let ind = ind - sw - endif - " unindent {{else}} - if cline =~# '\v^\s*\{\{else.*\}\}\s*$' - let ind = ind - sw - endif - " indent again after {{else}} - if line =~# '\v^\s*\{\{else.*\}\}\s*$' - let ind = ind + sw - endif - - return ind -endfunction diff --git a/bundle/mustache-handlebars/syntax/mustache.vim b/bundle/mustache-handlebars/syntax/mustache.vim deleted file mode 100644 index ec7d4fe..0000000 --- a/bundle/mustache-handlebars/syntax/mustache.vim +++ /dev/null @@ -1,89 +0,0 @@ -" Mustache & Handlebars syntax -" Language: Mustache, Handlebars -" Maintainer: Juvenn Woo -" Screenshot: http://imgur.com/6F408 -" Version: 2 -" Last Change: Oct 26th 2013 -" Remark: -" It lexically hilights embedded mustaches (exclusively) in html file. -" While it was written for Ruby-based Mustache template system, it should -" work for Google's C-based *ctemplate* as well as Erlang-based *et*. All -" of them are, AFAIK, based on the idea of ctemplate. -" References: -" [Mustache](http://github.com/defunkt/mustache) -" [Handlebars](https://github.com/wycats/handlebars.js) -" [ctemplate](http://code.google.com/p/google-ctemplate/) -" [ctemplate doc](http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html) -" [et](http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html) -" TODO: Feedback is welcomed. - - -" Read the HTML syntax to start with -if version < 600 - so :p:h/html.vim -else - runtime! syntax/html.vim - unlet b:current_syntax -endif - -if version < 600 - syntax clear -elseif exists("b:current_syntax") - finish -endif - -" Standard HiLink will not work with included syntax files -if version < 508 - command! -nargs=+ HtmlHiLink hi link -else - command! -nargs=+ HtmlHiLink hi def link -endif - -syntax match mustacheError '}}}\?' -syntax match mustacheInsideError '{{[{$#<>=!\/]\?' -syntax region mustacheInside start=/{{/ end=/}}}\?/ keepend containedin=TOP,@htmlMustacheContainer -syntax match mustacheOperators '=\|\.\|/' contained containedin=mustacheInside,@htmlMustacheContainer -syntax region mustacheSection start='{{[$#^/]'lc=2 end=/}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer -syntax region mustachePartial start=/{{[<>]/lc=2 end=/}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer -syntax region mustacheMarkerSet start=/{{=/lc=2 end=/=}}/me=e-2 contained containedin=mustacheInside,@htmlMustacheContainer -syntax match mustacheHandlebars '{{\|}}' contained containedin=mustacheInside,@htmlMustacheContainer -syntax match mustacheUnescape '{{{\|}}}' contained containedin=mustacheInside,@htmlMustacheContainer -syntax match mustacheConditionals '\([/#]\(if\|unless\)\|else\)' contained containedin=mustacheInside -syntax match mustacheHelpers '[/#]\(with\|each\)' contained containedin=mustacheSection -syntax region mustacheComment start=/{{!/rs=s+2 skip=/{{.\{-}}}/ end=/}}/re=e-2 contains=Todo contained containedin=mustacheInside,@htmlMustacheContainer -syntax region mustacheBlockComment start=/{{!--/rs=s+2 skip=/{{.\{-}}}/ end=/--}}/re=e-2 contains=Todo contained extend containedin=mustacheInside,@htmlMustacheContainer -syntax region mustacheQString start=/'/ skip=/\\'/ end=/'/ contained containedin=mustacheInside -syntax region mustacheDQString start=/"/ skip=/\\"/ end=/"/ contained containedin=mustacheInside - -" Clustering -syntax cluster htmlMustacheContainer add=htmlHead,htmlTitle,htmlString,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,htmlLink,htmlBold,htmlUnderline,htmlItalic,htmlValue - - -" Hilighting -" mustacheInside hilighted as Number, which is rarely used in html -" you might like change it to Function or Identifier -HtmlHiLink mustacheVariable Number -HtmlHiLink mustacheVariableUnescape Number -HtmlHiLink mustachePartial Number -HtmlHiLink mustacheSection Number -HtmlHiLink mustacheMarkerSet Number - -HtmlHiLink mustacheComment Comment -HtmlHiLink mustacheBlockComment Comment -HtmlHiLink mustacheError Error -HtmlHiLink mustacheInsideError Error - -HtmlHiLink mustacheHandlebars Special -HtmlHiLink mustacheUnescape Identifier -HtmlHiLink mustacheOperators Operator -HtmlHiLink mustacheConditionals Conditional -HtmlHiLink mustacheHelpers Repeat -HtmlHiLink mustacheQString String -HtmlHiLink mustacheDQString String - -syn region mustacheScriptTemplate start=++me=s-1 keepend -\ contains=mustacheInside,@htmlMustacheContainer,htmlTag,htmlEndTag,htmlTagName,htmlSpecialChar - -let b:current_syntax = "mustache" -delcommand HtmlHiLink diff --git a/bundle/puppet/README.md b/bundle/puppet/README.md deleted file mode 100755 index bec8ffc..0000000 --- a/bundle/puppet/README.md +++ /dev/null @@ -1,38 +0,0 @@ -vim-puppet -========== - -Make vim more Puppet friendly! - -Provides --------- - - * Formatting based on the latest Puppetlabs Style Guide - * Syntax highlighting - * Automatic => alignment (when the [tabular](https://github.com/godlygeek/tabular) plugin is also installed) - * If you don't like that, add `let g:puppet_align_hashes = 0` to your vimrc. - * Doesn't require a bloated JRE - * Doesn't take minutes to open - -Additional useful plugins -------------------------- - - * [syntastic](https://github.com/scrooloose/syntastic) plugin for automatic - syntax checking while in vim. - * [vim-snippets](https://github.com/honza/vim-snippets) is a library of - snippets for multiple languages, including Puppet. Works with both - [snipmate](https://github.com/garbas/vim-snipmate) and - [ultisnips](https://github.com/SirVer/ultisnips). - -Installation ------------- - -If you're using [pathogen](https://github.com/tpope/vim-pathogen) to manage your vim modules (and if you're not, why -aren't you), you can simply add this as a submodule in your `~/.vim/bundle/` -directory. - -My entire home directory is a git repository, so for me it's simply a case of - - $ git submodule add -f git://github.com/rodjek/vim-puppet.git .vim/bundle/puppet - -If you're not using pathogen, you can just manually place the files in the -appropriate places under `~/.vim/` diff --git a/bundle/puppet/after/ftplugin/puppet.vim b/bundle/puppet/after/ftplugin/puppet.vim deleted file mode 100755 index f976a45..0000000 --- a/bundle/puppet/after/ftplugin/puppet.vim +++ /dev/null @@ -1,16 +0,0 @@ -if !exists('g:puppet_align_hashes') - let g:puppet_align_hashes = 1 -endif - -if g:puppet_align_hashes && exists(':Tabularize') - inoremap > >:call puppetalign()a - function! s:puppetalign() - let p = '^\s*\w+\s*[=+]>.*$' - let column = strlen(substitute(getline('.')[0:col('.')],'\([^=]\|=[^>]\)','','g')) - let position = strlen(matchstr(getline('.')[0:col('.')],'.*=>\s*\zs.*')) - Tabularize /=>/l1 - normal! 0 - echo repeat('\([^=]\|=[^>]\)*=>',column).'\s\{-\}'.repeat('.',position) - call search(repeat('\([^=]\|=[^>]\)*=>',column).'\s\{-\}'.repeat('.',position),'ce',line('.')) - endfunction -endif diff --git a/bundle/puppet/ftdetect/puppet.vim b/bundle/puppet/ftdetect/puppet.vim deleted file mode 100755 index dc87505..0000000 --- a/bundle/puppet/ftdetect/puppet.vim +++ /dev/null @@ -1,2 +0,0 @@ -au! BufRead,BufNewFile *.pp setfiletype puppet -au! BufRead,BufNewFile Puppetfile setfiletype ruby diff --git a/bundle/puppet/ftplugin/puppet.vim b/bundle/puppet/ftplugin/puppet.vim deleted file mode 100755 index 175ac12..0000000 --- a/bundle/puppet/ftplugin/puppet.vim +++ /dev/null @@ -1,6 +0,0 @@ -setl ts=2 -setl sts=2 -setl sw=2 -setl et -setl keywordprg=puppet\ describe\ --providers -setl iskeyword=-,:,@,48-57,_,192-255 diff --git a/bundle/puppet/indent/puppet.vim b/bundle/puppet/indent/puppet.vim deleted file mode 100755 index cf49de8..0000000 --- a/bundle/puppet/indent/puppet.vim +++ /dev/null @@ -1,94 +0,0 @@ -" Vim indent file -" Language: Puppet -" Maintainer: Todd Zullinger -" Last Change: 2009 Aug 19 -" vim: set sw=4 sts=4: - -if exists("b:did_indent") - finish -endif -let b:did_indent = 1 - -setlocal autoindent smartindent -setlocal indentexpr=GetPuppetIndent() -setlocal indentkeys+=0],0) - -if exists("*GetPuppetIndent") - finish -endif - -" Check if a line is part of an include 'block', e.g.: -" include foo, -" bar, -" baz -function! s:PartOfInclude(lnum) - let lnum = a:lnum - while lnum - let lnum = lnum - 1 - let line = getline(lnum) - if line !~ ',$' - break - endif - if line =~ '^\s*include\s\+[^,]\+,$' - return 1 - endif - endwhile - return 0 -endfunction - -function! s:OpenBrace(lnum) - call cursor(a:lnum, 1) - return searchpair('{\|\[\|(', '', '}\|\]\|)', 'nbW') -endfunction - -function! GetPuppetIndent() - let pnum = prevnonblank(v:lnum - 1) - if pnum == 0 - return 0 - endif - - let line = getline(v:lnum) - let pline = getline(pnum) - let ind = indent(pnum) - - if pline =~ '^\s*#' - return ind - endif - - if pline =~ '\({\|\[\|(\|:\)$' - let ind += &sw - elseif pline =~ ';$' && pline !~ '[^:]\+:.*[=+]>.*' - let ind -= &sw - elseif pline =~ '^\s*include\s\+.*,$' - let ind += &sw - endif - - if pline !~ ',$' && s:PartOfInclude(pnum) - let ind -= &sw - endif - - " Match } }, }; ] ]: ], ]; ) - if line =~ '^\s*\(}\(,\|;\)\?$\|]:\|],\|}]\|];\?$\|)\)' - let ind = indent(s:OpenBrace(v:lnum)) - endif - - " Don't actually shift over for } else { - if line =~ '^\s*}\s*els\(e\|if\).*{\s*$' - let ind -= &sw - endif - - " Don't indent resources that are one after another with a ->(ordering arrow) - " file {'somefile': - " ... - " } -> - " - " package { 'mycoolpackage': - " ... - " } - if line =~ '->$' - let ind -= &sw - endif - - - return ind -endfunction diff --git a/bundle/puppet/syntax/puppet.vim b/bundle/puppet/syntax/puppet.vim deleted file mode 100755 index a979aca..0000000 --- a/bundle/puppet/syntax/puppet.vim +++ /dev/null @@ -1,166 +0,0 @@ -" puppet syntax file -" Filename: puppet.vim -" Language: puppet configuration file -" Maintainer: Luke Kanies -" URL: -" Last Change: -" Version: -" - -" Copied from the cfengine, ruby, and perl syntax files -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") - finish -endif - -" match class/definition/node declarations -syn region puppetDefine start="^\s*\(class\|define\|node\)\s" end="{" contains=puppetDefType,puppetDefName,puppetDefArguments,puppetNodeRe,@NoSpell -syn keyword puppetDefType class define node inherits contained -syn region puppetDefArguments start="(" end=")" contained contains=puppetArgument,puppetString,puppetComment,puppetMultilineComment -syn match puppetArgument "\w\+" contained -syn match puppetArgument "\$\w\+" contained -syn match puppetArgument "'[^']+'" contained -syn match puppetArgument '"[^"]+"' contained -syn match puppetDefName "\w\+" contained -syn match puppetNodeRe "/.*/" contained - -" match 'foo' in 'class foo { ...' -" match 'foo::bar' in 'class foo::bar { ...' -" match 'Foo::Bar' in 'Foo::Bar["..."] -"FIXME: "Foo-bar" doesn't get highlighted as expected, although "foo-bar" does. -syn match puppetInstance "[A-Za-z0-9_-]\+\(::[A-Za-z0-9_-]\+\)*\s*{" contains=puppetTypeName,puppetTypeDefault,@NoSpell -syn match puppetInstance "[A-Z][a-z_-]\+\(::[A-Z][a-z_-]\+\)*\s*[[{]" contains=puppetTypeName,puppetTypeDefault,@NoSpell -syn match puppetInstance "[A-Z][a-z_-]\+\(::[A-Z][a-z_-]\+\)*\s*<\?<|" contains=puppetTypeName,puppetTypeDefault,@NoSpell -syn match puppetTypeName "[a-z]\w*" contained -syn match puppetTypeDefault "[A-Z]\w*" contained - -syn match puppetParam "\w\+\s*\(=\|+\)>" contains=puppetTypeRArrow,puppetParamName -syn match puppetParamRArrow "\(=\|+\)>" contained -syn match puppetParamName "\w\+" contained contains=@NoSpell -syn match puppetVariable "$\(\(\(::\)\?\w\+\)\+\|{\(\(::\)\?\w\+\)\+}\)" -syn match puppetParen "(" -syn match puppetParen ")" -syn match puppetBrace "{" -syn match puppetBrace "}" -syn match puppetBrack "\[" -syn match puppetBrack "\]" -syn match puppetBrack "<|" -syn match puppetBrack "|>" - -" match 'present' in 'ensure => present' -" match '2755' in 'mode => 2755' -" don't match 'bar' in 'foo => bar' -syn match puppetParam "\w\+\s*[=+]>\s*[a-z0-9]\+" contains=puppetParamString,puppetParamName -syn match puppetParamString "[=+]>\s*\w\+" contains=puppetParamKeyword,puppetParamSpecial,puppetParamDigits contained -syn keyword puppetParamKeyword present absent purged latest installed running stopped mounted unmounted role configured file directory link contained -syn keyword puppetParamSpecial true false undef contained -syn match puppetParamDigits "[0-9]\+" - -" match 'template' in 'content => template("...")' -syn match puppetParam "\w\+\s*[=+]>\s*\w\+\s*(" contains=puppetFunction,puppetParamName -" statements -syn region puppetFunction start="^\s*\(alert\|crit\|debug\|emerg\|err\|fail\|include\|info\|notice\|realize\|require\|search\|tag\|warning\)\s*(" end=")" contained contains=puppetString -" rvalues -syn region puppetFunction start="^\s*\(defined\|file\|fqdn_rand\|generate\|inline_template\|regsubst\|sha1\|shellquote\|split\|sprintf\|tagged\|template\|versioncmp\)\s*(" end=")" contained contains=puppetString - -syn match puppetVariable "$[a-zA-Z0-9_:]\+" contains=@NoSpell -syn match puppetVariable "${[a-zA-Z0-9_:]\+}" contains=@NoSpell - -" match anything between simple/double quotes. -" don't match variables if preceded by a backslash. -syn region puppetString start=+'+ skip=+\\\\\|\\'+ end=+'+ -syn region puppetString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=puppetVariable,puppetNotVariable -syn match puppetNotVariable "\\$\w\+" contained -syn match puppetNotVariable "\\${\w\+}" contained - -syn keyword puppetKeyword import inherits include require contains -syn keyword puppetControl case default if else elsif -syn keyword puppetSpecial true false undef - -syn match puppetClass "[A-Za-z0-9_-]\+\(::[A-Za-z0-9_-]\+\)\+" contains=@NoSpell - -" Match the Regular Expression type -" XXX: Puppet does not currently support a few features available in the -" full Ruby Regexp class, namely, interpolation, lookbehind and named -" sub-expressions. Matches for these features are included in the -" commented-out versions of puppetRegexParen and puppetRegexSubName, -" plus the supporting groups puppetRegexAngBrack and puppetRegexTick. -syn region puppetRegex start="/" skip="\\/" end="/" contains=puppetRegexParen,puppetRegexBrace,puppetRegexOrpuppetRegexBrack,puppetRegexComment -syn match puppetRegexParen "(\(?\([imx]\{0,4}:\|[=!]\)\)\?" contains=puppetRegexSpecChar,puppetRegexSubName contained -"syn match puppetRegexParen "(\(?\([imxo]\{0,4}:\|['<][[:alnum:]]\+[>']\|" contained -"syn match puppetRegexTick +'+ contained -syn match puppetRegexOr "|" contained -"syn match puppetRegexSubName "['<][[:alnum:]]\+[>']" contains=puppetRegexAngBrack,puppetRegexTick contained -syn match puppetRegexSpecialChar "[?:imx]\|\(= 508 || !exists("did_puppet_syn_inits") - if version < 508 - let did_puppet_syn_inits = 1 - command -nargs=+ HiLink hi link - else - command -nargs=+ HiLink hi def link - endif - - HiLink puppetVariable Identifier - HiLink puppetType Identifier - HiLink puppetKeyword Keyword - HiLink puppetComment Comment - HiLink puppetMultilineComment Comment - HiLink puppetString String - HiLink puppetRegex Constant - HiLink puppetRegexParen Delimiter - HiLink puppetRegexBrace Delimiter - HiLink puppetRegexBrack Delimiter - HiLink puppetRegexAngBrack Delimiter - HiLink puppetRegexTick Delimiter - HiLink puppetRegexOr Delimiter - HiLink puppetRegexSubName Identifier - HiLink puppetRegexSpecChar SpecialChar - HiLink puppetRegexComment Comment - HiLink puppetParamKeyword Keyword - HiLink puppetParamDigits String - HiLink puppetNotVariable String - HiLink puppetParamSpecial Boolean - HiLink puppetSpecial Special - HiLink puppetTodo Todo - HiLink puppetBrack Delimiter - HiLink puppetTypeBrack Delimiter - HiLink puppetBrace Delimiter - HiLink puppetTypeBrace Delimiter - HiLink puppetParen Delimiter - HiLink puppetDelimiter Delimiter - HiLink puppetControl Statement - HiLink puppetDefType Define - HiLink puppetDefName Type - HiLink puppetNodeRe Type - HiLink puppetTypeName Statement - HiLink puppetTypeDefault Type - HiLink puppetParamName Identifier - HiLink puppetArgument Identifier - HiLink puppetFunction Function - HiLink puppetClass Include - - delcommand HiLink -endif - -let b:current_syntax = "puppet" diff --git a/bundle/scala/.gitignore b/bundle/scala/.gitignore deleted file mode 100644 index 01716d2..0000000 --- a/bundle/scala/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Ignore Vim tag files -tags - -# Ignore Vim swap files -.*.swp -.*.swo diff --git a/bundle/scala/.travis.yml b/bundle/scala/.travis.yml deleted file mode 100644 index c1ac6c5..0000000 --- a/bundle/scala/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: ruby -rvm: - - 1.9.3 -before_install: sudo apt-get install vim-gtk -before_script: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" -notifications: - email: - on_success: never - on_failure: change diff --git a/bundle/scala/Gemfile b/bundle/scala/Gemfile deleted file mode 100644 index 414fd03..0000000 --- a/bundle/scala/Gemfile +++ /dev/null @@ -1,5 +0,0 @@ -source 'https://rubygems.org/' -gem 'vimrunner', '0.3.0' -gem 'rake', '10.0.4' -gem 'rspec', '~> 2.13.0' - diff --git a/bundle/scala/Gemfile.lock b/bundle/scala/Gemfile.lock deleted file mode 100644 index ea5528e..0000000 --- a/bundle/scala/Gemfile.lock +++ /dev/null @@ -1,20 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - diff-lcs (1.1.3) - rake (0.9.2.2) - rspec (2.9.0) - rspec-core (~> 2.9.0) - rspec-expectations (~> 2.9.0) - rspec-mocks (~> 2.9.0) - rspec-core (2.9.0) - rspec-expectations (2.9.1) - diff-lcs (~> 1.1.3) - rspec-mocks (2.9.0) - -PLATFORMS - ruby - -DEPENDENCIES - rake - rspec diff --git a/bundle/scala/LICENSE.TXT b/bundle/scala/LICENSE.TXT deleted file mode 100644 index 66b0c46..0000000 --- a/bundle/scala/LICENSE.TXT +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright {yyyy} {name of copyright owner} - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/bundle/scala/README.md b/bundle/scala/README.md deleted file mode 100644 index c786a1c..0000000 --- a/bundle/scala/README.md +++ /dev/null @@ -1,36 +0,0 @@ -vim-scala [![Build Status](https://secure.travis-ci.org/lenniboy/vim-scala.png)](http://travis-ci.org/lenniboy/vim-scala) -========== - -This is a "bundle" for Vim that builds off of the initial Scala plugin modules -by Stefan Matthias Aust and adds some more "stuff" that I find useful, including -all of my notes and customizations. - -##Installation - -You really should be using Tim Pope's [Pathogen](https://github.com/tpope/vim-pathogen) module for Vim (http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen) if you're going to clone this repository because, well... you should. - -###Vundle -Alternatively, you can use [Vundle](https://github.com/gmarik/vundle) to -manage your plugins. - -If you have Vundle installed, simply add the following to your .vimrc: - -```vim -Bundle 'derekwyatt/vim-scala' -``` - -and then run - -```vim -:BundleInstall -``` - -to install it. - -##Sorting of import statements - :SortScalaImports - -There are different modes for import sorting available. For details, please -consult the vimdoc help with - - :help :SortScalaImports diff --git a/bundle/scala/Rakefile b/bundle/scala/Rakefile deleted file mode 100644 index 7c84562..0000000 --- a/bundle/scala/Rakefile +++ /dev/null @@ -1,6 +0,0 @@ -require 'rspec/core/rake_task' - -RSpec::Core::RakeTask.new - -task :test => :spec -task :default => :spec diff --git a/bundle/scala/after/plugin/help.vim b/bundle/scala/after/plugin/help.vim deleted file mode 100644 index 785160a..0000000 --- a/bundle/scala/after/plugin/help.vim +++ /dev/null @@ -1,50 +0,0 @@ - -function! FixTOCLine(beginning, colonCol) - let l = strlen(a:beginning) - let c = 0 - let dots = "" - while c < (a:colonCol - l) - let dots = dots . "." - let c += 1 - endwhile - return (a:beginning . dots . ":") -endfunction - -function! BuildTOC() - let lnum = getpos(".")[1] - call append(lnum - 1, "<<<") - call append(lnum, ">>>") - :g/^\d\+\./co/>>>/- - :g/^<<>>/s/ {{{\d\s*// - :g/^<<>>/s/\*/|/g - :g/^<<>>/s/^\ze\d\.\d\+\./ / - :g/^<<>>/s/^\ze\d\d\.\d\+\./ / - :g/^<<>>/s/^\ze\d\.\d\+/ / - :g/^<<>>/s/^\ze\d\d\.\d\+/ / - :g/^<<>>/s/^\ze\d\./ / - :g/^<<>>/s/^\ze\d\d\./ / - :g/^\s\+0\. Content/d - :g/<<>>/-s/^\(.\{-}\)\(\s\+\)\ze |/\=FixTOCLine(submatch(1), 45)/ - :g/<<>>/d -endfunction - -command! BuildNewTableOfContents silent! call BuildTOC() - -function! JustifyCurrentLine() - let cline = getline('.') - let matches = matchlist(cline, '^\(.*\)\s\+\(\*.*\)$') - let st = matches[1] - let fin = matches[2] - let spcnum = 78 - strlen(st) - strlen(fin) - let c = 0 - let spcs = "" - while c < spcnum - let spcs = spcs . " " - let c = c + 1 - endwhile - let newline = st . spcs . fin - :norm dd - let lnum = getpos('.')[1] - call append(lnum - 1, newline) -endfunction diff --git a/bundle/scala/after/syntax/help.vim b/bundle/scala/after/syntax/help.vim deleted file mode 100644 index b352a1e..0000000 --- a/bundle/scala/after/syntax/help.vim +++ /dev/null @@ -1,8 +0,0 @@ -let b:current_syntax = '' -unlet b:current_syntax -syntax include @ScalaCode syntax/scala.vim -if has('conceal') - syntax region rgnScala matchgroup=Ignore concealends start='!sc!' end='!/sc!' contains=@ScalaCode -else - syntax region rgnScala matchgroup=Ignore start='!sc!' end='!/sc!' contains=@ScalaCode -endif diff --git a/bundle/scala/doc/scala.txt b/bundle/scala/doc/scala.txt deleted file mode 100644 index d3277b4..0000000 --- a/bundle/scala/doc/scala.txt +++ /dev/null @@ -1,44 +0,0 @@ -*scala.txt* Syntax highlighting and helper functions for the Scala language. - -INTRODUCTION *scala* - -Syntax highlighting and helper functions for the scala language. - -COMMANDS *scala-commands* - - *:SortScalaImports* -:SortScalaImports There are two modes in which this command can operate. - By default it walks all import groups at the top of - the Scala file and orders their lines alphabetically. - A group is a series of lines starting with the - import keyword separated by one or more blank lines. - - The second, more advanced mode, can be activated by - setting - - let g:scala_sort_across_groups=1 - - This makes this command include all imports in the - sorting regardless of blank lines in between them and - puts them in three predefined groups instead. - The three groups in which the imports can fall are: - - 1. Scala and Java core - 2. Third party libraries - 3. First party code (ie. your own) - - Java and Scala core imports are identified by the - java(x) and scala namespaces. - Everything else that isn't a first party namespace - will be a third party import. - You can define a regex that matches first party - namespaces by setting - - g:scala_first_party_namespaces - - For example in a standard Play app this would be - set to - g:scala_first_party_namespaces= - \ '\(controllers\|views\|models\)' - - diff --git a/bundle/scala/ftdetect/scala.vim b/bundle/scala/ftdetect/scala.vim deleted file mode 100644 index 997a701..0000000 --- a/bundle/scala/ftdetect/scala.vim +++ /dev/null @@ -1,8 +0,0 @@ -fun! s:DetectScala() - if getline(1) == '#!/usr/bin/env scala' - set filetype=scala - endif -endfun - -au BufRead,BufNewFile *.scala,*.sbt set filetype=scala -au BufRead,BufNewFile * call s:DetectScala() diff --git a/bundle/scala/ftplugin/scala.vim b/bundle/scala/ftplugin/scala.vim deleted file mode 100644 index 3f0de96..0000000 --- a/bundle/scala/ftplugin/scala.vim +++ /dev/null @@ -1,195 +0,0 @@ -setlocal formatoptions+=ro -setlocal commentstring=//%s -let &l:include = '^\s*import' -let &l:includeexpr = 'substitute(v:fname,"\\.","/","g")' -setlocal path+=src/main/scala,src/test/scala -setlocal suffixesadd=.scala - -set makeprg=sbt\ -Dsbt.log.noformat=true\ compile -set efm=%E\ %#[error]\ %f:%l:\ %m,%C\ %#[error]\ %p^,%-C%.%#,%Z, - \%W\ %#[warn]\ %f:%l:\ %m,%C\ %#[warn]\ %p^,%-C%.%#,%Z, - \%-G%.%# - -if globpath(&rtp, 'plugin/fuf.vim') != '' - " - " FuzzyFinder stuff - " - " - " SanitizeDirForFuzzyFinder() - " - " This is really just a convenience function to clean up any stray '/' - " characters in the path, should they be there. - " - function! scala#SanitizeDirForFuzzyFinder(dir) - let dir = expand(a:dir) - let dir = substitute(dir, '/\+$', '', '') - let dir = substitute(dir, '/\+', '/', '') - - return dir - endfunction - - " - " GetDirForFuzzyFinder() - " - " Given a directory to start 'from', walk up the hierarchy, looking for a path - " that matches the 'addon' you want to see. - " - " If nothing can be found, then we just return the 'from' so we don't really get - " the advantage of a hint, but just let the user start from wherever he was - " starting from anyway. - " - function! scala#GetDirForFuzzyFinder(from, addon) - let from = scala#SanitizeDirForFuzzyFinder(a:from) - let addon = expand(a:addon) - let addon = substitute(addon, '^/\+', '', '') - let found = '' - " If the addon is right here, then we win - if isdirectory(from . '/' . addon) - let found = from . '/' . addon - else - let dirs = split(from, '/') - if !has('win32') && !has('win64') - let dirs[0] = '/' . dirs[0] - endif - " Walk up the tree and see if it's anywhere there - for n in range(len(dirs) - 1, 0, -1) - let path = join(dirs[0:n], '/') - if isdirectory(path . '/' . addon) - let found = path . '/' . addon - break - endif - endfor - endif - " If we found it, then let's see if we can go deeper - " - " For example, we may have found component_name/include - " but what if that directory only has a single directory - " in it, and that subdirectory only has a single directory - " in it, etc... ? This can happen when you're segmenting - " by namespace like this: - " - " component_name/include/org/vim/CoolClass.h - " - " You may find yourself always typing '' from the - " 'include' directory just to go into 'org/vim' so let's - " just eliminate the need to hit the ''. - if found != '' - let tempfrom = found - let globbed = globpath(tempfrom, '*') - while len(split(globbed, "\n")) == 1 - let tempfrom = globbed - let globbed = globpath(tempfrom, '*') - endwhile - let found = scala#SanitizeDirForFuzzyFinder(tempfrom) . '/' - else - let found = from - endif - - return found - endfunction - - " - " GetTestDirForFuzzyFinder() - " - " Now overload GetDirForFuzzyFinder() specifically for the test directory (I'm - " really only interested in going down into test/src 90% of the time, so let's - " hit that 90% and leave the other 10% to couple of extra keystrokes) - " - function! scala#GetTestDirForFuzzyFinder(from) - return scala#GetDirForFuzzyFinder(a:from, 'src/test/scala/') - endfunction - - " - " GetMainDirForFuzzyFinder() - " - " Now overload GetDirForFuzzyFinder() specifically for the main directory. - " - function! scala#GetMainDirForFuzzyFinder(from) - return scala#GetDirForFuzzyFinder(a:from, 'src/main/scala/') - endfunction - - " - " GetRootDirForFuzzyFinder() - " - " Now overload GetDirForFuzzyFinder() specifically for the root directory. - " - function! scala#GetRootDirForFuzzyFinder(from) - return scala#GetDirForFuzzyFinder(a:from, 'src/../') - endfunction - - " If you want to disable the default key mappings, write the following line in - " your ~/.vimrc - " let g:scala_use_default_keymappings = 0 - if get(g:, 'scala_use_default_keymappings', 1) - nnoremap ft :FufFile =scala#GetTestDirForFuzzyFinder('%:p:h') - nnoremap fs :FufFile =scala#GetMainDirForFuzzyFinder('%:p:h') - nnoremap fr :FufFile =scala#GetRootDirForFuzzyFinder('%:p:h') - endif -endif - -" If you want to disable the default key mappings, write the following line in -" your ~/.vimrc -" let g:scala_use_default_keymappings = 0 -if get(g:, 'scala_use_default_keymappings', 1) - nnoremap jt :call JustifyCurrentLine() -endif - -" -" TagBar -" -let g:tagbar_type_scala = { - \ 'ctagstype' : 'scala', - \ 'kinds' : [ - \ 'p:packages:1', - \ 'V:values', - \ 'v:variables', - \ 'T:types', - \ 't:traits', - \ 'o:objects', - \ 'a:aclasses', - \ 'c:classes', - \ 'r:cclasses', - \ 'm:methods' - \ ], - \ 'sro' : '.', - \ 'kind2scope' : { - \ 'T' : 'type', - \ 't' : 'trait', - \ 'o' : 'object', - \ 'a' : 'abstract class', - \ 'c' : 'class', - \ 'r' : 'case class' - \ }, - \ 'scope2kind' : { - \ 'type' : 'T', - \ 'trait' : 't', - \ 'object' : 'o', - \ 'abstract class' : 'a', - \ 'class' : 'c', - \ 'case class' : 'r' - \ } -\ } - -function! s:CreateOrExpression(keywords) - return '('.join(a:keywords, '|').')' -endfunction - -function! s:NextSection(backwards) - if a:backwards - let dir = '?' - else - let dir = '/' - endif - let keywords = [ 'def', 'class', 'trait', 'object' ] - let keywordsOrExpression = s:CreateOrExpression(keywords) - - let modifiers = [ 'public', 'private', 'private\[\w*\]', 'protected', 'abstract', 'case', 'override', 'implicit', 'final', 'sealed'] - let modifierOrExpression = s:CreateOrExpression(modifiers) - - let regex = '^ *('.modifierOrExpression.' )* *'.keywordsOrExpression."\r" - execute 'silent normal! ' . dir . '\v'.regex -endfunction - -noremap