Vimの補完プラグインをインストール。その2

Vimでpython-language-serverが動くようになりましたが、もう一つの本題が、いまいじってるvimrcをサポートしてくれるvim-language-server。これがnpmモジュールなんですね、実は。だって自分はTypeScript使わないから、npmもインストールしたくないし。なので、すでにDenoをインストールしているので、このvim-language-server(長いからvimlsにします)をDenoで使えないか、というあたりを攻めてみます。

Dinoは1.25以降でnpmモジュールをサポートするようになったということで、ちょっとこちらの解説を見ても今ひとつピンとこないのですが、要するにimport文やrunコマンドでnpmモジュールを指定することで、npm install相当のことをやってくれて実行できる、ということのようです。

$ pacman -Qs deno
local/deno 1.46.2-1
    A secure runtime for JavaScript and TypeScript
$ deno run npm:vim-language-server --help
✅ Granted env access to "XDG_RUNTIME_DIR".
✅ Granted sys access to "cpus".
error: Uncaught Error: Connection input stream is not set. Use arguments of createConnection or set command line parameters: '--node-ipc', '--stdio' or '--socket={number}'
(スタックトレースは省略)
$ deno run npm:vim-language-server --stdio
✅ Granted env access to "XDG_RUNTIME_DIR".
✅ Granted sys access to "cpus".

実際にはvimlsの他にstreamモジュールも必要だったので、コマンドラインからインストールしています。

$ deno
Deno 1.46.3
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
> import "npm:stream"
[Module: null prototype] {
  default: <ref *1> [Function: Stream] { Stream: [Circular *1] }
}
>

importするだけでインストールしてくれるので、楽ちん。もっとも、pacmanを使わないので、アップデートはどうするんだろうとかありますが。"npm:stream@0.0.3"とかするとバージョン指定できるので、それでやるのかな。ちなみにnpmモジュールは${XDG_CACHE_HOME}/deno/npm/registry.npmjs.org/の下にダウンロードされるようです。ついでに言えば、globalインストールする方法は調べてません。

それでは、vimlsをDenoで起動してみます。

$ deno run npm:vim-language-server
┏ ⚠️  Deno requests env access to "XDG_RUNTIME_DIR".
┠─ Learn more at: https://docs.deno.com/go/--allow-env
┠─ Run again with --allow-env to bypass this prompt.
┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) >

なんか許可するかどうするか聞いてきました。

Denoはセキュリティ強化の観点で、環境変数やファイルへのアクセス許可、実行許可などなど、いろいろ聞いてきます。vimlsは裏で起動してくれないと困るので、プロンプトを出さないようにするためにはオプション指定が必要です。-A を指定すると、全部まとめて許可!とかやってくれるみたいですが、推奨は個別指定なので、以下のようにしました。

$ deno run --allow-sys --allow-env --allow-read --allow-run npm:vim-language-server --stdio

--allow-readと--allow-runはvim-lspから起動されるときに必要になります。またvimlsは通信方法を指定しなくてはいけないので、--stdioを指定しています。上記のコマンドで起動すると、標準入力からの入力待ちになります。ということで起動まではOK。

vimlsの起動方法がわかったので、vimrcに設定していきます。

その1ではPythonの設定をしたのでそこから始めますが、それに先立って Neovim のCheckHealthと同等のチェックをしてくれるvim-healthcheckをインストールしておきます。language serversの状態も表示してくれるので、動いているかどうかの確認は簡単にできます。

call dein#add('rhysd/vim-healthcheck')

次に、vim-lspからlsp#regster_serverに食わせるために起動コマンドを記述するのですが、どうもnpmでvimlsをインストールした場合には vim-language-server というシンボリックリンクを作成してそれを起動しているみたいです。今回はDenoから起動する必要があるので、~/binにvim-language-serverというシェルスクリプトを作成して、それを起動することにします。

$ cat ~/bin/vim-language-server
#!/bin/sh
deno run --allow-sys --allow-env --allow-read --allow-run npm:vim-language-server --stdio

当然PATHも通しておきます。

そしてvimrcはこんな感じ。

