org-mode のキーバインド、その先

#はじめに

全国1万人の org-mode ユーザの皆様，こんにちは．[@takaxp](http://twitter.com/takaxp)です．

この記事は，[Emacs Org-mode](http://orgmode.org) を気に入り，キーバインドもそれなりに身についた，でも何か物足りないなぁと感じている，そんなあなたにピッタリの機能紹介です．

org-mode を使い始めてまず初めに覚えるキーバインドといえば，`M-return` でしょう．`*` で始まる新しい heading を追加するコマンドです．さらに `M-S-return` を押下して，小さな感動を覚えたユーザも多いでしょう．

また，どんなに長いキーバインドになろうとも org-mode に出来ぬことなど無いと信じる一部のユーザは，複雑な表を作って `C-u C-u C-c C-c` の押下でセルの計算結果を更新したり，`C-u C-u C-c C-x C-s`の押下で古いタイムスタンプのアイテムを refile して喜んでいることでしょう．

ところが org-mode のキーバインドには「その先」があるのです．そう，スピードコマンドです．たった一つのキーストロークでも，様々な機能を呼び出せるのです．

# スピードコマンド

スピードコマンドは org-mode に実装されている標準機能ですが，デフォルトでは OFF の状態です．次のようにして，有効化します．

```el
(setq org-use-speed-commands t)
```

無事に使えるようになったら，heading の先頭の`*`にカーソルを置いて，`n`や`p`を押下してみましょう．カーソルが heading 間をサクサクと移動するのを確認できます．

どんなコマンドが準備されているのかは，heading の先頭の`*`にカーソルを置いて，`?`を押下すればコマンドの一覧が表示されます(`M-x org-speed-command-help`に相当)．以下に一覧化するのは，org-mode 8.3.2 にある機能です．

- カーソル移動
- アウトラインの情報更新
- アウトラインの移動
- 表示更新
- タスク管理
- その他

## カーソル移動

`n`や`p`以外にも，カーソルを動かすコマンドが準備されています．例えば，`f`や`b`も同じようにカーソル移動の機能ですが，同じレベルの heading での移動に限定されます．個人的に一番使うのは，org-refile のスピードコマンド． 

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| n | C-c C-n | 下のアウトラインへ |
| p | C-c C-p | 上のアウトラインへ |
| f | C-c C-f | 下のアウトラインへ（同一レベル限定） |
| b | C-c C-b | 上のアウトラインへ（同一レベル限定） |
| u | C-c C-u | 上位レベルのアウトラインへ |
| g | C-c C-w | org-refile の機能で別アウトラインにジャンプ（アウトラインは転送されない） |
| j | C-c C-j | org-goto．バッファ内移動 |
| F | C-c M-f | 次のコードブロックへ |
| B | C-c M-b | 前のコードブロックへ |


## アウトラインの情報更新

使用頻度が高いのはやはり `t` ですね．通常 `C-c C-t d` とするところが `t d` で済むようになり，少し小指に優しいです．

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| t | C-c C-t | タスク状態変更の選択肢を表示（{TODO,DONE} など）|
| , | C-c , | 優先度変更の選択肢を表示（{A,B,C,<space>}から選ぶ） |
| 0 | C-c , \<space\> | 優先度を取る去る |
| 1 | C-c , a | 優先度を#Aに |
| 2 | C-c , b | 優先度を#Bに |
| 3 | C-c , c | 優先度を#Cに |
| : | C-c C-c | タグ変更 |
| W |  | プロパティにAPPT_WARNTIMEをを追加 |
| # | C-c ; | ステータスをコメントに変える（COMMENT を付ける） |

## アウトラインの移動
`i` で新しいアウトラインの追加と，org-refile を `w` で呼べるのが良いですね．

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| U | M-\<up\> | アウトラインを上に移動 |
| D | M-\<down\> | アウトラインを下に移動 |
| r | M-\<right\> | アウトラインのレベルを下げる |
| l | M-\<left\> | アウトラインのレベルを上げる |
| R | M-S-\<right\> | アウトラインのレベルをツリーごと下げる |
| L | M-S-\<left\> | アウトラインのレベルをツリーごと上げる |
| w | C-c C-w | org-refile．アウトラインの転送 |
| a |  | アウトラインをアーカイブ（確認を求める） |
| i | M-\<enter\> | 新しいアウトラインを追加 |
| ^ | C-c ^ | 子のアウトラインをソーティング |



## 表示更新
`=` をたまに使う程度ですかね．ナローイングの制御は，[org-tree-slide](https://github.com/takaxp/org-tree-slide) がお薦め（ステマ）．

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| c | TAB | org-cycle．順方向のサイクル |
| C | Shift-TAB | org-shittab．逆方向のサイクル |
| s | C-x n s | ナローイング．再度押すと widen できる． ~~戻すには M-x widen (C-x n w)~~ |
| = | C-c C-x C-c | org-columns．戻すには カラムビューの状態で q |

## タスク管理

`<`と`>`が地味に便利．

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| I | C-c C-x TAB | タスクの時間計測開始 |
| O | C-c C-x C-o | タスクの時間計測終了 |
| e | C-c C-x e | org-set-effort．作業予定時間の設定 |
| E | C-c C-x E | org-inc-effort．作業予定時間の追加 |
| v | C-c a | Agenda コマンドの呼び出し |
| < | C-c C-x < | org-agenda の解析対象を限定する |
| > | C-c C-x > | org-agenda の限定された解析対象を解除する |

## その他

`@`が便利ですね．

|コマンド|通常の入力|内容|
|:--:|:--:|:--|
| @ | C-c @ | アウトラインを選択（一般には C-\<space\> C-n） |
| / | C-c / | org-sparse-tree．条件にあうアウトラインを抽出 |
| o | C-c C-o  | heading にあるリンクを開く |
| \<space\> | | 属しているアウトラインのパスをミニバッファに表示 |
| ? |  | スピードコマンドのリストを表示 |

# スピードキーを拡張

標準で使える機能もかなり充実していることがおわかりと思います．しかし，使っているのは Emacs です．当然の如く自由に拡張できます．カスタム変数に `org-speed-commands` があるので，これを使うだけです．次の例は，`a`とほぼおなじですが，確認表示をスルーしてアウトラインを直接アーカイブします（`C-c $`）．

Update[2021-07-31] **Org 9.5 より、 `org-speed-commands-user` から `org-speed-commands` に変数名が変更されています。**

```el
(add-to-list 'org-speed-commands '("$" call-interactively 'org-archive-subtree))
```

上で紹介した `t d` の連続で`DONE`にするのすら面倒な私は，`d`押下の一発で完了させるよう次の設定を使っています．

```el
(add-to-list 'org-speed-commands '("d" org-todo "DONE"))
```

デフォルトでは `s` が `org-toggle-narrow-to-subtree` に設定されています~~が，ナローイングを解く `widen` が設定されていないので，自分で拡張しておくと便利です~~．

NOTE[2019-11-04]: 最新版では `s` が正しく動作するので，以下のように `S` を設定しなくても大丈夫です．好きなだけ `s` を連打してください．

```elisp
(add-to-list 'org-speed-commands '("S" call-interactively 'widen))
```

また自分で関数を定義して，それを呼び出すことも可能です．次は，`P`の押下でプロパティに`FONT`という項目をトグルする例です．

```el

(add-to-list 'org-speed-commands '("P" my:proportional-font-toggle))

(defcustom use-proportional-font nil
  "The status of FONT property"
  :type 'boolean
  :group 'org-mode)

(set-face-attribute 'variable-pitch nil
                    :family "Verdana"
                    :height 125)

(defun my:proportional-font-toggle ()
  (interactive)
  (setq use-proportional-font (not use-proportional-font))
  (if use-proportional-font
      (org-entry-put nil "FONT" "PROPORTIONAL")
    (org-delete-property "FONT")))
```

あるいは，周期タスクを `DONE`する時に，周期を解いて完全に終了させることも可能です．次の例では，`D`押下するだけで，"++1w" などと指定されている周期性が "++0w" に変更され，リピートせずに `DONE`へ直接ステータスを変更できます．

```el
(defun my:org-todo-cancel-repeat (&optional ARG)
  (when (org-get-repeat)
    (org-cancel-repeater))
  (org-todo ARG))
(add-to-list 'org-speed-commands '("D" my:org-todo-cancel-repeat "DONE"))
```


さらに，`org-use-speed-commands` は，`t` 以外にも関数を受け付けます．スピードコマンドの振る舞い自体を制御したいときに有効です．

# まとめ

この記事では，org-mode のスピードコマンド（Speed Key）を紹介しました．スピードコマンドを使うと，ストローク回数が明らかに減りますので，作業効率が確実に高まります．

ただ一点注意するべきなのは，**IMEで日本語入力が効いているとコマンドが発行されない**ことです．heading の先頭の`*`ではIMEをスルーする等のカスタマイズが必要かもしれませんね．

あるいは，heading で作業しているときは強制的にIMEをOFFにするとか．以下はMacの例です．

```el
(when (fboundp 'mac-toggle-input-method)
    (run-with-idle-timer 1 t 'ns-org-heading-auto-ascii))

(defun ns-org-heading-auto-ascii ()
    (when (and window-focus-p
               (eq major-mode 'org-mode)
               (or (looking-at org-heading-regexp)
                   (equal (buffer-name) org-agenda-buffer-name)))
      (my:ime-off)))

(defun my:ime-off ()
      (interactive)
      (mac-toggle-input-method nil)
      (run-hooks 'my:ime-off-hook))
```

（参考）http://orgmode.org/manual/Speed-keys.html