Skip to content

Commit f8b6893

Browse files
committed
Merge pull request rust-lang#52 from IanConnolly/feature/rustfmt
Integrate with rustfmt
2 parents 95f2b2a + 15081c8 commit f8b6893

File tree

5 files changed

+137
-3
lines changed

5 files changed

+137
-3
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Description
44

5-
This is a vim plugin that provides [Rust][r] file detection and syntax highlighting.
5+
This is a vim plugin that provides [Rust][r] file detection, syntax highlighting, and (optional) autoformatting.
66

77
## Installation
88

@@ -31,3 +31,12 @@ git clone --depth=1 https://github.com/rust-lang/rust.vim.git ~/.vim/bundle/rust
3131

3232
1. Add `NeoBundle 'rust-lang/rust.vim'` to `~/.vimrc`
3333
2. Re-open vim or execute `:source ~/.vimrc`
34+
35+
## Enabling autoformat
36+
37+
This plugin can optionally format your code using [rustfmt][rfmt] every time a
38+
buffer is written. Simple put `let g:rustfmt_autosave = 1` in your `.vimrc`.
39+
40+
## Help
41+
42+
Further help can be found in the documentation with `:help rust`.

autoload/rustfmt.vim

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
" Author: Stephen Sugden <[email protected]>
2+
"
3+
" Adapted from https://github.com/fatih/vim-go
4+
5+
if !exists("g:rustfmt_autosave")
6+
let g:rustfmt_autosave = 0
7+
endif
8+
9+
if !exists("g:rustfmt_command")
10+
let g:rustfmt_command = "rustfmt"
11+
endif
12+
13+
if !exists("g:rustfmt_options")
14+
let g:rustfmt_options = ""
15+
endif
16+
17+
if !exists("g:rustfmt_fail_silently")
18+
let g:rustfmt_fail_silently = 0
19+
endif
20+
21+
let s:got_fmt_error = 0
22+
23+
function! rustfmt#Format()
24+
let l:curw = winsaveview()
25+
let l:tmpname = expand("%:p:h") . "/." . expand("%:p:t") . ".rustfmt"
26+
call writefile(getline(1, '$'), l:tmpname)
27+
28+
let command = g:rustfmt_command . " --write-mode=overwrite "
29+
30+
let out = systemlist(command . g:rustfmt_options . " " . shellescape(l:tmpname))
31+
32+
if v:shell_error == 0
33+
" remove undo point caused via BufWritePre
34+
try | silent undojoin | catch | endtry
35+
36+
" Replace current file with temp file, then reload buffer
37+
call rename(l:tmpname, expand('%'))
38+
silent edit!
39+
let &syntax = &syntax
40+
41+
" only clear location list if it was previously filled to prevent
42+
" clobbering other additions
43+
if s:got_fmt_error
44+
let s:got_fmt_error = 0
45+
call setloclist(0, [])
46+
lwindow
47+
endif
48+
elseif g:rustfmt_fail_silently == 0
49+
" otherwise get the errors and put them in the location list
50+
let errors = []
51+
52+
for line in out
53+
" src/lib.rs:13:5: 13:10 error: expected `,`, or `}`, found `value`
54+
let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\):\s*\(\d\+:\d\+\s*\)\?\s*error: \(.*\)')
55+
if !empty(tokens)
56+
call add(errors, {"filename": @%,
57+
\"lnum": tokens[2],
58+
\"col": tokens[3],
59+
\"text": tokens[5]})
60+
endif
61+
endfor
62+
63+
if empty(errors)
64+
% | " Couldn't detect rustfmt error format, output errors
65+
endif
66+
67+
if !empty(errors)
68+
call setloclist(0, errors, 'r')
69+
echohl Error | echomsg "rustfmt returned error" | echohl None
70+
endif
71+
72+
let s:got_fmt_error = 1
73+
lwindow
74+
" We didn't use the temp file, so clean up
75+
call delete(l:tmpname)
76+
endif
77+
78+
call winrestview(l:curw)
79+
endfunction

doc/rust.txt

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,37 @@ g:ftplugin_rust_source_path~
8888
let g:ftplugin_rust_source_path = $HOME.'/dev/rust'
8989
<
9090

91-
*g:cargo_manifest_name*
91+
*g:cargo_manifest_name*
9292
g:cargo_manifest_name~
9393
Set this option to the name of the manifest file for your projects. If
9494
not specified it defaults to 'Cargo.toml' : >
95-
let g:cargo_manifest_name = 'Cargo.toml'
95+
let g:cargo_manifest_name = 'Cargo.toml'
96+
<
97+
98+
*g:rustfmt_command*
99+
g:rustfmt_command~
100+
Set this option to the name of the 'rustfmt' executable in your $PATH. If
101+
not specified it defaults to 'rustfmt' : >
102+
let g:rustfmt_command = 'rustfmt'
103+
<
104+
*g:rustfmt_autosave*
105+
g:rustfmt_autosave~
106+
Set this option to 1 to run |:RustFmt| automatically when saving a
107+
buffer. If not specified it defaults to 0 : >
108+
let g:rustfmt_autosave = 0
109+
<
110+
*g:rustfmt_fail_silently*
111+
g:rustfmt_fail_silently~
112+
Set this option to 1 to prevent 'rustfmt' from populating the
113+
|location-list| with errors. If not specified it defaults to 0: >
114+
let g:rustfmt_fail_silently = 0
115+
<
116+
*g:rustfmt_options*
117+
g:rustfmt_options~
118+
Set this option to a string of options to pass to 'rustfmt'. The
119+
write-mode is already set to 'overwrite'. If not specified it
120+
defaults to '' : >
121+
let g:rustmft_options = ''
96122
<
97123

98124
*g:rust_playpen_url*
@@ -183,6 +209,15 @@ COMMANDS *rust-commands*
183209
|g:rust_shortener_url| is the base url for the shorterner, by
184210
default "https://is.gd/"
185211

212+
:RustFmt *:RustFmt*
213+
Runs |g:rustfmt_command| on the current buffer. If
214+
|g:rustfmt_options| is set then those will be passed to the
215+
executable.
216+
217+
If |g:rustfmt_fail_silently| is 0 (the default) then it
218+
will populate the |location-list| with the errors from
219+
|g:rustfmt_command|. If |g:rustfmt_fail_silently| is set to 1
220+
then it will not populate the |location-list|.
186221

187222
==============================================================================
188223
MAPPINGS *rust-mappings*

ftplugin/rust.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ command! -nargs=* -buffer RustEmitAsm call rust#Emit("asm", <q-args>)
109109
" See |:RustPlay| for docs
110110
command! -range=% RustPlay :call rust#Play(<count>, <line1>, <line2>, <f-args>)
111111

112+
" See |:RustFmt| for docs
113+
command! -buffer RustFmt call rustfmt#Format()
114+
112115
" Mappings {{{1
113116

114117
" Bind ⌘R in MacVim to :RustRun

plugin/rustfmt.vim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
augroup rustfmt
2+
autocmd!
3+
4+
" code formatting on save
5+
if get(g:, "rustfmt_autosave", 0)
6+
autocmd BufWritePre *.rs call rustfmt#Format()
7+
endif
8+
augroup END

0 commit comments

Comments
 (0)