Umi Uyuraのブログ

プログラミング関連の作業ログ

Emacsのlsp-modeをPythonのvenv環境で使う

EmacsPythonコードをいじるとき用にlsp-modeを使ってみることにしましたが、venv環境で使うときに少し手間取ったので、やったことをメモ。

LSP Mode - Language Server Protocol support for Emacs

環境情報

項目 情報
OS Windows 11 Home 22H2 (OSビルド 22621.1413)
WSL Ubuntu 22.04.2 (Kernel: 5.15.90.1-microsoft-standard-WSL2)
Emacs GNU Emacs 28.1
Python 3.11.3

WSLのEmacsを使い、WSL内にPython開発環境を用意しています。

インストール

lsp-mode関連

公式サイトの Installation - LSP Mode - LSP support for Emacs 「Manually via MELPA」と「Vanilla Emacs」のあたりを参考に、以下のパッケージをpackage.elの list-package からインストール。

  • lsp-mode
  • lsp-ui
  • flycheck ※もともとインストール済
  • company-mode

lsp-modeインストール後は、 Performance - LSP Mode - LSP support for Emacs にあるとおり、 lsp-doctor を実行しつつ推奨設定をおこなっておきます。

Python用language-server

次にPython用のlanguage-serverをインストールしますが、 Languages - LSP Mode - LSP support for Emacs を見ると複数種類あって迷うところ。

deprecatedと書かれているPalantirと、リポジトリアーカイブされていたMicrosoftのもの除いても以下の4種類あります。

この中から、この時点でStarが一番多かった Pylsp (python-lsp/python-lsp-server) を使ってみることにしました。

プロジェクト用のフォルダを作成してから、venv環境を作成、パッケージをインストールします。

$ mkdir testproj && cd testproj
$ python -m venv .venv
$ . .venv/bin/activate
(.venv) $ python -m pip install 'python-lsp-server[all]'

lsp-mode実行

pylspが見えない

この状態でEmacs内でPythonソースコードを開いて M-x lsp を実行したところ、以下のようなメッセージが出力されました。

LSP :: The following servers support current file but do not have automatic installation: pyls pylsp ruff-lsp
You may find the installation instructions at https://emacs-lsp.github.io/lsp-mode/page/languages.
(If you have already installed the server check *lsp-log*).

*lsp-log* バッファを見ると、language-serverが見つからないというメッセージが。

Command "pyls" is not present on the path.
Command "pylsp" is not present on the path.
Command "ruff-lsp" is not present on the path.

この中の pylsp が今回入れたpython-lsp-serverなのですが、venv環境に入れたものが見えていないようです。

venv環境のlanguage-serverを参照する

lsp-modeがvenv環境にあるコマンドを参照してくれるように、プロジェクトローカルに設定を用意します。

まず、venv環境にある pylsp コマンドのパスを確認。

(.venv) $ which pylsp
path/to/.venv/bin/pylsp

Emacs上でPythonソースコードを開いた状態で M-x add-dir-local-variable を実行して、 python-mode に変数 lsp-pylsp-server-command と上記のパスを設定します。

Mode or subdirectory (default python-mode): python-mode
Add directory-local variable: lsp-pylsp-server-command
Add lsp-pylsp-server-command with value: "path/to/.venv/bin/pylsp"

パスは文字列として設定するので、ダブルクォーテーションで括ります。

実行すると、以下のように .dir-locals.el バッファが生成されるので、保存しておきます。

;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")

((python-mode . ((lsp-pylsp-server-command . "path/to/.venv/bin/pylsp"))))

あらためてPythonソースコードを開き直すと、以下のようにローカル変数を読み込むかどうかの確認が表示されるので、読み込むために y を選択。

The local variables list in <path/to/project>
contains variables that are risky (**).

DO you want to apply it? You can type
y -- to apply the local variables list.
n -- to ignore the local variables list.

 ** lsp-pylsp-server-command : "path/to/.venv/bin/pylsp"

ソースコードを開いて M-x lsp を実行すると、以下のようにプロジェクトのルートを聞かれるので、表示されているもので問題なければ i を選択。

i ==> Import project root <path/to/project>
I ==> Import project by selecting root directory interactively
. ==> Import project at current directory <path/to/project>
d ==> Do not ask again for the current project by adding <path/to/project> to lsp-session-folders-blacklist
D ==> Do not ask again for the current project by selecting ignore path interactively
n ==> Do nothing: ask again when opening other files from the current project

