Hatena::Groupemacs

Emacs/Lisp/Drill

 | 

2012-03-21

sense-expand-region.elの選択範囲拡張ロジックをexpand-region.elから拡張してみた

18:18 | はてなブックマーク - sense-expand-region.elの選択範囲拡張ロジックをexpand-region.elから拡張してみた - Emacs/Lisp/Drill

sense-expand-region.elの選択範囲拡張ロジックはexpand-region.elのer/expand-regionをそのまま使っていたんだけれども、一部どうしても修正したいところがあって拡張してみた。

何が問題だったのか

er/expand-regionはer/try-expand-listの範囲選択関数を順に実行していき、「現在の選択範囲よりも大きく」かつ「最も小さな選択範囲の」範囲選択関数で選択範囲を拡張していく。

ただ、この「最も小さな選択範囲」というのが曲者で、範囲選択のタイミングで選択開始位置が移動してしまった場合、またその開始位置で選択範囲関数を実行していってしまう。

さらにer/expand-regionでは選択開始位置だけでなく選択終了位置も広がる方向でないといけない。

expand-region.elは範囲選択関数を増やせたり拡張できるのが売りなのだけれども、例えば「最初の位置から行末までの範囲選択」する関数と「最初の位置から行頭までの範囲選択」する関数の両方は成立しない(位置によってどちらかが実行される)

自分は、「行選択」関数を加えようとしてこの問題に直面した。(行選択をしてしまうとどうしても選択開始位置が行頭になってしまうので、多くの範囲選択関数がとばされてしまう)


どう変えたのか

簡単にいうと最初の開始位置をうまく保持しておいて、あくまで「現在の選択範囲よりも大きい」順に範囲選択関数を実行できるようにした。


具体的に説明

以下のようにer/try-expand-listに行選択関数を追加した場合(sense-expand-region.elでは個人的趣味でデフォルトで追加している)。

(defun ser/mark-whole-line ()
  (interactive)
    (set-mark (save-excursion
                (end-of-line)
                (point)))
      (back-to-indentation))

(setq er/try-expand-list (append
                          er/try-expand-list
                          '(ser/mark-whole-line)))

カーソル位置がapp[e]ndにあったとき

(setq er/try-expand-list (app[e]nd
                          er/try-expand-list
                          '(ser/mark-whole-line)))

expand-region.elだと

(setq er/try-expand-list ([append]
                          er/try-expand-list
                          '(ser/mark-whole-line)))
(setq er/try-expand-list ([append
                          er/try-expand-list
                          '(ser/mark-whole-line)]))
(setq er/try-expand-list [(append
                          er/try-expand-list
                          '(ser/mark-whole-line))])
([setq er/try-expand-list (append
                          er/try-expand-list
                          '(ser/mark-whole-line))])
[(setq er/try-expand-list (append
                          er/try-expand-list
                          '(ser/mark-whole-line)))]

と選択範囲が広がって「行選択」は華麗に無視されるのだけれども

sense-expand-region.elだと

(setq er/try-expand-list ([append]
                          er/try-expand-list
                          '(ser/mark-whole-line)))
[(setq er/try-expand-list (append]
                          er/try-expand-list
                          '(ser/mark-whole-line)))

↑行選択がされて

(setq er/try-expand-list ([append
                          er/try-expand-list
                          '(ser/mark-whole-line)]))

↑他の関数も実行される

(setq er/try-expand-list [(append
                          er/try-expand-list
                          '(ser/mark-whole-line))])
([setq er/try-expand-list (append
                          er/try-expand-list
                          '(ser/mark-whole-line))])
[(setq er/try-expand-list (append
                          er/try-expand-list
                          '(ser/mark-whole-line)))]

というわけで

sense-expand-region.elがまたいい感じになった。うまく切り出せたらexpand-region.el側にもPull Requestを出してみる(思想が違うのでだめかもしれないけど)。


GitHub - k1LoW/emacs-sense-expand-region: (/ (+ sense-region.el expand-region.el inline-string-rectangle.el) 5) ;=> sense-expand-region.el !!

追記[2012/04/14]

先ほど丁寧にリジェクトされた感じになりました

 |