ansify 0.02.00 ごちゃごちゃ更新
パッケージ "ansify" とは別に パッケージ "ansify.ext" を作っりました。ANSI 標準以外の物はこっちから export するようにしま(す|した)。
"ansify.ext" からは以下の関数が export されてます。
- ansify.ext:optimize-type-check
- ansify.ext:canonicalize-typespec
- ansify.ext:read-value
以下の変数で警告を投げるかどうかを設定できます。デフォルトは全部オフになってます。
- ansify.ext:*warn-on-otherwise-in-middle* (case で
- ansify.ext:*warn-on-invalid-typespec* (typep とか
- ansify.ext:*warn-on-undefined-typespec* (同上
"ansify" から疑似 export してたものをちゃんと export するようにしたので `ansify:etypecase` などと書けるようになりました。(`ansify::install` すると "ansify" を use-package してたんですが lisp と盛大に衝突するのでしなくなってます。)
その他の変更点
- 細々したもの追加
- typespec 周りごちゃごちゃ見直し
- バグ修正(主に typespec 周り、id:miyamuko さんに感謝)
いつもの
- NetInstaller 用 packages.l
- 手動ダウンロード用 ansify-0.02.00.zip
local-window-flag
http://xyzzy.s53.xrea.com/reference/wiki.cgi?p=set-local-window-flags で設定する行番号とかのやつ。
- フラグは on か off か未設定か
- window と buffer がそれぞれにフラグを覚えてる
- 優先順位は buffer > window > (グローバルな設定)
- `get-local-window-flags` は多値で on のフラグと off のフラグを返す
;; 現在の buffer/window で flag が on なのか off なのか (defun window-flag (flag) (labels ((on? (x) (plusp (logand flag x)))) (multiple-value-bind (buffer-on buffer-off) (get-local-window-flags (selected-buffer)) (cond ((on? buffer-on) t) ((on? buffer-off) nil) (t (multiple-value-bind (window-on window-off) (get-local-window-flags (selected-window)) (cond ((on? window-on) t) ((on? window-off) nil) (t (on? (get-window-flags)))))))))) => window-flag
たぶん合ってる。もうちょっとスッキリ書けても良さそうなもんなんだが・・・。
ansify 0.01.01 バグ修正
早速 id:miyamuko さんからバグ報告もらったので修正しました。毎度ありがとうございます。
- case, typecase で `ansify::otherwise` ではなく `lisp:otherwise` を使うように修正
- xyzzy には otherwise は無いものと思い込んでたけどあった
- print-unreadable-object で princ にストリーム渡し忘れてたのを修正
ついでにバージョン変数 `ansify::+version+` 作っときました。
- NetInstaller 用 packages.l
- 手動ダウンロード用 ansify-0.01.01.zip
case の途中で (otherwise ...)
keys---a designator for a list of objects. In the case of case, the symbols t and otherwise may not be used as the keys designator. To refer to these symbols by themselves as keys, the designators (t) and (otherwise), respectively, must be used instead.
CLHS: Macro CASE, CCASE, ECASE
"may not be used" ってどうすりゃいいんだよ。エラー投げていいのん?と CL 処理系の挙動を調べてみたらバラバラだった・・・。
※処理系のバージョンが古いのは突っ込んであった LispCabinet に付属してたものだからです。
xyzzy + ansify
無言でマッチしない
(require "ansify") => t (ansify::case 3 (x 'x) (otherwise 'otherwise) (3 :three)) => :three
Clozure CL Version 1.6-r14468M
警告を出してマッチする
CL-USER> (case 3 (x 'x) (otherwise 'otherwise) (3 :three)) ; Warning: T or OTHERWISE clause in the middle of a CASE statement. Subsequent clauses ignored. ; While executing: CCL::CASE-AUX, in process repl-thread(10). OTHERWISE
CLISP 2.48
エラーで止まる
CL-USER> (case 3 (x 'x) (otherwise 'otherwise) (3 :three)) ---- debugger ---- CASE: the OTHERWISE clause must be the last one [Condition of type SYSTEM::SIMPLE-SOURCE-PROGRAM-ERROR] Restarts: 0: [RETRY] Retry SLIME REPL evaluation request. 1: [*PROCESS-INPUT] Continue reading input. 2: [ABORT] Return to SLIME's top level. 3: [CLOSE-CONNECTION] Close SLIME connection. 4: [ABORT] Abort main loop
setf-values 0.01.02 更新しました
しょーもないミスでおかしな展開形になってたのを修正した(miyamuko さんからパッチ頂きました。ありがとうございます。)のと、変数以外の atom に setf しようとしたのはマクロ展開時にエラーに。
- NetInstaller 用 packages.l
- 手動ダウンロード用 setf-values-0.01.02.zip
ansify 0.01.00 をリリースしました
今までバラバラに作ってた ANSI Common Lisp からもらってきたようなものを1つにまとめました。
具体的には
- NetInstaller 対応してたもの
- condition-restart
- symbol-macrolet
- typespec+
- GitHub あたりでこっそり作ってたもの
- GitHub - bowbow99/xyzzy.typecase: <discontinued> Common Lisp の typecase やらなんやら = typecase, etypecase, ctypecase
- GitHub - bowbow99/xyzzy.destructuring-bind: <discontinued> Common Lisp の destructuring-bind = destructuring-bind
- 今回実装したもの
- case 軍団: case, ecase, ccase
- print-unreadable-object
が全部入ってます。
- NetInstaller 用 packages.l
- 手動ダウンロード用 ansify-0.01.00.zip
使い方(開発者向け)
今まで公開してた condition-restart と symbol-macrolet は lisp パッケージからエクスポートしてましたがその方法だと問題ありなので、ansify では専用のパッケージをを使うようにしました。普通に export すると lisp パッケージのシンボルと衝突するので shadowing-import するようにしてあります。
数が多いんで必要なものを全部 shadowing-import する ansify::install という関数も用意しておきました。
(eval-when (:execute :compile-toplevel :load-toplevel) (require "ansify")) (defpackage :my-package ...) (in-package :my-package) (eval-when (:execute :compile-toplevel :load-toplevel) (ansify::install))
やってることは片っ端から shadowing-import なので、特定のオペレータのみ使いたいなどの場合は個別に shadowing-import したり defpackage の :shadowing-import-from に指定してもだいじょぶです。
(eval-when (:execute :compile-toplevel :load-toplevel) (require "ansify")) (defpackage :my-package (:use #:lisp #:editor) (:shadowing-import-from :ansify #:destructuring-bind #:etypecase ...))
取り込まれた拡張は deprecated になります。
- condition-restart
- symbol-macrolet
- typespec+
は deprecated になります。狙ったわけでもないのに ansify と同時にインストールしておいても問題は起きない*1んですが、ansify の方へ移行お願いします。しばらくはそのまま置いておきますがそのうち消えて無くなります。
condition-restart に含まれていた condition-restart-support.l(eval-region などから再起動を選択できるようにするもの)が ansify には含まれていません。無いと困るという人がいたら twitter か↓コメントか何かで連絡ください。
あと、condition-restart の再起動と ansify の再起動は互換性ないです。ansify::restart-case で用意した再起動は ansify::find-restart で探す必要があります(condition-restart:find-restart では見つけられないです)。
XTAGS #2 飛ぶ
タグジャンプ(jump-tag)できるようにするための何やら。
ローカル変数 ed:tags-find-target
この変数にセットした関数が引数なしで呼び出されるので、カーソル位置の単語を調べて
- クラス名
- 名前
- 関数か否か
を多値で返す。
3つ目の値は、nil なら変数、'lisp:structure なら構造体、それ以外なら関数、と扱われるっぽい(tags-find-entry-1 参照)のでそんな感じで。
この情報を元に XTAGS からジャンプ先のファイル名/ポイントを探してくれる。
ローカル変数 ed:tags-find-point
ジャンプ先のファイル名が見つかったらそのファイルを開いて、この関数が呼び出される。引数は以下の4つ。
- クラス名(ed:tags-find-target から)
- 名前(ed:tags-find-target から)
- 関数か否か(ed:tags-find-target から)
- ポイント(XTAGS エントリから)
ポイントを返すとそこへカーソルを移動する(その後行頭に移動してしまう)ので、XTAGS エントリに記録するポイントは必ずしも正確でなくてもこの関数で調整したりできる。
nil を返すと元のポイントへ移動する。
その他のタグジャンプ関連ローカル変数
ed::tags-case-insensitive
non-nil だと ed:tags-find-target から XTAGS エントリを探すのが case-insensitive になる。