Select action: i

メッセージに以下のように表示されれば、language-serverに接続できています。

LSP :: Connected to [pylsp:20879/starting path/to/project].

lsp-modeによるコード補完が動くようになりました。

lsp-modeによるコード補完

Windows 11のWSLでGitへSSH接続時に毎回パスワードが要求されるようになった

去年夏頃に買ったばかりなのに、先月SSDが壊れてしまったWindows 11のノートPC。(壊れた原因は、おそらく以前ケーブル引っ掛けてローテーブルから勢いよく落っことしてしまったことだと思うので、自分のせい)

最近のFlow Launcherプラグイン作成やGoの勉強などで活用し始めたところだったので、コミットしていなかったソースなどもあってちょっとショックでしたが、とりあえずSSDを交換して再セットアップし始めました。

umi-uyura.hatenablog.com

環境構築は以前Windows 10で実施したことをベースに実施。

umi-uyura.hatenablog.com

Windows Terminalが標準搭載されていたり、WSLのインストールが wsl --install 一発で済むようになっていたり、デフォルトでセットアップされるWSLのOSがUbuntu 22.04になっていたりと多少の違いはあるものの、Windows 11でもおおむね同じ手順で構築できました。

GitのSSH接続で問題発生

上記手順で実施しているように、WindowsとWSL側でSSHキーを共有して使うようにすることもできてはいたのですが、なぜかWSL側からGitHubへfetchやpushなどでSSH接続するときに毎回パスワードを求められる症状が出ていました。( ssh-add -l で鍵が追加されていることは確認できているものの、コマンド実行時にパスワードを求められる)

ssh configをいじってみたりして調べていたのですが、どうやらWindows 11に標準で入っているOpenSSHとUbuntu 22.04のもののバージョンの組み合わせの関係で、うまく動いていないとのこと。

Windows11 github 版 OpenSSH beta を使ってみた ~ ssh-agent の不具合対処 ~

上の記事を見て、新しいバージョンのOpenSSHを利用することで問題を解消できるようなので、入れ替えてみることにしました。

環境

項目 情報
OS Windows 11 Home 22H2 (OSビルド 22621.1413)
WSL Ubuntu 22.04.2 (Kernel: 5.15.90.1-microsoft-standard-WSL2)

このときのWindows 11側のSSHとGitのバージョンを確認。

>ssh -V
OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.3

>git --version
git version 2.40.0.windows.1

WSL側。

$ ssh -V
OpenSSH_8.9p1 Ubuntu-3ubuntu0.1, OpenSSL 3.0.2 15 Mar 2022

$ git --version
git version 2.40.0

参考にした記事の内容のとおり、Windows側のOpenSSHが8.6に対し、WSL側はそれより新しい8.9なので、やはり同じ問題と思われる。

今となってはうろ覚えですが、SSD交換前の最初のセットアップしたときは、まだUbuntu 20.04だった気がするので、この問題に遭遇しなかったのかな。

Windows 11のOpenSSHアンインストールする

設定→アプリ→オプション機能内のインストールされている機能から「OpenSSHクライアント」をアンインストール。

OpenSSHのアンインストール

実行すると再起動を求められるので実施。

>ssh -V
'ssh' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

ssh コマンドが使えなくなったことも確認。

OpenSSH Betaをインストールする

新しいOpenSSHはGitHubで公開されているのですが、ややこしいですが、関係するリポジトリが2つあるもよう。

インストールはwingetで入れられるようなので、実行。

>winget search openssh
名前         ID                     バージョン ソース
------------------------------------------------------
OpenSSH Beta Microsoft.OpenSSH.Beta 9.2.0.0    winget

>winget install --id Microsoft.OpenSSH.Beta

必要なPATHも登録してくれるので、Chocolatey付属の refreshenv環境変数を読み直すと、新しいバージョンの ssh がインストールされていることが確認できました。

>refreshenv
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..

>where ssh
C:\Program Files\OpenSSH\ssh.exe

>ssh -V
OpenSSH_for_Windows_9.2p1, LibreSSL 3.6.1

標準のOpenSSHのときはコマンドのパスが C:\Windows\System32\OpenSSH\ssh.exe でしたが、 Program Files 配下に入っています。

