1
0
mirror of https://github.com/amix/vimrc synced 2025-10-14 16:53:35 +08:00

Add plugins for Rust support.

This commit is contained in:
Isaac Andrade
2016-02-05 00:52:39 -07:00
parent 7187161032
commit a0d57ea14e
17 changed files with 1565 additions and 0 deletions

View File

@ -0,0 +1 @@
*.pyc

View File

@ -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

View File

@ -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')
finish
endif
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
endif
let g:racer_cmd = 'racer'
if !(executable(g:racer_cmd))
echohl WarningMsg | echomsg "No racer executable found in $PATH (" . $PATH . ")"
endif
endif
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"
endif
if isdirectory("/usr/src/rust/src")
let $RUST_SRC_PATH="/usr/src/rust/src"
endif
if isdirectory("C:\\rust\\src")
let $RUST_SRC_PATH="C:\\rust\\src"
endif
endif
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
else
echohl WarningMsg | echomsg "No directory was found at provided RUST_SRC_PATH: " . $RUST_SRC_PATH
endif
endif
if !exists('g:racer_experimental_completer')
let g:racer_experimental_completer = 0
endif
if !exists('g:racer_insert_paren')
let g:racer_insert_paren = 1
endif
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
endfunction
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'] .= "("
endif
let completion['info'] = join(completions[5:], ',')
elseif kind ==# 's' " struct
let completion['menu'] = substitute(substitute(join(completions[5:], ','), '\(pub\|struct\) ',"","g"), '{*$', "", "")
endif
let out = add(out, completion)
endif
endfor
call delete(b:tmpfname)
return out
endfunction
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)
let fname = expand("%:p")
let cmd = g:racer_cmd." complete ".line(".")." ".col." ".fname." ".b:tmpfname
let res = system(cmd)
let lines = split(res, "\\n")
let out = []
for line in lines
if line =~ "^MATCH"
let completion = split(line[6:], ",")[0]
let out = add(out, completion)
endif
endfor
call delete(b:tmpfname)
return out
endfunction
function! RacerGoToDefinition()
let col = col(".")-1
let b:racer_col = col
let fname = expand("%:p")
let tmpfname = tempname()
call writefile(getline(1, '$'), tmpfname)
let cmd = g:racer_cmd." find-definition ".line(".")." ".col." ".fname." ".tmpfname
let res = system(cmd)
let lines = split(res, "\\n")
for line in lines
if line =~ "^MATCH"
let linenum = split(line[6:], ",")[1]
let colnum = split(line[6:], ",")[2]
let fname = split(line[6:], ",")[3]
call RacerJumpToLocation(fname, linenum, colnum)
break
endif
endfor
call delete(tmpfname)
endfunction
function! RacerGetBufferContents(base)
" Re-combine the completion base word from omnicomplete with the current
" line contents. Since the base word gets remove from the buffer before
" this function is invoked we have to put it back in to out tmpfile.
let col = col(".")-1
let buf_lines = getline(1, '$')
let line_contents = getline('.')
let buf_lines[line('.') - 1] = strpart(line_contents, 0, col).a:base.strpart(line_contents, col, len(line_contents))
return buf_lines
endfunction
function! RacerJumpToLocation(filename, linenum, colnum)
if(a:filename != '')
" Record jump mark
normal! m`
if a:filename != bufname('%')
exec 'keepjumps e ' . fnameescape(a:filename)
endif
call cursor(a:linenum, a:colnum+1)
" Center definition on screen
normal! zz
endif
endfunction
function! RacerComplete(findstart, base)
if a:findstart
return RacerGetPrefixCol(a:base)
else
if g:racer_experimental_completer == 1
return RacerGetExpCompletions(a:base)
else
return RacerGetCompletions(a:base)
endif
endif
endfunction
autocmd FileType rust setlocal omnifunc=RacerComplete
autocmd FileType rust nnoremap <buffer>gd :call RacerGoToDefinition()<cr>
autocmd FileType rust nnoremap <buffer>gD :vsplit<cr>:call RacerGoToDefinition()<cr>
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,103 @@
#=============================================================================
# FILE: racer.py
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
# License: MIT license {{{
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# }}}
#=============================================================================
import re
import os
import subprocess
from .base import Base
class Source(Base):
def __init__(self, vim):
Base.__init__(self, vim)
self.name = 'racer'
self.mark = '[racer]'
self.filetypes = ['rust']
self.input_pattern = r'(\.|::)\w*'
self.__executable_racer = self.vim.funcs.executable(
self.vim.eval('g:racer_cmd'))
self.__racer = self.vim.eval('g:racer_cmd')
self.__encoding = self.vim.eval('&encoding')
def get_complete_position(self, context):
if not self.__executable_racer:
return -1
results = self.get_results('prefix', self.vim.funcs.col('.'))
if not results:
return -1
prefixline = results[0]
return int(prefixline[7:].split(',')[0])
def gather_candidates(self, context):
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'
}
candidates = []
insert_paren = int(self.vim.eval('g:racer_insert_paren'))
for line in [l[6:] for l
in self.get_results('complete-with-snippet',
context['complete_position'] + 1)
if l.startswith('MATCH')]:
completions = line.split(';', 6)
kind = typeMap[completions[5]]
completion = { 'kind': kind, 'word': completions[0], 'dup': 1 }
if kind == 'f': # function
completion['menu'] = completions[6].replace(
'pub ', '').replace('fn ', '').rstrip('{')
if ' where ' in completion['menu'] or completion[
'menu'].endswith(' where') :
where = completion['menu'].rindex(' where')
completion['menu'] = completion['menu'][: where]
if insert_paren:
completion['abbr'] = completions[0]
completion['word'] += '('
elif kind == 's' : # struct
completion['menu'] = completions[6].replace(
'pub ', '').replace( 'struct ', '').rstrip('{')
candidates.append(completion)
return candidates
def get_results(self, command, col):
temp = self.vim.funcs.tempname()
with open(temp, 'w') as f:
for l in self.vim.current.buffer:
f.write(l + "\n")
try:
results = subprocess.check_output([
self.__racer, command,
str(self.vim.funcs.line('.')),
str(col - 1),
temp
]).decode(self.__encoding).splitlines()
except subprocess.CalledProcessError:
return []
finally:
os.remove(temp)
return results