vim-lspでruffとpyrightを併用

今までは設定が楽なのでvim-lsp-settings用いてdefaultの形(pylsp-all)を使っていたが、ruffを使うようになってしばらく経つのでちゃんと設定変更することにしたのでメモ

ruffはlint/formatのみに特化する方針と書いてある

The server supports surfacing Ruff diagnostics, providing Code Actions to fix them, and formatting the code using Ruff's built-in formatter. Currently, the server is intended to be used alongside another Python Language Server in order to support features like navigation and autocompletion.

https://docs.astral.sh/ruff/editors/#language-server-protocol

というわけでcompletionには別のものを入れる必要があり、以下の理由によりpyrightにした

  • 最近はpyrightがよく使われている模様(特にvscodeで)
  • ちょっと動かしてみたら定義へのジャンプ動作が体感としてpylspより速い
  • type checkに対応している(というかそれがメイン)なのでmypyも置き換えられる

最近はneovimを使うのがほとんどなのでvimへの対応はなくしてしまってもよいものの、vim-lsp-settingsが設定要らずで便利なのでそこは変えない。

ちなみにruff-lspの機能はruff 0.5.3以降はruff自体に組み込まれたとのことなのでruff-lspは使わない
https://github.com/astral-sh/ruff-lsp

2つのlspを同時に起動する

ruffとpyright-language-serverをそれぞれLspInstallServerで入れてnvimを起動し直しても両方は起動してくれないようだったため、filetypeがpythonの際に使うlspを設定で明示したところ問題なく起動した

let g:lsp_settings_filetype_python = ['ruff', 'pyright-langserver']

lspの設定

pyrightではlint/format以外のことをやってほしいので重複する機能はoffにしておきたい

その話をしてるissue
https://github.com/astral-sh/ruff-lsp/issues/384#issuecomment-1941556771
type checkはoffになってほしくないのでignoreは入れない

pyrightのdiagnosticsのデフォルト設定はこちらにある通り
https://microsoft.github.io/pyright/#/configuration?id=diagnostic-settings-defaults
今のところ厳密にruffのものだけ出てほしいわけではないため、今後邪魔なものが見つかったら個別に設定を入れて対応

その他の設定はここにあるのでdefaultが明示されてなくて必要そうなものだけ入れておく
https://microsoft.github.io/pyright/#/configuration?id=type-check-diagnostics-settings

let g:lsp_settings = {
\  'pyright-langserver': {
\    'workspace_config': {
\      'python': {
\        'disableOrganizeImports': v:true,
\        'analysis': {
\          'autoSearchPaths': v:true,
\        }
\      }
\    }
\  },

ruffのhoverをoff

ruffはhoverの機能には対応しているものの、vim-lspで用いられる形とは異なるために邪魔になるとのことでdocsにある設定を入れておく
https://docs.astral.sh/ruff/editors/setup/#vim
https://github.com/astral-sh/ruff/issues/11719

capabilityをoffにする設定を入れておかないと、hoverさせようとした際にruffでは対応してないというエラーで動かない

function! s:on_lsp_buffer_enabled() abort
  let l:capabilities = lsp#get_server_capabilities('ruff')
  if !empty(l:capabilities)
    let l:capabilities.hoverProvider = v:false
  endif
endfunction
augroup lsp_install
     au!
     autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END

後半のautocmd部分はvim-lspのhelpにあるものをそのまま持ってきただけ

まとめ

結果的に設定全体はこうなる

[[plugins]]
repo = 'mattn/vim-lsp-settings'
hook_add = '''
  let g:lsp_settings_filetype_python = ['ruff', 'pyright-langserver']
  let g:lsp_settings = {
  \  'pyright-langserver': {
  \    'workspace_config': {
  \      'python': {
  \        'disableOrganizeImports': v:true,
  \        'analysis': {
  \          'autoSearchPaths': v:true,
  \        }
  \      }
  \    }
  \  }
  \}
  function! s:on_lsp_buffer_enabled() abort
    let l:capabilities = lsp#get_server_capabilities('ruff')
    if !empty(l:capabilities)
      let l:capabilities.hoverProvider = v:false
    endif
  endfunction
   augroup lsp_install
        au!
        autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
   augroup END
'''

追記

python以外のファイルを開いた際にruffが存在しなくてエラーになる https://github.com/prabirshrestha/vim-lsp/blob/04428c920002ac7cfacbecacb070a8af57b455d0/autoload/lsp.vim#L111

このちょっと上に有効なkeyかを判定する関数があったのでこれを使っておく https://github.com/prabirshrestha/vim-lsp/blob/04428c920002ac7cfacbecacb070a8af57b455d0/autoload/lsp.vim#L98-L100

  function! s:on_lsp_buffer_enabled() abort
    if lsp#is_valid_server_name('ruff')
      let l:capabilities = lsp#get_server_capabilities('ruff')
      if !empty(l:capabilities)
        let l:capabilities.hoverProvider = v:false
      endif
    endif
  endfunction