Merge commit '2bd57c7174d5a44157d4b3144e93c8424ef7c493' as 'vim/bundle/rust'
						commit
						59cb6672a6
					
				@ -0,0 +1 @@
 | 
			
		||||
/doc/tags
 | 
			
		||||
@ -0,0 +1,32 @@
 | 
			
		||||
# rust.vim
 | 
			
		||||
 | 
			
		||||
## Description
 | 
			
		||||
 | 
			
		||||
This is a vim plugin that provides [Rust][r] file detection and syntax highlighting.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
### Using [Vundle][v]
 | 
			
		||||
 | 
			
		||||
1. Add `Plugin 'rust-lang/rust.vim'` to `~/.vimrc`
 | 
			
		||||
2. `vim +PluginInstall +qall`
 | 
			
		||||
 | 
			
		||||
*Note:* Vundle will not automatically detect Rust files properly if `filetype
 | 
			
		||||
on` is executed before Vundle. Please check the [quickstart][vqs] for more
 | 
			
		||||
details.
 | 
			
		||||
 | 
			
		||||
### Using [Pathogen][p]
 | 
			
		||||
 | 
			
		||||
1. `cd ~/.vim/bundle`
 | 
			
		||||
2. `git clone https://github.com/rust-lang/rust.vim.git`
 | 
			
		||||
 | 
			
		||||
[r]: https://rust-lang.org
 | 
			
		||||
[v]: https://github.com/gmarik/vundle
 | 
			
		||||
[vqs]: https://github.com/gmarik/vundle#quick-start
 | 
			
		||||
[p]: https://github.com/tpope/vim-pathogen
 | 
			
		||||
[nb]: https://github.com/Shougo/neobundle.vim
 | 
			
		||||
 | 
			
		||||
### Using [NeoBundle][nb]
 | 
			
		||||
 | 
			
		||||
1. Add `NeoBundle 'rust-lang/rust.vim'` to `~/.vimrc`
 | 
			
		||||
2. Re-open vim or execute `:NeoBundleInstall`
 | 
			
		||||
@ -0,0 +1,364 @@
 | 
			
		||||
" Author: Kevin Ballard
 | 
			
		||||
" Description: Helper functions for Rust commands/mappings
 | 
			
		||||
" Last Modified: May 27, 2014
 | 
			
		||||
 | 
			
		||||
" Jump {{{1
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
endfunction
 | 
			
		||||
 | 
			
		||||
function! s:Jump_Back()
 | 
			
		||||
	call search('{', 'b')
 | 
			
		||||
	keepjumps normal! w99[{
 | 
			
		||||
endfunction
 | 
			
		||||
 | 
			
		||||
function! s:Jump_Forward()
 | 
			
		||||
	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)
 | 
			
		||||
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
 | 
			
		||||
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)
 | 
			
		||||
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
 | 
			
		||||
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)
 | 
			
		||||
endfunction
 | 
			
		||||
 | 
			
		||||
" Emit {{{1
 | 
			
		||||
 | 
			
		||||
function! rust#Emit(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
 | 
			
		||||
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 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
 | 
			
		||||
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)
 | 
			
		||||
		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
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
" }}}1
 | 
			
		||||
 | 
			
		||||
" vim: set noet sw=4 ts=4:
 | 
			
		||||
@ -0,0 +1,65 @@
 | 
			
		||||
" Vim compiler file
 | 
			
		||||
" Compiler:         Cargo Compiler
 | 
			
		||||
" Maintainer:       Damien Radtke <damienradtke@gmail.com>
 | 
			
		||||
" Latest Revision:  2014 Sep 24
 | 
			
		||||
 | 
			
		||||
if exists('current_compiler')
 | 
			
		||||
  finish
 | 
			
		||||
endif
 | 
			
		||||
runtime compiler/rustc.vim
 | 
			
		||||
let current_compiler = "cargo"
 | 
			
		||||
 | 
			
		||||
if exists(':CompilerSet') != 2
 | 
			
		||||
    command -nargs=* CompilerSet setlocal <args>
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if exists('g:cargo_makeprg_params')
 | 
			
		||||
    execute 'CompilerSet makeprg=cargo\ '.escape(g:cargo_makeprg_params, ' \|"').'\ $*'
 | 
			
		||||
