Elisp 入門
表記については Elisp という場合と Emacs Lisp という場合と,さらには部分 的な大文字・小文字の違いによっても実際には区別するようですが,ここでは単 純に Emacs 用の言語という意味合いで使います.Lisp というのはリスト処理を 得意とする言語です.人工知能分野の研究で多く使われていたりします.Elisp はそれをベースにした言語です.
C-j は emacs に式の評価を指令します.その結果 "This is foo" が表示された と思います.setq は「指示した変数に値を設定する」という関数で,先の例を 実行した結果 foo 変数に "This is foo" という値が設定されます.バッファに 表示されたものは,この設定の結果(式の評価結果)です.(setq foo "This is foo")
次にこの設定を確認してみましょう.
とだけ打ち込んでから C-j を入力して下さい."This ..." と表示されましたね? これは foo 変数に設定された値を示しています.foo
(setq foo-alist '(("^foo" . "Foo") ("^bar" . "Bar") (".+". "any")))
(while foo-alist
(car (car foo-alist))
(setq foo-alist (cdr foo-alist)))
例:foo 変数(数値), bar 変数(文字列)の値を確認する
(message (format "foo:%d bar:%s" foo bar))
---
[2001/12/25]
elisp: 浮動少数点の整数への変換は (truncate, floor, ceiling, round) の
4つ.逆に整数からの変換には float を使う.
-->floor とかで整数になるってのも不思議な実装よのう...
---
[2001/07/24]
Mew のサマリーフォーマットを変更する.
-->昔 (mew が MH ベースだった頃) は mew-scan-form という elisp 変数
で変更できたようだが,現在は IM というものベースになり,
~/.im/Config ファイル中の Form= の行で変更するのらしい.
-->~/.im ディレクトリがない場合は imsetup コマンドで初期設定を行な
うこと.
-->例:Form=%3n %m %d %i[%3K: %-14P] %s
-->フォーマットの冒頭は %n のメッセージナンバーから始めないと mew で
メッセージ本体を表示できない.
-->%C で月名が表示できるらしいのだが,これを指定するとサマリー名が取
得できず失敗する.
-->%C を冒頭に指定していて数字でないためだったらしい.%n を指定後
に %C を入れると動作した.
-->"Jul 24" のように月名+日で表示したいのに,%d では 月/日となり
日だけを指定する指定子がない.
-->フォーマット変更の反映は mew を起動後に O (mew-summary-pack) を押
して行なう.
---
[2001/05/14]
elisp: ie を起動させるのに start-process を使うとうまくいかない。
w32-shell-execute に "open" url の2つの引数を渡すとブラウザは選択でき
ないが現在開いているブラウザ内に URL を開くことはできる(新たにウィン
ドウを開くにはどうするんだろう?)。
---
[2000/12/01]
elisp: 改行 RET のキー割り当ては \C-m で行う.
---
[2000/11/23]
elisp: prin1-to-string と format の違い
-->(format "%s" foo) では foo の内容に " が含まれるとこれを除外する.
(prin1-to-string foo) では " も含めて文字列にする.
-->(print1-to-string foo t) とすると " は含めず無加工となる.
---
[2000/05/29]
elisp で Mule/Emacs が X 上で動いているかの識別
-->window-system 変数を見る.X 上であれば x そうでなければ nil が返
る.
---
[1999/07/07]
elisp で現在リージョンに入っている単語に対して incremental-search を掛
けるには?
---
[1999/07/05]
elisp:save-excursion の中で一時的にこれを抜け出して実際の移動を行うよ
うにはできないか?
---
[1999/06/02]
elisp で文字列 split はどうやるか?
-->こんなのを組んでみた.
(defun string-split (split-char str)
(let (list (m 0) (n 0))
(catch 'done
(while 1
(if (not (setq m (string-match split-char str))) (throw 'done 1)
(setq list (cons (substring str 0 m) list))
(setq str (substring str (+ m 1)))
)))
(setq list (cons (substring str n) list))
(reverse list)
))
[2002/01/23]
-->split-string というのがあったよ...
---
[1999/06/01]
elisp の連想リストで指定キーのリストが何番目にあるかはどうやって取得す
るのか?
-->こんな関数を書いてみた.
(defun nthassoc (key list)
(if (not (assoc key list)) nil
(let ((n 0))
(catch 'done
(while list
(setq id (car (car list)))
(if (numberp key) (setq key (int-to-string key)))
(if (numberp id) (setq id (int-to-string id )))
(if (string= id key) (throw 'done 1))
(setq n (+ n 1))
(setq list (cdr list))))
n)))
---
[1997/12/27]
elisp:指定位置のリストを置き換える(あってる?)
-->(setq aaa '(a b c d e f g h i j k))
(append
(reverse (nthcdr (- (length aaa) 8) (reverse aaa)))
'(0)
(nthcdr 9 aaa))
[1999/06/01]
-->こんな関数にしてみたがどうか...
(defun nthdelete (n list)
(nthreplace n list nil))
(defun nthinsert (n list ins)
(nthreplace n list (reverse (cons (nth n list) ins))))
(defun nthreplace (n list rep)
(append
(reverse (nthcdr (- (length list) n) (reverse list)))
rep
(nthcdr (+ n 1) list)))
[2002/05/04]
-->次のほうが元のリストを破壊するけどシンプル
(setcar (nthcdr n list) 'ins)
---
[1999/06/01]
elisp でのリスト要素の置き換えってどうやるんだっけ?
-->一つずつリストを見ていって新しいリストを作成するのだったか?
---
[1999/03/19]
Emacs で空いているキーバインドを探しやすくするにはどうすればいいか?
-->なにか elisp パッケージはないの?
---
[1999/01/26]
elisp での外部コマンド起動は shell-command ではなく start-process を使
うべきか?
-->see.
file:$YATEX/yahtml.el
-->(start-process NAME BUF PROGRAM &rest ARGS)
-->ex.
(start-process "mecl" nil "mecl" "~/.cshrc")
---
[1999/01/13]
elisp で telnet 接続
-->from. telnet.el
-->(make-comint "telnet" "telnet")
(accept-process-output (get-process "*telnet*"))
(send-string "*telnet*" "oshiro\n")
(send-string "*telnet*" "passwd\n")
(send-string "*telnet*" "exit\n")
-->Web 接続は??
(defun get-url (path host &optional method)
(if (null method) (setq method "GET"))
(setq bufname "jugo-www")
(switch-to-buffer
(make-comint bufname "telnet" nil host "http"))
(erase-buffer)
(setq bufname (concat "*" bufname "*"))
(send-string bufname (concat method " " path " HTTP/1.0\n\n"))
(switch-to-buffer (get-buffer"*scratch*")))
(defun format-html-buffer ()
(switch-to-buffer "*jugo-www*")
(goto-char (point-min))
(replace-string "
" "")
(goto-char (point-min))
(if (re-search-forward "^$")
(kill-region (point-min) (point)))
(goto-char (point-max))
(forward-line -3)
(kill-region (point) (point-max))
(goto-char (point-min))
(mapcar (lambda (f) (goto-char (point-min)) (replace-regexp f ""))
'(
"</H[0-9]> *\n?"
"</?A\\( [^>]+\\)*> *\n? *"
"<!--.+--> *\n?"
"<!--.+\n?"
".*--> *\n?"
"<BODY\\(.+\\)*> *\n? *"
"<HEAD\\(.+\\)*> *\n? *"
"<HTML\\(.+\\)*> *\n? *"
"</?TITLE\\(.+\\)*> *\n? *"
"</?[IB]> *\n? *"
"</BODY\\(.+\\)*> *\n? *"
"</HEAD\\(.+\\)*> *\n? *"
"</HTML\\(.+\\)*> *\n? *"
))
(mapcar
(lambda (f) (goto-char (point-min)) (replace-regexp f "\n"))
'("</?DL> *\n? *" "</?UL> *\n? *"
"<H[0-9]> *\n? *"
"</?DIV\\(.+\\)*> *\n? *"))
(mapcar
(lambda (f) (goto-char (point-min)) (replace-regexp f "\n * "))
'("<LI> *\n? *" "<DT> *\n? *" "<DD> *\n? *"))
(goto-char (point-min))
(replace-regexp " *\n?<HR> *\n? *" "<HR>")
(goto-char (point-min))
(replace-string "<HR>" "\n------")
)
(get-url "/" "jugo")
(format-html-buffer)
-->w3/url.el の次の関数が参考になるかも.
url-open-stream
url-http
url-retrieve-internal
url-retrieve
-->url-open-strem でも telnet で接続してるみたい
(start-process name buffer "itelnet" host service)
-->itelnet って何?
---
elisp: gnus のサマリーで b を押すと gnus-group-check-bogus-groups が呼
び出され,(たぶん)その時点でサーバ側に存在していないニュースグループ
を削除する.このとき一つずつ削除するかどうかを聞いてくるので削除件数が
多いとこの確認がうっとおしい.これを一気に行なうには ESC ESC で
eval-expression に入り (gnus-check-bogus-newsgroups nil) とする.
---
Emacs/Mule で関数や変数を探すときに help-for-help してからの補完を利用
することが多い.特に動作変更を行うための設定変数を探すのに有効な感じ.
---
Emacs でのエイリアス
-->defmacro では interactive に呼び出せない??
-->関数形式にして,該当関数を call-interactively で呼び出すように
した.
(defun ct () (interactive) (call-interactively 'canna-touroku-region))
-->defalias というものがあった.これを使えば大丈夫.
(defalias 'ct 'canna-touroku-region)
---
Emacs/Mule でのメールエイリアス更新.
-->(build-mail-aliases &optional FILENAME)
non-interactive 関数
---
~/.canna ファイルは Emacs が読む elisp ではなく canlisp という別の処
理系のものだったらしい.canlisp のドキュメントはなんとか見つけたけど,
mule から呼び出せるかんなの関数ってどこにドキュメントが存在しているん
だろうか?
---
Emacs のファイルの冒頭でのモード指定('# -*- memo -*-' など)で,サブモード(?,auto-fillとか)を追加して指定するのはどうやるの?
-->冒頭指定ではないけど (setq memo-mode-hook 'turn-on-auto-fill) で
指定可能
-->c.f. Info:emacs-jp:Major Modes:
---
Emacs でのモード指定について
-->vid.Info:emacs-jp:Choosing Modes
---
elisp での let と let* の違い
-->表面的にはどちらの動作も局所変数の作成で同じ.ただし,let* では局
所変数への初期値設定で既に出現している局所変数の値を使用すること
ができる.
-->eljman.info:ローカル変数をバインドする より抜粋
-->(setq Y 2)
(let (X (Y 1) (Z Y)
(list X Y Z))
-->nil 1 2
スコープに入る前の Y の値が Z に設定された
-->(setq Y 2)
(let* (X (Y 1) (Z Y))
(list X Y Z))
-->(nil 1 1)
スコープに入ってからの Y の値が Z に設定された.
---
emacs lisp の eq と equal は違う
-->eq は対象(アトム?)そのものが同じかどうか
-->equal は字面や値が同じかどうか
---
elisp のモード指定をファイルオープン時に自動的に行うときには,そのモー
ド移行が行われているときにはウィンドウはまだポップアップされていないら
しい.だから,set-window-start などはそのままでは有効とならない
(goto-char, re-search-forward などは有効となる).
-->set-window-start を使うためには switch-to-buffer で明示処理する必
要がある?
(switch-to-buffer (buffer-name (current-buffer)))
---
elisp で外部起動コマンドを取り込むには
-->(shell-command ...)
(call-process ...)
---
elisp でポイント設定
-->p に値を設定 ((setq p (point)) など).
(set-window-point (get-buffer-window (current-buffer)) p)
---
elisp でカーソル位置に記述されている情報を取得するのは ...-at-point と
いう関数を使うのか?
-->edic.el などのデフォルト引数の取得に使えるはず.
-->vid. ~mule/lisp/help.el:function-called-at-point
-->(defun show-word-at-point ()
(interactive)
(let (b e w)
(save-excursion
(backward-word 1)
(setq b (point))
(forward-word 1)
(setq e (point))
(setq w (buffer-substring b e))
(message "%s" w))))
---
elisp でカーソル位置のテキストから変数名を取得するには?
-->variable-at-point?
---
elisp では save-excursion と indent-to-left-margin は相性が悪い?
-->(save-excursion ...(indent-to-left-margin)...) という場合にカレン
トポイントが行頭スペースだと,ゼロカラムに位置が戻ってしまう??
-->save-restriction という関数もあるらしい.これはなに?
-->(narrow-to-region b e) の影響除去に使う.
---
elisp でバッファ・ウィンドウを操作
-->buffer
-->buffer-list
-->bufferp: (bufferp (get-buffer "*scratch*"))
-->window
-->windowp
-->one-window-p
-->delete-window
-->window-live-p
-->selected-window
-->select-window
-->next-window
-->set-window-buffer
---
リスト要素の削除と保存
-->(progn
(setq a '("b" ("c" "d")("e" "f")))
(if t (setq g a) (setq g (copy-alist a)))
(delq (car (cdr g)) g)
(eq a g)
)
---
elisp:delq でリスト要素の削除
-->(progn
(setq a-lis '(a b c))
(setq a-cdr (cdr a-lis))
(setq a (car a-cdr))
(setq a-cdr (delq a (copy-alist a-cdr)))
)
-->(c) # b が削除できた
(a b c) # a-lis はそのまま
-->(progn
(setq a-lis '(a (b c) (d e)))
(setq a-cdr (cdr a-lis))
(setq a (car a-cdr))
(setq a-cdr (delq a (copy-alist a-cdr)))
)
-->((b c) (d e)) # (b c) が削除できない
-->(progn
(setq a-lis '(a (b c) (d e))) # '(a b c) でも動作は同様
(setq a-cdr (cdr a-lis))
(setq a (car a-cdr))
(setq a-cdr (cdr (delq a a-lis)))
)
-->((d e)) # これなら削除できる
(a (d e)) # a-lis にも反映した
---
elisp:指定位置のリストを置き換える(あってる?)
-->(setq aaa '(a b c d e f g h i j k))
(append
(reverse (nthcdr (- (length aaa) 8) (reverse aaa)))
'(0)
(nthcdr 9 aaa))
---
elisp で指定位置のリストを抜きだす
-->(setq foo '(a b c))
(elt foo 2)
-->c
---
elisp で連想配列を使う
-->(progn
(setq foo '(("bar" (1 2 3)) ("baz" (4 5 6))))
(assoc "baz" foo))
-->RET VALUE:("baz" (4 5 6))
---
elisp でリスト操作
-->(setq foo-alist '(("^foo" . "Foo") ("^bar" . "Bar") (".+". "any")))
(while foo-alist
(car (car foo-alist))
(setq foo-alist (cdr foo-alist)))
---
elispメモ
-->先行引数のチェック current-prefix-arg
一定時間の処理停止 sit-for
インタラクティブ呼出チェック interactive-p
---
elisp で,C-u で与えた値を得る関数
-->prefix-numeric-value
---
elisp で生成した変数を消去するにはどうやるの?
---
Elisp での候補の選択と学習の例
-->yatex.el:YaTeX-cplread-with-learning
-->completing-read-with-history
(completing-read prompt table predicate require-match init)
-->glog-require-bbs-type
---
elisp の mapcar は何の処理をするの?
-->ex. (mapcar 'make-local-variable (... indent-line-function ...)
-->(mapcar 'foo (A B C..)) の形式で
(foo A) (foo B)... の繰り返し呼出しを実現できる.
---
Mule でドラッグ&ドロップってできるのかしら?
-->vid.
http://www.asahi-net.or.jp/~pi9s-nnb/myelisp.html
難波 elisp ページ
http://www.asahi-net.or.jp/~pi9s-nnb/dired-dd_toc.html
Dired Drag and Drop
---
Elisp の引数を対話的に入力する際に (default: foo) と聞いてきてくれる場
合がある.あれはどうやって実現してるのかなぁ.
-->elisp で (default:XXX) とデフォルト候補を処理するにはどうするか?
-->vid. glog-require-file-name
-->TYPE-I:空引数でデフォルトを指定する
(setq foo (read-string (format "Foo: %s"
(if defval (format "(default: %s)" defval) ""))))
(if (string= foo "") (setq foo defval))
-->TYPE-II:文字列取得の初期文字列を指定する(編集させたいときなど)
(setq foo (read-string "Foo: " defval))
---
elisp でプロセスの処理をしているときに sleep-for を使うと勝手にそのプ
ロセスが終ってしまうことがあるらしい.
---
cons によるリストの結合
(cons 'd '(a b c) )
-->(d a b c)
(cons '(a b c) 'd )
-->((a b c) . d)
(cons '(d) '(a b c))
-->((d) a b c)
(cons '(a b c) '(d))
-->((a b c) d)
---
Elisp での文字数カウント
-->(string-width "xxx")
interactive がうまくいかないのは関数定義への引数リストを付け忘れている
からかも
---
memo-mode.el で string-width という関数を使用していたが,標準ではない
らしい.
-->vm に付属の関数か?
-->tiny-mime に付属の関数のようである.
-->Mule なら標準装備の関数なのかな?
---
Mule 中での全角文字列の取扱いは?
-->(setq str "あいうえおかきくけこさしすせそ")
-->(string-width str)
30
-->(substring str 0 30)
"あいうえおかきくけこ"
-->(substring str 0 45)
"あいうえおかきくけこさしすせそ"
-->(setq str "abcdefghijklmnopqrstuvwxyz")
-->(string-width str)
26
-->(substring str 0 26)
"abcdefghijklmnopqrstuvwxyz"
-->全角の場合は substring と string-width とで字数の数えかたに食い違
いがある??
-->truncate-string をならば大丈夫?
---
elisp での,y/n の取得
-->(y-or-n-p "Ok?")
---
elisp で改行挿入を表すにはどうするのか?
-->物理的に改行するしかないのか.論理的な表現はないのか('\n' のよう
な).
-->'\n' でいけました (^^).
---