4

When editing Python files at work I have to include 20+ lines of boilerplate legalese at the start of the file. "start of the file" is not that strict: I'm allowed to include the Python docstring, and future imports before the boilerplate. But the boilerplate itself is very strict, I have to include it verbatim from a company template. Specifically: I am not allowed to indent it.

For Python I use

:set foldmethod=indent

but I would like to be able to fold away that boilerplate as well.

Is it possible to tweak the indent foldmethod to fold lines starting/ending with '#' as well? Or will I need to change to foldmethod=expr and write my own folding function?

  • One thing that I do with many of my source files is put one line at the top: Copyright © ...; see below for full copyright, and then put the license at the bottom of the file (like this). I have no idea if this is an option for your PHB, but you could try suggesting it.. – Martin Tournoij Feb 27 '15 at 13:21
  • Another way is to add/remove indentation with autocmd on BufReadPost and BufWritePre... I don't know what your file looks like exactly, so I can't give you a ready-made function – Martin Tournoij Feb 27 '15 at 13:24
  • Of course you could always go the lazy route and indent your legalese ;) – Matt Boehm Feb 27 '15 at 19:47
4

The cleanest would be to re-implement Vim's indent-folding via a custom 'foldexpr', and make that consider the legalese via a special case. :help fold-indent even gives implementation hints:

  The indent() function can be used in 'foldexpr' to get the indent of a line.

Another option is described nearby:

Some lines are ignored and get the fold level of the line above or below it,
whichever is lower.  These are empty or white lines and lines starting
with a character in 'foldignore'.  White space is skipped before checking for
characters in 'foldignore'.  For C use "#" to ignore preprocessor lines.

To use this, you'd need to have non-commented indented Python statements both above and below the block of legalese, like this:

    some Python statement
# legalese
# is comments
# starting in first column
    another Python statement

With :setlocal foldmethod=indent foldignore=#, the above will be folded as one block.

| improve this answer | |
1

Unfortunately, foldignore keyword just works for one line comments. So I fold with expr :

set foldmethod=expr
set foldexpr=FoldMethod(v:lnum)

function! FoldMethod(lnum)
  "get string of current line
  let crLine=getline(a:lnum)

  " check if empty line 
  if empty(crLine) "Empty line or end comment 
    return -1 " so same indent level as line before 
  endif 

  " check if comment 
  let a:data=join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )
  if a:data =~ ".*omment.*"
    return '='
  endif

  "Otherwise return foldlevel equal to indent /shiftwidth (like if
  "foldmethod=indent)
  else  "return indent base fold
    return indent(a:lnum)/&shiftwidth
endfunction

The last block :

indent(a:lnum)/&shiftwidth

Returns a foldlevel base on indent.

And the other one :

join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )

Checks if the first character of the line is consider as a comment with the syntax. So it is a good way to merge indent and syntax folding with expression, the most advanced folding.

Note that you can also "set foldtext" depending on how you want the result to look like.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.