bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 5/8] builtins/source: parse the -i option


From: Martin D Kealey
Subject: Re: [PATCH v2 5/8] builtins/source: parse the -i option
Date: Fri, 24 May 2024 22:17:53 +1200

On Tue, 21 May 2024 at 23:16, Koichi Murase <myoga.murase@gmail.com> wrote:

> 2024年5月21日(火) 14:56 Phi Debian <phi.debian@gmail.com>:
> > 'May be' bash could investigate the ksh93/zsh $FPATH autoload, but don't
> > know if that would be good enough for the initial purpose.
>
> There are already shell-function implementations at
> /examples/functions/autoload* in the Bash source. They reference FPATH
> to load functions, though one needs to call `autoload' for each
> function in advance (by e.g. `autoload "$fpath_element"/*' ).
>

My solution to this was to call 'autoload --all', which would gather all
the filenames in FPATH (*1) and create autoload stubs for them.

Alternatively one could define a commandnotfound function to defer this
until actually needed.

(*1 I actually used a different variable name, since I wasn't providing
exactly the same semantics as ksh, but that's relatively cosmetic)

However, I personally do not think the FPATH mechanism is useful
> because a file can only contain one function per file. Significantly
> non-trivial functions are usually implemented by a set of helper
> functions or sub-functions.


Defining extra (private) functions in a file loaded from FPATH does no
harm, as long as its name doesn't conflict.


> Also, in libraries, we usually have a set
> of functions that are closely related to one another and share the
> implementations. I don't think it is practical to split those
> functions into dozens or hundreds of files.


I would hesitate to call what I've done "a manager", but my approach has
been to allow a file to "declare" all the public functions it defines, and
then simply have symlinks (or even hard links) to a single underlying file.

I copied Perl and named my command "require" because it's a run-time check,
not a parse-time one.

Each file should contain a "provides" statement for each (public) function
it defines; except it's optional for a function name that matches the only
possible "require" name. Using this mechanism it's also possible to require
a module rather than an individual function.

The autoloader stubs I mentioned above is just:
  func() { require --from=/path/to/library/func.bash func && func "$@" ; }

(In order to get the correct search precedence, these would need to be
generated by scanning FPATH in reverse order, so that later ones will be
replaced by earlier ones; amongst other things, I define my own FPATH-like
var to have the reverse precedence order.)

Originally I just made autoloader stubs like
  func() { source /path/to/library/func.bash && func "$@" ; }
however it turned out that using "require" instead of "source" simplified
"provides" since it could then rely on local variables from "require" being
available.

It would also be slow to
> read many different files, which requires access to random positions
> on the disk.
>

My approach allows multiple functions per file, and only loads each file
once, no matter how many names it has.

-Martin


reply via email to

[Prev in Thread] Current Thread [Next in Thread]