else
 | 
			
		||||
    CompilerSet makeprg=cargo\ $*
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
" Allow a configurable global Cargo.toml name. This makes it easy to
 | 
			
		||||
" support variations like 'cargo.toml'.
 | 
			
		||||
let s:cargo_manifest_name = get(g:, 'cargo_manifest_name', 'Cargo.toml')
 | 
			
		||||
 | 
			
		||||
function! s:is_absolute(path)
 | 
			
		||||
    return a:path[0] == '/' || a:path =~ '[A-Z]\+:'
 | 
			
		||||
endfunction
 | 
			
		||||
 | 
			
		||||
let s:local_manifest = findfile(s:cargo_manifest_name, '.;')
 | 
			
		||||
if s:local_manifest != ''
 | 
			
		||||
    let s:local_manifest = fnamemodify(s:local_manifest, ':p:h').'/'
 | 
			
		||||
    augroup cargo
 | 
			
		||||
        au!
 | 
			
		||||
        au QuickfixCmdPost make call s:FixPaths()
 | 
			
		||||
    augroup END
 | 
			
		||||
 | 
			
		||||
    " FixPaths() is run after Cargo, and is used to change the file paths
 | 
			
		||||
    " to be relative to the current directory instead of Cargo.toml.
 | 
			
		||||
    function! s:FixPaths()
 | 
			
		||||
        let qflist = getqflist()
 | 
			
		||||
        let manifest = s:local_manifest
 | 
			
		||||
        for qf in qflist
 | 
			
		||||
            if !qf.valid
 | 
			
		||||
                let m = matchlist(qf.text, '(file://\(.*\))$')
 | 
			
		||||
                if !empty(m)
 | 
			
		||||
                    let manifest = m[1].'/'
 | 
			
		||||
                    " Manually strip another slash if needed; usually just an
 | 
			
		||||
                    " issue on Windows.
 | 
			
		||||
                    if manifest =~ '^/[A-Z]\+:/'
 | 
			
		||||
                        let manifest = manifest[1:]
 | 
			
		||||
                    endif
 | 
			
		||||
                endif
 | 
			
		||||
                continue
 | 
			
		||||
            endif
 | 
			
		||||
            let filename = bufname(qf.bufnr)
 | 
			
		||||
            if s:is_absolute(filename)
 | 
			
		||||
                continue
 | 
			
		||||
            endif
 | 
			
		||||
            let qf.filename = simplify(manifest.filename)
 | 
			
		||||
            call remove(qf, 'bufnr')
 | 
			
		||||
        endfor
 | 
			
		||||
        call setqflist(qflist, 'r')
 | 
			
		||||
    endfunction
 | 
			
		||||
endif
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
" Vim compiler file
 | 
			
		||||
" Compiler:         Rust Compiler
 | 
			
		||||
" Maintainer:       Chris Morgan <me@chrismorgan.info>
 | 
			
		||||
" Latest Revision:  2013 Jul 12
 | 
			
		||||
 | 
			
		||||
if exists("current_compiler")
 | 
			
		||||
  finish
 | 
			
		||||
endif
 | 
			
		||||
let current_compiler = "rustc"
 | 
			
		||||
 | 
			
		||||
let s:cpo_save = &cpo
 | 
			
		||||
set cpo&vim
 | 
			
		||||
 | 
			
		||||
if exists(":CompilerSet") != 2
 | 
			
		||||
	command -nargs=* CompilerSet setlocal <args>
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if exists("g:rustc_makeprg_no_percent") && g:rustc_makeprg_no_percent == 1
 | 
			
		||||
	CompilerSet makeprg=rustc
 | 
			
		||||
else
 | 
			
		||||
	CompilerSet makeprg=rustc\ \%
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
CompilerSet errorformat=
 | 
			
		||||
			\%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
 | 
			
		||||
@ -0,0 +1,178 @@
 | 
			
		||||
*rust.txt*      Filetype plugin for Rust
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
CONTENTS                                                      *rust* *ft-rust*
 | 
			
		||||
 | 
			
		||||