git コマンドがSSH接続するときに新しい ssh コマンドを利用してくれるように、環境変数 GIT_SSH も上記パスに変更しておきます。

GIT_SSH=C:\Program Files\OpenSSH\ssh.exe

また、SSHサーバー機能は使わないので、サービスに追加される「OpenSSH SSH Server」は無効にして停止しておきました。

SSH Server無効&停止化

動作確認

まずは入れ直したWindows側。

>ssh-add -l
256 SHA256:viFFe3jewdQrTIxOGzz660Pg+xxxxxxxxxxxxxxxxxx my_email@gmail.com (ED25519)

REM A project
>git fetch

SSHキーがssh-agentに登録されている状態で git fetch しても、パスワードは求められません。

次にWSL側。

$ ssh-add -l
256 SHA256:viFFe3jewdQrTIxOGzz660Pg+xxxxxxxxxxxxxxxxxx my_email@gmail.com (ED25519)

$ ssh -T git@github.com
Hi umi-uyura! You've successfully authenticated, but GitHub does not provide shell access.

# A project
$ git fetch

こちらもWindows側で登録したSSHキーが確認でき、同様に git fetch でパスワードは求められませんでした。

現時点ではベータ版という位置づけですが、新しいOpenSSHが標準搭載されるまでは、しばらくこちらのOpenSSHを使うことになりそうです。

magit-statusにユーザー情報を表示する

ふだん、コンソールの表示をカスタマイズしてGitのユーザー情報を表示させているのですが、同じようにMagit statusしたときにユーザー情報を表示できないかと思って調べてみたところ、Magitの仕組みとして用意されていたので、設定してみました。

Magit status headers hook

magit-status の表示内容はカスタマイズすることができるようで、上段の部分はStatus Header Sectionsと呼ばれ、 magit-status-header-hook に登録された関数で生成される仕組み。

標準で表示されるheadやupstream、エラー情報などもこの機構を利用して出力されているもよう。

Function: magit-insert-user-header

その中で、デフォルトでは有効になっていない magit-insert-user-header という関数を使うとユーザー情報を表示できます。

この関数を magit-status-header-hook に登録することで、git config で設定されている user.nameuser.email を表示してくれるようになります。

magit-statusにユーザー情報を表示

設定方法

今回はEmacsのcustomizeを利用して設定しました。

M-x customize でcustomizeを開いて、検索欄で magit-status を検索します。

検索結果に出てくる Magit Status Headers Hook を開くと、プリセットの関数が選択できるようになっています。

ところが、ドキュメントサイトには掲載されているものの、なぜか magit-insert-user-header は選択肢にないため、 INS を押してから magit-insert-user-header を直接入力しました。

customizeでmagit-insert-user-headerを設定

そのまま保存して良ければ、 State を押して 1: Save For Future Session を選択。

問題がなければ、以降 magit-status を実行したとき、ヘッダ部分にユーザー情報が表示されるようになります。

おわり

Magitはデフォルトでも充分便利なので、今まであまりカスタマイズなど考えなかったのですが、あらためてドキュメントを眺めてみると色々とできることがわかったので、他にも自分的に使える機能がないか探してみよう。

参考

Go言語触ってみた&指定した日付の曜日を表示するツールを作った

2023年プログラミング書き初めがてら、個人的に作りたいツールがあったので、Go言語デビューがてら作ってみました。

dow(指定した日付の曜日を表示するツール)

作ったものは、日付を渡すと、その日付の曜日を表示する、というだけのものです。

https://github.com/umi-uyura/dow

使い方はこんな感じ。

# LANG=ja_JP
$ dow 2023-1-1
日

カレンダーを見れば事足りるものではありますが、Emacsでメール用の文章を書いているときに期限などの日付を入れときに、適当に今日から3日後とか決めると曜日がパッとわからないことがあるので、コマンドがあればEmacsから呼び出して反映できるな、という思いつきから作ってみました。

Linuxのdateコマンドで調べる方法

ちなみに、わざわざコマンドを作らなくても、Linuxdate コマンドで以下のようにすれば表示できます。

$ date "+%a" -d "2023/1/1"
Sun

$ LANG=ja_JP.utf8 date "+%a" -d "2023/1/1"

まあせっかくテーマができたので、以前から触ってみたかったGoで作ってみようと思った次第です。

