The illogical-pathnames Reference Manual

Next: , Previous: , Up: (dir)   [Contents][Index]

The illogical-pathnames Reference Manual

This is the illogical-pathnames Reference Manual, version 1.0.1, generated automatically by Declt version 4.0 beta 2 "William Riker" on Thu Sep 15 05:05:26 2022 GMT+0.

Table of Contents


1 Introduction

                         ILLOGICAL PATHNAMES
                         ===================

                           By Robert Smith


Purpose
-------

The purpose of this library is to allow one to specify pathnames in
source files whose syntax mostly doesn't depend on a physical path
location. To put it simply, one can write

    #P(:HOME (".emacs.d") "foo.el")

instead of

    #P"/home/me/.emacs.d/foo.el".

Somewhere, :HOME---a so-called "illogical host"---has to be
specified. This is done by associating it with a directory via the
macro DEFINE-ILLOGICAL-HOST. They can be redefined, which won't affect
evaluated uses of #P(...) syntax.

The former syntax isn't actually an "illogical pathname"; it evaluates
to a physical pathname. (See the example below and the FAQ.) However,
it does involve objects of the type ILLOGICAL-PATHNAME under the hood.

Using illogical pathnames allows one to easily write code whose
pathnames are relative to a few known base directories. When the
program is moved, or perhaps an executable is created, one only has to
redefine the set of illogical hosts. Using the power of
*LOAD-TRUENAME* and others, one can make mostly portable applications
that don't depend on physical filesystem location at all.


Name
----

Before this library, I attempted to solve the same problem by defining
logical hosts with wildcard translations. This worked relatively well
with Clozure CL, due to their more flexible implementation of logical
pathnames. However, more ANSI compliant systems (with respect to
logical pathnames) didn't work with the same code. As such, in my
mind, I made "logical pathnames that solve the 95% case" and called
them "illogical pathnames", a play on the fact that they were supposed
to be "logical logical pathnames". (A double positive makes a
negative, right?)

Despite the name and the reasoning behind the name, these aren't a
replacement for logical pathnames and are not "better" than logical
pathnames; they just solve a different problem than that which logical
hosts solve on modern machines.


Example
-------

Note that normal pathname syntax isn't changed.

    > #P"/foo/bar"
    #P"/foo/bar"

Let's define an illogical host that points to my home directory.

    > (ipath:define-illogical-host :home "/home/me/")
    :HOME

Let's use the extended pathname syntax to refer to a file in my home
directory.

    > #P(:home ("Scratch") "new.txt")
    #P"/home/me/Scratch/new.txt"

We see that #P(...) isn't truly a literal for an illogical
pathname. It returned a physical pathname. What does #P(...) really
expand into then?

    > '#P(:home ("Scratch") "new.txt")
    (ILLOGICAL-PATHNAMES:TRANSLATE-ILLOGICAL-PATHNAME
      #S(ILLOGICAL-PATHNAMES:ILLOGICAL-PATHNAME
          :HOST :HOME
          :DIRECTORY ("Scratch")
          :NAME "new"
          :TYPE "txt"))

Just an unevaluated translation of an illogical pathname object.

