Cyrus Harmon's new completely useless blog



posted by cyrus in Lisp

So it turns out ASDF is very useful for packaging all kinds of documents in a form that can be easily distributed. With the help of some code that walks the ASDF system definition, I can automatically make tarball releases with all of the source code and other files, configuration files, shell scripts, documentation, images, etc... and have these be available to the user who downloads this distribution without worrying about where the package gets installed, relative paths, environment variables, etc...

This has been great, but I find myself writing a lot of code that looks like this:

    (let ((images-component          (asdf:find-component           (asdf:find-component            (asdf:find-system "ch-imageio-test") "test")           "images")))     (let ((inputfile            (asdf:component-pathname             (asdf:find-component              images-component "sunset-lzw")))           (imagedir (asdf:component-pathname images-component)))            ... 

Well, it's a lot easier to do something like this:

  (ch-asdf::asdf-lookup "asdf:/ch-imageio-test/test/images/sunset-lzw")  

This is a URI of scheme asdf with host nil and the path (:absolute "ch-imageio-test" "test" "images" "sunset-lzw"). Notice that this isn't a path in the filesystem, but rather a path in asdf space. The first element of the path (after the :abosulte) corresponds to the asdf system and the other elements correspond to ASDF components so we can find them with the following code:

  (defun asdf-lookup (path)   (cond ((and path (listp path))          (reduce #'asdf:find-component (cdr path)                  :initial-value (asdf:find-system (car path))))         ((stringp path)          (let ((uri (puri:parse-uri path)))            (when uri              (let ((scheme (puri:uri-scheme uri)))                (when (and (or (null scheme)                               (eql scheme :asdf))                           (puri:uri-parsed-path uri))                  (asdf-lookup (cdr (puri:uri-parsed-path uri)))))))))) 

Again, note that the elements of the path are not file names, but rather then names of ASDF components from the following asdf file:

  (defsystem :ch-imageio-test   :version "0.1.2-20050724"   :depends-on (ch-util ch-imageio tiff-ffi)   :components   ((:module     :test     :components     ((:ch-imageio-test-cl-source-file "defpackage")      (:ch-imageio-test-cl-source-file "test-ch-imageio" :depends-on ("defpackage"))      (:module       :images       :components       ((:tiff-file "euc-tiff" :pathname #p"euc.tiff")        (:tiff-file "eucgray-tiff" :pathname #p"eucgray.tiff")        (:jpeg-file "euc-jpeg" :pathname #p"euc.jpeg")        (:jpeg-file "eucgray-jpeg" :pathname #p"eucgray.jpeg")        (:tiff-file "sunset-lzw" :pathname #p"sunset-lzw.tiff")        (:jpeg-file "sanfran" :pathname #p"sanfran.jpeg")        ))))))  

It's a trivial little hack, but it saves me 6 lines of code all over the place.