やったことのメモ

今回はGo言語の文法などは必要に応じて調べていくことにして、最低限動いて公開するところまでを優先することにして、やったことのメモ。

  • プロジェクトの開始
  • 処理を実装する
  • 開発中に使う主なコマンド
  • 配布

開発した環境は以下のようなもの。

プロジェクトの開始

プロジェクトを開始する際には、他の外部モジュールを読み込むための準備として、プロジェクトのディレクトリで go mod init を実行します。

その際、引数としてmodule pathというものを指定しますが、これはモジュールを識別するためのもので、ソースコードを保存しているリポジトリの場所とするのが一般的とのこと。

今回、プロジェクト名は単純にday of weekから dow にしようと決めていたので、自分のGitHubリポジトリをベースにしたmodule pathにしました。

$ go mod init github.com/umi-uyura/dow

実行すると、module pathなどが記載されたgo.modというファイルがディレクトリ内に生成されました。

これがあると他の公開されている外部モジュールを go get コマンドでインストールできるようになります。

module pathは go mod edit コマンドを使うことで変更することもできるようなので、開発当初は仮で付けておくこともできそう。

$ go mod edit -module github.com/user/a-different-repo

処理を実装する場所

以下はGo公式サイトのGetting Startedに書かれているHello Worldのコードです。

Tutorial: Get started with Go - The Go Programming Language

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

この中で必須なのは package mainfunc main() で、main パッケージにある main() 関数がエントリポイントになるので、その中に処理を実装していきます。

開発中の実行方法

主に以下のコマンドを使って実行や動作確認をしていました。

ソースコードを実行する

$ go run main.go

バイナリを作る(この場合はプロジェクト直下に実行ファイルが生成される)

$ go build

プロジェクトから直接コマンドをインストールする( $GOPATH/bin に実行ファイルが生成される )

$ go install

インストールしたコマンドを削除する( $GOPATH/bin から実行ファイルが削除される )

$ go clean -i

配布

実装完了後は、プロジェクト開始時に指定したリポジトリ https://github.com/umi-uyura/dowソースコードをアップして、以下のように go install を実行したところ、コマンドがインストールできました。(WSL上のUbuntuWindowsで確認)

$ go install github.com/umi-uyura/dow@latest

とても簡単。

曜日を日本語表記で出力する

今回のコマンド、基本的には英語で表示しつつ、 LANG 環境変数で日本語などの表記で出力できるようにしようと考えたのですが、どうやらGoとしては標準では日本語リソースを持っておらず、日本語の言語パックを入れていても表示しないようでした。

調べてみたところ、こういった場合は標準の英語出力を文字列置換して対応するのが定石のようです。

Goで日本語曜日を含む日付format - Qiita

実際、今回曜日表記を多言語対応するために利用したライブラリでも、内部実装は同じようなことをしていました。

goodsign/monday

このライブラリのおかげで、40種類の言語での表記に対応できました。

おわり

とりあえずGo言語に取り組むとっかかりができたので、これをベースにしつつ、機能追加やテストの用意、あとはEmacsVSCodeでの開発環境作りなど掘り下げていけたらと思います。

DevToysのツールを呼び出すFlow Launcherプラグインを作った

開発者のスイスアーミーナイフこと DevToys のツールを呼び出す Flow Launcher 用のプラグインを作りました。

umi-uyura/Flow.Launcher.Plugin.DevToysLauncher

以前作ったデスクトップ掃除プラグインに続いて、2つ目のFlow Launcherプラグインです。

umi-uyura.hatenablog.com

DevToysとは

DevToys は、ソフトウェアの開発中によく発生するちょっとした作業のためのさまざまなツールが詰まった、まさに十徳ナイフのようなアプリケーションです。

2022/12/18の時点では、以下のような27種類のツールがあり、今後も追加されていくようです。

