Hatena::Groupemacs

Emacs/Lisp/Drill

2014-03-10

.emacsの秘伝のタレ解消をはじめました

22:58 | はてなブックマーク - .emacsの秘伝のタレ解消をはじめました - Emacs/Lisp/Drill

ずっと秘伝のタレだった.emacsをモダンなものに変え始めた

理由は、「Mac上での環境が必要になったため」

あまりに浦島太郎過ぎてツラい。特に「自作elがpackage.elに載っていない(自業自得)」がツラい。

そのツラさを加味しても便利。すごいいい感じ。世の中進んでるなー。

取りあえず https://github.com/k1LoW/dotfiles で管理開始。

というわけで、Emacsの老兵はここを去ります。

以降は http://k1low.hatenablog.com/ で。

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]

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

2012-03-19

expand-region.elとmark-multiple.elをいじっていたらsense-region.elみたいなものができた

23:58 | はてなブックマーク - expand-region.elとmark-multiple.elをいじっていたらsense-region.elみたいなものができた - Emacs/Lisp/Drill

no titleno titleを見ていて、

「おー便利そうだなー。expand-region.elはsense-regoin.elとどう違うのかな」といじってみた。


expand-region.elとsense-regoin.elの違いとしては

  • expand-region.elは選択範囲の拡大縮小に特化しているのでsense-region.elのような矩形選択はない。
  • 選択範囲拡大の挙動はexpand-region.elのほうがいい感じがする。
  • 最初の実行でsense-region.elはset-mark-commandなのに対し、expand-region.elはいきなり範囲選択になっている。

という感じ。


選択範囲拡大の挙動はとても好みなんだけど、やっぱり操作感としてはsense-region.elに慣れているので、そっちに合わせたいなーと関数を作り始めた。

さらにmark-multiple.el内のEmacs Lispをみていたら、inline-string-rectangle.elが矩形選択っぽい挙動をしていたので、

それを拡張するadviceも適当に追加してみた。


そしたら劣化sense-region.elっぽいものができた。


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


ただのラッパーなんだけれども、それなりに使いやすくて満足。矩形選択後のリージョンコピーもできる(sense-region.elと挙動が違うけど)

最近sense-region.elのサイトにアクセスできないので、とりあえず代替として拡張していこうかなと思う。


それよりも

expand-region.elとmark-multiple.elの作者は同じなんだけれども、リポジトリをみていたら鬼軍曹.elと全く同じコンセプトのEmacs Lispを作っていた。


GitHub - magnars/hardcore-mode.el: Disable arrow keys + optionally backspace and return



この人とは仲良くできそうな気がする。

2012-01-10

anything-css.elを作ってみたら意外に便利

21:27 | はてなブックマーク - anything-css.elを作ってみたら意外に便利 - Emacs/Lisp/Drill

anything-css.elを作ってみたら意外に便利。なんで今までなかったんだろ?

anything-css.elのできた経緯

結構前にCSSを一から自分で書く時代は終わっていて、デザイナーさんにコーディングしてもらったり、Twitter Bootstrapだったりと、CSSのコーディングルールが自分の頭の中に入っていないことが多い。なので、任意のidやclassのスタイルがどの.cssファイルに書いてあるのかというもの頭に入っていない。

で、いつもFirebugで該当.cssファイルを探していたのだけれども、ふと「これanythingでよくね?」と思って作ってみたら意外に便利だったという話。久しぶりのanything脳


GitHub - k1LoW/anything-css: Stylesheet selectors anything.el interface


プロジェクト内の.cssファイルを対象にセレクタで絞り込み検索するイメージ。

キャッシュ戦略

anything-find-project-resources.elばりにfindコマンドを利用するのだけれども、「プロジェクト内」と言えどもやっぱり重い。(ちなみにプロジェクトディレクトリの判定方法はanything-find-project-resources.elと全く同じ。)

ということで、キャッシュ戦略が必要になってくる(戦略というほどではないけども)。「一定期間キャッシュする」とか「ずっとキャッシュして任意のタイミングでコマンドでキャッシュを更新する」とか「ファイル保存時にキャッシュを更新する」とかいろいろ方法があるなか、今回はなんとなく「アイドル時間にキャッシュを更新する」形で実装してみた。デフォルトでは10秒アイドル時間がつづけばキャッシュを更新する。

最適かどうかはこれから使い続けて検討するつもり。キャッシュ更新処理を完全に別プロセスで実現できたらいいのに。


良いアイデアがあればガンガンforkしてってください。ソースを盗みにいきます。

2011-12-28

空気のようなEmacs Lisp -2011 冬-

14:43 | はてなブックマーク - 空気のようなEmacs Lisp -2011 冬- - Emacs/Lisp/Drill

Emacs Advent Calendar 2011ということで。