if (executable('vim-language-server'))
    augroup LspVim
        autocmd!
        autocmd User lsp_setup call lsp#register_server({
            \ 'name': 'vimls',
            \ 'cmd': {server_info->['vim-language-server']},
            \ 'allowlist': ['vim'],
            \ 'initialization_options': {
            \   'vimruntime': $VIMRUNTIME,
            \   'runtimepath': &rtp,
            \   'diagnostic': {'enable': v:true}
            \ }})
    augroup END
endif

最初は'cmd' に 'deno', 'run', ... などと試してましたが、シェルスクリプトを作成するのが一番シンプルだなと思いまして。

これでvimrcを開いて :CheckHealth すると、

lsp: health#lsp#check
=====================
## server status
  - WARNING: pylsp: not running
  - OK: vimls: running

## server configuration: pylsp
  - INFO:
    ### allowlist
    ['python']

## server configuration: vimls
  - INFO:
    ### allowlist
    ['vim']

と表示するようになりました。

そのうちRuffも入れてみようと思います。Ruffはpacmanからインストールできて、python-lsp-serverにプラグインとして組み込めるようなので、BlackやFlake8と同等の設定ができればいいなと考えています。

あと、Vimのmessages、cmdline、popupmenuを置き換えるNoiceというのもあるようで、これはおいおい試してみます。

Vimの補完プラグインをインストール。その1

 もちろんNeovimがいいんだけれど、NeovimとVimは設定を分けることができるし、ディストリビューションで標準でインストールされてるのはVimなことが多いので、Vimの環境づくり。

ちなみに現在のVimバージョンは9.1.707です。

さて、Vimの補完プラグインですが、Shougoさんが作成していたneocomplete.vimは終了し、deoplete.nvimを経て、現在はddc.vimが開発を続けられています。なので、補完フレームワークはddc.vimにして、そうするとLSPとかfileとかいろいろと補完ソースに指定することができるはず。

AURを見るとvim-ddc 0.17.0-1というパッケージソースがあるようなので、dpp.vimのようなプラグインマネージャを利用するか、pacman(自前パッケージ)を利用するか悩むところですが、AURからextraになることもないだろうし、そうするとアップデートも自分でチェックしてやることになって面倒が増えるだろうから、プラグインマネージャで行う方針にします。とりあえずはdpp.vimで考えてみることに。

ddc.vimもそうですが、dpp.vimもDenoを利用し、そのためにdenops.vimをインストールする必要があるので、まずはDenoをインストールします。こちらはpacmanでさっくり。

次にdenops.vimですが、こちらはvim-plugのようなプラグインマネージャでインストールして、と書いてあります。vimballが提供されていれば楽なんですが…。プラグインマネージャのdpp.vimをインストールするにはdenops.vimが必要で、denops.vimをインストールするにはプラグインマネージャが必要という鶏卵問題。

もうちょっとお手軽にいかないかな、と考えた結果、メンテナンスフェーズに移って開発は終了していますがdein.vimを使用することにしました。lazy.nvimに手を出してみたいけど、こちらはVimでは動かないようですし。

ということで、Dein-installer.vimの手順でインストールします。curlなら標準でインストールされているので、curlのほうで行います。さっくり。

すると$HOME/.vimrcに書くべき設定を表示してくれるので、これを.config/vim/vimrcにコピペします。ぺたぺた。

でもってdein#addのところにインストールしたいプラグインを記述します。

call dein#add('vim-denops/denops.vim')
call dein#add('vim-denops/denops-helloworld.vim')

vimrcをリロードしたら、:call dein#install() して、:DenopsHelloしてみると、ちゃんと挨拶を返してくれました。

次はddc.vimです。こちらはフレームワークなので、Vimの場合にはポップアップメニューを表示するための仕組みが必要になるので、pum.vimも必要です。それと、pumのUIを定義するためにddc-ui-pumも必要です…と言い切っちゃっていいのかどうかよくわかりませんが、一応インストールします。

call dein#add('Shougo/ddc.vim')
call dein#add('Shougo/pum.vim')
call dein#add('Shougo/ddc-ui-pum')

また、ddc.vimで入力補完を利用するにはソースプラグインとフィルタプラグインが必要です。ddc.vimはあくまでフレームワークなので。

call dein#add('Shougo/ddc-filter-sorter_rank')
call dein#add('Shougo/ddc-source-around')
call dein#add('Shougo/ddc-filter-matcher_head')

