dired の改良

# 背景

Emacs を使い続けて5年くらいになる。Eshell をshell として長く使っていたが、 作業ディレクトリが増えるに連れ、コマンドで移動するのが面倒になってきたため、 ディレクトリの移動、ファイルの実行はdired で行うようになった。 dired をカスタマイズして大分満足できるものになってきたため、 このページでは、自分のdired モードの強化に関して述べる。

# 環境

-   Linux 4.19.2 (arch Linux)
-   GNU Emacs 26.1

# カレントディレクトリをdired で開く

ファイルを開いているときに、カレントディレクトリをdired で素早く開きたいときが あるため、簡単だが下記の関数を作った。

```emacs-lisp
(defun find-file-current-dir ()
  "Find-file current directory"
  (interactive)
  (find-file default-directory))
```

キーバインドは `M-.` にあてた。コードは[キーバインドの変更例](#キーバインドの変更例) を参照。

# dired-open 周辺

dired-open はdired-mode でファイルを開く際に、ファイルごとに開くアプリケーションを 指定できるパッケージである。画像ファイルや動画ファイルなどを指定したアプリケーション で開くことが可能になる。似たようなパッケージにrunner もあるが、こちらは使ったことが ない。

## dired-open の導入と設定

MELPA から手に入る。 インストール方法は、[dired-open.el : diredから画像・メディアファイルやPDFなどを開く - るびきち](http://emacs.rubikitch.com/dired-open/) を参照する。

ファイルの拡張子とアプリケーションの関連付けは下記のようにした。 （アプリケーションは各人自分の環境に合ったものに書き換えて下さい。）

```emacs-lisp
(custom-set-variables
'(dired-open-extensions
   (quote
    (("pdf" . "zathura")
     ("svg" . "inkscape")
     ("jpg" . "imv")
     ("png" . "imv")))))
```

## 便利関数の作成

dired-open, dired はデフォルトの設定でも十分使えるが、いくつか改良したいところがあった。

-   `dired-up-directory`, `dired-open-file` はディレクトリ移動のたびに バッファが増えてしまう。
-   ブラウザのリンク先を新しいタブで開くときのように、 `dired-open-file` でディレクトリ移動のとき、別ウインドウに新たなバッファを作成し、 もとのバッファを選択したままにすることができるとよい。
-   `dired-up-directory` で行き先のディレクトリのバッファを別ウインドウで開いてほしい。

これらを踏まえ、

-   `dired-open-file` でディレクトリ移動の際は、バッファをkill する関数 `kill-current-buffer-and/or-dired-open-file`
-   `dired-up-directory` で元のバッファをkill する関数 `kill-current-buffer-and-dired-up-directory`
-   `dired-open-file` でディレクトリ移動のとき、別ウインドウに新たなバッファを作成し、 もとのバッファを選択したままにする関数 `dired-open-file-other-window`
-   `dired-up-directory` で行き先のディレクトリのバッファを別ウインドウで開く `dired-up-directory-other-window`

を作成した。

```emacs-lisp
   (defun kill-current-buffer-and/or-dired-open-file ()
    "In Dired, dired-open-file for a file. For a directory, dired-find-file and
kill previously selected buffer."
    (interactive)
    (if (file-directory-p (dired-get-file-for-visit))
        (dired-find-alternate-file)
      (dired-open-file)))

  (defun kill-current-buffer-and-dired-up-directory (&optional other-window)
    "In Dired, dired-up-directory and kill previously selected buffer."
    (interactive "P")
    (let ((b (current-buffer)))
      (dired-up-directory other-window)
      (kill-buffer b)))

  (defun dired-open-file-other-window ()
    "In Dired, open file on other-window and select previously selected buffer."
    (interactive)
    (let ((cur-buf (current-buffer)) (tgt-buf (dired-open-file)))
      (switch-to-buffer cur-buf)
      (when tgt-buf
        (with-selected-window (next-window)
          (switch-to-buffer tgt-buf)))))

  (defun dired-up-directory-other-window ()
    "In Dired, dired-up-directory on other-window"
    (interactive)
    (dired-up-directory t))
```

# ファイル・ディレクトリの名前以外を表示しない

私はバッファの左に行番号を現在の行を基準に表示している( `display-line-bumbers-mode` を使用)が、ファイルの特性を 表示しているとファイル・ディレクトリがどの行にあるのか分かりづらいため、 パーミッションなどの表示を隠した。なお、表示したいときは"(" キー （ `dired-hide-details-mode` ）で表示できる。

```emacs-lisp
(add-hook 'dired-mode-hook 'dired-hide-details-mode)
```

# 更新日時でソート

デフォルトでは、名前順でdired は並んでいるが、更新日時順で表示 するように変えた。

```emacs-lisp
(setq dired-listing-switches "-alth")
```

# キーバインドの変更例

dired バッファはデフォルトで読み取り専用となっており、vim のように "j", "k" で移動するキーバインドが便利だと感じる。また、"h", "l" は それぞれ"ディレクトリ階層のup", "ディレクトリを展開" とした。

```emacs-lisp
(with-eval-after-load 'dired
 (bind-keys :map dired-mode-map
          ("j" . dired-next-line)
          ("k" . dired-previous-line)
          ("h" . kill-current-buffer-and-dired-up-directory)
          ("l" . kill-current-buffer-and/or-dired-open-file)
          ("f" . kill-current-buffer-and/or-dired-open-file)
          ("H" . dired-up-directory-other-window)
          ("L" . dired-open-file-other-window)))

(bind-key "M-." 'find-file-current-dir)
```

# まとめ

dired の自分なりのカスタマイズ方法を載せた。特に、[便利関数の作成](#便利関数の作成) のところは dired-open を使っていない人にも、 `dired-open-file` の部分を `dired-find-file` などに変えれば使用可能なのでオススメしたい。