2025-12-10 ,

org-captureをタッチで使いやすくする

Android版のEmacsを使ってみて、org-captureが使いづらいというのはすぐに気がつきました。私はorg-captureコマンドを C-c r に割り当てていますが、Ctrlを押さなければならない時点でタッチパネルからでは使いづらいです。その後もテンプレートを選ぶのにキー入力が必要ですし、最後の C-c C-cC-c C-k もタッチでは打ちづらいです。org-captureは「キーボードで素早くノートを取る」ことに最適化されていますが、これがタッチでは逆に障害となっています。

なので、まずはテンプレートの選択はGUIメニューで行うようにします。

テンプレート選択メニュー
図1: テンプレート選択メニュー

そして入力が終わった後の C-c C-cC-c C-wC-c C-k と書いてある部分を押せるようにします。

ヘッダーラインにキャプチャ終了アクションが表示されている
図2: ヘッダーラインにキャプチャ終了アクションが表示されている

作成したコードは次の通りです。

;;; org-captureをタッチで使いやすくする。

;; マウス/タッチ使用時はテンプレート選択をx-popup-menuにする。

(defun my-org-mks (table _title &optional prompt specials)
  (unless prompt (setq prompt "Select: "))
  (x-popup-menu t
                (list
                 prompt
                 (cons ""
                       (nconc
                        (cl-loop for item in table
                                 when (cddr item) ;; Prefixの説明を除く
                                 collect (cons (cadr item) item))
                        (cl-loop for item in specials
                                 collect (cons (cadr item) (car item))))))))

(defun my-org-mks-around (old-fun &rest args)
  (if (use-dialog-box-p)
      (apply #'my-org-mks args)
    (apply old-fun args)))

(advice-add 'org-mks :around 'my-org-mks-around)

;; header-lineのキーヘルプをボタンにする。

(defun my-org-capture-make-clickable (str keymap)
  "STRの中にあるfaceがhelp-key-bindingである部分をボタンにして押せるようにします。"
  (setq str (copy-sequence str))
  (let ((pos 0))
    (while pos
      (let ((face (get-text-property pos 'font-lock-face str))
            (next (next-property-change pos str)))
        (when (eq face 'help-key-binding)
          (let* ((end (or next (length str)))
                 (key-str (substring str pos end))
                 ;; ↓ここはKEY-STRによっては良くないかもしれない。
                 (command (lookup-key keymap (kbd key-str))))
            (when command
              (let ((km (make-sparse-keymap)))
                (define-key km [down-mouse-1] command)
                (define-key km [header-line down-mouse-1] command)
                (put-text-property pos end 'keymap km str)
                (put-text-property pos end 'pointer 'hand str)))))
        (setq pos next))))
  str)
;; EXAMPLE: (my-org-capture-make-clickable (substitute-command-keys "\\<org-capture-mode-map>Capture buffer.  Finish `\\[org-capture-finalize]', refile `\\[org-capture-refile]', abort `\\[org-capture-kill]'.") org-capture-mode-map)

(defun my-org-capture-init ()
  (defvar org-capture-mode-map)
  (setq header-line-format
        (my-org-capture-make-clickable
         ;; ここはheader-line-formatを指定しても良いのですが、そのままだと
         ;; 長すぎてC-c C-kが画面の右からはみ出して押せないので短くします。
         (substitute-command-keys "\\<org-capture-mode-map> Finish:\\[org-capture-finalize] Refile:\\[org-capture-refile] Abort:\\[org-capture-kill]")
         org-capture-mode-map)))

(add-hook 'org-capture-mode-hook 'my-org-capture-init)

テンプレート選択のGUIメニュー化はorg-mks関数にadviceを仕込むことで実現しました。そこではy-or-n-p等がやっているように、use-dialog-box-pを使ってマウス・タッチ操作からのコマンド起動かを判断して、必要ならGUIでメニューを表示します。 my-org-mksx-popup-menuを使ってテンプレート選択メニューを表示するorg-mksの代替物です。私はあまり複雑なテンプレートの指定をしていないので、これでorg-mksの全てのユースケースをカバーしているかは分かりません。org-mksはざっと調べた限りorg-captureorg-insert-structure-templateでしか使われていないみたいです。

終了アクションをタッチでできるようにするために header-line 上の C-c C-c などと書かれている部分をボタン化することにしました。 window-tool-bar を使って上に○×ボタンを表示するのも面白いかなと思ったのですが、面倒なのでこの方法にしました。 my-org-capture-make-clickable 関数は、文字列(header-line-format)中の特殊なface(help-key-binding)が指定されている部分に、keymapテキストプロパティを追加してdown-mouse-1イベントに反応するようにします。kbdを使っている部分がキー設定によっては正しく動かない可能性はありますが(キー割り当てが M-x org-capture-finalize のように表示されている場合など)、デフォルトの状態なら問題は無いでしょう。

org-captureコマンドはすでにメニューバーにも追加していましたが、ツールバーにも追加しておきます。

メニューバーに「+」ボタンを追加したところ
図3: メニューバーに「+」ボタンを追加したところ

そのあたりのコードは以前の記事に追記しておきました。

Emacsのツールバーをカスタマイズする | Misohena Blog

これでスマートフォンからの入力がさらに便利になりました。

org-captureは前々から少し疑問を感じていた仕組みではありました。私は特定のファイルに新規エントリーを追加するという単純な目的にしか使っていません。それならもっと単純なやり方がある気がします。テンプレートを選んだら、即特定のファイルを開いて新規エントリーを挿入し、ポイントを適切な位置に移動すれば十分です。キャンセルしたければundoすれば良いのですから。なので今回の改良ではノートのキャプチャを行う仕組み自体を書き直そうかとも思いました。

しかしorg-captureにはノートを取った後に何事もなかったかのように元の状態に戻るという特徴があります。思いついた時にノートを取って、またすぐに元の作業に戻る。それがorg-captureの良いところなのかもしれないなと思い、今回はorg-captureを活かす改良で留めてみました。また不満を感じたら全体を書き直すかもしれません。