Vim Tips Wiki
(Undo revision 5931 by Heptite (Talk) -- oops, wrong tip)
(Change <tt> to <code>, perhaps also minor tweak.)
 
(26 intermediate revisions by 8 users not shown)
Line 1: Line 1:
  +
{{TipImported
[[Category:Perl]]
 
[[Category:Folding]]
 
{{review}}
 
{{Tip
 
 
|id=419
 
|id=419
  +
|previous=418
|title=Auto-fold perl subs (and possibly other languages)
 
  +
|next=425
|created=February 3, 2003 20:43
+
|created=2003
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Mina Naguib
 
|author=Mina Naguib
|version=6.0
+
|version=7.0
 
|rating=90/33
 
|rating=90/33
  +
|category1=Folding
|text=
 
  +
|category2=Perl
Add this to your .vimrc file and it'll automatically fold perl functions (and possibly other languages that define a subroutine with "sub ...")
 
 
Once you open a perl file, you'll see all functions are folded. You can then move to a function and (space) or "zo" to open it, "zc" to close it, "zR" to open all folds (normal file) and "zM" to re-fold all folds. It makes skimming over a file a breeze. See {{help|folding}} for more info on folding in general.
 
 
function GetPerlFold()
 
if getline(v:lnum) =~ '^\s*sub'
 
return "&gt;1"
 
elseif getline(v:lnum + 2) =~ '^\s*sub' &amp;&amp; getline(v:lnum + 1) =~ '^\s*$'
 
return "&lt;1"
 
else
 
return "="
 
endif
 
endfunction
 
 
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
 
 
}}
 
}}
  +
{{Deprecated|The patch mentioned below is outdated, does not apply cleanly to the Vim 7.3 runtime, and encounters problems with hash literals. Until this is fixed, if the syntax folding bugs bother you, you can use one of the alternate methods listed below the main tip.}}
== Comments ==
 
  +
The <code>$VIMRUNTIME/syntax/perl.vim</code> file provided with Vim has a [[Check_your_syntax_files_for_configurable_options|configurable option]] that allows folding in Perl programs. To enable folding in files with "perl" filetype, put the following line in your [[vimrc]] (see {{help|perl.vim}} for more details):
Regarding [[VimTip419]] , I modified it to:
 
  +
<pre>
1. Correctly recognize subs beginning, as well as disregard "substr"
 
 
let perl_fold = 1
2. Correctly recognize end of sub, as well as disregard any following comments (commonly belonging to NEXT SUB) and not include it in fold
 
  +
</pre>
   
  +
