hyperdoc
Hyperdoc means mapping symbols to documentation URIs for libraries as well as the COMMON-LISP package, as is done by hyperdoc.el and co. The client interface can then do whatever it likes with this URL (popping up a browser, rendering a link, etc).

There are several contending interfaces:


Hyperdoc model A

http://common-lisp.net/project/hyperdoc/

In the spirit of friendly propaganda, a short summary of the salient points offered by this interface:

  • Supports both introspection and index-based lookups, so documentation can be found for packages not in image.
  • The generated indices are in a very simple "strings in a list" format, so that Emacs should be able to read them without trouble, and do the lookup magic even if not connnected to a real lisp.
  • The packages supporting this interface do not need to depend on the hyperdoc package: only client side uses this code. Libraries just implement the interface.

Downside analysis welcome. ;-)


Hyperdoc model B

External interface is the HYPERDOC function. Packages do

(defmethod hyperdocumentation ((package (eql #.*package*) name doc-type)
   ... )
;;; 
(defgeneric hyperdocumentation (package name doc-type))
(defmethod hyperdocumentation ((package symbol) name doc-type)
  (hyperdocumentation (find-package package) name doc-type))

(defun hyperdoc (name doc-type)
  ;; if no type given return uris for all types, and autogenerate
  ;; a selection page (ala clhs)?
  (hyperdocumentation (symbol-package name) name doc-type))

Disadvantage: only works usefully for symbols, not functions or classes or anything else


Hyperdoc model C

2) Use the DOCUMENTATION framework, defining HDOC:T, HDOC:FUNCTION, etc etc as new doc-types

(documentation (function 'foo) 'hyper:t)
(documentation 'foo 'hyper:function)

Disadvantage: each object must have its documentation strings set individually with (setf documentation); probably most packages will end up doing something like

(loop for x being the external-symbols of "FOO" when (fboundp x) 
      do (setf (documentation x 'hyper:function) ...) and 
      do (setf (documentation (fdefinition x) 'hyper:t) ...))


Hyperdoc model D

(merger of B and C)

(defun hyperdoc (name doc-type) 
  (or (documentation name (intern (symbol-name doc-type) 
				  (find-package "HDOC")))
      (hyperdocumentation (symbol-package name) name doc-type)))

URLs returned from HYPERDOC should be absolute, however you achieve that. If the base url of your package is configurable, you're going to have to figure out some way to configure it. Couple of possibilities:

(a) for DOCUMENTATION users, define an additional HDOC:BASE-URI (or similar) doc-type on each documented object, and use a :around method to merge it in

(defmethod documentation :around (thing (type (eql hyper:t)))
  (merge-uris (call-next-method) (documentation thing 'hyper:base-uri)))

(b) If you're using HYPERDOCUMENTATION (i.e. specializing on Lisp package) you can merge YOURPACKAGE:*HYPERDOC-BASE-URI* in fairly easily.


Some sketchy thoughts on the subject

I'm a supporter of hyperdoc, but my angle may be slightly different. A future version of hyperdoc may want to accomodate editing and documentation-lookups in an emacs/editor when a lisp is not running or the lisp has not loaded all packages you're writing code for. Some of my projects either work as batch-jobs or they have quirky startup/restart and keeping a lisp with all code loaded for docs is not an option. I want hyperdoc to be able to lookup docs for my code following, e.g loaded lookup-tables, not unlike used for CLHS lookups now.

These lookup-tables can be produced by introspection at a point when the system/app is loaded or through groveling over the source-code without loading the actual system. The lookup-tables may contain more information that may be of interest, e.g matching a symbol to the asdf-system it belongs to, the file where it is defined, what kind of object it is, etc. This will allow hyperdoc to be extended to be able to return and combine this info, allowing quick use of it e.g to open a file where a certain function is.

Automating this process is also doable, maybe by letting common-lisp-controller ask the asdf-file for the location of the lookup-table or calling a docstring-fetcher/doc-tool on the asdf-file or compiled system. By putting the lookup-table in a dedicated directory, emacs/editor/slime/ilisp/etc can fetch this table just like it fetches the CLHS entries.

The lookup-tables may also be used by other lisp-related tools for other information. --Fufie

Some comments: I'd like to keep CLC out of the picture. I see two viable possibilities for index generation: either call hyperdoc:generate-index from within eval-when :compile-toplevel in the clien packages, or have a method on asdf:compile-op do it. I think the correct protocol vis-a-vis when to use indices and when to use introspection looks like:

  • Emacs: If connected use hyperdoc, if not use indices in ~/.hyperdoc/.
  • Hyperdoc: If the package is loaded, use introspection, if not use the indices.

I've implemented the hyperdoc side of this and an initial version of pregenerated indices in the hyperdoc repository.

This involved changing the interface of hyperdoc:lookup to (lookup package-desinator string-designator &optional documentation-type) to be able to do lookups for symbols in packages not in the current image. -- Nikodemus Siivola


Documentation Tool