diff options
38 files changed, 1372 insertions, 927 deletions
diff --git a/after/syntax/javascript/graphql.vim b/after/syntax/javascript/graphql.vim index 58c1de08..eb862e05 100644 --- a/after/syntax/javascript/graphql.vim +++ b/after/syntax/javascript/graphql.vim @@ -9,11 +9,17 @@ if exists('s:current_syntax') let b:current_syntax = s:current_syntax endif -syntax region graphqlTemplateString start=+`+ skip=+\\\(`\|$\)+ end=+`+ contains=@GraphQLSyntax,jsTemplateExpression,jsSpecial extend -exec 'syntax match graphqlTaggedTemplate +\%(' . join(g:graphql_javascript_tags, '\|') . '\)\%(`\)\@=+ nextgroup=graphqlTemplateString' +let s:tags = '\%(' . join(g:graphql_javascript_tags, '\|') . '\)' + +exec 'syntax region graphqlTemplateString start=+' . s:tags . '\@20<=`+ skip=+\\`+ end=+`+ contains=@GraphQLSyntax,jsTemplateExpression,jsSpecial extend' +exec 'syntax match graphqlTaggedTemplate +' . s:tags . '\ze`+ nextgroup=graphqlTemplateString' + +" Support expression interpolation ((${...})) inside template strings. +syntax region graphqlTemplateExpression start=+${+ end=+}+ contained contains=jsTemplateExpression containedin=graphqlFold keepend hi def link graphqlTemplateString jsTemplateString hi def link graphqlTaggedTemplate jsTaggedTemplate +hi def link graphqlTemplateExpression jsTemplateExpression syn cluster jsExpression add=graphqlTaggedTemplate syn cluster graphqlTaggedTemplate add=graphqlTemplateString diff --git a/after/syntax/rust.vim b/after/syntax/rust.vim index 9a317956..3e2c2077 100644 --- a/after/syntax/rust.vim +++ b/after/syntax/rust.vim @@ -1,12 +1,14 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 -if !exists('g:rust_conceal') || g:rust_conceal == 0 || !has('conceal') || &enc != 'utf-8' - finish +scriptencoding utf-8 + +if !get(g:, 'rust_conceal', 0) || !has('conceal') || &encoding !=# 'utf-8' + finish endif " For those who don't want to see `::`... -if exists('g:rust_conceal_mod_path') && g:rust_conceal_mod_path != 0 - syn match rustNiceOperator "::" conceal cchar=ㆍ +if get(g:, 'rust_conceal_mod_path', 0) + syn match rustNiceOperator "::" conceal cchar=ㆍ endif syn match rustRightArrowHead contained ">" conceal cchar= @@ -20,7 +22,7 @@ syn match rustNiceOperator "=>" contains=rustFatRightArrowHead,rustFatRightArrow syn match rustNiceOperator /\<\@!_\(_*\>\)\@=/ conceal cchar=′ " For those who don't want to see `pub`... -if exists('g:rust_conceal_pub') && g:rust_conceal_pub != 0 +if get(g:, 'rust_conceal_pub', 0) syn match rustPublicSigil contained "pu" conceal cchar=* syn match rustPublicRest contained "b" conceal cchar= syn match rustNiceOperator "pub " contains=rustPublicSigil,rustPublicRest @@ -28,11 +30,16 @@ endif hi link rustNiceOperator Operator -if !(exists('g:rust_conceal_mod_path') && g:rust_conceal_mod_path != 0) +if !get(g:, 'rust_conceal_mod_path', 0) hi! link Conceal Operator - " And keep it after a colorscheme change - au ColorScheme <buffer> hi! link Conceal Operator + augroup rust.vim.after + autocmd! + " And keep it after a colorscheme change + autocmd ColorScheme <buffer> hi! link Conceal Operator + augroup END endif +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/after/syntax/typescript/graphql.vim b/after/syntax/typescript/graphql.vim index 53999699..5fc9ab41 100644 --- a/after/syntax/typescript/graphql.vim +++ b/after/syntax/typescript/graphql.vim @@ -9,10 +9,16 @@ if exists('s:current_syntax') let b:current_syntax = s:current_syntax endif -syntax region graphqlTemplateString start=+`+ skip=+\\\(`\|$\)+ end=+`+ contains=@GraphQLSyntax,typescriptTemplateTag extend -exec 'syntax match graphqlTaggedTemplate +\%(' . join(g:graphql_javascript_tags, '\|') . '\)\%(`\)\@=+ nextgroup=graphqlTemplateString' +let s:tags = '\%(' . join(g:graphql_javascript_tags, '\|') . '\)' + +exec 'syntax region graphqlTemplateString start=+' . s:tags . '\@20<=`+ skip=+\\`+ end=+`+ contains=@GraphQLSyntax,typescriptTemplateSubstitution extend' +exec 'syntax match graphqlTaggedTemplate +' . s:tags . '\ze`+ nextgroup=graphqlTemplateString' + +" Support expression interpolation ((${...})) inside template strings. +syntax region graphqlTemplateExpression start=+${+ end=+}+ contained contains=typescriptTemplateSubstitution containedin=graphqlFold keepend hi def link graphqlTemplateString typescriptTemplate +hi def link graphqlTemplateExpression typescriptTemplateSubstitution syn cluster typescriptExpression add=graphqlTaggedTemplate syn cluster graphqlTaggedTemplate add=graphqlTemplateString diff --git a/autoload/cargo.vim b/autoload/cargo.vim index e92da22b..d1547fc9 100644 --- a/autoload/cargo.vim +++ b/autoload/cargo.vim @@ -1,89 +1,91 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 +function! cargo#Load() + " Utility call to get this script loaded, for debugging +endfunction + function! cargo#cmd(args) - silent! clear - if !a:args - execute "!" . "cargo ". a:args + execute "! cargo" a:args +endfunction + +function! s:nearest_cargo(...) abort + " If the second argument is not specified, the first argument determines + " whether we will start from the current directory or the directory of the + " current buffer, otherwise, we start with the provided path on the + " second argument. + + let l:is_getcwd = get(a:, 1, 0) + if l:is_getcwd + let l:starting_path = get(a:, 2, getcwd()) else - echom "Missing arguments" + let l:starting_path = get(a:, 2, expand('%:p:h')) endif + + return findfile('Cargo.toml', l:starting_path . ';') endfunction -function! cargo#build(args) - silent! clear - if !a:args - execute "!" . "cargo build " . a:args - else - execute "!" . "cargo build" +function! cargo#nearestCargo(is_getcwd) abort + return s:nearest_cargo(a:is_getcwd) +endfunction + +function! cargo#nearestWorkspaceCargo(is_getcwd) abort + let l:nearest = s:nearest_cargo(a:is_getcwd) + while l:nearest !=# '' + for l:line in readfile(l:nearest, '', 0x100) + if l:line =~# '\V[workspace]' + return l:nearest + endif + endfor + let l:next = fnamemodify(l:nearest, ':p:h:h') + let l:nearest = s:nearest_cargo(0, l:next) + endwhile + return '' +endfunction + +function! cargo#nearestRootCargo(is_getcwd) abort + " Try to find a workspace Cargo.toml, and if not found, take the nearest + " regular Cargo.toml + let l:workspace_cargo = cargo#nearestWorkspaceCargo(a:is_getcwd) + if l:workspace_cargo !=# '' + return l:workspace_cargo endif - silent! clear - execute "!" . "cargo build" + return s:nearest_cargo(a:is_getcwd) +endfunction + + +function! cargo#build(args) + call cargo#cmd("build " . a:args) endfunction function! cargo#clean(args) - silent! clear - if !a:args - execute "!" . "cargo clean " . a:args - else - execute "!" . "cargo clean" - endif - silent! clear - execute "!" . "cargo clean" + call cargo#cmd("clean " . a:args) endfunction function! cargo#doc(args) - silent! clear - if !a:args - execute "!" . "cargo doc " . a:args - else - execute "!" . "cargo doc" - endif + call cargo#cmd("doc " . a:args) endfunction function! cargo#new(args) - silent! clear - if !a:args - execute "!cargo new " . a:args - :cd `=a:args` - else - echom "Missing arguments" - endif + call cargo#cmd("new " . a:args) + cd `=a:args` endfunction function! cargo#init(args) - silent! clear - if !a:args - execute "!" . "cargo init " . a:args - else - execute "!" . "cargo init" - endif + call cargo#cmd("init " . a:args) endfunction function! cargo#run(args) - silent! clear - if !a:args - execute "!" . "cargo run " . a:args - else - execute "!" . "cargo run" - endif + call cargo#cmd("run " . a:args) endfunction function! cargo#test(args) - silent! clear - if !a:args - execute "!" . "cargo test " . a:args - else - execute "!" . "cargo test" - endif + call cargo#cmd("test " . a:args) endfunction function! cargo#bench(args) - silent! clear - if !a:args - execute "!" . "cargo bench " . a:args - else - execute "!" . "cargo bench" - endif + call cargo#cmd("bench " . a:args) endfunction +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/autoload/cargo/quickfix.vim b/autoload/cargo/quickfix.vim new file mode 100644 index 00000000..13c3b465 --- /dev/null +++ b/autoload/cargo/quickfix.vim @@ -0,0 +1,30 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 + +function! cargo#quickfix#CmdPre() abort + if &filetype ==# 'rust' && get(b:, 'current_compiler', '') ==# 'cargo' + " Preserve the current directory, and 'lcd' to the nearest Cargo file. + let b:rust_compiler_cargo_qf_has_lcd = haslocaldir() + let b:rust_compiler_cargo_qf_prev_cd = getcwd() + let b:rust_compiler_cargo_qf_prev_cd_saved = 1 + let l:nearest = fnamemodify(cargo#nearestRootCargo(0), ':h') + execute 'lchdir! '.l:nearest + else + let b:rust_compiler_cargo_qf_prev_cd_saved = 0 + endif +endfunction + +function! cargo#quickfix#CmdPost() abort + if b:rust_compiler_cargo_qf_prev_cd_saved + " Restore the current directory. + if b:rust_compiler_cargo_qf_has_lcd + execute 'lchdir! '.b:rust_compiler_cargo_qf_prev_cd + else + execute 'chdir! '.b:rust_compiler_cargo_qf_prev_cd + endif + let b:rust_compiler_cargo_qf_prev_cd_saved = 0 + endif +endfunction + +" vim: set et sw=4 sts=4 ts=8: + +endif diff --git a/autoload/rubycomplete.vim b/autoload/rubycomplete.vim index 8cb73fd5..1184c427 100644 --- a/autoload/rubycomplete.vim +++ b/autoload/rubycomplete.vim @@ -261,7 +261,7 @@ class VimRubyCompletion nums.each do |x| ln = buf[x] begin - eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln ) + eval( "require %s" % $1 ) if /.*require\s*(["'].*?["'])/.match( ln ) rescue Exception #ignore? end diff --git a/autoload/rust.vim b/autoload/rust.vim index 6edc48f7..7e766da1 100644 --- a/autoload/rust.vim +++ b/autoload/rust.vim @@ -7,203 +7,219 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " Jump {{{1 +function! rust#Load() + " Utility call to get this script loaded, for debugging +endfunction + +function! rust#GetConfigVar(name, default) + " Local buffer variable with same name takes predeence over global + if has_key(b:, a:name) + return get(b:, a:name) + endif + if has_key(g:, a:name) + return get(g:, a:name) + endif + return a:default +endfunction + + function! rust#Jump(mode, function) range - let cnt = v:count1 - normal! m' - if a:mode ==# 'v' - norm! gv - endif - let foldenable = &foldenable - set nofoldenable - while cnt > 0 - execute "call <SID>Jump_" . a:function . "()" - let cnt = cnt - 1 - endwhile - let &foldenable = foldenable + let cnt = v:count1 + normal! m' + if a:mode ==# 'v' + norm! gv + endif + let foldenable = &foldenable + set nofoldenable + while cnt > 0 + execute "call <SID>Jump_" . a:function . "()" + let cnt = cnt - 1 + endwhile + let &foldenable = foldenable endfunction function! s:Jump_Back() - call search('{', 'b') - keepjumps normal! w99[{ + call search('{', 'b') + keepjumps normal! w99[{ endfunction function! s:Jump_Forward() - normal! j0 - call search('{', 'b') - keepjumps normal! w99[{% - call search('{') + normal! j0 + call search('{', 'b') + keepjumps normal! w99[{% + call search('{') endfunction " Run {{{1 function! rust#Run(bang, args) - let args = s:ShellTokenize(a:args) - if a:bang - let idx = index(l:args, '--') - if idx != -1 - let rustc_args = idx == 0 ? [] : l:args[:idx-1] - let args = l:args[idx+1:] - else - let rustc_args = l:args - let args = [] - endif - else - let rustc_args = [] - endif - - let b:rust_last_rustc_args = l:rustc_args - let b:rust_last_args = l:args - - call s:WithPath(function("s:Run"), rustc_args, args) + let args = s:ShellTokenize(a:args) + if a:bang + let idx = index(l:args, '--') + if idx != -1 + let rustc_args = idx == 0 ? [] : l:args[:idx-1] + let args = l:args[idx+1:] + else + let rustc_args = l:args + let args = [] + endif + else + let rustc_args = [] + endif + + let b:rust_last_rustc_args = l:rustc_args + let b:rust_last_args = l:args + + call s:WithPath(function("s:Run"), rustc_args, args) endfunction function! s:Run(dict, rustc_args, args) - let exepath = a:dict.tmpdir.'/'.fnamemodify(a:dict.path, ':t:r') - if has('win32') - let exepath .= '.exe' - endif - - let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) - let rustc_args = [relpath, '-o', exepath] + a:rustc_args - - let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" - - let pwd = a:dict.istemp ? a:dict.tmpdir : '' - let output = s:system(pwd, shellescape(rustc) . " " . join(map(rustc_args, 'shellescape(v:val)'))) - if output != '' - echohl WarningMsg - echo output - echohl None - endif - if !v:shell_error - exe '!' . shellescape(exepath) . " " . join(map(a:args, 'shellescape(v:val)')) - endif + let exepath = a:dict.tmpdir.'/'.fnamemodify(a:dict.path, ':t:r') + if has('win32') + let exepath .= '.exe' + endif + + let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) + let rustc_args = [relpath, '-o', exepath] + a:rustc_args + + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + let pwd = a:dict.istemp ? a:dict.tmpdir : '' + let output = s:system(pwd, shellescape(rustc) . " " . join(map(rustc_args, 'shellescape(v:val)'))) + if output != '' + echohl WarningMsg + echo output + echohl None + endif + if !v:shell_error + exe '!' . shellescape(exepath) . " " . join(map(a:args, 'shellescape(v:val)')) + endif endfunction " Expand {{{1 function! rust#Expand(bang, args) - let args = s:ShellTokenize(a:args) - if a:bang && !empty(l:args) - let pretty = remove(l:args, 0) - else - let pretty = "expanded" - endif - call s:WithPath(function("s:Expand"), pretty, args) + let args = s:ShellTokenize(a:args) + if a:bang && !empty(l:args) + let pretty = remove(l:args, 0) + else + let pretty = "expanded" + endif + call s:WithPath(function("s:Expand"), pretty, args) endfunction function! s:Expand(dict, pretty, args) - try - let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" - - if a:pretty =~? '^\%(everybody_loops$\|flowgraph=\)' - let flag = '--xpretty' - else - let flag = '--pretty' - endif - let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) - let args = [relpath, '-Z', 'unstable-options', l:flag, a:pretty] + a:args - let pwd = a:dict.istemp ? a:dict.tmpdir : '' - let output = s:system(pwd, shellescape(rustc) . " " . join(map(args, 'shellescape(v:val)'))) - if v:shell_error - echohl WarningMsg - echo output - echohl None - else - new - silent put =output - 1 - d - setl filetype=rust - setl buftype=nofile - setl bufhidden=hide - setl noswapfile - " give the buffer a nice name - let suffix = 1 - let basename = fnamemodify(a:dict.path, ':t:r') - while 1 - let bufname = basename - if suffix > 1 | let bufname .= ' ('.suffix.')' | endif - let bufname .= '.pretty.rs' - if bufexists(bufname) - let suffix += 1 - continue - endif - exe 'silent noautocmd keepalt file' fnameescape(bufname) - break - endwhile - endif - endtry + try + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + if a:pretty =~? '^\%(everybody_loops$\|flowgraph=\)' + let flag = '--xpretty' + else + let flag = '--pretty' + endif + let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) + let args = [relpath, '-Z', 'unstable-options', l:flag, a:pretty] + a:args + let pwd = a:dict.istemp ? a:dict.tmpdir : '' + let output = s:system(pwd, shellescape(rustc) . " " . join(map(args, 'shellescape(v:val)'))) + if v:shell_error + echohl WarningMsg + echo output + echohl None + else + new + silent put =output + 1 + d + setl filetype=rust + setl buftype=nofile + setl bufhidden=hide + setl noswapfile + " give the buffer a nice name + let suffix = 1 + let basename = fnamemodify(a:dict.path, ':t:r') + while 1 + let bufname = basename + if suffix > 1 | let bufname .= ' ('.suffix.')' | endif + let bufname .= '.pretty.rs' + if bufexists(bufname) + let suffix += 1 + continue + endif + exe 'silent noautocmd keepalt file' fnameescape(bufname) + break + endwhile + endif + endtry endfunction function! rust#CompleteExpand(lead, line, pos) - if a:line[: a:pos-1] =~ '^RustExpand!\s*\S*$' - " first argument and it has a ! - let list = ["normal", "expanded", "typed", "expanded,identified", "flowgraph=", "everybody_loops"] - if !empty(a:lead) - call filter(list, "v:val[:len(a:lead)-1] == a:lead") - endif - return list - endif - - return glob(escape(a:lead, "*?[") . '*', 0, 1) + if a:line[: a:pos-1] =~ '^RustExpand!\s*\S*$' + " first argument and it has a ! + let list = ["normal", "expanded", "typed", "expanded,identified", "flowgraph=", "everybody_loops"] + if !empty(a:lead) + call filter(list, "v:val[:len(a:lead)-1] == a:lead") + endif + return list + endif + + return glob(escape(a:lead, "*?[") . '*', 0, 1) endfunction " Emit {{{1 function! rust#Emit(type, args) - let args = s:ShellTokenize(a:args) - call s:WithPath(function("s:Emit"), a:type, args) + let args = s:ShellTokenize(a:args) + call s:WithPath(function("s:Emit"), a:type, args) endfunction function! s:Emit(dict, type, args) - try - let output_path = a:dict.tmpdir.'/output' - - let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" - - let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) - let args = [relpath, '--emit', a:type, '-o', output_path] + a:args - let pwd = a:dict.istemp ? a:dict.tmpdir : '' - let output = s:system(pwd, shellescape(rustc) . " " . join(map(args, 'shellescape(v:val)'))) - if output != '' - echohl WarningMsg - echo output - echohl None - endif - if !v:shell_error - new - exe 'silent keepalt read' fnameescape(output_path) - 1 - d - if a:type == "llvm-ir" - setl filetype=llvm - let extension = 'll' - elseif a:type == "asm" - setl filetype=asm - let extension = 's' - endif - setl buftype=nofile - setl bufhidden=hide - setl noswapfile - if exists('l:extension') - " give the buffer a nice name - let suffix = 1 - let basename = fnamemodify(a:dict.path, ':t:r') - while 1 - let bufname = basename - if suffix > 1 | let bufname .= ' ('.suffix.')' | endif - let bufname .= '.'.extension - if bufexists(bufname) - let suffix += 1 - continue - endif - exe 'silent noautocmd keepalt file' fnameescape(bufname) - break - endwhile - endif - endif - endtry + try + let output_path = a:dict.tmpdir.'/output' + + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + let relpath = get(a:dict, 'tmpdir_relpath', a:dict.path) + let args = [relpath, '--emit', a:type, '-o', output_path] + a:args + let pwd = a:dict.istemp ? a:dict.tmpdir : '' + let output = s:system(pwd, shellescape(rustc) . " " . join(map(args, 'shellescape(v:val)'))) + if output != '' + echohl WarningMsg + echo output + echohl None + endif + if !v:shell_error + new + exe 'silent keepalt read' fnameescape(output_path) + 1 + d + if a:type == "llvm-ir" + setl filetype=llvm + let extension = 'll' + elseif a:type == "asm" + setl filetype=asm + let extension = 's' + endif + setl buftype=nofile + setl bufhidden=hide + setl noswapfile + if exists('l:extension') + " give the buffer a nice name + let suffix = 1 + let basename = fnamemodify(a:dict.path, ':t:r') + while 1 + let bufname = basename + if suffix > 1 | let bufname .= ' ('.suffix.')' | endif + let bufname .= '.'.extension + if bufexists(bufname) + let suffix += 1 + continue + endif + exe 'silent noautocmd keepalt file' fnameescape(bufname) + break + endwhile + endif + endif + endtry endfunction " Utility functions {{{1 @@ -221,145 +237,145 @@ endfunction " existing path of the current buffer. If the path is inside of {dict.tmpdir} " then it is guaranteed to have a '.rs' extension. function! s:WithPath(func, ...) - let buf = bufnr('') - let saved = {} - let dict = {} - try - let saved.write = &write - set write - let dict.path = expand('%') - let pathisempty = empty(dict.path) - - " Always create a tmpdir in case the wrapped command wants it - let dict.tmpdir = tempname() - call mkdir(dict.tmpdir) - - if pathisempty || !saved.write - let dict.istemp = 1 - " if we're doing this because of nowrite, preserve the filename - if !pathisempty - let filename = expand('%:t:r').".rs" - else - let filename = 'unnamed.rs' - endif - let dict.tmpdir_relpath = filename - let dict.path = dict.tmpdir.'/'.filename - - let saved.mod = &mod - set nomod - - silent exe 'keepalt write! ' . fnameescape(dict.path) - if pathisempty - silent keepalt 0file - endif - else - let dict.istemp = 0 - update - endif - - call call(a:func, [dict] + a:000) - finally - if bufexists(buf) - for [opt, value] in items(saved) - silent call setbufvar(buf, '&'.opt, value) - unlet value " avoid variable type mismatches - endfor - endif - if has_key(dict, 'tmpdir') | silent call s:RmDir(dict.tmpdir) | endif - endtry + let buf = bufnr('') + let saved = {} + let dict = {} + try + let saved.write = &write + set write + let dict.path = expand('%') + let pathisempty = empty(dict.path) + + " Always create a tmpdir in case the wrapped command wants it + let dict.tmpdir = tempname() + call mkdir(dict.tmpdir) + + if pathisempty || !saved.write + let dict.istemp = 1 + " if we're doing this because of nowrite, preserve the filename + if !pathisempty + let filename = expand('%:t:r').".rs" + else + let filename = 'unnamed.rs' + endif + let dict.tmpdir_relpath = filename + let dict.path = dict.tmpdir.'/'.filename + + let saved.mod = &mod + set nomod + + silent exe 'keepalt write! ' . fnameescape(dict.path) + if pathisempty + silent keepalt 0file + endif + else + let dict.istemp = 0 + update + endif + + call call(a:func, [dict] + a:000) + finally + if bufexists(buf) + for [opt, value] in items(saved) + silent call setbufvar(buf, '&'.opt, value) + unlet value " avoid variable type mismatches + endfor + endif + if has_key(dict, 'tmpdir') | silent call s:RmDir(dict.tmpdir) | endif + endtry endfunction function! rust#AppendCmdLine(text) - call setcmdpos(getcmdpos()) - let cmd = getcmdline() . a:text - return cmd + call setcmdpos(getcmdpos()) + let cmd = getcmdline() . a:text + return cmd endfunction " Tokenize the string according to sh parsing rules function! s:ShellTokenize(text) - " states: - " 0: start of word - " 1: unquoted - " 2: unquoted backslash - " 3: double-quote - " 4: double-quoted backslash - " 5: single-quote - let l:state = 0 - let l:current = '' - let l:args = [] - for c in split(a:text, '\zs') - if l:state == 0 || l:state == 1 " unquoted - if l:c ==# ' ' - if l:state == 0 | continue | endif - call add(l:args, l:current) - let l:current = '' - let l:state = 0 - elseif l:c ==# '\' - let l:state = 2 - elseif l:c ==# '"' - let l:state = 3 - elseif l:c ==# "'" - let l:state = 5 - else - let l:current .= l:c - let l:state = 1 - endif - elseif l:state == 2 " unquoted backslash - if l:c !=# "\n" " can it even be \n? - let l:current .= l:c - endif - let l:state = 1 - elseif l:state == 3 " double-quote - if l:c ==# '\' - let l:state = 4 - elseif l:c ==# '"' - let l:state = 1 - else - let l:current .= l:c - endif - elseif l:state == 4 " double-quoted backslash - if stridx('$`"\', l:c) >= 0 - let l:current .= l:c - elseif l:c ==# "\n" " is this even possible? - " skip it - else - let l:current .= '\'.l:c - endif - let l:state = 3 - elseif l:state == 5 " single-quoted - if l:c == "'" - let l:state = 1 - else - let l:current .= l:c - endif - endif - endfor - if l:state != 0 - call add(l:args, l:current) - endif - return l:args + " states: + " 0: start of word + " 1: unquoted + " 2: unquoted backslash + " 3: double-quote + " 4: double-quoted backslash + " 5: single-quote + let l:state = 0 + let l:current = '' + let l:args = [] + for c in split(a:text, '\zs') + if l:state == 0 || l:state == 1 " unquoted + if l:c ==# ' ' + if l:state == 0 | continue | endif + call add(l:args, l:current) + let l:current = '' + let l:state = 0 + elseif l:c ==# '\' + let l:state = 2 + elseif l:c ==# '"' + let l:state = 3 + elseif l:c ==# "'" + let l:state = 5 + else + let l:current .= l:c + let l:state = 1 + endif + elseif l:state == 2 " unquoted backslash + if l:c !=# "\n" " can it even be \n? + let l:current .= l:c + endif + let l:state = 1 + elseif l:state == 3 " double-quote + if l:c ==# '\' + let l:state = 4 + elseif l:c ==# '"' + let l:state = 1 + else + let l:current .= l:c + endif + elseif l:state == 4 " double-quoted backslash + if stridx('$`"\', l:c) >= 0 + let l:current .= l:c + elseif l:c ==# "\n" " is this even possible? + " skip it + else + let l:current .= '\'.l:c + endif + let l:state = 3 + elseif l:state == 5 " single-quoted + if l:c == "'" + let l:state = 1 + else + let l:current .= l:c + endif + endif + endfor + if l:state != 0 + call add(l:args, l:current) + endif + return l:args endfunction function! s:RmDir(path) - " sanity check; make sure it's not empty, /, or $HOME - if empty(a:path) - echoerr 'Attempted to delete empty path' - return 0 - elseif a:path == '/' || a:path == $HOME - echoerr 'Attempted to delete protected path: ' . a:path - return 0 - endif - return system("rm -rf " . shellescape(a:path)) + " sanity check; make sure it's not empty, /, or $HOME + if empty(a:path) + echoerr 'Attempted to delete empty path' + return 0 + elseif a:path == '/' || a:path == $HOME + echoerr 'Attempted to delete protected path: ' . a:path + return 0 + endif + return system("rm -rf " . shellescape(a:path)) endfunction " Executes {cmd} with the cwd set to {pwd}, without changing Vim's cwd. " If {pwd} is the empty string then it doesn't change the cwd. function! s:system(pwd, cmd) - let cmd = a:cmd - if !empty(a:pwd) - let cmd = 'cd ' . shellescape(a:pwd) . ' && ' . cmd - endif - return system(cmd) + let cmd = a:cmd + if !empty(a:pwd) + let cmd = 'cd ' . shellescape(a:pwd) . ' && ' . cmd + endif + return system(cmd) endfunction " Playpen Support {{{1 @@ -368,10 +384,10 @@ endfunction " http://github.com/mattn/gist-vim function! s:has_webapi() if !exists("*webapi#http#post") - try - call webapi#http#post() - catch - endtry + try + call webapi#http#post() + catch + endtry endif return exists("*webapi#http#post") endfunction @@ -383,26 +399,26 @@ function! rust#Play(count, line1, line2, ...) abort let l:rust_shortener_url = get(g:, 'rust_shortener_url', 'https://is.gd/') if !s:has_webapi() - echohl ErrorMsg | echomsg ':RustPlay depends on webapi.vim (https://github.com/mattn/webapi-vim)' | echohl None - return + echohl ErrorMsg | echomsg ':RustPlay depends on webapi.vim (https://github.com/mattn/webapi-vim)' | echohl None + return endif let bufname = bufname('%') if a:count < 1 - let content = join(getline(a:line1, a:line2), "\n") + let content = join(getline(a:line1, a:line2), "\n") else - let save_regcont = @" - let save_regtype = getregtype('"') - silent! normal! gvy - let content = @" - call setreg('"', save_regcont, save_regtype) + let save_regcont = @" + let save_regtype = getregtype('"') + silent! normal! gvy + let content = @" + call setreg('"', save_regcont, save_regtype) endif let body = l:rust_playpen_url."?code=".webapi#http#encodeURI(content) if strlen(body) > 5000 - echohl ErrorMsg | echomsg 'Buffer too large, max 5000 encoded characters ('.strlen(body).')' | echohl None - return + echohl ErrorMsg | echomsg 'Buffer too large, max 5000 encoded characters ('.strlen(body).')' | echohl None + return endif let payload = "format=simple&url=".webapi#http#encodeURI(body) @@ -410,7 +426,7 @@ function! rust#Play(count, line1, line2, ...) abort let url = res.content if exists('g:rust_clip_command') - call system(g:rust_clip_command, url) + call system(g:rust_clip_command, url) endif redraw | echomsg 'Done: '.url @@ -418,6 +434,6 @@ endfunction " }}}1 -" vim: set noet sw=8 ts=8: +" vim: set et sw=4 sts=4 ts=8: endif diff --git a/autoload/rust/debugging.vim b/autoload/rust/debugging.vim new file mode 100644 index 00000000..352556d7 --- /dev/null +++ b/autoload/rust/debugging.vim @@ -0,0 +1,98 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 + +" For debugging, inspired by https://github.com/w0rp/rust/blob/master/autoload/rust/debugging.vim + +let s:global_variable_list = [ + \ 'ftplugin_rust_source_path', + \ 'loaded_syntastic_rust_cargo_checker', + \ 'loaded_syntastic_rust_filetype', + \ 'loaded_syntastic_rust_rustc_checker', + \ 'rust_bang_comment_leader', + \ 'rust_cargo_avoid_whole_workspace', + \ 'rust_clip_command', + \ 'rust_conceal', + \ 'rust_conceal_mod_path', + \ 'rust_conceal_pub', + \ 'rust_fold', + \ 'rust_last_args', + \ 'rust_last_rustc_args', + \ 'rust_original_delimitMate_excluded_regions', + \ 'rust_playpen_url', + \ 'rust_recent_nearest_cargo_tol', + \ 'rust_recent_root_cargo_toml', + \ 'rust_recommended_style', + \ 'rust_set_conceallevel', + \ 'rust_set_conceallevel=1', + \ 'rust_set_foldmethod', + \ 'rust_set_foldmethod=1', + \ 'rust_shortener_url', + \ 'rustc_makeprg_no_percent', + \ 'rustc_path', + \ 'rustfmt_autosave', + \ 'rustfmt_autosave_because_of_config', + \ 'rustfmt_autosave_if_config_present', + \ 'rustfmt_command', + \ 'rustfmt_emit_files', + \ 'rustfmt_fail_silently', + \ 'rustfmt_options', + \ 'syntastic_extra_filetypes', + \ 'syntastic_rust_cargo_fname', + \] + +function! s:Echo(message) abort + execute 'echo a:message' +endfunction + +function! s:EchoGlobalVariables() abort + for l:key in s:global_variable_list + call s:Echo('let g:' . l:key . ' = ' . string(get(g:, l:key, v:null))) + + if has_key(b:, l:key) + call s:Echo('let b:' . l:key . ' = ' . string(b:[l:key])) + endif + endfor +endfunction + +function! rust#debugging#Info() abort + call cargo#Load() + call rust#Load() + call rustfmt#Load() + call s:Echo('rust.vim Global Variables:') + call s:Echo('') + call s:EchoGlobalVariables() + + silent let l:output = system(g:rustfmt_command . ' --version') + echo l:output + + let l:rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + silent let l:output = system(l:rustc . ' --version') + echo l:output + + silent let l:output = system('cargo --version') + echo l:output + + version +endfunction + +function! rust#debugging#InfoToClipboard() abort + redir @" + silent call rust#debugging#Info() + redir END + + call s:Echo('RustInfo copied to your clipboard') +endfunction + +function! rust#debugging#InfoToFile(filename) abort + let l:expanded_filename = expand(a:filename) + + redir => l:output + silent call rust#debugging#Info() + redir END + + call writefile(split(l:output, "\n"), l:expanded_filename) + call s:Echo('RustInfo written to ' . l:expanded_filename) +endfunction + +" vim: set et sw=4 sts=4 ts=8: + +endif diff --git a/autoload/rustfmt.vim b/autoload/rustfmt.vim index 307fead7..c0335173 100644 --- a/autoload/rustfmt.vim +++ b/autoload/rustfmt.vim @@ -6,106 +6,187 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if !exists("g:rustfmt_autosave") - let g:rustfmt_autosave = 0 + let g:rustfmt_autosave = 0 endif if !exists("g:rustfmt_command") - let g:rustfmt_command = "rustfmt" + let g:rustfmt_command = "rustfmt" endif if !exists("g:rustfmt_options") - let g:rustfmt_options = "" + let g:rustfmt_options = "" endif if !exists("g:rustfmt_fail_silently") - let g:rustfmt_fail_silently = 0 + let g:rustfmt_fail_silently = 0 +endif + +function! rustfmt#DetectVersion() + " Save rustfmt '--help' for feature inspection + silent let s:rustfmt_help = system(g:rustfmt_command . " --help") + let s:rustfmt_unstable_features = 1 - (s:rustfmt_help !~# "--unstable-features") + + " Build a comparable rustfmt version varible out of its `--version` output: + silent let s:rustfmt_version = system(g:rustfmt_command . " --version") + let s:rustfmt_version = matchlist(s:rustfmt_version, '\vrustfmt ([0-9]+[.][0-9]+[.][0-9]+)') + + if len(s:rustfmt_version) < 3 + let s:rustfmt_version = "0" + else + let s:rustfmt_version = s:rustfmt_version[1] + endif + + return s:rustfmt_version +endfunction + +call rustfmt#DetectVersion() + +if !exists("g:rustfmt_emit_files") + let g:rustfmt_emit_files = s:rustfmt_version >= "0.8.2" +endif + +if !exists("g:rustfmt_file_lines") + let g:rustfmt_file_lines = 1 - (s:rustfmt_help !~# "--file-lines JSON") endif let s:got_fmt_error = 0 +function! rustfmt#Load() + " Utility call to get this script loaded, for debugging +endfunction + +function! s:RustfmtWriteMode() + if g:rustfmt_emit_files + return "--emit=files" + else + return "--write-mode=overwrite" + endif +endfunction + function! s:RustfmtCommandRange(filename, line1, line2) - let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]} - return printf("%s %s --write-mode=overwrite --file-lines '[%s]'", g:rustfmt_command, g:rustfmt_options, json_encode(l:arg)) + if g:rustfmt_file_lines == 0 + echo "--file-lines is not supported in the installed `rustfmt` executable" + return + endif + + let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]} + let l:write_mode = s:RustfmtWriteMode() + + " FIXME: When --file-lines gets to be stable, enhance this version range checking + " accordingly. + let l:unstable_features = + \ (s:rustfmt_unstable_features && (s:rustfmt_version < '1.')) + \ ? '--unstable-features' : '' + + let l:cmd = printf("%s %s %s %s --file-lines '[%s]' %s", g:rustfmt_command, + \ l:write_mode, g:rustfmt_options, + \ l:unstable_features, json_encode(l:arg), shellescape(a:filename)) + return l:cmd endfunction function! s:RustfmtCommand(filename) - return g:rustfmt_command . " --write-mode=overwrite " . g:rustfmt_options . " " . shellescape(a:filename) + let l:write_mode = s:RustfmtWriteMode() + return g:rustfmt_command . " ". l:write_mode . " " . g:rustfmt_options . " " . shellescape(a:filename) endfunction -function! s:RunRustfmt(command, curw, tmpname) - if exists("*systemlist") - let out = systemlist(a:command) - else - let out = split(system(a:command), '\r\?\n') - endif - - if v:shell_error == 0 || v:shell_error == 3 - " remove undo point caused via BufWritePre - try | silent undojoin | catch | endtry - - " Replace current file with temp file, then reload buffer - call rename(a:tmpname, expand('%')) - silent edit! - let &syntax = &syntax - - " only clear location list if it was previously filled to prevent - " clobbering other additions - if s:got_fmt_error - let s:got_fmt_error = 0 - call setloclist(0, []) - lwindow - endif - elseif g:rustfmt_fail_silently == 0 - " otherwise get the errors and put them in the location list - let errors = [] - - for line in out - " src/lib.rs:13:5: 13:10 error: expected `,`, or `}`, found `value` - let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\):\s*\(\d\+:\d\+\s*\)\?\s*error: \(.*\)') - if !empty(tokens) - call add(errors, {"filename": @%, - \"lnum": tokens[2], - \"col": tokens[3], - \"text": tokens[5]}) - endif - endfor - - if empty(errors) - % | " Couldn't detect rustfmt error format, output errors - endif - - if !empty(errors) - call setloclist(0, errors, 'r') - echohl Error | echomsg "rustfmt returned error" | echohl None - endif - - let s:got_fmt_error = 1 - lwindow - " We didn't use the temp file, so clean up - call delete(a:tmpname) - endif - - call winrestview(a:curw) +function! s:RunRustfmt(command, tmpname, fail_silently) + mkview! + + if exists("*systemlist") + let out = systemlist(a:command) + else + let out = split(system(a:command), '\r\?\n') + endif + + if v:shell_error == 0 || v:shell_error == 3 + " remove undo point caused via BufWritePre + try | silent undojoin | catch | endtry + + " take the tmpfile's content, this is better than rename + " because it preserves file modes. + let l:content = readfile(a:tmpname) + 1,$d _ + call setline(1, l:content) + + " only clear location list if it was previously filled to prevent + " clobbering other additions + if s:got_fmt_error + let s:got_fmt_error = 0 + call setloclist(0, []) + lwindow + endif + elseif g:rustfmt_fail_silently == 0 && a:fail_silently == 0 + " otherwise get the errors and put them in the location list + let errors = [] + + let prev_line = "" + for line in out + " error: expected one of `;` or `as`, found `extern` + " --> src/main.rs:2:1 + let tokens = matchlist(line, '^\s-->\s\(.\{-}\):\(\d\+\):\(\d\+\)$') + if !empty(tokens) + call add(errors, {"filename": @%, + \"lnum": tokens[2], + \"col": tokens[3], + \"text": prev_line}) + endif + let prev_line = line + endfor + + if empty(errors) + % | " Couldn't detect rustfmt error format, output errors + endif + + if !empty(errors) + call setloclist(0, errors, 'r') + echohl Error | echomsg "rustfmt returned error" | echohl None + endif + + let s:got_fmt_error = 1 + lwindow + endif + + call delete(a:tmpname) + + silent! loadview endfunction -function! rustfmt#FormatRange(line1, line2) - let l:curw = winsaveview() - let l:tmpname = expand("%:p:h") . "/." . expand("%:p:t") . ".rustfmt" - call writefile(getline(1, '$'), l:tmpname) - - let command = s:RustfmtCommandRange(l:tmpname, a:line1, a:line2) +function! s:rustfmtSaveToTmp() + let l:tmpname = tempname() + call writefile(getline(1, '$'), l:tmpname) + return l:tmpname +endfunction - call s:RunRustfmt(command, l:curw, l:tmpname) +function! rustfmt#FormatRange(line1, line2) + let l:tmpname = s:rustfmtSaveToTmp() + let command = s:RustfmtCommandRange(l:tmpname, a:line1, a:line2) + call s:RunRustfmt(command, l:tmpname, 0) endfunction function! rustfmt#Format() - let l:curw = winsaveview() - let l:tmpname = expand("%:p:h") . "/." . expand("%:p:t") . ".rustfmt" - call writefile(getline(1, '$'), l:tmpname) - - let command = s:RustfmtCommand(l:tmpname) + let l:tmpname = s:rustfmtSaveToTmp() + let command = s:RustfmtCommand(l:tmpname) + call s:RunRustfmt(command, l:tmpname, 0) +endfunction - call s:RunRustfmt(command, l:curw, l:tmpname) +function! rustfmt#PreWrite() + if rust#GetConfigVar('rustfmt_autosave_if_config_present', 0) + if findfile('rustfmt.toml', '.;') !=# '' + let b:rustfmt_autosave = 1 + let b:rustfmt_autosave_because_of_config = 1 + endif + endif + + if !rust#GetConfigVar("rustfmt_autosave", 0) + return + endif + + let l:tmpname = s:rustfmtSaveToTmp() + let command = s:RustfmtCommand(l:tmpname) + call s:RunRustfmt(command, l:tmpname, 1) endfunction + +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/compiler/cargo.vim b/compiler/cargo.vim index 8e3c6212..10147e00 100644 --- a/compiler/cargo.vim +++ b/compiler/cargo.vim @@ -7,7 +7,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists('current_compiler') - finish + finish endif runtime compiler/rustc.vim let current_compiler = "cargo" @@ -16,26 +16,34 @@ let s:save_cpo = &cpo set cpo&vim if exists(':CompilerSet') != 2 - command -nargs=* CompilerSet setlocal <args> + command -nargs=* CompilerSet setlocal <args> endif if exists('g:cargo_makeprg_params') - execute 'CompilerSet makeprg=cargo\ '.escape(g:cargo_makeprg_params, ' \|"').'\ $*' + execute 'CompilerSet makeprg=cargo\ '.escape(g:cargo_makeprg_params, ' \|"').'\ $*' else - CompilerSet makeprg=cargo\ $* + CompilerSet makeprg=cargo\ $* endif +augroup RustCargoQuickFixHooks + autocmd! + autocmd QuickFixCmdPre make call cargo#quickfix#CmdPre() + autocmd QuickFixCmdPost make call cargo#quickfix#CmdPost() +augroup END + " Ignore general cargo progress messages CompilerSet errorformat+= - \%-G%\\s%#Downloading%.%#, - \%-G%\\s%#Compiling%.%#, - \%-G%\\s%#Finished%.%#, - \%-G%\\s%#error:\ Could\ not\ compile\ %.%#, - \%-G%\\s%#To\ learn\ more\\,%.%#, - \%-Gnote:\ Run\ with\ \`RUST_BACKTRACE=%.%#, - \%.%#panicked\ at\ \\'%m\\'\\,\ %f:%l + \%-G%\\s%#Downloading%.%#, + \%-G%\\s%#Compiling%.%#, + \%-G%\\s%#Finished%.%#, + \%-G%\\s%#error:\ Could\ not\ compile\ %.%#, + \%-G%\\s%#To\ learn\ more\\,%.%#, + \%-Gnote:\ Run\ with\ \`RUST_BACKTRACE=%.%#, + \%.%#panicked\ at\ \\'%m\\'\\,\ %f:%l:%c let &cpo = s:save_cpo unlet s:save_cpo +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/compiler/rustc.vim b/compiler/rustc.vim index 7b691b31..23390fd9 100644 --- a/compiler/rustc.vim +++ b/compiler/rustc.vim @@ -7,7 +7,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists("current_compiler") - finish + finish endif let current_compiler = "rustc" @@ -15,36 +15,39 @@ let s:cpo_save = &cpo set cpo&vim if exists(":CompilerSet") != 2 - command -nargs=* CompilerSet setlocal <args> + command -nargs=* CompilerSet setlocal <args> endif -if exists("g:rustc_makeprg_no_percent") && g:rustc_makeprg_no_percent != 0 - CompilerSet makeprg=rustc +if get(g:, 'rustc_makeprg_no_percent', 0) + CompilerSet makeprg=rustc else - CompilerSet makeprg=rustc\ \% + CompilerSet makeprg=rustc\ \% endif -" Old errorformat (before nightly 2016/08/10) +" New errorformat (after nightly 2016/08/10) CompilerSet errorformat= - \%f:%l:%c:\ %t%*[^:]:\ %m, - \%f:%l:%c:\ %*\\d:%*\\d\ %t%*[^:]:\ %m, - \%-G%f:%l\ %s, - \%-G%*[\ ]^, - \%-G%*[\ ]^%*[~], - \%-G%*[\ ]... + \%-G, + \%-Gerror:\ aborting\ %.%#, + \%-Gerror:\ Could\ not\ compile\ %.%#, + \%Eerror:\ %m, + \%Eerror[E%n]:\ %m, + \%Wwarning:\ %m, + \%Inote:\ %m, + \%C\ %#-->\ %f:%l:%c, + \%E\ \ left:%m,%C\ right:%m\ %f:%l:%c,%Z -" New errorformat (after nightly 2016/08/10) +" Old errorformat (before nightly 2016/08/10) CompilerSet errorformat+= - \%-G, - \%-Gerror:\ aborting\ %.%#, - \%-Gerror:\ Could\ not\ compile\ %.%#, - \%Eerror:\ %m, - \%Eerror[E%n]:\ %m, - \%Wwarning:\ %m, - \%Inote:\ %m, - \%C\ %#-->\ %f:%l:%c + \%f:%l:%c:\ %t%*[^:]:\ %m, + \%f:%l:%c:\ %*\\d:%*\\d\ %t%*[^:]:\ %m, + \%-G%f:%l\ %s, + \%-G%*[\ ]^, + \%-G%*[\ ]^%*[~], + \%-G%*[\ ]... let &cpo = s:cpo_save unlet s:cpo_save +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/extras/flow.vim b/extras/flow.vim index b3f899da..6a0aa94e 100644 --- a/extras/flow.vim +++ b/extras/flow.vim @@ -15,7 +15,7 @@ syntax region jsFlowArrowArguments contained matchgroup=jsFlowNoise start=/(/ syntax match jsFlowArrow contained /=>/ skipwhite skipempty nextgroup=jsFlowType,jsFlowTypeCustom,jsFlowParens syntax match jsFlowObjectKey contained /[0-9a-zA-Z_$?]*\(\s*:\)\@=/ contains=jsFunctionKey,jsFlowMaybe skipwhite skipempty nextgroup=jsObjectValue containedin=jsObject syntax match jsFlowOrOperator contained /|/ skipwhite skipempty nextgroup=@jsFlowCluster -syntax keyword jsFlowImportType contained type skipwhite skipempty nextgroup=jsModuleAsterisk,jsModuleKeyword,jsModuleGroup +syntax keyword jsFlowImportType contained type typeof skipwhite skipempty nextgroup=jsModuleAsterisk,jsModuleKeyword,jsModuleGroup syntax match jsFlowWildcard contained /*/ syntax match jsFlowReturn contained /:\s*/ contains=jsFlowNoise skipwhite skipempty nextgroup=@jsFlowReturnCluster,jsFlowArrow,jsFlowReturnParens @@ -23,7 +23,7 @@ syntax region jsFlowReturnObject contained matchgroup=jsFlowNoise start=/{/ syntax region jsFlowReturnArray contained matchgroup=jsFlowNoise start=/\[/ end=/\]/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp fold syntax region jsFlowReturnParens contained matchgroup=jsFlowNoise start=/(/ end=/)/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp,jsFlowReturnArrow fold syntax match jsFlowReturnArrow contained /=>/ skipwhite skipempty nextgroup=@jsFlowReturnCluster -syntax match jsFlowReturnKeyword contained /\k\+/ contains=jsFlowType,jsFlowTypeCustom skipwhite skipempty nextgroup=jsFlowReturnGroup,jsFuncBlock,jsFlowReturnOrOp +syntax match jsFlowReturnKeyword contained /\k\+/ contains=jsFlowType,jsFlowTypeCustom skipwhite skipempty nextgroup=jsFlowReturnGroup,jsFuncBlock,jsFlowReturnOrOp,jsFlowReturnArray syntax match jsFlowReturnMaybe contained /?/ skipwhite skipempty nextgroup=jsFlowReturnKeyword,jsFlowReturnObject syntax region jsFlowReturnGroup contained matchgroup=jsFlowNoise start=/</ end=/>/ contains=@jsFlowCluster skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturnOrOp syntax match jsFlowReturnOrOp contained /\s*|\s*/ skipwhite skipempty nextgroup=@jsFlowReturnCluster diff --git a/extras/jsdoc.vim b/extras/jsdoc.vim index ca4069cb..65546139 100644 --- a/extras/jsdoc.vim +++ b/extras/jsdoc.vim @@ -12,7 +12,7 @@ syntax match jsDocTags contained "@\(callback\|define\|enum\|external\| " tags containing references syntax match jsDocTags contained "@\(lends\|see\|tutorial\)\>" skipwhite nextgroup=jsDocSeeTag " other tags (no extra syntax) -syntax match jsDocTags contained "@\(abstract\|access\|accessor\|async\|author\|classdesc\|constant\|const\|constructor\|copyright\|deprecated\|desc\|description\|dict\|event\|example\|file\|file[oO]verview\|final\|function\|global\|ignore\|inheritDoc\|inner\|instance\|interface\|license\|localdoc\|method\|mixin\|nosideeffects\|override\|overview\|preserve\|private\|protected\|public\|readonly\|since\|static\|struct\|todo\|summary\|undocumented\|virtual\)\>" +syntax match jsDocTags contained "@\(abstract\|access\|accessor\|async\|author\|classdesc\|constant\|const\|constructor\|copyright\|deprecated\|desc\|description\|dict\|event\|example\|file\|file[oO]verview\|final\|function\|global\|ignore\|inherit[dD]oc\|inner\|instance\|interface\|license\|localdoc\|method\|mixin\|nosideeffects\|override\|overview\|preserve\|private\|protected\|public\|readonly\|since\|static\|struct\|todo\|summary\|undocumented\|virtual\)\>" syntax region jsDocType contained matchgroup=jsDocTypeBrackets start="{" end="}" contains=jsDocTypeRecord oneline skipwhite nextgroup=jsDocParam syntax match jsDocType contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" skipwhite nextgroup=jsDocParam diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 0a4d36d3..580946ff 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -442,23 +442,17 @@ endif if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == -1 augroup filetypedetect " javascript, from javascript.vim in pangloss/vim-javascript:_JAVASCRIPT -au BufNewFile,BufRead *.{js,mjs,jsm,es,es6},Jakefile setf javascript - -fun! s:SourceFlowSyntax() - if !exists('javascript_plugin_flow') && !exists('b:flow_active') && - \ search('\v\C%^\_s*%(//\s*|/\*[ \t\n*]*)\@flow>','nw') - runtime extras/flow.vim - let b:flow_active = 1 - endif -endfun -au FileType javascript au BufRead,BufWritePost <buffer> call s:SourceFlowSyntax() - fun! s:SelectJavascript() if getline(1) =~# '^#!.*/bin/\%(env\s\+\)\?node\>' set ft=javascript endif endfun -au BufNewFile,BufRead * call s:SelectJavascript() + +augroup javascript_syntax_detection + autocmd! + autocmd BufNewFile,BufRead *.{js,mjs,jsm,es,es6},Jakefile setfiletype javascript + autocmd BufNewFile,BufRead * call s:SelectJavascript() +augroup END augroup end endif @@ -951,6 +945,9 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 augroup filetypedetect " rust, from rust.vim in rust-lang/rust.vim au BufRead,BufNewFile *.rs set filetype=rust +au BufRead,BufNewFile Cargo.toml if &filetype == "" | set filetype=cfg | endif + +" vim: set et sw=4 sts=4 ts=8: augroup end endif diff --git a/ftplugin/elm.vim b/ftplugin/elm.vim index c989d922..b2423c29 100644 --- a/ftplugin/elm.vim +++ b/ftplugin/elm.vim @@ -43,14 +43,26 @@ setlocal comments=:-- setlocal commentstring=--\ %s " Commands -command! -buffer -nargs=? -complete=file ElmMake call elm#Make(<f-args>) -command! -buffer ElmMakeMain call elm#Make("Main.elm") -command! -buffer -nargs=? -complete=file ElmTest call elm#Test(<f-args>) -command! -buffer ElmRepl call elm#Repl() -command! -buffer ElmErrorDetail call elm#ErrorDetail() -command! -buffer ElmShowDocs call elm#ShowDocs() -command! -buffer ElmBrowseDocs call elm#BrowseDocs() -command! -buffer ElmFormat call elm#Format() +command -buffer -nargs=? -complete=file ElmMake call elm#Make(<f-args>) +command -buffer ElmMakeMain call elm#Make("Main.elm") +command -buffer -nargs=? -complete=file ElmTest call elm#Test(<f-args>) +command -buffer ElmRepl call elm#Repl() +command -buffer ElmErrorDetail call elm#ErrorDetail() +command -buffer ElmShowDocs call elm#ShowDocs() +command -buffer ElmBrowseDocs call elm#BrowseDocs() +command -buffer ElmFormat call elm#Format() + +" Commands cleanup +let b:undo_ftplugin = " + \ delcommand ElmMake + \|delcommand ElmMakeMain + \|delcommand ElmTest + \|delcommand ElmRepl + \|delcommand ElmErrorDetail + \|delcommand ElmShowDocs + \|delcommand ElmBrowseDocs + \|delcommand ElmFormat + \" if get(g:, 'elm_setup_keybindings', 1) nmap <buffer> <LocalLeader>m <Plug>(elm-make) diff --git a/ftplugin/eruby.vim b/ftplugin/eruby.vim index bf380e8a..12d3245f 100644 --- a/ftplugin/eruby.vim +++ b/ftplugin/eruby.vim @@ -7,7 +7,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ruby') == -1 " Release Coordinator: Doug Kearns <dougkearns@gmail.com> " Only do this when not done yet for this buffer -if exists("b:did_ftplugin") +if get(b:, 'did_ftplugin') =~# '\<eruby\>' finish endif @@ -25,6 +25,8 @@ endif if &filetype =~ '^eruby\.' let b:eruby_subtype = matchstr(&filetype,'^eruby\.\zs\w\+') +elseif &filetype =~ '^.*\.eruby\>' + let b:eruby_subtype = matchstr(&filetype,'^.\{-\}\ze\.eruby\>') elseif !exists("b:eruby_subtype") let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$") let b:eruby_subtype = matchstr(s:lines,'eruby_subtype=\zs\w\+') @@ -47,11 +49,14 @@ elseif !exists("b:eruby_subtype") endif endif -if exists("b:eruby_subtype") && b:eruby_subtype != '' && b:eruby_subtype !=? 'eruby' - exe "runtime! ftplugin/".b:eruby_subtype.".vim ftplugin/".b:eruby_subtype."_*.vim ftplugin/".b:eruby_subtype."/*.vim" -else - runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim +if &filetype =~# '^eruby\>' + if exists("b:eruby_subtype") && b:eruby_subtype != '' && b:eruby_subtype !=? 'eruby' + exe "runtime! ftplugin/".b:eruby_subtype.".vim ftplugin/".b:eruby_subtype."_*.vim ftplugin/".b:eruby_subtype."/*.vim" + else + runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim + endif endif +let s:did_ftplugin = get(b:, 'did_ftplugin', 1) unlet! b:did_ftplugin " Override our defaults if these were set by an included ftplugin. @@ -68,8 +73,23 @@ if exists("b:match_words") unlet b:match_words endif +let s:cfilemap = v:version >= 704 ? maparg('<Plug><cfile>', 'c', 0, 1) : {} +if !get(s:cfilemap, 'buffer') || !s:cfilemap.expr || s:cfilemap.rhs =~# 'ErubyAtCursor()' + let s:cfilemap = {} +endif +if !has_key(s:cfilemap, 'rhs') + let s:cfilemap.rhs = "substitute(&l:inex =~# '\\<v:fname\\>' && len(expand('<cfile>')) ? eval(substitute(&l:inex, '\\<v:fname\\>', '\\=string(expand(\"<cfile>\"))', 'g')) : '', '^$', \"\\022\\006\",'')" +endif +let s:ctagmap = v:version >= 704 ? maparg('<Plug><ctag>', 'c', 0, 1) : {} +if !get(s:ctagmap, 'buffer') || !s:ctagmap.expr || s:ctagmap.rhs =~# 'ErubyAtCursor()' + let s:ctagmap = {} +endif +let s:include = &l:include +let s:path = &l:path +let s:suffixesadd = &l:suffixesadd + runtime! ftplugin/ruby.vim ftplugin/ruby_*.vim ftplugin/ruby/*.vim -let b:did_ftplugin = 1 +let b:did_ftplugin = s:did_ftplugin . '.eruby' " Combine the new set of values with those previously included. if exists("b:undo_ftplugin") @@ -82,6 +102,15 @@ if exists("b:match_words") let s:match_words = b:match_words . ',' . s:match_words endif +if len(s:include) + let &l:include = s:include +endif +let &l:path = s:path . (s:path =~# ',$\|^$' ? '' : ',') . &l:path +let &l:suffixesadd = s:suffixesadd . (s:suffixesadd =~# ',$\|^$' ? '' : ',') . &l:suffixesadd +exe 'cmap <buffer><script><expr> <Plug><cfile> ErubyAtCursor() ? ' . maparg('<Plug><cfile>', 'c') . ' : ' . s:cfilemap.rhs +exe 'cmap <buffer><script><expr> <Plug><ctag> ErubyAtCursor() ? ' . maparg('<Plug><ctag>', 'c') . ' : ' . get(s:ctagmap, 'rhs', '"\022\027"') +unlet s:cfilemap s:ctagmap s:include s:path s:suffixesadd + " Change the browse dialog on Win32 to show mainly eRuby-related files if has("gui_win32") let b:browsefilter="eRuby Files (*.erb, *.rhtml)\t*.erb;*.rhtml\n" . s:browsefilter @@ -101,6 +130,11 @@ let b:undo_ftplugin = "setl cms< " let &cpo = s:save_cpo unlet s:save_cpo +function! ErubyAtCursor() abort + let groups = map(['erubyBlock', 'erubyComment', 'erubyExpression', 'erubyOneLiner'], 'hlID(v:val)') + return !empty(filter(synstack(line('.'), col('.')), 'index(groups, v:val) >= 0')) +endfunction + " vim: nowrap sw=2 sts=2 ts=8: endif diff --git a/ftplugin/ruby.vim b/ftplugin/ruby.vim index b844bfdf..5b763e16 100644 --- a/ftplugin/ruby.vim +++ b/ftplugin/ruby.vim @@ -46,19 +46,12 @@ endif setlocal formatoptions-=t formatoptions+=croql setlocal include=^\\s*\\<\\(load\\>\\\|require\\>\\\|autoload\\s*:\\=[\"']\\=\\h\\w*[\"']\\=,\\) -setlocal includeexpr=substitute(substitute(v:fname,'::','/','g'),'\\%(\\.rb\\)\\=$','.rb','') setlocal suffixesadd=.rb if exists("&ofu") && has("ruby") setlocal omnifunc=rubycomplete#Complete endif -" To activate, :set ballooneval -if has('balloon_eval') && exists('+balloonexpr') - setlocal balloonexpr=RubyBalloonexpr() -endif - - " TODO: "setlocal define=^\\s*def @@ -143,10 +136,20 @@ if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") \ "All Files (*.*)\t*.*\n" endif -let b:undo_ftplugin = "setl fo< inc< inex< sua< def< com< cms< path< tags< kp<" +let b:undo_ftplugin = "setl inc= sua= path= tags= fo< com< cms< kp=" \."| unlet! b:browsefilter b:match_ignorecase b:match_words b:match_skip" \."| if exists('&ofu') && has('ruby') | setl ofu< | endif" - \."| if has('balloon_eval') && exists('+bexpr') | setl bexpr< | endif" + +if get(g:, 'ruby_recommended_style', 1) + setlocal shiftwidth=2 softtabstop=2 expandtab + let b:undo_ftplugin .= ' | setl sw< sts< et<' +endif + +" To activate, :set ballooneval +if exists('+balloonexpr') && get(g:, 'ruby_balloonexpr') + setlocal balloonexpr=RubyBalloonexpr() + let b:undo_ftplugin .= "| setl bexpr=" +endif function! s:map(mode, flags, map) abort let from = matchstr(a:map, '\S\+') @@ -156,9 +159,9 @@ function! s:map(mode, flags, map) abort endif endfunction -cmap <buffer><script><expr> <Plug><cword> substitute(RubyCursorIdentifier(),'^$',"\022\027",'') +cmap <buffer><script><expr> <Plug><ctag> substitute(RubyCursorTag(),'^$',"\022\027",'') cmap <buffer><script><expr> <Plug><cfile> substitute(RubyCursorFile(),'^$',"\022\006",'') -let b:undo_ftplugin .= "| sil! cunmap <buffer> <Plug><cword>| sil! cunmap <buffer> <Plug><cfile>" +let b:undo_ftplugin .= "| sil! cunmap <buffer> <Plug><ctag>| sil! cunmap <buffer> <Plug><cfile>" if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") nmap <buffer><script> <SID>: :<C-U> @@ -206,19 +209,18 @@ if !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps") \."| sil! exe 'xunmap <buffer> iM' | sil! exe 'xunmap <buffer> aM'" endif - call s:map('c', '', '<C-R><C-W> <Plug><cword>') call s:map('c', '', '<C-R><C-F> <Plug><cfile>') cmap <buffer><script><expr> <SID>tagzv &foldopen =~# 'tag' ? '<Bar>norm! zv' : '' - call s:map('n', '<silent>', '<C-]> <SID>:exe v:count1."tag <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', 'g<C-]> <SID>:exe "tjump <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', 'g] <SID>:exe "tselect <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', '<C-W>] <SID>:exe v:count1."stag <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', '<C-W><C-]> <SID>:exe v:count1."stag <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', '<C-W>g<C-]> <SID>:exe "stjump <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', '<C-W>g] <SID>:exe "stselect <Plug><cword>"<SID>tagzv<CR>') - call s:map('n', '<silent>', '<C-W>} <SID>:exe v:count1."ptag <Plug><cword>"<CR>') - call s:map('n', '<silent>', '<C-W>g} <SID>:exe "ptjump <Plug><cword>"<CR>') + call s:map('n', '<silent>', '<C-]> <SID>:exe v:count1."tag <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', 'g<C-]> <SID>:exe "tjump <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', 'g] <SID>:exe "tselect <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>] <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W><C-]> <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>g<C-]> <SID>:exe "stjump <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>g] <SID>:exe "stselect <Plug><ctag>"<SID>tagzv<CR>') + call s:map('n', '<silent>', '<C-W>} <SID>:exe v:count1."ptag <Plug><ctag>"<CR>') + call s:map('n', '<silent>', '<C-W>g} <SID>:exe "ptjump <Plug><ctag>"<CR>') call s:map('n', '<silent>', 'gf <SID>c:find <Plug><cfile><CR>') call s:map('n', '<silent>', '<C-W>f <SID>c:sfind <Plug><cfile><CR>') @@ -352,6 +354,10 @@ function! RubyCursorIdentifier() abort return stripped == '' ? expand("<cword>") : stripped endfunction +function! RubyCursorTag() abort + return substitute(RubyCursorIdentifier(), '^[$@]*', '', '') +endfunction + function! RubyCursorFile() abort let isfname = &isfname try diff --git a/ftplugin/rust.vim b/ftplugin/rust.vim index d1765d07..acf4d71d 100644 --- a/ftplugin/rust.vim +++ b/ftplugin/rust.vim @@ -8,7 +8,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if exists("b:did_ftplugin") - finish + finish endif let b:did_ftplugin = 1 @@ -16,181 +16,190 @@ let s:save_cpo = &cpo set cpo&vim augroup rust.vim -autocmd! - -" Variables {{{1 - -" The rust source code at present seems to typically omit a leader on /*! -" comments, so we'll use that as our default, but make it easy to switch. -" This does not affect indentation at all (I tested it with and without -" leader), merely whether a leader is inserted by default or not. -if exists("g:rust_bang_comment_leader") && g:rust_bang_comment_leader != 0 - " Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why, - " but without it, */ gets indented one space even if there were no - " leaders. I'm fairly sure that's a Vim bug. - setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,:// -else - setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,:// -endif -setlocal commentstring=//%s -setlocal formatoptions-=t formatoptions+=croqnl -" j was only added in 7.3.541, so stop complaints about its nonexistence -silent! setlocal formatoptions+=j - -" smartindent will be overridden by indentexpr if filetype indent is on, but -" otherwise it's better than nothing. -setlocal smartindent nocindent - -if !exists("g:rust_recommended_style") || g:rust_recommended_style != 0 - setlocal tabstop=4 shiftwidth=4 softtabstop=4 expandtab - setlocal textwidth=99 -endif - -" This includeexpr isn't perfect, but it's a good start -setlocal includeexpr=substitute(v:fname,'::','/','g') - -setlocal suffixesadd=.rs - -if exists("g:ftplugin_rust_source_path") - let &l:path=g:ftplugin_rust_source_path . ',' . &l:path -endif - -if exists("g:loaded_delimitMate") - if exists("b:delimitMate_excluded_regions") - let b:rust_original_delimitMate_excluded_regions = b:delimitMate_excluded_regions - endif - - let s:delimitMate_extra_excluded_regions = ',rustLifetimeCandidate,rustGenericLifetimeCandidate' - - " For this buffer, when delimitMate issues the `User delimitMate_map` - " event in the autocommand system, add the above-defined extra excluded - " regions to delimitMate's state, if they have not already been added. - autocmd User <buffer> - \ if expand('<afile>') ==# 'delimitMate_map' && match( - \ delimitMate#Get("excluded_regions"), - \ s:delimitMate_extra_excluded_regions) == -1 - \| let b:delimitMate_excluded_regions = - \ delimitMate#Get("excluded_regions") - \ . s:delimitMate_extra_excluded_regions - \|endif - - " For this buffer, when delimitMate issues the `User delimitMate_unmap` - " event in the autocommand system, delete the above-defined extra excluded - " regions from delimitMate's state (the deletion being idempotent and - " having no effect if the extra excluded regions are not present in the - " targeted part of delimitMate's state). - autocmd User <buffer> - \ if expand('<afile>') ==# 'delimitMate_unmap' - \| let b:delimitMate_excluded_regions = substitute( - \ delimitMate#Get("excluded_regions"), - \ '\C\V' . s:delimitMate_extra_excluded_regions, - \ '', 'g') - \|endif -endif - -if has("folding") && exists('g:rust_fold') && g:rust_fold != 0 - let b:rust_set_foldmethod=1 - setlocal foldmethod=syntax - if g:rust_fold == 2 - setlocal foldlevel< - else - setlocal foldlevel=99 - endif -endif - -if has('conceal') && exists('g:rust_conceal') && g:rust_conceal != 0 - let b:rust_set_conceallevel=1 - setlocal conceallevel=2 -endif - -" Motion Commands {{{1 - -" Bind motion commands to support hanging indents -nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR> -nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR> -xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR> -xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR> -onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR> -onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR> - -" Commands {{{1 - -" See |:RustRun| for docs -command! -nargs=* -complete=file -bang -buffer RustRun call rust#Run(<bang>0, <q-args>) - -" See |:RustExpand| for docs -command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -buffer RustExpand call rust#Expand(<bang>0, <q-args>) - -" See |:RustEmitIr| for docs -command! -nargs=* -buffer RustEmitIr call rust#Emit("llvm-ir", <q-args>) - -" See |:RustEmitAsm| for docs -command! -nargs=* -buffer RustEmitAsm call rust#Emit("asm", <q-args>) - -" See |:RustPlay| for docs -command! -range=% RustPlay :call rust#Play(<count>, <line1>, <line2>, <f-args>) - -" See |:RustFmt| for docs -command! -buffer RustFmt call rustfmt#Format() - -" See |:RustFmtRange| for docs -command! -range -buffer RustFmtRange call rustfmt#FormatRange(<line1>, <line2>) - -" Mappings {{{1 - -" Bind ⌘R in MacVim to :RustRun -nnoremap <silent> <buffer> <D-r> :RustRun<CR> -" Bind ⌘⇧R in MacVim to :RustRun! pre-filled with the last args -nnoremap <buffer> <D-R> :RustRun! <C-r>=join(b:rust_last_rustc_args)<CR><C-\>erust#AppendCmdLine(' -- ' . join(b:rust_last_args))<CR> - -if !exists("b:rust_last_rustc_args") || !exists("b:rust_last_args") - let b:rust_last_rustc_args = [] - let b:rust_last_args = [] -endif - -" Cleanup {{{1 - -let b:undo_ftplugin = " - \ setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< - \|setlocal tabstop< shiftwidth< softtabstop< expandtab< textwidth< - \|if exists('b:rust_original_delimitMate_excluded_regions') - \|let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions - \|unlet b:rust_original_delimitMate_excluded_regions - \|else - \|unlet! b:delimitMate_excluded_regions - \|endif - \|if exists('b:rust_set_foldmethod') - \|setlocal foldmethod< foldlevel< - \|unlet b:rust_set_foldmethod - \|endif - \|if exists('b:rust_set_conceallevel') - \|setlocal conceallevel< - \|unlet b:rust_set_conceallevel - \|endif - \|unlet! b:rust_last_rustc_args b:rust_last_args - \|delcommand RustRun - \|delcommand RustExpand - \|delcommand RustEmitIr - \|delcommand RustEmitAsm - \|delcommand RustPlay - \|nunmap <buffer> <D-r> - \|nunmap <buffer> <D-R> - \|nunmap <buffer> [[ - \|nunmap <buffer> ]] - \|xunmap <buffer> [[ - \|xunmap <buffer> ]] - \|ounmap <buffer> [[ - \|ounmap <buffer> ]] - \|set matchpairs-=<:> - \|unlet b:match_skip - \" - -" }}}1 - -" Code formatting on save -if get(g:, "rustfmt_autosave", 0) - autocmd BufWritePre *.rs silent! call rustfmt#Format() -endif + autocmd! + + if get(b:, 'current_compiler', '') ==# '' + if strlen(findfile('Cargo.toml', '.;')) > 0 + compiler cargo + else + compiler rustc + endif + endif + + " Variables {{{1 + + " The rust source code at present seems to typically omit a leader on /*! + " comments, so we'll use that as our default, but make it easy to switch. + " This does not affect indentation at all (I tested it with and without + " leader), merely whether a leader is inserted by default or not. + if get(g:, 'rust_bang_comment_leader', 0) + " Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why, + " but without it, */ gets indented one space even if there were no + " leaders. I'm fairly sure that's a Vim bug. + setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,:// + else + setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,:// + endif + setlocal commentstring=//%s + setlocal formatoptions-=t formatoptions+=croqnl + " j was only added in 7.3.541, so stop complaints about its nonexistence + silent! setlocal formatoptions+=j + + " smartindent will be overridden by indentexpr if filetype indent is on, but + " otherwise it's better than nothing. + setlocal smartindent nocindent + + if get(g:, 'rust_recommended_style', 1) + let b:rust_set_style = 1 + setlocal tabstop=8 shiftwidth=4 softtabstop=4 expandtab + setlocal textwidth=99 + endif + + " This includeexpr isn't perfect, but it's a good start + setlocal includeexpr=substitute(v:fname,'::','/','g') + + setlocal suffixesadd=.rs + + if exists("g:ftplugin_rust_source_path") + let &l:path=g:ftplugin_rust_source_path . ',' . &l:path + endif + + if exists("g:loaded_delimitMate") + if exists("b:delimitMate_excluded_regions") + let b:rust_original_delimitMate_excluded_regions = b:delimitMate_excluded_regions + endif + + let s:delimitMate_extra_excluded_regions = ',rustLifetimeCandidate,rustGenericLifetimeCandidate' + + " For this buffer, when delimitMate issues the `User delimitMate_map` + " event in the autocommand system, add the above-defined extra excluded + " regions to delimitMate's state, if they have not already been added. + autocmd User <buffer> + \ if expand('<afile>') ==# 'delimitMate_map' && match( + \ delimitMate#Get("excluded_regions"), + \ s:delimitMate_extra_excluded_regions) == -1 + \| let b:delimitMate_excluded_regions = + \ delimitMate#Get("excluded_regions") + \ . s:delimitMate_extra_excluded_regions + \|endif + + " For this buffer, when delimitMate issues the `User delimitMate_unmap` + " event in the autocommand system, delete the above-defined extra excluded + " regions from delimitMate's state (the deletion being idempotent and + " having no effect if the extra excluded regions are not present in the + " targeted part of delimitMate's state). + autocmd User <buffer> + \ if expand('<afile>') ==# 'delimitMate_unmap' + \| let b:delimitMate_excluded_regions = substitute( + \ delimitMate#Get("excluded_regions"), + \ '\C\V' . s:delimitMate_extra_excluded_regions, + \ '', 'g') + \|endif + endif + + if has("folding") && get(g:, 'rust_fold', 0) + let b:rust_set_foldmethod=1 + setlocal foldmethod=syntax + if g:rust_fold == 2 + setlocal foldlevel< + else + setlocal foldlevel=99 + endif + endif + + if has('conceal') && get(g:, 'rust_conceal', 0) + let b:rust_set_conceallevel=1 + setlocal conceallevel=2 + endif + + " Motion Commands {{{1 + + " Bind motion commands to support hanging indents + nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR> + nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR> + xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR> + xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR> + onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR> + onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR> + + " Commands {{{1 + + " See |:RustRun| for docs + command! -nargs=* -complete=file -bang -buffer RustRun call rust#Run(<bang>0, <q-args>) + + " See |:RustExpand| for docs + command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -buffer RustExpand call rust#Expand(<bang>0, <q-args>) + + " See |:RustEmitIr| for docs + command! -nargs=* -buffer RustEmitIr call rust#Emit("llvm-ir", <q-args>) + + " See |:RustEmitAsm| for docs + command! -nargs=* -buffer RustEmitAsm call rust#Emit("asm", <q-args>) + + " See |:RustPlay| for docs + command! -range=% RustPlay :call rust#Play(<count>, <line1>, <line2>, <f-args>) + + " See |:RustFmt| for docs + command! -buffer RustFmt call rustfmt#Format() + + " See |:RustFmtRange| for docs + command! -range -buffer RustFmtRange call rustfmt#FormatRange(<line1>, <line2>) + + " See |:RustInfo| for docs + command! -bar RustInfo call rust#debugging#Info() + + " See |:RustInfoToClipboard| for docs + command! -bar RustInfoToClipboard call rust#debugging#InfoToClipboard() + + " See |:RustInfoToFile| for docs + command! -bar -nargs=1 RustInfoToFile call rust#debugging#InfoToFile(<f-args>) + + if !exists("b:rust_last_rustc_args") || !exists("b:rust_last_args") + let b:rust_last_rustc_args = [] + let b:rust_last_args = [] + endif + + " Cleanup {{{1 + + let b:undo_ftplugin = " + \ setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< + \|if exists('b:rust_set_style') + \|setlocal tabstop< shiftwidth< softtabstop< expandtab< textwidth< + \|endif + \|if exists('b:rust_original_delimitMate_excluded_regions') + \|let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions + \|unlet b:rust_original_delimitMate_excluded_regions + \|else + \|unlet! b:delimitMate_excluded_regions + \|endif + \|if exists('b:rust_set_foldmethod') + \|setlocal foldmethod< foldlevel< + \|unlet b:rust_set_foldmethod + \|endif + \|if exists('b:rust_set_conceallevel') + \|setlocal conceallevel< + \|unlet b:rust_set_conceallevel + \|endif + \|unlet! b:rust_last_rustc_args b:rust_last_args + \|delcommand RustRun + \|delcommand RustExpand + \|delcommand RustEmitIr + \|delcommand RustEmitAsm + \|delcommand RustPlay + \|nunmap <buffer> [[ + \|nunmap <buffer> ]] + \|xunmap <buffer> [[ + \|xunmap <buffer> ]] + \|ounmap <buffer> [[ + \|ounmap <buffer> ]] + \|set matchpairs-=<:> + \|unlet b:match_skip + \" + + " }}}1 + + " Code formatting on save + autocmd BufWritePre *.rs silent! call rustfmt#PreWrite() augroup END @@ -201,6 +210,6 @@ let b:match_skip = 's:comment\|string\|rustArrow' let &cpo = s:save_cpo unlet s:save_cpo -" vim: set noet sw=8 ts=8: +" vim: set et sw=4 sts=4 ts=8: endif diff --git a/ftplugin/rust/tagbar.vim b/ftplugin/rust/tagbar.vim new file mode 100644 index 00000000..5c95f357 --- /dev/null +++ b/ftplugin/rust/tagbar.vim @@ -0,0 +1,38 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 + +" +" Support for Tagbar -- https://github.com/majutsushi/tagbar +" +if !exists(':Tagbar') + finish +endif + +let s:save_cpo = &cpo +set cpo&vim + +let g:tagbar_type_rust = { + \ 'ctagstype' : 'rust', + \ 'kinds' : [ + \'T:types', + \'f:functions', + \'g:enumerations', + \'s:structures', + \'m:modules', + \'c:constants', + \'t:traits', + \'i:trait implementations', + \ ] + \ } + +" In case you've updated/customized your ~/.ctags and prefer to use it. +if !get(g:, 'rust_use_custom_ctags_defs', 0) + let g:tagbar_type_rust.deffile = expand('<sfile>:p:h:h:h') . '/ctags/rust.ctags' +endif + +let &cpo = s:save_cpo +unlet s:save_cpo + + +" vim: set et sw=4 sts=4 ts=8: + +endif diff --git a/ftplugin/vue.vim b/ftplugin/vue.vim index cc10c561..959dca4e 100644 --- a/ftplugin/vue.vim +++ b/ftplugin/vue.vim @@ -5,7 +5,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vue') == -1 " Maintainer: Eduardo San Martin Morote " Author: Adriaan Zonnenberg -if exists("b:did_ftplugin") +if exists('b:did_ftplugin') finish endif @@ -20,11 +20,9 @@ if !exists('g:no_plugin_maps') && !exists('g:no_vue_maps') nnoremap <silent> <buffer> ][ :call search('^</\(template\<Bar>script\<Bar>style\)', 'W')<CR> endif -if exists('g:loaded_ale') - let g:ale_linters = get(g:, 'ale_linters', {}) - let g:ale_linters.vue = get(g:ale_linters, 'vue', ['eslint']) - let g:ale_linter_aliases = get(g:, 'ale_linter_aliases', {}) - let g:ale_linter_aliases.vue = get(g:ale_linter_aliases, 'vue', 'javascript') -endif +" Run only ESLint for Vue files by default. +" linters specifically for Vue can still be loaded. +let b:ale_linter_aliases = ['vue', 'javascript'] +let b:ale_linters = ['eslint'] endif diff --git a/indent/eruby.vim b/indent/eruby.vim index 6fd76600..cdc5fedf 100644 --- a/indent/eruby.vim +++ b/indent/eruby.vim @@ -6,7 +6,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ruby') == -1 " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> -if exists("b:did_indent") +if get(b:, 'did_indent') =~# '\<eruby\>' finish endif @@ -14,12 +14,14 @@ runtime! indent/ruby.vim unlet! b:did_indent setlocal indentexpr= -if exists("b:eruby_subtype") && b:eruby_subtype != '' && b:eruby_subtype !=# 'eruby' - exe "runtime! indent/".b:eruby_subtype.".vim" -else - runtime! indent/html.vim +if &filetype =~# '^eruby\>' + if exists("b:eruby_subtype") && b:eruby_subtype != '' && b:eruby_subtype !=# 'eruby' + exe "runtime! indent/".b:eruby_subtype.".vim" + else + runtime! indent/html.vim + endif endif -unlet! b:did_indent +let b:did_indent = get(b:, 'did_indent', 1) . '.eruby' " Force HTML indent to not keep state. let b:html_indent_usestate = 0 @@ -33,8 +35,6 @@ if &l:indentexpr == '' endif let b:eruby_subtype_indentexpr = &l:indentexpr -let b:did_indent = 1 - setlocal indentexpr=GetErubyIndent() setlocal indentkeys=o,O,*<Return>,<>>,{,},0),0],o,O,!^F,=end,=else,=elsif,=rescue,=ensure,=when diff --git a/indent/nix.vim b/indent/nix.vim index fd277dcc..2910cbd6 100644 --- a/indent/nix.vim +++ b/indent/nix.vim @@ -21,6 +21,8 @@ let s:cpo_save = &cpo set cpo&vim let s:skip_syntax = '\%(Comment\|String\)$' +let s:binding_open = '\%(\<let\>\|{\)' +let s:binding_close = '\%(\<in\>\|}\)' let s:block_open = '\%({\|[\)' let s:block_close = '\%(}\|]\)' @@ -43,6 +45,23 @@ function! GetNixIndent() let current_line = getline(v:lnum) let last_line = getline(lnum) + if current_line =~ '^\s*in\>' + let save_cursor = getcurpos() + normal ^ + let bslnum = searchpair(s:binding_open, '', s:binding_close, 'bnW', + \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "StringSpecial$"') + call setpos('.', save_cursor) + return indent(bslnum) + endif + + if last_line =~ ';$' + let bslnum = searchpair(s:binding_open, '', s:binding_close, 'bnW', + \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "StringSpecial$"') + if bslnum != 0 + let ind = indent(bslnum) + &sw + endif + endif + if last_line =~ s:block_open . '\s*$' let ind += &sw endif @@ -51,6 +70,10 @@ function! GetNixIndent() let ind -= &sw endif + if last_line =~ '[(=]$' + let ind += &sw + endif + if last_line =~ '\<let\s*$' let ind += &sw endif diff --git a/indent/purescript.vim b/indent/purescript.vim index c22da095..515f88e2 100644 --- a/indent/purescript.vim +++ b/indent/purescript.vim @@ -103,7 +103,7 @@ function! GetPurescriptIndent() return s endif - if prevline =~ '^\S.*::' && line !~ '^\s*\(\.\|->\|→\|=>\|⇒\)' && !~ '^instance' + if prevline =~ '^\S.*::' && line !~ '^\s*\(\.\|->\|→\|=>\|⇒\)' && prevline !~ '^instance' " f :: String " -> String return 0 diff --git a/indent/rust.vim b/indent/rust.vim index 042e2ab5..fa4dfb54 100644 --- a/indent/rust.vim +++ b/indent/rust.vim @@ -3,17 +3,17 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " Vim indent file " Language: Rust " Author: Chris Morgan <me@chrismorgan.info> -" Last Change: 2017 Mar 21 +" Last Change: 2018 Jan 10 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim " Only load this indent file when no other was loaded. if exists("b:did_indent") - finish + finish endif let b:did_indent = 1 setlocal cindent -setlocal cinoptions=L0,(0,Ws,J1,j1 +setlocal cinoptions=L0,(0,Ws,J1,j1,m1 setlocal cinkeys=0{,0},!^F,o,O,0[,0] " Don't think cinwords will actually do anything at all... never mind setlocal cinwords=for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fn,extern,macro @@ -28,7 +28,7 @@ setlocal indentexpr=GetRustIndent(v:lnum) " Only define the function once. if exists("*GetRustIndent") - finish + finish endif let s:save_cpo = &cpo @@ -37,181 +37,183 @@ set cpo&vim " Come here when loading the script the first time. function! s:get_line_trimmed(lnum) - " Get the line and remove a trailing comment. - " Use syntax highlighting attributes when possible. - " NOTE: this is not accurate; /* */ or a line continuation could trick it - let line = getline(a:lnum) - let line_len = strlen(line) - if has('syntax_items') - " If the last character in the line is a comment, do a binary search for - " the start of the comment. synID() is slow, a linear search would take - " too long on a long line. - if synIDattr(synID(a:lnum, line_len, 1), "name") =~ 'Comment\|Todo' - let min = 1 - let max = line_len - while min < max - let col = (min + max) / 2 - if synIDattr(synID(a:lnum, col, 1), "name") =~ 'Comment\|Todo' - let max = col - else - let min = col + 1 - endif - endwhile - let line = strpart(line, 0, min - 1) - endif - return substitute(line, "\s*$", "", "") - else - " Sorry, this is not complete, nor fully correct (e.g. string "//"). - " Such is life. - return substitute(line, "\s*//.*$", "", "") - endif + " Get the line and remove a trailing comment. + " Use syntax highlighting attributes when possible. + " NOTE: this is not accurate; /* */ or a line continuation could trick it + let line = getline(a:lnum) + let line_len = strlen(line) + if has('syntax_items') + " If the last character in the line is a comment, do a binary search for + " the start of the comment. synID() is slow, a linear search would take + " too long on a long line. + if synIDattr(synID(a:lnum, line_len, 1), "name") =~ 'Comment\|Todo' + let min = 1 + let max = line_len + while min < max + let col = (min + max) / 2 + if synIDattr(synID(a:lnum, col, 1), "name") =~ 'Comment\|Todo' + let max = col + else + let min = col + 1 + endif + endwhile + let line = strpart(line, 0, min - 1) + endif + return substitute(line, "\s*$", "", "") + else + " Sorry, this is not complete, nor fully correct (e.g. string "//"). + " Such is life. + return substitute(line, "\s*//.*$", "", "") + endif endfunction function! s:is_string_comment(lnum, col) - if has('syntax_items') - for id in synstack(a:lnum, a:col) - let synname = synIDattr(id, "name") - if synname == "rustString" || synname =~ "^rustComment" - return 1 - endif - endfor - else - " without syntax, let's not even try - return 0 - endif + if has('syntax_items') + for id in synstack(a:lnum, a:col) + let synname = synIDattr(id, "name") + if synname == "rustString" || synname =~ "^rustComment" + return 1 + endif + endfor + else + " without syntax, let's not even try + return 0 + endif endfunction function GetRustIndent(lnum) - " Starting assumption: cindent (called at the end) will do it right - " normally. We just want to fix up a few cases. - - let line = getline(a:lnum) - - if has('syntax_items') - let synname = synIDattr(synID(a:lnum, 1, 1), "name") - if synname == "rustString" - " If the start of the line is in a string, don't change the indent - return -1 - elseif synname =~ '\(Comment\|Todo\)' - \ && line !~ '^\s*/\*' " not /* opening line - if synname =~ "CommentML" " multi-line - if line !~ '^\s*\*' && getline(a:lnum - 1) =~ '^\s*/\*' - " This is (hopefully) the line after a /*, and it has no - " leader, so the correct indentation is that of the - " previous line. - return GetRustIndent(a:lnum - 1) - endif - endif - " If it's in a comment, let cindent take care of it now. This is - " for cases like "/*" where the next line should start " * ", not - " "* " as the code below would otherwise cause for module scope - " Fun fact: " /*\n*\n*/" takes two calls to get right! - return cindent(a:lnum) - endif - endif - - " cindent gets second and subsequent match patterns/struct members wrong, - " as it treats the comma as indicating an unfinished statement:: - " - " match a { - " b => c, - " d => e, - " f => g, - " }; - - " Search backwards for the previous non-empty line. - let prevlinenum = prevnonblank(a:lnum - 1) - let prevline = s:get_line_trimmed(prevlinenum) - while prevlinenum > 1 && prevline !~ '[^[:blank:]]' - let prevlinenum = prevnonblank(prevlinenum - 1) - let prevline = s:get_line_trimmed(prevlinenum) - endwhile - - " Handle where clauses nicely: subsequent values should line up nicely. - if prevline[len(prevline) - 1] == "," - \ && prevline =~# '^\s*where\s' - return indent(prevlinenum) + 6 - endif - - if prevline[len(prevline) - 1] == "," - \ && s:get_line_trimmed(a:lnum) !~ '^\s*[\[\]{}]' - \ && prevline !~ '^\s*fn\s' - \ && prevline !~ '([^()]\+,$' - \ && s:get_line_trimmed(a:lnum) !~ '^\s*\S\+\s*=>' - " Oh ho! The previous line ended in a comma! I bet cindent will try to - " take this too far... For now, let's normally use the previous line's - " indent. - - " One case where this doesn't work out is where *this* line contains - " square or curly brackets; then we normally *do* want to be indenting - " further. - " - " Another case where we don't want to is one like a function - " definition with arguments spread over multiple lines: - " - " fn foo(baz: Baz, - " baz: Baz) // <-- cindent gets this right by itself - " - " Another case is similar to the previous, except calling a function - " instead of defining it, or any conditional expression that leaves - " an open paren: - " - " foo(baz, - " baz); - " - " if baz && (foo || - " bar) { - " - " Another case is when the current line is a new match arm. - " - " There are probably other cases where we don't want to do this as - " well. Add them as needed. - return indent(prevlinenum) - endif - - if !has("patch-7.4.355") - " cindent before 7.4.355 doesn't do the module scope well at all; e.g.:: - " - " static FOO : &'static [bool] = [ - " true, - " false, - " false, - " true, - " ]; - " - " uh oh, next statement is indented further! - - " Note that this does *not* apply the line continuation pattern properly; - " that's too hard to do correctly for my liking at present, so I'll just - " start with these two main cases (square brackets and not returning to - " column zero) - - call cursor(a:lnum, 1) - if searchpair('{\|(', '', '}\|)', 'nbW', - \ 's:is_string_comment(line("."), col("."))') == 0 - if searchpair('\[', '', '\]', 'nbW', - \ 's:is_string_comment(line("."), col("."))') == 0 - " Global scope, should be zero - return 0 - else - " At the module scope, inside square brackets only - "if getline(a:lnum)[0] == ']' || search('\[', '', '\]', 'nW') == a:lnum - if line =~ "^\\s*]" - " It's the closing line, dedent it - return 0 - else - return &shiftwidth - endif - endif - endif - endif - - " Fall back on cindent, which does it mostly right - return cindent(a:lnum) + " Starting assumption: cindent (called at the end) will do it right + " normally. We just want to fix up a few cases. + + let line = getline(a:lnum) + + if has('syntax_items') + let synname = synIDattr(synID(a:lnum, 1, 1), "name") + if synname == "rustString" + " If the start of the line is in a string, don't change the indent + return -1 + elseif synname =~ '\(Comment\|Todo\)' + \ && line !~ '^\s*/\*' " not /* opening line + if synname =~ "CommentML" " multi-line + if line !~ '^\s*\*' && getline(a:lnum - 1) =~ '^\s*/\*' + " This is (hopefully) the line after a /*, and it has no + " leader, so the correct indentation is that of the + " previous line. + return GetRustIndent(a:lnum - 1) + endif + endif + " If it's in a comment, let cindent take care of it now. This is + " for cases like "/*" where the next line should start " * ", not + " "* " as the code below would otherwise cause for module scope + " Fun fact: " /*\n*\n*/" takes two calls to get right! + return cindent(a:lnum) + endif + endif + + " cindent gets second and subsequent match patterns/struct members wrong, + " as it treats the comma as indicating an unfinished statement:: + " + " match a { + " b => c, + " d => e, + " f => g, + " }; + + " Search backwards for the previous non-empty line. + let prevlinenum = prevnonblank(a:lnum - 1) + let prevline = s:get_line_trimmed(prevlinenum) + while prevlinenum > 1 && prevline !~ '[^[:blank:]]' + let prevlinenum = prevnonblank(prevlinenum - 1) + let prevline = s:get_line_trimmed(prevlinenum) + endwhile + + " Handle where clauses nicely: subsequent values should line up nicely. + if prevline[len(prevline) - 1] == "," + \ && prevline =~# '^\s*where\s' + return indent(prevlinenum) + 6 + endif + + if prevline[len(prevline) - 1] == "," + \ && s:get_line_trimmed(a:lnum) !~ '^\s*[\[\]{}]' + \ && prevline !~ '^\s*fn\s' + \ && prevline !~ '([^()]\+,$' + \ && s:get_line_trimmed(a:lnum) !~ '^\s*\S\+\s*=>' + " Oh ho! The previous line ended in a comma! I bet cindent will try to + " take this too far... For now, let's normally use the previous line's + " indent. + + " One case where this doesn't work out is where *this* line contains + " square or curly brackets; then we normally *do* want to be indenting + " further. + " + " Another case where we don't want to is one like a function + " definition with arguments spread over multiple lines: + " + " fn foo(baz: Baz, + " baz: Baz) // <-- cindent gets this right by itself + " + " Another case is similar to the previous, except calling a function + " instead of defining it, or any conditional expression that leaves + " an open paren: + " + " foo(baz, + " baz); + " + " if baz && (foo || + " bar) { + " + " Another case is when the current line is a new match arm. + " + " There are probably other cases where we don't want to do this as + " well. Add them as needed. + return indent(prevlinenum) + endif + + if !has("patch-7.4.355") + " cindent before 7.4.355 doesn't do the module scope well at all; e.g.:: + " + " static FOO : &'static [bool] = [ + " true, + " false, + " false, + " true, + " ]; + " + " uh oh, next statement is indented further! + + " Note that this does *not* apply the line continuation pattern properly; + " that's too hard to do correctly for my liking at present, so I'll just + " start with these two main cases (square brackets and not returning to + " column zero) + + call cursor(a:lnum, 1) + if searchpair('{\|(', '', '}\|)', 'nbW', + \ 's:is_string_comment(line("."), col("."))') == 0 + if searchpair('\[', '', '\]', 'nbW', + \ 's:is_string_comment(line("."), col("."))') == 0 + " Global scope, should be zero + return 0 + else + " At the module scope, inside square brackets only + "if getline(a:lnum)[0] == ']' || search('\[', '', '\]', 'nW') == a:lnum + if line =~ "^\\s*]" + " It's the closing line, dedent it + return 0 + else + return &shiftwidth + endif + endif + endif + endif + + " Fall back on cindent, which does it mostly right + return cindent(a:lnum) endfunction let &cpo = s:save_cpo unlet s:save_cpo +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/syntax/ansible.vim b/syntax/ansible.vim index 0b732101..2f2d3b83 100644 --- a/syntax/ansible.vim +++ b/syntax/ansible.vim @@ -26,7 +26,7 @@ endif syn cluster jinjaSLSBlocks add=jinjaTagBlock,jinjaVarBlock,jinjaComment " https://github.com/mitsuhiko/jinja2/blob/6b7c0c23/ext/Vim/jinja.vim syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment,@jinjaSLSBlocks -syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment,@jinjaSLSBlocks +syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,yamlComment,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment,@jinjaSLSBlocks syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,@jinjaSLSBlocks highlight link jinjaVariable Constant highlight link jinjaVarDelim Delimiter diff --git a/syntax/crystal.vim b/syntax/crystal.vim index 32629781..88395596 100644 --- a/syntax/crystal.vim +++ b/syntax/crystal.vim @@ -274,7 +274,8 @@ syn match crystalLinkAttr "]" contained containedin=crystalLinkAttrRegion displa if !exists('g:crystal_no_special_methods') syn keyword crystalAccess protected private " attr is a common variable name - syn keyword crystalAttribute getter setter property abstract + syn keyword crystalAttribute abstract + syn match crystalAttribute "\<\%(class_\)\=\%(getter\|setter\|property\)[!?]\=\s" display syn match crystalControl "\<\%(abort\|at_exit\|exit\|fork\|loop\)\>[?!]\@!" display syn keyword crystalException raise " false positive with 'include?' diff --git a/syntax/elm.vim b/syntax/elm.vim index a26fb0f6..67d737a8 100644 --- a/syntax/elm.vim +++ b/syntax/elm.vim @@ -43,7 +43,7 @@ syn match elmInt "-\?\<\d\+\>\|0[xX][0-9a-fA-F]\+\>" syn match elmFloat "\(\<\d\+\.\d\+\>\)" " Identifiers -syn match elmTopLevelDecl "^\s*[a-zA-Z][a-zA-z0-9_]*\('\)*\s\+:\s\+" contains=elmOperator +syn match elmTopLevelDecl "^\s*[a-zA-Z][a-zA-z0-9_]*\('\)*\s\+:\(\r\n\|\r\|\n\|\s\)\+" contains=elmOperator " Folding syn region elmTopLevelTypedef start="type" end="\n\(\n\n\)\@=" contains=ALL fold diff --git a/syntax/eruby.vim b/syntax/eruby.vim index 75354042..1e760988 100644 --- a/syntax/eruby.vim +++ b/syntax/eruby.vim @@ -6,7 +6,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ruby') == -1 " URL: https://github.com/vim-ruby/vim-ruby " Release Coordinator: Doug Kearns <dougkearns@gmail.com> -if exists("b:current_syntax") +if &syntax !~# '\<eruby\>' || get(b:, 'current_syntax') =~# '\<eruby\>' finish endif @@ -20,6 +20,8 @@ endif if &filetype =~ '^eruby\.' let b:eruby_subtype = matchstr(&filetype,'^eruby\.\zs\w\+') +elseif &filetype =~ '^.*\.eruby\>' + let b:eruby_subtype = matchstr(&filetype,'^.\{-\}\ze\.eruby\>') elseif !exists("b:eruby_subtype") && main_syntax == 'eruby' let s:lines = getline(1)."\n".getline(2)."\n".getline(3)."\n".getline(4)."\n".getline(5)."\n".getline("$") let b:eruby_subtype = matchstr(s:lines,'eruby_subtype=\zs\w\+') @@ -43,16 +45,20 @@ elseif !exists("b:eruby_subtype") && main_syntax == 'eruby' endif if !exists("b:eruby_nest_level") - let b:eruby_nest_level = strlen(substitute(substitute(substitute(expand("%:t"),'@','','g'),'\c\.\%(erb\|rhtml\)\>','@','g'),'[^@]','','g')) + if &syntax =~# '\<eruby\.eruby\>' + let b:eruby_nest_level = strlen(substitute(substitute(&filetype,'\C\<eruby\>','@','g'),'[^@]','','g')) + else + let b:eruby_nest_level = strlen(substitute(substitute(substitute(expand("%:t"),'@','','g'),'\c\.\%(erb\|rhtml\)\>','@','g'),'[^@]','','g')) + endif endif if !b:eruby_nest_level let b:eruby_nest_level = 1 endif -if exists("b:eruby_subtype") && b:eruby_subtype != '' && b:eruby_subtype !=? 'eruby' +if get(b:, 'eruby_subtype', '') !~# '^\%(eruby\)\=$' && &syntax =~# '^eruby\>' exe "runtime! syntax/".b:eruby_subtype.".vim" - unlet! b:current_syntax endif +unlet! b:current_syntax syn include @rubyTop syntax/ruby.vim syn cluster erubyRegions contains=erubyOneLiner,erubyBlock,erubyExpression,erubyComment @@ -67,7 +73,7 @@ exe 'syn region erubyComment matchgroup=erubyDelimiter start="<%\{1,'.b:erub hi def link erubyDelimiter PreProc hi def link erubyComment Comment -let b:current_syntax = 'eruby' +let b:current_syntax = matchstr(&syntax, '^.*\<eruby\>') if main_syntax == 'eruby' unlet main_syntax diff --git a/syntax/go.vim b/syntax/go.vim index ab5ac8af..c3c26ed6 100644 --- a/syntax/go.vim +++ b/syntax/go.vim @@ -373,6 +373,10 @@ function! s:hi() " :GoCoverage commands hi def goCoverageCovered ctermfg=green guifg=#A6E22E hi def goCoverageUncover ctermfg=red guifg=#F92672 + + " :GoDebug commands + hi GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5 guifg=Black + hi GoDebugCurrent term=reverse ctermbg=12 ctermfg=7 guibg=DarkBlue guifg=White endfunction augroup vim-go-hi diff --git a/syntax/graphql.vim b/syntax/graphql.vim index c498afa4..b59151af 100644 --- a/syntax/graphql.vim +++ b/syntax/graphql.vim @@ -39,8 +39,8 @@ syn match graphqlConstant "\<[A-Z_]\+\>" display syn keyword graphqlMetaFields __schema __type __typename -syn region graphqlFold matchgroup=graphqlBraces start="{" end=/}\(\_s\+\ze\("\|{\)\)\@!/ transparent fold contains=ALLBUT,graphqlStructure -syn region graphqlList matchgroup=graphqlBraces start="\[" end=/]\(\_s\+\ze"\)\@!/ transparent contains=ALLBUT,graphqlDirective,graphqlStructure +syn region graphqlFold matchgroup=graphqlBraces start="{" end="}" transparent fold contains=ALLBUT,graphqlStructure +syn region graphqlList matchgroup=graphqlBraces start="\[" end="]" transparent contains=ALLBUT,graphqlDirective,graphqlStructure hi def link graphqlComment Comment hi def link graphqlOperator Operator diff --git a/syntax/i3.vim b/syntax/i3.vim index cbac6a53..45bf846e 100644 --- a/syntax/i3.vim +++ b/syntax/i3.vim @@ -58,7 +58,7 @@ syn keyword i3SeparatorSymbol separator_symbol nextgroup=@i3String skipwhite " Set statement syn match i3SetVar "\$\w\+" contained nextgroup=@i3String skipwhite -syn keyword i3SetKeyword set nextgroup=i3SetVar skipwhite +syn keyword i3SetKeyword set set_from_resource nextgroup=i3SetVar skipwhite " Workspaces syn keyword i3WsKeyword workspace nextgroup=i3WsSpecialParam,@i3String skipwhite diff --git a/syntax/javascript.vim b/syntax/javascript.vim index a4ffaa39..d1480e7c 100644 --- a/syntax/javascript.vim +++ b/syntax/javascript.vim @@ -15,7 +15,7 @@ if !exists("main_syntax") endif " Dollar sign is permitted anywhere in an identifier -if v:version > 704 || v:version == 704 && has('patch1142') +if (v:version > 704 || v:version == 704 && has('patch1142')) && main_syntax == 'javascript' syntax iskeyword @,48-57,_,192-255,$ else setlocal iskeyword+=$ @@ -27,7 +27,7 @@ syntax sync fromstart syntax case match syntax match jsNoise /[:,;]/ -syntax match jsNoise /\./ skipwhite skipempty nextgroup=jsObjectProp,jsFuncCall,jsPrototype,jsTaggedTemplate +syntax match jsDot /\./ skipwhite skipempty nextgroup=jsObjectProp,jsFuncCall,jsPrototype,jsTaggedTemplate syntax match jsObjectProp contained /\<\K\k*/ syntax match jsFuncCall /\<\K\k*\ze\s*(/ syntax match jsParensError /[)}\]]/ @@ -74,12 +74,12 @@ syntax region jsRegexpString start=+\%(\%(\<return\|\<typeof\|\_[^)\]'"[:blan syntax cluster jsRegexpSpecial contains=jsSpecial,jsRegexpBoundary,jsRegexpBackRef,jsRegexpQuantifier,jsRegexpOr,jsRegexpMod " Objects +syntax match jsObjectShorthandProp contained /\<\k*\ze\s*/ skipwhite skipempty nextgroup=jsObjectSeparator syntax match jsObjectKey contained /\<\k*\ze\s*:/ contains=jsFunctionKey skipwhite skipempty nextgroup=jsObjectValue -syntax match jsObjectColon contained /:/ skipwhite skipempty syntax region jsObjectKeyString contained start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1\|$+ contains=jsSpecial,@Spell skipwhite skipempty nextgroup=jsObjectValue syntax region jsObjectKeyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsObjectValue,jsFuncArgs extend syntax match jsObjectSeparator contained /,/ -syntax region jsObjectValue contained matchgroup=jsNoise start=/:/ end=/[,}]\@=/ contains=@jsExpression extend +syntax region jsObjectValue contained matchgroup=jsObjectColon start=/:/ end=/[,}]\@=/ contains=@jsExpression extend syntax match jsObjectFuncName contained /\<\K\k*\ze\_s*(/ skipwhite skipempty nextgroup=jsFuncArgs syntax match jsFunctionKey contained /\<\K\k*\ze\s*:\s*function\>/ syntax match jsObjectMethodType contained /\<[gs]et\ze\s\+\K\k*/ skipwhite skipempty nextgroup=jsObjectFuncName @@ -151,8 +151,8 @@ syntax region jsFinallyBlock contained matchgroup=jsFinallyBraces s syntax region jsSwitchBlock contained matchgroup=jsSwitchBraces start=/{/ end=/}/ contains=@jsAll,jsBlock,jsSwitchCase extend fold syntax region jsRepeatBlock contained matchgroup=jsRepeatBraces start=/{/ end=/}/ contains=@jsAll,jsBlock extend fold syntax region jsDestructuringBlock contained matchgroup=jsDestructuringBraces start=/{/ end=/}/ contains=jsDestructuringProperty,jsDestructuringAssignment,jsDestructuringNoise,jsDestructuringPropertyComputed,jsSpreadExpression,jsComment extend fold -syntax region jsDestructuringArray contained matchgroup=jsDestructuringBraces start=/\[/ end=/\]/ contains=jsDestructuringPropertyValue,jsNoise,jsDestructuringProperty,jsSpreadExpression,jsDestructuringBlock,jsComment extend fold -syntax region jsObject contained matchgroup=jsObjectBraces start=/{/ end=/}/ contains=jsObjectKey,jsObjectKeyString,jsObjectKeyComputed,jsObjectSeparator,jsObjectFuncName,jsObjectMethodType,jsGenerator,jsComment,jsObjectStringKey,jsSpreadExpression,jsDecorator,jsAsyncKeyword extend fold +syntax region jsDestructuringArray contained matchgroup=jsDestructuringBraces start=/\[/ end=/\]/ contains=jsDestructuringPropertyValue,jsNoise,jsDestructuringProperty,jsSpreadExpression,jsDestructuringBlock,jsDestructuringArray,jsComment extend fold +syntax region jsObject contained matchgroup=jsObjectBraces start=/{/ end=/}/ contains=jsObjectKey,jsObjectKeyString,jsObjectKeyComputed,jsObjectShorthandProp,jsObjectSeparator,jsObjectFuncName,jsObjectMethodType,jsGenerator,jsComment,jsObjectStringKey,jsSpreadExpression,jsDecorator,jsAsyncKeyword extend fold syntax region jsBlock matchgroup=jsBraces start=/{/ end=/}/ contains=@jsAll,jsSpreadExpression extend fold syntax region jsModuleGroup contained matchgroup=jsModuleBraces start=/{/ end=/}/ contains=jsModuleKeyword,jsModuleComma,jsModuleAs,jsComment,jsFlowTypeKeyword skipwhite skipempty nextgroup=jsFrom fold syntax region jsSpreadExpression contained matchgroup=jsSpreadOperator start=/\.\.\./ end=/[,}\]]\@=/ contains=@jsExpression @@ -232,7 +232,7 @@ if exists("javascript_plugin_flow") runtime extras/flow.vim endif -syntax cluster jsExpression contains=jsBracket,jsParen,jsObject,jsTernaryIf,jsTaggedTemplate,jsTemplateString,jsString,jsRegexpString,jsNumber,jsFloat,jsOperator,jsOperatorKeyword,jsBooleanTrue,jsBooleanFalse,jsNull,jsFunction,jsArrowFunction,jsGlobalObjects,jsExceptions,jsFutureKeys,jsDomErrNo,jsDomNodeConsts,jsHtmlEvents,jsFuncCall,jsUndefined,jsNan,jsPrototype,jsBuiltins,jsNoise,jsClassDefinition,jsArrowFunction,jsArrowFuncArgs,jsParensError,jsComment,jsArguments,jsThis,jsSuper,jsDo,jsForAwait,jsAsyncKeyword,jsStatement +syntax cluster jsExpression contains=jsBracket,jsParen,jsObject,jsTernaryIf,jsTaggedTemplate,jsTemplateString,jsString,jsRegexpString,jsNumber,jsFloat,jsOperator,jsOperatorKeyword,jsBooleanTrue,jsBooleanFalse,jsNull,jsFunction,jsArrowFunction,jsGlobalObjects,jsExceptions,jsFutureKeys,jsDomErrNo,jsDomNodeConsts,jsHtmlEvents,jsFuncCall,jsUndefined,jsNan,jsPrototype,jsBuiltins,jsNoise,jsClassDefinition,jsArrowFunction,jsArrowFuncArgs,jsParensError,jsComment,jsArguments,jsThis,jsSuper,jsDo,jsForAwait,jsAsyncKeyword,jsStatement,jsDot syntax cluster jsAll contains=@jsExpression,jsStorageClass,jsConditional,jsRepeat,jsReturn,jsException,jsTry,jsNoise,jsBlockLabel " Define the default highlighting. @@ -287,6 +287,7 @@ if version >= 508 || !exists("did_javascript_syn_inits") HiLink jsGenerator jsFunction HiLink jsArrowFuncArgs jsFuncArgs HiLink jsFuncName Function + HiLink jsFuncCall Function HiLink jsClassFuncName jsFuncName HiLink jsObjectFuncName Function HiLink jsArguments Special @@ -309,6 +310,7 @@ if version >= 508 || !exists("did_javascript_syn_inits") HiLink jsBooleanFalse Boolean HiLink jsObjectColon jsNoise HiLink jsNoise Noise + HiLink jsDot Noise HiLink jsBrackets Noise HiLink jsParens Noise HiLink jsBraces Noise @@ -343,6 +345,7 @@ if version >= 508 || !exists("did_javascript_syn_inits") HiLink jsParensDecorator jsParens HiLink jsFuncArgOperator jsFuncArgs HiLink jsClassProperty jsObjectKey + HiLink jsObjectShorthandProp jsObjectKey HiLink jsSpreadOperator Operator HiLink jsRestOperator Operator HiLink jsRestExpression jsFuncArgs diff --git a/syntax/jinja2.vim b/syntax/jinja2.vim index 55d9fbfd..402bad56 100644 --- a/syntax/jinja2.vim +++ b/syntax/jinja2.vim @@ -50,7 +50,7 @@ syn region jinjaNested matchgroup=jinjaOperator start="\[" end="\]" transparent syn region jinjaNested matchgroup=jinjaOperator start="{" end="}" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment -syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment +syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,yamlComment,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment " Jinja template 'raw' tag syn region jinjaRaw matchgroup=jinjaRawDelim start="{%\s*raw\s*%}" end="{%\s*endraw\s*%}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,jinjaComment diff --git a/syntax/julia.vim b/syntax/julia.vim index 3e5c1433..8d7d7b4d 100644 --- a/syntax/julia.vim +++ b/syntax/julia.vim @@ -84,7 +84,7 @@ let s:binop_chars_extra = "\\U214B\\U2190-\\U2194\\U219A\\U219B\\U21A0\\U21A3\\U let s:idregex = '\%([^' . s:nonidS_chars . '0-9!?' . s:uniop_chars . s:binop_chars . '][^' . s:nonidS_chars . s:uniop_chars . s:binop_chars . s:binop_chars_extra . ']*\|\<?\>\)' let s:operators = '\%(' . '\.\%([-+*/^÷%|&!]\|//\|\\\|<<\|>>>\?\)\?=' . - \ '\|' . '[:$<>]=\|||\|&&\||>\|<|\|<:\|:>\|::\|<<\|>>>\?\|//\|[-=]>\|\.\{3\}' . + \ '\|' . '[:$<>]=\|||\|&&\||>\|<|\|<:\|>:\|::\|<<\|>>>\?\|//\|[-=]>\|\.\{3\}' . \ '\|' . '[' . s:uniop_chars . '!$]' . \ '\|' . '\.\?[' . s:binop_chars . s:binop_chars_extra . ']' . \ '\)' diff --git a/syntax/nginx.vim b/syntax/nginx.vim index 944b36ab..10d69b26 100644 --- a/syntax/nginx.vim +++ b/syntax/nginx.vim @@ -558,6 +558,7 @@ syn keyword ngxDirective ssl_protocols nextgroup=ngxSSLProtocol,ngxSSLProtocolDe syn match ngxSSLProtocol 'TLSv1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite syn match ngxSSLProtocol 'TLSv1\.1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite syn match ngxSSLProtocol 'TLSv1\.2' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite +syn match ngxSSLProtocol 'TLSv1\.3' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite " Do not enable highlighting of insecure protocols if sslecure is loaded if !exists('g:loaded_sslsecure') diff --git a/syntax/rust.vim b/syntax/rust.vim index 81abf942..90e5b6b6 100644 --- a/syntax/rust.vim +++ b/syntax/rust.vim @@ -9,9 +9,9 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 " For bugs, patches and license go to https://github.com/rust-lang/rust.vim if version < 600 - syntax clear + syntax clear elseif exists("b:current_syntax") - finish + finish endif " Syntax definitions {{{1 @@ -29,6 +29,7 @@ syn match rustPanic "\<panic\(\w\)*!" contained syn keyword rustKeyword break syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty syn keyword rustKeyword continue +syn keyword rustKeyword crate syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty syn keyword rustKeyword in impl let @@ -45,8 +46,6 @@ syn keyword rustKeyword mod trait nextgroup=rustIdentifier skipwhite skipe syn keyword rustStorage move mut ref static const syn match rustDefault /\<default\ze\_s\+\(impl\|fn\|type\|const\)\>/ -syn keyword rustInvalidBareKeyword crate - syn keyword rustPubScopeCrate crate contained syn match rustPubScopeDelim /[()]/ contained syn match rustPubScope /([^()]*)/ contained contains=rustPubScopeDelim,rustPubScopeCrate,rustSuper,rustModPath,rustModPathSep,rustSelf transparent @@ -155,6 +154,16 @@ syn region rustDerive start="derive(" end=")" contained contains=rustDer " Some are deprecated (Encodable, Decodable) or to be removed after a new snapshot (Show). syn keyword rustDeriveTrait contained Clone Hash RustcEncodable RustcDecodable Encodable Decodable PartialEq Eq PartialOrd Ord Rand Show Debug Default FromPrimitive Send Sync Copy +" dyn keyword: It's only a keyword when used inside a type expression, so +" we make effort here to highlight it only when Rust identifiers follow it +" (not minding the case of pre-2018 Rust where a path starting with :: can +" follow). +" +" This is so that uses of dyn variable names such as in 'let &dyn = &2' +" and 'let dyn = 2' will not get highlighted as a keyword. +syn match rustKeyword "\<dyn\ze\_s\+\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)" contains=rustDynKeyword +syn keyword rustDynKeyword dyn contained + " Number literals syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\=" syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\=" @@ -174,7 +183,7 @@ syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE " For the benefit of delimitMate syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u{\%(\x_*\)\{1,6}}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime -syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate +syn region rustGenericRegion display start=/<\%('\|[^[:cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime "rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting @@ -191,11 +200,17 @@ syn region rustCommentLine star syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell syn region rustCommentLineDocError start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell contained syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell -syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell +syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,rustCommentBlockDocRustCode,@Spell syn region rustCommentBlockDocError matchgroup=rustCommentBlockDocError start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent syn region rustCommentBlockDocNestError matchgroup=rustCommentBlockDocError start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained transparent + +if exists("b:current_syntax_embed") +syn match rustCommentLine "^//" +syn match rustCommentLineDoc "^//\%(//\@!\|!\)" +endif + " FIXME: this is a really ugly and not fully correct implementation. Most " importantly, a case like ``/* */*`` should have the final ``*`` not being in " a comment, but in practice at present it leaves comments open two levels @@ -215,6 +230,32 @@ syn keyword rustTodo contained TODO FIXME XXX NB NOTE " FIXME: use the AST to make really good folding syn region rustFoldBraces start="{" end="}" transparent fold +if !exists("b:current_syntax_embed") + let b:current_syntax_embed = 1 + syntax include @RustCodeInComment <sfile>:p:h/rust.vim + unlet b:current_syntax_embed + + " We borrow the rules from rust’s src/librustdoc/html/markdown.rs, so that + " we only highlight as Rust what it would perceive as Rust (almost; it’s + " possible to trick it if you try hard, and indented code blocks aren’t + " supported because Markdown is a menace to parse and only mad dogs and + " Englishmen would try to handle that case correctly in this syntax file). + syn region rustCommentLinesDocRustCode matchgroup=rustCommentDocCodeFence start='^\z(\s*//[!/]\s*```\)[^A-Za-z0-9_-]*\%(\%(should_panic\|no_run\|ignore\|allow_fail\|rust\|test_harness\|compile_fail\|E\d\{4}\)\%([^A-Za-z0-9_-]\+\|$\)\)*$' end='^\z1$' keepend contains=@RustCodeInComment + syn region rustCommentBlockDocRustCode matchgroup=rustCommentDocCodeFence start='^\z(\%(\s*\*\)\?\s*```\)[^A-Za-z0-9_-]*\%(\%(should_panic\|no_run\|ignore\|allow_fail\|rust\|test_harness\|compile_fail\|E\d\{4}\)\%([^A-Za-z0-9_-]\+\|$\)\)*$' end='^\z1$' keepend contains=@RustCodeInComment,rustCommentBlockDocStar + " Strictly, this may or may not be correct; this code, for example, would + " mishighlight: + " + " /** + " ```rust + " println!("{}", 1 + " * 1); + " ``` + " */ + " + " … but I don’t care. Balance of probability, and all that. + syn match rustCommentBlockDocStar /^\s*\*\s\?/ contained +endif + " Default highlighting {{{1 hi def link rustDecNumber rustNumber hi def link rustHexNumber rustNumber @@ -246,6 +287,7 @@ hi def link rustFloat Float hi def link rustArrowCharacter rustOperator hi def link rustOperator Operator hi def link rustKeyword Keyword +hi def link rustDynKeyword rustKeyword hi def link rustTypedef Keyword " More precise is Typedef, but it doesn't feel right for Rust hi def link rustStructure Keyword " More precise is Structure hi def link rustUnion rustStructure @@ -269,7 +311,9 @@ hi def link rustCommentLineDoc SpecialComment hi def link rustCommentLineDocError Error hi def link rustCommentBlock rustCommentLine hi def link rustCommentBlockDoc rustCommentLineDoc +hi def link rustCommentBlockDocStar rustCommentBlockDoc hi def link rustCommentBlockDocError Error +hi def link rustCommentDocCodeFence rustCommentLineDoc hi def link rustAssert PreCondit hi def link rustPanic PreCondit hi def link rustMacro Macro @@ -282,7 +326,6 @@ hi def link rustStorage StorageClass hi def link rustObsoleteStorage Error hi def link rustLifetime Special hi def link rustLabel Label -hi def link rustInvalidBareKeyword Error hi def link rustExternCrate rustKeyword hi def link rustObsoleteExternMod Error hi def link rustBoxPlacementParens Delimiter @@ -300,4 +343,6 @@ syn sync maxlines=500 let b:current_syntax = "rust" +" vim: set et sw=4 sts=4 ts=8: + endif diff --git a/syntax/toml.vim b/syntax/toml.vim index 7a5b44f2..1decc5fb 100644 --- a/syntax/toml.vim +++ b/syntax/toml.vim @@ -28,6 +28,7 @@ syn region tomlString start=/'''/ end=/'''/ hi def link tomlString String syn match tomlInteger /\<[+-]\=[0-9]\(_\=\d\)*\>/ display +syn match tomlInteger /\<[+-]\=\(inf\|nan\)\>/ display hi def link tomlInteger Number syn match tomlFloat /\<[+-]\=[0-9]\(_\=\d\)*\.\d\+\>/ display @@ -43,16 +44,19 @@ syn match tomlDate /\d\{2\}:\d\{2\}:\d\{2\}\%(\.\d\+\)\?/ display syn match tomlDate /\d\{4\}-\d\{2\}-\d\{2\}[T ]\d\{2\}:\d\{2\}:\d\{2\}\%(\.\d\+\)\?\%(Z\|[+-]\d\{2\}:\d\{2\}\)\?/ display hi def link tomlDate Constant -syn region tomlKeyDq oneline start=/"/ end=/"/ contains=tomlEscape contained +syn match tomlKey /\v(^|[{,])\s*\zs[[:alnum:]_-]+\ze\s*\=/ display +hi def link tomlKey Identifier + +syn region tomlKeyDq oneline start=/\v(^|[{,])\s*\zs"/ end=/"\ze\s*=/ contains=tomlEscape hi def link tomlKeyDq Identifier -syn region tomlKeySq oneline start=/'/ end=/'/ contained +syn region tomlKeySq oneline start=/\v(^|[{,])\s*\zs'/ end=/'\ze\s*=/ hi def link tomlKeySq Identifier -syn region tomlTable oneline start=/^\s*\[[^\[]/ end=/\]/ contains=tomlKeyDq,tomlKeySq +syn region tomlTable oneline start=/^\s*\[[^\[]/ end=/\]/ contains=tomlKey,tomlKeyDq,tomlKeySq hi def link tomlTable Identifier -syn region tomlTableArray oneline start=/^\s*\[\[/ end=/\]\]/ contains=tomlKeyDq,tomlKeySq +syn region tomlTableArray oneline start=/^\s*\[\[/ end=/\]\]/ contains=tomlKey,tomlKeyDq,tomlKeySq hi def link tomlTableArray Identifier syn keyword tomlTodo TODO FIXME XXX BUG contained diff --git a/syntax/vifm.vim b/syntax/vifm.vim index 8843d1ac..1ae9da14 100644 --- a/syntax/vifm.vim +++ b/syntax/vifm.vim @@ -2,7 +2,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vifm') == -1 " vifm syntax file " Maintainer: xaizek <xaizek@posteo.net> -" Last Change: April 30, 2018 +" Last Change: July 4, 2018 " Inspired By: Vim syntax file by Dr. Charles E. Campbell, Jr. if exists('b:current_syntax') @@ -76,8 +76,9 @@ syntax keyword vifmHiGroups contained WildMenu Border Win CmdLine CurrLine \ OtherLine Directory Link Socket Device Executable Selected BrokenLink \ TopLine TopLineSel StatusLine JobLine SuggestBox Fifo ErrorMsg CmpMismatch \ AuxWin TabLine TabLineSel -syntax keyword vifmHiStyles contained bold underline reverse inverse standout - \ none + \ User1 User2 User3 User4 User5 User6 User7 User8 User9 +syntax keyword vifmHiStyles contained + \ bold underline reverse inverse standout italic none syntax keyword vifmHiColors contained black red green yellow blue magenta cyan \ white default lightblack lightred lightgreen lightyellow lightblue \ lightmagenta lightcyan lightwhite Grey0 NavyBlue DarkBlue Blue3 Blue3_2 @@ -233,7 +234,7 @@ syntax region vifmExecute start='!' skip='\(\n\s*\\\)\|\(\n\s*".*$\)' end='$' syntax region vifmMapArgs start='\ze\S\+' \ end='\ze.' skip='\(\n\s*\\\)\|\(\n\s*".*$\)' \ contained - \ nextgroup=vifmMapLhs + \ nextgroup=vifmMapArgList syntax region vifmCMapArgs start='\S\+' \ end='\n\s*\\' skip='\(\n\s*\\\)\|\(\n\s*".*$\)' \ contained @@ -381,6 +382,9 @@ syntax region vifmArgument contained start=+'+ skip=+\\\\\|\\'\|''+ end=+'+ syntax match vifmEnvVar contained /\$[0-9a-zA-Z_]\+/ syntax match vifmNumber contained /\d\+/ +" Optional map arguments right after command name +syntax match vifmMapArgList '\(<silent>\s*\)*' contained nextgroup=vifmMapLhs + " Ange-bracket notation syntax case ignore syntax match vifmNotation '<\(esc\|cr\|space\|del\|nop\|\(s-\)\?tab\|home\|end\|left\|right\|up\|down\|bs\|delete\|insert\|pageup\|pagedown\|\([acms]-\)\?f\d\{1,2\}\|c-s-[a-z[\]^_]\|s-c-[a-z[\]^_]\|c-[a-z[\]^_]\|[am]-c-[a-z]\|c-[am]-[a-z]\|[am]-[a-z]\)>' @@ -391,7 +395,7 @@ syntax region vifmComment contained contains=@Spell start='^\(\s\|:\)*"' end='$' " Comment at the end of a line syntax match vifmInlineComment contained contains=@Spell '\s"[^"]*$' " This prevents highlighting non-first line of multi-line command -syntax match vifmNotComment contained '\s"[^"]*\(\(\n\s*\(\\\|"\)\)\@!\|$\)' +syntax match vifmNotComment contained '\s"[^"]*\(\n\s*\(\\\|"\)\)\@=' " Empty line syntax match vifmEmpty /^\s*$/ @@ -435,6 +439,7 @@ highlight link vifmHiStyles PreProc highlight link vifmHiColors Special highlight link vifmOption PreProc highlight link vifmNotation Special +highlight link vifmMapArgList Special highlight link vifmString String highlight link vifmStringInExpr String highlight link vifmEnvVar PreProc |