On Tue, 21 May 2024 at 23:16, Koichi Murase <myoga.mur...@gmail.com> wrote:
> 2024年5月21日(火) 14:56 Phi Debian <phi.deb...@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