]> 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:

Pythonic folding expand level 1 by default
[etc/vim.git] / after / ftplugin / markdown.vim
1 " vim: ts=4 sw=4:
2 " folding for Markdown headers, both styles (atx- and setex-)
3 " http://daringfireball.net/projects/markdown/syntax#header
4 "
5 " this code can be placed in file
6 "   $HOME/.vim/after/ftplugin/markdown.vim
7 "
8 " original version from Steve Losh's gist: https://gist.github.com/1038710
9
10 function! s:is_mkdCode(lnum)
11     let name = synIDattr(synID(a:lnum, 1, 0), 'name')
12     return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)')
13 endfunction
14
15 if get(g:, "vim_markdown_folding_style_pythonic", 0)
16     function! Foldexpr_markdown(lnum)
17         let l1 = getline(a:lnum)
18         "~~~~~ keep track of fenced code blocks ~~~~~
19         "If we hit a code block fence
20         if l1 =~ '````*' || l1 =~ '\~\~\~\~*'
21             " toggle the variable that says if we're in a code block
22             if b:fenced_block == 0
23                 let b:fenced_block = 1
24             elseif b:fenced_block == 1
25                 let b:fenced_block = 0
26             endif
27         " else, if we're caring about front matter
28         elseif g:vim_markdown_frontmatter == 1
29             " if we're in front matter and not on line 1
30             if b:front_matter == 1 && a:lnum > 2
31                 let l0 = getline(a:lnum-1)
32                 " if the previous line fenced front matter
33                 if l0 == '---'
34                     " we must not be in front matter
35                     let b:front_matter = 0
36                 endif
37             " else, if we're on line one
38             elseif a:lnum == 1
39                 " if we hit a front matter fence
40                 if l1 == '---'
41                     " we're in the front matter
42                     let b:front_matter = 1
43                 endif
44             endif
45         endif
46
47         " if we're in a code block or front matter
48         if b:fenced_block == 1 || b:front_matter == 1
49             if a:lnum == 1
50                 " fold any 'preamble'
51                 return '>1'
52             else
53                 " keep previous foldlevel
54                 return '='
55             endif
56         endif
57
58         let l2 = getline(a:lnum+1)
59         " if the next line starts with two or more '='
60         " and is not code
61         if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
62             " next line is underlined (level 1)
63             return '>0'
64         " else, if the nex line starts with two or more '-'
65         " and is not code
66         elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
67             " next line is underlined (level 2)
68             return '>1'
69         endif
70
71         "if we're on a non-code line starting with a pound sign
72         if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
73             " set the fold level to the number of hashes -1
74             " return '>'.(matchend(l1, '^#\+') - 1)
75             " set the fold level to the number of hashes
76             return '>'.(matchend(l1, '^#\+'))
77         " else, if we're on line 1
78         elseif a:lnum == 1
79             " fold any 'preamble'
80             return '>1'
81         else
82             " keep previous foldlevel
83             return '='
84         endif
85     endfunction
86
87     function! Foldtext_markdown()
88         let line = getline(v:foldstart)
89         let has_numbers = &number || &relativenumber
90         let nucolwidth = &fdc + has_numbers * &numberwidth
91         let windowwidth = winwidth(0) - nucolwidth - 6
92         let foldedlinecount = v:foldend - v:foldstart
93         let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount))
94         let line = substitute(line, '\%("""\|''''''\)', '', '')
95         let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1
96         return line . ' ' . repeat("-", fillcharcount) . ' ' . foldedlinecount
97     endfunction
98 else " vim_markdown_folding_style_pythonic == 0
99     function! Foldexpr_markdown(lnum)
100         if (a:lnum == 1)
101             let l0 = ''
102         else
103             let l0 = getline(a:lnum-1)
104         endif
105
106         " keep track of fenced code blocks
107         if l0 =~ '````*' || l0 =~ '\~\~\~\~*'
108             if b:fenced_block == 0
109                 let b:fenced_block = 1
110             elseif b:fenced_block == 1
111                 let b:fenced_block = 0
112             endif
113         elseif g:vim_markdown_frontmatter == 1
114             if b:front_matter == 1
115                 if l0 == '---'
116                     let b:front_matter = 0
117                 endif
118             elseif a:lnum == 2
119                 if l0 == '---'
120                     let b:front_matter = 1
121                 endif
122             endif
123         endif
124
125         if b:fenced_block == 1 || b:front_matter == 1
126             " keep previous foldlevel
127             return '='
128         endif
129
130         let l2 = getline(a:lnum+1)
131         if  l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
132             " next line is underlined (level 1)
133             return '>1'
134         elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
135             " next line is underlined (level 2)
136             if s:vim_markdown_folding_level >= 2
137                 return '>1'
138             else
139                 return '>2'
140             endif
141         endif
142
143         let l1 = getline(a:lnum)
144         if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
145             " fold level according to option
146             if s:vim_markdown_folding_level == 1 || matchend(l1, '^#\+') > s:vim_markdown_folding_level
147                 if a:lnum == line('$')
148                     return matchend(l1, '^#\+') - 1
149                 else
150                     return -1
151                 endif
152             else
153                 " headers are not folded
154                 return 0
155             endif
156         endif
157
158         if l0 =~ '^#' && !s:is_mkdCode(a:lnum-1)
159             " previous line starts with hashes
160             return '>'.matchend(l0, '^#\+')
161         else
162             " keep previous foldlevel
163             return '='
164         endif
165     endfunction
166 endif
167
168
169 let b:fenced_block = 0
170 let b:front_matter = 0
171 let s:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1)
172
173 function! s:MarkdownSetupFolding()
174     if !get(g:, "vim_markdown_folding_disabled", 0)
175         if get(g:, "vim_markdown_folding_style_pythonic", 0)
176             if get(g:, "vim_markdown_override_foldtext", 1)
177                 setlocal foldtext=Foldtext_markdown()
178             endif
179         endif
180         setlocal foldexpr=Foldexpr_markdown(v:lnum)
181         setlocal foldmethod=expr
182     endif
183 endfunction
184
185 function! s:MarkdownSetupFoldLevel()
186     if get(g:, "vim_markdown_folding_style_pythonic", 0)
187         " set default foldlevel
188         execute "setlocal foldlevel=".s:vim_markdown_folding_level
189     endif
190 endfunction
191
192 call s:MarkdownSetupFoldLevel()
193 call s:MarkdownSetupFolding()
194
195 augroup Mkd
196     " These autocmds need to be kept in sync with the autocmds calling
197     " s:MarkdownRefreshSyntax in ftplugin/markdown.vim.
198     autocmd BufWinEnter,BufWritePost <buffer> call s:MarkdownSetupFolding()
199     autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownSetupFolding()
200     autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownSetupFolding()
201 augroup END