フィルタ用の設定も書き足します。

call ddc#custom#patch_global('sourceOptions', #{
      \   _: #{
      \     sorters: ['sorter_rank'],
      \   }
      \ })
call ddc#custom#patch_global('sourceOptions', #{
      \   around: #{ mark: 'A' },
      \ })
call ddc#custom#patch_global('sourceParams', #{
      \   around: #{ maxSize: 500 },
      \ })

ここまでは下準備で、次がようやく当初の目的のLSP(Language Service Protocol)のインストールです。

よく使うのはPythonなので、まずはPythonからいってみます。

PythonのLSPはMicrosoftのPyrightやPylanceなどもありますが、PyrightもPylanceはTypeScriptで記述されており、動作にはnode.jsが必要です。今回はnode.jsではなくDenoで行きたいので、これはなしの方向で。

ということで、Python LSP Serverことpylspを導入します。pylspはpipでもインストールできますが、pipだと前述したようにアップデートの管理が面倒なので、ArchLinuxのパッケージになっているpython-lsp-serverをインストールします。python-lsp-serverはSpyderプロジェクトにて開発されていたもので、Pythonで記述されているため、速度的には遅いもののnode.jsやnpmは不要です。

# sudo pacman -S python-lsp-server

また、Vim側でLSPをお話するLSPクライアントのプラグインであるvim-lspをインストールします。vim-lspはVimスクリプトで記述されていますが、重たい動作の部分をluaで実装しているため、Vimがluaをサポートしていないと利用できません。幸いArchLinuxのVimは+luaでコンパイルされているので問題なし。

call dein#add('prabirshrestha/vim-lsp')

vim-lspを使ったLSPの設定を用意にするために、vim-lsp-settingsを使ってもよいのですが、実はこれを使うとちょっとnode.jsがゴニョゴニョっぽいので自前で用意します。といっても、vim-lspのページのRegistering Serversの設定をコピペするだけ。なのでコードは省きます。これはpylsp用の設定なので、その他のLSPサーバを利用するときはそれ用の設定を加えないといけませんが、それはまたあとで。

ここまでやれば、あとはddc.vimに渡してやると動くようになります。

call ddc#custom#patch_global('sourceOptions', #{
      \   vim-lsp: #{
      \     matchers: ['matcher_head'],
      \     mark: 'lsp',
      \   },
      \ })

call ddc#custom#patch_global('sources', ['around', 'vim-lsp'])
call ddc#enable()

最後のddc#enable()をcallしないと動きませんが、結構忘れがち。これで .py のファイルを編集するときには自動でpylspが動きます。

とりあえずは動いたので、チューニングなどはおいおい :h vim-lsp などしてやっていきます。

ちなみにちなみに、Python用の高速なlinter/formatterのruffをpylspのプラグインとして利用するpython-lsp-ruffというのもあるようですが、これもまたあとで。これまで使っていたBlackとFlake8を置き換えられるかどうかの検討が必要かなと。Pythonの Ruff (linter) でコード整形もできるようになりましたでは

要約: Flake8 + Black + isort はもうすべて Ruff だけで置き換えられる。

などとあるのでちょっと気になってます。ちなみにruffはRustで書かれていますが、Rustってripgrepのアレだよねぇ、と高速っぽい印象バイアスかかってます。

それとは別に、python-lsp-blackというのもあり、こちらはBlackを使うプラグインです。どっちがいいんだろうか。それと静的型チェックを行うmypyのプラグインpylsp-mypyなんてのもあります。いずれにしてもまたあとで。

ArchLinux on WSLでどたばた。

Windows11のノートPCで、WSLでArchLinuxをインストールしようと思ってちょっと引っかかったところがあったのでメモ。

インストール自体はArchWSLのページの通りで進みましたが、pacman -Syu するとtrusted keyが云々でできませんでした。

そこで、/etc/pacman.d/gnupgをディレクトリごと削除し、また$HOMEにある .gnupg も削除してリブート、次に pacman-key --init してから、pacman-key --populate archlinux すると、archlinux.orgのarchlinux.gpgを追加してくれるので、以降は pacman -Syu できるようになりました。

  1. /etc/pacman.d/gnupgをディレクトリごと削除
  2. $HOMEにある .gnupg も削除
  3.  pacman-key --init
  4. pacman-key --populate archlinux
