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

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