diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2018-07-08 15:16:28 +0200 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2018-07-08 15:16:28 +0200 | 
| commit | 055f7710b65dfa2df52fc0b5be2486ae36ac5751 (patch) | |
| tree | 0b6c36a330e8c0c4e37ad521773d28b6c52ad3ec /autoload | |
| parent | 33f610feb73ce782cf41a7d9a377541991c692b5 (diff) | |
| download | vim-polyglot-055f7710b65dfa2df52fc0b5be2486ae36ac5751.tar.gz vim-polyglot-055f7710b65dfa2df52fc0b5be2486ae36ac5751.zip | |
Update dependencies
Diffstat (limited to 'autoload')
| -rw-r--r-- | autoload/cargo.vim | 116 | ||||
| -rw-r--r-- | autoload/cargo/quickfix.vim | 30 | ||||
| -rw-r--r-- | autoload/rubycomplete.vim | 2 | ||||
| -rw-r--r-- | autoload/rust.vim | 622 | ||||
| -rw-r--r-- | autoload/rust/debugging.vim | 98 | ||||
| -rw-r--r-- | autoload/rustfmt.vim | 229 | 
6 files changed, 662 insertions, 435 deletions
| 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 | 