これ、しばらくぶりにアップデートしようとするとハマるんですよね。

MSYSTEMはどこで設定する?

MSYS2 を今まで pacman でアップデートしてきたんですが、ちょっと apcupsd の apctray.exe をいじりたくて、make したら make がないとか言われたんで調べてみたら、構成がいろいろ変わっていて、/ucrt64 とかいろいろできていて、path を通さないといけないっぽい。ので、ちょっと調べてみました。

MSYS2 にある複数環境、C++ アプリ開発で簡単にまとめられていました。が、さてじゃあどれを使うのがいいのかというと、「自分がやりたいことができる環境にしなさい」らしいのですが……。

本家のドキュメントを見ると、Environments に、

If you are unsure, go with UCRT64.

とあるので、UCRT64 にしてみます。すると、

For example, in the UCRT64 environment the $PATH variable starts with /ucrt64/bin:/usr/bin so you get all ucrt64 based tools as well as all msys tools.

とあるように、UCRT64 環境を選ぶと、$PATH が /ucrt64/bin:/usr/bin というふうに変更されて、パスが通るようになっているようです。デフォルトでは bash が呼ばれるので、まずは /etc/profile が読み込まれるはず。そちらを見ると、

unset MINGW_MOUNT_POINT
. '/etc/msystem'
case "${MSYSTEM}" in
MINGW*|CLANG*|UCRT*)
  MINGW_MOUNT_POINT="${MINGW_PREFIX}"
  PATH="${MINGW_MOUNT_POINT}/bin:${MSYS2_PATH}${ORIGINAL_PATH:+:${ORIGINAL_PATH}}"
  PKG_CONFIG_PATH="${MINGW_MOUNT_POINT}/lib/pkgconfig:${MINGW_MOUNT_POINT}/share/pkgconfig"
  PKG_CONFIG_SYSTEM_INCLUDE_PATH="${MINGW_MOUNT_POINT}/include"
  PKG_CONFIG_SYSTEM_LIBRARY_PATH="${MINGW_MOUNT_POINT}/lib"
  ACLOCAL_PATH="${MINGW_MOUNT_POINT}/share/aclocal:/usr/share/aclocal"
  MANPATH="${MINGW_MOUNT_POINT}/local/man:${MINGW_MOUNT_POINT}/share/man:${MANPATH}"
  INFOPATH="${MINGW_MOUNT_POINT}/local/info:${MINGW_MOUNT_POINT}/share/info:${INFOPATH}"
  ;;
*)
  PATH="${MSYS2_PATH}:/opt/bin${ORIGINAL_PATH:+:${ORIGINAL_PATH}}"
  PKG_CONFIG_PATH="/usr/lib/pkgconfig:/usr/share/pkgconfig:/lib/pkgconfig"
esac

となっていて、2行目(ファイル中では48行目)で /etc/msystem をソースしています。長い行の改行がおかしな感じになってますが。

/etc/msystem を見ると、冒頭に

export MSYSTEM="${MSYSTEM:-MSYS}"

とあって、$MSYSTEM が定義されてなければ "MSYS" を設定するようになっています。

ということは、/etc/msystem が読まれる前に MSYSTEM を設定すれば、あとはドミノ倒しでうまくいきそうです。……なのですが、Shells には、

The launchers set the MSYSTEM variable and open a terminal window (mintty) with a proper shell (bash). Bash in turn sources /etc/profile which sets the environment depending on the value of MSYSTEM.

Without the correct environment, various things may and will (sometimes silently) break. The exception is using mingw subsystems from pure Windows, which shouldn't require any special environment apart from an entry in PATH. Do not set MSYSTEM outside of the shells, because that will also break things.

とあり、最後の行でなんだかよくわからないことが書いてあります。たぶん、ここは「shellが読み込んだ後に MSYSTEM を変えるな」ということだと思うのですが…。

ランチャが MSYSTEM 変数をセットしてから mintty を開くということなので、ランチャを見てみます。msys2_shell.cmd がそれです。すると37行目から、

