tmhedberg / simpylfold Goto Github PK
View Code? Open in Web Editor NEWNo-BS Python code folding for Vim
License: BSD 3-Clause "New" or "Revised" License
No-BS Python code folding for Vim
License: BSD 3-Clause "New" or "Revised" License
"""A module docstring
This is an example::
def foo():
...
Right?
"""
Trying to fold this snippet results in the indented code example getting folded together with the line below ("Right?").
@FirstArgumentIsPodcastURL
def episodes(self, url=None):
output = []
for podcast in self._model.get_podcasts():
podcast_printed = False
if url is None or podcast.url == url:
episodes = self._episodesList(podcast)
episodes = u'\n '.join(episodes)
output.append(u"""
Episodes from %s:
%s
""" % (podcast.url, episodes))
self._pager(u'\n'.join(output))
return True
this method is within a class, the class fold is broken till this line.
When loading a large file, vim takes approximately 5 seconds to load. I believe this to be due to SimpylFold, as when I uninstalled SimpylFold; files load normally (almost instant). The file I'm loading has 900 lines, 1 class and 20 or so methods.
I'm using Vundle, but could not install SimplylFold. Here's what I did:
In my .vimrc
I put the l line:
Bundle 'tmhedberg/SimpylFold'
BundleInstall
gives no errors, yet folding does not work (za
gives the message "No fold found"). In vim, echo &foldexpr
returns 0. I conclude that SimpylFold did not install.
I am able to install vim-scripts/Efficient-python-folding using the above described method.
Both
from foo import bar, \
baz
from quux import quux
and
from foo import (bar,
baz)
from quux import quux
confuse the import folder (#56).
There are some cases where writing a big dictionary is necessary, and I would very much like to fold it (in unit tests, for example).
Just want to report a case where folding seems to fail.
Test case:
def bad_fold(
foo,
bar
):
pass
pass
pass
pass
def foo():
pass
pass
pass
pass
Results after fold:
+-- 3 lines: def bad_fold(--------------------------------------------------------------------------------------------------------------------------------------------
):
pass
pass
pass
pass
+-- 5 lines: def foo():-----------------------------------------------------------------------------------------------------------------------------------------------
Steps to reproduce:
Create a Python file, test.py
:
def test():
pass
Create some other file, test.txt
:
test text
Open test.py
in Vim with SimpylFold installed. The test()
function should be folded, and setting 'foldcolumn' to a non-zero value will reveal the extent of the fold.
Open test.txt
in a new tab: :tab sp test.txt
Close the tab with test.py
in it: gT:q
Open test.py
in another new tab: :tab sp test.py
Expected result:
test.py
appears with the test()
function folded; 'foldcolumn` shows the extent of the fold.
Actual result:
test.py
appears with no folding; 'foldcolumn' shows that no fold exists.
Notes:
:unlet b:loaded_SimpylFold
and then reload the file with :e
.:sp
) instead of tabs (:tab sp
). I'm not sure why, though, and I prefer tabs to maximize vertical space.loaded_SimpylFold
flag should be window-local (w:
) rather than buffer-local (b:
).This is rather obvious, but using this plugin and restore_view.vim (which stores folding information) simultaneously results in some erratic behavior, like lines in a function being randomly excluded from the fold, parts of different functions being folded together, etc. Disabled restore_view.vim because I need this plugin more. I apologize that I don't have much more information on why this issue exists.
def foo():
print(0)
# comment
print(1)
is legal, but misfolded (SimpylFold thinks that the function stops before the comment).
https://www.python.org/dev/peps/pep-0008/#blank-lines recommends surrounding function definitions with one empty line, and class definitions with two empty lines.
SimpylFold's current behavior is to not include trailing empty lines in the fold. This means that a series of folded definitions leave unsightly unfolded whitespace that hinders browsing code (especially with most color schemes that use a different bgcolor for folds).
Code would be more browsable and readable if the empty lines were included in the fold.
With respect to the configuration section of the readme - it seems that the little configuration of "set foldmethod=indent" in .vimrc is necessary?
And also thanks very much for writing this.
I believe SimpylFold should be minimal as possible - folding only def
and class
blocks. However, if __name__ == '__main__':
block is kind of a special case: It's the application's main code block.
Any chance of adding support to fold it as well?
Might as well handle reverse writing of this block, that is if '__main__' == __name__:
, as some people use this convetion. Same for using double quotes instead of single quotes.
other issues already mention multiline misfolds, just for the record, this is a problem with the newly
introduced import folding as well (flask_sqlalchemy/__init.py__
):
30 from flask.ext.sqlalchemy._compat import iteritems, itervalues, xrange, \
31 string_types
11 +-- 20 lines: from __future__ import with_statement, absolute_import
31 string_types
I think SimpylFold can benefit from some body of automated testcases. We can use vim-vspec for it. I'll drop different versions of what we can do in comments.
Everything is already folded up as soon as Vim starts. I don't see any way to change this behavior :(
How to reproduce:
Open vim with a file.py
On the first line write two words separated by a space
first second
Put cursor on the first letter, hit x to delete an individual character as many times as needed to reach the blank space, boom, vim locks up with high cpu usage.
Doesnt happen on other lines, only on the very first line of a document.py and only if after the space(or spaces) there is another non space character.
It happen to me at random times, i finally isolated the issue.
Good luck. I like your plugin.
As mentioned in #9, it would be nice to have the option not to fold docstrings for those of us who don't really want that feature.
It would be very useful to have something like:
def foo(x)
'''
this is doc
>>> here is test
>>> more test
'''
print 'some statements in foo'
folds like
------ def foo ------
and then unfolds to
def foo(x):
------- ''' ---------
print 'some statements in foo'
and then unfolds again to
def foo(x):
'''
this is doc
------- >>> ---------
'''
print 'some statements in foo'
and then unfolds again to
def foo(x):
'''
this is doc
>>> here is test
>>> more test
'''
print 'some statements in foo'
I hope that helps.
Similarly to #40,
def foo():
x = """\
bar baz
foo"""
return 1
def bar():
pass
gets misfolded, as simpylfold believes the function ends after the "apparent" dedent.
Currently async def
is not folding correctly.
It could be interesting to support that ๐
Here's a sample Python file:
class FoldingExample(object):
"""
This is a perfectly reasonable class.
Unfortunately, it accidentally happens to have the word
CLASS at the beginning of one of the lines of its docstring.
"""
I would expect this to have one fold, covering the "class FoldingExample" line all the way to the end. Instead, it has two folds: one covering "class FoldingExample" to "Unfortunately, it...", and one covering "CLASS at..." to the end.
Of course, this is with g:SimpylFold_fold_docstring
set to 0, if I set it to 1 then I would expect two folds but get three.
It appears that if there are empty lines in the file after the last method, the last method is not folded.
Example of a file that would reproduce the issue:
class A(object):
""""""
def method1(self):
""""""
pass
def method2(self):
""""""
pass
<empty line>
<empty line>
<yet another empty line>
In this case after opening the file, Class A is folded. Open up Class A and method1 is folded but not method2. I would expect both methods to be folded. Note, that if there are not extra lines after method2, method2 will be folded.
Even opening moderately small files can cause up to a second lag.
Here's the timings for opening the file "seaborn/categorical.py" from the popular Python plotting package Seaborn. Per the documentation (:help profile), the "self" time will be wrong since SimpylFold is called recursively.
FUNCTION SimpylFold()
Called 6982 times
Total time: 0.809100
Self time: 0.360778
count total (s) self (s)
" 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`
6982 0.016330 if !exists('b:last_folded_line') || b:last_folded_line > a:lnum
50 0.000235 let b:cache_NumContainingDefs = {}
50 0.000052 let b:in_docstring = 0
50 0.000013 endif
6982 0.008365 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
6982 0.010268 let line = getline(a:lnum)
6982 0.024489 if line =~ s:blank_regex
1944 0.003536 let next_line = nextnonblank(a:lnum)
1944 0.001479 if next_line == 0
return 0
elseif getline(next_line) =~# s:def_regex
168 0.000292 return SimpylFold(next_line) - 1
else
1776 0.001048 return -1
endif
endif
5038 0.013018 let fold_docstrings = !exists('g:SimpylFold_fold_docstring') || g:SimpylFold_fold_docstring
5038 0.031019 let docstring_match = matchlist(line, s:docstring_start_regex)
5038 0.009477 let prev_line = getline(a:lnum - 1)
5038 0.033692 if !b:in_docstring && ( prev_line =~# s:def_regex || prev_line =~ s:multiline_def_end_regex ) && len(docstring_match)
4 0.000179 0.000013 let this_fl = s:NumContainingDefs(a:lnum) + fold_docstrings
4 0.000004 let b:in_docstring = 1
4 0.000006 if docstring_match[1] == '"""'
4 0.000008 let b:docstring_end_regex = s:docstring_end_double_regex
4 0.000001 else
let b:docstring_end_regex = s:docstring_end_single_regex
endif
4 0.000003 elseif b:in_docstring
10 0.000444 0.000036 let this_fl = s:NumContainingDefs(a:lnum) + fold_docstrings
10 0.000036 if line =~ b:docstring_end_regex
4 0.000006 let b:in_docstring = 0
4 0.000002 endif
10 0.000005 else
" Otherwise, its fold level is equal to its number of containing
" definitions, plus 1, if this line starts a definition of its own
5024 0.385522 0.035029 let this_fl = s:NumContainingDefs(a:lnum) + (line =~# s:def_regex)
5024 0.002473 endif
" If the very next line starts a definition with the same fold level as
" this one, explicitly indicate that a fold ends here
5038 0.024561 if getline(a:lnum + 1) =~# s:def_regex && SimpylFold(a:lnum + 1) == this_fl
return '<' . this_fl
else
5038 0.003546 return this_fl
endif
FUNCTION <SNR>103_NumContainingDefs()
Called 6380 times
Total time: 0.356571
Self time: 0.351067
count total (s) self (s)
" Recall memoized result if it exists in the cache
6380 0.011093 if has_key(b:cache_NumContainingDefs, a:lnum)
1382 0.001994 return b:cache_NumContainingDefs[a:lnum]
endif
4998 0.007690 let this_ind = indent(a:lnum)
4998 0.003350 if this_ind == 0
250 0.000129 return 0
endif
" Walk backwards to the previous non-blank line with a lower indent level
" than this line
4748 0.005298 let i = a:lnum - 1
15716 0.006771 while 1
15716 0.060302 if getline(i) !~ s:blank_regex
11524 0.014986 let i_ind = indent(i)
11524 0.008927 if i_ind < this_ind
1342 0.002669 let ncd = s:NumContainingDefs(i) + (getline(i) =~# s:def_regex)
1342 0.000836 break
elseif i_ind == this_ind && has_key(b:cache_NumContainingDefs, i)
3406 0.005980 let ncd = b:cache_NumContainingDefs[i]
3406 0.001698 break
endif
6776 0.002618 endif
10968 0.008147 let i -= 1
" If we hit the beginning of the buffer before finding a line with a
" lower indent level, there must be no definitions containing this
" line. This explicit check is required to prevent infinite looping in
" the syntactically invalid pathological case in which the first line
" or lines has an indent level greater than 0.
10968 0.005700 if i <= 1
let ncd = getline(1) =~# s:def_regex
break
endif
10968 0.004633 endwhile
" Memoize the return value to avoid duplication of effort on subsequent
" lines
4748 0.010655 let b:cache_NumContainingDefs[a:lnum] = ncd
4748 0.003551 return ncd
I almost gave up on trying to make SimpylFold work. I've been trying to get Python folding for a long time, and my .vimrc still set fdm='syntax' for python files. There's no indication that this is incorrect for SimpylFold, and it's easy to assume that syntax folding is appropriate.
Please consider making a note in the README that setting fdm='syntax' will prevent SimpylFold from working.
def test():
pass
pass
# pass
+-- 3 lines: def test():
# pass
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Apr 8 2016 13:38:49)
MacOS X (unix) version
Included patches: 1-1707
Here is a misfolded snippet (the method gets folded with the docstring). Is there a workaround yet? Or is this just not PEP8-compliant?
class Class(object):
""" docstring
"""
# comment
def method():
pass
The plugin is really useful and works out of the box. The current combination I use to fold unfold is 'z a'. I want to change it to Enter key. How should I do it ? Just fyi NERDTree allows to show / hide a directory by pressing the Enter key. Convenience reasons !!
this is a great plugin, but sometimes I need to make manual folds post-startup and this sets the foldmethod to 'expr', which prevents thats. Is there a way to automatically set the foldmethod to manual when this finishes?
Thanks!
If I write 2 classes with out space in between, the folding of the first class absorbs
the adjacent class or def. This happens for defs with sub defs. For instances
class test()
def init()
class test2()
def init()
folds to
class test().....
If I try to fold while on lines 7 or 8, vim says 'No fold found', which is correct since it's technically not part of the fold.
1 # Stuff
2
3 class A():
4 # a
5 # b
6 # c
7
8
9 class B():
But it would be great if trying to fold while on lines 7 or 8, it would fold class A and move your cursor to line 3.
1 # Stuff
2
3 class A(): # Now folded (3 lines hidden) and cursor now here
7
8
9 class B():
Ran into a nasty issue, function signatures with the parameters spanning multiple lines for example i got this:
def activate(request, backend,
template_name='registration/activate.html',
success_url=None, extra_context=None, **kwargs):
block_of_function
Cannot be folded :( i know folding in python is a tricky issue, i'll try other plugins and let you know if any can handle that.
I'd like to fold the module docstring in my python file.
Consider following content:
#!/usr/bin/env python2.7
"""
This module does ... (module docstring)
Author: ...
"""
# source code comes here
import ...
At the moment this docstring is not folded by SimpylFold. Is it possible to add this?
Possibly related is #18
... such as copyright notices.
I'd suggest that a fully blank line breaks a block, or perhaps that can be configurable.
A simple file like this one
def test():
a = """Something
That look like a docstring.
But is %s.
""" % ('not',)
return a
print test()
print test()
print test()
Will be falsely folded because the three print statements will be included in the fold of the test function.
it is conflict with ultisnips
when i am opening a python file, typing class
and followed by <tab>
key to trigger a python class completion, SimpylFold
folds the code where i am typing.
Hello, I was trying out your very nice plugin and ran into this small issue. If I have a multiline function signature, attempting to fold the docstring folds the entire function body. For example the following would get folded into
def foo(a,b,
c):
"""
Hello world
"""
pass
this
+-- 6 lines: def foo(a,b,---
It appears this also happens for multiline class declarations but those seem to be scarce in the wild.
I am using Vundle to manage my vim plugin. And after i add Plugin 'tmhedberg/SimpylFold' in my vundle_vimrc, I run BundleInstall command in vim. But there is error requiring github password and username. But I can exactly clone the repo in bash shell with git clone XXXXX command.
Could you help me?
Hi,
If I have a function like this:
def my_func():
#This is a comment.
#This too.
#They start in column 1.
print "Here is a properly indented code snippet."
then SimpylFold will not fold my_func(). Not a big deal, I suppose, but Python allows for comments without concern for indentation level (hence I bumped into this phenomenon).
Not a big deal... it's nice to get folding... but some of my comments include examples that are rather long so I prefer to stick them on the lefthand side. Maybe that's generally hated, I don't know.
In any event, thanks for SimpylFold. It's nice.
hi there - any idea how to fix this when running PluginInstall:
[2016-02-16 11:55:25] Plugin tmhedberg/SimplyFold |~ [2016-02-16 11:55:25] $ git clone --recursive 'https://github.com/tmhedberg/SimplyFold.git' '/root/.vim/b|~ undle/SimplyFold' |~ [2016-02-16 11:55:25] > Initialized empty Git repository in /root/.vim/bundle/SimplyFold/.git/ |~ [2016-02-16 11:55:25] > error: The requested URL returned error: 403 Forbidden while accessing https://github.com/tmhedberg/SimplyFold.git/info/refs |~ [2016-02-16 11:55:25] > |~ [2016-02-16 11:55:25] > fatal: HTTP request failed
Hi,
Given,
class Foo:
pass
breaks the folding behavior on Foo
. The hash character is in column 1. GIthub's markdown seems to be mangling this. Is there a way to get it to automatically fold even if there are such comment lines in the block.
Thanks!
All's in the title: it would be nice if multiline dicts/lists could be folded too.
Somewhat similarly to #21,
class Foo:
pass
def foo(): pass
def bar(): pass
incorrectly folds into
--- class Foo: ---
--- def bar(): pass ---
Hi,
I missed function and class folding if I set folding to indent, so I thought to look for possible solution.
You plugin OTOH folds just on functions and classes, but it does not fold any other code blocks.
Is there a way to set vim use regular indent fold style additionally to your plugin?
SimpylFold doesn't properly handle multi-line strings, especially important in test-driven development.
For example:
def testIndexToCoord(self):
m = '''Wrong coordinate given from index. Check indexToCoord() method.
Index given: {}
Observed coordinate: {}
Expected coordinate: {}'''
index = 3
expectedCoord = (0, 1)
becomes
+-- 2 lines: def testIndexToCoord(self):--------------------------------------------------------------
Index given: {}
Observed coordinate: {}
Expected coordinate: {}'''
index = 3
expectedCoord = (0, 1)
After merging 31520d3 functions which contain strings (""") are not folded the right way. The end of function is not correctly recognised.
def f():
""""
abc
""""
pass
def g():
"""
abc
"""
pass
is not folded well.
Reproduce Plan:
Results:
It appears that folds don't work on subsequent file opens. Only on the first file opened with vim. This is a regression as this was working earler yesterday. Heres the changeset that introduces the issue.
kenneth@poseidon:~/.vim/bundle/SimpylFold$ git bisect bad
ffe7f9d is the first bad commit
commit ffe7f9d
Author: Taylor Hedberg [email protected]
Date: Tue Mar 6 22:42:59 2012 -0500
Include guard
:040000 040000 c0d64518e4d72c4e4ff9978e221e9e46a24cb25f 1b735d022f946dea73786fe497a16203a7cd72b2 M ftplugin
It would be a peach if there was a docstring preview of the class/function.
What it is now:
830 +--- 4 lines: def openStyleDialog(self):----------------------------------------------------------------------------------------------------------------
To something like:
830 +--- 4 lines: def openStyleDialog(self): Open the style dialog on stage----------------------------------------------------------------------
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.