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