rem Shell types
if "x%~1" == "x-msys" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=MSYS& goto :checkparams
if "x%~1" == "x-msys2" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=MSYS& goto :checkparams
if "x%~1" == "x-mingw32" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=MINGW32& goto :checkparams
if "x%~1" == "x-mingw64" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=MINGW64& goto :checkparams
if "x%~1" == "x-ucrt64" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=UCRT64& goto :checkparams
if "x%~1" == "x-clang64" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=CLANG64& goto :checkparams
if "x%~1" == "x-clang32" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=CLANG32& goto :checkparams
if "x%~1" == "x-clangarm64" shift& set /a msys2_shiftCounter+=1& set MSYSTEM=CLANGARM64& goto :checkparams
if "x%~1" == "x-mingw" shift& set /a msys2_shiftCounter+=1& (if exist "%WD%..\..\mingw64" (set MSYSTEM=MINGW64) else (set MSYSTEM=MINGW32))& goto :checkparams

などとなっています。どうやら、msys2_shell.cmd に続いてハイフンとシェルタイプを指定すればよいようです。

うちの場合、Windows Terminal を使って MSYS2 を開くので、今までは

C:/Apps/msys64/msys2_shell.cmd -no-start -defterm -msys2 -here -shell zsh

としていましたが、UCRT64環境にしたければ -msys2 を -ucrt64 にすればよいようです。てっきり /etc 以下のどこかのファイルかと思ってしまいました。

AstroNvimでtelescope.nvimがエラーを吐いたとき。

Windowsの環境でAstroNvimをインストールして、Find Fileしたらtelescopeがエラーを吐いてきました。


メッセージは、
Failed to run `config` for telescope.nvim
...a/lazy/telescope.nvim/lua/telescope/extensions/init.lua:10: 'fzf' extension doesn't exist or isn't installed: ...nvim-data/lazy/

なんて感じになってます。 

~/.local/share/nvim-data/lazy/telescope-fsf-native.nvim を見ると、Makefileがあってsrcディレクトリがありますから、AstroNvimのインストール時にコンパイルしようとしてずっこけているようです。

Makefileを見てみると、libfzf.dllを作成して配置してやればよさそうなので、msys64のコンソールを起動してMakefileのあるディレクトリに移動し、make一発。buildディレクトリが作成されて、無事libfzf.dllができあがりました。ちなみに他のディレクトリにインストールする必要はなく、このbuildディレクトにあることが必要なようです。

Neovimを起動してみると上記のエラーは消えていました。めでたしめでたし。

WesternDigitalこわれた。

たぶん寿命を過ぎてるのでクレームとまではいかないのだけれど。

WesternDigitalのWD60EFRXが壊れました。モノは2014年11月に購入。ところが3年で壊れ、RMAにより2017年11月に交換したものです。BlackBlazeでも故障率がそれなりに高かったので、そういうもんなんだろうな、という感じですが。

ちなみに症状は、PCをリブートしたらいきなりWindowsの起動画面で画面中央下のマルがくるくると永遠に回り続ける状態で、最悪ブートドライブ交換の再インストールコースかと覚悟し、m.2 ssdとかいろいろ準備してから取り掛かったらWDがおかしくて止まってたというオチ。スピンドルは回ってるようだけどヘッドの動く音がしないので、叩けば治るかもですが。

ただ、中のデータはそんなに大事なものではなく、さらに大容量の東芝16TBを導入してコピーしていたはずなので、暇を見てコンコンしてみます。

TeXLive2024がインストールできない。

TeX Live 2024がリリースされていたので、インストールしてみました。

BitTorrentでISOをダウンロードして、ISOイメージをダブルクリックすると自動でマウントされるので、そのままinstall-tl-windows.batを実行。するとエラーになります。


こんな感じ。もしかしたらPythonのtcl/tkとかち合ってるのかもしれません。

ぐぐってみるとError in Installation Processにあるのが同じ状態でした。

結論として、コマンドプロンプトを開いて

i:\install-tl-windows.bat -texdir c:\texlive\2024 -gui text

とすれば、GUIなしでインストーラを起動でき、無事にインストールできました。

SWDなら3線でいいとはいうものの。

 安価で優秀なデバッグプローブはないかしら、と探したら、 Raspberry Pi Debug Probe というのがあったんですが、これは3線がにゅるんと出てるだけです。 もちろんSWDなら3線を繋げばいいのではありますが、汎用的に考えるなら5x2のリボンケーブルコネクタが欲し...