From c4773a9b8e0ac823009bb342b2642f780de33cdc Mon Sep 17 00:00:00 2001 From: Alexandre Constantino Date: Tue, 12 Jan 2016 17:37:16 +0000 Subject: [PATCH 1/1] Fix bug related to folding and hash comments Fix bug that occurs when hash comments are used in fenced code blocks. Fix same problem that occurs when building a TOC with the :Toc command. Add flag that allow the user to set folding level, by default set to 1. --- README.md | 16 ++++++++++++++++ after/ftplugin/markdown.vim | 38 ++++++++++++++++++++++++++++++------- ftplugin/markdown.vim | 28 +++++++++++++++++++++++---- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d2ed419..da77a07 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,22 @@ Highlight YAML frontmatter as used by Jekyll: let g:vim_markdown_frontmatter=1 ``` +#### Folding level + +Folding level is a number between 1 and 6. By default, if not specified, it is set to 1. + +```vim +let g:vim_markdown_folding_level = 6 +``` + +Tip: it can be changed on the fly with: + +```vim +:let g:vim_markdown_folding_level = 1 +:edit +``` + + ## Mappings The following work on normal and visual modes: diff --git a/after/ftplugin/markdown.vim b/after/ftplugin/markdown.vim index d965a71..f6bfe47 100644 --- a/after/ftplugin/markdown.vim +++ b/after/ftplugin/markdown.vim @@ -47,6 +47,20 @@ if get(g:, "vim_markdown_folding_style_pythonic", 0) endfunction else function! Foldexpr_markdown(lnum) + if (a:lnum == 1) + let l0 = '' + else + let l0 = getline(a:lnum-1) + endif + " keep track of fenced code blocks + if l0 =~ '````*' || l0 =~ '~~~~*' + if b:fenced_block == 0 + let b:fenced_block = 1 + elseif b:fenced_block == 1 + let b:fenced_block = 0 + endif + endif + let l2 = getline(a:lnum+1) if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1) " next line is underlined (level 1) @@ -58,16 +72,22 @@ else let l1 = getline(a:lnum) if l1 =~ '^#' && !s:is_mkdCode(a:lnum) - " don't include the section title in the fold - return '-1' + " fold level according to option + " (in vim -1 is visible, >= 0 is folded) + let l:level = matchend(l1, '^#\+') + if g:vim_markdown_folding_level == 1 || l:level > g:vim_markdown_folding_level + return -1 + else + " code blocks are always folded + return b:fenced_block + endif endif - if (a:lnum == 1) - let l0 = '' - else - let l0 = getline(a:lnum-1) - endif if l0 =~ '^#' && !s:is_mkdCode(a:lnum-1) + " collapse comments in fenced code blocks into a single fold + if b:fenced_block == 1 + return 1 + endif " current line starts with hashes return '>'.matchend(l0, '^#\+') else @@ -77,6 +97,10 @@ else endfunction endif + +let b:fenced_block = 0 +let g:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1) + if !get(g:, "vim_markdown_folding_disabled", 0) setlocal foldexpr=Foldexpr_markdown(v:lnum) setlocal foldmethod=expr diff --git a/ftplugin/markdown.vim b/ftplugin/markdown.vim index f68e54c..bc916ef 100644 --- a/ftplugin/markdown.vim +++ b/ftplugin/markdown.vim @@ -302,12 +302,32 @@ function! s:Toc(...) let l:window_type = 'vertical' endif - try - silent lvimgrep /\(^\S.*\(\n[=-]\+\n\)\@=\|^#\+\)/ % - catch /E480/ + + let b:bufnr = bufnr('%') + let b:fenced_block = 0 + let b:header_list = [] + let l:header_max_len = 0 + for i in range(1, line('$')) + let l:lineraw = getline(i) + let l:line = substitute(l:lineraw, "#", "\\\#", "g") + if l:line =~ '````*' || l:line =~ '\~\~\~\~*' + if b:fenced_block == 0 + let b:fenced_block = 1 + elseif b:fenced_block == 1 + let b:fenced_block = 0 + endif + endif + if l:line =~ '^#\+' && b:fenced_block == 0 + " append line to location list + let b:item = {'lnum': i, 'text': l:line, 'valid': 1, 'bufnr': b:bufnr, 'col': 1} + let b:header_list = b:header_list + [b:item] + endif + endfor + if len(b:header_list) == 0 echom "Toc: No headers." return - endtry + endif + call setloclist(0, b:header_list) if l:window_type ==# 'horizontal' lopen -- 2.39.5