cwal

whcl: PathFinder
Login

whcl: PathFinder

(⬑Table of Contents) (⬑API Index)

The PathFinder Class

This API may be installed using:

whcl install-api PathFinder

or calling whcl_install_api() from C code with a module name of PathFinder.

It adds a whcl[PathFinder] constructor function and the API described below.

Jump to...

PathFinder

PathFinder is a utility class for searching for files based on client-provided search paths and file extensions/suffixes. Its primary use is for finding library-level scripts and loadable modules based on a configurable search paths and possibly platform-specific file extensions (e.g. ".dll" vs ".so"). This class is implemented as a "native" type binding, and demonstrates the plugging-in of an arbitrary C-side struct to the scripting engine. Only a very small amount of its code depends on whcl, per se - it primarily depends on the engine (cwal) and not the language interpreter (whcl). The underlying C class itself has been wandering from source tree to source tree since the early 2000's (though it was initially implemented in C++).

PathFinder is used like this:

decl pf new whcl[PathFinder]
# Configure search paths:
pf add-dir '/etc' '/bin' '/usr/bin'
assert '/etc/hosts' == [pf search 'hosts']
assert [pf search 'ls']
assert undefined == [pf search 'no-such-file-we-hope']
# Replace search path:
set pf[path] array 'unit' '.'
# Configure file suffixes/extensions:
pf add-ext '.whcl'
assert [pf search "000-000-0empty.whcl"]
# ^^^ a local test script
assert undefined == [pf search 'no-such-script']

PathFinder Members

Constructor

new whcl[PathFinder] [array|string dirList [array|string fileExtensions]]

The two optional arguments are used to initialize the path resp. extensions properties of this object. If they are arrays, they are assigned as-is to the corresponding property. If they are strings, they are parsed as conventional PATH-style strings, as documented for the tokenize-path class-level method, and the resulting arrays are assigned to the corresponding property.

It throws if passed arguments of any other type except, as a special case, that it silently ignores undefined and null values (to simplify certain usage patterns, e.g. new whcl[PathFinder] [getenv "blah"]).

Class-Level Members

The following functions may be called from the prototype or from any instance of the class. The prototype is accessible via whcl[PathFinder][__prototype].

is-accessible

Usage: is-accessible [-w] filename

Returns true if the given filename refers to a readable file (or writeable if passed the -w flag), else returns false. This function does no path/extension-based lookup of the filename and does not require a specific this type, thus it may be called on the prototype or copied for use outside the context of a PathFinder instance.

path-from-env

Usage: path-from-env cliFlagName [ENV_VAR_NAME=$cliFlagName]

This function is a proxy for tokenize-path (see below) which gets its path string from either a CLI flag or an environment variable (in that order, stopping if it finds a match in its first argument). Its first argument is the name of a flag which is presumed to possibly be set in whcl[ARGV][flags], minus any leading dashes. If such a flag is set, it is used as the source string for a call to tokenize-path. If no such flag is set then it looks in getenv(argv[1]), with argv[1] defaulting to argv[0]. If such an environment variable is found, that string is used for the call to tokenize-path. If no match is found, undefined is returned, else the result of tokenize-path is returned.

This function may be called directly from the prototype (or copied to a new location for convenient reuse elsewhere) or from any PathFinder instance.

Examples:

decl P whcl[PathFinder][__prototype]
P path-from-env a-flag-name; # looks in ARGV[flags][a-flag-name] then getenv("a-flag-name")
P path-from-env flagx PATH; # looks in ARGV[flags][flagx] then getenv("PATH")

tokenize-path

Usage: tokenize-path pathString [targetArray]

Tokenizes a conventional PATH-style string, delimited by path separator characters. On Windows builds, only ; is considered a valid delimiter, but on non-Windows builds both ; and : characters are considered delimiters. It returns the entries (if any) as an array. If passed an array as its second argument, the entries are appended to that array and that array gets returned. Empty entries (leading, trailing, and/or consecutive delimiters) are elided. Throws if passed invalid arguments, noting that an empty path string, or one with no path elements, is not an error.

C-level clients may bind their own copy of this function using whcl_cb_tokenize_path(). The non-script-side APIs for this feature are the whcl_path_toker type and its methods (search whcl.h for that type name).

Instance Methods

The following methods require a PathFinder instance...

add-dir

Usage: add-dir dirName [... dirNameN]

Adds the given directories to this instance's search list, creating the path property (an array), if needed, to hold them. Alternately, the path property may be manipulated directly from script code. Returns this object.

add-ext

Usage: add-ext fileExtension [... fileExtensionN]

Adds the given file extension(s) to this instance's search list, creating the extensions property (an array), if needed, to hold them. Alternately, the extensions property may be manipulated directly from script code. Returns this object.

Note that the extension is really a filename suffix and must include any characters which the to-be-searched-for files might end with, including the conventional . before a file extension. e.g. an "extension" of _xyz will match a filename which ends with _xyz, even though that's not normally what is thought of as a file extension.

search

Usage: search baseName [bool|int directoryPolicy=0]

If the PathFinder can resolve the given base filename, based on its search path and extensions lists (its path resp. extensions properties), it returns the resolved name, otherwise it returns the undefined value. It only checks that the file is readable. The optional second argument specifies how to handle directory names: a boolean true or a positive integer value means to match both directories and files; a boolean false or integer 0 means never to match directory names; a negative integer means to only match directory names, never files. (BUG: on Non-Unix platforms it cannot determine if a file is a directory.)

The directoryPolicy values are stored as constant values of the PathFinder prototype: SEARCH_ANY, SEARCH_FILES, SEARCH_DIRS.

Even if the search path is empty, the first argument is still checked as-is and (if needed) in combination with the configured extensions, so it may match a filesytem entry in any directory. For example:

decl p new whcl[PathFinder]; # w/ empty path/extensions
p search '/etc/hosts'; # will find a match on most Unix-like systems.
# Likewise:
p add-ext 'osts' p.SEARCH_FILES
p search '/etc/h'; # == "/etc/hosts"

to-jsonable

Usage: to-jsonable

Overridden to return a plain object with this object's core state:

{ "path": ["..."], "extensions": ["..."] }

See the JSON API for more details.

Configuring Search Paths

The list of directories and file extensions can be manipulated via the array-type path resp. extensions properties or via helper methods like add-dir or add-ext. The client may either directly assign an array to them, and manipulate that array directly, or may use the add-dir resp. add-ext methods to append to them (those functions create them if needed). The search method looks up the path and ext properties, so any changes made to them will be seen by it.