Vim Tips Wiki
m (fixed code formatting)
(Change <tt> to <code>, perhaps also minor tweak.)
 
(31 intermediate revisions by 10 users not shown)
Line 1: Line 1:
  +
{{TipImported
{{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 ...")
 
  +
}}
  +
{{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.}}
  +
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):
  +
<pre>
 
let perl_fold = 1
 
</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].
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 "[http://vimplugin.sf.net/cgi-bin/help?tag={{urlencode:folding}} :help folding]" for more info on folding in general.
 
   
  +
==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 <code>'foldexpr'</code>.
   
  +
===Plugin: SimpleFold===
<code>
 
  +
If you are able to install scripts, the {{script|id=1868|text=SimpleFold script}} is very nice and supports Perl, among other languages.
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
 
   
  +
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.
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
 
</code>
 
   
  +
About the only thing that doesn’t work is lines which both close and open a block, e.g.:
== Comments ==
 
Regarding [[VimTip419]] , I modified it to:
 
1. Correctly recognize subs beginning, as well as disregard "substr"
 
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>
Here's the new code:
 
  +
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 ).
<code>
 
  +
function GetPerlFold()
 
  +
===foldexpr workaround===
if getline(v:lnum) =~ '^\s*sub\s'
 
 
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 ...".
return "&gt;1"
 
  +
<pre>
elseif getline(v:lnum) =~ '\}\s*$'
 
 
function GetPerlFold()
let my_perloffset = 1
 
 
if getline(v:lnum) =~ '^\s*sub\s'
while (1)
 
 
return ">1"
let my_perldata = getline(v:lnum + my_perloffset)
 
 
elseif getline(v:lnum) =~ '\}\s*$'
if my_perldata == ""
 
 
let my_perlnum = v:lnum
return "&lt;1"
 
 
let my_perlmax = line("$")
elseif my_perldata =~ '^\s*sub\s'
 
 
while (1)
return "&lt;1"
 
 
let my_perlnum = my_perlnum + 1
elseif my_perldata =~ '^\s*\(\&#35;.*\)\?$'
 
 
if my_perlnum > my_perlmax
" do nothing
 
 
return "<1"
else
 
  +
endif
return "="
 
 
let my_perldata = getline(my_perlnum)
endif
 
 
if my_perldata =~ '^\s*\(\#.*\)\?$'
let my_perloffset = my_perloffset + 1
 
 
" do nothing
endwhile
 
 
elseif my_perldata =~ '^\s*sub\s'
else
 
return "="
+
return "<1"
  +
else
endif
 
 
return "="
endfunction
 
  +
endif
setlocal foldexpr=GetPerlFold()
 
  +
endwhile
  +
else
 
return "="
  +
endif
 
endfunction
 
setlocal foldexpr=GetPerlFold()
 
setlocal foldmethod=expr
 
setlocal foldmethod=expr
</code>
+
</pre>
   
  +
==See also==
  +
*[[Folding]] presents an overview of how to use folding
   
  +
==References==
webmaster--AT--topfx.com
 
  +
*{{help|folding}}
, 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
 
   
 
==Comments==
<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>.
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
 
</code>
 
 
 
webmaster--AT--topfx.com
 
, February 3, 2003 23:00
 
----
 
The perl syntax file already has this functionality.
 
 
To enable it, just put the line:
 
 
let perl_fold=1
 
 
in your .vimrc, _vimrc or ftplugin/perl.vim.
 
 
zak at pobox.com
 
, February 4, 2003 0:42
 
----
 
Aww man ! Why wasn't I told about this before !
 
 
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.
 
 
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 "[http://vimplugin.sf.net/cgi-bin/help?tag={{urlencode:perl}} :help perl].vim" (or "help html.vim", ...)
 
 
anonymous
 
, February 10, 2003 16:44
 
----
 
if u 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).