Personal tools
You are here: Home ブログ sugawara Stuff gotanda-emacs 菅原の資料
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
jlineで日本語を使えるようにする。 sugawara 2009-12-10
五反田Emacsの資料 sugawara 2009-10-19
trac-ticket.el sugawara 2007-11-19
Emacs Lisp 勉強会(バッファとウィンドウ編) sugawara 2007-10-22
Categories
Emacs
勉強会
java
 
Document Actions

菅原の資料

Click here to get the file

Size 8.0 kB - File type text/plain

File contents

-*-org-*-

anything のソースを書けるようになってみる + anything.el を読んでみる。

* なんとなく
anything 便利なんだけど、案外自分でソース書いてる人いない。
巷にあふれてるソースだけで十分っちゃ十分なんだけど、やっぱり自分で書けると楽しい。

というわけで、anything のソース書き講座。
# 実は本人はそこまで anything 信者じゃなかったりもする。
# 便利で好きだけどね。年寄りなもんで。

一応ソースのさんぷるとかと anything.el を行ったり来たりしながら話すつもり。
もしかしたら、あちこちしすぎてわかりづらいかもしれない。

で、anything の便利な使い方は他の人の方が知ってると思うからやんない。
あとで教えてくださいませ。

* 対象
elispがなんとなく読める人
  - 色々わかってる人にはものたりないかも
  - 全然知らない人には難しいかも

わからなかったらさくっと質問してください。
変なこと言ってたらさくっとつっこんでください。

* anything-sources
言わずとしれた anything の情報源。
ここにソースをごりごり書いてくと M-x anything で使えるようになる。

たとえば

(setq anything-sources
      '(anything-c-source-buffers+
        anything-c-source-file-name-history))

とか。


ちょっと anything の中身のはなし。

M-x anything すると
 - いろいろ hook 実行したりしてから
 - anything-initialize を実行
   - そこで
       (anything-funcall-foreach 'init)
     ってのをやって
 - minibuffer-local-map を anything-map にしてあげて
 - anything-update を実行。最初のバッファ更新。
 - ほいで、anything-preselect で最初の候補選んで
 - あとは
     (read-string (or any-prompt "pattern: ")
                  (if any-resume anything-pattern any-input))
   ってして anything-map にまかせたげる。

anything-update はそーすまわして anything-process-source をぐりぐりよぶ。
入力があるごとにこいつがよばれる。

anything-process-source は一個のソースが相手。
anything-compute-matches でマッチした子を表示してくれる。

anything-compute-matches は anything の中核。
candidate 属性とか使って絞り込みをしてくれる。

* ソース書いてみる
name, action, candidates で大体はなんとかなる。

(setq anything-c-source-sample
      '((name . "hoge")
	(candidates . ("fuga" "mage"))
	(action . (("Insert" . insert)
		   ("Search" . (lambda (x) (search-forward x nil t)))))
	))