ツール名 日本語名
JSON <> YAML JSON <> YAML 変換ツール
Unix Timestamp Converter Unix タイムスタンプ変換
Number Base Converter 基数変換ツール
Cron Parser Cron パーサ
HTML Encoder/Decoder HTML エンコーダー / デコーダ
URL Encoder/Decoder URL エンコーダー / デコーダ
Base64 Text Encoder/Decoder テキスト向けの Base64 エンコード / デコードツール
Base64 Image Encoder/Decoder 画像向けの Base64 エンコード / デコードツール
GZip Encoder/Decoder GZip を利用した文字列の圧縮と展開
JWT Encoder/Decoder JWT エンコーダー / デコーダ
Json Formatter JSON フォーマッター
SQL Formatter SQL フォーマッター
XML Formatter XML フォーマッター
Hash Generator ハッシュ生成ツール
UUID Generator UUID 生成ツール
Lorem Ipsum Generator Lorem Ipsum (ダミーテキスト) 生成ツール
Checksum File チェックサム生成
Text Escape / Unescape テキストのエスケープと解除
Text Case Converter & Inspector 文字列の検査と変換
Regular Expression Tester 正規表現テスター
Text Comparer テキスト比較ツール
XML Validator XML の検証
Markdown Preview Markdown プレビュー
Color Blindness Simulator 色覚異常シミュレーター
Color Picker & Contrast カラーピッカーとコントラスト
PNG / JPEG Compressor PNG / JPEG 最適化
Image Converter 画像フォーマット変換

ひとつひとつは単発のコマンドだったり、そういった機能を提供するウェブサイトを使ったりすることがありますが、まとまっていることで新たに探す必要がなくなるのと、ローカルで使えるというのもメリットかなと思います。

個人的には、Unixタイムスタンプ変換や、日本語を含んでいるURLの内容を把握するために「URL Encoder/Decoder」でデコードしたり、といったあたりをよく使っています。

DevToys Launcherプラグイン

DevToysには機能がたくさんあるのは良いことなのですが、アプリを起動してから目的のツールを使うためにはメニューから選んでいかないといけない点が少々面倒くさいところでした。

DevToysの画面

お気に入りや起動時に開くツールを設定するピンどめという機能はあるものの、どうせならダイレクトに目的のツールを開きたいなと考えていたところ、DevToysのリポジトリコマンドラインで指定のツールを直接開く 方法が載っていることを発見したので、それを元にFlow Launcher上から呼び出すプラグインを作ることにしました。

インストール

使いたいときは、Flow Launcherのウィンドウで

pm install devtoys launcher

と打ち込めばインストールできます。

また、DevToysアプリ自体がインストールされている必要がありますので、 Microsoft Store などからインストールしてください。

使い方

Flow Launcherのウィンドウで dtoys と打ち込むと、呼び出せるツールが一覧表示されるので選択するだけです。

DevToys Launcher実行例

さらに文字を入力することで、ツールを絞り込むこともできます。

日本語化

ツール名はデフォルトでは英語表記としていますが、設定を変更することで日本語表記にすることもできます。

設定変更は画面ではなく、プラグインのプログラムがあるフォルダにある設定ファイルでおこないます。

Flow Launcherのウィンドウに flow launcher userdata と打ち込んで実行すると、Flow Launcherのユーザーデータフォルダがエクスプローラで開かれますので、その中の Plugins\DevToys Launcher-1.0.0\.env が設定ファイルです。( 1.0.0 はバージョン番号なので、今後は変わるかもしれません)

メモ帳などで .env を開いて、 local=en の部分を local=ja に書き換えると、以降の呼び出し時にはツール名が日本語で表示されます。

DevToys Launcherの実行例(日本語表示)

DevToysの他プラットフォーム展開

DevToysは今のところWindows版のみの提供ですが、クロスプラットフォームで使えるようにする計画が進行中なもよう。ただ、まだしばらく時間がかかりそう。

Suggestion: Cross-platform UI (Windows, MacOS, Linux) · Issue #156 · veler/DevToys

macOS向けには独自に開発されている人がいたので、興味ある人は使ってみてください。

ObuchiYuki/DevToysMac: DevToys For mac

FastCopyをwingetでインストールするときにインストール先を指定する

FastCopyをwingetでインストールするときにインストール先を指定する

Windows系最速(? ※公式のまま)のファイルコピー&バックアップツール FastCopy ですが、wingetを使って普通にインストールするとホームディレクトリの直下に C:\Users\<user>\FastCopy のようにインストールされます。(インストーラを手動で実行すればインストール場所を指定できます)

個人的にホームディレクトリ直下にプログラムを置きたくなかったので、場所を変更することにしました。

wingetでは --location オプションを与えることでインストール先を指定することができます。

