diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2015-12-06 11:31:38 +0100 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2015-12-06 11:31:38 +0100 | 
| commit | 303b3f1b434f26f936c241789c84dca6e2f50df2 (patch) | |
| tree | 1507706b422e3ec29c0e5f30bcf14681e04ab374 /autoload | |
| parent | bf849731731a7da008c891476b878735e8280bdc (diff) | |
| download | vim-polyglot-303b3f1b434f26f936c241789c84dca6e2f50df2.tar.gz vim-polyglot-303b3f1b434f26f936c241789c84dca6e2f50df2.zip | |
Update all bundles
Diffstat (limited to 'autoload')
| -rw-r--r-- | autoload/rust.vim | 319 | ||||
| -rw-r--r-- | autoload/rustfmt.vim | 83 | 
2 files changed, 337 insertions, 65 deletions
| diff --git a/autoload/rust.vim b/autoload/rust.vim index e6f7b053..12591399 100644 --- a/autoload/rust.vim +++ b/autoload/rust.vim @@ -36,72 +36,74 @@ endfunction  " Run {{{1  function! rust#Run(bang, args) +	let args = s:ShellTokenize(a:args)  	if a:bang -		let idx = index(a:args, '--') +		let idx = index(l:args, '--')  		if idx != -1 -			let rustc_args = idx == 0 ? [] : a:args[:idx-1] -			let args = a:args[idx+1:] +			let rustc_args = idx == 0 ? [] : l:args[:idx-1] +			let args = l:args[idx+1:]  		else -			let rustc_args = a:args +			let rustc_args = l:args  			let args = []  		endif  	else  		let rustc_args = [] -		let args = a:args  	endif -	let b:rust_last_rustc_args = rustc_args -	let b:rust_last_args = args +	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(path, rustc_args, args) -	try -		let exepath = tempname() -		if has('win32') -			let exepath .= '.exe' -		endif +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 rustc_args = [a:path, '-o', exepath] + a:rustc_args +	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 rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" -		let output = system(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 -	finally -		if exists("exepath") -			silent! call delete(exepath) -		endif -	endtry +	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) -	if a:bang && !empty(a:args) -		let pretty = a:args[0] -		let args = a:args[1:] +	let args = s:ShellTokenize(a:args) +	if a:bang && !empty(l:args) +		let pretty = remove(l:args, 0)  	else  		let pretty = "expanded" -		let args = a:args  	endif  	call s:WithPath(function("s:Expand"), pretty, args)  endfunction -function! s:Expand(path, pretty, args) +function! s:Expand(dict, pretty, args)  	try  		let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" -		let args = [a:path, '--pretty', a:pretty] + a:args -		let output = system(shellescape(rustc) . " " . join(map(args, "shellescape(v:val)"))) +		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 @@ -115,6 +117,20 @@ function! s:Expand(path, pretty, args)  			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 @@ -122,7 +138,7 @@ 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="] +		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 @@ -135,72 +151,120 @@ endfunction  " Emit {{{1  function! rust#Emit(type, args) -	call s:WithPath(function("s:Emit"), a:type, a:args) +	let args = s:ShellTokenize(a:args) +	call s:WithPath(function("s:Emit"), a:type, args)  endfunction -function! s:Emit(path, type, args) +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 args = [a:path, '--emit', a:type, '-o', '-'] + a:args -		let output = system(shellescape(rustc) . " " . join(map(args, "shellescape(v:val)"))) -		if v:shell_error +		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 -		else +		endif +		if !v:shell_error  			new -			silent put =output +			exe 'silent keepalt read' fnameescape(output_path)  			1  			d -			if a:type == "ir" +			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 +" Invokes func(dict, ...) +" Where {dict} is a dictionary with the following keys: +"   'path' - The path to the file +"   'tmpdir' - The path to a temporary directory that will be deleted when the +"              function returns. +"   'istemp' - 1 if the path is a file inside of {dict.tmpdir} or 0 otherwise. +" If {istemp} is 1 then an additional key is provided: +"   'tmpdir_relpath' - The {path} relative to the {tmpdir}. +" +" {dict.path} may be a path to a file inside of {dict.tmpdir} or it may be the +" 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 save_write = &write +		let saved.write = &write  		set write -		let path = expand('%') -		let pathisempty = empty(path) -		if pathisempty || !save_write -			" use a temporary file named 'unnamed.rs' inside a temporary -			" directory. This produces better error messages -			let tmpdir = tempname() -			call mkdir(tmpdir) - -			let save_cwd = getcwd() -			silent exe 'lcd' fnameescape(tmpdir) - -			let path = 'unnamed.rs' +		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 save_mod = &mod +			let saved.mod = &mod  			set nomod -			silent exe 'keepalt write! ' . fnameescape(path) +			silent exe 'keepalt write! ' . fnameescape(dict.path)  			if pathisempty  				silent keepalt 0file  			endif  		else +			let dict.istemp = 0  			update  		endif -		call call(a:func, [path] + a:000) +		call call(a:func, [dict] + a:000)  	finally -		if exists("save_mod")   | let &mod = save_mod                    | endif -		if exists("save_write") | let &write = save_write                | endif -		if exists("save_cwd")   | silent exe 'lcd' fnameescape(save_cwd) | endif -		if exists("tmpdir")     | silent call s:RmDir(tmpdir)            | endif +		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 @@ -210,6 +274,71 @@ function! rust#AppendCmdLine(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 +endfunction +  function! s:RmDir(path)  	" sanity check; make sure it's not empty, /, or $HOME  	if empty(a:path) @@ -222,6 +351,66 @@ function! s:RmDir(path)  	silent exe "!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) +endfunction + +" Playpen Support {{{1 +" Parts of gist.vim by Yasuhiro Matsumoto <mattn.jp@gmail.com> reused +" gist.vim available under the BSD license, available at +" http://github.com/mattn/gist-vim +function! s:has_webapi() +  if !exists("*webapi#http#post") +    try +      call webapi#http#post() +    catch +    endtry +  endif +  return exists("*webapi#http#post") +endfunction + +function! rust#Play(count, line1, line2, ...) abort +  redraw + +  let l:rust_playpen_url = get(g:, 'rust_playpen_url', 'https://play.rust-lang.org/') +  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 +  endif + +  let bufname = bufname('%') +  if a:count < 1 +    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) +  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 +  endif + +  let payload = "format=simple&url=".webapi#http#encodeURI(body) +  let res = webapi#http#post(l:rust_shortener_url.'create.php', payload, {}) +  let url = res.content + +  redraw | echomsg 'Done: '.url +endfunction +  " }}}1  " vim: set noet sw=4 ts=4: diff --git a/autoload/rustfmt.vim b/autoload/rustfmt.vim new file mode 100644 index 00000000..20fd5852 --- /dev/null +++ b/autoload/rustfmt.vim @@ -0,0 +1,83 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'rust') == -1 +   +" Author: Stephen Sugden <stephen@stephensugden.com> +" +" Adapted from https://github.com/fatih/vim-go + +if !exists("g:rustfmt_autosave") +  let g:rustfmt_autosave = 0 +endif + +if !exists("g:rustfmt_command") +    let g:rustfmt_command = "rustfmt" +endif + +if !exists("g:rustfmt_options") +  let g:rustfmt_options = "" +endif + +if !exists("g:rustfmt_fail_silently") +  let g:rustfmt_fail_silently = 0 +endif + +let s:got_fmt_error = 0 + +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 = g:rustfmt_command . " --write-mode=overwrite " + +  let out = systemlist(command . g:rustfmt_options . " " . shellescape(l:tmpname)) + +  if v:shell_error == 0 +    " remove undo point caused via BufWritePre +    try | silent undojoin | catch | endtry + +    " Replace current file with temp file, then reload buffer +    call rename(l: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(l:tmpname) +  endif + +  call winrestview(l:curw) +endfunction + +endif | 
