Skip to content

Modern and consistent filepath manipulation for Common Lisp.

License

Notifications You must be signed in to change notification settings

fosskers/filepaths

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

filepaths

(This README is best viewed on Codeberg).

Inspired by str, this library offers modern and consistent filepath manipulation for Common Lisp.

It addresses three main issues found with the status quo, namely:

  • Centrality: Functionality is spread across the standard library and uiop.
  • Completeness: A number of common operations found in newer languages are missing entirely.
  • Clarity: Function names are often unintuitive.

The filepaths library solves these issues by offering functions commonly found elsewhere while naming them what you’d generally expect them to be. For instance:

(filepaths:join "/home/you/code" "common-lisp" "hello.lisp")
#P"/home/you/code/common-lisp/hello.lisp"

There are many more functions available.

Note that this library is currently Unix only and doesn’t offer functions for communicating with the filesystem to test if files exist, etc.

Compatibility

Compiler**.jsonVerbatum ..Unicode Paths
SBCLYesYesYes
ECLNoYesYes
ABCLYesNoYes
CCLYesNoYes
ClaspNoYesYes (2.7)
AllegroYesNoYes

Installation

This library is available on Ultralisp. It uses only standard library functions and has no external dependencies.

Usage

It is recommended that you import this library with the nickname path or p, although the usage examples further down all use the full name, filepaths.

(:local-nicknames (:p :filepaths))

Note that nearly every function here can be passed either a pathname or a string.

Structural Tests

rootp, emptyp

Is the given PATH the root directory?

(filepaths:rootp #p"/")
T

Is the given PATH an empty string?

(filepaths:emptyp #p"")
T

absolutep, relativep

Yields T when the given PATH is a full, absolute path.

(filepaths:absolutep "/home/colin/foo.txt")
T

Yields T when the given PATH is a relative one.

(filepaths:relativep #p"bar/foo.txt")
T

starts-with-p, ends-with-p

Are the initial components of a PATH some BASE?

(filepaths:starts-with-p #p"/foo/bar/baz/zing.json" "/foo/bar")
T

Are the final components of a PATH some given CHILD?

(filepaths:ends-with-p #p"/foo/bar/baz/zing.json" "baz/zing.json")
T

directoryp

Yields T if the PATH represents a directory. It only tests for structure; the filesystem isn’t probed.

(filepaths:directoryp #p"/foo/bar/")
T
(filepaths:directoryp #p"/foo/bar/baz.txt")
NIL

Construction

join

Combine two or more components together.

(filepaths:join "/foo" "bar" "baz" "test.json")
#P"/foo/bar/baz/test.json"
(filepaths:join #p"/bar/baz/" #p"foo.json")
#P"/bar/baz/foo.json"

Component Access

base, with-base

The non-extension, non-directory portion of the filename of a PATH.

(filepaths:base #p"/foo/bar/baz.txt")
baz

Swap the base portion of a PATH with a NEW one. Yields a new path object.

(filepaths:with-base #p"/foo/bar/baz.txt" "jack")
#P"/foo/bar/jack.txt"

name, with-name

The filename of a PATH with no other directory components.

(filepaths:name #p"/foo/bar/baz.txt")
baz.txt

Swap the filename portion of a PATH with a NEW one. Yields a new path object.

(filepaths:with-name #p"/foo/bar/baz.txt" "jack.json")
#P"/foo/bar/jack.json"

parent, with-parent

Yield PATH without its final component, if there is one.

(filepaths:parent #p"/foo/bar/baz.txt")
#P"/foo/bar/"

Swap the parent portion of a PATH.

(filepaths:with-parent #p"/foo/bar/baz.json" #p"/zing")
#P"/zing/baz.json"

extension, with-extension, add-extension, drop-extension

The extension of a given PATH.

(filepaths:extension #p"/foo/bar.json")
json

Swap the entire extension of a given PATH. Yields a new path object.

(filepaths:with-extension #p"/foo/bar/baz.txt" "json")
#P"/foo/bar/baz.json"

Add an extension to the given path, even if it already has one.

(filepaths:add-extension #p"/foo/bar/baz.txt" "zip")
#P"/foo/bar/baz.txt.zip"

Remove an extension from a PATH.

(filepaths:drop-extension #p"/foo/bar/baz.json")
#P"/foo/bar/baz"
(filepaths:drop-extension #p"/foo/bar/baz.json.zip")
#P"/foo/bar/baz.json"

Conversion

components, from-list

Every component of a PATH broken up as a list.

(filepaths:components #p"/foo/bar/baz.json")
("/" "foo" "bar" "baz.json")

Given a LIST of path components, construct a proper pathname object.

(filepaths:from-list '("foo" "bar" "baz"))
#P"foo/bar/baz"
(filepaths:from-list (filepaths:components "/foo/bar/baz/file.txt"))
#P"/foo/bar/baz/file.txt"

ensure-directory, ensure-string, ensure-path

If a given PATH doesn’t end in a path separator, add one.

(filepaths:ensure-directory #p"/foo/bar/baz")
#P"/foo/bar/baz/"

A PATH is definitely a string after this.

(type-of (filepaths:ensure-string #p"/foo/bar"))
(SIMPLE-BASE-STRING 8)

A PATH is definitely a pathname after this.

(type-of (filepaths:ensure-path "/foo/bar"))
PATHNAME

to-string, from-string

Convert a PATH object into string.

(filepaths:to-string #p"/foo/bar/baz.txt")
/foo/bar/baz.txt

Convert a string into a proper filepath object.

(filepaths:from-string "/foo/bar/baz.txt")
#P"/foo/bar/baz.txt"

Conditions

For certain functions in this library, it is not appropriate to return nil in case of an error. The following conditions are thus triggered under certain circumstances:

  • no-filename
  • empty-path
  • root-no-parent

Further Work

  • Windows support

See Also