1. Introduction                                                   |rust-intro|
 | 
			
		||||
2. Settings                                                    |rust-settings|
 | 
			
		||||
3. Commands                                                    |rust-commands|
 | 
			
		||||
4. Mappings                                                    |rust-mappings|
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
INTRODUCTION                                                      *rust-intro*
 | 
			
		||||
 | 
			
		||||
This plugin provides syntax and supporting functionality for the Rust
 | 
			
		||||
filetype.
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
SETTINGS                                                       *rust-settings*
 | 
			
		||||
 | 
			
		||||
This plugin has a few variables you can define in your vimrc that change the
 | 
			
		||||
behavior of the plugin.
 | 
			
		||||
 | 
			
		||||
                                                                *g:rustc_path*
 | 
			
		||||
g:rustc_path~
 | 
			
		||||
	Set this option to the path to rustc for use in the |:RustRun| and
 | 
			
		||||
	|:RustExpand| commands. If unset, "rustc" will be located in $PATH: >
 | 
			
		||||
	    let g:rustc_path = $HOME."/bin/rustc"
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                  *g:rustc_makeprg_no_percent*
 | 
			
		||||
g:rustc_makeprg_no_percent~
 | 
			
		||||
	Set this option to 1 to have 'makeprg' default to "rustc" instead of
 | 
			
		||||
	"rustc %": >
 | 
			
		||||
	    let g:rustc_makeprg_no_percent = 1
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                              *g:rust_conceal*
 | 
			
		||||
g:rust_conceal~
 | 
			
		||||
	Set this option to turn on the basic |conceal| support: >
 | 
			
		||||
	    let g:rust_conceal = 1
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                     *g:rust_conceal_mod_path*
 | 
			
		||||
g:rust_conceal_mod_path~
 | 
			
		||||
	Set this option to turn on |conceal| for the path connecting token
 | 
			
		||||
	"::": >
 | 
			
		||||
	    let g:rust_conceal_mod_path = 1
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                          *g:rust_conceal_pub*
 | 
			
		||||
g:rust_conceal_pub~
 | 
			
		||||
	Set this option to turn on |conceal| for the "pub" token: >
 | 
			
		||||
	    let g:rust_conceal_pub = 1
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                     *g:rust_recommended_style*
 | 
			
		||||
g:rust_recommended_style~
 | 
			
		||||
        Set this option to enable vim indentation and textwidth settings to
 | 
			
		||||
        conform to style conventions of the rust standard library (i.e. use 4
 | 
			
		||||
        spaces for indents and sets 'textwidth' to 99). This option is enabled
 | 
			
		||||
	by default. To disable it: >
 | 
			
		||||
	    let g:rust_recommended_style = 0
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                                 *g:rust_fold*
 | 
			
		||||
g:rust_fold~
 | 
			
		||||
	Set this option to turn on |folding|: >
 | 
			
		||||
	    let g:rust_fold = 1
 | 
			
		||||
<
 | 
			
		||||
	Value		Effect ~
 | 
			
		||||
	0		No folding
 | 
			
		||||
	1		Braced blocks are folded. All folds are open by
 | 
			
		||||
			default.
 | 
			
		||||
	2		Braced blocks are folded. 'foldlevel' is left at the
 | 
			
		||||
			global value (all folds are closed by default).
 | 
			
		||||
 | 
			
		||||
                                                  *g:rust_bang_comment_leader*
 | 
			
		||||