Let's define another illogical host referring to my scratch space
directory in my home directory.

    > (ipath:define-illogical-host :scratch #P(:home ("Scratch")))
    :SCRATCH

Let's open a new file and write to it in my scratch space.

    > (with-open-file (s #P(:scratch nil "test.txt") :direction ':output
                                                     :if-does-not-exist ':create)
        (write-string "testing, 1 2 3" s))
    "testing, 1 2 3"

And finally, let's read it back.

    > (with-open-file (s #P(:scratch nil "test.txt") :direction ':input)
        (read-line s))
    "testing, 1 2 3"
     T

That is basically it.


Frequently Asked Questions
--------------------------

Q. Why doesn't #P(...) specify a literal illogical pathname object?

This was a pragmatic choice. If Common Lisp had a generic function
called, say, TRANSLATE-TO-PATHNAME which all relevant Common Lisp
functions knew about, we could indeed use illogical pathname objects
by creating a method of that generic function. However, since we don't
have that functionality, yet we want to relatively transparently be
able to specify illogical pathnames in the places they're used, we do
the translation within the expansion of #P(...).


Q. My system needs to be bootstrapped, and I can't rely on Quicklisp
   or ASDF, but I want to use illogical pathnames.

No problem. The file "illogical-pathnames.lisp" is self-contained. You
can load it as-is.


Q. ANSI logical pathnames can solve this problem. I tried it and
   it works fine!
   
The ANSI spec requires that strings in logical pathnames must be uppercase,
and the system should convert them to uppercase when pathnames are created:

"Logical pathname words are restricted to non-case-sensitive letters,
digits, and hyphens to avoid creating problems with real file systems
that support limited character sets for file naming. (If logical pathnames
were case-sensitive, it would be very difficult to map them into a file
system that is not sensitive to case in its file names.)"

https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node213.html

The phrase in parentheses above is precisely the opposite of the truth.
A fully ANSI-conforming logical pathname implementation cannot generally
be used on a case-sensitive file system such as that typically used in Linux
or Unix.

If you are not seeing this problem with your CL implementation, it is either because
you are using a case-insensitive file system like MacOSX, or because
your implementation (e.g., Clozure CL or Franz) sanely nixed the ANSI idea
of logical pathnames and made them case-preserving.
Unfortunately, that is not ANSI conforming.


Q. Why didn't you just make a DEFINE-* macro and a function?

Pathnames need to be convenient, and specifying functions in full is
not syntactically convenient. If one doesn't like the #P syntax, they
may opt to create ILLOGICAL-PATHNAME objects and call
TRANSLATE-ILLOGICAL-PATHNAME at will.

       > (ipath:define-illogical-host :home "/Users/me/")
       :HOME
       > (ipath:make-illogical-pathname
          :host ':home
          :directory '("foo" "bar")
          :name "test"
          :type "txt")
       #S(ILLOGICAL-PATHNAMES:ILLOGICAL-PATHNAME :HOST :HOME :DIRECTORY ("foo" "bar") :NAME "test" :TYPE "txt")
       > (ipath:translate-illogical-pathname *)
       #P"/Users/me/foo/bar/test.txt"


2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 illogical-pathnames

Mostly filesystem-position-independent pathnames.

Author

Robert Smith <quad@symbo1ics.com>

License

BSD 3-clause (See illogical-pathnames.lisp)

Version

1.0.1

Source

illogical-pathnames.asd.

Child Components

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Next: , Previous: , Up: Files   [Contents][Index]

3.1 Lisp


3.1.1 illogical-pathnames/illogical-pathnames.asd

Source

illogical-pathnames.asd.

Parent Component

illogical-pathnames (system).

ASDF Systems

illogical-pathnames.


Previous: , Up: Files   [Contents][Index]

3.2 Static


Previous: , Up: Static   [Contents][Index]

3.2.1 illogical-pathnames/README.txt

Source

illogical-pathnames.asd.

Parent Component

illogical-pathnames (system).


4 Packages

Packages are listed by definition order.


5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Public Interface


5.1.1 Macros

Macro: define-illogical-host (host directory &optional documentation)

Define the illogical host HOST to the absolute directory DIRECTORY.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.


5.1.2 Ordinary functions

Function: disable-illogical-pathname-syntax ()

Disable illogical pathname syntax.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: enable-illogical-pathname-syntax ()

Enable illogical pathname syntax.

#P"..." ; traditional pathname syntax

#P(<illogical-host> (<directory name>*) <filename>?)

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: illogical-host-translation (illogical-host)

Translate the illogical host ILLOGICAL-HOST to its defined absolute directory.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: (setf illogical-host-translation) (illogical-host)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Reader: illogical-pathname-directory (instance)
Writer: (setf illogical-pathname-directory) (instance)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Target Slot

directory.

Reader: illogical-pathname-host (instance)
Writer: (setf illogical-pathname-host) (instance)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Target Slot

host.

Reader: illogical-pathname-name (instance)
Writer: (setf illogical-pathname-name) (instance)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Target Slot

name.

Function: illogical-pathname-p (object)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Reader: illogical-pathname-type (instance)
Writer: (setf illogical-pathname-type) (instance)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Target Slot

type.

Function: make-illogical-pathname (&key host directory name type)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: translate-illogical-pathname (illogical-pathname)

Translate the illogical pathname ILLOGICAL-PATHNAME to its equivalent absolute pathname.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.


5.1.3 Standalone methods

Method: make-load-form ((self illogical-pathname) &optional environment)
Source

illogical-pathnames.lisp.


5.1.4 Structures

Structure: illogical-pathname
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Direct superclasses

structure-object.

Direct methods

make-load-form.

Direct slots
Slot: host
Readers

illogical-pathname-host.

Writers

(setf illogical-pathname-host).

Slot: directory
Package

common-lisp.

Readers

illogical-pathname-directory.

Writers

(setf illogical-pathname-directory).

Slot: name
Readers

illogical-pathname-name.

Writers

(setf illogical-pathname-name).

Slot: type
Package

common-lisp.

Readers

illogical-pathname-type.

Writers

(setf illogical-pathname-type).


Previous: , Up: Public Interface   [Contents][Index]

5.1.5 Types

Type: illogical-host ()

The type of an illogical host object.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.


5.2 Internals


Next: , Previous: , Up: Internals   [Contents][Index]

5.2.1 Special variables

Special Variable: *common-lisp-sharp-p*
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Special Variable: *illogical-hosts*

Association between ILLOGICAL-HOSTs and their pathname translation.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.


Previous: , Up: Internals   [Contents][Index]

5.2.2 Ordinary functions

Function: component-present-p (value)

Helper function for DIRECTORY-PATHNAME-P which checks whether VALUE is neither NIL nor the keyword :UNSPECIFIC.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: copy-illogical-pathname (instance)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: directory-pathname-p (pathspec)

Returns NIL if PATHSPEC (a pathname designator) does not designate a directory, PATHSPEC otherwise. It is irrelevant whether file or directory designated by PATHSPEC does actually exist.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: illogical-#p-reader (stream subchar arg)

Reader for illogical pathnames. Returns an illogical pathname.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: illogical-pathname-relative-pathname (illogical-pathname)

Convert the illogical pathname ILLOGICAL-PATHNAME to its representative relative pathname.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: new-#p-reader (stream subchar arg)
Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: pathname-absolute-p (a)

Returns true if A is an absolute pathname.

This simply tests if A’s directory list starts with :ABSOLUTE

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.

Function: pathname-as-file (pathspec)

Converts the non-wild pathname designator PATHSPEC to file form.

Package

illogical-pathnames.

Source

illogical-pathnames.lisp.


Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts


Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   (  
C   D   E   F   I   M   N   P   T  
Index Entry  Section

(
(setf illogical-host-translation): Public ordinary functions
(setf illogical-pathname-directory): Public ordinary functions
(setf illogical-pathname-host): Public ordinary functions
(setf illogical-pathname-name): Public ordinary functions
(setf illogical-pathname-type): Public ordinary functions

C
component-present-p: Private ordinary functions
copy-illogical-pathname: Private ordinary functions

D
define-illogical-host: Public macros
directory-pathname-p: Private ordinary functions
disable-illogical-pathname-syntax: Public ordinary functions

E
enable-illogical-pathname-syntax: Public ordinary functions

F
Function, (setf illogical-host-translation): Public ordinary functions
Function, (setf illogical-pathname-directory): Public ordinary functions
Function, (setf illogical-pathname-host): Public ordinary functions
Function, (setf illogical-pathname-name): Public ordinary functions
Function, (setf illogical-pathname-type): Public ordinary functions
Function, component-present-p: Private ordinary functions
Function, copy-illogical-pathname: Private ordinary functions
Function, directory-pathname-p: Private ordinary functions
Function, disable-illogical-pathname-syntax: Public ordinary functions
Function, enable-illogical-pathname-syntax: Public ordinary functions
Function, illogical-#p-reader: Private ordinary functions
Function, illogical-host-translation: Public ordinary functions
Function, illogical-pathname-directory: Public ordinary functions
Function, illogical-pathname-host: Public ordinary functions
Function, illogical-pathname-name: Public ordinary functions
Function, illogical-pathname-p: Public ordinary functions
Function, illogical-pathname-relative-pathname: Private ordinary functions
Function, illogical-pathname-type: Public ordinary functions
Function, make-illogical-pathname: Public ordinary functions
Function, new-#p-reader: Private ordinary functions
Function, pathname-absolute-p: Private ordinary functions
Function, pathname-as-file: Private ordinary functions
Function, translate-illogical-pathname: Public ordinary functions

I
illogical-#p-reader: Private ordinary functions
illogical-host-translation: Public ordinary functions
illogical-pathname-directory: Public ordinary functions
illogical-pathname-host: Public ordinary functions
illogical-pathname-name: Public ordinary functions
illogical-pathname-p: Public ordinary functions
illogical-pathname-relative-pathname: Private ordinary functions
illogical-pathname-type: Public ordinary functions

M
Macro, define-illogical-host: Public macros
make-illogical-pathname: Public ordinary functions
make-load-form: Public standalone methods
Method, make-load-form: Public standalone methods

N
new-#p-reader: Private ordinary functions

P
pathname-absolute-p: Private ordinary functions
pathname-as-file: Private ordinary functions

T
translate-illogical-pathname: Public ordinary functions

Jump to:   (  
C   D   E   F   I   M   N   P   T