diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2019-12-12 16:43:09 +0100 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2019-12-12 16:43:09 +0100 | 
| commit | cea0d08a062478503814e51aa21c6486a0dd1b21 (patch) | |
| tree | 085f856a71019a5f9046501b9f45116286726d51 | |
| parent | 43085dc02f34d7d54208e6e20989d4779bffe71c (diff) | |
| download | vim-polyglot-cea0d08a062478503814e51aa21c6486a0dd1b21.tar.gz vim-polyglot-cea0d08a062478503814e51aa21c6486a0dd1b21.zip | |
Replace markdown plugin for faster onev4.1.4
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | after/ftplugin/markdown.vim | 205 | ||||
| -rw-r--r-- | autoload/markdown.vim | 532 | ||||
| -rwxr-xr-x | build | 2 | ||||
| -rw-r--r-- | config.vim | 12 | ||||
| -rw-r--r-- | ftdetect/polyglot.vim | 23 | ||||
| -rw-r--r-- | ftplugin/markdown.vim | 903 | ||||
| -rw-r--r-- | indent/markdown.vim | 79 | ||||
| -rw-r--r-- | syntax/markdown.vim | 1085 | ||||
| -rw-r--r-- | syntax/markdown_jekyll.vim | 34 | 
10 files changed, 1671 insertions, 1206 deletions
| @@ -119,7 +119,7 @@ If you need full functionality of any plugin, please use it directly with your p  - [log](https://github.com/MTDL9/vim-log-highlighting) (syntax)  - [lua](https://github.com/tbastos/vim-lua) (syntax, indent)  - [mako](https://github.com/sophacles/vim-bundle-mako) (syntax, indent, ftplugin) -- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, indent, ftplugin) +- [markdown](https://github.com/gabrielelana/vim-markdown) (syntax, autoload, ftplugin)  - [mathematica](https://github.com/voldikss/vim-mma) (syntax, ftplugin)  - [mdx](https://github.com/jxnblk/vim-mdx-js) (syntax)  - [meson](https://github.com/mesonbuild/meson) (syntax, indent, ftplugin) diff --git a/after/ftplugin/markdown.vim b/after/ftplugin/markdown.vim deleted file mode 100644 index 1d1e410c..00000000 --- a/after/ftplugin/markdown.vim +++ /dev/null @@ -1,205 +0,0 @@ -if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1 - -" vim: ts=4 sw=4: -" folding for Markdown headers, both styles (atx- and setex-) -" http://daringfireball.net/projects/markdown/syntax#header -" -" this code can be placed in file -"   $HOME/.vim/after/ftplugin/markdown.vim -" -" original version from Steve Losh's gist: https://gist.github.com/1038710 - -function! s:is_mkdCode(lnum) -    let name = synIDattr(synID(a:lnum, 1, 0), 'name') -    return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)') -endfunction - -if get(g:, "vim_markdown_folding_style_pythonic", 0) -    function! Foldexpr_markdown(lnum) -        let l1 = getline(a:lnum) -        "~~~~~ keep track of fenced code blocks ~~~~~ -        "If we hit a code block fence -        if l1 =~ '````*' || l1 =~ '\~\~\~\~*' -            " toggle the variable that says if we're in a code block -            if b:fenced_block == 0 -                let b:fenced_block = 1 -            elseif b:fenced_block == 1 -                let b:fenced_block = 0 -            endif -        " else, if we're caring about front matter -        elseif g:vim_markdown_frontmatter == 1 -            " if we're in front matter and not on line 1 -            if b:front_matter == 1 && a:lnum > 2 -                let l0 = getline(a:lnum-1) -                " if the previous line fenced front matter -                if l0 == '---' -                    " we must not be in front matter -                    let b:front_matter = 0 -                endif -            " else, if we're on line one -            elseif a:lnum == 1 -                " if we hit a front matter fence -                if l1 == '---' -                    " we're in the front matter -                    let b:front_matter = 1 -                endif -            endif -        endif - -        " if we're in a code block or front matter -        if b:fenced_block == 1 || b:front_matter == 1 -            if a:lnum == 1 -                " fold any 'preamble' -                return '>1' -            else -                " keep previous foldlevel -                return '=' -            endif -        endif - -        let l2 = getline(a:lnum+1) -        " if the next line starts with two or more '=' -        " and is not code -        if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1) -            " next line is underlined (level 1) -            return '>0' -        " else, if the nex line starts with two or more '-' -        " and is not code -        elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1) -            " next line is underlined (level 2) -            return '>1' -        endif - -        "if we're on a non-code line starting with a pound sign -        if l1 =~ '^#' && !s:is_mkdCode(a:lnum) -            " set the fold level to the number of hashes -1 -            " return '>'.(matchend(l1, '^#\+') - 1) -            " set the fold level to the number of hashes -            return '>'.(matchend(l1, '^#\+')) -        " else, if we're on line 1 -        elseif a:lnum == 1 -            " fold any 'preamble' -            return '>1' -        else -            " keep previous foldlevel -            return '=' -        endif -    endfunction - -    function! Foldtext_markdown() -        let line = getline(v:foldstart) -        let has_numbers = &number || &relativenumber -        let nucolwidth = &fdc + has_numbers * &numberwidth -        let windowwidth = winwidth(0) - nucolwidth - 6 -        let foldedlinecount = v:foldend - v:foldstart -        let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount)) -        let line = substitute(line, '\%("""\|''''''\)', '', '') -        let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1 -        return line . ' ' . repeat("-", fillcharcount) . ' ' . foldedlinecount -    endfunction -else " vim_markdown_folding_style_pythonic == 0 -    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 -        elseif g:vim_markdown_frontmatter == 1 -            if b:front_matter == 1 -                if l0 == '---' -                    let b:front_matter = 0 -                endif -            elseif a:lnum == 2 -                if l0 == '---' -                    let b:front_matter = 1 -                endif -            endif -        endif - -        if b:fenced_block == 1 || b:front_matter == 1 -            " keep previous foldlevel -            return '=' -        endif - -        let l2 = getline(a:lnum+1) -        if  l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1) -            " next line is underlined (level 1) -            return '>1' -        elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1) -            " next line is underlined (level 2) -            if s:vim_markdown_folding_level >= 2 -                return '>1' -            else -                return '>2' -            endif -        endif - -        let l1 = getline(a:lnum) -        if l1 =~ '^#' && !s:is_mkdCode(a:lnum) -            " fold level according to option -            if s:vim_markdown_folding_level == 1 || matchend(l1, '^#\+') > s:vim_markdown_folding_level -                if a:lnum == line('$') -                    return matchend(l1, '^#\+') - 1 -                else -                    return -1 -                endif -            else -                " headers are not folded -                return 0 -            endif -        endif - -        if l0 =~ '^#' && !s:is_mkdCode(a:lnum-1) -            " previous line starts with hashes -            return '>'.matchend(l0, '^#\+') -        else -            " keep previous foldlevel -            return '=' -        endif -    endfunction -endif - - -let b:fenced_block = 0 -let b:front_matter = 0 -let s:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1) - -function! s:MarkdownSetupFolding() -    if !get(g:, "vim_markdown_folding_disabled", 0) -        if get(g:, "vim_markdown_folding_style_pythonic", 0) -            if get(g:, "vim_markdown_override_foldtext", 1) -                setlocal foldtext=Foldtext_markdown() -            endif -        endif -        setlocal foldexpr=Foldexpr_markdown(v:lnum) -        setlocal foldmethod=expr -    endif -endfunction - -function! s:MarkdownSetupFoldLevel() -    if get(g:, "vim_markdown_folding_style_pythonic", 0) -        " set default foldlevel -        execute "setlocal foldlevel=".s:vim_markdown_folding_level -    endif -endfunction - -call s:MarkdownSetupFoldLevel() -call s:MarkdownSetupFolding() - -augroup Mkd -    " These autocmds need to be kept in sync with the autocmds calling -    " s:MarkdownRefreshSyntax in ftplugin/markdown.vim. -    autocmd BufWinEnter,BufWritePost <buffer> call s:MarkdownSetupFolding() -    autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownSetupFolding() -    autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownSetupFolding() -augroup END - -endif diff --git a/autoload/markdown.vim b/autoload/markdown.vim new file mode 100644 index 00000000..3db667e1 --- /dev/null +++ b/autoload/markdown.vim @@ -0,0 +1,532 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1 + + +" {{{ FOLDING + +function! markdown#FoldLevelOfLine(lnum) +  let currentline = getline(a:lnum) +  let nextline = getline(a:lnum + 1) + +  " an empty line is not going to change the indentation level +  if match(currentline, '^\s*$') >= 0 +    return '=' +  endif + +  " folding lists +  if s:SyntaxGroupOfLineIs(a:lnum, '^markdownListItem') +    if s:SyntaxGroupOfLineIs(a:lnum - 1, '^markdownListItem') +      return 'a1' +    endif +    if s:SyntaxGroupOfLineIs(a:lnum + 1, '^markdownListItem') +      return 's1' +    endif +    return '=' +  endif + +  " we are not going to fold things inside list items, too hairy +  let is_inside_a_list_item = s:SyntaxGroupOfLineIs(a:lnum, '^markdownListItem') +  if is_inside_a_list_item +    return '=' +  endif + +  " folding atx headers +  if match(currentline, '^#\{1,6}\s') >= 0 +    let header_level = strlen(substitute(currentline, '^\(#\{1,6}\).*', '\1', '')) +    return '>' . header_level +  endif + +  " folding fenced code blocks +  let next_line_syntax_group = synIDattr(synID(a:lnum + 1, 1, 1), 'name') +  if match(currentline, '^\s*```') >= 0 +    if next_line_syntax_group ==# 'markdownFencedCodeBlock' +      return 'a1' +    endif +    return 's1' +  endif + +  " folding code blocks +  let current_line_syntax_group = synIDattr(synID(a:lnum, 1, 1), 'name') +  let prev_line_syntax_group = synIDattr(synID(a:lnum - 1, 1, 1), 'name') +  if match(currentline, '^\s\{4,}') >= 0 +    if current_line_syntax_group ==# 'markdownCodeBlock' +      if prev_line_syntax_group !=# 'markdownCodeBlock' +        return 'a1' +      endif +      if next_line_syntax_group !=# 'markdownCodeBlock' +        return 's1' +      endif +    endif +    return '=' +  endif + +  " folding setex headers +  if (match(currentline, '^.*$') >= 0) +    if (match(nextline, '^=\+$') >= 0) +      return '>1' +    endif +    if (match(nextline, '^-\+$') >= 0) +      return '>2' +    endif +  endif + +  return '=' +endfunction + +function! s:SyntaxGroupOfLineIs(lnum, pattern) +  let stack = synstack(a:lnum, a:cnum) +  if len(stack) > 0 +    return synIDattr(stack[0], 'name') =~# a:pattern +  endif +  return 0 +endfunction + +" }}} + +" {{{ EDIT + +function! markdown#EditBlock() range abort +  if exists('b:markdown_temporary_buffer') && b:markdown_temporary_buffer +    echo 'Sorry, you cannot edit a code block inside a temporary buffer' +    return +  endif +  " Github fenced code blocks like ```ruby +  let code_block = s:LocateFencedCodeBlock(a:firstline, +    \ '^\s*`\{3,}\(\w\+\)\%(\s.*$\|$\)', +    \ '^\s*`\{3,}\s*$' +    \ ) +  if code_block['from'] == 0 || code_block['to'] == 0 +    " Github fenced code blocks with metadata like ```{ruby, <WHATEVER>} +    let code_block = s:LocateFencedCodeBlock(a:firstline, +      \ '^\s*`\{3,}{\(\w\+\),[^}]\+}\%(\s.*$\|$\)', +      \ '^\s*`\{3,}\s*$' +      \ ) +  endif +  if code_block['from'] == 0 || code_block['to'] == 0 +    " Github fenced code blocks alternate style like ~~~ruby +    let code_block = s:LocateFencedCodeBlock(a:firstline, +      \ '^\s*\~\{3,}\(\w\+\)\%(\s.*$\|$\)', +      \ '^\s*\~\{3,}\s*$' +      \ ) +  endif +  if code_block['from'] == 0 || code_block['to'] == 0 +    " Liquid fenced code blocks {% highlight ruby %} +    " (since we support some liquid/jekyll tags, why not?) +    let code_block = s:LocateFencedCodeBlock(a:firstline, +      \ '^\s*{%\s*highlight\s\+\(\w\+\)\s*%}\%(\s.*$\|$\)', +      \ '^\s*{%\s*endhighlight\s*%}\%(\s.*$\|$\)' +      \ ) +  endif +  if code_block['from'] == 0 || code_block['to'] == 0 +    let code_block = s:LocateRangeBlock(a:firstline, a:lastline) +  endif +  if code_block['from'] == 0 || code_block['to'] == 0 +    echo 'Sorry, I did not find any suitable code block to edit or create' +    return +  endif + +  let code_block['file_extension'] = '.' . code_block['language'] +  if has_key(s:known_file_extensions, code_block['language']) +    let code_block['file_extension'] = s:known_file_extensions[code_block['language']] +  endif +  let code_block['file_path'] = tempname() . code_block['file_extension'] +  let code_block['content'] = getline(code_block['from'], code_block['to']) +  let code_block['content'] = s:UnindentBlock(code_block['content'], code_block['indentation']) + +  call writefile(code_block['content'], code_block['file_path']) +  augroup MarkdownReplaceEditedBlock +    autocmd BufEnter <buffer> call s:ReplaceEditedBlock() +  augroup END + +  let b:code_block = code_block +  execute 'split ' . code_block['file_path'] +  let b:markdown_temporary_buffer = 1 +  autocmd BufLeave <buffer> wq +endfunction + +function! s:ReplaceEditedBlock() +  augroup MarkdownReplaceEditedBlock +    autocmd! +  augroup END +  augroup! MarkdownReplaceEditedBlock + +  if b:code_block['to'] - b:code_block['from'] >= 0 +    execute b:code_block['from'] . ',' b:code_block['to'] . ' delete _' +  endif +  let content = readfile(b:code_block['file_path']) +  let content = s:IndentBlock(l:content, b:code_block['indentation']) +  let content = s:SurroundWithFencedCodeBlock(l:content, b:code_block) +  call append(b:code_block['from']-1, content) +  call setpos('.', b:code_block['back_to_position']) + +  execute 'silent bwipeout! ' . b:code_block['file_path'] +  call delete(b:code_block['file_path']) +  unlet! b:code_block +endfunction + +function! s:UnindentBlock(content, indentation) +  return map(a:content, 'substitute(v:val, ''^' . a:indentation . ''', '''', ''g'')') +endfunction + +function! s:IndentBlock(content, indentation) +  return map(a:content, 'substitute(v:val, ''^'', ''' . a:indentation . ''', ''g'')') +endfunction + +function! s:SurroundWithFencedCodeBlock(code, editing) +  if !a:editing['surround'] | return a:code | endif +  if a:editing['language'] =~# 'markdown' | return a:code | endif +  let before = +    \ (a:editing['make_room_before'] ? [''] : []) + +    \ [a:editing['indentation'] . '```' . a:editing['language']] +  let after = +    \ [a:editing['indentation'] . '```'] + +    \ (a:editing['make_room_after'] ? [''] : []) +  return l:before + a:code + l:after +endfunction + +function! s:LocateRangeBlock(from, to) +  " TODO: extract initialize_code_block +  let code_block = {'from': 0, 'to': 0, 'language': 'txt', 'indentation': '', 'surround': 0} +  if a:to >= a:from +    let code_block['from'] = a:from +    let code_block['to'] = a:to +    let code_block['back_to_position'] = getpos('.') +    let code_block['language'] = 'markdown' + +    if a:from == a:to && getline(a:from) =~ '^\s*$' +      let code_block['surround'] = 1 +      let code_block['make_room_before'] = getline(a:from - 1) !~ '^\s*$' +      let code_block['make_room_after'] = getline(a:to + 1) !~ '^\s*$' +      let code_block['language'] = input('filetype? (default: markdown) ', '', 'filetype') +      if code_block['language'] =~ '^\s*$' +        let code_block['language'] = 'markdown' +      endif +    endif +  endif +  return code_block +endfunction + +function! s:LocateFencedCodeBlock(starting_from, upper_delimiter, lower_delimiter) +  " TODO: extract initialize_code_block +  let code_block = {'from': 0, 'to': 0, 'language': 'txt', 'indentation': '', 'surround': 0} +  let initial_position = getpos('.') +  let search_position = copy(initial_position) +  let search_position[1] = a:starting_from +  let search_position[2] = 0 +  cal setpos('.', search_position) + +  let start_code_block_backward = search(a:upper_delimiter, 'cbnW') +  let end_code_block_backward = search(a:lower_delimiter, 'cbnW') +  let end_code_block_forward = search(a:lower_delimiter, 'cnW') + +  let found_code_block = +        \ start_code_block_backward > 0 && +        \ end_code_block_forward > 0 +  let between_two_code_blocks = +        \ start_code_block_backward < end_code_block_backward && +        \ end_code_block_backward <= a:starting_from +  let starting_inside_code_block = +        \ found_code_block && +        \ !between_two_code_blocks && +        \ start_code_block_backward <= a:starting_from && +        \ end_code_block_forward >= a:starting_from + +  if starting_inside_code_block +    let code_block['language'] = s:ExtractLanguage(start_code_block_backward, a:upper_delimiter) +    let code_block['indentation'] = s:ExtractIndentation(start_code_block_backward) +    let code_block['back_to_position'] = initial_position +    let code_block['back_to_position'][1] = start_code_block_backward +    let code_block['back_to_position'][2] = 0 +    let code_block['from'] = start_code_block_backward + 1 +    let code_block['to'] = end_code_block_forward - 1 +  endif +  return code_block +endfunction + +function! s:ExtractLanguage(start_at, upper_delimiter) +  return substitute(getline(a:start_at), a:upper_delimiter, '\1', '') +endfunction + +function! s:ExtractIndentation(start_at) +  return substitute(getline(a:start_at), '\(^\s*\).\+$', '\1', '') +endfunction + +let s:known_file_extensions = { +  \ 'abap': '.abap', +  \ 'antlr': '.g4', +  \ 'asp': '.asp', +  \ 'ats': '.dats', +  \ 'actionscript': '.as', +  \ 'ada': '.adb', +  \ 'agda': '.agda', +  \ 'apacheconf': '.apacheconf', +  \ 'apex': '.cls', +  \ 'applescript': '.applescript', +  \ 'arc': '.arc', +  \ 'arduino': '.ino', +  \ 'asciidoc': '.asciidoc', +  \ 'assembly': '.asm', +  \ 'augeas': '.aug', +  \ 'autohotkey': '.ahk', +  \ 'autoit': '.au3', +  \ 'awk': '.awk', +  \ 'batchfile': '.bat', +  \ 'befunge': '.befunge', +  \ 'blitzbasic': '.bb', +  \ 'blitzmax': '.bmx', +  \ 'bluespec': '.bsv', +  \ 'boo': '.boo', +  \ 'brainfuck': '.b', +  \ 'brightscript': '.brs', +  \ 'bro': '.bro', +  \ 'c': '.c', +  \ 'c++': '.cpp', +  \ 'cpp': '.cpp', +  \ 'clips': '.clp', +  \ 'cmake': '.cmake', +  \ 'cobol': '.cob', +  \ 'css': '.css', +  \ 'ceylon': '.ceylon', +  \ 'chuck': '.ck', +  \ 'cirru': '.cirru', +  \ 'clean': '.icl', +  \ 'clojure': '.clj', +  \ 'coffeescript': '.coffee', +  \ 'coldfusion': '.cfm', +  \ 'coq': '.coq', +  \ 'creole': '.creole', +  \ 'crystal': '.cr', +  \ 'cucumber': '.feature', +  \ 'cuda': '.cu', +  \ 'cython': '.pyx', +  \ 'd': '.d', +  \ 'dm': '.dm', +  \ 'dot': '.dot', +  \ 'dart': '.dart', +  \ 'diff': '.diff', +  \ 'dylan': '.dylan', +  \ 'ecl': '.ecl', +  \ 'eiffel': '.e', +  \ 'elixir': '.ex', +  \ 'elm': '.elm', +  \ 'erlang': '.erl', +  \ 'flux': '.fx', +  \ 'fortran': '.f90', +  \ 'factor': '.factor', +  \ 'fancy': '.fy', +  \ 'fantom': '.fan', +  \ 'forth': '.fth', +  \ 'gas': '.s', +  \ 'glsl': '.glsl', +  \ 'genshi': '.kid', +  \ 'glyph': '.glf', +  \ 'go': '.go', +  \ 'gosu': '.gs', +  \ 'groff': '.man', +  \ 'groovy': '.groovy', +  \ 'html': '.html', +  \ 'http': '.http', +  \ 'haml': '.haml', +  \ 'handlebars': '.handlebars', +  \ 'harbour': '.hb', +  \ 'haskell': '.hs', +  \ 'haxe': '.hx', +  \ 'hy': '.hy', +  \ 'idl': '.pro', +  \ 'ini': '.ini', +  \ 'idris': '.idr', +  \ 'io': '.io', +  \ 'ioke': '.ik', +  \ 'j': '.ijs', +  \ 'json': '.json', +  \ 'json5': '.json5', +  \ 'jsonld': '.jsonld', +  \ 'jade': '.jade', +  \ 'java': '.java', +  \ 'javascript': '.js', +  \ 'julia': '.jl', +  \ 'krl': '.krl', +  \ 'kotlin': '.kt', +  \ 'lfe': '.lfe', +  \ 'llvm': '.ll', +  \ 'lasso': '.lasso', +  \ 'less': '.less', +  \ 'lilypond': '.ly', +  \ 'livescript': '.ls', +  \ 'logos': '.xm', +  \ 'logtalk': '.lgt', +  \ 'lua': '.lua', +  \ 'm': '.mumps', +  \ 'makefile': '.mak', +  \ 'mako': '.mako', +  \ 'markdown': '.md', +  \ 'mask': '.mask', +  \ 'matlab': '.matlab', +  \ 'max': '.maxpat', +  \ 'mediawiki': '.mediawiki', +  \ 'mirah': '.druby', +  \ 'monkey': '.monkey', +  \ 'moocode': '.moo', +  \ 'moonscript': '.moon', +  \ 'myghty': '.myt', +  \ 'nsis': '.nsi', +  \ 'nemerle': '.n', +  \ 'netlogo': '.nlogo', +  \ 'nginx': '.nginxconf', +  \ 'nimrod': '.nim', +  \ 'nu': '.nu', +  \ 'numpy': '.numpy', +  \ 'ocaml': '.ml', +  \ 'objdump': '.objdump', +  \ 'omgrofl': '.omgrofl', +  \ 'opa': '.opa', +  \ 'opencl': '.cl', +  \ 'org': '.org', +  \ 'oxygene': '.oxygene', +  \ 'pawn': '.pwn', +  \ 'php': '.php', +  \ 'parrot': '.parrot', +  \ 'pascal': '.pas', +  \ 'perl': '.pl', +  \ 'perl6': '.p6', +  \ 'pike': '.pike', +  \ 'pod': '.pod', +  \ 'pogoscript': '.pogo', +  \ 'postscript': '.ps', +  \ 'powershell': '.ps1', +  \ 'processing': '.pde', +  \ 'prolog': '.prolog', +  \ 'puppet': '.pp', +  \ 'python': '.py', +  \ 'qml': '.qml', +  \ 'r': '.r', +  \ 'rdoc': '.rdoc', +  \ 'realbasic': '.rbbas', +  \ 'rhtml': '.rhtml', +  \ 'rmarkdown': '.rmd', +  \ 'racket': '.rkt', +  \ 'rebol': '.rebol', +  \ 'redcode': '.cw', +  \ 'robotframework': '.robot', +  \ 'rouge': '.rg', +  \ 'ruby': '.rb', +  \ 'rust': '.rs', +  \ 'scss': '.scss', +  \ 'sql': '.sql', +  \ 'sage': '.sage', +  \ 'sass': '.sass', +  \ 'scala': '.scala', +  \ 'scaml': '.scaml', +  \ 'scheme': '.scm', +  \ 'scilab': '.sci', +  \ 'self': '.self', +  \ 'shell': '.sh', +  \ 'shen': '.shen', +  \ 'slash': '.sl', +  \ 'smalltalk': '.st', +  \ 'smarty': '.tpl', +  \ 'squirrel': '.nut', +  \ 'stylus': '.styl', +  \ 'supercollider': '.scd', +  \ 'toml': '.toml', +  \ 'txl': '.txl', +  \ 'tcl': '.tcl', +  \ 'tcsh': '.tcsh', +  \ 'tex': '.tex', +  \ 'tea': '.tea', +  \ 'textile': '.textile', +  \ 'turing': '.t', +  \ 'twig': '.twig', +  \ 'typescript': '.ts', +  \ 'unrealscript': '.uc', +  \ 'vhdl': '.vhdl', +  \ 'vala': '.vala', +  \ 'verilog': '.v', +  \ 'viml': '.vim', +  \ 'volt': '.volt', +  \ 'xc': '.xc', +  \ 'xml': '.xml', +  \ 'xproc': '.xpl', +  \ 'xquery': '.xquery', +  \ 'xs': '.xs', +  \ 'xslt': '.xslt', +  \ 'xtend': '.xtend', +  \ 'yaml': '.yml', +  \ 'ec': '.ec', +  \ 'edn': '.edn', +  \ 'fish': '.fish', +  \ 'mupad': '.mu', +  \ 'nesc': '.nc', +  \ 'ooc': '.ooc', +  \ 'restructuredtext': '.rst', +  \ 'wisp': '.wisp', +  \ 'xbase': '.prg', +\ } + +" }}} + +" {{{ FORMAT +function! markdown#FormatTable() +  let p = '^\s*|\s.*\s|\s*$' +  if exists(':Tabularize') && getline('.') =~# '^\s*|' && (getline(line('.')-1) =~# p || getline(line('.')+1) =~# p) +    let column = strlen(substitute(getline('.')[0:col('.')],'[^|]','','g')) +    let position = strlen(matchstr(getline('.')[0:col('.')],'.*|\s*\zs.*')) +    let separator_line_number = search('^\s*|\s*-\{3,}', 'cbnW') + +    call s:ShrinkTableHeaderSeparator(separator_line_number) +    Tabularize/|/l1 +    call s:ExpandTableHeaderSeparator(separator_line_number) +    normal! 0 + +    call search(repeat('[^|]*|',column).'\s\{-\}'.repeat('.',position),'ce',line('.')) +  endif +endfunction + +function! s:ShrinkTableHeaderSeparator(separator_line_number) +  if a:separator_line_number > 0 +    let separator_line = getline(a:separator_line_number) +    let separator_line = substitute(separator_line, '-\+', '---', 'g') +    call setline(a:separator_line_number, separator_line) +  endif +endfunction + +function! s:ExpandTableHeaderSeparator(separator_line_number) +  if a:separator_line_number > 0 +    let separator_line = getline(a:separator_line_number) +    let separator_line = substitute( +      \ separator_line, +      \ '|\([^|]*\)', +      \ '\="| " . repeat("-", strlen(submatch(1)) - 2) . " "', +      \ 'g') +    let separator_line = substitute(separator_line, '\s*$', '', '') +    call setline(a:separator_line_number, separator_line) +  endif +endfunction +" }}} + +" {{{ SWITCH STATUS +function! markdown#SwitchStatus() +  let current_line = getline('.') +  if match(current_line, '^\s*[*\-+] \[ \]') >= 0 +    call setline('.', substitute(current_line, '^\(\s*[*\-+]\) \[ \]', '\1 [x]', '')) +    return +  endif +  if match(current_line, '^\s*[*\-+] \[x\]') >= 0 +    call setline('.', substitute(current_line, '^\(\s*[*\-+]\) \[x\]', '\1', '')) +    return +  endif +  if match(current_line, '^\s*[*\-+] \(\[[x ]\]\)\@!') >= 0 +    call setline('.', substitute(current_line, '^\(\s*[*\-+]\)', '\1 [ ]', '')) +    return +  endif +  if match(current_line, '^\s*#\{1,5}\s') >= 0 +    call setline('.', substitute(current_line, '^\(\s*#\{1,5}\) \(.*$\)', '\1# \2', '')) +    return +  endif +  if match(current_line, '^\s*#\{6}\s') >= 0 +    call setline('.', substitute(current_line, '^\(\s*\)#\{6} \(.*$\)', '\1# \2', '')) +    return +  endif +endfunction +" }}} + +endif @@ -233,7 +233,7 @@ PACKS="    log:MTDL9/vim-log-highlighting    lua:tbastos/vim-lua    mako:sophacles/vim-bundle-mako -  markdown:plasticboy/vim-markdown +  markdown:gabrielelana/vim-markdown    mathematica:voldikss/vim-mma    mdx:jxnblk/vim-mdx-js    meson:mesonbuild/meson:_ALL:/data/syntax-highlighting/vim/ @@ -1,3 +1,15 @@ +if !exists('g:markdown_enable_spell_checking') +  let g:markdown_enable_spell_checking = 0 +end + +if !exists('g:markdown_enable_input_abbreviations') +  let g:markdown_enable_input_abbreviations = 0 +end + +if !exists('g:markdown_enable_mappings') +  let g:markdown_enable_mappings = 0 +end +  " Enable jsx syntax by default  if !exists('g:jsx_ext_required')    let g:jsx_ext_required = 0 diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 5ab23e80..480ea023 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -1,3 +1,15 @@ +if !exists('g:markdown_enable_spell_checking') +  let g:markdown_enable_spell_checking = 0 +end + +if !exists('g:markdown_enable_input_abbreviations') +  let g:markdown_enable_input_abbreviations = 0 +end + +if !exists('g:markdown_enable_mappings') +  let g:markdown_enable_mappings = 0 +end +  " Enable jsx syntax by default  if !exists('g:jsx_ext_required')    let g:jsx_ext_required = 0 @@ -781,15 +793,8 @@ endif  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1    augroup filetypedetect -  " markdown, from markdown.vim in plasticboy/vim-markdown -if !has('patch-7.4.480') -    " Before this patch, vim used modula2 for .md. -    au! filetypedetect BufRead,BufNewFile *.md -endif - -" markdown filetype file -au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} setfiletype markdown -au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn}.{des3,des,bf,bfa,aes,idea,cast,rc2,rc4,rc5,desx} setfiletype markdown +  " markdown, from markdown.vim in gabrielelana/vim-markdown +au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} set filetype=markdown    augroup end  endif diff --git a/ftplugin/markdown.vim b/ftplugin/markdown.vim index 43c9773a..8d327f61 100644 --- a/ftplugin/markdown.vim +++ b/ftplugin/markdown.vim @@ -1,795 +1,202 @@  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1 -"TODO print messages when on visual mode. I only see VISUAL, not the messages. - -" Function interface phylosophy: -" -" - functions take arbitrary line numbers as parameters. -"    Current cursor line is only a suitable default parameter. -" -" - only functions that bind directly to user actions: -" -"    - print error messages. -"       All intermediate functions limit themselves return `0` to indicate an error. -" -"    - move the cursor. All other functions do not move the cursor. -" -" This is how you should view headers for the header mappings: -" -"   |BUFFER -"   | -"   |Outside any header -"   | -" a-+# a -"   | -"   |Inside a -"   | -" a-+ -" b-+## b -"   | -"   |inside b -"   | -" b-+ -" c-+### c -"   | -"   |Inside c -"   | -" c-+ -" d-|# d -"   | -"   |Inside d -"   | -" d-+ -" e-|e -"   |==== -"   | -"   |Inside e -"   | -" e-+ - -" For each level, contains the regexp that matches at that level only. -" -let s:levelRegexpDict = { -    \ 1: '\v^(#[^#]@=|.+\n\=+$)', -    \ 2: '\v^(##[^#]@=|.+\n-+$)', -    \ 3: '\v^###[^#]@=', -    \ 4: '\v^####[^#]@=', -    \ 5: '\v^#####[^#]@=', -    \ 6: '\v^######[^#]@=' -\ } - -" Maches any header level of any type. -" -" This could be deduced from `s:levelRegexpDict`, but it is more -" efficient to have a single regexp for this. -" -let s:headersRegexp = '\v^(#|.+\n(\=+|-+)$)' - -" Returns the line number of the first header before `line`, called the -" current header. -" -" If there is no current header, return `0`. -" -" @param a:1 The line to look the header of. Default value: `getpos('.')`. -" -function! s:GetHeaderLineNum(...) -    if a:0 == 0 -        let l:l = line('.') -    else -        let l:l = a:1 -    endif -    while(l:l > 0) -        if join(getline(l:l, l:l + 1), "\n") =~ s:headersRegexp -            return l:l -        endif -        let l:l -= 1 -    endwhile -    return 0 -endfunction +if exists('b:did_ftplugin') | finish | endif -" -  if inside a header goes to it. -"    Return its line number. -" -" -  if on top level outside any headers, -"    print a warning -"    Return `0`. -" -function! s:MoveToCurHeader() -    let l:lineNum = s:GetHeaderLineNum() -    if l:lineNum != 0 -        call cursor(l:lineNum, 1) -    else -        echo 'outside any header' -        "normal! gg -    endif -    return l:lineNum -endfunction +" {{{ CONFIGURATION -" Move cursor to next header of any level. -" -" If there are no more headers, print a warning. -" -function! s:MoveToNextHeader() -    if search(s:headersRegexp, 'W') == 0 -        "normal! G -        echo 'no next header' -    endif -endfunction +if !exists('g:markdown_flavor') +  let g:markdown_flavor = 'github' +endif -" Move cursor to previous header (before current) of any level. -" -" If it does not exist, print a warning. -" -function! s:MoveToPreviousHeader() -    let l:curHeaderLineNumber = s:GetHeaderLineNum() -    let l:noPreviousHeader = 0 -    if l:curHeaderLineNumber <= 1 -        let l:noPreviousHeader = 1 -    else -        let l:previousHeaderLineNumber = s:GetHeaderLineNum(l:curHeaderLineNumber - 1) -        if l:previousHeaderLineNumber == 0 -            let l:noPreviousHeader = 1 -        else -            call cursor(l:previousHeaderLineNumber, 1) -        endif -    endif -    if l:noPreviousHeader -        echo 'no previous header' -    endif -endfunction +if !exists('g:markdown_enable_folding') +  let g:markdown_enable_folding = 0 +endif -" - if line is inside a header, return the header level (h1 -> 1, h2 -> 2, etc.). -" -" - if line is at top level outside any headers, return `0`. -" -function! s:GetHeaderLevel(...) -    if a:0 == 0 -        let l:line = line('.') -    else -        let l:line = a:1 -    endif -    let l:linenum = s:GetHeaderLineNum(l:line) -    if l:linenum != 0 -        return s:GetLevelOfHeaderAtLine(l:linenum) -    else -        return 0 -    endif -endfunction +if !exists('g:markdown_enable_mappings') +  " make it compatible with previous configuration value +  if exists('g:markdown_include_default_mappings') +    let g:markdown_enable_mappings = g:markdown_include_default_mappings +  else +    let g:markdown_enable_mappings = 1 +  endif +endif -" Returns the level of the header at the given line. -" -" If there is no header at the given line, returns `0`. -" -function! s:GetLevelOfHeaderAtLine(linenum) -    let l:lines = join(getline(a:linenum, a:linenum + 1), "\n") -    for l:key in keys(s:levelRegexpDict) -        if l:lines =~ get(s:levelRegexpDict, l:key) -            return l:key -        endif -    endfor -    return 0 -endfunction +if !exists('g:markdown_enable_insert_mode_mappings') +  " make it compatible with previous configuration value +  if exists('g:markdown_include_insert_mode_default_mappings') +    let g:markdown_enable_insert_mode_mappings = g:markdown_include_insert_mode_default_mappings +  else +    let g:markdown_enable_insert_mode_mappings = 1 +  endif +endif -" Move cursor to parent header of the current header. -" -" If it does not exit, print a warning and do nothing. -" -function! s:MoveToParentHeader() -    let l:linenum = s:GetParentHeaderLineNumber() -    if l:linenum != 0 -        call cursor(l:linenum, 1) -    else -        echo 'no parent header' -    endif -endfunction +if !exists('g:markdown_enable_insert_mode_leader_mappings') +    let g:markdown_enable_insert_mode_leader_mappings = 0 +endif -" Return the line number of the parent header of line `line`. -" -" If it has no parent, return `0`. -" -function! s:GetParentHeaderLineNumber(...) -    if a:0 == 0 -        let l:line = line('.') -    else -        let l:line = a:1 -    endif -    let l:level = s:GetHeaderLevel(l:line) -    if l:level > 1 -        let l:linenum = s:GetPreviousHeaderLineNumberAtLevel(l:level - 1, l:line) -        return l:linenum -    endif -    return 0 -endfunction +if !exists('g:markdown_drop_empty_blockquotes') +    let g:markdown_drop_empty_blockquotes = 0 +endif -" Return the line number of the previous header of given level. -" in relation to line `a:1`. If not given, `a:1 = getline()` -" -" `a:1` line is included, and this may return the current header. -" -" If none return 0. -" -function! s:GetNextHeaderLineNumberAtLevel(level, ...) -    if a:0 < 1 -        let l:line = line('.') -    else -        let l:line = a:1 -    endif -    let l:l = l:line -    while(l:l <= line('$')) -        if join(getline(l:l, l:l + 1), "\n") =~ get(s:levelRegexpDict, a:level) -            return l:l -        endif -        let l:l += 1 -    endwhile -    return 0 -endfunction +if !exists('g:markdown_mapping_switch_status') +  let g:markdown_mapping_switch_status = '<space>' +endif -" Return the line number of the previous header of given level. -" in relation to line `a:1`. If not given, `a:1 = getline()` -" -" `a:1` line is included, and this may return the current header. -" -" If none return 0. -" -function! s:GetPreviousHeaderLineNumberAtLevel(level, ...) -    if a:0 == 0 -        let l:line = line('.') -    else -        let l:line = a:1 -    endif -    let l:l = l:line -    while(l:l > 0) -        if join(getline(l:l, l:l + 1), "\n") =~ get(s:levelRegexpDict, a:level) -            return l:l -        endif -        let l:l -= 1 -    endwhile -    return 0 -endfunction +if !exists('g:markdown_enable_spell_checking') +  let g:markdown_enable_spell_checking = 1 +endif -" Move cursor to next sibling header. -" -" If there is no next siblings, print a warning and don't move. -" -function! s:MoveToNextSiblingHeader() -    let l:curHeaderLineNumber = s:GetHeaderLineNum() -    let l:curHeaderLevel = s:GetLevelOfHeaderAtLine(l:curHeaderLineNumber) -    let l:curHeaderParentLineNumber = s:GetParentHeaderLineNumber() -    let l:nextHeaderSameLevelLineNumber = s:GetNextHeaderLineNumberAtLevel(l:curHeaderLevel, l:curHeaderLineNumber + 1) -    let l:noNextSibling = 0 -    if l:nextHeaderSameLevelLineNumber == 0 -        let l:noNextSibling = 1 -    else -        let l:nextHeaderSameLevelParentLineNumber = s:GetParentHeaderLineNumber(l:nextHeaderSameLevelLineNumber) -        if l:curHeaderParentLineNumber == l:nextHeaderSameLevelParentLineNumber -            call cursor(l:nextHeaderSameLevelLineNumber, 1) -        else -            let l:noNextSibling = 1 -        endif -    endif -    if l:noNextSibling -        echo 'no next sibling header' -    endif -endfunction +if !exists('g:markdown_enable_input_abbreviations') +  let g:markdown_enable_input_abbreviations = 1 +endif -" Move cursor to previous sibling header. -" -" If there is no previous siblings, print a warning and do nothing. -" -function! s:MoveToPreviousSiblingHeader() -    let l:curHeaderLineNumber = s:GetHeaderLineNum() -    let l:curHeaderLevel = s:GetLevelOfHeaderAtLine(l:curHeaderLineNumber) -    let l:curHeaderParentLineNumber = s:GetParentHeaderLineNumber() -    let l:previousHeaderSameLevelLineNumber = s:GetPreviousHeaderLineNumberAtLevel(l:curHeaderLevel, l:curHeaderLineNumber - 1) -    let l:noPreviousSibling = 0 -    if l:previousHeaderSameLevelLineNumber == 0 -        let l:noPreviousSibling = 1 -    else -        let l:previousHeaderSameLevelParentLineNumber = s:GetParentHeaderLineNumber(l:previousHeaderSameLevelLineNumber) -        if l:curHeaderParentLineNumber == l:previousHeaderSameLevelParentLineNumber -            call cursor(l:previousHeaderSameLevelLineNumber, 1) -        else -            let l:noPreviousSibling = 1 -        endif -    endif -    if l:noPreviousSibling -        echo 'no previous sibling header' -    endif -endfunction +" }}} -function! s:Toc(...) -    if a:0 > 0 -        let l:window_type = a:1 -    else -        let l:window_type = 'vertical' -    endif +" {{{ OPTIONS -    let l:bufnr = bufnr('%') -    let l:cursor_line = line('.') -    let l:cursor_header = 0 -    let l:fenced_block = 0 -    let l:front_matter = 0 -    let l:header_list = [] -    let l:header_max_len = 0 -    let l:vim_markdown_toc_autofit = get(g:, "vim_markdown_toc_autofit", 0) -    let l:vim_markdown_frontmatter = get(g:, "vim_markdown_frontmatter", 0) -    for i in range(1, line('$')) -        let l:lineraw = getline(i) -        let l:l1 = getline(i+1) -        let l:line = substitute(l:lineraw, "#", "\\\#", "g") -        if l:line =~ '````*' || l:line =~ '\~\~\~\~*' -            if l:fenced_block == 0 -                let l:fenced_block = 1 -            elseif l:fenced_block == 1 -                let l:fenced_block = 0 -            endif -        elseif l:vim_markdown_frontmatter == 1 -            if l:front_matter == 1 -                if l:line == '---' -                    let l:front_matter = 0 -                endif -            elseif i == 1 -                if l:line == '---' -                    let l:front_matter = 1 -                endif -            endif -        endif -        if l:line =~ '^#\+' || (l:l1 =~ '^=\+\s*$' || l:l1 =~ '^-\+\s*$') && l:line =~ '^\S' -            let l:is_header = 1 -        else -            let l:is_header = 0 -        endif -        if l:is_header == 1 && l:fenced_block == 0 && l:front_matter == 0 -            " append line to location list -            let l:item = {'lnum': i, 'text': l:line, 'valid': 1, 'bufnr': l:bufnr, 'col': 1} -            let l:header_list = l:header_list + [l:item] -            " set header number of the cursor position -            if l:cursor_header == 0 -                if i == l:cursor_line -                    let l:cursor_header = len(l:header_list) -                elseif i > l:cursor_line -                    let l:cursor_header = len(l:header_list) - 1 -                endif -            endif -            " keep track of the longest header size (heading level + title) -            let l:total_len = stridx(l:line, ' ') + strdisplaywidth(l:line) -            if l:total_len > l:header_max_len -                let l:header_max_len = l:total_len -            endif -        endif -    endfor -    call setloclist(0, l:header_list) -    if len(l:header_list) == 0 -        echom "Toc: No headers." -        return -    endif +setlocal textwidth=0 +setlocal ts=2 sw=2 expandtab smarttab +setlocal comments=b:*,b:-,b:+,n:>,se:``` commentstring=>\ %s +setlocal formatoptions=tron +setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\\|^\\s*[+-\\*]\\s\\+ +setlocal nolisp +setlocal autoindent + +" Enable spelling and completion based on dictionary words +if &spelllang !~# '^\s*$' && g:markdown_enable_spell_checking +  setlocal spell +endif + +" Custom dictionary for emoji +execute 'setlocal dictionary+=' . shellescape(expand('<sfile>:p:h:h')) . '/dict/emoticons.dict' +setlocal iskeyword+=:,+,- +setlocal complete+=k + +if g:markdown_enable_input_abbreviations +  " Replace common ascii emoticons with supported emoji +  iabbrev <buffer> :-) :smile: +  iabbrev <buffer> :-D :laughing: +  iabbrev <buffer> :-( :disappointed: + +  " Replace common punctuation +  iabbrev <buffer> ... … +  iabbrev <buffer> << « +  iabbrev <buffer> >> » +endif + +" Folding +if g:markdown_enable_folding +  setlocal foldmethod=expr +  setlocal foldexpr=markdown#FoldLevelOfLine(v:lnum) +endif + +" }}} -    if l:window_type ==# 'horizontal' -        lopen -    elseif l:window_type ==# 'vertical' -        vertical lopen -        " auto-fit toc window when possible to shrink it -        if (&columns/2) > l:header_max_len && l:vim_markdown_toc_autofit == 1 -            execute 'vertical resize ' . (l:header_max_len + 1) -        else -            execute 'vertical resize ' . (&columns/2) -        endif -    elseif l:window_type ==# 'tab' -        tab lopen -    else -        lopen -    endif -    setlocal modifiable -    for i in range(1, line('$')) -        " this is the location-list data for the current item -        let d = getloclist(0)[i-1] -        " atx headers -        if match(d.text, "^#") > -1 -            let l:level = len(matchstr(d.text, '#*', 'g'))-1 -            let d.text = substitute(d.text, '\v^#*[ ]*', '', '') -            let d.text = substitute(d.text, '\v[ ]*#*$', '', '') -        " setex headers -        else -            let l:next_line = getbufline(d.bufnr, d.lnum+1) -            if match(l:next_line, "=") > -1 -                let l:level = 0 -            elseif match(l:next_line, "-") > -1 -                let l:level = 1 -            endif -        endif -        call setline(i, repeat('  ', l:level). d.text) -    endfor -    setlocal nomodified -    setlocal nomodifiable -    execute 'normal! ' . l:cursor_header . 'G' -endfunction -" Convert Setex headers in range `line1 .. line2` to Atx. -" -" Return the number of conversions. -" -function! s:SetexToAtx(line1, line2) -    let l:originalNumLines = line('$') -    execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n\=+$/# \1/' -    execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n-+$/## \1/' -    return l:originalNumLines - line('$') +" {{{ FUNCTIONS + +function! s:JumpToHeader(forward, visual) +  let cnt = v:count1 +  let save = @/ +  let pattern = '\v^#{1,6}.*$|^.+\n%(\-+|\=+)$' +  if a:visual +    normal! gv +  endif +  if a:forward +    let motion = '/' . pattern +  else +    let motion = '?' . pattern +  endif +  while cnt > 0 +	  silent! execute motion +	  let cnt = cnt - 1 +  endwhile +  call histdel('/', -1) +  let @/ = save  endfunction -" If `a:1` is 0, decrease the level of all headers in range `line1 .. line2`. -" -" Otherwise, increase the level. `a:1` defaults to `0`. -" -function! s:HeaderDecrease(line1, line2, ...) -    if a:0 > 0 -        let l:increase = a:1 +function! s:Indent(indent) +  if getline('.') =~ '\v^\s*%([-*+]|\d\.)\s*$' +    if a:indent +      normal >>      else -        let l:increase = 0 +      normal <<      endif -    if l:increase -        let l:forbiddenLevel = 6 -        let l:replaceLevels = [5, 1] -        let l:levelDelta = 1 +    call setline('.', substitute(getline('.'), '\([-*+]\|\d\.\)\s*$', '\1 ', '')) +    normal $ +  elseif getline('.') =~ '\v^\s*(\s?\>)+\s*$' +    if a:indent +      call setline('.', substitute(getline('.'), '>\s*$', '>> ', ''))      else -        let l:forbiddenLevel = 1 -        let l:replaceLevels = [2, 6] -        let l:levelDelta = -1 +      call setline('.', substitute(getline('.'), '\s*>\s*$', ' ', '')) +      call setline('.', substitute(getline('.'), '^\s\+$', '', ''))      endif -    for l:line in range(a:line1, a:line2) -        if join(getline(l:line, l:line + 1), "\n") =~ s:levelRegexpDict[l:forbiddenLevel] -            echomsg 'There is an h' . l:forbiddenLevel . ' at line ' . l:line . '. Aborting.' -            return -        endif -    endfor -    let l:numSubstitutions = s:SetexToAtx(a:line1, a:line2) -    let l:flags = (&gdefault ? '' : 'g') -    for l:level in range(replaceLevels[0], replaceLevels[1], -l:levelDelta) -        execute 'silent! ' . a:line1 . ',' . (a:line2 - l:numSubstitutions) . 'substitute/' . s:levelRegexpDict[l:level] . '/' . repeat('#', l:level + l:levelDelta) . '/' . l:flags -    endfor -endfunction - -" Format table under cursor. -" -" Depends on Tabularize. -" -function! s:TableFormat() -    let l:pos = getpos('.') -    normal! { -    " Search instead of `normal! j` because of the table at beginning of file edge case. -    call search('|') -    normal! j -    " Remove everything that is not a pipe, colon or hyphen next to a colon othewise -    " well formated tables would grow because of addition of 2 spaces on the separator -    " line by Tabularize /|. -    let l:flags = (&gdefault ? '' : 'g') -    execute 's/\(:\@<!-:\@!\|[^|:-]\)//e' . l:flags -    execute 's/--/-/e' . l:flags -    Tabularize /| -    " Move colons for alignment to left or right side of the cell. -    execute 's/:\( \+\)|/\1:|/e' . l:flags -    execute 's/|\( \+\):/|:\1/e' . l:flags -    execute 's/ /-/' . l:flags -    call setpos('.', l:pos) +    normal $ +  endif  endfunction -" Wrapper to do move commands in visual mode. -" -function! s:VisMove(f) -    norm! gv -    call function(a:f)() +function! s:IsAnEmptyListItem() +  return getline('.') =~ '\v^\s*%([-*+]|\d\.)\s*$'  endfunction -" Map in both normal and visual modes. -" -function! s:MapNormVis(rhs,lhs) -    execute 'nn <buffer><silent> ' . a:rhs . ' :call ' . a:lhs . '()<cr>' -    execute 'vn <buffer><silent> ' . a:rhs . ' <esc>:call <sid>VisMove(''' . a:lhs . ''')<cr>' +function! s:IsAnEmptyQuote() +  return getline('.') =~ '\v^\s*(\s?\>)+\s*$'  endfunction -" Parameters: -" -" - step +1 for right, -1 for left -" -" TODO: multiple lines. -" -function! s:FindCornerOfSyntax(lnum, col, step) -    let l:col = a:col -    let l:syn = synIDattr(synID(a:lnum, l:col, 1), 'name') -    while synIDattr(synID(a:lnum, l:col, 1), 'name') ==# l:syn -        let l:col += a:step -    endwhile -    return l:col - a:step -endfunction - -" Return the next position of the given syntax name, -" inclusive on the given position. -" -" TODO: multiple lines -" -function! s:FindNextSyntax(lnum, col, name) -    let l:col = a:col -    let l:step = 1 -    while synIDattr(synID(a:lnum, l:col, 1), 'name') !=# a:name -        let l:col += l:step -    endwhile -    return [a:lnum, l:col] -endfunction +" }}} -function! s:FindCornersOfSyntax(lnum, col) -    return [<sid>FindLeftOfSyntax(a:lnum, a:col), <sid>FindRightOfSyntax(a:lnum, a:col)] -endfunction -function! s:FindRightOfSyntax(lnum, col) -    return <sid>FindCornerOfSyntax(a:lnum, a:col, 1) -endfunction +" {{{ MAPPINGS -function! s:FindLeftOfSyntax(lnum, col) -    return <sid>FindCornerOfSyntax(a:lnum, a:col, -1) -endfunction +" Commands +command! -nargs=0 -range MarkdownEditBlock :<line1>,<line2>call markdown#EditBlock() -" Returns: -" -" - a string with the the URL for the link under the cursor -" - an empty string if the cursor is not on a link -" -" TODO -" -" - multiline support -" - give an error if the separator does is not on a link -" -function! s:Markdown_GetUrlForPosition(lnum, col) -    let l:lnum = a:lnum -    let l:col = a:col -    let l:syn = synIDattr(synID(l:lnum, l:col, 1), 'name') - -    if l:syn ==# 'mkdInlineURL' || l:syn ==# 'mkdURL' || l:syn ==# 'mkdLinkDefTarget' -        " Do nothing. -    elseif l:syn ==# 'mkdLink' -        let [l:lnum, l:col] = <sid>FindNextSyntax(l:lnum, l:col, 'mkdURL') -        let l:syn = 'mkdURL' -    elseif l:syn ==# 'mkdDelimiter' -        let l:line = getline(l:lnum) -        let l:char = l:line[col - 1] -        if l:char ==# '<' -            let l:col += 1 -        elseif l:char ==# '>' || l:char ==# ')' -            let l:col -= 1 -        elseif l:char ==# '[' || l:char ==# ']' || l:char ==# '(' -            let [l:lnum, l:col] = <sid>FindNextSyntax(l:lnum, l:col, 'mkdURL') -        else -            return '' -        endif -    else -        return '' -    endif +if g:markdown_enable_mappings +  " Jumping around +  noremap <silent> <buffer> <script> ]] :<C-u>call <SID>JumpToHeader(1, 0)<CR> +  noremap <silent> <buffer> <script> [[ :<C-u>call <SID>JumpToHeader(0, 0)<CR> +  vnoremap <silent> <buffer> <script> ]] :<C-u>call <SID>JumpToHeader(1, 1)<CR> +  vnoremap <silent> <buffer> <script> [[ :<C-u>call <SID>JumpToHeader(0, 1)<CR> +  noremap <silent> <buffer> <script> ][ <nop> +  noremap <silent> <buffer> <script> [] <nop> -    let [l:left, l:right] = <sid>FindCornersOfSyntax(l:lnum, l:col) -    return getline(l:lnum)[l:left - 1 : l:right - 1] -endfunction +  if g:markdown_enable_insert_mode_mappings +    " Indenting things +    inoremap <silent> <buffer> <script> <expr> <Tab> +      \ <SID>IsAnEmptyListItem() \|\| <SID>IsAnEmptyQuote() ? '<C-O>:call <SID>Indent(1)<CR>' : '<Tab>' +    inoremap <silent> <buffer> <script> <expr> <S-Tab> +      \ <SID>IsAnEmptyListItem() \|\| <SID>IsAnEmptyQuote() ? '<C-O>:call <SID>Indent(0)<CR>' : '<Tab>' -" Front end for GetUrlForPosition. -" -function! s:OpenUrlUnderCursor() -    let l:url = s:Markdown_GetUrlForPosition(line('.'), col('.')) -    if l:url != '' -        call s:VersionAwareNetrwBrowseX(l:url) +    if g:markdown_drop_empty_blockquotes +      " Remove empty quote and list items when press <CR> +      inoremap <silent> <buffer> <script> <expr> <CR> <SID>IsAnEmptyQuote() \|\| <SID>IsAnEmptyListItem() ? '<C-O>:normal 0D<CR>' : '<CR>'      else -        echomsg 'The cursor is not on a link.' +      " Remove only empty list items when press <CR> +      inoremap <silent> <buffer> <script> <expr> <CR> <SID>IsAnEmptyListItem() ? '<C-O>:normal 0D<CR>' : '<CR>'      endif -endfunction - -" We need a definition guard because we invoke 'edit' which will reload this -" script while this function is running. We must not replace it. -if !exists('*s:EditUrlUnderCursor') -    function s:EditUrlUnderCursor() -        let l:url = s:Markdown_GetUrlForPosition(line('.'), col('.')) -        if l:url != '' -            if get(g:, 'vim_markdown_autowrite', 0) -                write -            endif -            let l:anchor = '' -            if get(g:, 'vim_markdown_follow_anchor', 0) -                let l:parts = split(l:url, '#', 1) -                if len(l:parts) == 2 -                    let [l:url, l:anchor] = parts -                    let l:anchorexpr = get(g:, 'vim_markdown_anchorexpr', '') -                    if l:anchorexpr != '' -                        let l:anchor = eval(substitute( -                            \ l:anchorexpr, 'v:anchor', -                            \ escape('"'.l:anchor.'"', '"'), '')) -                    endif -                endif -            endif -            if l:url != '' -                let l:ext = '' -                if get(g:, 'vim_markdown_no_extensions_in_markdown', 0) -                    " use another file extension if preferred -                    if exists('g:vim_markdown_auto_extension_ext') -                        let l:ext = '.'.g:vim_markdown_auto_extension_ext -                    else -                        let l:ext = '.md' -                    endif -                endif -                let l:url = fnameescape(fnamemodify(expand('%:h').'/'.l:url.l:ext, ':.')) -                let l:editmethod = '' -                " determine how to open the linked file (split, tab, etc) -                if exists('g:vim_markdown_edit_url_in') -                  if g:vim_markdown_edit_url_in == 'tab' -                    let l:editmethod = 'tabnew' -                  elseif g:vim_markdown_edit_url_in == 'vsplit' -                    let l:editmethod = 'vsp' -                  elseif g:vim_markdown_edit_url_in == 'hsplit' -                    let l:editmethod = 'sp' -                  else -                    let l:editmethod = 'edit' -                  endif -                else -                  " default to current buffer -                  let l:editmethod = 'edit' -                endif -                execute l:editmethod l:url -            endif -            if l:anchor != '' -                silent! execute '/'.l:anchor -            endif -        else -            echomsg 'The cursor is not on a link.' -        endif -    endfunction -endif -function! s:VersionAwareNetrwBrowseX(url) -    if has('patch-7.4.567') -        call netrw#BrowseX(a:url, 0) -    else -        call netrw#NetrwBrowseX(a:url, 0) -    endif -endf +    " Format tables +    inoremap <silent> <buffer> <Bar> <Bar><Esc>:call markdown#FormatTable()<CR>a +  endif -function! s:MapNotHasmapto(lhs, rhs) -    if !hasmapto('<Plug>' . a:rhs) -        execute 'nmap <buffer>' . a:lhs . ' <Plug>' . a:rhs -        execute 'vmap <buffer>' . a:lhs . ' <Plug>' . a:rhs -    endif -endfunction +  " Switch status of things +  execute 'nnoremap <silent> <buffer> ' . g:markdown_mapping_switch_status . ' :call markdown#SwitchStatus()<CR>' -call <sid>MapNormVis('<Plug>Markdown_MoveToNextHeader', '<sid>MoveToNextHeader') -call <sid>MapNormVis('<Plug>Markdown_MoveToPreviousHeader', '<sid>MoveToPreviousHeader') -call <sid>MapNormVis('<Plug>Markdown_MoveToNextSiblingHeader', '<sid>MoveToNextSiblingHeader') -call <sid>MapNormVis('<Plug>Markdown_MoveToPreviousSiblingHeader', '<sid>MoveToPreviousSiblingHeader') -call <sid>MapNormVis('<Plug>Markdown_MoveToParentHeader', '<sid>MoveToParentHeader') -call <sid>MapNormVis('<Plug>Markdown_MoveToCurHeader', '<sid>MoveToCurHeader') -nnoremap <Plug>Markdown_OpenUrlUnderCursor :call <sid>OpenUrlUnderCursor()<cr> -nnoremap <Plug>Markdown_EditUrlUnderCursor :call <sid>EditUrlUnderCursor()<cr> - -if !get(g:, 'vim_markdown_no_default_key_mappings', 0) -    call <sid>MapNotHasmapto(']]', 'Markdown_MoveToNextHeader') -    call <sid>MapNotHasmapto('[[', 'Markdown_MoveToPreviousHeader') -    call <sid>MapNotHasmapto('][', 'Markdown_MoveToNextSiblingHeader') -    call <sid>MapNotHasmapto('[]', 'Markdown_MoveToPreviousSiblingHeader') -    call <sid>MapNotHasmapto(']u', 'Markdown_MoveToParentHeader') -    call <sid>MapNotHasmapto(']c', 'Markdown_MoveToCurHeader') -    call <sid>MapNotHasmapto('gx', 'Markdown_OpenUrlUnderCursor') -    call <sid>MapNotHasmapto('ge', 'Markdown_EditUrlUnderCursor') -endif +  " Leader mappings +  nnoremap <buffer> <Leader>e :MarkdownEditBlock<CR> +  vnoremap <buffer> <Leader>e :MarkdownEditBlock<CR> +  nnoremap <silent> <buffer> <Leader>ft  :call markdown#FormatTable()<CR> -command! -buffer -range=% HeaderDecrease call s:HeaderDecrease(<line1>, <line2>) -command! -buffer -range=% HeaderIncrease call s:HeaderDecrease(<line1>, <line2>, 1) -command! -buffer -range=% SetexToAtx call s:SetexToAtx(<line1>, <line2>) -command! -buffer TableFormat call s:TableFormat() -command! -buffer Toc call s:Toc() -command! -buffer Toch call s:Toc('horizontal') -command! -buffer Tocv call s:Toc('vertical') -command! -buffer Toct call s:Toc('tab') - -" Heavily based on vim-notes - http://peterodding.com/code/vim/notes/ -if exists('g:vim_markdown_fenced_languages') -    let s:filetype_dict = {} -    for s:filetype in g:vim_markdown_fenced_languages -        let key = matchstr(s:filetype, "[^=]*") -        let val = matchstr(s:filetype, "[^=]*$") -        let s:filetype_dict[key] = val -    endfor -else -    let s:filetype_dict = { -        \ 'c++': 'cpp', -        \ 'viml': 'vim', -        \ 'bash': 'sh', -        \ 'ini': 'dosini' -    \ } +  " Insert Mode mappings +  if g:markdown_enable_insert_mode_leader_mappings +    inoremap <buffer> <Leader>e <Esc>:MarkdownEditBlock<CR> +    inoremap <silent> <buffer> <Leader>ft  <Esc>:call markdown#FormatTable()<CR>a +  endif  endif -function! s:MarkdownHighlightSources(force) -    " Syntax highlight source code embedded in notes. -    " Look for code blocks in the current file -    let filetypes = {} -    for line in getline(1, '$') -        let ft = matchstr(line, '```\s*\zs[0-9A-Za-z_+-]*') -        if !empty(ft) && ft !~ '^\d*$' | let filetypes[ft] = 1 | endif -    endfor -    if !exists('b:mkd_known_filetypes') -        let b:mkd_known_filetypes = {} -    endif -    if !exists('b:mkd_included_filetypes') -        " set syntax file name included -        let b:mkd_included_filetypes = {} -    endif -    if !a:force && (b:mkd_known_filetypes == filetypes || empty(filetypes)) -        return -    endif - -    " Now we're ready to actually highlight the code blocks. -    let startgroup = 'mkdCodeStart' -    let endgroup = 'mkdCodeEnd' -    for ft in keys(filetypes) -        if a:force || !has_key(b:mkd_known_filetypes, ft) -            if has_key(s:filetype_dict, ft) -                let filetype = s:filetype_dict[ft] -            else -                let filetype = ft -            endif -            let group = 'mkdSnippet' . toupper(substitute(filetype, "[+-]", "_", "g")) -            if !has_key(b:mkd_included_filetypes, filetype) -                let include = s:SyntaxInclude(filetype) -                let b:mkd_included_filetypes[filetype] = 1 -            else -                let include = '@' . toupper(filetype) -            endif -            let command = 'syntax region %s matchgroup=%s start="^\s*```\s*%s$" matchgroup=%s end="\s*```$" keepend contains=%s%s' -            execute printf(command, group, startgroup, ft, endgroup, include, has('conceal') && get(g:, 'vim_markdown_conceal', 1) && get(g:, 'vim_markdown_conceal_code_blocks', 1) ? ' concealends' : '') -            execute printf('syntax cluster mkdNonListItem add=%s', group) - -            let b:mkd_known_filetypes[ft] = 1 -        endif -    endfor -endfunction - -function! s:SyntaxInclude(filetype) -    " Include the syntax highlighting of another {filetype}. -    let grouplistname = '@' . toupper(a:filetype) -    " Unset the name of the current syntax while including the other syntax -    " because some syntax scripts do nothing when "b:current_syntax" is set -    if exists('b:current_syntax') -        let syntax_save = b:current_syntax -        unlet b:current_syntax -    endif -    try -        execute 'syntax include' grouplistname 'syntax/' . a:filetype . '.vim' -        execute 'syntax include' grouplistname 'after/syntax/' . a:filetype . '.vim' -    catch /E484/ -        " Ignore missing scripts -    endtry -    " Restore the name of the current syntax -    if exists('syntax_save') -        let b:current_syntax = syntax_save -    elseif exists('b:current_syntax') -        unlet b:current_syntax -    endif -    return grouplistname -endfunction - - -function! s:MarkdownRefreshSyntax(force) -    if &filetype =~ 'markdown' && line('$') > 1 -        call s:MarkdownHighlightSources(a:force) -    endif -endfunction - -function! s:MarkdownClearSyntaxVariables() -    if &filetype =~ 'markdown' -        unlet! b:mkd_included_filetypes -    endif -endfunction +" }}} -augroup Mkd -    " These autocmd calling s:MarkdownRefreshSyntax need to be kept in sync with -    " the autocmds calling s:MarkdownSetupFolding in after/ftplugin/markdown.vim. -    autocmd! * <buffer> -    autocmd BufWinEnter <buffer> call s:MarkdownRefreshSyntax(1) -    autocmd BufUnload <buffer> call s:MarkdownClearSyntaxVariables() -    autocmd BufWritePost <buffer> call s:MarkdownRefreshSyntax(0) -    autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownRefreshSyntax(0) -    autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownRefreshSyntax(0) -augroup END +let b:did_ftplugin = 1  endif diff --git a/indent/markdown.vim b/indent/markdown.vim deleted file mode 100644 index fa797312..00000000 --- a/indent/markdown.vim +++ /dev/null @@ -1,79 +0,0 @@ -if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1 - -if exists("b:did_indent") | finish | endif -let b:did_indent = 1 - -setlocal indentexpr=GetMarkdownIndent() -setlocal nolisp -setlocal autoindent - -" Automatically continue blockquote on line break -setlocal formatoptions+=r -setlocal comments=b:> -if get(g:, "vim_markdown_auto_insert_bullets", 1) -    " Do not automatically insert bullets when auto-wrapping with text-width -    setlocal formatoptions-=c -    " Accept various markers as bullets -    setlocal comments+=b:*,b:+,b:- -endif - -" Only define the function once -if exists("*GetMarkdownIndent") | finish | endif - -function! s:IsMkdCode(lnum) -    let name = synIDattr(synID(a:lnum, 1, 0), 'name') -    return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)') -endfunction - -function! s:IsLiStart(line) -    return a:line !~ '^ *\([*-]\)\%( *\1\)\{2}\%( \|\1\)*$' && -      \    a:line =~ '^\s*[*+-] \+' -endfunction - -function! s:IsHeaderLine(line) -    return a:line =~ '^\s*#' -endfunction - -function! s:IsBlankLine(line) -    return a:line =~ '^$' -endfunction - -function! s:PrevNonBlank(lnum) -    let i = a:lnum -    while i > 1 && s:IsBlankLine(getline(i)) -        let i -= 1 -    endwhile -    return i -endfunction - -function GetMarkdownIndent() -    if v:lnum > 2 && s:IsBlankLine(getline(v:lnum - 1)) && s:IsBlankLine(getline(v:lnum - 2)) -        return 0 -    endif -    let list_ind = get(g:, "vim_markdown_new_list_item_indent", 4) -    " Find a non-blank line above the current line. -    let lnum = s:PrevNonBlank(v:lnum - 1) -    " At the start of the file use zero indent. -    if lnum == 0 | return 0 | endif -    let ind = indent(lnum) -    let line = getline(lnum)    " Last line -    let cline = getline(v:lnum) " Current line -    if s:IsLiStart(cline) -        " Current line is the first line of a list item, do not change indent -        return indent(v:lnum) -    elseif s:IsHeaderLine(cline) && !s:IsMkdCode(v:lnum) -        " Current line is the header, do not indent -        return 0 -    elseif s:IsLiStart(line) -        if s:IsMkdCode(lnum) -            return ind -        else -            " Last line is the first line of a list item, increase indent -            return ind + list_ind -        end -    else -        return ind -    endif -endfunction - -endif diff --git a/syntax/markdown.vim b/syntax/markdown.vim index 063ba10d..8c5e10ba 100644 --- a/syntax/markdown.vim +++ b/syntax/markdown.vim @@ -1,188 +1,947 @@  if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1  " Vim syntax file -" Language:	Markdown -" Maintainer:	Ben Williams <benw@plasticboy.com> -" URL:		http://plasticboy.com/markdown-vim-mode/ -" Remark:	Uses HTML syntax file -" TODO: 	Handle stuff contained within stuff (e.g. headings within blockquotes) +" Language:     Markdown +" Maintainer:   Gabriele Lana <gabriele.lana@gmail.com> +" Filenames:    *.md +if exists("b:current_syntax") +  finish +endif -" Read the HTML syntax to start with -if version < 600 -  so <sfile>:p:h/html.vim -else -  runtime! syntax/html.vim - -  if exists('b:current_syntax') -    unlet b:current_syntax -  endif +if !exists('main_syntax') +  let main_syntax = 'markdown'  endif -if version < 600 -  syntax clear -elseif exists("b:current_syntax") -  finish +if !exists('g:markdown_flavor') +  let g:markdown_flavor = 'github'  endif -" don't use standard HiLink, it will not work with included syntax files -if version < 508 -  command! -nargs=+ HtmlHiLink hi link <args> +if exists('g:markdown_enable_conceal') && g:markdown_enable_conceal +    let b:markdown_concealends = 'concealends' +    let b:markdown_conceal = 'conceal' +    set conceallevel=2 +    set concealcursor=  else -  command! -nargs=+ HtmlHiLink hi def link <args> +    let b:markdown_concealends = '' +    let b:markdown_conceal = ''  endif  syn spell toplevel +syn sync fromstart  syn case ignore -syn sync linebreaks=1 - -let s:conceal = '' -let s:concealends = '' -let s:concealcode = '' -if has('conceal') && get(g:, 'vim_markdown_conceal', 1) -  let s:conceal = ' conceal' -  let s:concealends = ' concealends' -endif -if has('conceal') && get(g:, 'vim_markdown_conceal_code_blocks', 1) -  let s:concealcode = ' concealends' -endif -" additions to HTML groups -if get(g:, 'vim_markdown_emphasis_multiline', 1) -    let s:oneline = '' -else -    let s:oneline = ' oneline' -endif -syn region mkdItalic matchgroup=mkdItalic start="\%(\*\|_\)"    end="\%(\*\|_\)" -syn region mkdBold matchgroup=mkdBold start="\%(\*\*\|__\)"    end="\%(\*\*\|__\)" -syn region mkdBoldItalic matchgroup=mkdBoldItalic start="\%(\*\*\*\|___\)"    end="\%(\*\*\*\|___\)" -execute 'syn region htmlItalic matchgroup=mkdItalic start="\%(^\|\s\)\zs\*\ze[^\\\*\t ]\%(\%([^*]\|\\\*\|\n\)*[^\\\*\t ]\)\?\*\_W" end="[^\\\*\t ]\zs\*\ze\_W" keepend contains=@Spell' . s:oneline . s:concealends -execute 'syn region htmlItalic matchgroup=mkdItalic start="\%(^\|\s\)\zs_\ze[^\\_\t ]" end="[^\\_\t ]\zs_\ze\_W" keepend contains=@Spell' . s:oneline . s:concealends -execute 'syn region htmlBold matchgroup=mkdBold start="\%(^\|\s\)\zs\*\*\ze\S" end="\S\zs\*\*" keepend contains=@Spell' . s:oneline . s:concealends -execute 'syn region htmlBold matchgroup=mkdBold start="\%(^\|\s\)\zs__\ze\S" end="\S\zs__" keepend contains=@Spell' . s:oneline . s:concealends -execute 'syn region htmlBoldItalic matchgroup=mkdBoldItalic start="\%(^\|\s\)\zs\*\*\*\ze\S" end="\S\zs\*\*\*" keepend contains=@Spell' . s:oneline . s:concealends -execute 'syn region htmlBoldItalic matchgroup=mkdBoldItalic start="\%(^\|\s\)\zs___\ze\S" end="\S\zs___" keepend contains=@Spell' . s:oneline . s:concealends - -" [link](URL) | [link][id] | [link][] |  -syn region mkdFootnotes matchgroup=mkdDelimiter start="\[^"    end="\]" -execute 'syn region mkdID matchgroup=mkdDelimiter    start="\["    end="\]" contained oneline' . s:conceal -execute 'syn region mkdURL matchgroup=mkdDelimiter   start="("     end=")"  contained oneline' . s:conceal -execute 'syn region mkdLink matchgroup=mkdDelimiter  start="\\\@<!!\?\[\ze[^]\n]*\n\?[^]\n]*\][[(]" end="\]" contains=@mkdNonListItem,@Spell nextgroup=mkdURL,mkdID skipwhite' . s:concealends - -" Autolink without angle brackets. -" mkd  inline links:      protocol     optional  user:pass@  sub/domain                    .com, .co.uk, etc         optional port   path/querystring/hash fragment -"                         ------------ _____________________ ----------------------------- _________________________ ----------------- __ -syn match   mkdInlineURL /https\?:\/\/\(\w\+\(:\w\+\)\?@\)\?\([A-Za-z0-9][-_0-9A-Za-z]*\.\)\{1,}\(\w\{2,}\.\?\)\{1,}\(:[0-9]\{1,5}\)\?\S*/ - -" Autolink with parenthesis. -syn region  mkdInlineURL matchgroup=mkdDelimiter start="(\(https\?:\/\/\(\w\+\(:\w\+\)\?@\)\?\([A-Za-z0-9][-_0-9A-Za-z]*\.\)\{1,}\(\w\{2,}\.\?\)\{1,}\(:[0-9]\{1,5}\)\?\S*)\)\@=" end=")" - -" Autolink with angle brackets. -syn region mkdInlineURL matchgroup=mkdDelimiter start="\\\@<!<\ze[a-z][a-z0-9,.-]\{1,22}:\/\/[^> ]*>" end=">" - -" Link definitions: [id]: URL (Optional Title) -syn region mkdLinkDef matchgroup=mkdDelimiter   start="^ \{,3}\zs\[\^\@!" end="]:" oneline nextgroup=mkdLinkDefTarget skipwhite -syn region mkdLinkDefTarget start="<\?\zs\S" excludenl end="\ze[>[:space:]\n]"   contained nextgroup=mkdLinkTitle,mkdLinkDef skipwhite skipnl oneline -syn region mkdLinkTitle matchgroup=mkdDelimiter start=+"+     end=+"+  contained -syn region mkdLinkTitle matchgroup=mkdDelimiter start=+'+     end=+'+  contained -syn region mkdLinkTitle matchgroup=mkdDelimiter start=+(+     end=+)+  contained - -"HTML headings -syn region htmlH1       matchgroup=mkdHeading     start="^\s*#"                   end="$" contains=mkdLink,mkdInlineURL,@Spell -syn region htmlH2       matchgroup=mkdHeading     start="^\s*##"                  end="$" contains=mkdLink,mkdInlineURL,@Spell -syn region htmlH3       matchgroup=mkdHeading     start="^\s*###"                 end="$" contains=mkdLink,mkdInlineURL,@Spell -syn region htmlH4       matchgroup=mkdHeading     start="^\s*####"                end="$" contains=mkdLink,mkdInlineURL,@Spell -syn region htmlH5       matchgroup=mkdHeading     start="^\s*#####"               end="$" contains=mkdLink,mkdInlineURL,@Spell -syn region htmlH6       matchgroup=mkdHeading     start="^\s*######"              end="$" contains=mkdLink,mkdInlineURL,@Spell -syn match  htmlH1       /^.\+\n=\+$/ contains=mkdLink,mkdInlineURL,@Spell -syn match  htmlH2       /^.\+\n-\+$/ contains=mkdLink,mkdInlineURL,@Spell - -"define Markdown groups -syn match  mkdLineBreak    /  \+$/ -syn region mkdBlockquote   start=/^\s*>/                   end=/$/ contains=mkdLink,mkdInlineURL,mkdLineBreak,@Spell -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!`/                     end=/`/'  . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!``/ skip=/[^`]`[^`]/   end=/``/' . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(`\{3,}\)[^`]*$/                       end=/^\s*\z1`*\s*$/'            . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!\~\~/  end=/\(\([^\\]\|^\)\\\)\@<!\~\~/'               . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(\~\{3,}\)\s*[0-9A-Za-z_+-]*\s*$/      end=/^\s*\z1\~*\s*$/'           . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<pre[^>]*\\\@<!>"                            end="</pre>"'                   . s:concealcode -execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<code[^>]*\\\@<!>"                           end="</code>"'                  . s:concealcode -syn region mkdFootnote     start="\[^"                     end="\]" -syn match  mkdCode         /^\s*\n\(\(\s\{8,}[^ ]\|\t\t\+[^\t]\).*\n\)\+/ -syn match  mkdCode         /\%^\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/ -syn match  mkdCode         /^\s*\n\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/ contained -syn match  mkdListItem     /^\s*\%([-*+]\|\d\+\.\)\ze\s\+/ contained -syn region mkdListItemLine start="^\s*\%([-*+]\|\d\+\.\)\s\+" end="$" oneline contains=@mkdNonListItem,mkdListItem,@Spell -syn region mkdNonListItemBlock start="\(\%^\(\s*\([-*+]\|\d\+\.\)\s\+\)\@!\|\n\(\_^\_$\|\s\{4,}[^ ]\|\t+[^\t]\)\@!\)" end="^\(\s*\([-*+]\|\d\+\.\)\s\+\)\@=" contains=@mkdNonListItem,@Spell -syn match  mkdRule         /^\s*\*\s\{0,1}\*\s\{0,1}\*\(\*\|\s\)*$/ -syn match  mkdRule         /^\s*-\s\{0,1}-\s\{0,1}-\(-\|\s\)*$/ -syn match  mkdRule         /^\s*_\s\{0,1}_\s\{0,1}_\(_\|\s\)*$/ - -" YAML frontmatter -if get(g:, 'vim_markdown_frontmatter', 0) -  syn include @yamlTop syntax/yaml.vim -  syn region Comment matchgroup=mkdDelimiter start="\%^---$" end="^\(---\|\.\.\.\)$" contains=@yamlTop keepend -  unlet! b:current_syntax -endif -if get(g:, 'vim_markdown_toml_frontmatter', 0) -  try -    syn include @tomlTop syntax/toml.vim -    syn region Comment matchgroup=mkdDelimiter start="\%^+++$" end="^+++$" transparent contains=@tomlTop keepend -    unlet! b:current_syntax -  catch /E484/ -    syn region Comment matchgroup=mkdDelimiter start="\%^+++$" end="^+++$" -  endtry -endif +" {{{ INLINE ELEMENTS + +syn cluster markdownInline contains= +  \ markdownItalic,markdownBold,markdownBoldItalic,markdownStrike,markdownInlineCode, +  \ markdownPullRequestLinkInText,markdownUrlLinkInText,markdownUserLinkInText, +  \ markdownEmailLinkInText,markdownLinkContainer,markdownXmlComment, +  \ markdownXmlElement,markdownXmlEmptyElement,markdownXmlEntities + +execute 'syn region markdownItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|_\|^\)\@<=\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends +execute 'syn region markdownItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|\*\|^\)\@<=_\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!_" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends + +execute 'syn region markdownBold matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|__\|^\)\@<=\*\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\*\)\@<!\*\*" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends +execute 'syn region markdownBold matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|\*\*\|^\)\@<=__\%(\s\|_\|$\)\@!" end="\%(\s\|__\)\@<!__" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends + +execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|_\|^\)\@<=\*\*\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*\*\*" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends +execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|\*\|^\)\@<=___\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!___" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends +execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|_\|^\)\@<=\*\*_\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!_\*\*" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends +execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter ' +  \ . 'start="\%(\s\|\*\|^\)\@<=__\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*__" ' +  \ . 'contains=@markdownInline ' +  \ . b:markdown_concealends + +syn match markdownStrike /\%(\\\)\@<!\~\~\%(\S\)\@=\_.\{-}\%(\S\)\@<=\~\~/ contains=markdownStrikeDelimiter,@markdownInline +syn match markdownStrikeDelimiter /\~\~/ contained + +" Fenced code blocks in list items must be preceded by an empty line This is +" made this way so that the second rule could eat up something that is not a +" fenced code block like +" +"     * This is a list item +"       ```ruby +"       # this is not a fenced code block but it's a code block +"       def ruby; +"       ``` +execute 'syn region markdownInlineCode matchgroup=markdownCodeDelimiter start=/\%(`\)\@<!`/ end=/`/ keepend contains=@NoSpell ' . b:markdown_concealends +execute 'syn region markdownInlineCode matchgroup=markdownCodeDelimiter start=/\%(`\)\@<!`\z(`\+\)/ end=/`\z1/ keepend contains=@NoSpell ' . b:markdown_concealends + +" case insensitive +" preceded by something that is not a word +" could be surrounded by angle brackets +" could begin with / or // (path) or the url protocol +" inside the url pairs of balanced parentheses are allowed +" inside the url html entities are allowed +" the end block is different because ?!:,. are not included in the url if they +" appear at the end of the url +let b:markdown_syntax_url = +  \ '\c' +  \ . '\%(\W\)\@<=' +  \ . '<\?' +  \ . '\%(' +  \ .   '\%(\<\%(https\?\|ftp\|file\):\/\/\|www\.\|ftp\.\)' +  \ .   '\|' +  \ .   '\/\/\?' +  \ . '\)' +  \ . '\%(' +  \ .   '&#\?[0-9A-Za-z]\{1,8};' +  \ .   '\|' +  \ .   '\\' +  \ .   '\|' +  \ .   '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)' +  \ .   '\|' +  \ .   '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]' +  \ .   '\|' +  \ .   '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}' +  \ .   '\|' +  \ .   '[-A-Z0-9+&@#/%=~_|$?!:,.]' +  \ . '\)*' +  \ . '\%(' +  \ .   '&#\?[0-9A-Za-z]\{1,8};' +  \ .   '\|' +  \ .   '\\' +  \ .   '\|' +  \ .   '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)' +  \ .   '\|' +  \ .   '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]' +  \ .   '\|' +  \ .   '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}' +  \ .   '\|' +  \ .   '[-A-Z0-9+&@#/%=~_|$]\+' +  \ . '\)' +  \ . '>\?' +execute 'syn match markdownUrlLinkInText /' . b:markdown_syntax_url . '/ contains=@NoSpell display' + +syn match markdownPullRequestLinkInText /\%(\w\)\@<!#\d\+/ display +syn match markdownUserLinkInText /\%(\w\)\@<!@[[:alnum:]._\/-]\+/ contains=@NoSpell display +syn match markdownEmailLinkInText /[[:alnum:]._%+-]\+@[[:alnum:].-]\+\.\w\{2,4}/ contains=@NoSpell display -if get(g:, 'vim_markdown_json_frontmatter', 0) -  try -    syn include @jsonTop syntax/json.vim -    syn region Comment matchgroup=mkdDelimiter start="\%^{$" end="^}$" contains=@jsonTop keepend -    unlet! b:current_syntax -  catch /E484/ -    syn region Comment matchgroup=mkdDelimiter start="\%^{$" end="^}$" -  endtry +" something encosed in square brackets +" could not be preceded by a backslash +" could contain pairs of square brackets +" could contain no more than two consecutive newlines +" could contain single square brackets (open or closed) escaped +" could not contain unbalanced square brackets like 'a [ b \] c' +" could not contain nested square brackets +let b:markdown_syntax_allowed_characters_in_square_brackets = '\%([^\[\]]\|\\\[\|\\\]\)*' +let b:markdown_syntax_square_brackets_block = '' +  \ . '\%(\\\)\@<!\[' +  \ .   '\%(' +  \ .     b:markdown_syntax_allowed_characters_in_square_brackets +  \ .     '\|' +  \ .     b:markdown_syntax_allowed_characters_in_square_brackets +  \ .     '\[' +  \ .       b:markdown_syntax_allowed_characters_in_square_brackets +  \ .     '\]' +  \ .     b:markdown_syntax_allowed_characters_in_square_brackets +  \ .   '\)' +  \ .   '\%(' +  \ .     '\n\%(\n\)\@!' +  \ .     '\%(' +  \ .       b:markdown_syntax_allowed_characters_in_square_brackets +  \ .       '\|' +  \ .       b:markdown_syntax_allowed_characters_in_square_brackets +  \ .       '\[' +  \ .         b:markdown_syntax_allowed_characters_in_square_brackets +  \ .       '\]' +  \ .       b:markdown_syntax_allowed_characters_in_square_brackets +  \ .     '\)' +  \ .   '\)*' +  \ . '\]' + +" something encosed in round brackets +" could not be preceded by a backslash +" could contain pairs of round brackets +" could contain no more than two consecutive newlines +" could contain single round brackets (open or closed) escaped +" could not contain unbalanced round brackets like 'a ( b \) c' +" could not contain nested round brackets +let b:markdown_syntax_allowed_characters_in_round_brackets = '[^()]*' +let b:markdown_syntax_round_brackets_block = '' +  \ . '\%(\\\)\@<!(' +  \ .   '\%(' +  \ .     b:markdown_syntax_allowed_characters_in_round_brackets +  \ .     '\|' +  \ .     b:markdown_syntax_allowed_characters_in_round_brackets +  \ .     '(' +  \ .       b:markdown_syntax_allowed_characters_in_round_brackets +  \ .     ')' +  \ .     b:markdown_syntax_allowed_characters_in_round_brackets +  \ .   '\)' +  \ .   '\%(' +  \ .     '\n\%(\n\)\@!' +  \ .     '\%(' +  \ .       b:markdown_syntax_allowed_characters_in_round_brackets +  \ .       '\|' +  \ .       b:markdown_syntax_allowed_characters_in_round_brackets +  \ .       '(' +  \ .         b:markdown_syntax_allowed_characters_in_round_brackets +  \ .       ')' +  \ .       b:markdown_syntax_allowed_characters_in_round_brackets +  \ .     '\)' +  \ .   '\)*' +  \ . ')' + +execute 'syn match markdownLinkContainer ' +  \ . 'contains=markdownLinkTextContainer,markdownLinkUrlContainer transparent ' +  \ . '/' +  \ . '!\?' +  \ . b:markdown_syntax_square_brackets_block +  \ . '\%(\s*\|\n\%\(\n\)\@!\)' +  \ . '\%(' +  \ .   b:markdown_syntax_round_brackets_block +  \ .   '\|' +  \ .   b:markdown_syntax_square_brackets_block +  \ . '\)' +  \ . '/' + +execute 'syn match markdownLinkTextContainer contained ' +  \ . 'contains=markdownLinkText ' +  \ . '/' +  \ . '!\?' +  \ . b:markdown_syntax_square_brackets_block +  \ . '/' + +execute 'syn match markdownLinkText contained ' +  \ . 'contains=@markdownInline,@NoSpell ' +  \ . '/' +  \ . '!\?' +  \ . b:markdown_syntax_square_brackets_block +  \ . '/' +  \ . 'hs=s+1,he=e-1' + +execute 'syn match markdownLinkUrlContainer contained ' +  \ . 'contains=markdownLinkUrl,markdownLinkTitleSingleQuoted,markdownLinkTitleDoubleQuoted ' +  \ . '/' +  \ . b:markdown_syntax_round_brackets_block +  \ . '/ ' +  \ . b:markdown_conceal + +execute 'syn match markdownLinkUrl contained ' +  \ . 'contains=@NoSpell ' +  \ . '/' +  \ . '\%((\)\@<=' +  \ . '\%(' +  \ .   '&#\?[0-9A-Za-z]\{1,8};' +  \ .   '\|' +  \ .   '\\' +  \ .   '\|' +  \ .   '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)' +  \ .   '\|' +  \ .   '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]' +  \ .   '\|' +  \ .   '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}' +  \ .   '\|' +  \ .   '[-A-Z0-9+&@#/%=~_|$?!:,.]' +  \ .   '\|' +  \ .   '\s' +  \ . '\)\+' +  \ . '\%(\s\+["'']\|)\|\n\)\@=' +  \ . '/' + +execute 'syn region markdownLinkTitleSingleQuoted start=/\s*''/ skip=/\\''/ end=/''\_s*/ display ' +  \ . 'keepend contained contains=@markdownInline ' +  \ . b:markdown_conceal + +execute 'syn region markdownLinkTitleDoubleQuoted start=/\s*"/ skip=/\\"/ end=/"\_s*/ display ' +  \ . 'keepend contained contains=@markdownInline ' +  \ . b:markdown_conceal + +syn match markdownXmlComment /\c<\!--\_.\{-}-->/ contains=@NoSpell +syn match markdownXmlElement /\c<\([-A-Z0-9_$?!:,.]\+\)[^>]\{-}>\_.\{-}<\/\1>/ contains=@NoSpell +syn match markdownXmlEmptyElement /\c<\([-A-Z0-9_$?!:,.]\+\)\%(\s\+[^>]\{-}\/>\|\s*\/>\)/ contains=@NoSpell +syn match markdownXmlEntities /&#\?[0-9A-Za-z]\{1,8};/ contains=@NoSpell + +" }}} + + +" {{{ ANCHORED BLOCKS + +syn match markdownRule /^\s*\*\s*\*\s*\*[[:space:]*]*$/ display +syn match markdownRule /^\s*-\s*-\s*-[[:space:]-]*$/ display +syn match markdownRule /^\s*_\s*_\s*_[[:space:]_]*$/ display + +if g:markdown_flavor ==? 'github' +  syn region markdownH1 matchgroup=markdownHeadingDelimiter start=/^#\%(\s\+\)\@=/      end=/#*\s*$/ display oneline contains=@markdownInline +  syn region markdownH2 matchgroup=markdownHeadingDelimiter start=/^##\%(\s\+\)\@=/     end=/#*\s*$/ display oneline contains=@markdownInline +  syn region markdownH3 matchgroup=markdownHeadingDelimiter start=/^###\%(\s\+\)\@=/    end=/#*\s*$/ display oneline contains=@markdownInline +  syn region markdownH4 matchgroup=markdownHeadingDelimiter start=/^####\%(\s\+\)\@=/   end=/#*\s*$/ display oneline contains=@markdownInline +  syn region markdownH5 matchgroup=markdownHeadingDelimiter start=/^#####\%(\s\+\)\@=/  end=/#*\s*$/ display oneline contains=@markdownInline +  syn region markdownH6 matchgroup=markdownHeadingDelimiter start=/^######\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline + +  syn match markdownH1 /^.\+\n=\+$/ display contains=@markdownInline,markdownHeadingUnderline +  syn match markdownH2 /^.\+\n-\+$/ display contains=@markdownInline,markdownHeadingUnderline +  syn match markdownHeadingUnderline /^[=-]\+$/ display contained  endif -if get(g:, 'vim_markdown_math', 0) -  syn include @tex syntax/tex.vim -  syn region mkdMath start="\\\@<!\$" end="\$" skip="\\\$" contains=@tex keepend -  syn region mkdMath start="\\\@<!\$\$" end="\$\$" skip="\\\$" contains=@tex keepend +if g:markdown_flavor ==? 'kramdown' +  syn match markdownHeaderContainer /^#\{1,6}.\+$/ display transparent +    \ contains=@markdownInline,markdownHeader,markdownHeaderId,markdownHeadingDelimiter +  syn match markdownHeader /\%(^#\+\)\@<=\%([^#]\+\%(#\+\s*\%($\|{\)\)\@=\|[^{]\{-}\%({\)\@=\|#$\)/ + +  syn match markdownHeader /^.\+\n=\+$/ display contains=@markdownInline,markdownHeadingUnderline,markdownHeaderId +  syn match markdownHeader /^.\+\n-\+$/ display contains=@markdownInline,markdownHeadingUnderline,markdownHeaderId +  syn match markdownHeadingUnderline /^[=-]\+$/ display contained + +  syn match markdownHeaderId /{[^}]\+}\s*$/ display contained +  syn match markdownHeadingDelimiter /#\+\%(.\+\)\@=/ display contained  endif -" Strike through -if get(g:, 'vim_markdown_strikethrough', 0) -    execute 'syn region mkdStrike matchgroup=htmlStrike start="\%(\~\~\)" end="\%(\~\~\)"' . s:concealends -    HtmlHiLink mkdStrike        htmlStrike +execute 'syn match markdownLinkReference ' +  \ . 'contains=@NoSpell ' +  \ . 'display ' +  \ . '/' +  \ . '^\s\{,3}' +  \ . b:markdown_syntax_square_brackets_block +  \ . ':.*' +  \ . '\%(\n\%\(\n\)\@!.*$\)*' +  \ . '/' + +syn region markdownBlockquote start=/^\s*\%(>\s\?\)\+\%(.\)\@=/ end=/\n\n/ contains=markdownBlockquoteDelimiter,@NoSpell +syn match markdownBlockquoteDelimiter /^\s*\%(>\s\?\)\+/ contained + +syn region markdownFencedCodeBlock matchgroup=markdownCodeDelimiter start=/^\s\{,3}```\%(`*\).*$/ end=/^\s\{,3}```\%(`*\)\s*$/ contains=@NoSpell +syn region markdownFencedCodeBlock matchgroup=markdownCodeDelimiter start=/^\s\{,3}\~\~\~\%(\~*\).*$/ end=/^\s\{,3}\~\~\~\%(\~*\)\s*$/ contains=@NoSpell + +syn match markdownCodeBlock /\%(^\n\)\@<=\%(\%(\s\{4,}\|\t\+\).*\n\)\+$/ contains=@NoSpell + +let s:markdown_table_header_rows_separator = '' +  \ . '\%(' +  \ .   '\s*|\?\%(\s*[-:]-\{1,}[-:]\s*|\)\+\s*[-:]-\{1,}[-:]\s*|\?\s*' +  \ .   '\|' +  \ .   '\s*|\s*[-:]-\{1,}[-:]\s*|\s*' +  \ .   '\|' +  \ .   '\s*|\s*[-:]-\{1,}[-:]\s*' +  \ .   '\|' +  \ .   '\s*[-:]-\{1,}[-:]\s*|\s*' +  \ . '\)' +execute 'syn match markdownTable ' +  \ . 'transparent contains=markdownTableHeader,markdownTableDelimiter,@markdownInline ' +  \ . '/' +  \ .   '^\s*\n' +  \ .   '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n' +  \ .   s:markdown_table_header_rows_separator . '\n' +  \ .   '\%(' +  \ .     '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n' +  \ .   '\)*' +  \ .   '$' +  \ . '/' +syn match markdownTableDelimiter /|/ contained +execute 'syn match markdownTableDelimiter contained ' +  \ . '/' . s:markdown_table_header_rows_separator . '/' +execute 'syn match markdownTableHeader contained contains=@markdownInline ' +  \ . '/\%(|\?\s*\)\@<=[^|]\+\%(.*\n' . s:markdown_table_header_rows_separator . '\)\@=/' + +" }}} + + +" {{{ NESTED BLOCKS + +for s:level in range(1, 16) +  let s:indented_as_content = '\%( \{' . (2*s:level) . '}\|\t\{' . (s:level) . '}\)' +  let s:indented_as_container = '\%( \{' . (2*(s:level-1)) . '}\|\t\{' . (s:level-1) . '}\)' +  let s:preceded_by_separator = '^\s*\n' + +  execute 'syn region markdownListItemAtLevel' . (s:level) . ' ' +    \ . 'matchgroup=markdownItemDelimiter ' +    \ . (s:level > 1 ? 'contained ' : '') +    \ . 'keepend ' +    \ . 'contains=' +    \ .   'markdownTableInListItemAtLevel' . (s:level) . ',' +    \ .   'markdownCodeBlockInListItemAtLevel' . (s:level) . ',' +    \ .   'markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH1InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH2InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH3InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH4InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH5InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownH6InListItemAtLevel' . (s:level) . ',' +    \ .   'markdownRuleInListItemAtLevel' . (s:level) . ',' +    \ .   'markdownBlockquoteInListItemAtLevel' . (s:level) . ',' +    \ .   'markdownListItemAtLevel' . (s:level+1) . ',' +    \ .   '@markdownInline ' +    \ . 'start=/^' . (s:indented_as_container) . '\%([-*+]\|\d\+\.\)\%(\s\+\[[ x]\]\)\?\s\+/ ' +    \ . 'end=' +    \ .   '/' +    \ .     '\n\%(\n\n\)\@=' +    \ .     '\|' +    \ .     '\n\%(' . (s:indented_as_container) . '\%([-*+]\|\d\+\.\)\s\+\)\@=' +    \ .     '\|' +    \ .     '\n\%(\n' . (s:indented_as_container) . '\S\)\@=' +    \ .   '/' + +  " fenced code blocks could have leading spaces after the base level indentation +  " so at least it must be indented as content but could be indented more +  " there's no upper limit to the indentation because the following rule on +  " code blocks is going to take care of that +  " TL;DR: don't swap markdownFencedCodeBlockInListItemAtLevel* with +  " markdownCodeBlockInListItemAtLevel* :-) +  execute 'syn region markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' ' +    \ . 'contained contains=@NoSpell ' +    \ . 'matchgroup=markdownFencedCodeBlockInItemDelimiter ' +    \ . 'start=' +    \ .   '/' +    \ .     (s:preceded_by_separator) +    \ .     '\z( \{' . (2*s:level) . ',}\|\t\{' . (s:level) . ',}\)*```\%(`*\).*$' +    \ .   '/ ' +    \ . 'end=/^\z1```\%(`*\)\s*$/' +  execute 'syn region markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' ' +    \ . 'contained contains=@NoSpell ' +    \ . 'matchgroup=markdownFencedCodeBlockInItemDelimiter ' +    \ . 'start=' +    \ .   '/' +    \ .     (s:preceded_by_separator) +    \ .     '\z( \{' . (2*s:level) . ',}\|\t\{' . (s:level) . ',}\)*\~\~\~\%(\~*\).*$' +    \ .   '/ ' +    \ . 'end=/^\z1\~\~\~\%(\~*\)\s*$/' +  execute 'hi def link markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' String' + +  execute 'syn match markdownCodeBlockInListItemAtLevel' . (s:level) . ' ' +    \ . 'contained contains=@NoSpell ' +    \ . '/' . (s:preceded_by_separator) . '\%(\%( \{' . (6+2*s:level)  . ',}\|\t\{' . (1+s:level) . ',}\).*\n\?\)\+$/' +  execute 'hi def link markdownCodeBlockInListItemAtLevel' . (s:level) . ' String' + +  execute 'syn region markdownH1InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '#\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'syn region markdownH2InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '##\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'syn region markdownH3InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '###\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'syn region markdownH4InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '####\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'syn region markdownH5InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '#####\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'syn region markdownH6InListItemAtLevel' . (s:level) . ' ' +    \ . 'contained display oneline ' +    \ . 'matchgroup=markdownHeadingDelimiter ' +    \ . 'contains=@markdownInline ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '######\%(\s\+\)\@=/ ' +    \ . 'end=/#*\s*$/' +  execute 'hi def link markdownH1InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH2InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH3InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH4InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH5InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH6InListItemAtLevel' . (s:level) . ' Title' + +  execute 'syn match markdownH1InListItemAtLevel' . (s:level) . ' ' +    \ . 'display contained contains=@markdownInline,markdownHeadingDelimiterInListItemAtLevel'. (s:level) . ' ' +    \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '.\+\n' . (s:indented_as_content) . '=\+$/' +  execute 'syn match markdownH1InListItemAtLevel' . (s:level) . ' ' +    \ . 'display contained contains=@markdownInline,markdownHeadingDelimiterInListItemAtLevel'. (s:level) . ' ' +    \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '.\+\n' . (s:indented_as_content) . '-\+$/' +  execute 'syn match markdownHeadingDelimiterInListItemAtLevel' . (s:level) . ' ' +    \ . 'display contained ' +    \ . '/^' . (s:indented_as_content) . '\%(-\+\|=\+\)$/' +  execute 'hi def link markdownH1InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownH2InListItemAtLevel' . (s:level) . ' Title' +  execute 'hi def link markdownHeadingDelimiterInListItemAtLevel' . (s:level) . ' Special' + +  execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' ' +    \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '*\*\s*\*\s*\*[[:space:]*]*$/ display' +  execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' ' +    \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '-\s*-\s*-[[:space:]-]*$/ display' +  execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' ' +    \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '_\s*_\s*_[[:space:]_]*$/ display' +  execute 'hi def link markdownRuleInListItemAtLevel' . (s:level) . ' Identifier' + +  execute 'syn region markdownBlockquoteInListItemAtLevel' . (s:level) . ' ' +    \ . 'contained ' +    \ . 'contains=markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ',@NoSpell ' +    \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '\%(>\s\?\)\+\%(.\)\@=/ ' +    \ . 'end=/\n\n/' +  execute 'syn match markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ' ' +    \ . 'contained ' +    \ . '/^' . (s:indented_as_content) . '\%(>\s\?\)\+/' +  execute 'hi def link markdownBlockquoteInListItemAtLevel' . (s:level) . ' Comment' +  execute 'hi def link markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ' Delimiter' + +  " " the only constraint here is that the table begins at least at the same +  " " level as the list item's content, se we could reuse the previous syntactic +  " " elements, we could do that because tables could have arbitrary indentation +  execute 'syn match markdownTableInListItemAtLevel' . (s:level) . ' ' +    \ . 'transparent contained contains=markdownTableHeader,markdownTableDelimiter,@markdownInline ' +    \ . '/' +    \ .   '^\s*\n' +    \ .   (s:indented_as_content) . '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n' +    \ .   s:markdown_table_header_rows_separator . '\n' +    \ .   '\%(' +    \ .     '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n' +    \ .   '\)*' +    \ .   '$' +    \ . '/' +endfor +hi def link markdownItemDelimiter Special +hi def link markdownFencedCodeBlockInItemDelimiter Special + +" }}} + + +" {{{ EMOTICONS + +syn keyword markdownEmoticonKeyword :bowtie: :smile: :laughing: :blush: :smiley: +syn keyword markdownEmoticonKeyword :bowtie: :smile: :laughing: :blush: :smiley: +syn keyword markdownEmoticonKeyword :relaxed: :smirk: :heart_eyes: :kissing_heart: :kissing_closed_eyes: +syn keyword markdownEmoticonKeyword :flushed: :relieved: :satisfied: :grin: :wink: +syn keyword markdownEmoticonKeyword :stuck_out_tongue_winking_eye: :stuck_out_tongue_closed_eyes: :grinning: :kissing: :kissing_smiling_eyes: +syn keyword markdownEmoticonKeyword :stuck_out_tongue: :sleeping: :worried: :frowning: :anguished: +syn keyword markdownEmoticonKeyword :open_mouth: :grimacing: :confused: :hushed: :expressionless: +syn keyword markdownEmoticonKeyword :unamused: :sweat_smile: :sweat: :disappointed_relieved: :weary: +syn keyword markdownEmoticonKeyword :pensive: :disappointed: :confounded: :fearful: :cold_sweat: +syn keyword markdownEmoticonKeyword :persevere: :cry: :sob: :joy: :astonished: +syn keyword markdownEmoticonKeyword :scream: :neckbeard: :tired_face: :angry: :rage: +syn keyword markdownEmoticonKeyword :triumph: :sleepy: :yum: :mask: :sunglasses: +syn keyword markdownEmoticonKeyword :dizzy_face: :imp: :smiling_imp: :neutral_face: :no_mouth: +syn keyword markdownEmoticonKeyword :innocent: :alien: :yellow_heart: :blue_heart: :purple_heart: +syn keyword markdownEmoticonKeyword :heart: :green_heart: :broken_heart: :heartbeat: :heartpulse: +syn keyword markdownEmoticonKeyword :two_hearts: :revolving_hearts: :cupid: :sparkling_heart: :sparkles: +syn keyword markdownEmoticonKeyword :star: :star2: :dizzy: :boom: :collision: +syn keyword markdownEmoticonKeyword :anger: :exclamation: :question: :grey_exclamation: :grey_question: +syn keyword markdownEmoticonKeyword :zzz: :dash: :sweat_drops: :notes: :musical_note: +syn keyword markdownEmoticonKeyword :fire: :hankey: :poop: :shit: :+1: +syn keyword markdownEmoticonKeyword :thumbsup: :-1: :thumbsdown: :ok_hand: :punch: +syn keyword markdownEmoticonKeyword :facepunch: :fist: :v: :wave: :hand: +syn keyword markdownEmoticonKeyword :raised_hand: :open_hands: :point_up: :point_down: :point_left: +syn keyword markdownEmoticonKeyword :point_right: :raised_hands: :pray: :point_up_2: :clap: +syn keyword markdownEmoticonKeyword :muscle: :metal: :fu: :walking: :runner: +syn keyword markdownEmoticonKeyword :running: :couple: :family: :two_men_holding_hands: :two_women_holding_hands: +syn keyword markdownEmoticonKeyword :dancer: :dancers: :ok_woman: :no_good: :information_desk_person: +syn keyword markdownEmoticonKeyword :raising_hand: :bride_with_veil: :person_with_pouting_face: :person_frowning: :bow: +syn keyword markdownEmoticonKeyword :couplekiss: :couple_with_heart: :massage: :haircut: :nail_care: +syn keyword markdownEmoticonKeyword :boy: :girl: :woman: :man: :baby: +syn keyword markdownEmoticonKeyword :older_woman: :older_man: :person_with_blond_hair: :man_with_gua_pi_mao: :man_with_turban: +syn keyword markdownEmoticonKeyword :construction_worker: :cop: :angel: :princess: :smiley_cat: +syn keyword markdownEmoticonKeyword :smile_cat: :heart_eyes_cat: :kissing_cat: :smirk_cat: :scream_cat: +syn keyword markdownEmoticonKeyword :crying_cat_face: :joy_cat: :pouting_cat: :japanese_ogre: :japanese_goblin: +syn keyword markdownEmoticonKeyword :see_no_evil: :hear_no_evil: :speak_no_evil: :guardsman: :skull: +syn keyword markdownEmoticonKeyword :feet: :lips: :kiss: :droplet: :ear: +syn keyword markdownEmoticonKeyword :eyes: :nose: :tongue: :love_letter: :bust_in_silhouette: +syn keyword markdownEmoticonKeyword :busts_in_silhouette: :speech_balloon: :thought_balloon: :feelsgood: :finnadie: +syn keyword markdownEmoticonKeyword :goberserk: :godmode: :hurtrealbad: :rage1: :rage2: +syn keyword markdownEmoticonKeyword :rage3: :rage4: :suspect: :trollface: :sunny: +syn keyword markdownEmoticonKeyword :umbrella: :cloud: :snowflake: :snowman: :zap: +syn keyword markdownEmoticonKeyword :cyclone: :foggy: :ocean: :cat: :dog: +syn keyword markdownEmoticonKeyword :mouse: :hamster: :rabbit: :wolf: :frog: +syn keyword markdownEmoticonKeyword :tiger: :koala: :bear: :pig: :pig_nose: +syn keyword markdownEmoticonKeyword :cow: :boar: :monkey_face: :monkey: :horse: +syn keyword markdownEmoticonKeyword :racehorse: :camel: :sheep: :elephant: :panda_face: +syn keyword markdownEmoticonKeyword :snake: :bird: :baby_chick: :hatched_chick: :hatching_chick: +syn keyword markdownEmoticonKeyword :chicken: :penguin: :turtle: :bug: :honeybee: +syn keyword markdownEmoticonKeyword :ant: :beetle: :snail: :octopus: :tropical_fish: +syn keyword markdownEmoticonKeyword :fish: :whale: :whale2: :dolphin: :cow2: +syn keyword markdownEmoticonKeyword :ram: :rat: :water_buffalo: :tiger2: :rabbit2: +syn keyword markdownEmoticonKeyword :dragon: :goat: :rooster: :dog2: :pig2: +syn keyword markdownEmoticonKeyword :mouse2: :ox: :dragon_face: :blowfish: :crocodile: +syn keyword markdownEmoticonKeyword :dromedary_camel: :leopard: :cat2: :poodle: :paw_prints: +syn keyword markdownEmoticonKeyword :bouquet: :cherry_blossom: :tulip: :four_leaf_clover: :rose: +syn keyword markdownEmoticonKeyword :sunflower: :hibiscus: :maple_leaf: :leaves: :fallen_leaf: +syn keyword markdownEmoticonKeyword :herb: :mushroom: :cactus: :palm_tree: :evergreen_tree: +syn keyword markdownEmoticonKeyword :deciduous_tree: :chestnut: :seedling: :blossom: :ear_of_rice: +syn keyword markdownEmoticonKeyword :shell: :globe_with_meridians: :sun_with_face: :full_moon_with_face: :new_moon_with_face: +syn keyword markdownEmoticonKeyword :new_moon: :waxing_crescent_moon: :first_quarter_moon: :waxing_gibbous_moon: :full_moon: +syn keyword markdownEmoticonKeyword :waning_gibbous_moon: :last_quarter_moon: :waning_crescent_moon: :last_quarter_moon_with_face: :first_quarter_moon_with_face: +syn keyword markdownEmoticonKeyword :moon: :earth_africa: :earth_americas: :earth_asia: :volcano: +syn keyword markdownEmoticonKeyword :milky_way: :partly_sunny: :octocat: :squirrel: :bamboo: +syn keyword markdownEmoticonKeyword :gift_heart: :dolls: :school_satchel: :mortar_board: :flags: +syn keyword markdownEmoticonKeyword :fireworks: :sparkler: :wind_chime: :rice_scene: :jack_o_lantern: +syn keyword markdownEmoticonKeyword :ghost: :santa: :christmas_tree: :gift: :bell: +syn keyword markdownEmoticonKeyword :no_bell: :tanabata_tree: :tada: :confetti_ball: :balloon: +syn keyword markdownEmoticonKeyword :crystal_ball: :cd: :dvd: :floppy_disk: :camera: +syn keyword markdownEmoticonKeyword :video_camera: :movie_camera: :computer: :tv: :iphone: +syn keyword markdownEmoticonKeyword :phone: :telephone: :telephone_receiver: :pager: :fax: +syn keyword markdownEmoticonKeyword :minidisc: :vhs: :sound: :speaker: :mute: +syn keyword markdownEmoticonKeyword :loudspeaker: :mega: :hourglass: :hourglass_flowing_sand: :alarm_clock: +syn keyword markdownEmoticonKeyword :watch: :radio: :satellite: :loop: :mag: +syn keyword markdownEmoticonKeyword :mag_right: :unlock: :lock: :lock_with_ink_pen: :closed_lock_with_key: +syn keyword markdownEmoticonKeyword :key: :bulb: :flashlight: :high_brightness: :low_brightness: +syn keyword markdownEmoticonKeyword :electric_plug: :battery: :calling: :email: :mailbox: +syn keyword markdownEmoticonKeyword :postbox: :bath: :bathtub: :shower: :toilet: +syn keyword markdownEmoticonKeyword :wrench: :nut_and_bolt: :hammer: :seat: :moneybag: +syn keyword markdownEmoticonKeyword :yen: :dollar: :pound: :euro: :credit_card: +syn keyword markdownEmoticonKeyword :money_with_wings: :e-mail: :inbox_tray: :outbox_tray: :envelope: +syn keyword markdownEmoticonKeyword :incoming_envelope: :postal_horn: :mailbox_closed: :mailbox_with_mail: :mailbox_with_no_mail: +syn keyword markdownEmoticonKeyword :door: :smoking: :bomb: :gun: :hocho: +syn keyword markdownEmoticonKeyword :pill: :syringe: :page_facing_up: :page_with_curl: :bookmark_tabs: +syn keyword markdownEmoticonKeyword :bar_chart: :chart_with_upwards_trend: :chart_with_downwards_trend: :scroll: :clipboard: +syn keyword markdownEmoticonKeyword :calendar: :date: :card_index: :file_folder: :open_file_folder: +syn keyword markdownEmoticonKeyword :scissors: :pushpin: :paperclip: :black_nib: :pencil2: +syn keyword markdownEmoticonKeyword :straight_ruler: :triangular_ruler: :closed_book: :green_book: :blue_book: +syn keyword markdownEmoticonKeyword :orange_book: :notebook: :notebook_with_decorative_cover: :ledger: :books: +syn keyword markdownEmoticonKeyword :bookmark: :name_badge: :microscope: :telescope: :newspaper: +syn keyword markdownEmoticonKeyword :football: :basketball: :soccer: :baseball: :tennis: +syn keyword markdownEmoticonKeyword :8ball: :rugby_football: :bowling: :golf: :mountain_bicyclist: +syn keyword markdownEmoticonKeyword :bicyclist: :horse_racing: :snowboarder: :swimmer: :surfer: +syn keyword markdownEmoticonKeyword :ski: :spades: :hearts: :clubs: :diamonds: +syn keyword markdownEmoticonKeyword :gem: :ring: :trophy: :musical_score: :musical_keyboard: +syn keyword markdownEmoticonKeyword :violin: :space_invader: :video_game: :black_joker: :flower_playing_cards: +syn keyword markdownEmoticonKeyword :game_die: :dart: :mahjong: :clapper: :memo: +syn keyword markdownEmoticonKeyword :pencil: :book: :art: :microphone: :headphones: +syn keyword markdownEmoticonKeyword :trumpet: :saxophone: :guitar: :shoe: :sandal: +syn keyword markdownEmoticonKeyword :high_heel: :lipstick: :boot: :shirt: :tshirt: +syn keyword markdownEmoticonKeyword :necktie: :womans_clothes: :dress: :running_shirt_with_sash: :jeans: +syn keyword markdownEmoticonKeyword :kimono: :bikini: :ribbon: :tophat: :crown: +syn keyword markdownEmoticonKeyword :womans_hat: :mans_shoe: :closed_umbrella: :briefcase: :handbag: +syn keyword markdownEmoticonKeyword :pouch: :purse: :eyeglasses: :fishing_pole_and_fish: :coffee: +syn keyword markdownEmoticonKeyword :tea: :sake: :baby_bottle: :beer: :beers: +syn keyword markdownEmoticonKeyword :cocktail: :tropical_drink: :wine_glass: :fork_and_knife: :pizza: +syn keyword markdownEmoticonKeyword :hamburger: :fries: :poultry_leg: :meat_on_bone: :spaghetti: +syn keyword markdownEmoticonKeyword :curry: :fried_shrimp: :bento: :sushi: :fish_cake: +syn keyword markdownEmoticonKeyword :rice_ball: :rice_cracker: :rice: :ramen: :stew: +syn keyword markdownEmoticonKeyword :oden: :dango: :egg: :bread: :doughnut: +syn keyword markdownEmoticonKeyword :custard: :icecream: :ice_cream: :shaved_ice: :birthday: +syn keyword markdownEmoticonKeyword :cake: :cookie: :chocolate_bar: :candy: :lollipop: +syn keyword markdownEmoticonKeyword :honey_pot: :apple: :green_apple: :tangerine: :lemon: +syn keyword markdownEmoticonKeyword :cherries: :grapes: :watermelon: :strawberry: :peach: +syn keyword markdownEmoticonKeyword :melon: :banana: :pear: :pineapple: :sweet_potato: +syn keyword markdownEmoticonKeyword :eggplant: :tomato: :corn: :house: :house_with_garden: +syn keyword markdownEmoticonKeyword :school: :office: :post_office: :hospital: :bank: +syn keyword markdownEmoticonKeyword :convenience_store: :love_hotel: :hotel: :wedding: :church: +syn keyword markdownEmoticonKeyword :department_store: :european_post_office: :city_sunrise: :city_sunset: :japanese_castle: +syn keyword markdownEmoticonKeyword :european_castle: :tent: :factory: :tokyo_tower: :japan: +syn keyword markdownEmoticonKeyword :mount_fuji: :sunrise_over_mountains: :sunrise: :stars: :statue_of_liberty: +syn keyword markdownEmoticonKeyword :bridge_at_night: :carousel_horse: :rainbow: :ferris_wheel: :fountain: +syn keyword markdownEmoticonKeyword :roller_coaster: :ship: :speedboat: :boat: :sailboat: +syn keyword markdownEmoticonKeyword :rowboat: :anchor: :rocket: :airplane: :helicopter: +syn keyword markdownEmoticonKeyword :steam_locomotive: :tram: :mountain_railway: :bike: :aerial_tramway: +syn keyword markdownEmoticonKeyword :suspension_railway: :mountain_cableway: :tractor: :blue_car: :oncoming_automobile: +syn keyword markdownEmoticonKeyword :car: :red_car: :taxi: :oncoming_taxi: :articulated_lorry: +syn keyword markdownEmoticonKeyword :bus: :oncoming_bus: :rotating_light: :police_car: :oncoming_police_car: +syn keyword markdownEmoticonKeyword :fire_engine: :ambulance: :minibus: :truck: :train: +syn keyword markdownEmoticonKeyword :station: :train2: :bullettrain_front: :bullettrain_side: :light_rail: +syn keyword markdownEmoticonKeyword :monorail: :railway_car: :trolleybus: :ticket: :fuelpump: +syn keyword markdownEmoticonKeyword :vertical_traffic_light: :traffic_light: :warning: :construction: :beginner: +syn keyword markdownEmoticonKeyword :atm: :slot_machine: :busstop: :barber: :hotsprings: +syn keyword markdownEmoticonKeyword :checkered_flag: :crossed_flags: :izakaya_lantern: :moyai: :circus_tent: +syn keyword markdownEmoticonKeyword :performing_arts: :round_pushpin: :triangular_flag_on_post: :jp: :kr: +syn keyword markdownEmoticonKeyword :cn: :us: :fr: :es: :it: +syn keyword markdownEmoticonKeyword :ru: :gb: :uk: :de: :one: +syn keyword markdownEmoticonKeyword :two: :three: :four: :five: :six: +syn keyword markdownEmoticonKeyword :seven: :eight: :nine: :keycap_ten: :1234: +syn keyword markdownEmoticonKeyword :zero: :hash: :symbols: :arrow_backward: :arrow_down: +syn keyword markdownEmoticonKeyword :arrow_forward: :arrow_left: :capital_abcd: :abcd: :abc: +syn keyword markdownEmoticonKeyword :arrow_lower_left: :arrow_lower_right: :arrow_right: :arrow_up: :arrow_upper_left: +syn keyword markdownEmoticonKeyword :arrow_upper_right: :arrow_double_down: :arrow_double_up: :arrow_down_small: :arrow_heading_down: +syn keyword markdownEmoticonKeyword :arrow_heading_up: :leftwards_arrow_with_hook: :arrow_right_hook: :left_right_arrow: :arrow_up_down: +syn keyword markdownEmoticonKeyword :arrow_up_small: :arrows_clockwise: :arrows_counterclockwise: :rewind: :fast_forward: +syn keyword markdownEmoticonKeyword :information_source: :ok: :twisted_rightwards_arrows: :repeat: :repeat_one: +syn keyword markdownEmoticonKeyword :new: :top: :up: :cool: :free: +syn keyword markdownEmoticonKeyword :ng: :cinema: :koko: :signal_strength: :u5272: +syn keyword markdownEmoticonKeyword :u5408: :u55b6: :u6307: :u6708: :u6709: +syn keyword markdownEmoticonKeyword :u6e80: :u7121: :u7533: :u7a7a: :u7981: +syn keyword markdownEmoticonKeyword :sa: :restroom: :mens: :womens: :baby_symbol: +syn keyword markdownEmoticonKeyword :no_smoking: :parking: :wheelchair: :metro: :baggage_claim: +syn keyword markdownEmoticonKeyword :accept: :wc: :potable_water: :put_litter_in_its_place: :secret: +syn keyword markdownEmoticonKeyword :congratulations: :m: :passport_control: :left_luggage: :customs: +syn keyword markdownEmoticonKeyword :ideograph_advantage: :cl: :sos: :id: :no_entry_sign: +syn keyword markdownEmoticonKeyword :underage: :no_mobile_phones: :do_not_litter: :non-potable_water: :no_bicycles: +syn keyword markdownEmoticonKeyword :no_pedestrians: :children_crossing: :no_entry: :eight_spoked_asterisk: :eight_pointed_black_star: +syn keyword markdownEmoticonKeyword :heart_decoration: :vs: :vibration_mode: :mobile_phone_off: :chart: +syn keyword markdownEmoticonKeyword :currency_exchange: :aries: :taurus: :gemini: :cancer: +syn keyword markdownEmoticonKeyword :leo: :virgo: :libra: :scorpius: :sagittarius: +syn keyword markdownEmoticonKeyword :capricorn: :aquarius: :pisces: :ophiuchus: :six_pointed_star: +syn keyword markdownEmoticonKeyword :negative_squared_cross_mark: :a: :b: :ab: :o2: +syn keyword markdownEmoticonKeyword :diamond_shape_with_a_dot_inside: :recycle: :end: :on: :soon: +syn keyword markdownEmoticonKeyword :clock1: :clock130: :clock10: :clock1030: :clock11: +syn keyword markdownEmoticonKeyword :clock1130: :clock12: :clock1230: :clock2: :clock230: +syn keyword markdownEmoticonKeyword :clock3: :clock330: :clock4: :clock430: :clock5: +syn keyword markdownEmoticonKeyword :clock530: :clock6: :clock630: :clock7: :clock730: +syn keyword markdownEmoticonKeyword :clock8: :clock830: :clock9: :clock930: :heavy_dollar_sign: +syn keyword markdownEmoticonKeyword :copyright: :registered: :tm: :x: :heavy_exclamation_mark: +syn keyword markdownEmoticonKeyword :bangbang: :interrobang: :o: :heavy_multiplication_x: :heavy_plus_sign: +syn keyword markdownEmoticonKeyword :heavy_minus_sign: :heavy_division_sign: :white_flower: :100: :heavy_check_mark: +syn keyword markdownEmoticonKeyword :ballot_box_with_check: :radio_button: :link: :curly_loop: :wavy_dash: +syn keyword markdownEmoticonKeyword :part_alternation_mark: :trident: :black_square: :white_square: :white_check_mark: +syn keyword markdownEmoticonKeyword :black_square_button: :white_square_button: :black_circle: :white_circle: :red_circle: +syn keyword markdownEmoticonKeyword :large_blue_circle: :large_blue_diamond: :large_orange_diamond: :small_blue_diamond: :small_orange_diamond: +syn keyword markdownEmoticonKeyword :small_red_triangle: :small_red_triangle_down: :shipit: :relaxed: :smirk: +syn keyword markdownEmoticonKeyword :heart_eyes: :kissing_heart: :kissing_closed_eyes: :flushed: :relieved: +syn keyword markdownEmoticonKeyword :satisfied: :grin: :wink: :stuck_out_tongue_winking_eye: :stuck_out_tongue_closed_eyes: +syn keyword markdownEmoticonKeyword :grinning: :kissing: :kissing_smiling_eyes: :stuck_out_tongue: :sleeping: +syn keyword markdownEmoticonKeyword :worried: :frowning: :anguished: :open_mouth: :grimacing: +syn keyword markdownEmoticonKeyword :confused: :hushed: :expressionless: :unamused: :sweat_smile: +syn keyword markdownEmoticonKeyword :sweat: :disappointed_relieved: :weary: :pensive: :disappointed: +syn keyword markdownEmoticonKeyword :confounded: :fearful: :cold_sweat: :persevere: :cry: +syn keyword markdownEmoticonKeyword :sob: :joy: :astonished: :scream: :neckbeard: +syn keyword markdownEmoticonKeyword :tired_face: :angry: :rage: :triumph: :sleepy: +syn keyword markdownEmoticonKeyword :yum: :mask: :sunglasses: :dizzy_face: :imp: +syn keyword markdownEmoticonKeyword :smiling_imp: :neutral_face: :no_mouth: :innocent: :alien: +syn keyword markdownEmoticonKeyword :yellow_heart: :blue_heart: :purple_heart: :heart: :green_heart: +syn keyword markdownEmoticonKeyword :broken_heart: :heartbeat: :heartpulse: :two_hearts: :revolving_hearts: +syn keyword markdownEmoticonKeyword :cupid: :sparkling_heart: :sparkles: :star: :star2: +syn keyword markdownEmoticonKeyword :dizzy: :boom: :collision: :anger: :exclamation: +syn keyword markdownEmoticonKeyword :question: :grey_exclamation: :grey_question: :zzz: :dash: +syn keyword markdownEmoticonKeyword :sweat_drops: :notes: :musical_note: :fire: :hankey: +syn keyword markdownEmoticonKeyword :poop: :shit: :+1: :thumbsup: :-1: +syn keyword markdownEmoticonKeyword :thumbsdown: :ok_hand: :punch: :facepunch: :fist: +syn keyword markdownEmoticonKeyword :v: :wave: :hand: :raised_hand: :open_hands: +syn keyword markdownEmoticonKeyword :point_up: :point_down: :point_left: :point_right: :raised_hands: +syn keyword markdownEmoticonKeyword :pray: :point_up_2: :clap: :muscle: :metal: +syn keyword markdownEmoticonKeyword :fu: :walking: :runner: :running: :couple: +syn keyword markdownEmoticonKeyword :family: :two_men_holding_hands: :two_women_holding_hands: :dancer: :dancers: +syn keyword markdownEmoticonKeyword :ok_woman: :no_good: :information_desk_person: :raising_hand: :bride_with_veil: +syn keyword markdownEmoticonKeyword :person_with_pouting_face: :person_frowning: :bow: :couplekiss: :couple_with_heart: +syn keyword markdownEmoticonKeyword :massage: :haircut: :nail_care: :boy: :girl: +syn keyword markdownEmoticonKeyword :woman: :man: :baby: :older_woman: :older_man: +syn keyword markdownEmoticonKeyword :person_with_blond_hair: :man_with_gua_pi_mao: :man_with_turban: :construction_worker: :cop: +syn keyword markdownEmoticonKeyword :angel: :princess: :smiley_cat: :smile_cat: :heart_eyes_cat: +syn keyword markdownEmoticonKeyword :kissing_cat: :smirk_cat: :scream_cat: :crying_cat_face: :joy_cat: +syn keyword markdownEmoticonKeyword :pouting_cat: :japanese_ogre: :japanese_goblin: :see_no_evil: :hear_no_evil: +syn keyword markdownEmoticonKeyword :speak_no_evil: :guardsman: :skull: :feet: :lips: +syn keyword markdownEmoticonKeyword :kiss: :droplet: :ear: :eyes: :nose: +syn keyword markdownEmoticonKeyword :tongue: :love_letter: :bust_in_silhouette: :busts_in_silhouette: :speech_balloon: +syn keyword markdownEmoticonKeyword :thought_balloon: :feelsgood: :finnadie: :goberserk: :godmode: +syn keyword markdownEmoticonKeyword :hurtrealbad: :rage1: :rage2: :rage3: :rage4: +syn keyword markdownEmoticonKeyword :suspect: :trollface: :sunny: :umbrella: :cloud: +syn keyword markdownEmoticonKeyword :snowflake: :snowman: :zap: :cyclone: :foggy: +syn keyword markdownEmoticonKeyword :ocean: :cat: :dog: :mouse: :hamster: +syn keyword markdownEmoticonKeyword :rabbit: :wolf: :frog: :tiger: :koala: +syn keyword markdownEmoticonKeyword :bear: :pig: :pig_nose: :cow: :boar: +syn keyword markdownEmoticonKeyword :monkey_face: :monkey: :horse: :racehorse: :camel: +syn keyword markdownEmoticonKeyword :sheep: :elephant: :panda_face: :snake: :bird: +syn keyword markdownEmoticonKeyword :baby_chick: :hatched_chick: :hatching_chick: :chicken: :penguin: +syn keyword markdownEmoticonKeyword :turtle: :bug: :honeybee: :ant: :beetle: +syn keyword markdownEmoticonKeyword :snail: :octopus: :tropical_fish: :fish: :whale: +syn keyword markdownEmoticonKeyword :whale2: :dolphin: :cow2: :ram: :rat: +syn keyword markdownEmoticonKeyword :water_buffalo: :tiger2: :rabbit2: :dragon: :goat: +syn keyword markdownEmoticonKeyword :rooster: :dog2: :pig2: :mouse2: :ox: +syn keyword markdownEmoticonKeyword :dragon_face: :blowfish: :crocodile: :dromedary_camel: :leopard: +syn keyword markdownEmoticonKeyword :cat2: :poodle: :paw_prints: :bouquet: :cherry_blossom: +syn keyword markdownEmoticonKeyword :tulip: :four_leaf_clover: :rose: :sunflower: :hibiscus: +syn keyword markdownEmoticonKeyword :maple_leaf: :leaves: :fallen_leaf: :herb: :mushroom: +syn keyword markdownEmoticonKeyword :cactus: :palm_tree: :evergreen_tree: :deciduous_tree: :chestnut: +syn keyword markdownEmoticonKeyword :seedling: :blossom: :ear_of_rice: :shell: :globe_with_meridians: +syn keyword markdownEmoticonKeyword :sun_with_face: :full_moon_with_face: :new_moon_with_face: :new_moon: :waxing_crescent_moon: +syn keyword markdownEmoticonKeyword :first_quarter_moon: :waxing_gibbous_moon: :full_moon: :waning_gibbous_moon: :last_quarter_moon: +syn keyword markdownEmoticonKeyword :waning_crescent_moon: :last_quarter_moon_with_face: :first_quarter_moon_with_face: :moon: :earth_africa: +syn keyword markdownEmoticonKeyword :earth_americas: :earth_asia: :volcano: :milky_way: :partly_sunny: +syn keyword markdownEmoticonKeyword :octocat: :squirrel: :bamboo: :gift_heart: :dolls: +syn keyword markdownEmoticonKeyword :school_satchel: :mortar_board: :flags: :fireworks: :sparkler: +syn keyword markdownEmoticonKeyword :wind_chime: :rice_scene: :jack_o_lantern: :ghost: :santa: +syn keyword markdownEmoticonKeyword :christmas_tree: :gift: :bell: :no_bell: :tanabata_tree: +syn keyword markdownEmoticonKeyword :tada: :confetti_ball: :balloon: :crystal_ball: :cd: +syn keyword markdownEmoticonKeyword :dvd: :floppy_disk: :camera: :video_camera: :movie_camera: +syn keyword markdownEmoticonKeyword :computer: :tv: :iphone: :phone: :telephone: +syn keyword markdownEmoticonKeyword :telephone_receiver: :pager: :fax: :minidisc: :vhs: +syn keyword markdownEmoticonKeyword :sound: :speaker: :mute: :loudspeaker: :mega: +syn keyword markdownEmoticonKeyword :hourglass: :hourglass_flowing_sand: :alarm_clock: :watch: :radio: +syn keyword markdownEmoticonKeyword :satellite: :loop: :mag: :mag_right: :unlock: +syn keyword markdownEmoticonKeyword :lock: :lock_with_ink_pen: :closed_lock_with_key: :key: :bulb: +syn keyword markdownEmoticonKeyword :flashlight: :high_brightness: :low_brightness: :electric_plug: :battery: +syn keyword markdownEmoticonKeyword :calling: :email: :mailbox: :postbox: :bath: +syn keyword markdownEmoticonKeyword :bathtub: :shower: :toilet: :wrench: :nut_and_bolt: +syn keyword markdownEmoticonKeyword :hammer: :seat: :moneybag: :yen: :dollar: +syn keyword markdownEmoticonKeyword :pound: :euro: :credit_card: :money_with_wings: :e-mail: +syn keyword markdownEmoticonKeyword :inbox_tray: :outbox_tray: :envelope: :incoming_envelope: :postal_horn: +syn keyword markdownEmoticonKeyword :mailbox_closed: :mailbox_with_mail: :mailbox_with_no_mail: :door: :smoking: +syn keyword markdownEmoticonKeyword :bomb: :gun: :hocho: :pill: :syringe: +syn keyword markdownEmoticonKeyword :page_facing_up: :page_with_curl: :bookmark_tabs: :bar_chart: :chart_with_upwards_trend: +syn keyword markdownEmoticonKeyword :chart_with_downwards_trend: :scroll: :clipboard: :calendar: :date: +syn keyword markdownEmoticonKeyword :card_index: :file_folder: :open_file_folder: :scissors: :pushpin: +syn keyword markdownEmoticonKeyword :paperclip: :black_nib: :pencil2: :straight_ruler: :triangular_ruler: +syn keyword markdownEmoticonKeyword :closed_book: :green_book: :blue_book: :orange_book: :notebook: +syn keyword markdownEmoticonKeyword :notebook_with_decorative_cover: :ledger: :books: :bookmark: :name_badge: +syn keyword markdownEmoticonKeyword :microscope: :telescope: :newspaper: :football: :basketball: +syn keyword markdownEmoticonKeyword :soccer: :baseball: :tennis: :8ball: :rugby_football: +syn keyword markdownEmoticonKeyword :bowling: :golf: :mountain_bicyclist: :bicyclist: :horse_racing: +syn keyword markdownEmoticonKeyword :snowboarder: :swimmer: :surfer: :ski: :spades: +syn keyword markdownEmoticonKeyword :hearts: :clubs: :diamonds: :gem: :ring: +syn keyword markdownEmoticonKeyword :trophy: :musical_score: :musical_keyboard: :violin: :space_invader: +syn keyword markdownEmoticonKeyword :video_game: :black_joker: :flower_playing_cards: :game_die: :dart: +syn keyword markdownEmoticonKeyword :mahjong: :clapper: :memo: :pencil: :book: +syn keyword markdownEmoticonKeyword :art: :microphone: :headphones: :trumpet: :saxophone: +syn keyword markdownEmoticonKeyword :guitar: :shoe: :sandal: :high_heel: :lipstick: +syn keyword markdownEmoticonKeyword :boot: :shirt: :tshirt: :necktie: :womans_clothes: +syn keyword markdownEmoticonKeyword :dress: :running_shirt_with_sash: :jeans: :kimono: :bikini: +syn keyword markdownEmoticonKeyword :ribbon: :tophat: :crown: :womans_hat: :mans_shoe: +syn keyword markdownEmoticonKeyword :closed_umbrella: :briefcase: :handbag: :pouch: :purse: +syn keyword markdownEmoticonKeyword :eyeglasses: :fishing_pole_and_fish: :coffee: :tea: :sake: +syn keyword markdownEmoticonKeyword :baby_bottle: :beer: :beers: :cocktail: :tropical_drink: +syn keyword markdownEmoticonKeyword :wine_glass: :fork_and_knife: :pizza: :hamburger: :fries: +syn keyword markdownEmoticonKeyword :poultry_leg: :meat_on_bone: :spaghetti: :curry: :fried_shrimp: +syn keyword markdownEmoticonKeyword :bento: :sushi: :fish_cake: :rice_ball: :rice_cracker: +syn keyword markdownEmoticonKeyword :rice: :ramen: :stew: :oden: :dango: +syn keyword markdownEmoticonKeyword :egg: :bread: :doughnut: :custard: :icecream: +syn keyword markdownEmoticonKeyword :ice_cream: :shaved_ice: :birthday: :cake: :cookie: +syn keyword markdownEmoticonKeyword :chocolate_bar: :candy: :lollipop: :honey_pot: :apple: +syn keyword markdownEmoticonKeyword :green_apple: :tangerine: :lemon: :cherries: :grapes: +syn keyword markdownEmoticonKeyword :watermelon: :strawberry: :peach: :melon: :banana: +syn keyword markdownEmoticonKeyword :pear: :pineapple: :sweet_potato: :eggplant: :tomato: +syn keyword markdownEmoticonKeyword :corn: :house: :house_with_garden: :school: :office: +syn keyword markdownEmoticonKeyword :post_office: :hospital: :bank: :convenience_store: :love_hotel: +syn keyword markdownEmoticonKeyword :hotel: :wedding: :church: :department_store: :european_post_office: +syn keyword markdownEmoticonKeyword :city_sunrise: :city_sunset: :japanese_castle: :european_castle: :tent: +syn keyword markdownEmoticonKeyword :factory: :tokyo_tower: :japan: :mount_fuji: :sunrise_over_mountains: +syn keyword markdownEmoticonKeyword :sunrise: :stars: :statue_of_liberty: :bridge_at_night: :carousel_horse: +syn keyword markdownEmoticonKeyword :rainbow: :ferris_wheel: :fountain: :roller_coaster: :ship: +syn keyword markdownEmoticonKeyword :speedboat: :boat: :sailboat: :rowboat: :anchor: +syn keyword markdownEmoticonKeyword :rocket: :airplane: :helicopter: :steam_locomotive: :tram: +syn keyword markdownEmoticonKeyword :mountain_railway: :bike: :aerial_tramway: :suspension_railway: :mountain_cableway: +syn keyword markdownEmoticonKeyword :tractor: :blue_car: :oncoming_automobile: :car: :red_car: +syn keyword markdownEmoticonKeyword :taxi: :oncoming_taxi: :articulated_lorry: :bus: :oncoming_bus: +syn keyword markdownEmoticonKeyword :rotating_light: :police_car: :oncoming_police_car: :fire_engine: :ambulance: +syn keyword markdownEmoticonKeyword :minibus: :truck: :train: :station: :train2: +syn keyword markdownEmoticonKeyword :bullettrain_front: :bullettrain_side: :light_rail: :monorail: :railway_car: +syn keyword markdownEmoticonKeyword :trolleybus: :ticket: :fuelpump: :vertical_traffic_light: :traffic_light: +syn keyword markdownEmoticonKeyword :warning: :construction: :beginner: :atm: :slot_machine: +syn keyword markdownEmoticonKeyword :busstop: :barber: :hotsprings: :checkered_flag: :crossed_flags: +syn keyword markdownEmoticonKeyword :izakaya_lantern: :moyai: :circus_tent: :performing_arts: :round_pushpin: +syn keyword markdownEmoticonKeyword :triangular_flag_on_post: :jp: :kr: :cn: :us: +syn keyword markdownEmoticonKeyword :fr: :es: :it: :ru: :gb: +syn keyword markdownEmoticonKeyword :uk: :de: :one: :two: :three: +syn keyword markdownEmoticonKeyword :four: :five: :six: :seven: :eight: +syn keyword markdownEmoticonKeyword :nine: :keycap_ten: :1234: :zero: :hash: +syn keyword markdownEmoticonKeyword :symbols: :arrow_backward: :arrow_down: :arrow_forward: :arrow_left: +syn keyword markdownEmoticonKeyword :capital_abcd: :abcd: :abc: :arrow_lower_left: :arrow_lower_right: +syn keyword markdownEmoticonKeyword :arrow_right: :arrow_up: :arrow_upper_left: :arrow_upper_right: :arrow_double_down: +syn keyword markdownEmoticonKeyword :arrow_double_up: :arrow_down_small: :arrow_heading_down: :arrow_heading_up: :leftwards_arrow_with_hook: +syn keyword markdownEmoticonKeyword :arrow_right_hook: :left_right_arrow: :arrow_up_down: :arrow_up_small: :arrows_clockwise: +syn keyword markdownEmoticonKeyword :arrows_counterclockwise: :rewind: :fast_forward: :information_source: :ok: +syn keyword markdownEmoticonKeyword :twisted_rightwards_arrows: :repeat: :repeat_one: :new: :top: +syn keyword markdownEmoticonKeyword :up: :cool: :free: :ng: :cinema: +syn keyword markdownEmoticonKeyword :koko: :signal_strength: :u5272: :u5408: :u55b6: +syn keyword markdownEmoticonKeyword :u6307: :u6708: :u6709: :u6e80: :u7121: +syn keyword markdownEmoticonKeyword :u7533: :u7a7a: :u7981: :sa: :restroom: +syn keyword markdownEmoticonKeyword :mens: :womens: :baby_symbol: :no_smoking: :parking: +syn keyword markdownEmoticonKeyword :wheelchair: :metro: :baggage_claim: :accept: :wc: +syn keyword markdownEmoticonKeyword :potable_water: :put_litter_in_its_place: :secret: :congratulations: :m: +syn keyword markdownEmoticonKeyword :passport_control: :left_luggage: :customs: :ideograph_advantage: :cl: +syn keyword markdownEmoticonKeyword :sos: :id: :no_entry_sign: :underage: :no_mobile_phones: +syn keyword markdownEmoticonKeyword :do_not_litter: :non-potable_water: :no_bicycles: :no_pedestrians: :children_crossing: +syn keyword markdownEmoticonKeyword :no_entry: :eight_spoked_asterisk: :eight_pointed_black_star: :heart_decoration: :vs: +syn keyword markdownEmoticonKeyword :vibration_mode: :mobile_phone_off: :chart: :currency_exchange: :aries: +syn keyword markdownEmoticonKeyword :taurus: :gemini: :cancer: :leo: :virgo: +syn keyword markdownEmoticonKeyword :libra: :scorpius: :sagittarius: :capricorn: :aquarius: +syn keyword markdownEmoticonKeyword :pisces: :ophiuchus: :six_pointed_star: :negative_squared_cross_mark: :a: +syn keyword markdownEmoticonKeyword :b: :ab: :o2: :diamond_shape_with_a_dot_inside: :recycle: +syn keyword markdownEmoticonKeyword :end: :on: :soon: :clock1: :clock130: +syn keyword markdownEmoticonKeyword :clock10: :clock1030: :clock11: :clock1130: :clock12: +syn keyword markdownEmoticonKeyword :clock1230: :clock2: :clock230: :clock3: :clock330: +syn keyword markdownEmoticonKeyword :clock4: :clock430: :clock5: :clock530: :clock6: +syn keyword markdownEmoticonKeyword :clock630: :clock7: :clock730: :clock8: :clock830: +syn keyword markdownEmoticonKeyword :clock9: :clock930: :heavy_dollar_sign: :copyright: :registered: +syn keyword markdownEmoticonKeyword :tm: :x: :heavy_exclamation_mark: :bangbang: :interrobang: +syn keyword markdownEmoticonKeyword :o: :heavy_multiplication_x: :heavy_plus_sign: :heavy_minus_sign: :heavy_division_sign: +syn keyword markdownEmoticonKeyword :white_flower: :100: :heavy_check_mark: :ballot_box_with_check: :radio_button: +syn keyword markdownEmoticonKeyword :link: :curly_loop: :wavy_dash: :part_alternation_mark: :trident: +syn keyword markdownEmoticonKeyword :black_square: :white_square: :white_check_mark: :black_square_button: :white_square_button: +syn keyword markdownEmoticonKeyword :black_circle: :white_circle: :red_circle: :large_blue_circle: :large_blue_diamond: +syn keyword markdownEmoticonKeyword :large_orange_diamond: :small_blue_diamond: :small_orange_diamond: :small_red_triangle: :small_red_triangle_down: +syn keyword markdownEmoticonKeyword :shipit: + +" }}} + + +" {{{ HIGHLIGHT DEFINITION + +hi def Italic                       term=italic cterm=italic gui=italic +hi def Bold                         term=bold cterm=bold gui=bold +hi def BoldItalic                   term=bold,italic cterm=bold,italic gui=bold,italic + +hi def link markdownItalic                  Italic +hi def link markdownBold                    Bold +hi def link markdownBoldItalic              BoldItalic + +hi def link markdownPullRequestLinkInText   Underlined +hi def link markdownUserLinkInText          Underlined +hi def link markdownUrlLinkInText           Underlined +hi def link markdownEmailLinkInText         Underlined + +hi def link markdownLinkText                Underlined +hi def link markdownLinkUrl                 Underlined +hi def link markdownLinkTitleSingleQuoted   Bold +hi def link markdownLinkTitleDoubleQuoted   Bold +hi def link markdownLinkUrlContainer        Delimiter +hi def link markdownLinkTextContainer       Delimiter +hi def link markdownLinkReference           NonText + +hi def link markdownCodeDelimiter           Delimiter +hi def link markdownInlineCode              String +hi def link markdownFencedCodeBlock         String +hi def link markdownCodeBlock               String + +hi def link markdownTableDelimiter          Delimiter +hi def link markdownTableHeader             Bold + +hi def link markdownStrike                  NonText +hi def link markdownStrikeDelimiter         Delimiter +hi def link markdownBlockquote              Comment +hi def link markdownBlockquoteDelimiter     Delimiter +hi def link markdownInlineDelimiter         Delimiter +hi def link markdownListDelimiter           Delimiter + +hi def link markdownHeaderId                Delimiter +hi def link markdownHeadingDelimiter        Delimiter +hi def link markdownHeadingUnderline        Delimiter +hi def link markdownHeader                  Title +hi def link markdownH1                      Title +hi def link markdownH2                      Title +hi def link markdownH3                      Title +hi def link markdownH4                      Title +hi def link markdownH5                      Title +hi def link markdownH6                      Title + +hi def link markdownEmoticonKeyword         Statement +hi def link markdownRule                    Identifier + +hi def link markdownXmlComment              NonText +hi def link markdownXmlElement              NonText +hi def link markdownXmlEmptyElement         NonText +hi def link markdownXmlEntities             Special + +" }}} + + +if !exists('g:markdown_include_jekyll_support') || g:markdown_include_jekyll_support +  execute 'runtime! syntax/markdown_jekyll.vim'  endif -syn cluster mkdNonListItem contains=@htmlTop,htmlItalic,htmlBold,htmlBoldItalic,mkdFootnotes,mkdInlineURL,mkdLink,mkdLinkDef,mkdLineBreak,mkdBlockquote,mkdCode,mkdRule,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,mkdMath,mkdStrike - -"highlighting for Markdown groups -HtmlHiLink mkdString        String -HtmlHiLink mkdCode          String -HtmlHiLink mkdCodeDelimiter String -HtmlHiLink mkdCodeStart     String -HtmlHiLink mkdCodeEnd       String -HtmlHiLink mkdFootnote      Comment -HtmlHiLink mkdBlockquote    Comment -HtmlHiLink mkdListItem      Identifier -HtmlHiLink mkdRule          Identifier -HtmlHiLink mkdLineBreak     Visual -HtmlHiLink mkdFootnotes     htmlLink -HtmlHiLink mkdLink          htmlLink -HtmlHiLink mkdURL           htmlString -HtmlHiLink mkdInlineURL     htmlLink -HtmlHiLink mkdID            Identifier -HtmlHiLink mkdLinkDef       mkdID -HtmlHiLink mkdLinkDefTarget mkdURL -HtmlHiLink mkdLinkTitle     htmlString -HtmlHiLink mkdDelimiter     Delimiter - -let b:current_syntax = "mkd" - -delcommand HtmlHiLink -" vim: ts=8 +let b:current_syntax = "markdown" +if main_syntax ==# 'markdown' +  unlet main_syntax +endif  endif diff --git a/syntax/markdown_jekyll.vim b/syntax/markdown_jekyll.vim new file mode 100644 index 00000000..68bf549b --- /dev/null +++ b/syntax/markdown_jekyll.vim @@ -0,0 +1,34 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1 + +let b:markdown_in_jekyll=0 + +if getline(1) =~ '^---\s*$' +  let b:markdown_in_jekyll=1 + +  syn region markdownJekyllFrontMatter matchgroup=markdownJekyllDelimiter contains=@NoSpell +    \ start="\%^---" end="^---$" + +  syn region markdownJekyllLiquidTag matchgroup=markdownJekyllDelimiter contains=@NoSpell oneline +    \ start="{%" end="%}" + +  syn region markdownJekyllLiquidOutputTag matchgroup=markdownJekyllDelimiter contains=@NoSpell oneline +    \ start="{{" skip=/"}}"/ end="}}" + +  syn region markdownJekyllLiquidBlockTag matchgroup=markdownJekyllDelimiter contains=@NoSpell +    \ start="{%\s*\z(comment\|raw\|highlight\)[^%]*%}" end="{%\s*\%(no\|end\)\z1\s*%}" + +  silent spell! nocomment +  silent spell! endcomment +  silent spell! nohighlight +  silent spell! endhighlight +  silent spell! noraw +  silent spell! endraw + +  hi def link markdownJekyllFrontMatter         NonText +  hi def link markdownJekyllLiquidTag           NonText +  hi def link markdownJekyllLiquidOutputTag     NonText +  hi def link markdownJekyllLiquidBlockTag      NonText +  hi def link markdownJekyllDelimiter           Delimiter +endif + +endif | 