The Vim 7.2 <code>perl.vim</code> has some bugs. A [http://groups.google.com/group/vim_dev/browse_thread/thread/e2a54d22c728d04b patch is available].
Here's the new code:
 
   
  +
==Alternatives==
function GetPerlFold()
 
  +
It is easier for most users to use the built-in procedure outlined above, but it is also possible to work around any issues you have with the built-in folding, using a plugin or directly writing and using a <code>'foldexpr'</code>.
if getline(v:lnum) =~ '^\s*sub\s'
 
return "&gt;1"
 
elseif getline(v:lnum) =~ '\}\s*$'
 
let my_perloffset = 1
 
while (1)
 
let my_perldata = getline(v:lnum + my_perloffset)
 
if my_perldata == ""
 
return "&lt;1"
 
elseif my_perldata =~ '^\s*sub\s'
 
return "&lt;1"
 
elseif my_perldata =~ '^\s*\(\&#35;.*\)\?$'
 
" do nothing
 
else
 
return "="
 
endif
 
let my_perloffset = my_perloffset + 1
 
endwhile
 
else
 
return "="
 
endif
 
endfunction
 
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
 
   
  +
===Plugin: SimpleFold===
  +
If you are able to install scripts, the {{script|id=1868|text=SimpleFold script}} is very nice and supports Perl, among other languages.
   
  +
Version 0.5 of this plugin does not support a lot of fold cases for Perl properly, however. Nevertheless, a [[Script:1868#Perl support fix|simple patch]] can fix it.
webmaster--AT--topfx.com
 
, February 3, 2003 21:49
 
----
 
Yet another bugfix. This one fixes a bug where if a sub has inside it a } followed by an empty line, the fold would end there instead of at the real end of the sub
 
   
  +
About the only thing that doesn’t work is lines which both close and open a block, e.g.:
function GetPerlFold()
 
if getline(v:lnum) =~ '^\s*sub\s'
 
return "&gt;1"
 
elseif getline(v:lnum) =~ '\}\s*$'
 
let my_perlnum = v:lnum
 
let my_perlmax = line("$")
 
while (1)
 
let my_perlnum = my_perlnum + 1
 
if my_perlnum &gt; my_perlmax
 
return "&lt;1"
 
endif
 
let my_perldata = getline(my_perlnum)
 
if my_perldata =~ '^\s*\(\&#35;.*\)\?$'
 
" do nothing
 
elseif my_perldata =~ '^\s*sub\s'
 
return "&lt;1"
 
else
 
return "="
 
endif
 
endwhile
 
else
 
return "="
 
endif
 
endfunction
 
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
 
   
  +
<pre>
  +
if (something) {
  +
stuff
  +
} elsif (somethingelse) { #this doesn’t work
  +
otherstuff
  +
}
  +
</pre>
   
  +
This doesn't appear simple to fix, so you're better off just adding a line break and refolding (by default it calculates and sets folds with <leader>f ).
webmaster--AT--topfx.com
 
, February 3, 2003 23:00
 
----
 
The perl syntax file already has this functionality.
 
   
  +
===foldexpr workaround===
To enable it, just put the line:
 
 
Add this to your [[vimrc]] to automatically fold Perl functions. You may also like to modify the script for similar languages that define a subroutine with "sub ...".
let perl_fold=1
 
  +
<pre>
 
function GetPerlFold()
 
if getline(v:lnum) =~ '^\s*sub\s'
 
return ">1"
 
elseif getline(v:lnum) =~ '\}\s*$'
 
let my_perlnum = v:lnum
 
let my_perlmax = line("$")
 
while (1)
 
let my_perlnum = my_perlnum + 1
 
if my_perlnum > my_perlmax
 
return "<1"
 
endif
 
let my_perldata = getline(my_perlnum)
 
if my_perldata =~ '^\s*\(\#.*\)\?$'
 
" do nothing
 
elseif my_perldata =~ '^\s*sub\s'
 
return "<1"
 
else
 
return "="
 
endif
 
endwhile
 
else
 
return "="
 
endif
 
endfunction
 
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
  +
</pre>
   
  +
==See also==
in your .vimrc, _vimrc or ftplugin/perl.vim.
 
  +
*[[Folding]] presents an overview of how to use folding
   
  +
==References==
zak at pobox.com
 
  +
*{{help|folding}}
, February 4, 2003 0:42
 
----
 
Aww man ! Why wasn't I told about this before !
 
   
 
==Comments==
Well, at least I learnt a little bit of vim-scripting. The let perl_fold=1 seems to do it more gracefully than my code.
 
  +
When <code>let perl_fold = 1</code> is used, the fold method (<code>:set fdm?</code>) will be "syntax", and you will not be able to use manual or marker folds. If wanted, you can change the fold method, for example, <code>:set foldmethod=manual</code>.
 
Thanks for the tip.
 
 
webmaster--AT--topfx.com
 
, February 4, 2003 8:47
 
----
 
In most cases one should look into the $VIMRUNTIME/syntax/*.vim files. There is additional 'documentation' about extra options for folding and syntax highlighting.
 
 
'''Anonymous'''
 
, February 7, 2003 0:05
 
----
 
Better yet - try {{help|perl.vim}} (or {{help|html.vim}}, ...)
 
 
anonymous
 
, February 10, 2003 16:44
 
----
 
if you put let perl_fold = 1 in your .vimrc, fold on marker doesnt work anymore
 
 
cnf--AT--antwerpen.be
 
, July 4, 2003 12:15
 
----
 
I remember seeing komodo code folding if,elsif,else clauses as well as functions which was rather cool.
 
 
roberth--AT--hydrix.com
 
, July 14, 2003 10:05
 
----
 
i found let perl_fold = 1 works unreliably-depends on indentation etc.
 
The function above works better.
 
 
However, that function does not recognize .cgi files as perl(.pl OK) perl_fold recognizes both.
 
 
what to do?
 
 
'''Anonymous'''
 
, January 26, 2004 14:26
 
----
 
Is it possible to modify the function so that the folding occurs after the sub name? The folding is very useful but I think it would be make it more useful if you can see the function name being folded instead of having to unfold the function to see the 'sub name'
 
 
cramirez--AT--gte.net
 
, December 13, 2004 21:06
 
----
 
I also found that using perl_fold = 1 the package is folded by default which for most files is not necessary. Also didn't recognise the end of a sub in some cases.
 
   
  +
In other words, if you want vim to autofold perl subroutines, use <code>let perl_fold = 1</code> in your .vimrc. This <em>should</em> automatically <code>set foldmethod=syntax</code> when you load a perl file, but if not, you can manually <code>set foldmethod=syntax</code> or put this command in a file in <code>$HOME/.vim/after/syntax</code> called <code>perl.vim</code> (create this directory and file if it does not yet exist).
'''Anonymous'''
 
, January 21, 2005 1:01
 
 
----
 
----
<!-- parsed by vimtips.py in 0.474003 seconds-->
 

Latest revision as of 05:29, 13 July 2012

Tip 419 Printable Monobook Previous Next

created 2003 · complexity intermediate · author Mina Naguib · version 7.0


This tip is deprecated for the following reasons:

The patch mentioned below is outdated, does not apply cleanly to the Vim 7.3 runtime, and encounters problems with hash literals. Until this is fixed, if the syntax folding bugs bother you, you can use one of the alternate methods listed below the main tip.

The $VIMRUNTIME/syntax/perl.vim file provided with Vim has a configurable option that allows folding in Perl programs. To enable folding in files with "perl" filetype, put the following line in your vimrc (see :help perl.vim for more details):

let perl_fold = 1

The Vim 7.2 perl.vim has some bugs. A patch is available.

Alternatives[]

It is easier for most users to use the built-in procedure outlined above, but it is also possible to work around any issues you have with the built-in folding, using a plugin or directly writing and using a 'foldexpr'.

Plugin: SimpleFold[]

If you are able to install scripts, the SimpleFold script is very nice and supports Perl, among other languages.

Version 0.5 of this plugin does not support a lot of fold cases for Perl properly, however. Nevertheless, a simple patch can fix it.

About the only thing that doesn’t work is lines which both close and open a block, e.g.:

if (something) {
    stuff
} elsif (somethingelse) {                 #this doesn’t work
   otherstuff
}

This doesn't appear simple to fix, so you're better off just adding a line break and refolding (by default it calculates and sets folds with <leader>f ).

foldexpr workaround[]

Add this to your vimrc to automatically fold Perl functions. You may also like to modify the script for similar languages that define a subroutine with "sub ...".

function GetPerlFold()
  if getline(v:lnum) =~ '^\s*sub\s'
    return ">1"
  elseif getline(v:lnum) =~ '\}\s*$'
    let my_perlnum = v:lnum
    let my_perlmax = line("$")
    while (1)
      let my_perlnum = my_perlnum + 1
      if my_perlnum > my_perlmax
        return "<1"
      endif
      let my_perldata = getline(my_perlnum)
      if my_perldata =~ '^\s*\(\#.*\)\?$'
        " do nothing
      elseif my_perldata =~ '^\s*sub\s'
        return "<1"
      else
        return "="
      endif
    endwhile
  else
    return "="
  endif
endfunction
setlocal foldexpr=GetPerlFold()
setlocal foldmethod=expr

See also[]

  • Folding presents an overview of how to use folding

References[]

Comments[]

When let perl_fold = 1 is used, the fold method (:set fdm?) will be "syntax", and you will not be able to use manual or marker folds. If wanted, you can change the fold method, for example, :set foldmethod=manual.

In other words, if you want vim to autofold perl subroutines, use let perl_fold = 1 in your .vimrc. This should automatically set foldmethod=syntax when you load a perl file, but if not, you can manually set foldmethod=syntax or put this command in a file in $HOME/.vim/after/syntax called perl.vim (create this directory and file if it does not yet exist).