From a81cdc4f4db86821b20930107d3c214a1b685fb2 Mon Sep 17 00:00:00 2001 From: monteiro Date: Fri, 18 Nov 2016 08:23:25 -0200 Subject: [PATCH 1/4] improved folding in various cases --- autoload/pymode/folding.vim | 120 +++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 16 deletions(-) diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index 3ed61bc5..b8362722 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -1,16 +1,25 @@ " Python-mode folding functions +" Notice that folding is based on single line so complex regular expressions +" that take previous line into consideration are not fit for the job. +" Regex definitions for correct folding let s:def_regex = g:pymode_folding_regex let s:blank_regex = '^\s*$' -let s:decorator_regex = '^\s*@' -let s:doc_begin_regex = '^\s*\%("""\|''''''\)' +" Spyder, a very popular IDE for python has a template which includes +" '@author:' ; thus the regex below. +let s:decorator_regex = '^\s*@\(author:\)\@!' +let s:doc_begin_regex = '^\s*[uU]\=\%("""\|''''''\)' let s:doc_end_regex = '\%("""\|''''''\)\s*$' -let s:doc_line_regex = '^\s*\("""\|''''''\).\+\1\s*$' +" This one is needed for the while loop to count for opening and closing +" docstrings. +let s:doc_general_regex = '\%("""\|''''''\)' +let s:doc_line_regex = '^\s*[uU]\=\("""\|''''''\).\+\1\s*$' let s:symbol = matchstr(&fillchars, 'fold:\zs.') " handles multibyte characters if s:symbol == '' let s:symbol = ' ' endif +" '''''''' fun! pymode#folding#text() " {{{ @@ -33,24 +42,29 @@ fun! pymode#folding#text() " {{{ let line = substitute(line, '\t', onetab, 'g') let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount)) - let line = substitute(line, '\%("""\|''''''\)', '', '') + let line = substitute(line, '[uU]\=\%("""\|''''''\)', '', '') let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1 return line . ' ' . repeat(s:symbol, fillcharcount) . ' ' . foldedlinecount endfunction "}}} - fun! pymode#folding#expr(lnum) "{{{ let line = getline(a:lnum) let indent = indent(a:lnum) let prev_line = getline(a:lnum - 1) + let next_line = getline(a:lnum + 1) + " Decorators {{{ if line =~ s:decorator_regex return ">".(indent / &shiftwidth + 1) - endif + endif "}}} + " Definition {{{ if line =~ s:def_regex - " single line def + " If indent of this line is greater or equal than line below + " and previous non blank line does not end with : (that is, is not a + " definition) + " Keep the same indentation if indent(a:lnum) >= indent(a:lnum+1) && getline(prevnonblank(a:lnum)) !~ ':\s*$' return '=' endif @@ -71,16 +85,35 @@ fun! pymode#folding#expr(lnum) "{{{ else return ">".(indent / &shiftwidth + 1) endif - endif + endif "}}} - if line =~ s:doc_begin_regex && line !~ s:doc_line_regex && prev_line =~ s:def_regex - return ">".(indent / &shiftwidth + 1) + " Docstrings {{{ + + " TODO: A while loop now counts the number of open and closed folding in + " order to determine if it is a closing or opening folding. + " It is working but looks like it is an overkill. + + " Notice that an effect of this is that other docstring matches will not + " be one liners. + if line =~ s:doc_line_regex + return "=" endif - if line =~ s:doc_end_regex && line !~ s:doc_line_regex - return "<".(indent / &shiftwidth + 1) + if line =~ s:doc_begin_regex + " echom 'just entering' + if s:Is_opening_folding(a:lnum) + " echom 'entering at line ' . a:lnum + return ">".(indent / &shiftwidth + 1) + endif endif + if line =~ s:doc_end_regex + if !s:Is_opening_folding(a:lnum) + " echom 'leaving at line ' . a:lnum + return "<".(indent / &shiftwidth + 1) + endif + endif "}}} + " Nested Definitions {{{ " Handle nested defs but only for files shorter than " g:pymode_folding_nest_limit lines due to performance concerns if line('$') < g:pymode_folding_nest_limit && indent(prevnonblank(a:lnum)) @@ -125,18 +158,25 @@ fun! pymode#folding#expr(lnum) "{{{ finally call setpos('.', curpos) endtry - endif + endif " }}} + " Blank Line {{{ if line =~ s:blank_regex if prev_line =~ s:blank_regex - if indent(a:lnum + 1) == 0 && getline(a:lnum + 1) !~ s:blank_regex - return 0 + if indent(a:lnum + 1) == 0 && next_line !~ s:blank_regex && next_line !~ s:doc_general_regex + if s:Is_opening_folding(a:lnum) + " echom a:lnum + return "=" + else + " echom "not " . a:lnum + return 0 + endif endif return -1 else return '=' endif - endif + endif " }}} return '=' @@ -174,4 +214,52 @@ fun! s:BlockEnd(lnum) "{{{ return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1 endfunction "}}} +function! s:Is_opening_folding(lnum) "{{{ + " Helper function to see if docstring is opening or closing + let number_of_folding = 0 " To be analized if odd/even to inform if it is opening or closing. + let has_open_docstring = 0 " To inform is already has an open docstring. + let extra_docstrings = 0 " To help skipping ''' and """ which are not docstrings + + " The idea of this part of the function is to identify real docstrings and + " not just triple quotes (that could be a regular string). + " + " Iterater over all lines from the start until current line (inclusive) + for i in range(1, a:lnum) + let i_line = getline(i) + + if i_line =~ s:doc_line_regex + " echom "case 00 on line " . i + continue + endif + + if i_line =~ s:doc_begin_regex && ! has_open_docstring + " echom "case 01 on line " . i + " This causes the loop to continue if there is a triple quote which + " is not a docstring. + if extra_docstrings > 0 + let extra_docstrings = extra_docstrings - 1 + continue + else + let has_open_docstring = 1 + let number_of_folding = number_of_folding + 1 + endif + " If it is an end doc and has an open docstring. + elseif i_line =~ s:doc_end_regex && has_open_docstring + " echom "case 02 on line " . i + let has_open_docstring = 0 + let number_of_folding = number_of_folding + 1 + + elseif i_line =~ s:doc_general_regex + " echom "extra docstrings on line " . i + let extra_docstrings = extra_docstrings + 1 + endif + endfor + + if fmod(number_of_folding, 2) == 1 "If odd then it is an opening + return 1 + else + return 0 + endif +endfunction "}}} + " vim: fdm=marker:fdl=0 From 2c6e8981fdf051800d6d86f2491e6ecd22a1de42 Mon Sep 17 00:00:00 2001 From: monteiro Date: Fri, 18 Nov 2016 08:53:25 -0200 Subject: [PATCH 2/4] commiting to trigger travis support --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e10ed9f1..7097078e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,3 +4,4 @@ rvm: - 1.9.3 script: - make travis + From 72bbe35974b170c62887f7b7a767e8620dc624fa Mon Sep 17 00:00:00 2001 From: monteiro Date: Mon, 6 Feb 2017 12:19:24 -0200 Subject: [PATCH 3/4] fixed folding for inline def statements --- autoload/pymode/folding.vim | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index b8362722..5a692ab6 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -8,7 +8,7 @@ let s:def_regex = g:pymode_folding_regex let s:blank_regex = '^\s*$' " Spyder, a very popular IDE for python has a template which includes " '@author:' ; thus the regex below. -let s:decorator_regex = '^\s*@\(author:\)\@!' +let s:decorator_regex = '^\s*@\(author:\)\@!' let s:doc_begin_regex = '^\s*[uU]\=\%("""\|''''''\)' let s:doc_end_regex = '\%("""\|''''''\)\s*$' " This one is needed for the while loop to count for opening and closing @@ -200,7 +200,7 @@ fun! s:BlockStart(lnum) "{{{ " Now find the class/def one shiftwidth lower than the start of the " aforementioned indent block. - if next_stmt_at_def_indent && next_stmt_at_def_indent < a:lnum + if next_stmt_at_def_indent && a:lnum <= next_stmt_at_def_indent let max_indent = max([indent(next_stmt_at_def_indent) - &shiftwidth, 0]) else let max_indent = max([indent(prevnonblank(a:lnum)) - &shiftwidth, 0]) @@ -211,6 +211,14 @@ endfunction "}}} fun! s:BlockEnd(lnum) "{{{ " Note: Make sure to reset cursor position after using this function. call cursor(a:lnum, 0) + " Regex translation: + " \v: very magic + " \s: any space char + " {...}: zero to more as many as possible + " \S: non whitespace + " index [0]: gets the line returned by searchpos + " flag 'n': do not move cursor + " flag 'W': don't wrap around the end of the file return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1 endfunction "}}} @@ -227,7 +235,7 @@ function! s:Is_opening_folding(lnum) "{{{ for i in range(1, a:lnum) let i_line = getline(i) - if i_line =~ s:doc_line_regex + if i_line =~ s:doc_line_regex " echom "case 00 on line " . i continue endif @@ -252,7 +260,7 @@ function! s:Is_opening_folding(lnum) "{{{ elseif i_line =~ s:doc_general_regex " echom "extra docstrings on line " . i let extra_docstrings = extra_docstrings + 1 - endif + endif endfor if fmod(number_of_folding, 2) == 1 "If odd then it is an opening From a8dcbc8805bf743455809df1f7c17d11e92fe38a Mon Sep 17 00:00:00 2001 From: monteiro Date: Mon, 6 Feb 2017 12:32:59 -0200 Subject: [PATCH 4/4] improved folding of various cases --- autoload/pymode/folding.vim | 10 +--------- plugin/pymode.vim | 6 +++--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/autoload/pymode/folding.vim b/autoload/pymode/folding.vim index 5a692ab6..218520f0 100644 --- a/autoload/pymode/folding.vim +++ b/autoload/pymode/folding.vim @@ -200,7 +200,7 @@ fun! s:BlockStart(lnum) "{{{ " Now find the class/def one shiftwidth lower than the start of the " aforementioned indent block. - if next_stmt_at_def_indent && a:lnum <= next_stmt_at_def_indent + if next_stmt_at_def_indent && next_stmt_at_def_indent < a:lnum let max_indent = max([indent(next_stmt_at_def_indent) - &shiftwidth, 0]) else let max_indent = max([indent(prevnonblank(a:lnum)) - &shiftwidth, 0]) @@ -211,14 +211,6 @@ endfunction "}}} fun! s:BlockEnd(lnum) "{{{ " Note: Make sure to reset cursor position after using this function. call cursor(a:lnum, 0) - " Regex translation: - " \v: very magic - " \s: any space char - " {...}: zero to more as many as possible - " \S: non whitespace - " index [0]: gets the line returned by searchpos - " flag 'n': do not move cursor - " flag 'W': don't wrap around the end of the file return searchpos('\v^\s{,'.indent('.').'}\S', 'nW')[0] - 1 endfunction "}}} diff --git a/plugin/pymode.vim b/plugin/pymode.vim index 26541ae2..3ac97388 100644 --- a/plugin/pymode.vim +++ b/plugin/pymode.vim @@ -1,5 +1,5 @@ " vi: fdl=1 -let g:pymode_version = "0.8.1" +let g:pymode_version = "0.9.0" com! PymodeVersion echomsg "Current python-mode version: " . g:pymode_version com! PymodeTroubleshooting call pymode#troubleshooting#test() @@ -39,7 +39,8 @@ call pymode#default("g:pymode_folding", 1) " Maximum file length to check for nested class/def statements call pymode#default("g:pymode_folding_nest_limit", 1000) " Change for folding customization (by example enable fold for 'if', 'for') -call pymode#default("g:pymode_folding_regex", '^\s*\%(class\|def\) \w\+') +call pymode#default("g:pymode_folding_regex", '^\s*\%(class\|def\|async\s\+def\) .\+\(:\s\+\w\)\@!') + " Enable/disable python motion operators call pymode#default("g:pymode_motion", 1) @@ -314,4 +315,3 @@ endif command! PymodeVersion echomsg "Pymode version: " . g:pymode_version . " interpreter: " . g:pymode_python . " lint: " . g:pymode_lint . " rope: " . g:pymode_rope augroup pymode - pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy