nabeo がピーしているブログ (仮)

どーも、nabeop です

Kotlin のテックカンファレンスなのに Emacs ネタで登壇してきた #KotlinFest

2025年11月1日に品川で開催された Kotlin にフィーチャーしたテックカンファレンスの Kotlin Fest 2025 に登壇してきた。

Kotlin Fest 2025 は国内で開催される Kotlin 系のテックカンファレンスでは最大規模のイベントで、毎年多くの Kotlin 開発者が登壇している。僕が勤めている会社でも Kotlin をメイン言語で使っているということもあって、スポンサーブースを出したり登壇者を出したりしてきた。

今年も Kotlin Fest 2025 の CfP が始まったタイミングで会社の有志でプロポーザルを出すぞ!!となって集まったときに、なぜか登壇を後押しする側の僕が同僚から背中を押されて kotlin-lsp + Emacs というネタでプロポーザルを出すことになった。

後押しをしてくれた同僚曰く、kotlin-lsp は今年の KotlinConf で発表されてアツいし、尖った内容だからいけるよーということだったけど、プロポーザルを出した時は半信半疑だった。

結果として僕のプロポーザルが採択されて登壇チャンスをもらえたんだけど、当日のタイムスケジュールでは Kotlin のコアな話題が集まる中で突然の Emacs が出てくるという光景が広がっていた。

とはいえ、今回の登壇をきっかけにして、Emacs の開発環境も見直すことができて個人的には得るものが大きかったです。具体的には

  • Emacs の LSP クライアントを eglot から lsp-mode に変更する決断ができた
  • LSP の機能としてフォーマットやリンター相当のことができることを知れた
  • flycheck の挙動やチェッカーの作り方とかなど再確認することができた

というあたり。

残念ながら最新の kotlin-lsp では補完が確定できないという不具合があったり、リリースが滞っていたりなど心配なところもあるけど、そこは JetBrains さんを信じて kotlin-lsp の開発を見守っていきたいです。

会社のブースで対応しつつになったけど、気になっていたセッションにも参加できてよかったです。とくにマヤミトさんの「ビルドプロセスをデバッグしよう!」では通常の Kotlin アプリケーションと同様にビルドプロセスでデバッガによるブレークポイントを仕込んで調査する様子をみれて参考になりました。

Kotlin Fest 2025 の運営の皆様、参加者の皆様、ありがとうございました。国内の Kotlin 開発者と楽しく交流できる貴重なイベントなのでまた来年も開催されると嬉しいです。

あと、会社では非公式なアフターパーティを企画していて、ここでは今回の登壇に関連して、「IntelliJ IDEA 以外での Kotlin 開発のリアル」として VimVSCode で Kotlin 開発に挑戦している渡邊 泰紀 a.k.a yasunoriさんと髙野 氷河さんで座談会も企画しているので、よりディープなエディタ談義ができそうで今から楽しみにしています。

Emacs + eglot で kotlin-lsp を使う

Kotlin Conf 2025 でサラッと Kotlin の LSP サーバ実装を開発中ということが発表された。

VS Code の拡張として提供されるらしいが、Githubリポジトリをみると Emacs や neovim 向けでも使えるように Standalone 版がダウンロードできるようになっている。今までは仕事で Kotlin を使うために InteliJ IDEA を起動していたけど、手に馴染んだ Emacs で Kotlin のコードを触ることができるなら、そうしたいので Standalone 版の kotlin-lsp を Emacs + eglot の環境で使えるように試行錯誤してみた。