Program Filesにはインストールできず

はじめはアプリケーションのインストール先として一般的な C:\Program Files にインストールしようとしました。

>winget install FastCopy --location "C:\Program Files\FastCopy"

ところがこの場合、実際にインストールされた場所は C:\Program\FastCopy となっていました。

手動でインストーラを実行した場合は問題なかったので、どうやらwinget経由してFastCopyインストーラにパスが渡されるときに、スペースが含まれていると、そこで途切れてしまっているようです。

%LOCALAPPDATA% にインストールする

というわけで、スペースを含まないパスにインストールした方が良さそうなのだけれど、どこにしたものかと考えていたときに、以下の記事を見つけました。

LocalAppData にアプリケーションをインストールするという選択 - meg_nakagamiの日記

少し調べてみたものの、明確に %LOCALAPPDATA% の用途について説明されているドキュメントを見つけられませんでしたが、たしかに最近のアプリケーションを見ていると %LOCALAPPDATA% にインストールされているものも多いようなので、ここにインストールすることにしました。

>winget install FastCopy --location "%LOCALAPPDATA%\FastCopy"

%LOCALAPPDATA%C:\Users\<user>\AppData\Local とスペースを含まないパスに展開できるので、wingetでのインストールも意図通り C:\Users\<user>\AppData\Local\FastCopy にインストールできました。

便利な使い方

インストール先のパスを環境変数 PATH に追加しておくことで、コマンドプロンプトからも利用することができるようになります。

個人的にはコピーよりも削除で利用することが多く、 doskey で以下のようなマクロを用意しています。

fastrm=fastcopy /cmd=delete /auto_close $1

Node.jsのnode_modulesをまっさらにしたいときなど fastrm node_modules と実行することで削除できます。

ついでに

C:\Users\<user>\AppData には Local 以外に RoamingLocalLow というフォルダがありますが、どういう使い分けなのか気になったところ、以下の記事が参考になりました。

猫科研究所 - Roaming, Local, LocalLow

WSL + Homebrewの環境でMkDocsがModuleNotFoundError: No module named '_ctypes'

Markdownベースでドキュメントサイトを作ることができるPython製のツール MkDocs を使おうとしたところ、 ModuleNotFoundError が発生してコマンドが動かない問題が出てしまいました。

原因はHomebrew (Linuxbrew)で入れていたライブラリで、それを除去してPythonを入れ直すことで解消したので、経緯をメモしておきます。

環境

エラーが出た状況と考察

WSL (Ubuntu)環境で、venvで作ったPython仮想環境に pip install mkdocs でMkDocsをインストールしました。

インストール自体は問題なかったものの、 mkdocs new を実行時にエラーが発生しました。

$ mkdocs new
Traceback (most recent call last):
...
ModuleNotFoundError: No module named '_ctypes'

参考になったのは Pythonでの ctype の依存関係エラー対策の備忘録 / ModuleNotFoundError: No module named ctypes 対策 | simple blog という記事でした。

WSL上にPythonをインストールするにあたり、asdfとそのプラグインであるasdf-pythonを使っています。

asdf-pythonの内部ではpyenvが使われており、pyenvはPythonのバージョンをインストールするときにソースコードからビルドをおこないますが、その際環境に応じて事前に必要なパッケージをインストールしておく必要があります。

Suggested build environment

そういえば、WSL上にPython環境を構築するとき、Homebrewも導入していたこともあり、一度Linuxbrew用の指定パッケージを入れてしまっていました。

umi-uyura.hatenablog.com

ただ、これではうまくいかず、Ubuntu用の指定パッケージを入れることでasdf-pythonが使えるようになりました。

そのため、もしかするとこのときに入れてしまったLinuxbrew用のパッケージが影響しているのではないかと考えました。

Homebrew (Linuxbrew) の依存関係を取り除く

先のpyenvのサイトによると、Linuxbrewの場合は以下のパッケージが指定されています。

brew install bzip2 libffi libxml2 libxmlsec1 openssl readline sqlite xz zlib

よって、これらを削除すれば良いかなと思いましたが、Homebrewの他のアプリケーションなどで使われているものがあるかもしれないので、念のため調べてみます。

参考: Homebrew でパッケージの依存関係を調べる方法 - Qiita

brew uses <package> --installed で、そのパッケージがインストールされている他のパッケージから使われているかどうかを調べることができるとのこと。

