Emacs for AndroidをTermuxと一緒に使う

# Emacs for AndroidをTermuxと一緒に使う

[0. 前書き](#0-前書き)

[1. Termuxのバックアップと再インストール](#1-Termuxのバックアップと再インストール)

[2. Emacs for Androidの設定](#2-Emacs-for-Androidの設定)
[2.1 early-init.elの作成](#21-early-initelの作成)
[2.2 init.elの作成](#22-initelの作成)

[3. 結び](#3-結び)

# 0. 前書き
前記事となる[EmacsのAndroidポートのビルド](https://qiita.com/ayatakesi/items/c857c907c8c7e675da9e)では、Emacsのmasterブランチ(いずれ次バージョンであるemacs-30になるブランチ)にmergeされたEmacsのAndroidポートについて、現時点で盛れる機能すべてを盛ったバージョンを付属するドキュメントにしたがってビルドした体験を記しました。その記事ではでは少ししか触れませんでしたが、そのビルド体験記?には機能を盛るのとは少し異なる設定が1つ潜んでいます。それは_Emacsの共有ユーザーIDとして`com.termux`を指定する_という点です。これを設定してしまうと、もしデバイスに(Google PlayやF-Droidによって署名されているはずの)Termuxがインストールされている場合にはインストールができません(そのTermuxを削除、もし使用を継続したければEmacsと同じキーで署名したバージョンを再インストールする必要がある)。わたしが当然のことのようにこんな制約を含んだビルドを公開したかというと、以下2点に要約されるわたしの独断が理由なのではないでしょうか(前記事を書いてた途中で気づいたんですが、共存できないようなバージョンとかをビルドするなんて端から念頭になかったんですよ)。

- Emacsの多くの機能は、(おそらく)元々のデフォルトのインストール対象先であったLinux環境を背景としている([松山朋洋様の良記事を参照](https://qiita.com/akmiyoshi/items/1c19d1484049683b4cec))

- すでにTermuxというLinuxエミュレーション環境を使役している人であれば、その環境を利用できないEmacsにあまり魅力を感じない(2大キラーアプリの1つであるorgは使えますが、magitは無理でしょう)

という訳で、わたしのような要件をもつユーザーのために、Termuxと共存可能なバージョンのEmacsを実際にTermuxと共存させるために、わたしが行ったことをざくっと紹介したいと思います。

# 1. Termuxのバックアップと再インストール

以前からTermuxを使っている場合には、すでに多くの資産(インストール済みアプリやドキュメント)がある筈です。何もせずに再インストールしてしまうとそれらをすべて失ってしまいます(署名キーが違うアプリへのアップグレードは認められていないので削除して新規インストールしなければならない)。そんなのあり得ませんよね? (わたしは無理)

# 1.2 Termuxのバックアップ

2022年の11月2日以来、それまでTermuxの主要な配布元であったGoogle Playから、F-Droid等に配布元が変更されました(Android APレベル29以降への適応断念による; [Termux Google Play](https://wiki.termux.com/wiki/Termux_Google_Play)を参照)。それ以降にF-Droid版へ移行した人であれば体験済みかもしれませんが、まずはTermuxのバックアップについて説明します。既存のTermuxと新たにインストールする予定のTermuxは、バージョンが同じであれば署名キー以外同じアプリです。バージョンが違う場合でも大丈夫だと思いますが(わたしは問題が発生した経験はありません)、心配な人は

1. Google Play版の最新版(v0.101)に更新してTermuxをバックアップ(Google Play版を使っている人)
2. F-Droid版の最古版(v0.102)をインストールしてバックアップをリストア
3．F-Droid版の最新版(v0.117)にアップグレードしてTermuxをバックアップ
4. [Emacs for Android](https://sourceforge.net/projects/android-ports-for-gnu-emacs/files/termux/)のTermux(termux-app_apt-android-7-release_universal.apk)をインストールしてバックアップをリストア

とかがいちばん段差が少ない移行方法です。さてTermuxのバックアップについて説明します。方法については[Termux WikiのBacking up Termux](https://wiki.termux.com/wiki/Backing_up_Termux)に詳しい解説があります。ざっと説明すると

1. バックアップできるように`termux-setup-storage`コマンドで`termux-setup-storage`への書き込み権限を付与する

:::note info
`/sdcard`は内部ストレージのようですが、空きが少ない人は外部SDのような場所でも問題はありません。以降の説明でバックアップ先を適宜読み替えてください。
:::

2. /data/data/com.termux/filesの`home/`と`usr/`をバックアップ

```shell:command
tar -zcf /sdcard/termux-backup.tar.gz -C /data/data/com.termux/files ./home ./usr
```

:::note alert
Termuxで外部SDにアクセスする場合には、Termuxからは`~/storage/external-X`からアクセスできます。このフォルダはファイルマネージャのような他のアプリからも見える場所なので安心?してしまいがちですが、アンインストールによってここも消えます。でも上記のコマンドではバックアップされないので忘れずにどこかへ退避しましょう(わたし消しました、2回も)。
:::

3. Termuxをアンインストールします。Termux:Tasker等のプラグインも同一共有ユーザーIDなのでアンインストールする必要があります。

:::note info
これらのプラグインについては、現在のところリストアできません(`home/`配下にある設定ファイルはリストアされるがプラグインは消えます)。これらの使用を続けたい場合には自前でビルドしてEmacsのキー`emacs.keystore`で署名する必要があります。参考になるか判りませんが、たとえばTermux:Taskerであればemacs-compat-termux-taskerのような名前で自前でビルドして署名した[レポジトリ](https://github.com/ayatakesi/emacs-compat-termux-tasker)もあるので、よろしければ参考にしてください(Github Actionsで、`build.grade`のkeystoreファイルを参照する箇所を`emacs.keystore`に変更しているだけです)。
:::

4. Emacs共存版?のAPKファイルをインストール

5. Termuxを`termux-setup-storage`を実行する

6. バックアップをリストア

```shell:command
tar -zxf /sdcard/termux-backup.tar.gz -C /data/data/com.termux/files --recursive-unlink --preserve-permissions
```

`termux-backup`や`termux-restore`といったコマンドもあるようですが、使ったことがないのでよく判りません。

# 2. Emacs for Androidの設定

以下、わたしが設定を行った際の手順を記しますが、[Emacs for AndroidのREADME](https://sourceforge.net/projects/android-ports-for-gnu-emacs/files/)にしたがって行っただけなので他にも色々やり方はある筈です。ここで行う設定とは、Emacsの設定を通常行う際のようにinitファイル類の記述を意味しています。Android版Emacsを起動して編集してもよいし、Termuxから設定することもできます(TermuxからもAndroid版Emacsのディレクトリーは参照できるようになっている筈なので)。

:::note info
Android版Emacsのホーム`~`は`/data/data/org.gnu.emacs/files`、Termuxのホーム`~`は`/data/data/com.termux/files/home`といった名前のディレクトリーです(`/data/data`の部分はでデバイスによっては異なるかもしれません)。いちいち手打ちも面倒くさいので`ln -s /data/data/org.gnu.emacs/files (~/EfAのようにTermux側から簡単に参照できるリンク名)`、`ln -s /data/data/com.termux/files/home (~/TのようにAndroid版Emacs側から簡単に参照できるリンク名)`のように、ディレクトリーへのリンク(Windows風にいうとディレクトリーへのショートカット)を作成しておけば先々楽ができると思います
:::


# 2.1 early-init.elの作成

`/data/data/org.gnu.emacs/files/.emacs.d/`というディレクトリーがある筈なので、そこに以下の内容で`early-init.el`というファイルを作成します。これはAndroid版EmacsがTermuxにあるコマンドを優先して実行できるようにするための設定です(これを行わないとAndroidのコマンドを呼び出してしまうのです)。

```elisp:early-init.el
(setenv "PATH" (format "%s:%s" "/data/data/com.termux/files/usr/bin"
		       (getenv "PATH")))

(setenv "LD_LIBRARY_PATH" (format "%s:%s"
				  "/data/data/com.termux/files/usr/lib"
				  (getenv "LD_LIBRARY_PATH")))

(push "/data/data/com.termux/files/usr/bin" exec-path)
```

# 2.2 init.elの作成

`/data/data/org.gnu.emacs/files/.emacs.d/`に`init.el`というファイルを作成します。自分用のパッケージの設定等を除いた基本設定は以下のように行いました。

- modifier-barモードの有効化

ctrlやmetaのないオンスクリーンキーボードを使っている場合に、それらの修飾キーをツールバーから押せるようにします。[emacs-develの議論](https://lists.gnu.org/archive/html/emacs-devel/2023-07/msg00052.html)から作成されたモードです。

```elisp:init.el
;; ツールバーに修飾キー押下用バーを表示する
(modifier-bar-mode 1)
```

- 音量キーへのctrl/metaの割り当て

Termuxを使ったこちがあればボリュームダウンキーをctrlとして使うことに慣れていると思います。ここでは上記スレッドの[後発投稿](https://lists.gnu.org/archive/html/emacs-devel/2023-07/msg00193.html)からそれに近い設定を頂きました。

```elisp:init.el
;; ボリュームアップを<meta>、
(define-key local-function-key-map (kbd "<volume-up>")
            #'tool-bar-event-apply-meta-modifier)

;; ボリュームダウンは<ctrl>
(define-key local-function-key-map (kbd "<volume-down>")
            #'tool-bar-event-apply-control-modifier)
```

:::note info
実はこの投稿は上記を解決策として答える投稿ではなく、「これで物理キーでctrlとmetaを押せるようになったけど、ctrl+metaは物理キーだけでは押せないのでどうすればよいか?」と質問している投稿です。それにたいするヒントも[後続の投稿](https://lists.gnu.org/archive/html/emacs-devel/2023-07/msg00218.html)にて与えられていますが、それ以降MLでは発展しませんでした(多分)。わたしは端末でよく使われる回避策である`meta-ctrl-X` = `esc ctrl-X`  = `ctrl-[ ctrl-X`で回避してます。この音量キーをツールバーのコマンドにマップする方法において特徴的なのが、その押し方です。通常の物理キーボードやTermuxのボリュームキーのctrlは押しっぱなしにして`X`を押下すると`ctrl-X`、escキーを押したあと離してから`X`押下で`meta-X`になりますが、上記で設定した音量キーはあたかも後者のescの場合のように振る舞うのです。何を言っているか判らないと思いますが、わたしにもよく判らないので実際に試してみてください。
:::

# 3. 結び

\~ *Emacs: The Software Engineer's Swiss Army Knife* \~

上記の'Swiss Army Knife'という形容表現、知ってるなあと思いググってみたら[Emacsのバグ報告用ML](https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs)のサブタイトルとしても使われてる、昔からある有名な形容表現のようです。そして時は下って2023年「これぞまさしくスイスアーミーナイフだよなあ」などとひとりごちつつAndroid版のEmacsを試している今日この頃でございます。

おわり

# a. おまけ

試しにいくつか有名なのを実行してみました。Termuxでコマンドが存在するかどうか等でできることは変わってきます。パッケージのインストールは`package-list-packages`で行いました('package--check-signature-content: failed to verify signature...'とかのエラーは`(setq package-check-signature nil)`で回避)。

- orgモードでorgのマニュアルを表示

![Screenshot_20231012-155215.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134669/8b30cf76-8fcb-6df6-552f-82c6f9712076.jpeg)

- magitでEmacsのmasterブランチのログを表示

![Screenshot_20231012-155151.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134669/8c289715-ac87-e84e-99c0-d642f67ca0fe.jpeg)

- かの有名なspaceemacs(まだ修整が必要みたいです)

![Screenshot_20230926-235117.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134669/106e3dcf-52ca-654c-a449-1707cb61b85d.jpeg)

- 2023/11/01 追記
わたしはあんまりパッケージをインストールしないので、`init.el`はすごく小さいです。なのでTermuxのTUI版の`init.el`を共有して使っちゃうために以下のような設定で試しています。

```elisp:/data/data/org.gnu.emacs/files/.emacs.d/early-init.el
;; 独自に追加。HOMEをTermuxのHOMEにしています。
(setenv "HOME" "/data/data/com.termux/files/home")

(setenv "PATH" (format "%s:%s" "/data/data/com.termux/files/usr/bin"
		       (getenv "PATH")))
(setenv "LD_LIBRARY_PATH" (format "%s:%s"
				  "/data/data/com.termux/files/usr/lib"
				  (getenv "LD_LIBRARY_PATH")))
(push "/data/data/com.termux/files/usr/bin" exec-path)
```

`system-type`が`gnu/linux`の場合には、わたしはノートのLinuxとTermuxはinit.elを共有してないのでTermux、`android`の場合にはEmacs for Android用のセッティングです。共有不可な部分がでてくればここに押し込めていく予定です。

(AndroidにインストールせずにEmacs for Androidで使うだけのフォントであれば、ttfファイルを`/data/data/org.gnu.emacs/files/fonts/`に置いとけば使えます)

([Emacs for Android配布サイトのREADME](https://sourceforge.net/projects/android-ports-for-gnu-emacs/files/)のFAQ 20.で示されるとおり、メニューの`options`の`Set Default Font`はうまいこと動かないので、上記フォルダに放り込んだらEmacsを再起動して`*scratch*`とかで`(font-family-list)`で確認して表示されればそのフォントを使える筈です)

```elisp:/data/data/com.termux/files/home/.emacs.d/init.el
(pcase system-type
  ('gnu/linux
   (message "system-type is %s" system-type)
   (xterm-mouse-mode 1)
   (global-set-key [mouse-4] #'scroll-down-line)
   (global-set-key [mouse-5] #'scroll-up-line))
  
  ('android
   (message "system-type is %s" system-type)
   (modifier-bar-mode 1)
   (define-key local-function-key-map (kbd "<volume-up>")
	       #'tool-bar-event-apply-meta-modifier)
   (define-key local-function-key-map (kbd "<volume-down>")
	       #'tool-bar-event-apply-control-modifier)
   (set-frame-font "Source Code Pro-8")))
```