diff options
| -rw-r--r-- | core/vimrc | 84 |
1 files changed, 31 insertions, 53 deletions
| @@ -186,75 +186,53 @@ endif | |||
| 186 | let g:gitgutter_sign_column_always = 0 | 186 | let 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 '' | ||
| 193 | function! RustCrate() abort | 192 | function! 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 '' |
| 208 | endfunction | 203 | endfunction |
| 204 | function! 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 | ||
| 209 | endfunction | ||
| 210 | " Called once at server start (root_uri is read just before the init options). | ||
| 209 | function! RustRoot() abort | 211 | function! 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') | ||
| 212 | endfunction | 217 | endfunction |
| 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. | ||
| 216 | let 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. | ||
| 219 | let g:ra_init = { | 218 | let 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 | \ } | ||
| 227 | function! 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 | ||
| 242 | endfunction | ||
| 243 | augroup rust_detached | 221 | augroup 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 | ||
| 246 | augroup END | 227 | augroup 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) |
| 249 | if executable(expand('~/.cargo/bin/rust-analyzer')) | 229 | if 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 | \ }) | ||
| 258 | endif | 236 | endif |
| 259 | if executable(expand('~/.local/bin/ruff')) | 237 | if executable(expand('~/.local/bin/ruff')) |
| 260 | au User lsp_setup call lsp#register_server({ | 238 | au User lsp_setup call lsp#register_server({ |