$ brew uses bzip2 --installed
$ brew uses libffi --installed
autogen gnutls guile guile@2 libxmlsec1 p11-kit
$ brew uses libxml2 --installed
autogen gettext gnutls libidn2 libxmlsec1 nghttp2
$ brew uses libxmlsec1 --installed
$ brew uses openssl@1.1 --installed
asdf autoconf automake berkeley-db gnutls libevent libxmlsec1 nghttp2 perl unbound
$ brew uses readline --installed
asdf autogen gettext gnutls guile guile@2 libidn2 libxml2 libxmlsec1 nghttp2 sqlite
$ brew uses sqlite --installed
$ brew uses xz --installed
$ brew uses zlib --installed
autogen binutils fnm gcc gettext gnutls libidn2 libxml2 libxmlsec1 nghttp2 sqlite zstd

こう見ると、依存されているものがあるのは libffi libxml2 openssl@1.1 readline zlib でした。

また、 brew deps <package> とすることで、指定パッケージが依存しているパッケージを調べることができます。

今のところ、Homebrewで使っているものとしては asdfgcc、direnv、fnm といったあたりだったので、今度はそれらが依存しているパッケージを調べてみます。

$ brew deps asdf
attr
autoconf
automake
berkeley-db
ca-certificates
coreutils
expat
gdbm
gmp
libtool
libyaml
m4
ncurses
openssl@1.1
perl
readline
unixodbc
$ brew deps gcc
binutils
gmp
isl
libmpc
mpfr
zlib
zstd
$ brew deps direnv
$ brew deps fnm
zlib

こうしてみると、 openssl@1.1 readline zlib あたりは他のものでも使っているようなので、それらはいったん残すことにして、それ以外のパッケージをアンインストールしてみることにします。

$ brew uninstall bzip2 libffi libxml2 libxmlsec1 sqlite xz
Error: Refusing to uninstall /home/linuxbrew/.linuxbrew/Cellar/libffi/3.4.2 and /home/linuxbrew/.linuxbrew/Cellar/libxml2/2.9.12
because they are required by autogen, gettext, gnutls, guile, guile@2, libidn2, nghttp2 and p11-kit, which are currently installed.
You can override this and force removal with:
  brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz

libxml2 に依存しているパッケージがあるため、エラーになりました。

これを無視したい場合は --ignore-dependencies を付ければ良いようなので、オプションを付けて再実行します。

$ brew uninstall --ignore-dependencies bzip2 libffi libxml2 libxmlsec1 sqlite xz

Python再インストールとMkDocsの動作確認

これでHomebrewの不要と思われる依存関係を取り除けたので、Pythonを再ビルドするためにアンインストール&再インストールをおこないます。

$ asdf uninstall python 3.10.2
$ asdf install python 3.10.2
python-build 3.10.2 /home/<user>/.asdf/installs/python/3.10.2
Downloading Python-3.10.2.tar.xz...
-> https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tar.xz
Installing Python-3.10.2...
python-build: use readline from homebrew
python-build: use zlib from homebrew
Installed Python-3.10.2 to /home/<user>/.asdf/installs/python/3.10.2

よく見ると、 python-build: use readline from homebrew のようにHomebrewのパッケージを参照しているものが出力されていました。

もしかすると、当初Pythonをインストールしたときには除去した依存関係も出力されていたのかもしれません。

Pythonインストール後、venvで仮想環境を作ってからMkDocsのインストール&実行してみます。

$ python -m venv .venv
$ . .venv/bin/activate
(.venv) $ python -m pip install mkdocs
(.venv) $ mkdocs new hoge
INFO     -  Creating project directory: hoge
INFO     -  Writing config file: hoge/mkdocs.yml
INFO     -  Writing initial docs: hoge/docs/index.md
(.venv) $ cd hoge
(.venv) hoge$ mkdocs serve
$ mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  Documentation built in 0.05 seconds
INFO     -  [14:21:23] Serving on http://127.0.0.1:8000/

MkDocs、使えるようになりました。

定期メンテナンス

こうしてみると、依存関係でインストールされたものの、その後使われなくなるパッケージというのもけっこうありそうなので、そういったメンテナンスするのに以下の記事が参考になりそう。

Homebrew で使われていない formula を削除する :: by and for engineers