user-emacs-directory 以下の data/kotlin-lsp ディレクトリにダウンロードしてきた zip ファイルを展開して eglot-server-program に以下のような設定を追加した。

  (add-to-list
    'eglot-server-programs
    `((kotlin-mode kotlin-ts-mode) . (,(concat user-emacs-directory "data/kotlin-lsp/kotlin-lsp.sh") "--stdio")))

で、この状態で kotlin で書かれたファイルを開くと kotlin-lsp が起動するんだけど、LSP サーバの起動時の initialize 処理で OOM で落ちるという状況だった。macOSアクティビティモニタをみていると僕の環境では 8GB から 9GB 付近に天井がありそうだった。kotlin-lsp.sh を読んだところ外部から heap 領域の上限を指定できるようにはなってなかったので、Java を起動しているところに -Xmx24G として割り当ててみた。

今度は OOM で落ちることはなくなったけど、 initialize 処理で eglot がタイムアウトしたので、eglot-connect-timeout を 60 で設定してたところを 120 にしてあげた。

これでひとまず使えるようになったけど、kotlin-lsp は対象の Kotlin プロジェクトのサイズによってメモリを消費するぽくて、感覚的にはローカル LLM で少し大きめのモデルを使った時と同じくらいだった。ちょっとこのまま使い続けるかは悩むところだけど、以前の状況よりもマシにはなってきているのでこのまま頑張ってほしい。Jetbrains さんのビジネスモデルを考えると将来的には kotlin-lsp を使うために有料のプランが必要ということになりそうだけど、まともに使えるなら有料プランに課金もやぶさかではないというスタンスです。

homebrew の emacs-plus をビルドしたら Emacs.app が開けない

homebrew の d12frosted/emacs-plus で Emacs をビルドして使おうとすると、「アプリケーション "Finder" には "Emacs.app" を開くアクセス権がありません」というようなダイアログが出て起動に失敗する。macOS のコンソール.appで Emacs 関連のログを見るとエラーとして以下の2行が記録されていた。

Sandbox: itunescloudd(832) deny(1) file-read-data /usr/local/Cellar/emacs-plus@30/HEAD-63adf9d/Emacs.app
1 duplicate report for Sandbox: itunescloudd(832) deny(1) file-read-data /usr/local/Cellar/emacs-plus@30/HEAD-63adf9d/Emacs.app

なんか kernel の Sandbox 的に起動を拒む雰囲気がある。

それぽい情報がないかをググると以下のコメントがあった。

今回は emacs-plus@30 で同様の事象に遭遇したので、こんな感じで解決させた。

sudo codesign --force --deep --sign - /usr/local/opt/emacs-plus@30/Emacs.app

1X年ぶりにターミナル環境を作り替えている話

時の流れは恐ろしいもので、25才で社会人になり、今年で社会人人生が20年の節目の年だった。言い換えると、仮に65才定年だとすると社会人人生の折り返しの年でもあったらしい。

オールドタイプなインフラエンジニアなので仕事ではずーっと CLI 中心の生活になっていたので、ターミナル環境は生活の一部として継ぎ足しで整備をしてきた。継ぎ足して整備しているということは連続的な変化で特に新しい刺激はなく淡々と日々の仕事に支障なく使っていたのでマンネリな気配もあった。

たぶん、今のままの環境を使い続けても特に不満はないけど、節目の年ということもあって新しい風をいれてみるか、ということでターミナル環境で使っているツール類を入れ替えてみた。

入れ替え後の旧環境と新環境のツール類は以下のような感じになった。

旧環境 新環境
ターミナルエミュレータ iTerm2 WezTerm
*env 系ツール *env 各種 mise
zsh プロンプト 自作 starship
ターミナル向けエディタ MacVim Neovim
ドットファイル管理 してない chezmoi
ターミナルマルチプレクサー tmux tmux

ターミナルエミュレータ

ターミナルエミュレータの iTerm2 は X の過去のポストを遡ると少なくとも 2011年の時点では使っていたらしい。

長らく使っていたということもあって、iTerm2 には大きな不満はなかったけど、さすがに動作が重いというときがあって、軽量かつ機能的にカバーできる代替のターミナルエミュレータを探したところ、WezTerm が良さそうなので乗り換えてみた。

WezTerm は Lua で設定を書けるし、ドキュメントが充実しているので、自分のやりたいことは大体できるというところが気に入っている。あと、Lua は後述の Neovim でも使うことになるので、設定で使用する言語が同じというところも都合がよかった。

ただし、WezTerm はターミナルマルチプレクサとしても使えるんだけど、tmux の choose-window 相当の動作が実現できないのでターミナルマルチプレクサ部分を置き換えることはできなかった。

で、この記事を書いて下書きで寝かせているうちに Ghostty が正式リリースされて、どうしよう...となっている。

*env 系ツール

スクリプト言語を切り替える env 系ツールは rbevn や pyenv など個別の env 系ツールを使っていたけど、mise に一本化した。

一本化することで *env 系ツールの設定を1つにまとめることができたし、更新を取り込むときも mise up だけで済むというのは快適だった。

*env 系ツールの rbenv 向けに gem の移行用として rbenv-gem-migrate というプラグインを自作していたけど、mise では ~/.default-gems として全てのバージョンで入れておきたい gem を指定できるのでめでたくお役御免となった。

zsh プロンプト

zsh は学生の頃から使っていて、プロンプトは自前で PROMPT 環境変数RPROMPT 環境変数を調整していたけど、今風なプロンプトを手軽に実現したかったので、starship に乗り換えた。

今風で見た目が良いというだけではなく、各種モジュールでカレントディレクトリの状態がプロンプトに表示されていて便利だった。とくに Git Status モジュールはリモートブランチからの乖離が一目でわかるようになったので、トピックブランチを生やす時にリモートブランチの HEAD の取り込み漏れが減ったり、stash の状態が一目でわかるのでゴミ掃除が捗った。

ターミナル向けエディタ

通常時は Emacs を使っているけど、ターミナル内でちょっとした修正や EDITOR 環境変数は MacVim に付属している vim コマンドを使っていた。~/.vimrcEmacs ほどではないけど、それなりに育ていたけど、ちょっとした事情で育ていた環境を吹っ飛ばした時のバックアップ漏れで一年ほど素の状態で使い続けることになった。ガッツリ使っているわけではないので、大きな不満はなかったけど、少し使いづらいなーと感じる場面には遭遇するので、同僚が使っている Neovim を導入してみた。

プラグイン管理は LazyVim を使って Treesitter によるシンタックスハイライトや LSP の設定などを入れている。目的にあった Neovim のプラグインを探す時は dotfyle.com というサイトでいろんな人の設定を見れたり、目的別の人気のプラグインがわかるのでかなり重宝した。

あとは zshエイリアスとして以下を設定しておいた。

alias vim=nvim
alias view='nvim -mR'

Neovim の設定は Emacs と同様に github の個人アカウントでパブリックリポジトリとして公開している。

ドットファイル管理

ドットファイル管理は以前はファイルの symlink で管理する方法が主流だったけど、symlink での管理はなんとなく嫌だったので、これまでは避けていた。しかし、バックアップをとらずに育てていた ~/.vimrc を吹っ飛ばしたり、設定ファイルを Lua で記述できるツールが増えたりしたので、ドットファイル管理も Github で管理する機運が高まった。

そんななかで、chezmoi というツールが実ファイルを残して管理できるし、リモートリポジトリでの公開に躊躇うような秘密情報は暗号化して管理できそうということがわかったので、今回のことをきっかけに chezmoi によるドットファイル管理を取り入れることにした。

chezmoi も個人の Github アカウントにリポジトリを作っているけど、秘密情報の暗号化漏れが怖いのでプライベートリポジトリとして運用している。

chezmoi は Go のテンプレートでファイルを記述できるので、仕事用のマシンと私用のマシンでマシンのコンテキストを考慮しtた状態で設定を共有することも可能ということもよかった。あと、外部リポジトリを chezmoi の同期対象に入れることもできるので、Emacs や Neovim の設定を chezmoi の同期対象にいれることでドットファイル管理の統一ができたということも嬉しかった。

まとめ

じつは10年以上大きく変えてこなかった環境の入れ替えを決心できたのは今の会社では SSH によるリモートログインがほとんど必要なくて、ターミナル環境は自分のマシンだけを考えておけば良いという状態になったということも大きかった。今までは手元の環境を現代風にしたとしても SSH でリモートログインしたときに操作感が大きく異なることで作業効率が落ちることを嫌がって変化を拒んでいたという側面はあったけど、そういう心配がかなり小さくなったので変更に踏み切りやすかった。

今回の変更で10年以上戦えるかというとかなり微妙だけど、ドットファイルを管理するようになったので、大きな変更をして失敗しても切り戻すことはできるので変更しやすくなった。

あと、長いこと使い続けているツールとして zsh という超大物がいるけど、macOS のデフォルトシェルが zsh なのでこのまま使い続けるんじゃないかと思っている。

続: (Emacs さんの) 気分によってフォントを変える

半年前くらい Emacs のフォントは起動時にランダムで決定されたフォントを使っていました。設定した当初はお気に入りのフォントが見つかるかなーと思っていたけど、蓋を開けてみたら選択する候補のフォントは増えていた。

git のログを見る感じだと候補のフォントの入れ替わりはこんな感じだった。

現時点での候補はこんな感じになっている。これだけ見ると Moralerspace がどんだけ好きやねん?となりそうだけど、実際に Moralerspace Krypton HWNF はクセが強いけど視認性が悪くなくて結構好きです。

ここまで多いと起動時に読み込ませるだけでは物足りなくなってきて、任意のタイミングでフォントガチャを回してくなってきた。

話は変わって Emacs のテーマは doomemacs/themes を使っているんだけど、こっちもテーマの数がめっちゃあるのでフォントと同じようにガチャを回したくなってきた。というのも、今までは Solarized 由来のダーク系テーマを好んで使っていたけど、Neovim や WezTerm を使っている時に Tokyo Night というテーマの存在を知って、これいいじゃんとなったので Emacs のカラーテーマも色々かえてみようかという気持ちになってきた。

ということで、フォントの設定部分と同様に doom-theme の設定時にいくつか選んできたテーマをランダムで決定するようにして、フォントの選択部分と合わせていつでも呼び出せるようにしてみた。

nabeo/randomly-select-doom-themeとして doom-theme をいい感じに選択する

nabeo/set-my-font としてフォントファミリーをいい感じに選択する

nabeo/randomly-select-doom-themenabeo/set-my-fontC-c C-r でいつでも呼び出せるようにする

これで作業しているときにいつでも Emacs の中身をガラッと変えられるようになって日々の作業が充実するようになった。

本当は nabeo/randomly-select-themeafter-save-hook とか日常の手癖になっている操作の hook に登録して、いきなり Emacs さんの見た目が変わるなどのオモシロを取り入れてもいいかなーと思っている。

terraform は Homebrew で管理しない方が良いという話

macOS のパッケージ管理は Homebrew が主流だけど、terraform については Homebrew で管理しないほうが良いと言う話です。以前は Homebrew 経由で入れていたけど、今は mise を使って terraform コマンドを管理しています。

続きを読む

WezTerm 事始め

少なくともここ10年くらいは macOS のターミナルエミュレータは iTerm2 を使っていたんだけど、私用の macbook air は未だに intel CPU を使っていて、だんだん iTerm2 の動作がもっさりしてきていてストレスを感じるようになってきた。そんな中でどうやら WezTerm が軽量ぽいみたいな話題をみたので、iTerm2 で凝った設定をしていないということもあり、ターミナルエミュレータの引越しをしてみた。

続きを読む