summaryrefslogtreecommitdiff
path: root/vim/bundle/vim-racer
diff options
context:
space:
mode:
authorNick Shipp <nick@shipp.ninja>2017-05-07 09:04:01 -0400
committerNick Shipp <nick@shipp.ninja>2017-05-07 09:04:01 -0400
commitc012f55efda29f09179e921cf148d79deb57616e (patch)
treeff0ad37f22622d51194cab192a2aa4b0106d7ad0 /vim/bundle/vim-racer
parent4ca8f6608883d230131f8a9e8b6d6c091c516049 (diff)
Much maturering of vim configs
Diffstat (limited to 'vim/bundle/vim-racer')
-rw-r--r--vim/bundle/vim-racer/.gitignore1
-rw-r--r--vim/bundle/vim-racer/README.md60
-rw-r--r--vim/bundle/vim-racer/autoload/racer.vim265
-rw-r--r--vim/bundle/vim-racer/ftplugin/rust_racer.vim44
-rw-r--r--vim/bundle/vim-racer/rplugin/python3/deoplete/sources/racer.py111
-rw-r--r--vim/bundle/vim-racer/syntax/rustdoc.vim178
6 files changed, 659 insertions, 0 deletions
diff --git a/vim/bundle/vim-racer/.gitignore b/vim/bundle/vim-racer/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/vim/bundle/vim-racer/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/vim/bundle/vim-racer/README.md b/vim/bundle/vim-racer/README.md
new file mode 100644
index 0000000..b56655d
--- /dev/null
+++ b/vim/bundle/vim-racer/README.md
@@ -0,0 +1,60 @@
+# Vim Racer Plugin
+
+This plugin allows vim to use [Racer](http://github.com/phildawes/racer) for Rust code completion and navigation.
+
+## Installation
+
+1. Build / Install [Racer](http://github.com/phildawes/racer)
+
+2. Install using Pathogen, Vundle or NeoBundle. Or, copy `plugin/racer.vim` into your `~/.vim/plugin` directory.
+
+ Vundle users:
+ ```
+ Plugin 'racer-rust/vim-racer'
+ ```
+
+ NeoBundle users:
+ ```
+ NeoBundle 'racer-rust/vim-racer'
+ ```
+
+ vim-plug users:
+ ```
+ Plug 'racer-rust/vim-racer'
+ ```
+
+ Pathogen users:
+ ```
+ git clone --depth=1 https://github.com/racer-rust/vim-racer.git ~/.vim/bundle/vim-racer
+ ```
+
+3. Add `g:racer_cmd` to your `.vimrc`. Also it's worth turning on 'hidden' mode for buffers otherwise you need to save the current buffer every time you do a goto-definition. E.g.:
+
+ ```
+ set hidden
+ let g:racer_cmd = "/path/to/racer/bin"
+ ```
+
+4. If you want completions to show the complete function definition (e.g. its arguments and return type), enable the experimental completer:
+
+ ```
+ let g:racer_experimental_completer = 1
+ ```
+
+## Example Mappings
+
+vim-racer enables `C-x-C-o` to search for completions and provides several
+`<Plug>` mappings for source code navigation. These mappings are not enabled by
+default but you can easily use them by adding the following lines to your
+`.vimrc` (Or `init.vim` in case of Neovim).
+
+For example, with the following mappings you can navigate to the identifier under
+the cursor and open it on the current buffer, on an horizontal or vertical split,
+or go straight to the documentation:
+
+```
+au FileType rust nmap gd <Plug>(rust-def)
+au FileType rust nmap gs <Plug>(rust-def-split)
+au FileType rust nmap gx <Plug>(rust-def-vertical)
+au FileType rust nmap <leader>gd <Plug>(rust-doc)
+```
diff --git a/vim/bundle/vim-racer/autoload/racer.vim b/vim/bundle/vim-racer/autoload/racer.vim
new file mode 100644
index 0000000..5cb80d7
--- /dev/null
+++ b/vim/bundle/vim-racer/autoload/racer.vim
@@ -0,0 +1,265 @@
+function! s:RacerGetPrefixCol(base)
+ let col = col('.') - 1
+ let b:racer_col = col
+ let b:tmpfname = tempname()
+ call writefile(s:RacerGetBufferContents(a:base), b:tmpfname)
+ let cmd = g:racer_cmd . ' prefix ' . line('.') . ' ' . col . ' ' . b:tmpfname
+ let res = system(cmd)
+ let prefixline = split(res, '\n')[0]
+ let startbyte = split(prefixline[7:], ',')[0]
+ return startbyte - line2byte(byte2line(startbyte)) + 1
+endfunction
+
+function! s:RacerGetExpCompletions(base)
+ let col = col('.')-1
+ let b:tmpfname = tempname()
+ call writefile(s:RacerGetBufferContents(a:base), b:tmpfname)
+ let fname = expand('%:p')
+ let cmd = g:racer_cmd . ' complete ' . line('.') . ' ' . col . ' "' . fname . '" "' . b:tmpfname . '"'
+ let res = system(cmd)
+
+ let typeMap = {
+ \ 'Struct' : 's', 'Module' : 'M', 'Function' : 'f',
+ \ 'Crate' : 'C', 'Let' : 'v', 'StructField' : 'm',
+ \ 'Impl' : 'i', 'Enum' : 'e', 'EnumVariant' : 'E',
+ \ 'Type' : 't', 'FnArg' : 'v', 'Trait' : 'T'
+ \ }
+
+ let lines = split(res, '\n')
+ let out = []
+
+ for line in lines
+ if line !~# '^MATCH'
+ continue
+ endif
+
+ let completions = split(line[6:], ',')
+ let kind = get(typeMap, completions[4])
+ let completion = { 'kind' : kind, 'word' : completions[0], 'dup' : 1 }
+ let info = join(completions[5:], ',')
+
+ if kind ==# 'f'
+ " function
+ let completion['menu'] = substitute(
+ \ substitute(
+ \ substitute(info, '\(pub\|fn\) ', '', 'g'),
+ \ '{*$', '', ''
+ \ ),
+ \ ' where\s\?.*$', '', ''
+ \ )
+ if g:racer_insert_paren == 1
+ let completion['abbr'] = completions[0]
+ let completion['word'] .= '('
+ endif
+ let completion['info'] = info
+ elseif kind ==# 's' " struct
+ let completion['menu'] = substitute(
+ \ substitute(info, '\(pub\|struct\) ', '', 'g'),
+ \ '{*$', '', ''
+ \ )
+ endif
+
+ if stridx(tolower(completions[0]), tolower(a:base)) == 0
+ let out = add(out, completion)
+ endif
+ endfor
+ call delete(b:tmpfname)
+ return out
+endfunction
+
+function! s:RacerSplitLine(line)
+ let separator = ';'
+ let placeholder = '{PLACEHOLDER}'
+ let line = substitute(a:line, '\\;', placeholder, 'g')
+ let parts = split(line, separator)
+ let docs = substitute(
+ \ substitute(
+ \ substitute(
+ \ substitute(get(parts, 7, ''), '^\"\(.*\)\"$', '\1', ''),
+ \ '\\\"', '\"', 'g'
+ \ ),
+ \ '\\''', '''', 'g'
+ \ ),
+ \ '\\n', '\n', 'g'
+ \ )
+ let parts = add(parts[:6], docs)
+ let parts = map(copy(parts), 'substitute(v:val, ''{PLACEHOLDER}'', '';'', ''g'')')
+
+ return parts
+endfunction
+
+function! racer#ShowDocumentation()
+ let winview = winsaveview() " Save the current cursor position
+ " Move to the end of the word for the entire token to search.
+ " Move one char back to avoid moving to the end of the *next* word.
+ execute 'normal he'
+ let col = col('.')
+ let b:tmpfname = tempname()
+ " Create temporary file with the buffer's current state
+ call writefile(getline(1, '$'), b:tmpfname)
+ let fname = expand('%:p')
+ let cmd = g:racer_cmd . ' complete-with-snippet ' . line('.') . ' ' . col . ' ' . fname . ' ' . b:tmpfname
+ let res = system(cmd)
+ " Restore de cursor position
+ call winrestview(winview)
+ " Delete the temporary file
+ call delete(b:tmpfname)
+ let lines = split(res, '\n')
+ for line in lines
+ if line !~# '^MATCH'
+ continue
+ endif
+
+ let docs = s:RacerSplitLine(line[6:])[7]
+ if len(docs) == 0
+ break
+ endif
+
+ " Only open doc buffer if there're docs to show
+ let bn = bufnr('__doc__')
+ if bn > 0
+ let wi = index(tabpagebuflist(tabpagenr()), bn)
+ if wi >= 0
+ " If the __doc__ buffer is open in the current tab, jump to it
+ silent execute (wi+1) . 'wincmd w'
+ else
+ silent execute 'sbuffer ' . bn
+ endif
+ else
+ split '__doc__'
+ endif
+
+ setlocal nobuflisted
+ setlocal modifiable
+ setlocal noswapfile
+ setlocal buftype=nofile
+ silent normal! ggdG
+ silent $put=docs
+ silent normal! 1Gdd
+ setlocal nomodifiable
+ setlocal nomodified
+ setlocal filetype=rustdoc
+ break
+ endfor
+endfunction
+
+function! s:RacerGetCompletions(base)
+ let col = col('.') - 1
+ let b:tmpfname = tempname()
+ " HACK: Special case to offer autocompletion on a string literal
+ if getline('.')[:col-1] =~# '".*"\.$'
+ call writefile(['fn main() {', ' let x: &str = "";', ' x.', '}'], b:tmpfname)
+ let fname = expand('%:p')
+ let cmd = g:racer_cmd . ' complete 3 6 "' . fname . '" "' . b:tmpfname . '"'
+ else
+ call writefile(s:RacerGetBufferContents(a:base), b:tmpfname)
+ let fname = expand('%:p')
+ let cmd = g:racer_cmd . ' complete ' . line('.') . ' ' . col . ' "' . fname . '" "' . b:tmpfname . '"'
+ endif
+ let res = system(cmd)
+ let lines = split(res, '\n')
+ let out = []
+ for line in lines
+ if line !~# '^MATCH'
+ continue
+ endif
+ let completion = split(line[6:], ',')[0]
+ if stridx(tolower(completion), tolower(a:base)) == 0
+ let out = add(out, completion)
+ endif
+ endfor
+ call delete(b:tmpfname)
+
+ return out
+endfunction
+
+function! racer#GoToDefinition()
+ if s:ErrorCheck()
+ return
+ endif
+
+ let col = col('.') - 1
+ let b:racer_col = col
+ let fname = expand('%:p')
+ let tmpfname = tempname()
+ call writefile(getline(1, '$'), tmpfname)
+ let cmd = g:racer_cmd . ' find-definition ' . line('.') . ' ' . col . ' ' . fname . ' ' . tmpfname
+ let res = system(cmd)
+ let lines = split(res, '\n')
+ for line in lines
+ if res =~# ' error: ' && line !=# 'END'
+ call s:Warn(line)
+ elseif line =~# '^MATCH'
+ let linenum = split(line[6:], ',')[1]
+ let colnum = split(line[6:], ',')[2]
+ let fname = split(line[6:], ',')[3]
+ call s:RacerJumpToLocation(fname, linenum, colnum)
+ break
+ endif
+ endfor
+ call delete(tmpfname)
+endfunction
+
+function! s:RacerGetBufferContents(base)
+ " Re-combine the completion base word from omnicomplete with the current
+ " line contents. Since the base word gets remove from the buffer before
+ " this function is invoked we have to put it back in to out tmpfile.
+ let col = col('.') - 1
+ let buf_lines = getline(1, '$')
+ let line_contents = getline('.')
+ let buf_lines[line('.') - 1] =
+ \ strpart(line_contents, 0, col) .
+ \ a:base .
+ \ strpart(line_contents, col, len(line_contents))
+ return buf_lines
+endfunction
+
+function! s:RacerJumpToLocation(filename, linenum, colnum)
+ if a:filename == ''
+ return
+ endif
+
+ " Record jump mark
+ normal! m`
+ if a:filename != bufname('%')
+ try
+ exec 'keepjumps e ' . fnameescape(a:filename)
+ catch /^Vim\%((\a\+)\)\=:E37/
+ " When the buffer is not saved, E37 is thrown. We can ignore it.
+ endtry
+ endif
+ call cursor(a:linenum, a:colnum + 1)
+ " Center definition on screen
+ normal! zz
+endfunction
+
+function! racer#RacerComplete(findstart, base)
+ if a:findstart
+ if s:ErrorCheck()
+ return -1
+ endif
+
+ return s:RacerGetPrefixCol(a:base)
+ else
+ if s:ErrorCheck()
+ return []
+ endif
+
+ if g:racer_experimental_completer == 1
+ return s:RacerGetExpCompletions(a:base)
+ else
+ return s:RacerGetCompletions(a:base)
+ endif
+ endif
+endfunction
+
+function! s:Warn(msg)
+ echohl WarningMsg | echomsg a:msg | echohl NONE
+endfunction
+
+function! s:ErrorCheck()
+ if !executable(g:racer_cmd)
+ call s:Warn('No racer executable found in $PATH (' . $PATH . ')')
+ return 1
+ endif
+endfunction
diff --git a/vim/bundle/vim-racer/ftplugin/rust_racer.vim b/vim/bundle/vim-racer/ftplugin/rust_racer.vim
new file mode 100644
index 0000000..a76fc3b
--- /dev/null
+++ b/vim/bundle/vim-racer/ftplugin/rust_racer.vim
@@ -0,0 +1,44 @@
+let s:save_cpo = &cpo
+set cpo&vim
+
+let s:is_win = has('win32') || has('win64')
+
+if !exists('g:racer_cmd')
+ let s:sep = s:is_win ? '\' : '/'
+ let s:path = join([
+ \ escape(expand('<sfile>:p:h'), '\'),
+ \ '..',
+ \ 'target',
+ \ 'release',
+ \ ], s:sep)
+ if isdirectory(s:path)
+ let s:pathsep = s:is_win ? ';' : ':'
+ let $PATH .= s:pathsep . s:path
+ endif
+ let g:racer_cmd = 'racer'
+endif
+
+" Expand '~' and environment variables
+let g:racer_cmd = expand(g:racer_cmd)
+
+if !exists('g:racer_experimental_completer')
+ let g:racer_experimental_completer = 0
+endif
+
+if !exists('g:racer_insert_paren')
+ let g:racer_insert_paren = 1
+endif
+
+nnoremap <silent><buffer> <Plug>(rust-def)
+ \ :call racer#GoToDefinition()<CR>
+nnoremap <silent><buffer> <Plug>(rust-def-split)
+ \ :split<CR>:call racer#GoToDefinition()<CR>
+nnoremap <silent><buffer> <Plug>(rust-def-vertical)
+ \ :vsplit<CR>:call racer#GoToDefinition()<CR>
+nnoremap <silent><buffer> <Plug>(rust-doc)
+ \ :call racer#ShowDocumentation()<CR>
+
+setlocal omnifunc=racer#RacerComplete
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
diff --git a/vim/bundle/vim-racer/rplugin/python3/deoplete/sources/racer.py b/vim/bundle/vim-racer/rplugin/python3/deoplete/sources/racer.py
new file mode 100644
index 0000000..f041530
--- /dev/null
+++ b/vim/bundle/vim-racer/rplugin/python3/deoplete/sources/racer.py
@@ -0,0 +1,111 @@
+#=============================================================================
+# FILE: racer.py
+# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
+# License: MIT license {{{
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+# }}}
+#=============================================================================
+
+import re
+import os
+import subprocess
+import tempfile
+from .base import Base
+
+class Source(Base):
+ def __init__(self, vim):
+ Base.__init__(self, vim)
+
+ self.name = 'racer'
+ self.mark = '[racer]'
+ self.filetypes = ['rust']
+ self.input_pattern = r'(\.|::)\w*'
+ self.rank = 500
+
+ def on_init(self, context):
+ self.__executable_racer = self.vim.funcs.executable(
+ self.vim.eval('g:racer_cmd'))
+ self.__racer = self.vim.eval('g:racer_cmd')
+
+ def get_complete_position(self, context):
+ if not self.__executable_racer:
+ return -1
+
+ m = re.search('\w*$', context['input'])
+ return m.start() if m else -1
+
+
+ def gather_candidates(self, context):
+ typeMap = {
+ 'Struct': 's', 'Module': 'M', 'Function': 'f',
+ 'Crate': 'C', 'Let': 'v', 'StructField': 'm',
+ 'Impl': 'i', 'Enum': 'e', 'EnumVariant': 'E',
+ 'Type': 't', 'FnArg': 'v', 'Trait': 'T',
+ 'Const': 'c'
+ }
+
+ candidates = []
+ insert_paren = int(self.vim.eval('g:racer_insert_paren'))
+ for line in [l[6:] for l
+ in self.get_results(context, 'complete',
+ context['complete_position'] + 1)
+ if l.startswith('MATCH')]:
+ completions = line.split(',')
+ kind = typeMap.get(completions[4], '')
+ completion = { 'kind': kind, 'word': completions[0], 'dup': 1 }
+ if kind == 'f': # function
+ completion['menu'] = ','.join(completions[5:]).replace(
+ 'pub ', '').replace('fn ', '').rstrip('{')
+ if ' where ' in completion['menu'] or completion[
+ 'menu'].endswith(' where') :
+ where = completion['menu'].rindex(' where')
+ completion['menu'] = completion['menu'][: where]
+ if insert_paren:
+ completion['abbr'] = completions[0]
+ completion['word'] += '('
+ elif kind == 's' : # struct
+ completion['menu'] = ','.join(completions[5:]).replace(
+ 'pub ', '').replace( 'struct ', '').rstrip('{')
+ candidates.append(completion)
+ return candidates
+
+ def get_results(self, context, command, col):
+ with tempfile.NamedTemporaryFile(mode='w') as tf:
+ tf.write("\n".join(self.vim.current.buffer))
+ tf.flush()
+
+ args = [
+ self.__racer, command,
+ str(self.vim.funcs.line('.')),
+ str(col - 1),
+ tf.name
+ ] if command == 'prefix' else [
+ self.__racer, command,
+ str(self.vim.funcs.line('.')),
+ str(col - 1),
+ self.vim.current.buffer.name,
+ tf.name
+ ]
+ try:
+ results = subprocess.check_output(args).decode(
+ context['encoding']).splitlines()
+ except subprocess.CalledProcessError:
+ return []
+ return results
diff --git a/vim/bundle/vim-racer/syntax/rustdoc.vim b/vim/bundle/vim-racer/syntax/rustdoc.vim
new file mode 100644
index 0000000..d527c9b
--- /dev/null
+++ b/vim/bundle/vim-racer/syntax/rustdoc.vim
@@ -0,0 +1,178 @@
+" Vim syntax file
+" Language: Rust Documentation (Markdown)
+" Maintainer: Esteban Kuber <esteban@kuber.com.ar>
+" Remark: Uses HTML and Rust syntax files.
+" Based off plasticboy's Markdown Vim Mode:
+" https://github.com/plasticboy/vim-markdown.
+" TODO: Handle stuff contained within stuff (e.g. headings within blockquotes)
+
+
+" 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
+endif
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+" don't use standard HiLink, it will not work with included syntax files
+if version < 508
+ command! -nargs=+ HtmlHiLink hi link <args>
+else
+ command! -nargs=+ HtmlHiLink hi def link <args>
+endif
+
+syn spell toplevel
+syn case ignore
+syn sync linebreaks=1
+
+let s:conceal = ''
+let s:concealends = ''
+if has('conceal') && get(g:, 'vim_markdown_conceal', 1)
+ let s:conceal = ' conceal'
+ let s:concealends = ' concealends'
+endif
+
+" additions to HTML groups
+if get(g:, 'vim_markdown_emphasis_multiline', 1)
+ let s:oneline = ''
+else
+ let s:oneline = ' oneline'
+endif
+execute 'syn region htmlItalic start="\%(^\|\s\)\zs\*\ze[^\\\*\t ]\%(\%([^*]\|\\\*\|\n\)*[^\\\*\t ]\)\?\*\_W" end="[^\\\*\t ]\zs\*\ze\_W" keepend' . s:oneline
+execute 'syn region htmlItalic start="\%(^\|\s\)\zs_\ze[^\\_\t ]" end="[^\\_\t ]\zs_\ze\_W" keepend' . s:oneline
+execute 'syn region htmlBold start="\%(^\|\s\)\*\*\ze\S" end="\S\zs\*\*" keepend' . s:oneline
+execute 'syn region htmlBold start="\%(^\|\s\)\zs__\ze\S" end="\S\zs__" keepend' . s:oneline
+execute 'syn region htmlBoldItalic start="\%(^\|\s\)\zs\*\*\*\ze\S" end="\S\zs\*\*\*" keepend' . s:oneline
+execute 'syn region htmlBoldItalic start="\%(^\|\s\)\zs___\ze\S" end="\S\zs___" keepend' . s:oneline
+
+" [link](URL) | [link][id] | [link][] | ![image](URL)
+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="\\\@<!!\?\[" end="\n\{-,1}[^]]\{-}\zs\]\ze[[(]" contains=@mkdNonListItem,@Spell nextgroup=mkdURL,mkdID skipwhite oneline' . 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 start="^\s*#" end="$" contains=@Spell
+syn region htmlH2 start="^\s*##" end="$" contains=@Spell
+syn region htmlH3 start="^\s*###" end="$" contains=@Spell
+syn region htmlH4 start="^\s*####" end="$" contains=@Spell
+syn region htmlH5 start="^\s*#####" end="$" contains=@Spell
+syn region htmlH6 start="^\s*######" end="$" contains=@Spell
+syn match htmlH1 /^.\+\n=\+$/ contains=@Spell
+syn match htmlH2 /^.\+\n-\+$/ contains=@Spell
+
+"define Markdown groups
+syn match mkdLineBreak / \+$/
+syn region mkdBlockquote start=/^\s*>/ end=/$/ contains=mkdLineBreak,@Spell
+syn region mkdCode start=/\(\([^\\]\|^\)\\\)\@<!`/ end=/\(\([^\\]\|^\)\\\)\@<!`/
+syn region mkdCode start=/\s*``[^`]*/ end=/[^`]*``\s*/
+syn region mkdCode start=/^\s*\z(`\{3,}\)[^`]*$/ end=/^\s*\z1`*\s*$/
+syn region mkdCode start=/\s*\~\~[^\~]*/ end=/[^\~]*\~\~\s*/
+syn region mkdCode start=/^\s*\z(\~\{3,}\)\s*[0-9A-Za-z_+-]*\s*$/ end=/^\s*\z1\~*\s*$/
+syn region mkdCode start="<pre[^>]*\\\@<!>" end="</pre>"
+syn region mkdCode start="<code[^>]*\\\@<!>" end="</code>"
+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\+\.\)\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}\*$/
+syn match mkdRule /^\s*-\s\{0,1}-\s\{0,1}-$/
+syn match mkdRule /^\s*_\s\{0,1}_\s\{0,1}_$/
+syn match mkdRule /^\s*-\{3,}$/
+syn match mkdRule /^\s*\*\{3,5}$/
+
+" 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
+
+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
+endif
+
+if get(g:, 'vim_markdown_math', 0)
+ syn include @tex syntax/tex.vim
+ syn region mkdMath start="\\\@<!\$" end="\$" contains=@tex keepend
+ syn region mkdMath start="\\\@<!\$\$" end="\$\$" contains=@tex keepend
+endif
+
+syn include @rust syntax/rust.vim
+syn region mkdRust start="\`\`\`$" end="\`\`\`$" contains=@rust keepend
+syn region mkdRust start="\`\`\`rust" end="\`\`\`$" contains=@rust keepend
+syn region mkdRust start="\`\`\`no_run" end="\`\`\`$" contains=@rust keepend
+
+syn cluster mkdNonListItem contains=@htmlTop,htmlItalic,htmlBold,htmlBoldItalic,mkdFootnotes,mkdInlineURL,mkdLink,mkdLinkDef,mkdLineBreak,mkdBlockquote,mkdCode,mkdRule,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,mkdMath,mkdRust
+
+"highlighting for Markdown groups
+HtmlHiLink mkdString String
+HtmlHiLink mkdCode 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=2