Skip to content

Commit

Permalink
auto merge of #7665 : chris-morgan/rust/better-vim-support, r=cmr
Browse files Browse the repository at this point in the history
General tweaks for Vim support, especially proper indenting.
  • Loading branch information
bors committed Jul 9, 2013
2 parents 62bb843 + 121ae82 commit 0a1fc45
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 14 deletions.
25 changes: 25 additions & 0 deletions src/etc/vim/ftplugin/rust.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
" Vim syntax file
" Language: Rust
" Maintainer: Chris Morgan <[email protected]>
" Last Change: 2013 Jul 6

if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1

setlocal comments=s1:/*,mb:*,ex:*/,:///,://!,://
setlocal commentstring=//%s
setlocal formatoptions-=t formatoptions+=croqnlj

" 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

let b:undo_ftplugin = "setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd<"
132 changes: 129 additions & 3 deletions src/etc/vim/indent/rust.vim
Original file line number Diff line number Diff line change
@@ -1,11 +1,137 @@
" Vim indent file
" Language: Rust
" Author: Chris Morgan <[email protected]>
" Last Change: 2013 Jul 10

" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
finish
endif

let b:did_indent = 1

setlocal cindent
setlocal cinoptions=L0,(0,Ws,JN
setlocal cinkeys=0{,0},!^F,o,O
setlocal cinkeys=0{,0},!^F,o,O,0[,0]
" Don't think cinwords will actually do anything at all... never mind
setlocal cinwords=do,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 GetRustIndent(lnum)

" Starting assumption: cindent (called at the end) will do it right
" normally. We just want to fix up a few cases.

if has('syntax_items')
if synIDattr(synID(a:lnum, 1, 1), "name") == "rustString"
" If the start of the line is in a string, don't change the indent
return -1
elseif synIDattr(synID(a:lnum, 1, 1), "name") =~ "\\(Comment\\|Todo\\)"
\ && getline(a:lnum) !~ "^\\s*/\\*"
" 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 prevline = s:get_line_trimmed(prevnonblank(a:lnum - 1))
if prevline[len(prevline) - 1] == ","
\ && s:get_line_trimmed(a:lnum) !~ "^\\s*[\\[\\]{}]"
" Oh ho! The previous line ended in a comma! I bet cindent will try to
" take this too far... For now, let's use the previous line's indent
return GetRustIndent(a:lnum - 1)
endif

" cindent 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)

let line = getline(a:lnum)
call cursor(a:lnum, 1)
if searchpair('{\|(', '', '}\|)', 'nbW') == 0
if searchpair('\[', '', '\]', 'nbW') == 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

" Fall back on cindent, which does it mostly right
return cindent(a:lnum)
endfunction
30 changes: 19 additions & 11 deletions src/etc/vim/syntax/rust.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
" Language: Rust
" Maintainer: Patrick Walton <[email protected]>
" Maintainer: Ben Blum <[email protected]>
" Last Change: 2013 Jun 14
" Maintainer: Chris Morgan <[email protected]>
" Last Change: 2013 Jul 10

if version < 600
syntax clear
Expand All @@ -13,8 +14,8 @@ endif
syn keyword rustConditional match if else
syn keyword rustOperator as

syn match rustAssert "\<assert\(\w\)*!"
syn match rustFail "\<fail\(\w\)*!"
syn match rustAssert "\<assert\(\w\)*!" contained
syn match rustFail "\<fail\(\w\)*!" contained
syn keyword rustKeyword break copy do extern
syn keyword rustKeyword for if impl let log
syn keyword rustKeyword copy do extern
Expand Down Expand Up @@ -90,7 +91,7 @@ syn match rustFormat display "%%" contained
syn region rustString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=rustTodo,rustFormat

syn region rustAttribute start="#\[" end="\]" contains=rustString,rustDeriving
syn region rustDeriving start="deriving(" end=")" contains=rustTrait
syn region rustDeriving start="deriving(" end=")" contained contains=rustTrait

" Number literals
syn match rustNumber display "\<[0-9][0-9_]*\>"
Expand All @@ -116,13 +117,18 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9
syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'"

syn region rustCommentDoc start="/\*[\*!]" end="\*/"
syn region rustCommentDoc start="//[/!]" skip="\\$" end="$" keepend
syn match rustComment "/\*\*/"
syn region rustComment start="/\*\([^\*!]\|$\)" end="\*/" contains=rustTodo
syn region rustComment start="//\([^/!]\|$\)" skip="\\$" end="$" contains=rustTodo keepend
syn region rustComment start="/\*" end="\*/" contains=rustTodo
syn region rustComment start="//" skip="\\$" end="$" contains=rustTodo keepend
syn region rustCommentDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
syn region rustCommentDoc start="//[/!]" skip="\\$" end="$" contains=rustTodo keepend

syn keyword rustTodo contained TODO FIXME XXX NB
syn keyword rustTodo contained TODO FIXME XXX NB NOTE

" Trivial folding rules to begin with.
" TODO: use the AST to make really good folding
syn region rustFoldBraces start="{" end="}" transparent fold
" If you wish to enable this, setlocal foldmethod=syntax
" It's not enabled by default as it would drive some people mad.

hi def link rustHexNumber rustNumber
hi def link rustBinNumber rustNumber
Expand All @@ -142,10 +148,13 @@ hi def link rustKeyword Keyword
hi def link rustConditional Conditional
hi def link rustIdentifier Identifier
hi def link rustModPath Include
hi def link rustModPathSep Delimiter
hi def link rustFuncName Function
hi def link rustFuncCall Function
hi def link rustCommentDoc SpecialComment
hi def link rustComment Comment
hi def link rustAssert PreCondit
hi def link rustFail PreCondit
hi def link rustMacro Macro
hi def link rustType Type
hi def link rustTodo Todo
Expand All @@ -160,7 +169,6 @@ hi def link rustLifetime Special
" hi rustAssert ctermfg=yellow
" hi rustFail ctermfg=red
" hi rustMacro ctermfg=magenta
" hi rustModPathSep ctermfg=grey

syn sync minlines=200
syn sync maxlines=500
Expand Down

0 comments on commit 0a1fc45

Please sign in to comment.