amix 7 years ago
commit cda6e529bd
  1. 19
  2. 1
  3. 30
  4. 31
  5. 225
  6. 65
  7. 33
  8. 178
  9. 1
  10. 150
  11. 196
  12. 22
  13. 262
  14. 35
  15. 1
  16. 1
  17. 36
  18. 196
  19. 103
  20. 25
  21. 8
  22. 4

@ -15,7 +15,14 @@ The awesome version includes a lot of great plugins, configurations and color sc
git clone https://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh
The taglist.vim plugin will require ctags (http://ctags.sourceforge.net) (Debian: apt-get install ctags)
The taglist.vim plugin will require ctags (http://ctags.sourceforge.net)
For Debian and Ubuntu:
apt-get install ctags
For Arch Linux:
pacman -S ctags
I also recommend using [Source Code Pro font from Adobe](http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1960) (it's free and awesome font for writing and programming). The Awesome vimrc is already setup to try to use it
@ -102,7 +109,7 @@ Remove all clutter and focus only on the essential. Similar to iA Writer or Writ
* [vim-bundle-mako](https://github.com/sophacles/vim-bundle-mako)
* [vim-markdown](https://github.com/tpope/vim-markdown)
* [nginx.vim](https://github.com/vim-scripts/nginx.vim): Highlights configuration files for nginx
* [vim-golang](https://github.com/jnwhiteh/vim-golang)
* [vim-go](https://github.com/fatih/vim-go)
## How to include your own stuff?
@ -137,7 +144,7 @@ Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin:
let g:ctrlp_map = '<c-f>'
Open [PeepOpen](https://peepcode.com/products/peepopen) plugin:
Open [PeepOpen](http://topfunky.github.io/PeepOpen/) plugin:
map <leader>j :PeepOpen<cr>
@ -327,3 +334,9 @@ Vimscript mappings:
* [Folding in Vim](http://amix.dk/blog/post/19132#Folding-in-Vim)
* [
Zen room for Vim: Focusing only on the essential](http://amix.dk/blog/post/19744#zenroom-for-Vim-Focsuing-only-on-the-essential)
## How to uninstall
Do following:
* Remove `~/.vim_runtime`
* Remove any lines that refernce `.vim_runtime` in your `~/.vimrc`

@ -0,0 +1,30 @@
# rust.vim
## Description
This is a vim plugin provides [Rust][r] file detection and syntax highlighting.
It is synchronized daily to the vim support code in [rust-lang/rust][rr]'s
master branch via cronjob.
## Installation
### Using [Vundle][v]
1. Add `Plugin 'wting/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
### Using [Pathogen][p]
1. `cd ~/.vim/bundle`
2. `git clone https://github.com/wting/rust.vim.git`
[rr]: https://github.com/rust-lang/rust
[p]: https://github.com/tpope/vim-pathogen
[r]: https://en.wikipedia.org/wiki/Rust_language
[v]: https://github.com/gmarik/vundle
[vqs]: https://github.com/gmarik/vundle#quick-start

@ -0,0 +1,31 @@
if !exists('g:rust_conceal') || !has('conceal') || &enc != 'utf-8'
" For those who don't want to see `::`...
if exists('g:rust_conceal_mod_path')
syn match rustNiceOperator "::" conceal cchar=
syn match rustRightArrowHead contained ">" conceal cchar= 
syn match rustRightArrowTail contained "-" conceal cchar=
syn match rustNiceOperator "->" contains=rustRightArrowHead,rustRightArrowTail
syn match rustFatRightArrowHead contained ">" conceal cchar= 
syn match rustFatRightArrowTail contained "=" conceal cchar=
syn match rustNiceOperator "=>" contains=rustFatRightArrowHead,rustFatRightArrowTail
syn match rustNiceOperator /\<\@!_\(_*\>\)\@=/ conceal cchar=
" For those who don't want to see `pub`...
if exists('g:rust_conceal_pub')
syn match rustPublicSigil contained "pu" conceal cchar=
syn match rustPublicRest contained "b" conceal cchar= 
syn match rustNiceOperator "pub " contains=rustPublicSigil,rustPublicRest
hi link rustNiceOperator Operator
if !exists('g:rust_conceal_mod_path')
hi! link Conceal Operator

@ -0,0 +1,225 @@
" 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
let foldenable = &foldenable
set nofoldenable
while cnt > 0
execute "call <SID>Jump_" . a:function . "()"
let cnt = cnt - 1
let &foldenable = foldenable
function! s:Jump_Back()
call search('{', 'b')
keepjumps normal! w99[{
function! s:Jump_Forward()
normal! j0
call search('{', 'b')
keepjumps normal! w99[{%
call search('{')
" Run {{{1
function! rust#Run(bang, args)
if a:bang
let idx = index(a:args, '--')
if idx != -1
let rustc_args = idx == 0 ? [] : a:args[:idx-1]
let args = a:args[idx+1:]
let rustc_args = a:args
let args = []
let rustc_args = []
let args = a:args
let b:rust_last_rustc_args = rustc_args
let b:rust_last_args = args
call s:WithPath(function("s:Run"), rustc_args, args)
function! s:Run(path, rustc_args, args)
let exepath = tempname()
if has('win32')
let exepath .= '.exe'
let rustc_args = [a:path, '-o', exepath] + a:rustc_args
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
if !v:shell_error
exe '!' . shellescape(exepath) . " " . join(map(a:args, 'shellescape(v:val)'))
if exists("exepath")
silent! call delete(exepath)
" Expand {{{1
function! rust#Expand(bang, args)
if a:bang && !empty(a:args)
let pretty = a:args[0]
let args = a:args[1:]
let pretty = "expanded"
let args = a:args
call s:WithPath(function("s:Expand"), pretty, args)
function! s:Expand(path, pretty, args)
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 v:shell_error
echohl WarningMsg
echo output
echohl None
silent put =output
setl filetype=rust
setl buftype=nofile
setl bufhidden=hide
setl noswapfile
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="]
if !empty(a:lead)
call filter(list, "v:val[:len(a:lead)-1] == a:lead")
return list
return glob(escape(a:lead, "*?[") . '*', 0, 1)
" Emit {{{1
function! rust#Emit(type, args)
call s:WithPath(function("s:Emit"), a:type, a:args)
function! s:Emit(path, type, args)
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
echohl WarningMsg
echo output
echohl None
silent put =output
if a:type == "ir"
setl filetype=llvm
elseif a:type == "asm"
setl filetype=asm
setl buftype=nofile
setl bufhidden=hide
setl noswapfile
" Utility functions {{{1
function! s:WithPath(func, ...)
let save_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 save_mod = &mod
set nomod
silent exe 'keepalt write! ' . fnameescape(path)
if pathisempty
silent keepalt 0file
call call(a:func, [path] + a:000)
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
function! rust#AppendCmdLine(text)
call setcmdpos(getcmdpos())
let cmd = getcmdline() . a:text
return cmd
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
silent exe "!rm -rf " . shellescape(a:path)
" }}}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')
runtime compiler/rustc.vim
let current_compiler = "cargo"
if exists(':CompilerSet') != 2
command -nargs=* CompilerSet setlocal <args>
if exists('g:cargo_makeprg_params')
execute 'CompilerSet makeprg=cargo\ '.escape(g:cargo_makeprg_params, ' \|"').'\ $*'
CompilerSet makeprg=cargo\ $*
" 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]\+:'
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 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:]
let filename = bufname(qf.bufnr)
if s:is_absolute(filename)
let qf.filename = simplify(manifest.filename)
call remove(qf, 'bufnr')
call setqflist(qflist, 'r')

@ -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")
let current_compiler = "rustc"
let s:cpo_save = &cpo
set cpo&vim
if exists(":CompilerSet") != 2
command -nargs=* CompilerSet setlocal <args>
if exists("g:rustc_makeprg_no_percent") && g:rustc_makeprg_no_percent == 1
CompilerSet makeprg=rustc
CompilerSet makeprg=rustc\ \%
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
SETTINGS *rust-settings*
This plugin has a few variables you can define in your vimrc that change the
behavior of the plugin.
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"
Set this option to 1 to have 'makeprg' default to "rustc" instead of
"rustc %": >
let g:rustc_makeprg_no_percent = 1
Set this option to turn on the basic |conceal| support: >
let g:rust_conceal = 1
Set this option to turn on |conceal| for the path connecting token
"::": >
let g:rust_conceal_mod_path = 1
Set this option to turn on |conceal| for the "pub" token: >
let g:rust_conceal_pub = 1
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
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
2 Braced blocks are folded. 'foldlevel' is left at the
global value (all folds are closed by default).
Set this option to 1 to preserve the leader on multi-line doc comments
using the /*! syntax: >
let g:rust_bang_comment_leader = 1
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'
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
If ! is specified, the first argument is the expansion type to
pass to rustc --pretty. Otherwise it will default to
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:
<D-r> Executes |:RustRun| with no arguments.
Note: This binding is only available in MacVim.
<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.

@ -0,0 +1 @@
au BufRead,BufNewFile *.rs set filetype=rust

@ -0,0 +1,150 @@
" Language: Rust
" Description: Vim syntax file for Rust
" Maintainer: Chris Morgan <me@chrismorgan.info>
" Maintainer: Kevin Ballard <kevin@sb.org>
" Last Change: Jul 07, 2014
if exists("b:did_ftplugin")
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:*/,:///,://!,://
setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://
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
" 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
if exists("g:loaded_delimitMate")
if exists("b:delimitMate_excluded_regions")
let b:rust_original_delimitMate_excluded_regions = b:delimitMate_excluded_regions
let b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate'
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<
setlocal foldlevel=99
if has('conceal') && exists('g:rust_conceal')
let b:rust_set_conceallevel=1
setlocal conceallevel=2
" Motion Commands {{{1
" Bind motion commands to support hanging indents
nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR>
nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR>
xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR>
xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR>
onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR>
onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR>
" Commands {{{1
" See |:RustRun| for docs
command! -nargs=* -complete=file -bang -bar -buffer RustRun call rust#Run(<bang>0, [<f-args>])
" See |:RustExpand| for docs
command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer RustExpand call rust#Expand(<bang>0, [<f-args>])
" See |:RustEmitIr| for docs
command! -nargs=* -bar -buffer RustEmitIr call rust#Emit("ir", [<f-args>])
" See |:RustEmitAsm| for docs
command! -nargs=* -bar -buffer RustEmitAsm call rust#Emit("asm", [<f-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 = []
" 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
\|unlet! b:delimitMate_excluded_regions
\|if exists('b:rust_set_foldmethod')
\|setlocal foldmethod< foldlevel<
\|unlet b:rust_set_foldmethod
\|if exists('b:rust_set_conceallevel')
\|setlocal conceallevel<
\|unlet b:rust_set_conceallevel
\|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> ]]
" }}}1
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set noet sw=4 ts=4:

@ -0,0 +1,196 @@
" 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")
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")
" 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
let min = col + 1
let line = strpart(line, 0, min - 1)
return substitute(line, "\s*$", "", "")
" Sorry, this is not complete, nor fully correct (e.g. string "//").
" Such is life.
return substitute(line, "\s*//.*$", "", "")
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
" without syntax, let's not even try
return 0
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)
" 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)
" 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)
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)
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
" 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
return &shiftwidth
" Fall back on cindent, which does it mostly right
return cindent(a:lnum)

@ -0,0 +1,22 @@
" Vim syntastic plugin helper
" Language: Rust
" Maintainer: Andrew Gallant <jamslam@gmail.com>
if exists("g:loaded_syntastic_rust_filetype")
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')
let g:syntastic_extra_filetypes = ['rust']
let &cpo = s:save_cpo
unlet s:save_cpo

@ -0,0 +1,262 @@
" Vim syntax file
" Language: Rust
" Maintainer: Patrick Walton <pcwalton@mozilla.com>
" Maintainer: Ben Blum <bblum@cs.cmu.edu>
" Maintainer: Chris Morgan <me@chrismorgan.info>
" Last Change: January 5, 2015
if version < 600
syntax clear
elseif exists("b:current_syntax")
" Syntax definitions {{{1
" Basic keywords {{{2
syn keyword rustConditional match if else
syn keyword rustOperator as
syn match rustAssert "\<assert\(\w\)*!" contained
syn match rustPanic "\<panic\(\w\)*!" contained
syn keyword rustKeyword break
syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty
syn keyword rustKeyword continue
syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty
syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty
syn keyword rustKeyword for in if impl let
syn keyword rustKeyword loop once pub
syn keyword rustKeyword return super
syn keyword rustKeyword unsafe virtual where while
syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty
" FIXME: Scoped impl's name is also fallen in this category
syn keyword rustKeyword mod trait struct enum type nextgroup=rustIdentifier skipwhite skipempty
syn keyword rustStorage move mut ref static const
syn keyword rustInvalidBareKeyword crate
syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty
" This is to get the `bar` part of `extern crate "foo" as bar;` highlighting.
syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator
syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty
syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
syn match rustFuncName "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
syn region rustBoxPlacement matchgroup=rustBoxPlacementParens start="(" end=")" contains=TOP contained
syn keyword rustBoxPlacementExpr GC containedin=rustBoxPlacement
" Ideally we'd have syntax rules set up to match arbitrary expressions. Since
" we don't, we'll just define temporary contained rules to handle balancing
" delimiters.
syn region rustBoxPlacementBalance start="(" end=")" containedin=rustBoxPlacement transparent
syn region rustBoxPlacementBalance start="\[" end="\]" containedin=rustBoxPlacement transparent
" {} are handled by rustFoldBraces
syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end=")" contains=TOP nextgroup=rustMacroRepeatCount
syn match rustMacroRepeatCount ".\?[*+]" contained
syn match rustMacroVariable "$\w\+"
" Reserved (but not yet used) keywords {{{2
syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro
" Built-in types {{{2
syn keyword rustType isize usize float char bool u8 u16 u32 u64 f32
syn keyword rustType f64 i8 i16 i32 i64 str Self
" Things from the prelude (src/libstd/prelude.rs) {{{2
" This section is just straight transformation of the contents of the prelude,
" to make it easy to update.
" Reexported core operators {{{3
syn keyword rustTrait Copy Send Sized Sync
syn keyword rustTrait Drop Fn FnMut FnOnce
" Reexported functions {{{3
syn keyword rustFunction drop
" Reexported types and traits {{{3
syn keyword rustTrait Box
syn keyword rustTrait CharExt
syn keyword rustTrait Clone
syn keyword rustTrait PartialEq PartialOrd Eq Ord
syn keyword rustTrait DoubleEndedIterator
syn keyword rustTrait ExactSizeIterator
syn keyword rustTrait Iterator IteratorExt Extend
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
syn keyword rustTrait PtrExt MutPtrExt
syn keyword rustEnum Result
syn keyword rustEnumVariant Ok Err
syn keyword rustTrait AsSlice
syn keyword rustTrait SliceExt SliceConcatExt
syn keyword rustTrait Str StrExt
syn keyword rustTrait String ToString
syn keyword rustTrait Vec
" FIXME: remove when path reform lands
syn keyword rustTrait Path GenericPath
" FIXME: remove when I/O reform lands
syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
" Other syntax {{{2
syn keyword rustSelf self
syn keyword rustBoolean true false
" If foo::bar changes to foo.bar, change this ("::" to "\.").
" If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
syn match rustModPathSep "::"
syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
" This is merely a convention; note also the use of [A-Z], restricting it to
" latin identifiers rather than the full Unicode uppercase. I have not used
" [:upper:] as it depends upon 'noignorecase'
"syn match rustCapsIdent display "[A-Z]\w\(\w\)*"
syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?"
" This one isn't *quite* right, as we could have binary-& with a reference
syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1
syn match rustSigil display /[&~@*][^)= \t\r\n]/he=e-1,me=e-1
" This isn't actually correct; a closure with no arguments can be `|| { }`.
" Last, because the & in && isn't a sigil
syn match rustOperator display "&&\|||"
syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustPanic
syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic
syn match rustEscapeError display contained /\\./
syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
syn match rustEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{8}\)/
syn match rustEscapeUnicode display contained /\\u{\x\{1,6}}/
syn match rustStringContinuation display contained /\\\n\s*/
syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation
syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDerive
syn region rustDerive start="derive(" end=")" contained contains=rustTrait
" Number literals
syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(s\|8\|16\|32\|64\)\)\="
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
syn match rustBinNumber display "\<0b[01_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
" Special case for numbers of the form "1." which are float literals, unless followed by
" an identifier, which makes them integer literals with a method call or field access,
" or by another ".", which makes them integer literals followed by the ".." token.
" (This must go first so the others take precedence.)
syn match rustFloat display "\<[0-9][0-9_]*\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\|\.\)\@!"
" To mark a number as a normal float, it must have at least one of the three things integral values don't have:
" a decimal point and more numbers; an exponent; and a type suffix.
syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\="
syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\="
syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"
" For the benefit of delimitMate
syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate
syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
"rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting
syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
syn match rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/
" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).
syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/
syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode
syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\|u{\x\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid
syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell
syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell
syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell
syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell
syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent
syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent
" FIXME: this is a really ugly and not fully correct implementation. Most
" importantly, a case like ``/* */*`` should have the final ``*`` not being in
" a comment, but in practice at present it leaves comments open two levels
" deep. But as long as you stay away from that particular case, I *believe*
" the highlighting is correct. Due to the way Vim's syntax engine works
" (greedy for start matches, unlike Rust's tokeniser which is searching for
" the earliest-starting match, start or end), I believe this cannot be solved.
" Oh you who would fix it, don't bother with things like duplicating the Block
" rules and putting ``\*\@<!`` at the start of them; it makes it worse, as
" then you must deal with cases like ``/*/**/*/``. And don't try making it
" worse with ``\%(/\@<!\*\)\@<!``, either...
syn keyword rustTodo contained TODO FIXME XXX NB NOTE
" Folding rules {{{2
" Trivial folding rules to begin with.
" FIXME: use the AST to make really good folding
syn region rustFoldBraces start="{" end="}" transparent fold
" Default highlighting {{{1
hi def link rustDecNumber rustNumber
hi def link rustHexNumber rustNumber
hi def link rustOctNumber rustNumber
hi def link rustBinNumber rustNumber
hi def link rustIdentifierPrime rustIdentifier
hi def link rustTrait rustType
hi def link rustMacroRepeatCount rustMacroRepeatDelimiters
hi def link rustMacroRepeatDelimiters Macro
hi def link rustMacroVariable Define
hi def link rustSigil StorageClass
hi def link rustEscape Special
hi def link rustEscapeUnicode rustEscape
hi def link rustEscapeError Error
hi def link rustStringContinuation Special
hi def link rustString String
hi def link rustCharacterInvalid Error
hi def link rustCharacterInvalidUnicode rustCharacterInvalid
hi def link rustCharacter Character
hi def link rustNumber Number
hi def link rustBoolean Boolean
hi def link rustEnum rustType
hi def link rustEnumVariant rustConstant
hi def link rustConstant Constant
hi def link rustSelf Constant
hi def link rustFloat Float
hi def link rustOperator Operator
hi def link rustKeyword Keyword
hi def link rustReservedKeyword Error
hi def link rustConditional Conditional
hi def link rustIdentifier Identifier
hi def link rustCapsIdent rustIdentifier
hi def link rustModPath Include
hi def link rustModPathSep Delimiter
hi def link rustFunction Function
hi def link rustFuncName Function
hi def link rustFuncCall Function
hi def link rustCommentLine Comment
hi def link rustCommentLineDoc SpecialComment
hi def link rustCommentBlock rustCommentLine
hi def link rustCommentBlockDoc rustCommentLineDoc
hi def link rustAssert PreCondit
hi def link rustPanic PreCondit
hi def link rustMacro Macro
hi def link rustType Type
hi def link rustTodo Todo
hi def link rustAttribute PreProc
hi def link rustDerive PreProc
hi def link rustStorage StorageClass
hi def link rustObsoleteStorage Error
hi def link rustLifetime Special
hi def link rustInvalidBareKeyword Error
hi def link rustExternCrate rustKeyword
hi def link rustObsoleteExternMod Error
hi def link rustBoxPlacementParens Delimiter
hi def link rustBoxPlacementExpr rustKeyword
" Other Suggestions:
" hi rustAttribute ctermfg=cyan
" hi rustDerive ctermfg=cyan
" hi rustAssert ctermfg=yellow
" hi rustPanic ctermfg=red
" hi rustMacro ctermfg=magenta
syn sync minlines=200
syn sync maxlines=500
let b:current_syntax = "rust"

@ -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")
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 })
call g:SyntasticRegistry.CreateAndRegisterChecker({
\ 'filetype': 'rust',
\ 'name': 'rustc'})
let &cpo = s:save_cpo
unlet s:save_cpo

@ -0,0 +1 @@
Subproject commit 28a989b28457e38df620e4c7ab23e224aff70efe

@ -0,0 +1,36 @@
# Vim Racer Plugin
This plugin allows vim to use [Racer](http://github.com/phildawes/racer) for Rust code completion and navigation.
## Installation
1. Build / Install [Racer](http://github.com/phildawes/racer)
1. Install using Pathogen, Vundle or NeoBundle. Or, copy `plugin/racer.vim` into your `~/.vim/plugin` directory.
Vundle users:
Plugin 'racer-rust/vim-racer'
NeoBundle users:
NeoBundle 'racer-rust/vim-racer'
vim-plug users:
Plug 'racer-rust/vim-racer'
2. Add `g:racer_cmd` and `$RUST_SRC_PATH` variables to your `.vimrc`. Also it's worth turning on 'hidden' mode for buffers otherwise you need to save the current buffer every time you do a goto-definition. E.g.:
set hidden
let g:racer_cmd = "<path-to-racer>/target/release/racer"
let $RUST_SRC_PATH="<path-to-rust-srcdir>/src/"
3. In insert mode use `C-x-C-o` to search for completions
4. In normal mode type `gd` to go to a definition

@ -0,0 +1,196 @@
" Vim plugin for Racer
" (by Phil Dawes)
" 1. Edit the variables below (or override in .vimrc)
" 2. copy this file into .vim/plugin/
" 3. - now in insert mode do 'C-x C-o' to autocomplete the thing at the cursor
" - in normal mode do 'gd' to go to definition
" - 'gD' goes to the definition in a new vertical split
" (This plugin is best used with the 'hidden' option enabled so that switching buffers doesn't force you to save)
if exists('g:loaded_racer')
let g:loaded_racer = 1
let s:save_cpo = &cpo
set cpo&vim
if !exists('g:racer_cmd')
let path = escape(expand('<sfile>:p:h'), '\') . '/../target/release/'
if isdirectory(path)
let s:pathsep = has("win32") ? ';' : ':'
let $PATH .= s:pathsep . path
let g:racer_cmd = 'racer'
if !(executable(g:racer_cmd))
echohl WarningMsg | echomsg "No racer executable found in $PATH (" . $PATH . ")"
if !exists('$RUST_SRC_PATH')
let s:rust_src_default = 1
if isdirectory("/usr/local/src/rust/src")
let $RUST_SRC_PATH="/usr/local/src/rust/src"
if isdirectory("/usr/src/rust/src")
let $RUST_SRC_PATH="/usr/src/rust/src"
if isdirectory("C:\\rust\\src")
let $RUST_SRC_PATH="C:\\rust\\src"
if !isdirectory($RUST_SRC_PATH)
if exists('s:rust_src_default')
echohl WarningMsg | echomsg "No RUST_SRC_PATH environment variable present, nor could default installation be found at: " . $RUST_SRC_PATH
echohl WarningMsg | echomsg "No directory was found at provided RUST_SRC_PATH: " . $RUST_SRC_PATH
if !exists('g:racer_experimental_completer')
let g:racer_experimental_completer = 0
if !exists('g:racer_insert_paren')
let g:racer_insert_paren = 1
function! RacerGetPrefixCol(base)
let col = col(".")-1
let b:racer_col = col
let b:tmpfname = tempname()
call writefile(RacerGetBufferContents(a:base), b:tmpfname)
let cmd = g:racer_cmd." prefix ".line(".")." ".col." ".b:tmpfname
let res = system(cmd)
let prefixline = split(res, "\\n")[0]
let startcol = split(prefixline[7:], ",")[0]
return startcol
function! RacerGetExpCompletions(base)
let col = strlen(getline('.')) + strlen(a:base) " use the column from the previous RacerGetPrefixCol() call, since vim ammends it afterwards
call writefile(RacerGetBufferContents(a:base), b:tmpfname)
let fname = expand("%:p")
let cmd = g:racer_cmd." complete ".line(".")." ".col." ".fname." ".b:tmpfname
let res = system(cmd)
let typeMap = {
\ 'Struct' : 's', 'Module' : 'M', 'Function' : 'f',
\ 'Crate' : 'C', 'Let' : 'v', 'StructField' : 'm',
\ 'Impl' : 'i', 'Enum' : 'e', 'EnumVariant' : 'E',
\ 'Type' : 't', 'FnArg' : 'v', 'Trait' : 'T'
\ }
let lines = split(res, "\\n")
let out = []
for line in lines
if line =~ "^MATCH"
let completions = split(line[6:], ",")
let kind = get(typeMap, completions[4])
let completion = {'kind' : kind, 'word' : completions[0], 'dup':1 }
if kind ==# 'f' " function
let completion['menu'] = substitute(substitute(substitute(join(completions[5:], ','), '\(pub\|fn\) ',"","g"), '{*$', "", ""), ' where\s\?.*$', "", "")
if g:racer_insert_paren == 1
let completion['abbr'] = completions[0]
let completion['word'] .= "("
let completion['info'] = join(completions[5:], ',')
elseif kind ==# 's' " struct
let completion['menu'] = substitute(substitute(join(completions[5:], ','), '\(pub\|struct\) ',"","g"), '{*$', "", "")
let out = add(out, completion)
call delete(b:tmpfname)
return out
function! RacerGetCompletions(base)
let col = strlen(getline('.')) + strlen(a:base) " use the column from the previous RacerGetPrefixCol() call, since vim ammends it afterwards
call writefile(RacerGetBufferContents(a:base), b:tmpfname)