summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxs <xs@xs.local>2026-11-05 10:45:29 +0800
committerxs <xs@xs.local>2026-11-05 10:45:32 +0800
commit71053fa5e61b08381ef940db338ec6dcf7ab2909 (patch)
tree5fffcf5fd2eb5a1f5ad8f7e6d45d0877cc6153ed
parentbbe55a3f647f07a6b7c9852a499c45d03ac068af (diff)
vimrc: standalone .rs files via detachedFiles, added at server start
A .rs file that is a target of its nearest Cargo.toml uses that crate; any other .rs file is loaded standalone via detachedFiles with checkOnSave off (cargo check needs a Cargo.toml).
-rw-r--r--core/vimrc84
1 files changed, 31 insertions, 53 deletions
diff --git a/core/vimrc b/core/vimrc
index 017e754..22b6b41 100644
--- a/core/vimrc
+++ b/core/vimrc
@@ -186,75 +186,53 @@ endif
186let g:gitgutter_sign_column_always = 0 186let g:gitgutter_sign_column_always = 0
187 187
188 188
189" rust-analyzer root: nearest Cargo.toml dir only if this file is a target of that crate 189" rust-analyzer: a file that is a target of its nearest Cargo.toml (src/ examples/ tests/
190" (src/ examples/ tests/ benches/ build.rs, or its path appears in the manifest); else the 190" benches/ build.rs, or its path is in the manifest) uses that crate. Any other .rs file is
191" file's own dir, so rust-analyzer loads it standalone (std resolves) instead of detached-in-a-foreign-project 191" loaded standalone via detachedFiles, with checkOnSave off (cargo check needs a Cargo.toml).
192" RustCrate(): crate dir if this buffer is a target of its nearest Cargo.toml, else ''
193function! RustCrate() abort 192function! RustCrate() abort
194 let l:p = expand('%:p') 193 let l:p = expand('%:p')
195 let l:d = lsp#utils#find_nearest_parent_file_directory(l:p, 'Cargo.toml') 194 let l:d = lsp#utils#find_nearest_parent_file_directory(l:p, 'Cargo.toml')
196 if !empty(l:d) 195 if empty(l:d) | return '' | endif
197 let l:d = substitute(fnamemodify(l:d, ':p'), '/$', '', '') 196 let l:d = substitute(fnamemodify(l:d, ':p'), '/$', '', '')
198 let l:rel = stridx(l:p, l:d . '/') == 0 ? l:p[len(l:d) + 1:] : '' 197 let l:rel = stridx(l:p, l:d . '/') == 0 ? l:p[len(l:d) + 1:] : ''
199 let l:target = l:rel =~# '^\(src\|examples\|tests\|benches\)/' || l:rel ==# 'build.rs' 198 if l:rel =~# '^\(src\|examples\|tests\|benches\)/\|^build\.rs$'
200 if !l:target && !empty(l:rel) 199 \ || (!empty(l:rel) && stridx(join(readfile(l:d . '/Cargo.toml')), '"' . l:rel . '"') >= 0)
201 let l:target = stridx(join(readfile(l:d . '/Cargo.toml'), "\n"), '"' . l:rel . '"') >= 0 200 return l:d
202 endif
203 if l:target
204 return l:d
205 endif
206 endif 201 endif
207 return '' 202 return ''
208endfunction 203endfunction
204function! s:RustAddDetached() abort
205 let l:p = expand('%:p')
206 if empty(l:p) || index(g:ra_init.detachedFiles, l:p) >= 0 | return 0 | endif
207 call add(g:ra_init.detachedFiles, l:p)
208 return 1
209endfunction
210" Called once at server start (root_uri is read just before the init options).
209function! RustRoot() abort 211function! RustRoot() abort
210 let l:c = RustCrate() 212 let l:c = RustCrate()
211 return empty(l:c) ? expand('%:p:h') : l:c 213 let g:ra_init.checkOnSave = empty(l:c) ? v:false : v:true
214 if !empty(l:c) | return l:c | endif
215 call s:RustAddDetached()
216 return expand('%:p:h')
212endfunction 217endfunction
213" Standalone .rs files (no owning crate) must be listed in rust-analyzer's detachedFiles,
214" else it loads nothing for them (no gd/completion). The list is shared by reference with
215" the init options below (covers the first file) and pushed as config for later files.
216let g:ra_detached = []
217" checkOnSave runs `cargo check` on the file, which needs nightly -Zscript for a file with
218" no Cargo.toml; RustDetach turns it off when the server starts on a standalone file.
219let g:ra_init = { 218let g:ra_init = {
220 \ 'completion': { 219 \ 'completion': {'autoimport': {'enable': v:true}, 'postfix': {'enable': v:true}},
221 \ 'autoimport': { 'enable': v:true }, 220 \ 'checkOnSave': v:true, 'detachedFiles': []}
222 \ 'postfix': { 'enable': v:true },
223 \ },
224 \ 'checkOnSave': v:true,
225 \ 'detachedFiles': g:ra_detached,
226 \ }
227function! RustDetach() abort
228 if !exists('g:lsp_loaded')
229 return
230 endif
231 let l:p = expand('%:p')
232 if empty(l:p) || !empty(RustCrate()) || index(g:ra_detached, l:p) >= 0
233 return
234 endif
235 call add(g:ra_detached, l:p)
236 if lsp#get_server_status('rust-analyzer') !~# '^\(running\|starting\)$'
237 let g:ra_init['checkOnSave'] = v:false
238 endif
239 if lsp#get_server_status('rust-analyzer') ==# 'running'
240 call lsp#update_workspace_config('rust-analyzer', {'rust-analyzer': {'detachedFiles': copy(g:ra_detached)}})
241 endif
242endfunction
243augroup rust_detached 221augroup rust_detached
244 au! 222 au!
245 au BufEnter *.rs call RustDetach() 223 " standalone file opened while the server already runs: add it live (check setting untouched)
224 au BufEnter *.rs if exists('g:lsp_loaded') && lsp#get_server_status('rust-analyzer') ==# 'running'
225 \ && empty(RustCrate()) && s:RustAddDetached()
226 \ | call lsp#update_workspace_config('rust-analyzer', {'rust-analyzer': g:ra_init}) | endif
246augroup END 227augroup END
247
248" rust-analyzer via the rustup proxy shim (portable across toolchains/machines) 228" rust-analyzer via the rustup proxy shim (portable across toolchains/machines)
249if executable(expand('~/.cargo/bin/rust-analyzer')) 229if executable(expand('~/.cargo/bin/rust-analyzer'))
250 au User lsp_setup call lsp#register_server({ 230 au User lsp_setup call lsp#register_server({
251 \ 'name': 'rust-analyzer', 231 \ 'name': 'rust-analyzer', 'allowlist': ['rust'],
252 \ 'cmd': {server_info -> [expand('~/.cargo/bin/rust-analyzer')]}, 232 \ 'cmd': {server_info -> [expand('~/.cargo/bin/rust-analyzer')]},
253 \ 'allowlist': ['rust'], 233 \ 'root_uri': {server_info -> lsp#utils#path_to_uri(RustRoot())},
254 \ 'root_uri': {server_info -> lsp#utils#path_to_uri(RustRoot())}, 234 \ 'initialization_options': g:ra_init,
255 \ 'initialization_options': g:ra_init, 235 \ 'workspace_config': {'rust-analyzer': g:ra_init}})
256 \ 'workspace_config': {'rust-analyzer': {'detachedFiles': g:ra_detached}},
257 \ })
258endif 236endif
259if executable(expand('~/.local/bin/ruff')) 237if executable(expand('~/.local/bin/ruff'))
260 au User lsp_setup call lsp#register_server({ 238 au User lsp_setup call lsp#register_server({