" vim: set fdm=marker et ts=4 sw=4 sts=4: function! pandoc#formatting#Init() abort "{{{1 " set up defaults {{{2 " Formatting mode {{{3 " s: use soft wraps " h: use hard wraps " a: auto format (only used if h is set) " A: smart auto format if !exists('g:pandoc#formatting#mode') let g:pandoc#formatting#mode = 's' endif "}}}3 " Auto-format {{{3 " Autoformat blacklist {{{4 if !exists('g:pandoc#formatting#smart_autoformat_blacklist') let g:pandoc#formatting#smart_autoformat_blacklist = [ \ 'pandoc.+header', \ 'pandoc\S{-}(code|title|line|math)block(title)?', \ 'pdc(delimited|latex)?codeblock', \ 'pandoc.+table', \ 'pandoctable', \ 'pandoc.+latex', \ 'pandocreferencedefinition', \ 'pandocreferencelabel', \ 'tex.*', \ 'pdclatex*', \ 'yaml.*', \ 'pdcyaml', \ 'delimiter' \] endif " }}}4 " Autoformat on CursorMovedI {{{4 if !exists('g:pandoc#formatting#smart_autoformat_on_cursormoved') let g:pandoc#formatting#smart_autoformat_on_cursormoved = 0 endif "}}}4 "}}}3 " Text width {{{3 if !exists('g:pandoc#formatting#textwidth') let g:pandoc#formatting#textwidth = 79 endif " }}}3 " equalprg {{{3 if !exists('g:pandoc#formatting#equalprg') if executable('pandoc') let g:pandoc#formatting#equalprg = 'pandoc -t markdown' if g:pandoc#formatting#mode =~# 'h' let g:pandoc#formatting#equalprg.= ' --columns '.g:pandoc#formatting#textwidth else let g:pandoc#formatting#equalprg.= ' --wrap=none' endif else let g:pandoc#formatting#equalprg = '' endif endif " extend the value of equalprg if needed if !exists('g:pandoc#formatting#extra_equalprg') let g:pandoc#formatting#extra_equalprg = '--reference-links' endif " }}}3 " formatprg {{{3 if !exists('g:pandoc#formatting#formatprg#use_pandoc') let g:pandoc#formatting#formatprg#use_pandoc = 0 endif if !exists('g:pandoc#formatting#formatprg') if g:pandoc#formatting#formatprg#use_pandoc == 1 if executable('pandoc') let g:pandoc#formatting#formatprg = 'pandoc -t markdown' if g:pandoc#formatting#mode =~# 'h' let g:pandoc#formatting#formatprg.= ' --columns '.g:pandoc#formatting#textwidth else let g:pandoc#formatting#formatprg.= ' --wrap=none' endif endif else let g:pandoc#formatting#formatprg = '' endif endif " }}}3 " Use a custom indentexpr? {{{3 if !exists('g:pandoc#formatting#set_indentexpr') let g:pandoc#formatting#set_indentexpr = 0 endif " }}}3 " set up soft or hard wrapping modes "{{{2 if stridx(g:pandoc#formatting#mode, 'h') >= 0 && stridx(g:pandoc#formatting#mode, 's') < 0 call pandoc#formatting#UseHardWraps() elseif stridx(g:pandoc#formatting#mode, 's') >= 0 && stridx(g:pandoc#formatting#mode, 'h') < 0 call pandoc#formatting#UseSoftWraps() else echoerr 'pandoc: The value of g:pandoc#formatting#mode is inconsistent. Using default.' call pandoc#formatting#UseSoftWraps() endif " equalprog {{{2 " " Use pandoc to tidy up text? " " NOTE: If you use this on your entire file, it will wipe out title blocks. " if g:pandoc#formatting#equalprg !=? '' let &l:equalprg=g:pandoc#formatting#equalprg.' '.g:pandoc#formatting#extra_equalprg endif " formatprg {{{2 if g:pandoc#formatting#formatprg !=? '' let &l:formatprg=g:pandoc#formatting#formatprg endif " common settings {{{2 " indent using a custom indentexpr if g:pandoc#formatting#set_indentexpr == 1 setlocal indentexpr=pandoc#formatting#IndentExpr() endif setlocal autoindent " copy indent level from previous line. " Don't add two spaces at the end of punctuation when joining lines setlocal nojoinspaces " Always use linebreak. setlocal linebreak setlocal breakat-=* if exists('+breakindent') setlocal breakindent endif if has('smartindent') setlocal nosmartindent endif " Textile uses .. for comments if &filetype ==? 'textile' setlocal commentstring=..%s setlocal comments=f:.. else " Other markup formats use HTML-style comments setlocal commentstring= setlocal comments=s:,:\|,n:> endif let s:last_autoformat_lnum = 0 "}}}2 " " Global settings we must override {{{2 let s:original_breakat = &breakat augroup pandoc_formatting au! BufEnter set breakat-=@ au! BufLeave exe 'set breakat='.substitute(s:original_breakat, '\s*', '\\ ', 1) augroup END set breakat-=@ "}}}2 endfunction " Autoformat switches {{{1 function! pandoc#formatting#isAutoformatEnabled() abort if exists('b:pandoc_autoformat_enabled') return b:pandoc_autoformat_enabled else return 1 endif endfunction function! pandoc#formatting#EnableAutoformat() abort let b:pandoc_autoformat_enabled = 1 endfunction function! pandoc#formatting#DisableAutoformat() abort let b:pandoc_autoformat_enabled = 0 endfunction function! pandoc#formatting#ToggleAutoformat() abort if get(b:, 'pandoc_autoformat_enabled', 1) == 1 let b:pandoc_autoformat_enabled = 0 else let b:pandoc_autoformat_enabled = 1 endif endfunction function! pandoc#formatting#AutoFormat(force) abort "{{{1 if !exists('b:pandoc_autoformat_enabled') || b:pandoc_autoformat_enabled == 1 let l:line = line('.') if a:force == 1 || l:line != s:last_autoformat_lnum || (l:line == s:last_autoformat_lnum && col('.') == 1) let s:last_autoformat_lnum = l:line let l:stack = [] let l:should_enable = 1 let l:context_prevents = 0 let l:blacklist_re = '\c\v('.join(g:pandoc#formatting#smart_autoformat_blacklist, '|').')' let l:stack = synstack(l:line, col('.')) if len(l:stack) == 0 " let's try with the first column in this line let l:stack = synstack(l:line, 1) endif if len(l:stack) > 0 let l:synName = synIDattr(l:stack[0], 'name') " we check on the base syntax id, so we don't have to pollute the " blacklist with stuff like pandocAtxMark, which is contained if match(l:synName, l:blacklist_re) >= 0 let l:should_enable = 0 endif if match(l:synName, 'pandocdefinitionblock') >= 0 let context_prevents = 1 endif try let l:p_synName = synIDattr(synstack(l:line-1, col('$'))[0], 'name') catch /E684/ let l:p_synName = '' endtry if match(l:synName.l:p_synName, '\c\v(pandoc|pdc)[uo]?list') >= 0 let l:context_prevents = 1 endif else let l:p_synName = synIDattr(synID(l:line-1, col('$'), 0), 'name') if l:p_synName =~? '\c\vpandoc(u?list|referencedef)' let l:context_prevents = 1 elseif l:p_synName =~? '\c\vpandochrule' let l:context_prevents = 1 elseif l:p_synName =~? '\c\v(pandoc|pdc)codeblock' && indent('.')%4 == 0 let l:context_prevents = 1 elseif getline(l:line -1) =~? '^\w\+:' let l:context_prevents = 1 endif endif if l:should_enable == 1 if l:context_prevents != 1 setlocal formatoptions+=a else setlocal formatoptions-=a " in case it is set endif setlocal formatoptions+=t " block quotes are formatted like text comments (hackish, i know), " so we want to make them break at textwidth if l:stack != [] && l:synName ==? '\c\v(pandoc|pdc)blockquote' setlocal formatoptions+=c endif elseif l:should_enable == 0 setlocal formatoptions-=a setlocal formatoptions-=t setlocal formatoptions-=c "just in case we have added it for a block quote endif endif elseif &formatoptions !=# 'tn' setlocal formatoptions=tnroq endif endfunction function! pandoc#formatting#UseHardWraps() abort "{{{1 " reset settings that might have changed by UseSoftWraps setlocal formatoptions& setlocal display& setlocal wrap& " textwidth exec 'setlocal textwidth='.g:pandoc#formatting#textwidth " t: wrap on &textwidth " n: keep inner indent for list items. setlocal formatoptions=tnroq " will detect numbers, letters, *, +, and - as list headers, according to " pandoc syntax. " TODO: add support for roman numerals setlocal formatlistpat=^\\s*\\([*+-]\\\|\\((*\\d\\+[.)]\\+\\)\\\|\\((*\\l[.)]\\+\\)\\)\\s\\+ if stridx(g:pandoc#formatting#mode, 'a') >= 0 " a: auto-format " w: lines with trailing spaces mark continuing " paragraphs, and lines ending on non-spaces end paragraphs. " we add `w` as a workaround to `a` joining compact lists. setlocal formatoptions+=aw elseif stridx(g:pandoc#formatting#mode, 'A') >= 0 augroup pandoc_autoformat au InsertEnter call pandoc#formatting#AutoFormat(1) au InsertLeave setlocal formatoptions=tnroq if g:pandoc#formatting#smart_autoformat_on_cursormoved == 1 au CursorMovedI call pandoc#formatting#AutoFormat(0) endif augroup END endif endfunction function! pandoc#formatting#UseSoftWraps() abort "{{{1 " reset settings that might have been changed by UseHardWraps setlocal textwidth& setlocal formatoptions& setlocal formatlistpat& " soft wrapping setlocal wrap setlocal formatoptions=1n " Show partial wrapped lines setlocal display=lastline endfunction function! pandoc#formatting#IndentExpr() abort "{{{1 let l:cline = getline(v:lnum) let l:pline = getline(v:lnum - 1) let l:cline_li = matchstr(l:cline, '^\s*[*-:]\s*') if l:cline_li !=? '' return len(matchstr(l:cline_li, '^\s*')) endif let l:pline_li = matchstr(l:pline, '^\s*[*-:]\s\+') if l:pline_li !=? '' return len(l:pline_li) endif if l:pline ==? '' return indent(v:lnum) else return indent(v:lnum - 1) endif endfunction