Permalink
Browse files

Version 1.1

    - Performance improvements (up to 3-4x faster in large buffers)
    - Option to display first line of folded docstring in fold text
    - Help file
    - Numerous bug fixes
    - BSD license
  • Loading branch information...
1 parent 6f921a2 commit 964375b8f9d1c02f88bbc8eb9f47ef801a72eb61 @tmhedberg tmhedberg committed with Mar 9, 2012
Showing with 153 additions and 5 deletions.
  1. +25 −0 LICENSE
  2. +31 −0 README.md
  3. +44 −0 doc/SimpylFold.txt
  4. +53 −5 ftplugin/{ → python}/SimpylFold.vim
View
25 LICENSE
@@ -0,0 +1,25 @@
+Copyright (c)2012, Taylor M. Hedberg <t@tmh.cc>
+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.
View
31 README.md
@@ -0,0 +1,31 @@
+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 (because there's only one that's correct); it just works, simply.
+
+Installation
+------------
+
+If you're using [Pathogen](https://github.com/tpope/vim-pathogen) and Git to manage your Vim plugins (highly recommended), you can just
+
+ cd ~/.vim
+ git submodule add https://github.com/tmhedberg/SimpylFold.git bundle/SimpylFold
+ git submodule init
+
+and you're good to go. Otherwise, clone somewhere else or just grab the tarball, and drop the plugin file into your `~/.vim/ftplugin/python`.
+
+Configuration
+-------------
+
+No configuration is necessary. However, if you want to enable previewing of your folded classes' and functions' docstrings in the fold text, add the following to your .vimrc:
+
+ let g:SimpylFold_docstring_preview = 1
+
+Bugs
+----
+
+If you find any bugs, please report them and/or submit pull requests on Github! Simple is nice, but simple and correct is much better.
+
+Happy hacking!
View
44 doc/SimpylFold.txt
@@ -0,0 +1,44 @@
+*SimpylFold.txt* No-BS Python code folding for Vim
+*SimpylFold*
+
+==============================================================================
+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 (because there's only one that's
+correct); it just works, simply.
+
+
+==============================================================================
+Configuration *SimpylFold-config*
+
+There is no configuration necessary for SimpylFold to start working. Just
+install it, and you're good to go!
+
+ *SimpylFold_docstring_preview*
+
+If you want to see the first line of your docstrings appear in the fold text,
+set g:SimpylFold_docstring_preview to 1 in your .vimrc.
+
+
+==============================================================================
+Bugs *SimpylFold-bugs*
+
+If you find any bugs, please report them and/or submit pull requests on
+Github! Simple is nice, but simple and correct is much better.
+
+
+==============================================================================
+Happy hacking!
View
58 ftplugin/SimpylFold.vim → ftplugin/python/SimpylFold.vim
@@ -1,10 +1,20 @@
+if exists('b:loaded_SimpylFold')
+ finish
+endif
+let b:loaded_SimpylFold = 1
+
let s:blank_regex = '^\s*$'
let s:def_regex = '^\s*\%(class\|def\) \w\+'
" Determine the number of containing class or function definitions for the
" given line
function! s:NumContainingDefs(lnum)
+ " Recall memoized result if it exists in the cache
+ if has_key(b:cache_NumContainingDefs, a:lnum)
+ return b:cache_NumContainingDefs[a:lnum]
+ endif
+
let this_ind = indent(a:lnum)
if this_ind == 0
@@ -24,25 +34,40 @@ function! s:NumContainingDefs(lnum)
" the syntactically invalid pathological case in which the first line
" or lines has an indent level greater than 0.
if i <= 1
- return 0
+ return getline(1) =~ s:def_regex
endif
endwhile
- return s:NumContainingDefs(i) + (getline(i) =~ s:def_regex)
+ " Memoize the return value to avoid duplication of effort on subsequent
+ " lines
+ let ncd = s:NumContainingDefs(i) + (getline(i) =~ s:def_regex)
+ let b:cache_NumContainingDefs[a:lnum] = ncd
+
+ return ncd
endfunction
" Compute fold level for Python code
function! SimpylFold(lnum)
+ " If we are starting a new sweep of the buffer (i.e. the current line
+ " being folded comes before the previous line that was folded), initialize
+ " the cache of results of calls to `s:NumContainingDefs`
+ if !exists('b:last_folded_line') || b:last_folded_line > a:lnum
+ let b:cache_NumContainingDefs = {}
+ endif
+ let b:last_folded_line = a:lnum
+
" If this line is blank, its fold level is equal to the minimum of its
" neighbors' fold levels, but if the next line begins a definition, then
" this line should fold at one level below the next
let line = getline(a:lnum)
if line =~ s:blank_regex
let next_line = nextnonblank(a:lnum)
- if getline(next_line) =~ s:def_regex
+ if next_line == 0
+ return 0
+ elseif getline(next_line) =~ s:def_regex
return SimpylFold(next_line) - 1
else
return -1
@@ -63,5 +88,28 @@ function! SimpylFold(lnum)
endfunction
-set foldexpr=SimpylFold(v:lnum)
-set foldmethod=expr
+" Obtain the first line of the docstring for the folded class or function, if
+" any exists, for use in the fold text
+function! SimpylFoldText()
+ let next = nextnonblank(v:foldstart + 1)
+ let docstring = getline(next)
+ let ds_prefix = '^\s*\%(\%(["'']\)\{3}\|[''"]\ze[^''"]\)'
+ if docstring =~ ds_prefix
+ let quote_char = docstring[match(docstring, '["'']')]
+ let docstring = substitute(docstring, ds_prefix, '', '')
+ if docstring =~ s:blank_regex
+ let docstring =
+ \ substitute(getline(nextnonblank(next + 1)), '^\s*', '', '')
+ endif
+ let docstring = substitute(docstring, quote_char . '\{,3}$', '', '')
+ return ' ' . docstring
+ endif
+ return ''
+endfunction
+
+setlocal foldexpr=SimpylFold(v:lnum)
+setlocal foldmethod=expr
+
+if exists('SimpylFold_docstring_preview') && SimpylFold_docstring_preview
+ setlocal foldtext=foldtext()\ .\ SimpylFoldText()
+endif

0 comments on commit 964375b

Please sign in to comment.