Author: rklochkov Date: Sun Dec 23 02:43:24 2012 New Revision: 9
Log: Added docs
Added: README.md Modified: src.lisp
Added: README.md ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ README.md Sun Dec 23 02:43:24 2012 (r9) @@ -0,0 +1,114 @@ +advanced-readtable +================== + +Features +- per-package aliases for packages +- per-package shortcuts for package hierarchies +- extendable find-package and find-symbol +- local use package in form package:(here form where package used) +- local intern package like in SBCL: package::(symbol1 symbol2) will intern + package::symbol1 and package::symbol2 + +_push-import-prefix_ -- enables import prefix on package name +-------------------------------------------- + +For example, you have packages com.clearly-useful.iterator-protocol, com.clearly-useful.reducers, ... +You may use them as + + (push-import-prefix :com.clearly-useful) + (iterator-protocol:do-iterator ...) + (reducers:r/map #'1+ data) + +and so on. +Package prefix is enabled per package so it is safe to use it in your package. + +If there is package, which name coincides with shortcut, package name has priority. + +So, if you make + + (defpackage :reducers ...) + +after that reducers:... will refer to new package, not com.clearly-useful.reducers. + +_push-local-nickname_ -- enables nickname for package in current package +------------------------------------------- + +Enables package nickname in CURRENT-PACKAGE. +For example, you found COM.INFORMATIMAGO.COMMON-LISP.CESARUM.LIST package and want to use +it. But don't want to USE-PACKAGE them, because some exported symbols from it are clashing +with yours. + +You may do it right: + + (push-local-nickname :com.informatimago.common-lisp.cesarum.list :ilist) + (ilist:circular-length l) + +Local-nicknames are local, so you may use it freely. + +If package A wants package LIB version 1, and package B wants package LIB version 2, one can simply +rename LIB version 1 to LIB1 and LIB version 2 to LIB2 and make + + (push-local-nickname :lib1 :lib :a) + (push-local-nickname :lib2 :lib :b) + +_push-local-package_ -- sets local-package for a symbol +---------------------------------------------- + +Many macroses use there own clauses. +For example, ITERATE uses FOR, COLLECT and so on. +If you don't want to USE-PACKAGE iterate, this function will help. + + (push-local-package 'iter:iter :iterate) + (iter:iter (for i from 1 to 10) (collect i)) + +Caution: this function enables package substitution in all cases, +where SYMBOL is the car of a list. +For example, this will be error: + + (let (iter:iter for) (list iter:iter for)) + +, because first for is in ITERATE package, but second -- is not. + +_set-macro-symbol_ - syntax is like set-macro-character, +------------------ + +But FUNC is binded to SYMBOL, not character. +Now you may make something like + + html:[body [table (as-html sql:[select * from t1])]] + +html:[ and sql:[ will have different handlers and you may mix them in +one expression. + +_get-macro-symbol_ - syntax is like get-macro-character, +------------------ + +Returns function, assigned by set-macro-symbol + +Low-level API +------------- + +There are five lists: +- *package-finders* -- global for find-package +- *symbol-finders* -- global for find-symbol +- (package-finders package) -- per-package for find-package +- (symbol-finders package) -- per-package for find-symbol +- (extra-finders symbol) -- per-symbol for (symbol ....) package substitution + +They are all alists. Key denotes handler and should be uniq for the list. +Value should have form (lambda (name package) ...) and return symbol for +symbol-finders and extra-finders and return pacakge for package-finders. + +You may freely change them to develop your own symbol or package schemes +(for example, hierarchy-packages, conduits and so on). + +Middle-level API +---------------- + +To simplify adding new handlers with keys there is macro _set-handler_ + + (set-handler (package-finders pack) '(:my handler1) #'handler-func) + +will set handler for package pack, if there are no hanler with key +(:my handler1). So you may set it in your file and not be afraid, that it +will duplicate on reloading.
Modified: src.lisp ============================================================================== --- src.lisp Sun Dec 9 01:12:39 2012 (r8) +++ src.lisp Sun Dec 23 02:43:24 2012 (r9) @@ -1,13 +1,13 @@ (in-package #:advanced-readtable)
-;;; Advanced-readtable -;;; -;;; per-package aliases for packages -;;; per-package shortcuts for package hierarchies -;;; extendable find-package and find-symbol -;;; local use pcakage in form package:(here form where package used) -;;; local intern package like in SBCL: package::(symbol1 symbol2) will intern -;;; package::symbol1 and package::symbol2 +;;;; Advanced-readtable +;;;; +;;;; per-package aliases for packages +;;;; per-package shortcuts for package hierarchies +;;;; extendable find-package and find-symbol +;;;; local use package in form package:(here form where package used) +;;;; local intern package like in SBCL: package::(symbol1 symbol2) will intern +;;;; package::symbol1 and package::symbol2
(defvar *per-package-finders* (make-hash-table :test 'eq) "Hash package -> list of handlers. Each handler is a cons (key . function)") @@ -118,11 +118,12 @@
(defun find-symbol (name &optional dpackage) "We try to find symbol -1. In package set with car of list, for example, PUSh-LOCAL-PACKAGE -2. By CL-FIND-SYMBOL +1. In package set with car of list, for example, PUSH-LOCAL-PACKAGE +2. By CL-FIND-SYMBOL, when package explicitly given 3. By packages added with package:(...) 4. By per-package finders -5. By global finders" +5. By global finders +6. By CL-FIND-SYMBOL" (declare (type string name)) (let ((package (if dpackage (find-package dpackage) *package*))) (macrolet ((mv-or (&rest clauses) @@ -134,10 +135,11 @@
(mv-or (try-mv-funcall *extra-symbol-finders* name package) - (cl:find-symbol name package) + (when dpackage (cl:find-symbol name package)) (unless dpackage (try-local-packages *local-packages* name)) (try-mv-funcall (symbol-finders package) name package) - (try-mv-funcall *symbol-finders* name package))))) + (try-mv-funcall *symbol-finders* name package) + (unless dpackage (cl:find-symbol name package))))))
(defun read-token (stream) " @@ -158,7 +160,7 @@
(defun read-after-colon (stream maybe-package colons) "Read symbol package:sym or list package:(...)" - (when (= colons 0) + (when (= colons 0) ; no colon: this is a symbol or an atom (return-from read-after-colon (if (symbolp maybe-package) (let ((name (symbol-name maybe-package))) @@ -243,6 +245,17 @@ (gethash symbol *extra-finders*))
(defmacro set-handler (handler-list key function) + "This is middle-level public API for changing handlers for +find-symbol and find-package. There are five lists: + *package-finders* -- global for find-package + *symbol-finders* -- global for find-symbol + (package-finders package) -- per-package for find-package + (symbol-finders package) -- per-package for find-symbol + (extra-finders symbol) -- per-symbol for (symbol ....) package substitution + +Key should be uniq in the sense of EQUAL in the list. SET-HANDLER adds +new handler if it is not already there. +" (let ((key-var (gensym "key"))) `(let ((,key-var ,key)) (unless (assoc ,key-var ,handler-list :test #'equal) @@ -288,10 +301,11 @@
Local-nicknames are local, so you may use it freely.
-Local-nickname shadows any package, which name is NICK, so if package A wants -package LIB version 1, and package B wants package LIB version 2, one can simply -rename LIB version 1 to LIB1 and make +If package A wants package LIB version 1, and package B wants package +LIB version 2, one can simply rename LIB version 1 to LIB1 and rename LIB +version 2 to LIB2 and make (push-local-nickname :lib1 :lib :a) + (push-local-nickname :lib2 :lib :b) " (let ((dpackage (find-package long-package))) (%set-handler (package-finders current-package) `(:nick ,long-package ,nick) name