rust.vim 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. " Language: Rust
  2. " Description: Vim ftplugin for Rust
  3. " Maintainer: Chris Morgan <me@chrismorgan.info>
  4. " Last Change: 2024 Mar 17
  5. " 2024 May 23 by Riley Bruins <ribru17@gmail.com ('commentstring')
  6. " 2025 Mar 31 by Vim project (set 'formatprg' option)
  7. " For bugs, patches and license go to https://github.com/rust-lang/rust.vim
  8. if exists("b:did_ftplugin")
  9. finish
  10. endif
  11. let b:did_ftplugin = 1
  12. " vint: -ProhibitAbbreviationOption
  13. let s:save_cpo = &cpo
  14. set cpo&vim
  15. " vint: +ProhibitAbbreviationOption
  16. if get(b:, 'current_compiler', '') ==# ''
  17. if strlen(findfile('Cargo.toml', '.;')) > 0
  18. compiler cargo
  19. else
  20. compiler rustc
  21. endif
  22. endif
  23. " Variables {{{1
  24. " The rust source code at present seems to typically omit a leader on /*!
  25. " comments, so we'll use that as our default, but make it easy to switch.
  26. " This does not affect indentation at all (I tested it with and without
  27. " leader), merely whether a leader is inserted by default or not.
  28. if get(g:, 'rust_bang_comment_leader', 0)
  29. " Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why,
  30. " but without it, */ gets indented one space even if there were no
  31. " leaders. I'm fairly sure that's a Vim bug.
  32. setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,://
  33. else
  34. setlocal comments=s0:/*!,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://
  35. endif
  36. setlocal commentstring=//\ %s
  37. setlocal formatoptions-=t formatoptions+=croqnl
  38. " j was only added in 7.3.541, so stop complaints about its nonexistence
  39. silent! setlocal formatoptions+=j
  40. " smartindent will be overridden by indentexpr if filetype indent is on, but
  41. " otherwise it's better than nothing.
  42. setlocal smartindent nocindent
  43. if get(g:, 'rust_recommended_style', 1)
  44. let b:rust_set_style = 1
  45. setlocal shiftwidth=4 softtabstop=4 expandtab
  46. setlocal textwidth=99
  47. endif
  48. setlocal include=\\v^\\s*(pub\\s+)?use\\s+\\zs(\\f\|:)+
  49. setlocal includeexpr=rust#IncludeExpr(v:fname)
  50. setlocal suffixesadd=.rs
  51. if executable(get(g:, 'rustfmt_command', 'rustfmt'))
  52. if get(g:, "rustfmt_fail_silently", 0)
  53. augroup rust.vim.FailSilently
  54. autocmd! * <buffer>
  55. autocmd ShellFilterPost <buffer> if v:shell_error | execute 'echom "shell filter returned error " . v:shell_error . ", undoing changes"' | undo | endif
  56. augroup END
  57. endif
  58. let &l:formatprg = get(g:, 'rustfmt_command', 'rustfmt') . ' ' .
  59. \ get(g:, 'rustfmt_options', '') . ' ' .
  60. \ rustfmt#RustfmtConfigOptions()
  61. endif
  62. if exists("g:ftplugin_rust_source_path")
  63. let &l:path=g:ftplugin_rust_source_path . ',' . &l:path
  64. endif
  65. if exists("g:loaded_delimitMate")
  66. if exists("b:delimitMate_excluded_regions")
  67. let b:rust_original_delimitMate_excluded_regions = b:delimitMate_excluded_regions
  68. endif
  69. augroup rust.vim.DelimitMate
  70. autocmd!
  71. autocmd User delimitMate_map :call rust#delimitmate#onMap()
  72. autocmd User delimitMate_unmap :call rust#delimitmate#onUnmap()
  73. augroup END
  74. endif
  75. " Integration with auto-pairs (https://github.com/jiangmiao/auto-pairs)
  76. if exists("g:AutoPairsLoaded") && !get(g:, 'rust_keep_autopairs_default', 0)
  77. let b:AutoPairs = {'(':')', '[':']', '{':'}','"':'"', '`':'`'}
  78. endif
  79. if has("folding") && get(g:, 'rust_fold', 0)
  80. let b:rust_set_foldmethod=1
  81. setlocal foldmethod=syntax
  82. if g:rust_fold == 2
  83. setlocal foldlevel<
  84. else
  85. setlocal foldlevel=99
  86. endif
  87. endif
  88. if has('conceal') && get(g:, 'rust_conceal', 0)
  89. let b:rust_set_conceallevel=1
  90. setlocal conceallevel=2
  91. endif
  92. " Motion Commands {{{1
  93. if !exists("g:no_plugin_maps") && !exists("g:no_rust_maps")
  94. " Bind motion commands to support hanging indents
  95. nnoremap <silent> <buffer> [[ :call rust#Jump('n', 'Back')<CR>
  96. nnoremap <silent> <buffer> ]] :call rust#Jump('n', 'Forward')<CR>
  97. xnoremap <silent> <buffer> [[ :call rust#Jump('v', 'Back')<CR>
  98. xnoremap <silent> <buffer> ]] :call rust#Jump('v', 'Forward')<CR>
  99. onoremap <silent> <buffer> [[ :call rust#Jump('o', 'Back')<CR>
  100. onoremap <silent> <buffer> ]] :call rust#Jump('o', 'Forward')<CR>
  101. endif
  102. " Commands {{{1
  103. " See |:RustRun| for docs
  104. command! -nargs=* -complete=file -bang -buffer RustRun call rust#Run(<bang>0, <q-args>)
  105. " See |:RustExpand| for docs
  106. command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -buffer RustExpand call rust#Expand(<bang>0, <q-args>)
  107. " See |:RustEmitIr| for docs
  108. command! -nargs=* -buffer RustEmitIr call rust#Emit("llvm-ir", <q-args>)
  109. " See |:RustEmitAsm| for docs
  110. command! -nargs=* -buffer RustEmitAsm call rust#Emit("asm", <q-args>)
  111. " See |:RustPlay| for docs
  112. command! -range=% -buffer RustPlay :call rust#Play(<count>, <line1>, <line2>, <f-args>)
  113. " See |:RustFmt| for docs
  114. command! -bar -buffer RustFmt call rustfmt#Format()
  115. " See |:RustFmtRange| for docs
  116. command! -range -buffer RustFmtRange call rustfmt#FormatRange(<line1>, <line2>)
  117. " See |:RustInfo| for docs
  118. command! -bar -buffer RustInfo call rust#debugging#Info()
  119. " See |:RustInfoToClipboard| for docs
  120. command! -bar -buffer RustInfoToClipboard call rust#debugging#InfoToClipboard()
  121. " See |:RustInfoToFile| for docs
  122. command! -bar -nargs=1 -buffer RustInfoToFile call rust#debugging#InfoToFile(<f-args>)
  123. " See |:RustTest| for docs
  124. command! -buffer -nargs=* -count -bang RustTest call rust#Test(<q-mods>, <count>, <bang>0, <q-args>)
  125. if !exists("b:rust_last_rustc_args") || !exists("b:rust_last_args")
  126. let b:rust_last_rustc_args = []
  127. let b:rust_last_args = []
  128. endif
  129. " Cleanup {{{1
  130. let b:undo_ftplugin = "
  131. \ compiler make |
  132. \ setlocal formatoptions< comments< commentstring< include< includeexpr< suffixesadd< formatprg<
  133. \|if exists('b:rust_set_style')
  134. \|setlocal tabstop< shiftwidth< softtabstop< expandtab< textwidth<
  135. \|endif
  136. \|if exists('b:rust_original_delimitMate_excluded_regions')
  137. \|let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions
  138. \|unlet b:rust_original_delimitMate_excluded_regions
  139. \|else
  140. \|unlet! b:delimitMate_excluded_regions
  141. \|endif
  142. \|if exists('b:rust_set_foldmethod')
  143. \|setlocal foldmethod< foldlevel<
  144. \|unlet b:rust_set_foldmethod
  145. \|endif
  146. \|if exists('b:rust_set_conceallevel')
  147. \|setlocal conceallevel<
  148. \|unlet b:rust_set_conceallevel
  149. \|endif
  150. \|unlet! b:rust_last_rustc_args b:rust_last_args
  151. \|delcommand -buffer RustRun
  152. \|delcommand -buffer RustExpand
  153. \|delcommand -buffer RustEmitIr
  154. \|delcommand -buffer RustEmitAsm
  155. \|delcommand -buffer RustPlay
  156. \|delcommand -buffer RustFmt
  157. \|delcommand -buffer RustFmtRange
  158. \|delcommand -buffer RustInfo
  159. \|delcommand -buffer RustInfoToClipboard
  160. \|delcommand -buffer RustInfoToFile
  161. \|delcommand -buffer RustTest
  162. \|silent! nunmap <buffer> [[
  163. \|silent! nunmap <buffer> ]]
  164. \|silent! xunmap <buffer> [[
  165. \|silent! xunmap <buffer> ]]
  166. \|silent! ounmap <buffer> [[
  167. \|silent! ounmap <buffer> ]]
  168. \|setlocal matchpairs-=<:>
  169. \|unlet b:match_skip
  170. \"
  171. " }}}1
  172. " Code formatting on save
  173. augroup rust.vim.PreWrite
  174. autocmd!
  175. autocmd BufWritePre *.rs silent! call rustfmt#PreWrite()
  176. augroup END
  177. setlocal matchpairs+=<:>
  178. " For matchit.vim (rustArrow stops `Fn() -> X` messing things up)
  179. let b:match_skip = 's:comment\|string\|rustCharacter\|rustArrow'
  180. command! -buffer -nargs=+ Cargo call cargo#cmd(<q-args>)
  181. command! -buffer -nargs=* Cbuild call cargo#build(<q-args>)
  182. command! -buffer -nargs=* Ccheck call cargo#check(<q-args>)
  183. command! -buffer -nargs=* Cclean call cargo#clean(<q-args>)
  184. command! -buffer -nargs=* Cdoc call cargo#doc(<q-args>)
  185. command! -buffer -nargs=+ Cnew call cargo#new(<q-args>)
  186. command! -buffer -nargs=* Cinit call cargo#init(<q-args>)
  187. command! -buffer -nargs=* Crun call cargo#run(<q-args>)
  188. command! -buffer -nargs=* Ctest call cargo#test(<q-args>)
  189. command! -buffer -nargs=* Cbench call cargo#bench(<q-args>)
  190. command! -buffer -nargs=* Cupdate call cargo#update(<q-args>)
  191. command! -buffer -nargs=* Csearch call cargo#search(<q-args>)
  192. command! -buffer -nargs=* Cpublish call cargo#publish(<q-args>)
  193. command! -buffer -nargs=* Cinstall call cargo#install(<q-args>)
  194. command! -buffer -nargs=* Cruntarget call cargo#runtarget(<q-args>)
  195. let b:undo_ftplugin .= '
  196. \|delcommand -buffer Cargo
  197. \|delcommand -buffer Cbuild
  198. \|delcommand -buffer Ccheck
  199. \|delcommand -buffer Cclean
  200. \|delcommand -buffer Cdoc
  201. \|delcommand -buffer Cnew
  202. \|delcommand -buffer Cinit
  203. \|delcommand -buffer Crun
  204. \|delcommand -buffer Ctest
  205. \|delcommand -buffer Cbench
  206. \|delcommand -buffer Cupdate
  207. \|delcommand -buffer Csearch
  208. \|delcommand -buffer Cpublish
  209. \|delcommand -buffer Cinstall
  210. \|delcommand -buffer Cruntarget'
  211. " vint: -ProhibitAbbreviationOption
  212. let &cpo = s:save_cpo
  213. unlet s:save_cpo
  214. " vint: +ProhibitAbbreviationOption
  215. " vim: set et sw=4 sts=4 ts=8: