Lightweight package system
Damien Diederen <dd@crosstwine.com>
Package package implements a lightweight package system for SKILL. It generally favors convention over configuration.
A package is a directory which contains a SKILL or SKILL++ file with the same base name (<directory>.{il,ils}), which in turn begins with a comment header formatted in a specific way. A minimal package foo would consist in a single file:
foo/foo.il
with a single-line header:
;;; foo.il --- Minimal package
More complex packages may contain @-prefixed metadata tags in the header comment, each beginning with:
;; @<tag-name>
The following tags are defined:
;; @author A.U.Thor <author@example.com> ;; @requires bar, baz ;; @load a.il, b.ils, ...
@author states the name and email address of an author of the package. If there are multiple authors, repeat the tag for each of them.
@requires and @load are discussed with the VedaPackageFilesystemInfo class.
Packages are normally searched for in two locations relative to the execution directory: pkg/ and ../, in that order.
(defclass VedaPackageAbstractInfo () ...)
Class VedaPackageAbstractInfo holds information that is common to all packages, independently of their underlying representation.
@initarg ?name @reader GetName
The name of the package, as understood by the Info/Load functions.
@initarg ?description @reader GetDescription
The package's synopsis.
@initarg ?authors @reader GetAuthors
A (possibly empty) list of package authors strings, each having the following form (cf. name-addr production in RFC 5322):
Human-readable Name <email@example.com>
(defclass VedaPackageFilesystemInfo (VedaPackageAbstractInfo) ...)
Class VedaPackageFilesystemInfo describes filesystem-based packages as "natively" implemented by this package.
@initarg ?base @reader GetBaseDir
The directory of the search path in which the package was found, a /-terminated string.
@initarg ?header @reader GetHeaderFilename
The titular file containing package information.
@initarg ?requires @reader GetPackageRequires
A list of other packages required by this package. The contents of this field can be controlled via the @requires tag, e.g.:
;; @requires bar, baz
@initarg ?sources @reader GetSourceFilenames
The package's source files, in load order.
The contents of this field can be controlled via the @load tag, e.g.:
;; @load foo.il, bar.ils
or
;; @load foo.il, bar.ils, ...
where the ellipsis means that any other source file founds in the package's directory are to be loaded after foo.il and bar.ils (in an undefined order).
@initarg ?tests @reader GetTestFilenames
Package test files, in load order.
(defclass VedaPackageLoadOptions (VedaPackageSearchOptions) ...)
Class VedaPackageLoadOptions holds options that are used when loading packages; cf. PackageLoad.
@initarg ?requires @reader GetRequires @writer SetRequires
When t, honor the package's @requires tag. Otherwise, a (possibly) empty list of packages which are to be required before the target.
Defaults to t.
@initarg ?forceReload @reader GetForceReload @writer SetForceReload
When t, reset the table of loaded packages before loading the target. Otherwise, a (possibly) empty list of package names to be evicted from the table of loaded packages before loading the target.
Defaults to nil.
(defclass VedaPackageSearchOptions () ...)
Class VedaPackageSearchOptions holds options that are used for locating packages; cf. PackageLoad and PackageInfo.
@initarg ?searchPath @reader GetSearchPath @writer SetSearchPath
The list of /-terminated directories which are searched (in order) for packages. Non-anchored directories are relative to the execution directory.
Defaults to searching pkg/ then ../.
(defmethod printObject ((pi VedaPackageFilesystemInfo) @optional (port poport)) ...)
printObject formats unreadable VedaPackageFilesystemInfo instances for diagnostic purposes.
(defun PackageInfo (pkg @key options) ...)
PackageInfo returns metadata about the package named by the string pkg, either by querying a hook or by searching a number of preset filesystem bases.
It returns a concrete subclass of VedaPackageAbstractInfo, or nil if not found.
?options, if non-nil, must be an instance of VedaPackageSearchOptions. If nil, a default-initialized instance is used.
The hook, if present, must be named VedaPackageInfoHook and is invoked as:
(VedaPackageInfoHook pkg)
where pkg is the package name.
(defun PackageLoad (pkg @key options) ...)
PackageLoad loads the sources of the package named by the string pkg, as well as its dependencies, as necessary or requested via the ?options argument.
?options, if non-nil, must be an instance of VedaPackageLoadOptions. If nil, a default-initialized instance is used.
The PackageInfo function is used for locating the package and its dependencies, using the same ?options argument as PackageLoad. An error is raised if one of the packages cannot be found.
The function returns the concrete subclass of VedaPackageAbstractInfo corresponding to pkg.