summaryrefslogtreecommitdiffstats
path: root/autoload/rust
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2018-10-08 19:00:59 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2018-10-08 19:00:59 +0200
commitfd74d8b2b170b540680a9bbf6c64990f8ebafd08 (patch)
treeb1fdef6203a78a21053d1b8e0666ab7a38c36df2 /autoload/rust
parent055f7710b65dfa2df52fc0b5be2486ae36ac5751 (diff)
downloadvim-polyglot-3.3.3.tar.gz
vim-polyglot-3.3.3.zip
Updatev3.3.3
Diffstat (limited to '')
-rw-r--r--autoload/rust.vim91
-rw-r--r--autoload/rust/debugging.vim1
-rw-r--r--autoload/rust/delimitmate.vim48
-rw-r--r--autoload/rustfmt.vim142
4 files changed, 226 insertions, 56 deletions
diff --git a/autoload/rust.vim b/autoload/rust.vim
index 7e766da1..77c38b7c 100644
--- a/autoload/rust.vim
+++ b/autoload/rust.vim
@@ -86,7 +86,7 @@ function! s:Run(dict, rustc_args, args)
let pwd = a:dict.istemp ? a:dict.tmpdir : ''
let output = s:system(pwd, shellescape(rustc) . " " . join(map(rustc_args, 'shellescape(v:val)')))
- if output != ''
+ if output !=# ''
echohl WarningMsg
echo output
echohl None
@@ -153,7 +153,7 @@ function! s:Expand(dict, pretty, args)
endfunction
function! rust#CompleteExpand(lead, line, pos)
- if a:line[: a:pos-1] =~ '^RustExpand!\s*\S*$'
+ 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)
@@ -182,7 +182,7 @@ function! s:Emit(dict, type, args)
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 != ''
+ if output !=# ''
echohl WarningMsg
echo output
echohl None
@@ -192,10 +192,10 @@ function! s:Emit(dict, type, args)
exe 'silent keepalt read' fnameescape(output_path)
1
d
- if a:type == "llvm-ir"
+ if a:type ==# "llvm-ir"
setl filetype=llvm
let extension = 'll'
- elseif a:type == "asm"
+ elseif a:type ==# "asm"
setl filetype=asm
let extension = 's'
endif
@@ -261,8 +261,8 @@ function! s:WithPath(func, ...)
let dict.tmpdir_relpath = filename
let dict.path = dict.tmpdir.'/'.filename
- let saved.mod = &mod
- set nomod
+ let saved.mod = &modified
+ set nomodified
silent exe 'keepalt write! ' . fnameescape(dict.path)
if pathisempty
@@ -343,7 +343,7 @@ function! s:ShellTokenize(text)
endif
let l:state = 3
elseif l:state == 5 " single-quoted
- if l:c == "'"
+ if l:c ==# "'"
let l:state = 1
else
let l:current .= l:c
@@ -361,7 +361,7 @@ function! s:RmDir(path)
if empty(a:path)
echoerr 'Attempted to delete empty path'
return 0
- elseif a:path == '/' || a:path == $HOME
+ elseif a:path ==# '/' || a:path ==# $HOME
echoerr 'Attempted to delete protected path: ' . a:path
return 0
endif
@@ -414,22 +414,83 @@ function! rust#Play(count, line1, line2, ...) abort
call setreg('"', save_regcont, save_regtype)
endif
- let body = l:rust_playpen_url."?code=".webapi#http#encodeURI(content)
+ let url = 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
+ if strlen(url) > 5000
+ echohl ErrorMsg | echomsg 'Buffer too large, max 5000 encoded characters ('.strlen(url).')' | echohl None
return
endif
- let payload = "format=simple&url=".webapi#http#encodeURI(body)
+ let payload = "format=simple&url=".webapi#http#encodeURI(url)
let res = webapi#http#post(l:rust_shortener_url.'create.php', payload, {})
- let url = res.content
+ if res.status[0] ==# '2'
+ let url = res.content
+ endif
+ let footer = ''
if exists('g:rust_clip_command')
call system(g:rust_clip_command, url)
+ if !v:shell_error
+ let footer = ' (copied to clipboard)'
+ endif
endif
+ redraw | echomsg 'Done: '.url.footer
+endfunction
- redraw | echomsg 'Done: '.url
+" Run a test under the cursor or all tests {{{1
+
+" Finds a test function name under the cursor. Returns empty string when a
+" test function is not found.
+function! s:SearchTestFunctionNameUnderCursor() abort
+ let cursor_line = line('.')
+
+ " Find #[test] attribute
+ if search('#\[test]', 'bcW') is 0
+ return ''
+ endif
+
+ " Move to an opening brace of the test function
+ let test_func_line = search('^\s*fn\s\+\h\w*\s*(.\+{$', 'eW')
+ if test_func_line is 0
+ return ''
+ endif
+
+ " Search the end of test function (closing brace) to ensure that the
+ " cursor position is within function definition
+ normal! %
+ if line('.') < cursor_line
+ return ''
+ endif
+
+ return matchstr(getline(test_func_line), '^\s*fn\s\+\zs\h\w*')
+endfunction
+
+function! rust#Test(all, options) abort
+ let pwd = expand('%:p:h')
+ if findfile('Cargo.toml', pwd . ';') ==# ''
+ return rust#Run(1, '--test ' . a:options)
+ endif
+
+ let pwd = shellescape(pwd)
+
+ if a:all
+ execute '!cd ' . pwd . ' && cargo test ' . a:options
+ return
+ endif
+
+ let saved = getpos('.')
+ try
+ let func_name = s:SearchTestFunctionNameUnderCursor()
+ if func_name ==# ''
+ echohl ErrorMsg
+ echo 'No test function was found under the cursor. Please add ! to command if you want to run all tests'
+ echohl None
+ return
+ endif
+ execute '!cd ' . pwd . ' && cargo test ' . func_name . ' ' . a:options
+ finally
+ call setpos('.', saved)
+ endtry
endfunction
" }}}1
diff --git a/autoload/rust/debugging.vim b/autoload/rust/debugging.vim
index 352556d7..ff88e00c 100644
--- a/autoload/rust/debugging.vim
+++ b/autoload/rust/debugging.vim
@@ -18,6 +18,7 @@ let s:global_variable_list = [
\ 'rust_last_rustc_args',
\ 'rust_original_delimitMate_excluded_regions',
\ 'rust_playpen_url',
+ \ 'rust_prev_delimitMate_quotes',
\ 'rust_recent_nearest_cargo_tol',
\ 'rust_recent_root_cargo_toml',
\ 'rust_recommended_style',
diff --git a/autoload/rust/delimitmate.vim b/autoload/rust/delimitmate.vim
new file mode 100644
index 00000000..e99cc87d
--- /dev/null
+++ b/autoload/rust/delimitmate.vim
@@ -0,0 +1,48 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1
+
+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.
+function! rust#delimitmate#onMap() abort
+ if &filetype !=# 'rust'
+ return
+ endif
+
+ if get(b:, "delimitMate_quotes")
+ let b:rust_prev_delimitMate_quotes = b:delimitMate_quotes
+ endif
+ let b:delimitMate_quotes = "\" `"
+
+ if match(delimitMate#Get("excluded_regions"),
+ \ s:delimitMate_extra_excluded_regions) == -1
+ call delimitMate#Set("excluded_regions",
+ \delimitMate#Get("excluded_regions").s:delimitMate_extra_excluded_regions)
+ endif
+endfunction
+
+" 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).
+function! rust#delimitmate#onUnmap() abort
+ if &filetype !=# 'rust'
+ return
+ endif
+
+ if get(b:, "rust_prev_delimitMate_quotes")
+ let b:delimitMate_quotes = b:rust_prev_delimitMate_quotes
+ endif
+
+ call delimitMate#Set("excluded_regions", substitute(
+ \ delimitMate#Get("excluded_regions"),
+ \ '\C\V' . s:delimitMate_extra_excluded_regions,
+ \ '', 'g'))
+endfunction
+
+" vim: set et sw=4 sts=4 ts=8:
+
+
+endif
diff --git a/autoload/rustfmt.vim b/autoload/rustfmt.vim
index c0335173..916736c0 100644
--- a/autoload/rustfmt.vim
+++ b/autoload/rustfmt.vim
@@ -63,6 +63,20 @@ function! s:RustfmtWriteMode()
endif
endfunction
+function! s:RustfmtConfig()
+ let l:rustfmt_toml = findfile('rustfmt.toml', expand('%:p:h') . ';')
+ if l:rustfmt_toml !=# ''
+ return '--config-path '.l:rustfmt_toml
+ endif
+
+ let l:_rustfmt_toml = findfile('.rustfmt.toml', expand('%:p:h') . ';')
+ if l:_rustfmt_toml !=# ''
+ return '--config-path '.l:_rustfmt_toml
+ endif
+
+ return ''
+endfunction
+
function! s:RustfmtCommandRange(filename, line1, line2)
if g:rustfmt_file_lines == 0
echo "--file-lines is not supported in the installed `rustfmt` executable"
@@ -71,6 +85,7 @@ function! s:RustfmtCommandRange(filename, line1, line2)
let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]}
let l:write_mode = s:RustfmtWriteMode()
+ let l:rustfmt_config = s:RustfmtConfig()
" FIXME: When --file-lines gets to be stable, enhance this version range checking
" accordingly.
@@ -78,34 +93,73 @@ function! s:RustfmtCommandRange(filename, line1, line2)
\ (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))
+ let l:cmd = printf("%s %s %s %s %s --file-lines '[%s]' %s", g:rustfmt_command,
+ \ l:write_mode, g:rustfmt_options,
+ \ l:unstable_features, l:rustfmt_config,
+ \ json_encode(l:arg), shellescape(a:filename))
return l:cmd
endfunction
-function! s:RustfmtCommand(filename)
- let l:write_mode = s:RustfmtWriteMode()
- return g:rustfmt_command . " ". l:write_mode . " " . g:rustfmt_options . " " . shellescape(a:filename)
+function! s:RustfmtCommand()
+ if g:rustfmt_emit_files
+ let l:write_mode = "--emit=stdout"
+ else
+ let l:write_mode = "--write-mode=display"
+ endif
+ " rustfmt will pick on the right config on its own due to the
+ " current directory change.
+ return g:rustfmt_command . " ". l:write_mode . " " . g:rustfmt_options
+endfunction
+
+function! s:DeleteLines(start, end) abort
+ silent! execute a:start . ',' . a:end . 'delete _'
endfunction
function! s:RunRustfmt(command, tmpname, fail_silently)
mkview!
- if exists("*systemlist")
- let out = systemlist(a:command)
+ let l:stderr_tmpname = tempname()
+ let l:command = a:command . ' 2> ' . l:stderr_tmpname
+
+ if a:tmpname ==# ''
+ " Rustfmt in stdin/stdout mode
+
+ " chdir to the directory of the file
+ let l:has_lcd = haslocaldir()
+ let l:prev_cd = getcwd()
+ execute 'lchdir! '.expand('%:h')
+
+ let l:buffer = getline(1, '$')
+ if exists("*systemlist")
+ silent let out = systemlist(l:command, l:buffer)
+ else
+ silent let out = split(system(l:command, l:buffer), '\r\?\n')
+ endif
else
- let out = split(system(a:command), '\r\?\n')
+ if exists("*systemlist")
+ silent let out = systemlist(l:command)
+ else
+ silent let out = split(system(l:command), '\r\?\n')
+ endif
endif
- if v:shell_error == 0 || v:shell_error == 3
+ let l:stderr = readfile(l:stderr_tmpname)
+
+ call delete(l:stderr_tmpname)
+
+ if v:shell_error == 0
" 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 _
+ if a:tmpname ==# ''
+ let l:content = l:out
+ else
+ " take the tmpfile's content, this is better than rename
+ " because it preserves file modes.
+ let l:content = readfile(a:tmpname)
+ endif
+
+ call s:DeleteLines(len(l:content), line('$'))
call setline(1, l:content)
" only clear location list if it was previously filled to prevent
@@ -117,61 +171,69 @@ function! s:RunRustfmt(command, tmpname, fail_silently)
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 l:errors = []
- let prev_line = ""
- for line in out
+ let l:prev_line = ""
+ for l:line in l:stderr
" error: expected one of `;` or `as`, found `extern`
" --> src/main.rs:2:1
- let tokens = matchlist(line, '^\s-->\s\(.\{-}\):\(\d\+\):\(\d\+\)$')
+ let tokens = matchlist(l:line, '^\s\+-->\s\(.\{-}\):\(\d\+\):\(\d\+\)$')
if !empty(tokens)
- call add(errors, {"filename": @%,
+ call add(l:errors, {"filename": @%,
\"lnum": tokens[2],
\"col": tokens[3],
- \"text": prev_line})
+ \"text": l:prev_line})
endif
- let prev_line = line
+ let l:prev_line = l:line
endfor
- if empty(errors)
- % | " Couldn't detect rustfmt error format, output errors
- endif
-
- if !empty(errors)
- call setloclist(0, errors, 'r')
+ if !empty(l:errors)
+ call setloclist(0, l:errors, 'r')
echohl Error | echomsg "rustfmt returned error" | echohl None
+ else
+ echo "rust.vim: was not able to parse rustfmt messages. Here is the raw output:"
+ echo "\n"
+ for l:line in l:stderr
+ echo l:line
+ endfor
endif
let s:got_fmt_error = 1
lwindow
endif
- call delete(a:tmpname)
+ " Restore the current directory if needed
+ if a:tmpname ==# ''
+ if l:has_lcd
+ execute 'lchdir! '.l:prev_cd
+ else
+ execute 'chdir! '.l:prev_cd
+ endif
+ endif
silent! loadview
endfunction
-function! s:rustfmtSaveToTmp()
+function! rustfmt#FormatRange(line1, line2)
let l:tmpname = tempname()
call writefile(getline(1, '$'), l:tmpname)
- return l:tmpname
-endfunction
-
-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)
+ call delete(l:tmpname)
endfunction
function! rustfmt#Format()
- let l:tmpname = s:rustfmtSaveToTmp()
- let command = s:RustfmtCommand(l:tmpname)
- call s:RunRustfmt(command, l:tmpname, 0)
+ call s:RunRustfmt(s:RustfmtCommand(), '', 0)
+endfunction
+
+function! rustfmt#Cmd()
+ " Mainly for debugging
+ return s:RustfmtCommand()
endfunction
function! rustfmt#PreWrite()
if rust#GetConfigVar('rustfmt_autosave_if_config_present', 0)
- if findfile('rustfmt.toml', '.;') !=# ''
+ if findfile('rustfmt.toml', '.;') !=# '' || findfile('.rustfmt.toml', '.;') !=# ''
let b:rustfmt_autosave = 1
let b:rustfmt_autosave_because_of_config = 1
endif
@@ -181,9 +243,7 @@ function! rustfmt#PreWrite()
return
endif
- let l:tmpname = s:rustfmtSaveToTmp()
- let command = s:RustfmtCommand(l:tmpname)
- call s:RunRustfmt(command, l:tmpname, 1)
+ call s:RunRustfmt(s:RustfmtCommand(), '', 1)
endfunction