emacs --no-window-systemで truecolorを効かせずに起動する

GUIエディタは VScodeでいいかということで, Emacsは常に -nw で起動するようにしてみたのだが, 昨今の terminal emulatorは truecolor対応になっており, リモートの環境で使っていた Emacsの色設定がかなり変に見えてしまう問題があった. 対応も面倒くさいということで, 256color対応で立ち上げる方法を模索したところ環境変数 COLORTERMtruecolor から適当の値に変えてやればよいということがわかった. なので下記のような aliasを作成した.

alias emacs='env COLORTERM=1 emacs'

Emacs 29の eglotを使った Rust環境の設定

Emacs 29から eglotが標準パッケージに入るということで, 最近はちょっとした C++や Goを書くときなどは Emacsを使うことが少し増えてきた. 仕事だと IDEVScodeだけど. そこで 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-256colorEmacsを起動するとこんな感じなのだが

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対応した

github.com

古いままだぞという指摘されたので対応した. もっとちゃんとしない部分はあるけど基本は元のままにオプション等をひとまず version 3対応した.

bash補完は公式で提供されるのが, flutterコマンドを実行して補完リストを使っているので遅い. コードは少なくて済むのだけど. zshは現状手でちまちま書いており, メンテナンスは大変だが, bash版に比べるとだいぶ早く実用的にも問題ないと思うのでまあいいかという感じ. Cとか Rustとかで書かれていれば, コマンド実行して補完リスト使ってていうのも選択肢には入ると思うのだが, Dartのせいなのかまだ無理かなと感じた.

ダウンロードした 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等で書くよりはだいぶ楽に書けた気がする. 何も補完が効かないとかさすがにもう書けなくなってしまったのでありがたい存在でした.