Last Modified:
use Module行をキレイにソートする #Emacs #Perl
Perlコード中のuse Module;
をASCII順にソートする場合、Emacsのsort-lines
を使うと
use Digest::MD5;
use Digest;
みたいになってちょっと気持ち悪い。:
が0x3aで;
が0x3bだから当たり前なんだけど、やっぱり階層順
use Digest;
use Digest::MD5;
になって欲しい。
それからプラグマ(e.g. strict
)とかプラグマっぽい小文字なモジュール(e.g. Digest::base
)が先に来るように、つまり
use Digest::MD5;
use Digest::base;
use autodie;
ではなく
use autodie;
use Digest::base;
use Digest::MD5;
になって欲しい。
というわけで、そうなるようなソート関数を書いた。
(defun cperl-sort-lines-helper (region)
(let ((words (split-string (buffer-substring-no-properties (car region) (cdr region)) "[ ;]+" t))
(diff (- ?a ?A)))
(concat (mapcar #'(lambda (c)
(cond
((and (<= ?A c) (<= c ?Z)) (+ c diff))
((and (<= ?a c) (<= c ?z)) (- c diff))
(t c)))
(vconcat (nth 0 words) (nth 1 words))))))
(defun cperl-sort-lines (reverse beg end)
"モジュールの並べ替えのためにモジュール名以降を無視してソートする。"
(interactive "P\nr")
(save-excursion
(save-restriction
(narrow-to-region beg end)
(goto-char (point-min))
(let ;; To make `end-of-line' and etc. to ignore fields.
((inhibit-field-text-motion t))
(sort-subr reverse 'forward-line 'end-of-line nil nil
#'(lambda (a b) (string< (cperl-sort-lines-helper a) (cperl-sort-lines-helper b))))))))
- 書いたと言ってもほとんど
sort-lines
のコピーで、sort-subr
の呼び出しにpredicate
を渡すようにしただけ。- 古いEmacsだと渡せないかも知れないので注意(24.2.1で渡せることを確認済)
- ちなみに最初は
(defadvice sort-subr)
でやってた。ただそれだと影響範囲が大きそうなので別関数に変更した。
predicate
の中身は- 半角空白かセミコロンで区切る
- 1番目と2番目だけ("use"と"Module")を取り出す
- 大文字と小文字を反転させる(小文字が先に来るようにするため。もしかしたらcase-tableをいじるのかも知れないけど良く分からなかったので)
- すみません。lisp newbieです。添削お願いします。