Working from @Omar comment to this answer, I coded a fold method to languages which comment with //
, like JS. Add following to ~/.vimrc:
autocmd FileType javascript setlocal foldmethod=expr foldcolumn=6
autocmd FileType javascript setlocal foldexpr=JSFolds()
" Level of a folding:
"// #: level 1
"// ##: level 2
"// ###: level 3
function! JSFolds()
" Option 1: // and no space and hashes:
"if getline(v:lnum) =~ '^//#'
" Option 2: // and 1 space and hashes:
"if getline(v:lnum) =~ '^//\+ #'
" Option 3: spaces/tabs/nothing and // and 1 space and hashes:
if getline(v:lnum) =~ '^\s*//\+ #'
" Option 4: anything and // and 1 space and hashes:
" DANEGROUS! Potential conflict with code. E.g. print("// # Title");
" if getline(v:lnum) =~ '//\+ #'
" Number of hashs # in line that success previous condition (if)
" determine the fold level
let repeatHash = len(matchstr(getline(v:lnum), '#\+'))
return ">" . repeatHash
endif
return "="
endfunction
Examples. Note on the left the fold levels ("|" and "-"):
- // # ** Fold style recommended **
- // # 1 easy case
|- // ## 2 easy case
||- // ### 3 easy case
||| // Comment inside level 3
|||- // #### 4 easy case
|||| // Comment inside level 4
|- // ## 2 easy case (indents are OK with Option 3)
|| /#### error (JS comment needs 2 slashes)
||
- // # ** Fold of just 1 line **
|-- // ### 3 easy case
||- // ### = same fold level as previous line, thus previous line folds just itself ?!? (not concerns this fold function)
|||
- // # ** Space needed before, BUT not needed after hash/-es **
|- // ##Fold Level changed Because no space after hashes is OK: '// # ' vs '// #NoSpace'. NoSpace could even be a return carriage (enter).
|| //## Fold Level Unchanged Because no space after pair of slashes: '// #' vs '//#'
|| // ##txt Unchanged Because too much space after slashes
|| // ## txt Unchanged Because too much space after slashes
||
- // # ** Odds vs Even slashes **
- /// # 1 overrides typo 3 slash instead of just 2 (/// vs //)
- ///// # 1 overrides typo 5 slash instead of just 4 (///// vs ////). Read Recommenting Comments notes.
|- // ## ** As long as the pattern is at least '// # ', further previous slashes are ok **
- // # 1 easy case
|-- // ### 3 ok (and recommended fold style)
||- ///// ### 3 ok (recommented + typo)
||- ////// ### 3 ok (re-recommented)
||- /// ### 3 ok (typo)
||- //// ### 3 ok (recommented)
||- ///////// ### 3 ok (who cares? it works!)
|||
- // # ** Recommenting Comments **
- // # 1 easy case
| // Comment inside level 1
- //// # 1 recommented a comment
| //// Comment inside level 1
- ///// # 1 re-re-recomment
| ///// Comment inside level 1
|
- // # ** Recommenting Comments adding text **
|-- // ### //// # 3 changing fold level on purpose of a recommented a comment
||| // Comment inside level 3
||| // text // ## 2 (recommented a comment adding text)
||| // text#text // ## 2 right {recommented a comment adding initial text, as long as this text has no hash just after '// ' (2*slash + space) would be ok }
- // #text#text // ## 2 wrongly {recommented a comment adding initial text, as long as this text has no hash just after '// ' (2*slash + space) would be ok }
- // # changeFoldIntentionally // ## 1 clear intention to change fold level of comments
- // #changeFoldIntentionally // ## 1 clear intention to change fold level of comments (previousi example, with space after hash would be clearer)
|-- // ### changeFoldIntentionally // ## 3 clear intention to change fold level of comments
|||
PD: totally open to critics and improvements of the code. Actually I'm a beginner with vimscript.