From e6f90a24d5c39dd9b5442cc9071e1d2c4e199a83 Mon Sep 17 00:00:00 2001 From: Salt Date: Thu, 30 Nov 2017 17:30:19 -0600 Subject: [PATCH] Vim: Add SimpylFold I keep fucking making these the wrong way and it's going to bite me in the ass. Submodules, self. SUBMODULES. SUBMODULES. --- .vim/bundle/SimpylFold/.vintrc.yaml | 3 + .vim/bundle/SimpylFold/AUTHORS | 9 + .vim/bundle/SimpylFold/LICENSE | 25 ++ .vim/bundle/SimpylFold/README.md | 80 ++++ .../bundle/SimpylFold/autoload/SimpylFold.vim | 389 ++++++++++++++++++ .vim/bundle/SimpylFold/doc/SimpylFold.txt | 69 ++++ .vim/bundle/SimpylFold/ftplugin/cython | 1 + .../SimpylFold/ftplugin/python/SimpylFold.vim | 16 + .vim/bundle/SimpylFold/plugin/SimpylFold.vim | 7 + .vim/bundle/YouCompleteMe | 1 + 10 files changed, 600 insertions(+) create mode 100644 .vim/bundle/SimpylFold/.vintrc.yaml create mode 100644 .vim/bundle/SimpylFold/AUTHORS create mode 100644 .vim/bundle/SimpylFold/LICENSE create mode 100644 .vim/bundle/SimpylFold/README.md create mode 100644 .vim/bundle/SimpylFold/autoload/SimpylFold.vim create mode 100644 .vim/bundle/SimpylFold/doc/SimpylFold.txt create mode 120000 .vim/bundle/SimpylFold/ftplugin/cython create mode 100644 .vim/bundle/SimpylFold/ftplugin/python/SimpylFold.vim create mode 100644 .vim/bundle/SimpylFold/plugin/SimpylFold.vim create mode 160000 .vim/bundle/YouCompleteMe diff --git a/.vim/bundle/SimpylFold/.vintrc.yaml b/.vim/bundle/SimpylFold/.vintrc.yaml new file mode 100644 index 00000000..b371660c --- /dev/null +++ b/.vim/bundle/SimpylFold/.vintrc.yaml @@ -0,0 +1,3 @@ +policies: + ProhibitImplicitScopeVariable: + enabled: false diff --git a/.vim/bundle/SimpylFold/AUTHORS b/.vim/bundle/SimpylFold/AUTHORS new file mode 100644 index 00000000..f7bd823c --- /dev/null +++ b/.vim/bundle/SimpylFold/AUTHORS @@ -0,0 +1,9 @@ +# This is the list of SimpylFold authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control. + +Taylor Hedberg +Google Inc. +nfnty diff --git a/.vim/bundle/SimpylFold/LICENSE b/.vim/bundle/SimpylFold/LICENSE new file mode 100644 index 00000000..340bc674 --- /dev/null +++ b/.vim/bundle/SimpylFold/LICENSE @@ -0,0 +1,25 @@ +Copyright 2012-2017 the SimpylFold authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of Taylor M. Hedberg nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.vim/bundle/SimpylFold/README.md b/.vim/bundle/SimpylFold/README.md new file mode 100644 index 00000000..7c06e813 --- /dev/null +++ b/.vim/bundle/SimpylFold/README.md @@ -0,0 +1,80 @@ +SimpylFold +========== + +Because of its reliance on significant whitespace rather than explicit block +delimiters, properly folding Python code can be tricky. The Python syntax +definition that comes bundled with Vim doesn't contain any fold directives at +all, and the simplest workaround is to `set foldmethod=indent`, which usually +ends up folding a lot more than you really want it to. + +There's no shortage of Vim plugins for improved Python folding, but most seem +to suffer from cobbled-together algorithms with bizarre, intractable bugs +in the corner cases. SimpylFold aims to be exactly what its name suggests: +simple, correct folding for Python. + +It's nothing more than it needs to be: it properly folds class and +function/method definitions, and leaves your loops and conditional blocks +untouched. There's no BS involved: no screwing around with unrelated options +(which several of the other plugins do), no choice of algorithms to scratch +your head over (there's only one that's correct); it just works, simply. + +Installation +------------ + +Use one of the following plugin managers: + +* [dein](https://github.com/Shougo/dein.vim) +* [vim-plug](https://github.com/junegunn/vim-plug) +* [vundle](https://github.com/VundleVim/Vundle.vim) +* [pathogen](https://github.com/tpope/vim-pathogen) + +Also strongly recommend using [FastFold](https://github.com/Konfekt/FastFold) +due to Vim's folding being extremely slow by default. + +Configuration +------------- + +No configuration is necessary. However, there are a few configurable options. + +### Option variables + +Set variable to `1` to enable or `0` to disable. + +For example to enable docstring preview in fold text you can add the +following command to your `~/.config/nvim/init.vim` or `~/.vimrc`: +```vim +let g:SimpylFold_docstring_preview = 1 +``` +| Variable | Description | Default | +| -------------------------------- | ------------------------------ | ------- | +| `g:SimpylFold_docstring_preview` | Preview docstring in fold text | `0` | +| `g:SimpylFold_fold_docstring` | Fold docstrings | `1` | +| `b:SimpylFold_fold_docstring` | Fold docstrings (buffer local) | `1` | +| `g:SimpylFold_fold_import` | Fold imports | `1` | +| `b:SimpylFold_fold_import` | Fold imports (buffer local) | `1` | + +### Commands + +There are also a few buffer local commands for fast toggling: + +| Command | Description | +| ----------------------- | ------------------------- | +| `SimpylFoldDocstrings` | Enable docstring folding | +| `SimpylFoldDocstrings!` | Disable docstring folding | +| `SimpylFoldImports` | Enable import folding | +| `SimpylFoldImports!` | Disable import folding | + +Usage +----- + +Use Vim's built-in folding commands to expand and collapse folds. +The most basic commands are `zc` to close a fold and `zo` to open one. +See `:help fold-commands` for full documentation. + +Bugs +---- + +If you find any bugs, please report them and submit pull requests on GitHub! +Simple is nice, but simple and correct is much better. + +Happy hacking! diff --git a/.vim/bundle/SimpylFold/autoload/SimpylFold.vim b/.vim/bundle/SimpylFold/autoload/SimpylFold.vim new file mode 100644 index 00000000..ec1281d5 --- /dev/null +++ b/.vim/bundle/SimpylFold/autoload/SimpylFold.vim @@ -0,0 +1,389 @@ +let s:blank_re = '^\s*$' +let s:comment_re = '^\s*#' +let s:multi_def_end_re = ')\%(\s*->\s*\S\+[^#]*\)\?:\s*\%(#.*\)\?$' +let s:multi_def_end_solo_re = '^\s*)\%(\s*->\s*\S\+[^#]*\)\?:\s*\%(#.*\)\?$' +let s:docstring_re = '^\s*[bBfFrRuU]\{0,2}\\\@ 0 + return &softtabstop + elseif &softtabstop < 0 && &shiftwidth > 0 + return &shiftwidth + endif + return &tabstop +endfunction + +" Calculate indent +function! s:indent(line, ind_spaces) abort + let ind = matchend(a:line, '^ *') / a:ind_spaces + if ind == 0 + let ind = matchend(a:line, '^\t*') + endif + " Fix indent for solo def multiline endings + if a:line =~# s:multi_def_end_solo_re + return ind + 1 + endif + return ind +endfunction + +function! s:defs_stack_prune(cache, defs_stack, ind) abort + for idx in range(len(a:defs_stack)) + let ind_stack = a:cache[(a:defs_stack[idx])]['indent'] + if a:ind == ind_stack + return a:defs_stack[(idx + 1):] + elseif a:ind > ind_stack + return a:defs_stack[(idx):] + endif + endfor + return [] +endfunction + +" Adjust previous blanks and comments +function! s:blanks_adj(cache, lnum, foldlevel) abort + let lnum_prev = a:lnum - 1 + while lnum_prev != 0 && ( + \ a:cache[lnum_prev]['is_blank'] || ( + \ a:cache[lnum_prev]['is_comment'] && + \ a:cache[lnum_prev]['indent'] <= a:cache[(a:lnum)]['indent'] + \ ) + \ ) + let a:cache[lnum_prev]['foldexpr'] = a:foldlevel + let lnum_prev -= 1 + endwhile +endfunction + +" Check if previous lines are blanks or comments +function! s:are_lines_prev_blank(cache, lnum) abort + let lnum_prev = a:lnum - 1 + while lnum_prev != 0 + if !a:cache[lnum_prev]['is_blank'] && !a:cache[lnum_prev]['is_comment'] + return 0 + endif + let lnum_prev -= 1 + endwhile + return 1 +endfunction + +" Compatibility shim +" 1.1x slower when `matchstrpos` exists +" 2.5x slower otherwise +let s:exists_matchstrpos = exists('*matchstrpos') +function! s:matchstrpos(expr, pat) abort + if s:exists_matchstrpos + return matchstrpos(a:expr, a:pat) + else + return [matchstr(a:expr, a:pat), match(a:expr, a:pat), matchend(a:expr, a:pat)] + endif +endfunction + +" Multiline string parsing +" Returns: +" - bool: In string? +" - bool: Single quoted? +" - bool: Found multiple strings? +" - string: End regex. +" - string: Everything before first match. +function! s:multi_string(line, first_re, in_string) abort + " 2x performance for general case + if a:line !~# '[''"]' + return [a:in_string, 0, 0, '', ''] + endif + + let string_match = s:matchstrpos(a:line, a:first_re) + if string_match[1] == -1 + return [a:in_string, 0, 0, '', ''] + endif + + " Anything before first match? + if string_match[1] >= 1 + let before_first = a:line[:(string_match[1] - 1)] + else + let before_first = '' + endif + + let in_string = a:in_string + let next_re = '' + let line_slice = a:line + let found_ends = 0 + while string_match[1] != -1 + if in_string + let in_string = 0 + let found_ends += 1 + let next_re = s:string_start_re + else + let in_string = 1 + let quotes = string_match[0][matchend(string_match[0], s:string_prefix_re):] + let next_re = '\\\@= 1), '', before_first] + else + return [1, single_quoted, (found_ends >= 1), next_re, before_first] + endif + else + return [0, 0, (found_ends >= 2), '', before_first] + endif +endfunction + +" Create a new cache +function! s:cache() abort + let cache = [{}] " With padding for lnum offset + let lines = getbufline(bufnr('%'), 1, '$') + let lnum_last = len(lines) + call insert(lines, '') " Padding for lnum offset + + let ind_spaces = s:indent_spaces() + + let defs_stack = [] + let ind_def = -1 + let in_string = 0 + let docstring_start = -1 + let in_import = 0 + let was_import = 0 + for lnum in range(1, lnum_last) + let line = lines[lnum] + + " Multiline strings + if in_string + let foldlevel = len(defs_stack) + call add(cache, {'is_blank': 0, 'is_comment': 0, 'foldexpr': foldlevel}) + + let string_match = s:multi_string(line, string_end_re, 1) + if string_match[0] + " Starting new multiline string? + if string_match[2] + let in_string_single = string_match[1] + let string_end_re = string_match[3] + let docstring_start = -1 " Invalid docstring + elseif in_string_single && line !~# s:line_cont_re + let in_string = 0 + endif + else + if docstring_start != -1 + let foldlevel += 1 + let cache[docstring_start]['foldexpr'] = '>' . foldlevel + for lnum_docstring in range((docstring_start + 1), lnum) + let cache[lnum_docstring]['foldexpr'] = foldlevel + endfor + let docstring_start = -1 + endif + let in_string = 0 + endif + continue + endif + + " Blank lines + if line =~# s:blank_re + if lnum == lnum_last + call add(cache, {'is_blank': 1, 'is_comment': 0, 'foldexpr': 0}) + call s:blanks_adj(cache, lnum, 0) + else + call add(cache, {'is_blank': 1, 'is_comment': 0, 'foldexpr': len(defs_stack)}) + endif + continue + endif + + let ind = s:indent(line, ind_spaces) + + " Comments + if line =~# s:comment_re + call add(cache, {'is_blank': 0, 'is_comment': 1, 'indent': ind}) + let foldlevel = 0 + let defs_stack_len = len(defs_stack) + for idx in range(defs_stack_len) + if ind > cache[defs_stack[idx]]['indent'] + let foldlevel = defs_stack_len - idx + break + endif + endfor + let cache[lnum]['foldexpr'] = foldlevel + call s:blanks_adj(cache, lnum, foldlevel) + continue + endif + + call add(cache, {'is_blank': 0, 'is_comment': 0, + \ 'is_def': line =~# b:SimpylFold_def_re, 'indent': ind}) + + " Definitions + if cache[lnum]['is_def'] + if empty(defs_stack) + let defs_stack = [lnum] + elseif ind == ind_def + let defs_stack[0] = lnum + elseif ind > ind_def + call insert(defs_stack, lnum) + elseif ind < ind_def + let defs_stack = [lnum] + s:defs_stack_prune(cache, defs_stack, ind) + endif + let foldlevel = len(defs_stack) - 1 + let ind_def = ind + call s:blanks_adj(cache, lnum, foldlevel) + let cache[lnum]['foldexpr'] = '>' . (foldlevel + 1) + continue + endif + + " Everything else + if !empty(defs_stack) + if ind == ind_def + let defs_stack = defs_stack[1:] + let ind_def = cache[defs_stack[0]]['indent'] + elseif ind < ind_def + let defs_stack = s:defs_stack_prune(cache, defs_stack, ind) + if !empty(defs_stack) + let ind_def = cache[defs_stack[0]]['indent'] + else + let ind_def = -1 + endif + endif + endif + let foldlevel = len(defs_stack) + + " Multiline strings start + let string_match = s:multi_string(line, s:string_start_re, 0) + if string_match[0] + let in_string = 1 + let in_string_single = string_match[1] + let string_end_re = string_match[3] + + " Docstrings + if b:SimpylFold_fold_docstring && !string_match[2] && string_match[4] =~# s:blank_re + let lnum_prev = lnum - 1 + if lnum == 1 || s:are_lines_prev_blank(cache, lnum) || ( + \ !cache[lnum_prev]['is_blank'] && !cache[lnum_prev]['is_comment'] && ( + \ cache[lnum_prev]['is_def'] || + \ lines[lnum_prev] =~# s:multi_def_end_re + \ ) + \ ) + let docstring_start = lnum + endif + endif + + let cache[lnum]['foldexpr'] = foldlevel + continue + endif + + " Imports + if b:SimpylFold_fold_import + if in_import + if line =~# import_end_re + let in_import = 0 + endif + + call s:blanks_adj(cache, lnum, foldlevel + 1) + let cache[lnum]['foldexpr'] = foldlevel + 1 + continue + elseif match(line, s:import_start_re) != -1 + let import_cont_match = matchlist(line, s:import_cont_re) + if !empty(import_cont_match) + if import_cont_match[1] ==# '(' + let import_end_re = s:import_end_paren_re + let in_import = 1 + elseif import_cont_match[2] ==# '\' + let import_end_re = s:import_end_esc_re + let in_import = 1 + endif + endif + + if was_import + call s:blanks_adj(cache, lnum, foldlevel + 1) + let cache[lnum]['foldexpr'] = foldlevel + 1 + else + let cache[lnum]['foldexpr'] = '>' . (foldlevel + 1) + endif + let was_import = 1 + continue + else + let was_import = 0 + endif + endif + + " Normal + call s:blanks_adj(cache, lnum, foldlevel) + let cache[lnum]['foldexpr'] = foldlevel + endfor + + return cache +endfunction + +" Compute foldexpr for Python code +function! SimpylFold#FoldExpr(lnum) abort + if !exists('b:SimpylFold_cache') + let b:SimpylFold_cache = s:cache() + endif + return b:SimpylFold_cache[(a:lnum)]['foldexpr'] +endfunction + +" Recache the buffer +function! SimpylFold#Recache() abort + if exists('b:SimpylFold_cache') + unlet b:SimpylFold_cache + endif +endfunction + +" Compute foldtext by obtaining the first line of the docstring for +" the folded class or function, if any exists +function! SimpylFold#FoldText() abort + let lnum = v:foldstart + let line = getline(lnum) + let string_match = matchlist(line, s:docstring_re) + " Docstring folds + if !empty(string_match) + let docstring = substitute(line, s:docstring_re, '', '') + if docstring !~# s:blank_re + return '' + endif + let docstring = getline(nextnonblank(lnum + 1)) + " Definition folds + else + let lnum = nextnonblank(lnum + 1) + let line = getline(lnum) + let string_match = matchlist(line, s:docstring_re) + if empty(string_match) + return '' + endif + let docstring = substitute(line, s:docstring_re, '', '') + if docstring =~# s:blank_re + let docstring = getline(nextnonblank(lnum + 1)) + endif + endif + return ' ' . substitute(docstring, '^\s*\|\s*$\|' . string_match[1] . '\s*$', '', 'g') +endfunction diff --git a/.vim/bundle/SimpylFold/doc/SimpylFold.txt b/.vim/bundle/SimpylFold/doc/SimpylFold.txt new file mode 100644 index 00000000..3f09557d --- /dev/null +++ b/.vim/bundle/SimpylFold/doc/SimpylFold.txt @@ -0,0 +1,69 @@ +*SimpylFold.txt* No-BS Python code folding for Vim + +============================================================================== +Introduction *SimpylFold* + +Because of its reliance on significant whitespace rather than explicit block +delimiters, properly folding Python code can be tricky. The Python syntax +definition that comes bundled with Vim doesn't contain any fold directives at +all, and the simplest workaround is to `set foldmethod=indent`, which usually +ends up folding a lot more than you really want it to. + +There's no shortage of Vim plugins for improved Python folding, but most seem +to suffer from cobbled-together algorithms with bizarre, intractable bugs +in the corner cases. SimpylFold aims to be exactly what its name suggests: +simple, correct folding for Python. + +It's nothing more than it needs to be: it properly folds class and +function/method definitions, and leaves your loops and conditional blocks +untouched. There's no BS involved: no screwing around with unrelated options +(which several of the other plugins do), no choice of algorithms to scratch +your head over (there's only one that's correct); it just works, simply. + +============================================================================== +Configuration *SimpylFold-configuration* + +No configuration is necessary. However, there are a few configurable options. + +Option variables +---------------- + +Set variable to `1` to enable or `0` to disable. + +For example to enable docstring preview in fold text you can add the +following command to your `~/.config/nvim/init.vim` or `~/.vimrc`: > + + let g:SimpylFold_docstring_preview = 1 +< +| Variable | Description | Default | +| ------------------------------- | ------------------------------ | ------- | +| `g:SimpylFold_docstring_preview` | Preview docstring in fold text | `0` | +| `g:SimpylFold_fold_docstring` | Fold docstrings | `1` | +| `b:SimpylFold_fold_docstring` | Fold docstrings (buffer local) | `1` | +| `g:SimpylFold_fold_import` | Fold imports | `1` | +| `b:SimpylFold_fold_import` | Fold imports (buffer local) | `1` | + +Commands +-------- + +There are also a few buffer local commands for fast toggling: + +| Command | Description | +| ----------------------- | ------------------------- | +| `SimpylFoldDocstrings` | Enable docstring folding | +| `SimpylFoldDocstrings!` | Disable docstring folding | +| `SimpylFoldImports` | Enable import folding | +| `SimpylFoldImports!` | Disable import folding | + +============================================================================== +Usage *SimpylFold-usage* + +Use Vim's built-in folding commands to expand and collapse folds. +The most basic commands are `zc` to close a fold and `zo` to open one. +See `:help fold-commands` for full documentation. + +============================================================================== +Bugs *SimpylFold-bugs* + +If you find any bugs, please report them and submit pull requests on GitHub! +Simple is nice, but simple and correct is much better. diff --git a/.vim/bundle/SimpylFold/ftplugin/cython b/.vim/bundle/SimpylFold/ftplugin/cython new file mode 120000 index 00000000..d8654aa0 --- /dev/null +++ b/.vim/bundle/SimpylFold/ftplugin/cython @@ -0,0 +1 @@ +python \ No newline at end of file diff --git a/.vim/bundle/SimpylFold/ftplugin/python/SimpylFold.vim b/.vim/bundle/SimpylFold/ftplugin/python/SimpylFold.vim new file mode 100644 index 00000000..f8882c57 --- /dev/null +++ b/.vim/bundle/SimpylFold/ftplugin/python/SimpylFold.vim @@ -0,0 +1,16 @@ +if exists('b:loaded_SimpylFold') + finish +endif +let b:loaded_SimpylFold = 1 + +call SimpylFold#BufferInit() +setlocal foldexpr=SimpylFold#FoldExpr(v:lnum) +setlocal foldmethod=expr + +augroup SimpylFold + autocmd TextChanged,InsertLeave call SimpylFold#Recache() +augroup END + +if exists('g:SimpylFold_docstring_preview') && g:SimpylFold_docstring_preview + setlocal foldtext=foldtext()\ .\ SimpylFold#FoldText() +endif diff --git a/.vim/bundle/SimpylFold/plugin/SimpylFold.vim b/.vim/bundle/SimpylFold/plugin/SimpylFold.vim new file mode 100644 index 00000000..35cda778 --- /dev/null +++ b/.vim/bundle/SimpylFold/plugin/SimpylFold.vim @@ -0,0 +1,7 @@ +if exists('g:loaded_SimpylFold') + finish +endif +let g:loaded_SimpylFold = 1 + +command! -bang SimpylFoldDocstrings let b:SimpylFold_fold_docstring = 1 | call SimpylFold#Recache() +command! -bang SimpylFoldImports let b:SimpylFold_fold_import = 1 | call SimpylFold#Recache() diff --git a/.vim/bundle/YouCompleteMe b/.vim/bundle/YouCompleteMe new file mode 160000 index 00000000..e8e144d4 --- /dev/null +++ b/.vim/bundle/YouCompleteMe @@ -0,0 +1 @@ +Subproject commit e8e144d446603fbaebf23c54491f43ccd79b65f4