(anything
 '(anything-c-source-sample))

 - candidates に書いたやつを anything が出してくれる
 - action に書いたやつを選んだときに anything が実行してくれる
   - 複数書いたら RET したら最初のが選ばれる
   - TAB すると全部

candidates には関数も書ける。

(setq anything-c-source-sample2
      '((name . "buffers")
	(candidates . (lambda () (mapcar 'buffer-name (buffer-list))))
	(action . (("Select" . switch-to-buffer)
		   ("Kill" . kill-buffer)))
	))

(anything
 '(anything-c-source-sample2))

candidates は (DISPLAY . REAL) っていうペアのリストも返せる。
一覧に表示させたいものと、action で処理したいものが違うときなんかに有用。

(setq anything-c-source-sample3
      '((name . "buffers2")
	(candidates . (lambda () 
			(mapcar 
			 (lambda (x)
			   (cons
			    (if (buffer-file-name x)
				(concat (buffer-name x) 
					"[" (buffer-file-name x) "]")
			      (buffer-name x))
			    x
			    ))
			 (buffer-list))))
	(action . (("Select" . switch-to-buffer)
		   ("Kill" . kill-buffer)))
	))

(anything
 '(anything-c-source-sample3))

ひとつの候補が複数行ある場合は multiline 属性を使う

(setq anything-c-source-sample4
      '((name . "multi")
	(candidates . ("fuga\nhoge" "mage\nhoge"))
	(action . (("Insert" . insert)
		   ("Search" . (lambda (x) (search-forward x nil t)))))
	(multiline . t)
	))

(anything
 '(anything-c-source-sample4))


ふつーは candidates はキャッシュしてくれる。volatile 属性つけるとキャッシュしない
ついでに init も。こいつは anything を実行するときに最初の一回だけ実行してくれる。
volatile 使わないときは candidates でがんばっちゃってもおけ。

(setq anything-c-source-sample5
      '((name . "hoge")
	(init . (lambda () (setq hoge 0)))
	(candidates . (lambda () 
			(setq hoge (1+ hoge))
			(list "hoge" (format "hoge%d" hoge))))
	(action . (("Insert" . insert)
		   ("Search" . (lambda (x) (search-forward x nil t)))))
	(volatile . t)
	))

(anything
 '(anything-c-source-sample5))


candidates-in-buffer つかうとバッファの中身を候補にしてくれる。
どっちかっていうとパフォーマンスを気にするときむけ。

candidates-in-buffer を使うには init で anything-candidate-buffer を使っ
てバッファとソースを紐付けしておく。anything-candidate-buffer の引数は
 - バッファ
   - そのバッファをマーク
 - global ってシンボル
   - ワークのバッファを作ってそれを登録。with-current-buffer と一緒に。
 - それ以外のシンボル
   - ソースだけじゃなくって、起動したバッファとも紐付ける。resume向けかな?
ふつーはglobal使うことが多いんじゃないかな。と。

あと、anything-current-buffer って変数に anything を起動したときのバッファがはいってる。
べんり。

(setq anything-c-source-sample6
      '((name . "hoge")
	(init . (lambda () (with-current-buffer (anything-candidate-buffer 'global)
			     (insert-buffer-substring anything-current-buffer))))
	(candidates-in-buffer)
	(action . (("Insert" . insert)
		   ("Search" . (lambda (x) (search-forward x nil t)))))
	(volatile . t)
	))

(anything
 '(anything-c-source-sample6))


** anything-compute-matches をちょいと見てみる。
match とって candidates をキャッシュからとってぐりぐり。
かんたん。
match は候補の一致のさせかたを変えるんだけど、 anything-match-plugin とのあいしょう悪し。
anything-default-match-functions が必ず match 関数に入っちゃう。

* anything お他のアプリとくみあわせる
anything 関数はソースのリストを引数に取れる。で、このソースのリストの中
身って別にシンボルじゃなきゃいけないって訳じゃない。

ってことは関数の中でリストをぐりぐり作ってそれを anything で表示するっ
てこともできるわけだ。

ソースの数が固定で中身をぐりぐりするだけじゃなくって、ソースの数を可変にするのもあり。
あんま見ないけど、descbinds-anything なんかはそんなことやってる。

* プラグインを書く
プラグインを書くには anything-compile-source-functions に関数を追加する。
関数はソースを引数に取ってソースを変えす。
ようするにプラグインってのはソースを変換するためのしかけってこと。

たとえば anything-match-plugin は match に機能を追加するためのプラグインだし、
candidates-file-plugin は candidates-file って属性を追加するためのプラグイン。


ためしに簡単なプラグインをひとつだけ。
候補にかならず草をつけるプラグイン

(defun anything-compile-source--grass (source)
  (lexical-let 
      ((trans (assoc-default 'candidate-transformer source))
       (grass (assoc-default 'grass source)))
    (setq grass (or grass "ww"))
    `((candidate-transformer
       . ,(cons
	   (lambda (cands)
	     (mapcar (lambda (c) 
		       (let ((d (if (consp c) (car c) c))
			     (r (if (consp c) (cdr c) c)))
			 (cons (concat d grass) r)))
		     cands))
	   (if (listp trans) trans (list trans))))
      ,@source)))

(add-to-list 'anything-compile-source-functions 'anything-compile-source--grass)
(anything-document-attribute 'grass "grass plugin"
  "wwww.")

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.