27日目はd:id:k6kyさんの Anything-BibTeX を作りました - そんなことないよです。

TeXは大学の論文以来使っていないので、とても懐しかったです。

当時は「黒い画面」が大嫌いで、Emacsなんてもっての外でした。良い思い出です。


さて、28日目ということで既に今年は出遅れました。今年は目立ったことが何もできなかった1年でした。

今年も3年連続で「空気のようなEmacs Lisp」を紹介します。

一昨年の「Calendar->空前のEmacsブーム->社内でEmacsが浸透」作戦は見事に失敗に終わってしまい、

今年こそはとEmacs Bootcampを実施するも結果はでず、相変わらずEmacserは社内ではマイノリティです。

今年もAdvent Calendarはレベルが高くて困りますね。


今回も、個人的に「全てのエディタで標準でよくね?」と思えるくらい便利なのに、意外に浸透していないっぽいEmacs Lispを紹介します。

導入していない人はだまされたと思ってインストールしてみてください。


Dynamic Macro (dmacro.el)

普段使いのエディタというのはプログラムだけでなく、ちょっとしたテキスト編集にもつかうものです。

やりたい編集のやり方が浮かんできますから。

例えば特殊な置換とか行頭の単語の削除とか、「あー自分ならこうやっている」というのが浮かぶのではないでしょうか。


ちなみに社内にはそんなエディタが「Excel」という猛者がいますが、正直この人に勝てる気がしません。


個人的感覚ですが、ちょっとしたテキスト編集というのはだいたい「繰り返し操作」だったりします。

ただ、その繰り返しのルールが毎回異なるんですよね。

Emacsにはそういった操作のために「キーボードマクロ」というものがありますが、あまり使いやすいものではありません。

とくに「ちょっとした」もののためにキーボードマクロを設定するのも億劫です。

というかキーボードマクロが使いこなせていない人のほうが多いと思っています。


そういった繰り返し操作を「よきにはからって」記録して、いつでも実行できるようにしてくれるEmacs Lispが今回紹介するDynamic Macroです。


以下の設定を.emacsに記述します。その際にdmacro.elをロードパスに設置しておきます。

今回の設定では繰り返し指定キーを[Ctrl + r]にしていますが、自由に設定して構いません。

(defconst *dmacro-key* "\C-r" "繰返し指定キー")
(global-set-key *dmacro-key* 'dmacro-exec)
(autoload 'dmacro-exec "dmacro" nil t)

dmacro.elは公式ページでも丁寧に紹介されているように「繰り返し操作」をよきにはからって覚えて、その後の操作をキー1つで繰り返し操作を実行してくれるEmacs Lispですが、これを単なる「文字列の繰り返し」だけだと思ってはいけません。


dmacro.elは「キー操作の繰り返し」をよきにはからってくれるのです。


例えば、以下のような文字列があったりします。

abc abc def abc def abc abc abc abc def abc abc abc def def abc abc abc abc def abc abc abc def abc abc
abc abc def abc def abc abc abc abc def abc abc abc def def abc abc abc abc def abc abc abc def abc abc
abc abc def abc def abc abc abc abc def abc abc abc def def abc abc abc abc def abc abc abc def abc abc
abc abc def abc def abc abc abc abc def abc abc abc def def abc abc abc abc def abc abc abc def abc abc

『この文字列の「abc」の偶数番目のみ「fgh」に編集したい』ときどうしますか?

ちなみに編集後の正解は以下です。

abc fgh def abc def fgh abc fgh abc def fgh abc fgh def def abc fgh abc fgh def abc fgh abc def fgh abc
fgh abc def fgh def abc fgh abc fgh def abc fgh abc def def fgh abc fgh abc def fgh abc fgh def abc fgh
abc fgh def abc def fgh abc fgh abc def fgh abc fgh def def abc fgh abc fgh def abc fgh abc def fgh abc
fgh abc def fgh def abc fgh abc fgh def abc fgh abc def def fgh abc fgh abc def fgh abc fgh def abc fgh

手動でやるとなかなか骨が折れそうです。適当なタイミングで「def」がはいっていることで、単純な文字列置換ではうまくいかなそうです。


ところが、dmacro.elでは

『i-search(C-s)の「abc」の検索結果の2番目まで移動して、それを「fgh」に変更する』

というキー操作を繰り返すことができるのです。検索まで含めて繰り返すことができるのです。


一般的なキーバインドだと[C-s abc C-s C-m Backspace Backspace Backspace fgh]のキー操作の繰り返しです。

この操作を2回ほど繰り返して、後は[C-r]を連打すれば編集完了です。すばらしい。



まとめ

今回も「空気のようなEmacs Lisp」としてdmacro.elを紹介しました。

自分はこのEmacs Lispのおかげで何度となく楽をしています。

皆さんも是非設定してみてください。


明日はd:id:poginさんです。