プロジェクトの site-lisp を *load-path* に追加する
xyzzy の拡張書くときは ~/work/<プロジェクト名>
にこんな風にファイルが配置される。
- ~/work/<プロジェクト名>/
- README.md
- site-lisp/
- <プロジェクト名>.l
- <プロジェクト名>/
- packages.l
- util.l
- ...
最初は <プロジェクト名>.l
に全部書いてるんだけど、何度も書いては捨ててるうちに毎回書くもの(パッケージ定義とかユーティリティとかある程度形が決まってきたものとか)を別ファイルに分割していくので、この時点では主に <プロジェクト名>.l
で色々やってる。
~/work/<プロジェクト名>/site-lisp/
が *load-path*
に追加される形を想定しているので、各ファイルのモジュール名はこうなる。
~/work/<プロジェクト名>/site-lisp/<プロジェクト名>.l
- --> "<プロジェクト名>"
~/work/<プロジェクト名>/site-lisp/<プロジェクト名>/packages.l
- --> "<プロジェクト名>/packages"
~/work/<プロジェクト名>/site-lisp/<プロジェクト名>/util.l
- --> "<プロジェクト名>/util"
なので <プロジェクト名>.l
から他のファイルを require
している。
(eval-when (:execute :compile-toplevel :load-toplevel) (require "<プロジェクト名>/packages.l") (require "<プロジェクト名>/util.l") ...)
諸々の事情(Windows Update など)で xyzzy を再起動したりした時には、~/work/<プロジェクト名>/
が *load-path*
に登録されていないので、こいつらを見つけられなくなって、全部のファイルを順番に手動でロードしたり repl から手動で *load-path*
に追加したりしてたんだけど、めんどくなったので勝手に *load-path*
へ追加するようにした。
(in-package :editor) (defun provide-module-name () (save-excursion (goto-char (point-min)) (when (scan-buffer "^(provide \"\\([^\"]+\\)" :regexp t) (format nil "~A.l" (match-string 1))))) (defun module-root-pathname (pathname module-name) (let ((path (reverse (split-string pathname "/"))) (name (reverse (split-string module-name "/")))) (while name (unless (string= (car path) (car name)) (error "モジュール名とファイル名が一致しません: ~S" module-name)) (setf path (cdr path) name (cdr name))) (format nil "~{~A/~}" (reverse path)))) (defun add-module-root-to-load-path () (let ((root (module-root-pathname (get-buffer-file-name) (provide-module-name)))) (pushnew root *load-path* :test #'path-equal))) (defconstant +original-require-function+ #'require) (defun require (module-name &optional pathname) (handler-case (funcall +original-require-function+ module-name pathname) (error (e) (if (and (typep e 'simple-error) (string= (princ-to-string (simple-error-format-string e)) "ファイルが見つかりません")) (progn (add-module-root-to-load-path) (funcall +original-require-function+ module-name pathname)) (error e)))))
今編集してる lisp ファイルを保存したときに(コンパイルして)ロードしてるので、現在のバッファでモジュール名とか探してる。他のところからロードしたときは使えねーわ。