Emacs 29の eglotを使った Rust環境の設定
Emacs 29から eglotが標準パッケージに入るということで, 最近はちょっとした C++や Goを書くときなどは Emacsを使うことが少し増えてきた. 仕事だと IDEや VScodeだけど. そこで Rustも設定しておくかということでやってみた. VSCodeだと基本的に全部自動だが, Emacsでの作業が幾分必要であるのはやはり面倒だと思った.
必要なツールのインストール
% rustup component add rust-analyzer % rustup component add rust-src
PATHの設定
rust-analyzer
を PATHに設定されている場所に置く. 直接 PATH設定するなり好きにすればよい
% ln -s ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rust-analyzer ~/.cargo/bin/
Emacsの設定
;; rust-modeのインストール. 使っているパッケージに合わせてください. 下記は el-get (el-get-bundle rust-lang/rust-mode) ;; 補完のために company-modeも入れる (el-get-bundle company-mode/company-mode :name company-mode) ;; elgotの有効化 (add-hook 'rust-mode-hook 'elgot-ensure)
単純な Rustプロジェクトであればこれだけで動くが, 複数プロジェクト構成だったり, git rootに Cargo.tomlがないケースではうまく行かない問題があった. rust-analyzerは性質上 Rust project rootで起動する必要があるようだが, eglotは project.elの機能を使って project rootを探しており, それはデフォルトでは .gitがあるディレクトリになってしまう. このため .gitがあるディレクトリと Cargo.tomlがあるディレクトリが一致しない場合, LSP用のサーバが起動できずエラーになってしまう. そこで project rootを探す処理に手を入れ対応する必要がある. 具体的には project.elは project-find-functions
に登録されている関数を順番に実行し, non-nilが返った場合 それを project rootとして認識するので下記のような対応を行った.
(defun my/find-rust-project-root (dir) (when-let ((root (locate-dominating-file dir "Cargo.toml"))) (list 'vc 'Git root))) (defun my/rust-mode-hook () (setq-local project-find-functions (list #'my/find-rust-project-root))) (add-hook 'rust-mode-hook #'my/rust-mode-hook)
これで .git rootに Cargo.tomlがないようなケースでも動くようになった.
おわりに
VSCodeとか IDE使っていたら自動ですべてやってくれるから LSPの恩恵というのをイマイチ実感していなかったけど, LSPはかなりライフチェンジングなものなんだなと Emacsの設定を通じて今更感じた。VSCodeとかに比べればまだまだ手間なんだけど、Emacs29からは上記のような特殊なケースは除くとしてもサーバプログラムさえあれば LSPの恩恵を数行の設定で受けられるってのはとても良い体験だと感じた。
tmux + 256colorで Emacsの見た目の調整
Ubuntu 22.10で環境変数 TERM=xterm-256color
で Emacsを起動するとこんな感じなのだが
tmuxを起動すると以下のようになりめちゃ見づらい
これが嫌で TERM=xterm
でここ 10年ぐらいやってきたのだが, さすがに 256colorの方が良いんじゃないって思って対応方法を調べていろいろ試したんだけど全部うまくいかなくて, 最終的に tmuxでシェルを起動したときだけ TERM=tmux-256color
としてやると期待通りになることはわかった.
if [[ "$TERM_PROGRAM" == "tmux" ]]; then export TERM=tmux-256color else export TERM=xterm-256color fi
tmuxのなしの場合と同じような見た目にすることはできた. 原因とかはよくわかっていないがひとまずヨシということで。
i386 architectureのパッケージをすべて削除する
昨日メイン PCとサーバを Ubuntu 22.10に上げたけど改めて考えると i386パッケージいらないだろってことで消してみた. 複数あることでアップデートなんかも遅くなるので.
パッケージを削除する
下記のコマンドなどで i386パッケージを一覧を得て, :i386
が末尾についているパッケージを削除していく. 一応依存を確認したりしながら行ったが, 基本的には全部いらないと思う.
## 一覧表示 % dpkg -l |grep ':i386' ## パッケージ削除 % sudo apt purge some_package:i386 ## 依存関係を見る % apt rdepends --installed some_package:i386
22.04で i386環境がある場合, おそらく以下のパッケージが削除できない
- gcc-12-base
- libc6
- libcrypt1
- libgcc-s1
これらのパッケージは下記のコマンドで強制的に削除する
sudo dpkg --purge --force-remove-protected {gcc-12-base,libc6,libcrypt1,libgcc-s1}:i386
アーキテクチャリストから i386を削除する
依存パッケージをすべて削除したら, 下記のコマンドで i386をアーキテクチャリストから削除する
% sudo dpkg --remove-architecture i386
最後に i386が削除されたことを確認する. 何も表示されなければ OK
% dpkg --print-foreign-architectures
特定のプログラミング言語でショートカットキーを有効化する
[ { "key": "f1", "command": "rust-analyzer.openDocs", "when": "editorLangId == rust" }, ]
when
プロパティに editorLangId
の条件を追加してやればよい.
リファレンス - https://code.visualstudio.com/api/references/when-clause-contexts - https://code.visualstudio.com/docs/languages/identifiers
flutterの zsh補完を version 3対応した
ダウンロードした tar.gzをファイルに書き出さずに展開する
諸事情で Perlを書いていてやり方がわからなかったので調べた. ローカルファイルの tar.gzを展開みたいなのはそれなりにあったけど, オンメモリのまま処理する方法が皆無だった.
#!/usr/bin/env perl use strict; use warnings; use HTTP::Tiny; use Encode; use Archive::Tar; use IO::Uncompress::Gunzip qw(:all); my $dest = shift; my $url = 'https://www.cpan.org/src/5.0/perl-5.36.0.tar.gz'; my $res = HTTP::Tiny->new->get($url); unless ($res->{success}) { die "$res->{status} $res->{reason}"; } my $tar_buf; gunzip \$res->{content}, \$tar_buf or die "gunzip failed: $GunzipError\n"; open my $fh, '<', \$tar_buf or die "Can't open tar content as a file handle: $!"; my $tar = Archive::Tar->new; $tar->read($fh); if (defined $dest) { $tar->setcwd($dest); } $tar->extract; close $fh;
Perl Navigator を使って書いたけど, 他言語に比べるとだいぶ貧弱だが, 幾分補完やエラーチェックも効き Emacs等で書くよりはだいぶ楽に書けた気がする. 何も補完が効かないとかさすがにもう書けなくなってしまったのでありがたい存在でした.