]> git.madduck.net Git - etc/vim.git/blob - after/ftplugin/markdown.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Refactoring the fenced code block handling of folding
[etc/vim.git] / after / ftplugin / markdown.vim
1 " folding for Markdown headers, both styles (atx- and setex-)
2 " http://daringfireball.net/projects/markdown/syntax#header
3 "
4 " this code can be placed in file
5 "   $HOME/.vim/after/ftplugin/markdown.vim
6 "
7 " original version from Steve Losh's gist: https://gist.github.com/1038710
8
9 function! s:is_mkdCode(lnum)
10     let name = synIDattr(synID(a:lnum, 1, 0), 'name')
11     return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)')
12 endfunction
13
14 if get(g:, "vim_markdown_folding_style_pythonic", 0)
15     function! Foldexpr_markdown(lnum)
16         let l1 = getline(a:lnum)
17         " keep track of fenced code blocks
18         if l1 =~ '````*' || l1 =~ '\~\~\~\~*'
19             if b:fenced_block == 0
20                 let b:fenced_block = 1
21             elseif b:fenced_block == 1
22                 let b:fenced_block = 0
23             endif
24         endif
25
26         if b:fenced_block == 1
27             if a:lnum == 1
28                 " fold any 'preamble'
29                 return '>1'
30             else
31                 " keep previous foldlevel
32                 return '='
33             endif
34         endif
35
36         let l2 = getline(a:lnum+1)
37         if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
38             " next line is underlined (level 1)
39             return '>0'
40         elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
41             " next line is underlined (level 2)
42             return '>1'
43         endif
44
45         if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
46             " current line starts with hashes
47             return '>'.(matchend(l1, '^#\+') - 1)
48         elseif a:lnum == 1
49             " fold any 'preamble'
50             return '>1'
51         else
52             " keep previous foldlevel
53             return '='
54         endif
55     endfunction
56
57     function! Foldtext_markdown()
58         let line = getline(v:foldstart)
59         let has_numbers = &number || &relativenumber
60         let nucolwidth = &fdc + has_numbers * &numberwidth
61         let windowwidth = winwidth(0) - nucolwidth - 6
62         let foldedlinecount = v:foldend - v:foldstart
63         let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount))
64         let line = substitute(line, '\%("""\|''''''\)', '', '')
65         let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1
66         return line . ' ' . repeat("-", fillcharcount) . ' ' . foldedlinecount
67     endfunction
68 else
69     function! Foldexpr_markdown(lnum)
70         if (a:lnum == 1)
71             let l0 = ''
72         else
73             let l0 = getline(a:lnum-1)
74         endif
75
76         " keep track of fenced code blocks
77         if l0 =~ '````*' || l0 =~ '\~\~\~\~*'
78             if b:fenced_block == 0
79                 let b:fenced_block = 1
80             elseif b:fenced_block == 1
81                 let b:fenced_block = 0
82             endif
83         endif
84
85         if b:fenced_block == 1
86             " keep previous foldlevel
87             return '='
88         endif
89
90         let l2 = getline(a:lnum+1)
91         if  l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
92             " next line is underlined (level 1)
93             return '>1'
94         elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
95             " next line is underlined (level 2)
96             if g:vim_markdown_folding_level >= 2
97                 return '>1'
98             else
99                 return '>2'
100             endif
101         endif
102
103         let l1 = getline(a:lnum)
104         if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
105             " fold level according to option
106             let l:level = matchend(l1, '^#\+')
107             if g:vim_markdown_folding_level == 1 || l:level > g:vim_markdown_folding_level
108                 return -1
109             else
110                 " headers are not folded
111                 return 0
112             endif
113         endif
114
115         if l0 =~ '^#' && !s:is_mkdCode(a:lnum-1)
116             " current line starts with hashes
117             return '>'.matchend(l0, '^#\+')
118         else
119             " fold here because of setext headers
120             return '='
121         endif
122     endfunction
123 endif
124
125
126 let b:fenced_block = 0
127 let g:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1)
128
129 if !get(g:, "vim_markdown_folding_disabled", 0)
130     setlocal foldexpr=Foldexpr_markdown(v:lnum)
131     setlocal foldmethod=expr
132     if get(g:, "vim_markdown_folding_style_pythonic", 0)
133         setlocal foldtext=Foldtext_markdown()
134     endif
135 endif