g:rust_bang_comment_leader~
 | 
			
		||||
	Set this option to 1 to preserve the leader on multi-line doc comments
 | 
			
		||||
	using the /*! syntax: >
 | 
			
		||||
	    let g:rust_bang_comment_leader = 1
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                 *g:ftplugin_rust_source_path*
 | 
			
		||||
g:ftplugin_rust_source_path~
 | 
			
		||||
	Set this option to a path that should be prepended to 'path' for Rust
 | 
			
		||||
	source files: >
 | 
			
		||||
	    let g:ftplugin_rust_source_path = $HOME.'/dev/rust'
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
                                                       *g:cargo_manifest_name*
 | 
			
		||||
g:cargo_manifest_name~
 | 
			
		||||
	Set this option to the name of the manifest file for your projects. If
 | 
			
		||||
	not specified it defaults to 'Cargo.toml' : >
 | 
			
		||||
	    let g:cargo_manifest_name = 'Cargo.toml'
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
COMMANDS                                                       *rust-commands*
 | 
			
		||||
 | 
			
		||||
:RustRun  [args]                                                    *:RustRun*
 | 
			
		||||
:RustRun! [rustc-args] [--] [args]
 | 
			
		||||
		Compiles and runs the current file. If it has unsaved changes,
 | 
			
		||||
		it will be saved first using |:update|. If the current file is
 | 
			
		||||
		an unnamed buffer, it will be written to a temporary file
 | 
			
		||||
		first. The compiled binary is always placed in a temporary
 | 
			
		||||
		directory, but is run from the current directory.
 | 
			
		||||
 | 
			
		||||
		The arguments given to |:RustRun| will be passed to the
 | 
			
		||||
		compiled binary.
 | 
			
		||||
 | 
			
		||||
		If ! is specified, the arguments are passed to rustc instead.
 | 
			
		||||
		A "--" argument will separate the rustc arguments from the
 | 
			
		||||
		arguments passed to the binary.
 | 
			
		||||
 | 
			
		||||
		If |g:rustc_path| is defined, it is used as the path to rustc.
 | 
			
		||||
		Otherwise it is assumed rustc can be found in $PATH.
 | 
			
		||||
 | 
			
		||||
:RustExpand  [args]                                              *:RustExpand*
 | 
			
		||||
:RustExpand! [TYPE] [args]
 | 
			
		||||
		Expands the current file using --pretty and displays the
 | 
			
		||||
		results in a new split. If the current file has unsaved
 | 
			
		||||
		changes, it will be saved first using |:update|. If the
 | 
			
		||||
		current file is an unnamed buffer, it will be written to a
 | 
			
		||||
		temporary file first.
 | 
			
		||||
 | 
			
		||||
		The arguments given to |:RustExpand| will be passed to rustc.
 | 
			
		||||
		This is largely intended for specifying various --cfg
 | 
			
		||||
		configurations.
 | 
			
		||||
 | 
			
		||||
		If ! is specified, the first argument is the expansion type to
 | 
			
		||||
		pass to rustc --pretty. Otherwise it will default to
 | 
			
		||||
		"expanded".
 | 
			
		||||
 | 
			
		||||
		If |g:rustc_path| is defined, it is used as the path to rustc.
 | 
			
		||||
		Otherwise it is assumed rustc can be found in $PATH.
 | 
			
		||||
 | 
			
		||||
:RustEmitIr [args]                                               *:RustEmitIr*
 | 
			
		||||
		Compiles the current file to LLVM IR and displays the results
 | 
			
		||||
		in a new split. If the current file has unsaved changes, it
 | 
			
		||||
		will be saved first using |:update|. If the current file is an
 | 
			
		||||
		unnamed buffer, it will be written to a temporary file first.
 | 
			
		||||
 | 
			
		||||
		The arguments given to |:RustEmitIr| will be passed to rustc.
 | 
			
		||||
 | 
			
		||||
		If |g:rustc_path| is defined, it is used as the path to rustc.
 | 
			
		||||
		Otherwise it is assumed rustc can be found in $PATH.
 | 
			
		||||
 | 
			
		||||
:RustEmitAsm [args]                                             *:RustEmitAsm*
 | 
			
		||||
		Compiles the current file to assembly and displays the results
 | 
			
		||||
		in a new split. If the current file has unsaved changes, it
 | 
			
		||||
		will be saved first using |:update|. If the current file is an
 | 
			
		||||
		unnamed buffer, it will be written to a temporary file first.
 | 
			
		||||
 | 
			
		||||
		The arguments given to |:RustEmitAsm| will be passed to rustc.
 | 
			
		||||
 | 
			
		||||
		If |g:rustc_path| is defined, it is used as the path to rustc.
 | 
			
		||||
		Otherwise it is assumed rustc can be found in $PATH.
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
MAPPINGS                                                       *rust-mappings*
 | 
			
		||||
 | 
			
		||||
This plugin defines mappings for |[[| and |]]| to support hanging indents.
 | 
			
		||||
 | 
			
		||||
It also has a few other mappings:
 | 
			
		||||
 | 
			
		||||
							*rust_<D-r>*
 | 
			
		||||
<D-r>			Executes |:RustRun| with no arguments.
 | 
			
		||||
			Note: This binding is only available in MacVim.
 | 
			
		||||
 | 
			
		||||
							*rust_<D-R>*
 | 
			
		||||
<D-R>			Populates the command line with |:RustRun|! using the
 | 
			
		||||
			arguments given to the last invocation, but does not
 | 
			
		||||
			execute it.
 | 
			
		||||
			Note: This binding is only available in MacVim.
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
 vim:tw=78:sw=4:noet:ts=8:ft=help:norl:
 | 
			
		||||
@ -0,0 +1 @@
 | 
			
		||||
au BufRead,BufNewFile *.rs set filetype=rust
 | 
			
		||||
@ -0,0 +1,162 @@
 | 
			
		||||
" Language:     Rust
 | 
			
		||||
" Description:  Vim syntax file for Rust
 | 
			
		||||
" Maintainer:   Chris Morgan <me@chrismorgan.info>
 | 
			
		||||
" Maintainer:   Kevin Ballard <kevin@sb.org>
 | 
			
		||||
" Last Change:  January 29, 2015
 | 
			
		||||
 | 
			
		||||
if exists("b:did_ftplugin")
 | 
			
		||||
	finish
 | 
			
		||||
endif
 | 
			
		||||
let b:did_ftplugin = 1
 | 
			
		||||
 | 
			
		||||
let s:save_cpo = &cpo
 | 
			
		||||
set cpo&vim
 | 
			
		||||
 | 
			
		||||
" 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 == 1
 | 
			
		||||
	" 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 == 1
 | 
			
		||||
	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')
 | 
			
		||||
 | 
			
		||||
" NOT adding .rc as it's being phased out (0.7)
 | 
			
		||||
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 b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate'
 | 
			
		||||
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')
 | 
			
		||||
	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>
 | 
			
		||||
 | 
			
		||||
" %-matching. <:> is handy for generics.
 | 
			
		||||
set matchpairs+=<:>
 | 
			
		||||
" There are two minor issues with it; (a) comparison operators in expressions,
 | 
			
		||||
" where a less-than may match a greater-than later on—this is deemed a trivial
 | 
			
		||||
" issue—and (b) `Fn() -> X` syntax. This latter issue is irremediable from the
 | 
			
		||||
" highlighting perspective (built into Vim), but the actual % functionality
 | 
			
		||||
" can be fixed by this use of matchit.vim.
 | 
			
		||||
let b:match_skip = 's:comment\|string\|rustArrow'
 | 
			
		||||
source $VIMRUNTIME/macros/matchit.vim
 | 
			
		||||
 | 
			
		||||
" 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>)
 | 
			
		||||
 | 
			
		||||
" 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
 | 
			
		||||
		\|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
 | 
			
		||||
 | 
			
		||||
let &cpo = s:save_cpo
 | 
			
		||||
unlet s:save_cpo
 | 
			
		||||
 | 
			
		||||
" vim: set noet sw=4 ts=4:
 | 
			
		||||
@ -0,0 +1,203 @@
 | 
			
		||||
" Vim indent file
 | 
			
		||||
" Language:         Rust
 | 
			
		||||
" Author:           Chris Morgan <me@chrismorgan.info>
 | 
			
		||||
" Last Change:      2014 Sep 13
 | 
			
		||||
 | 
			
		||||
" Only load this indent file when no other was loaded.
 | 
			
		||||
if exists("b:did_indent")
 | 
			
		||||
  finish
 | 
			
		||||
endif
 | 
			
		||||
let b:did_indent = 1
 | 
			
		||||
 | 
			
		||||
setlocal cindent
 | 
			
		||||
setlocal cinoptions=L0,(0,Ws,J1,j1
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
" Some preliminary settings
 | 
			
		||||
setlocal nolisp		" Make sure lisp indenting doesn't supersede us
 | 
			
		||||
setlocal autoindent	" indentexpr isn't much help otherwise
 | 
			
		||||
" Also do indentkeys, otherwise # gets shoved to column 0 :-/
 | 
			
		||||
setlocal indentkeys=0{,0},!^F,o,O,0[,0]
 | 
			
		||||
 | 
			
		||||
setlocal indentexpr=GetRustIndent(v:lnum)
 | 
			
		||||
 | 
			
		||||
" Only define the function once.
 | 
			
		||||
if exists("*GetRustIndent")
 | 
			
		||||
  finish
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
" 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
 | 
			
		||||
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
 | 
			
		||||
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 !~ '([^()]\+,$'
 | 
			
		||||
		" 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) {
 | 
			
		||||
		"
 | 
			
		||||
		" 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
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
" Vim syntastic plugin helper
 | 
			
		||||
" Language:     Rust
 | 
			
		||||
" Maintainer:   Andrew Gallant <jamslam@gmail.com>
 | 
			
		||||
 | 
			
		||||
if exists("g:loaded_syntastic_rust_filetype")
 | 
			
		||||
  finish
 | 
			
		||||
endif
 | 
			
		||||
let g:loaded_syntastic_rust_filetype = 1
 | 
			
		||||
let s:save_cpo = &cpo
 | 
			
		||||
set cpo&vim
 | 
			
		||||
 | 
			
		||||
" This is to let Syntastic know about the Rust filetype.
 | 
			
		||||
" It enables tab completion for the 'SyntasticInfo' command.
 | 
			
		||||
" (This does not actually register the syntax checker.)
 | 
			
		||||
if exists('g:syntastic_extra_filetypes')
 | 
			
		||||
    call add(g:syntastic_extra_filetypes, 'rust')
 | 
			
		||||
else
 | 
			
		||||
    let g:syntastic_extra_filetypes = ['rust']
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
let &cpo = s:save_cpo
 | 
			
		||||
unlet s:save_cpo
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
" Vim syntastic plugin
 | 
			
		||||
" Language:     Rust
 | 
			
		||||
" Maintainer:   Andrew Gallant <jamslam@gmail.com>
 | 
			
		||||
"
 | 
			
		||||
" See for details on how to add an external Syntastic checker:
 | 
			
		||||
" https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide#external
 | 
			
		||||
 | 
			
		||||
if exists("g:loaded_syntastic_rust_rustc_checker")
 | 
			
		||||
    finish
 | 
			
		||||
endif
 | 
			
		||||
let g:loaded_syntastic_rust_rustc_checker = 1
 | 
			
		||||
 | 
			
		||||
let s:save_cpo = &cpo
 | 
			
		||||
set cpo&vim
 | 
			
		||||
 | 
			
		||||
function! SyntaxCheckers_rust_rustc_GetLocList() dict
 | 
			
		||||
    let makeprg = self.makeprgBuild({ 'args': '-Zparse-only' })
 | 
			
		||||
 | 
			
		||||
    let errorformat  =
 | 
			
		||||
        \ '%E%f:%l:%c: %\d%#:%\d%# %.%\{-}error:%.%\{-} %m,'   .
 | 
			
		||||
        \ '%W%f:%l:%c: %\d%#:%\d%# %.%\{-}warning:%.%\{-} %m,' .
 | 
			
		||||
        \ '%C%f:%l %m,' .
 | 
			
		||||
        \ '%-Z%.%#'
 | 
			
		||||
 | 
			
		||||
    return SyntasticMake({
 | 
			
		||||
        \ 'makeprg': makeprg,
 | 
			
		||||
        \ 'errorformat': errorformat })
 | 
			
		||||
endfunction
 | 
			
		||||
 | 
			
		||||
call g:SyntasticRegistry.CreateAndRegisterChecker({
 | 
			
		||||
    \ 'filetype': 'rust',
 | 
			
		||||
    \ 'name': 'rustc'})
 | 
			
		||||
 | 
			
		||||
let &cpo = s:save_cpo
 | 
			
		||||
unlet s:save_cpo
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue