Re: Re: [PATCH 0/4] Add import builtin
> This is your key assertion, and it does not appear to have achieved > consensus. That's true, unfortunately. >> The behavior of the source builtin already has several special cases. > Do you mean the treatment of the DEBUG trap? That's for the debugger. I mean that the source builtin already behaves differently depending on the state of the shell. The bash documentation for the source builtin states: > If filename does not contain a slash, > the PATH variable is used to find filename, > but filename does not need to be executable. > When Bash is not in POSIX mode, > it searches the current directory > if filename is not found in $PATH. I thought that simply adding the BASH_SOURCE_PATH variable would end up adding a new if statement to the documentation. Something like: > If the BASH_SOURCE_PATH environment variable > is defined, bash will search for filename in the > directories specified by it first, falling back to > PATH if not found. I interpreted that as adding complexity to the builtin and sought to avoid it by taking another approach. The result would be documented like this: > If the -l option is passed, bash searches the directories > specified by BASH_LIBRARIES _PATH only. PATH is ignored. I thought that was simpler. -- Matheus
Re: Re: [PATCH 0/4] Add import builtin
> Neither of these requires a new builtin command. > They require changes to the shell, since they differ from > existing functionality, but those changes don't have to > take the form of a builtin. Builtin was not the correct word for what I meant. I meant to say there were advantages to implementing this as a change in bash, in contrast to implementing it a an external function. It's true that BASH_SOURCE_PATH would solve the problem and it would be a very welcome change to the shell. I will be very happy if support for that is added. I also agree that the attempt to introduce a new builtin was misguided and I have already abandoned it. This email thread belongs to the first patch set I sent, I followed up with a more conservative approach that adds an option to the source builtin. I'm currently preparing a v2 patch set which incorporates all the feedback I've received. > It takes less than a dozen lines of code > to implement BASH_SOURCE_PATH. The actual code implementing the feature in the source builtin is in that range. These are the changes I made which truly implement the feature: variables: define default BASH_LIBRARIES_PATH config-top.h | 7 +++ variables.c | 1 + builtins/source: search libraries in library mode builtins/source.def | 5 - About half of the patch was just some reorganization. I tried to make the code better as I went along, so that the final implementation would be shorter. Some of those changes had unintended consequences such as exposing a function to builtins as an API. Others were not desired such as long option support. They will be dropped in the v2 patch set, which will be much smaller. -- Matheus
Re: [PATCH 0/4] Add import builtin
On 5/8/24 7:09 AM, Matheus Afonso Martins Moreira wrote: In these discussions we've managed to discover at least two *concrete* reasons why it should actually be a builtin. - It can avoid touching PATH. Pure shell import cannot. - It's compatible with restricted shells. Most module managers resolve the path and pass in absolute file names, as you noted. Neither of these requires a new builtin command. They require changes to the shell, since they differ from existing functionality, but those changes don't have to take the form of a builtin. The number of lines being 203 is definitely large. Definitely large? I don't know about that. I even split it up into logical changes. It takes less than a dozen lines of code to implement BASH_SOURCE_PATH. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/8/24 3:45 AM, Koichi Murase wrote: As an alternative option, is it possible that the `.' builtin follows POSIX while the `source' builtin has the extension of BASH_SOURCE_PATH? I don't have a particular preference here, but I'm just curious about if there is a reason or motivation that the `source' builtin should also follow POSIX. Because `.' and `source' have always been equivalent, and it will take a better reason than this to change that. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/7/24 8:53 PM, Matheus Afonso Martins Moreira wrote: Surely these module managers do more than simply implement an alternate search path? Yes. The core feature that they provide, namely module loading, should be native to bash though. This is your key assertion, and it does not appear to have achieved consensus. The behavior of the source builtin already has several special cases. Do you mean the treatment of the DEBUG trap? That's for the debugger. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Re: Re: Re: [PATCH 0/4] Add import builtin
> I've checked the behavior, where the `source' builtin seems to still > load the non-executable one found first in the path. I was wrong about that. I derived find_user_library from find_user_command. That's what I had in mind. > How do you define `the libraries' out of a wider category of Bash > scripts intended to be sourced? Intended purpose. As I've described in other emails, the lines can get blurry. The reliable way is to look at the way the developer intended it to be used. > No. I just think it's unreasonable to force everyone to use a specific > way of module management that you are trying to invent without > referencing existing implementations. No one's being forced to do anything though. > Right, but the reserve is not true either. I don't think everything > that is significantly complicated to show the power of Bash should be > a builtin. I never used that argument to begin with. I always maintained that building this into bash is the better solution. In these discussions we've managed to discover at least two *concrete* reasons why it should actually be a builtin. - It can avoid touching PATH. Pure shell import cannot. - It's compatible with restricted shells. Most module managers resolve the path and pass in absolute file names, as you noted. These points are not "personal hangups". Those are real limitations, present in module managers, that this patch overcomes by virtue of being a builtin. > The number of lines being 203 is definitely large. Definitely large? I don't know about that. I even split it up into logical changes. I have no idea what the problem is. Are you saying it's difficult to review the patch? > I now know the reason. There are additional refactorings. So you hadn't actually read the patch until now? > Right. At the same time, more or less, it is the user's responsibility > to avoid name conflicts between a script file and an executable file > just like it is between two script files to be sourced. Why is responsibility being brought up? Bash can help the user by supporting separate paths. If bash can help the user, then it should help the user. Empowering and helping the user is the software's reponsibility. > But I agree that the situation of the mixed script files > and executable files can be improved. Then we agree. > After thinking about it, I think the suggested feature itself should > probably be disabled under the restricted shell Not our call to make. It's up to the system's administrator. They could whitelist some libraries for restricted use. > similar features such as `enable -f' and `command -p' > are also disabled in the restricted shell. The most similar feature at all is the source builtin and it's not disabled, it's just restricted to file names that don't contain slashes. Pure bash module managers are just straight up incompatible with this if they depend on the ability to pass an absolute file name to source. The builtin option approach does not have this limitation. > If it would be enabled, BASH_SOURCE_PATH should be > at least readonly the same as PATH. That feature will be in the v2 patch set which I'm already preparing. > I think it's unrealistic to ensure all the existing codes > that prepare restricted shells to be updated to care > about BASH_SOURCE_PATH before Bash is updated Restrictions are enforced after startup files are read. In case of restricted shell, the libraries path could be set to the empty string. That'd require the administrator to explicitly whitelist a set of paths for source, avoiding any potential problems. > Of course the topic is different, but the logic is similar. I'm just gonna accept that. Otherwise this will derail into a discussion about XDG directories. > I think they are still serious, but they don't have time to explain > everything in detail. The whole point of discussing things is to get those details though. > Your statement "My only request here is that you seriously consider > the work of a fellow software developer for merging into master. > That's all." read like so. I asked only that you read the patch and evaluate its merits. At no point did I demand that it be merged. Evaluating/criticizing the code? That's absolutely fine. Not even reading the patch though? That just signals I'm beneath your consideration. > turned out that there are "refactorings" > unrelated to the present purpose. Yes, there are refactorings. I moved some code around. I turned hard coded strings into function parameters. -- Matheus
Re: Re: [PATCH 0/4] Add import builtin
On Fri, May 3, 2024 at 10:53 PM Koichi Murase wrote: > [1] > https://github.com/niieani/bash-oo-framework?tab=readme-ov-file#using-import > [2] > https://github.com/akinomyoga/ble.sh/wiki/Manual-%C2%A78-Miscellaneous#user-content-fn-ble-import > [3] > https://github.com/basherpm/basher?tab=readme-ov-file#sourcing-files-from-a-package-into-current-shell > [4] https://github.com/modernish/modernish?tab=readme-ov-file#simple-form > [5] > https://github.com/bash-bastion/basalt/blob/main/docs/reference/api.md#basaltload > [6] https://github.com/ko1nksm/modulesh/blob/master/README.md#import > [7] > https://github.com/scop/bash-completion/blob/c48854850f702604aeb600ae496fb6b2eb840f8e/bash_completion#L3127 > [8] > https://github.com/ohmybash/oh-my-bash/blob/9cfb35c946953cb8cc1511cce47986cdd630852a/oh-my-bash.sh#L52 You might want to add my 15-year-old framework too. Thank you very much. :) https://loader.sourceforge.io/overview/ -- konsolebox
Re: Re: [PATCH 0/4] Add import builtin
2024年5月8日(水) 7:12 Matheus Afonso Martins Moreira : > > a language that has no support for namespaces, awkward scoping rules, > > a problematic implementation of name references, and so on. > > I could at least attempt to address those issues. I don't think these are requests to you. Those topics (in particular the scoping and namerefs) are the ones that repeatedly pop up in the bug-bash list. Each single topic could be a project that takes years. Also, if you start to implement those (and the `load once' feature), I need to go back to the arguments of the standard module manager. There are existing module managers implemented by shell functions, which are based on years of practices. Then, you cannot ignore them. > Namespacing could be as simple as prepending the module name > to the symbols that are being created. I don't think that works consistently. The shell language is inherently dynamic, so it isn't possible to resolve everything statically at the loading time. What happens when a function is called by its name stored in a variable passed through the caller's parameter? What happens when a variable is referenced by its name similarly? The behavior is unpredictable. Also, if you consider implementing a namespace, I think you should first check the ksh's implementation of namespace and learn what would be the good points and what could be the practical problem there.
Re: [PATCH 0/4] Add import builtin
2024年5月7日(火) 23:17 Chet Ramey : > On 5/6/24 1:21 AM, Phi Debian wrote: > > Well even this is unclear 'BASH_SOURCE_PATH get searched before PATH' or > > 'BASH_SOURCE_PATH get searched instead of' or even 'BASH_SOURCE_PATH get > > searched after PATH' > > Because we haven't discussed the semantics. There shouldn't be any changes > in posix mode, so that will continue to use PATH. As an alternative option, is it possible that the `.' builtin follows POSIX while the `source' builtin has the extension of BASH_SOURCE_PATH? I don't have a particular preference here, but I'm just curious about if there is a reason or motivation that the `source' builtin should also follow POSIX.
Re: Re: Re: [PATCH 0/4] Add import builtin
2024年5月7日(火) 21:40 Martin D Kealey : > I wonder if it would be useful to add options to 'command': Thanks for your suggestion. I still think those should be implemented by shell functions, but that interface sounds interesting. That seems to cover most of the cases I raised. However, those are merely examples I know, and I still think it would be better to leave the degrees of freedom for module managers. > * '-o' would report only the first command found (when more than one is > given) (or could be '-1'); > * '-p' would skip builtins & functions, and fail silently if no file can be > found; > * '-x' would search for files that lack exec permission. Maybe I'll attempt a shell-function implementation of this interface.
Re: Re: Re: [PATCH 0/4] Add import builtin
2024年5月7日(火) 2:11 Matheus Afonso Martins Moreira : > >> A native way to source libraries. Built into bash, available to all users. > > That's the source builtin. > > It looks for scripts in directories meant for executables. > It prefers files with the executable bit set. Is this related to [1]? [1] https://lists.gnu.org/archive/html/bug-bash/2024-05/msg00132.html I've checked the behavior, where the `source' builtin seems to still load the non-executable one found first in the path. $ GNU bash, version 5.3.0(1)-alpha (x86_64-pc-linux-gnu) $ ls -l t/bin{1,2}/file -rw-r--r-- 1 murase murase 15 2024-05-08 11:27:33 t/bin1/file -rwxr-xr-x 1 murase murase 15 2024-05-08 11:27:25 t/bin2/file $ head t/bin{1,2}/file ==> t/bin1/file <== echo bin1/file ==> t/bin2/file <== echo bin2/file $ (PATH=t/bin1:t/bin2 source file) bin1/file > It's a native way to load bash scripts for sure. > But it's not a native way to load libraries. How do you define `the libraries' out of a wider category of Bash scripts intended to be sourced? Even if they are distinct from other types of Bash scripts, they are still a subcategory of Bash scripts. Then, the source builtin is also a native way to load libraries. Maybe you mean a dedicated way by "the native way", but I don't see the necessity of having a dedicated way. > > It's just your expectation of the ergonomics but not ours. > > What are your expectations? The answer is found later in the same paragraph as the above sentence. I mean the community by `ours' but not specifically mine. There are existing implementations of module managers, which you don't seem to have yet performed a survey, and which are not just simple as yours. Of course, existing implementations are not designed by anti-ergonomics, and there should be ergonomics by the respective designers. > Do you really think it's reasonable to suggest that > users implement their own library importing function? No. I just think it's unreasonable to force everyone to use a specific way of module management that you are trying to invent without referencing existing implementations. > The fact such a function can be written in bash > is evidence of how powerful bash is. It doesn't > really follow though that everything that can be > written in bash should be done in bash. Right, but the reserve is not true either. I don't think everything that is significantly complicated to show the power of Bash should be a builtin. > > He submitted patch seems unneededly large. > > The diffstat shows 9 files changed, > 203 insertions, 92 deletions. The number of lines being 203 is definitely large. > Most of those are very simple > refactorings of existing code. I now know the reason. There are additional refactorings. > > incomplete addition of the long option of builtins > > What do you mean? What is missing? > > > an incomplete support for the XDG base directories, which should > > actually be discussed separately. > > XDG does not specify the ~/.local and ~/.local/lib directories. [...] I've replied to them in respective patches. > > It does seem your personal hangup not giving a filename extension to > > the script files, which ended up with mixed script files to be sourced > > and executable files. > > Whether to use file extensions or not is the user's choice. > Bash should work correctly regardless of what the file name is. Right. At the same time, more or less, it is the user's responsibility to avoid name conflicts between a script file and an executable file just like it is between two script files to be sourced. But I agree that the situation of the mixed script files and executable files can be improved. > > If you think that is the problem, your suggestion doesn't actually > > solve the problem of module managers. > > I didn't think it was a problem at first. I just thought it was unnecessary. > Bash already knows how to do it. We should make it do it for us. > > Now I do see it as a problem to be solved. Bash has a restricted shell mode > which, among many other things, prohibits slashes in file names passed to > the source builtin. If things are as you claim and the module managers really > do resolve the paths themselves in order to pass an absolute path to source, > that means they are all incompatible with bash's restricted shells. > The proposed native implementation of the module loader is not. I haven't thought about the restricted shells. After thinking about it, I think the suggested feature itself should probably be disabled under the restricted shell since similar features such as `enable -f' and `command -p' are also disabled in the restricted shell. If it would be enabled, BASH_SOURCE_PATH should be at least readonly the same as PATH. Also, administrators who prepare a restricted shell environment need to carefully set BASH_SOURCE_PATH to be a restricted one. However, it would still be a loophole for old setups for the restricted shell that don't take account of
Re: [PATCH 0/4] Add import builtin
> as long as there's no expectation that I'll accept a new feature > just because someone implemented it. There is certainly no expectation of the sort. Thanks for considering the patch. Matheus
Re: [PATCH 0/4] Add import builtin
> Surely these module managers do more than simply implement an > alternate search path? Yes. The core feature that they provide, namely module loading, should be native to bash though. Users who need just that core feature need not pull in an entire module manager just to get it. So for those users the code reduction is quite significant. > For the record I think it would be fine to introduce a new variable > BASH_SOURCE_PATH that changes the behavior of "source" in non-POSIX > mode. I don't think "source" requires a new option to use this. That's true and I think it's also a reasonable way to solve the problem. My original idea was to do exactly that. I changed course while developing it because when I thought about it I concluded it had disadvantages. The behavior of the source builtin already has several special cases. https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#index-_002e Simply taking the variable into account would add to that complexity. Adding the option to source though allows simple and unambiguous behavior. I'm not at all opposed to the variable solution however. I can implement it that way if it's deemed to be the preferred way. > I didn't say or mean to imply that it was; I was just comparing it > to another suggested feature about which I have a similar opinion. > The presence or absence of patches has nothing to do with it. (By > the by, at least two implementations of XDG startup files have been > submitted in the past.) I apologize if I've given offense. I think I got a bit defensive after I read another email. > And I appreciate the effort you've put in so far. > Everyone has been seriously considering it. Thanks. Matheus
Re: [PATCH 0/4] Add import builtin
On Mon, May 6, 2024, at 1:27 AM, Matheus Afonso Martins Moreira wrote: >> I fail to see how this could possibly save "thousands and thousands >> of lines of code". > > How many lines of code were needed to implement the module managers? > Probably a lot of lines. I guessed it was in the "thousands of lines" > ballpark. > > However many lines that is, this feature would allow me > to reduce them all to zero by not actually needing a > module manager. And the benefit would be multiplied > by all the users of bash which is probably the most > ubiquitous shell there is. That's a lot of benefit. Surely these module managers do more than simply implement an alternate search path? >> You keep talking about this proposal as if it would spark a huge >> sea change in script maintenance, but I just don't see it, at all. > > A native way to source libraries. Built into bash, available to all users. > With the ergonomics you expect it to have. With good defaults, no setup. > > That's an incredibly huge change. > Especially considering how little code > was required to make it happen. > > [...] > >> The sourced files that can be written with your feature available >> are exactly the same as the ones that can be written right now. > > It's possible but it's not as easy or ergonomic as it could be. At this point it doesn't even feel like we're talking about the same thing. > I think the best solution is to just avoid all that by adding another > variable. > This approach resolves all the above concerns. It also reuses bash's > pathname resolution code and has the added benefit of being native > to bash and available to all users, eliminating the requirement that > they implement this themselves or install an external dependency > just to load libraries. For the record I think it would be fine to introduce a new variable BASH_SOURCE_PATH that changes the behavior of "source" in non-POSIX mode. I don't think "source" requires a new option to use this. >> Much like the periodic requests for XDG-organized startup files > > I think I deserve at least a little more credit than that. > This was not some simple drive-by feature request. I didn't say or mean to imply that it was; I was just comparing it to another suggested feature about which I have a similar opinion. The presence or absence of patches has nothing to do with it. (By the by, at least two implementations of XDG startup files have been submitted in the past.) > But I don't think it's fair at all to just dismiss it as a "request". > The code has been written and as far as I can tell it works > and makes bash better than it used to be. I even made sure > to separate the commits into logical changes so that the > the maintainer would be able to cherry pick the general > refactoring improvements even if the overall feature was > rejected in the end. It was my intention to do at least some > good even if this turned out to be a stupid idea in the end. And I appreciate the effort you've put in so far. > My only request here is that you seriously consider the work > of a fellow software developer for merging into master. That's all. Everyone has been seriously considering it. That doesn't mean they have to agree about it. >> BASH_SOURCE_PATH might be convenient >> but is not groundbreaking and probably >> doesn't merit significant changes to the shell. > > I can't speak for others but I'd say this feature > is going to be quite ground breaking for me. > It's going to significantly and permanently > change the way I use bash. I'm going to write > lots of little libraries. I'll release them as free > software too. My dotfiles repository is AGPLv3. I simply don't see why you can't do all of this right now, as many other people do. >> even convinced it merits a new "source" option. > > Why not? Current commands don't need an option to use their associated path-like variables (BASH_LOADABLES_PATH for "enable", CDPATH for "cd"). -- vq
Re: Re: [PATCH 0/4] Add import builtin
> a language that has no support for namespaces, awkward scoping rules, > a problematic implementation of name references, and so on. I could at least attempt to address those issues. Namespacing could be as simple as prepending the module name to the symbols that are being created. Bash seems to have no issues with symbol names such as path.add. It would be crude but effective. A true implementation would consist of completely separate evaluation environments with symbols linked in-between them. However, I imagine that this will not be possible because it would fundamentally change how bash works so thoroughly that it would just become another language. Please elaborate on the scoping and name reference issues. I'll address them if possible. I'd like to propose two additional semantics for source --library: - Load once The library `x` is loaded and evaluated only once in each context, no matter how many times `source -l x` is executed. There could be an additional `-f|--force` flag to override this. - Automatic symbolic namespacing The library name and a dot are automatically prepended to all symbols defined when a file is sourced via `source -l`. So if `x` contains `location=/etc/config`, then `source -l x` introduces the `x.location` variable into the current environment. Valid library file names would be restricted to the same set of characters that bash allows in variable names, excluding the dot. Otherwise the prefix cannot be derived automatically. There could be additional flags to override this: an `-n NAME` option which specifies a custom prefix and an `-N` option which disables namespacing. > provided that the behaviour of the posix mode > were to be left unchanged in all respects. I'll refactor it so that in POSIX mode the builtin behaves exactly as before. Matheus
Re: [PATCH 0/4] Add import builtin
On 5/6/24 1:27 AM, Matheus Afonso Martins Moreira wrote: Either you add the library directories to the PATH and risk false positives, or you delete the other directories and make sourced scripts unable to run commands. External commands, but there is nothing preventing something like a `registration' shell function, for example, that the sourced file invokes that runs with a local $PATH. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/6/24 1:21 AM, Phi Debian wrote: On Sun, May 5, 2024 at 9:47 PM Greg Wooledge wrote: On Sun, May 05, 2024 at 03:32:04PM -0400, Lawrence Velázquez wrote: The idea to add a BASH_SOURCE_PATH variable that gets searched before, or instead of, PATH when using the source builtin -- that sounds good. I don't really understand the concepts behind the rest of the discussion. Well even this is unclear 'BASH_SOURCE_PATH get searched before PATH' or 'BASH_SOURCE_PATH get searched instead of' or even 'BASH_SOURCE_PATH get searched after PATH' Because we haven't discussed the semantics. There shouldn't be any changes in posix mode, so that will continue to use PATH. In default mode, as long as the `sourcepath' option is enabled, if BASH_SOURCE PATH is set it would supersede PATH. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/7/24 2:43 AM, Kerin Millar wrote: Of course, it is sensible to gauge whether there is any potential interest in a proposed feature prior to submitting patches. Matheus tried to do exactly that on the 21st April. I may think that the resulting patches have been oversold but I would not fault his process. I don't have any problem with his process, as long as there's no expectation that I'll accept a new feature just because someone implemented it. Implementation is once, maintenance is forever. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/7/24 12:24 AM, Phi Debian wrote: Just questioning, I really have no idea what is the bash dev team way of receiving enhancement request. This list is the traditional place where proposals and discussion happen. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: [PATCH 0/4] Add import builtin
On 5/6/24 9:12 AM, Koichi Murase wrote: Chet mentioned the additional variable for the locations to search, but not a new builtin or a flag. Correct. The $PATH overloading has always been a source of confusion, or at least something you need to get used to; it would be a benefit to have a way to sidestep it without temporarily changing $PATH. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Re: Re: [PATCH 0/4] Add import builtin
On Sun, 5 May 2024 at 11:50, Koichi Murase wrote: > > Ideally, they'll be using bash's native import under the hood! > > Yes, module managers still need to implement their own "import" > command while using the proposed "import" primitive under the hood, > and it's simply interchangeable with the source builtin we already > have. > > * Module managers typically try to identify the file under more detailed > rules [...] For these reasons, most module managers actually resolve the > path by itself using their rules and specify *the absolute path* to the > source builtin. As far as the absolute path is specified, there is no > difference between the source builtin and the suggested `source -i' or > `import'. > I wonder if it would be useful to add options to 'command': * '-o' would report only the first command found (when more than one is given) (or could be '-1'); * '-p' would skip builtins & functions, and fail silently if no file can be found; * '-x' would search for files that *lack* exec permission. Then a module loader could simply be: require() { [[ ${__loaded_from[$1]} ]] && return local rp rp=$( PATH=$LIB_PATH \ command -opvx "$1".bash "$1".sh "$1" ) && source "$rp" && __loaded_from[$1]=$rp } (Being a Perl monk, I like the distinction between 'require' that has effect during run time, and 'use' that has effect during parsing. And 'import' is the process for binding names into namespaces, not the process for loading files.) -Martin
Re: [PATCH 0/4] Add import builtin
Ok thanx for clarification. I agry about git{lab,hub} position that's why I added {,whatever} meaning something really free. Ok now all is clear and I will not be surprised anymore if some other 'feature' proposal shows up in the future.
Re: [PATCH 0/4] Add import builtin
On Tue, 7 May 2024, at 5:24 AM, Phi Debian wrote: > On Mon, May 6, 2024 at 7:51 PM Kerin Millar wrote: >> >> >> I'll put it in a little more detail, though no less plainly. I find the >> terminology of "libraries" and "modules" to be specious in the context of a >> language that has no support for namespaces, awkward scoping rules, a >> problematic implementation of name references, and so on. These foundational >> defects are hardly going to be addressed by a marginally more flexible >> source builtin. Indeed, it is unclear that they can be - or ever will be - >> addressed. Presently, bash is what it is: a messy, slow, useful >> implementation of the Shell Command Language with an increasing number of >> accoutrements, some of which are fine and others of which are less so (and >> virtually impossible to get rid of). As curmudgeonly as it may be to gripe >> over variable and option names, this is why the import of library, as a >> word, does not rest at all well in these quarters. That aside, I do not find >> the premise of the patch series to be a convincing one but would have little >> else to say about its prospective inclusion, provided that the behaviour of >> the posix mode were to be left unchanged in all respects. >> >> -- >> Kerin Millar >> > > Thanx @Kerin, I got an intuitive reluctance with the patch series, but > could not formalize it that way, that is exactly it (specially the > nameref to me :-)) > > That brings up some questioning about the bash dev workflow. I > personally only monitor bash-bug (not the others bash-*), specially to > be aware of new incoming patches. > > Generally, the few patch that shows up here are patches that fix a > specific standing bug, or on some occasion, the declaration of a bug > along with a patch to fix it, they are generally reply with 'thanx for > the report and patch!' > > I rarely see patches about "Hey guys I got this great idea what do you > think", so I wonder for this kind of request does git{lab,hub,whatever} > be more appropriate? or may be I should say convenient, a public git > project (clone) generally have all the infrastructure for discussions, > enhancement and fix. I don't think that there is anything wrong with the workflow that has recently been in evidence. In case you're not fully aware, it goes something like this: 1) git clone https://git.savannah.gnu.org/git/bash.git 2) enter the local working copy and checkout the "devel" branch 3) optionally create a new branch to contain the intended changes 4) hack on the code and apply some commits 5) use git-format-patch(1) to generate a series of patches based on those commits 6) post the patches to the list, either manually or by using git-send-email(1) 7) allow the patches to undergo discussion and review 8) return to step 4 if necessary Let's say that Chet is prepared to accept the most recently posted patch series. In that case, all he need do is use git-am(1) to apply the commits from the posted messages directly to his own working copy of the devel branch. Similarly, anyone that would like to try out the patches themselves can do the very same thing and (re)compile bash. Perhaps even iterate on them. There are a few characteristics of this workflow that are worth noting. There is no requirement for a specialised platform or service to be involved. Only the git software is required, along with some medium by which to convey the am-formatted patches to whomsoever is to review them. Of course, it is sensible to gauge whether there is any potential interest in a proposed feature prior to submitting patches. Matheus tried to do exactly that on the 21st April. I may think that the resulting patches have been oversold but I would not fault his process. I don't wish to take this thread out into the weeds but would add one more thing. Not everyone is content with the encroachment of proprietary services such as GitHub. Increasingly, it is becoming the bar that must be cleared for open-source participation of any kind. Do we really want for a future in which one cannot even send a simple patch without agreeing to GitHub's terms and conditions, signing up, forking a project then opening a pull request? Or where maintainers won't even stoop to communicate with would-be contributors unless opening an issue on such a platform? > > The bash code owner can then pull the great idea when the demand for it > start roaring? For more ambitious feature branches, it might be more convenient. Ultimately, if Chet is content to review patches in the present fashion then that's all that really matters. > > Just questioning, I really have no idea what is the bash dev team way > of receiving enhancement request. The description of this list is as follows. "This list distributes, to the active maintainers of BASH (the Bourne Again SHell), bug reports and fixes for, and suggestions for improvements in BASH." As such, proposing enhancements here
Re: [PATCH 0/4] Add import builtin
On Mon, May 6, 2024 at 7:51 PM Kerin Millar wrote: > > > I'll put it in a little more detail, though no less plainly. I find the > terminology of "libraries" and "modules" to be specious in the context of a > language that has no support for namespaces, awkward scoping rules, a > problematic implementation of name references, and so on. These > foundational defects are hardly going to be addressed by a marginally more > flexible source builtin. Indeed, it is unclear that they can be - or ever > will be - addressed. Presently, bash is what it is: a messy, slow, useful > implementation of the Shell Command Language with an increasing number of > accoutrements, some of which are fine and others of which are less so (and > virtually impossible to get rid of). As curmudgeonly as it may be to gripe > over variable and option names, this is why the import of library, as a > word, does not rest at all well in these quarters. That aside, I do not > find the premise of the patch series to be a convincing one but would have > little else to say about its prospective inclusion, provided that the > behaviour of the posix mode were to be left unchanged in all respects. > > -- > Kerin Millar > > Thanx @Kerin, I got an intuitive reluctance with the patch series, but could not formalize it that way, that is exactly it (specially the nameref to me :-)) That brings up some questioning about the bash dev workflow. I personally only monitor bash-bug (not the others bash-*), specially to be aware of new incoming patches. Generally, the few patch that shows up here are patches that fix a specific standing bug, or on some occasion, the declaration of a bug along with a patch to fix it, they are generally reply with 'thanx for the report and patch!' I rarely see patches about "Hey guys I got this great idea what do you think", so I wonder for this kind of request does git{lab,hub,whatever} be more appropriate? or may be I should say convenient, a public git project (clone) generally have all the infrastructure for discussions, enhancement and fix. The bash code owner can then pull the great idea when the demand for it start roaring? Just questioning, I really have no idea what is the bash dev team way of receiving enhancement request.
Re: [PATCH 0/4] Add import builtin
On Mon, 6 May 2024, at 6:11 PM, Matheus Afonso Martins Moreira wrote: >>> A native way to source libraries. Built into bash, available to all users. >> That's the source builtin. > > It looks for scripts in directories meant for executables. > It prefers files with the executable bit set. > It's a native way to load bash scripts for sure. > But it's not a native way to load libraries. > >> It's just your expectation of the ergonomics but not ours. > > What are your expectations? > > Do you really think it's reasonable to suggest that > users implement their own library importing function? > > The fact such a function can be written in bash > is evidence of how powerful bash is. It doesn't > really follow though that everything that can be > written in bash should be done in bash. > >> He submitted patch seems unneededly large. > > The diffstat shows 9 files changed, > 203 insertions, 92 deletions. > > Most of those are very simple > refactorings of existing code. > >> incomplete addition of the long option of builtins > > What do you mean? What is missing? > >> an incomplete support for the XDG base directories, which should >> actually be discussed separately. > > XDG does not specify the ~/.local and ~/.local/lib directories. > Only the XDG Data Directory defaults to ~/.local/share if unset. > That implies a ~/.local directory tree that mirrors that of /usr. > Seemed simple enough so I just used that path. However, it is > not actually specified anywhere and there are no variables for > those directories. So I don't think there's anything that needs > to be supported here. > > Also, it appears the matter of XDG variables > has already been decided: > > https://savannah.gnu.org/support/?108134 > https://savannah.gnu.org/patch/?10431 > >> It does seem your personal hangup not giving a filename extension to >> the script files, which ended up with mixed script files to be sourced >> and executable files. > > Whether to use file extensions or not is the user's choice. > Bash should work correctly regardless of what the file name is. > > Besides, using file extensions does not actually prevent > false positives. Scripts often end in .sh and .bash too. > I have named them that way before. > > File extensions do not enforce any hard separation > between executables and libraries. Directories do that. > >> If you think that is the problem, your suggestion doesn't actually >> solve the problem of module managers. > > I didn't think it was a problem at first. I just thought it was unnecessary. > Bash already knows how to do it. We should make it do it for us. > > Now I do see it as a problem to be solved. Bash has a restricted shell mode > which, among many other things, prohibits slashes in file names passed to > the source builtin. If things are as you claim and the module managers really > do resolve the paths themselves in order to pass an absolute path to source, > that means they are all incompatible with bash's restricted shells. > The proposed native implementation of the module loader is not. > >> Module managers will have to implement it by themselves to satisfy >> their needs (which is obviously different from your ergonomics) >> even if your feature is added to Bash. > > That's true. When I mentioned ergonomics, I wasn't really talking about > the module managers though. I was talking from the perspective of a > user who just launched a terminal emulator, got a bash prompt > and now wants to source some custom functions. > >> Is this your rebuttal to Lawrence's "The sourced files that can be >> written with your feature available are exactly the same as the ones >> that can be written right now. Much like the periodic requests for >> XDG-organized startup files.". > > No. It was not actually a rebuttal at all. It was my response > to the exact text I quoted in the message. Specifically, this text: > >> Much like the periodic requests for XDG-organized startup files > > I'd really appreciate it if my contribution wasn't regarded > as just the latest iteration in the infinite loop of annoying > XDG Base Directory implementation requests from users. > >> If you avoid discussion by showing the relation with the authority, >> it seems a proof of lacking a straightforward counter argument > > I avoided discussion because I started to feel like > I wasn't being taken seriously. I was discussing > the matter with you in good faith before that. > >> Chet mentioned the additional variable for the locations to search, >> but not a new builtin or a flag. > > That's true. I did that of my own initiative. > After some discussion in the help-bash list, > I began to think that a builtin was justified. > Then after discussing it with you I changed > my mind and rewrote the patch so that it's an > option for the source builtin instead of an > entirely new builtin. You made excellent points > and you convinced me that a new builtin was > the wrong approach. > > I understand that it's not exactly what was discussed.
Re: Re: Re: [PATCH 0/4] Add import builtin
>> A native way to source libraries. Built into bash, available to all users. > That's the source builtin. It looks for scripts in directories meant for executables. It prefers files with the executable bit set. It's a native way to load bash scripts for sure. But it's not a native way to load libraries. > It's just your expectation of the ergonomics but not ours. What are your expectations? Do you really think it's reasonable to suggest that users implement their own library importing function? The fact such a function can be written in bash is evidence of how powerful bash is. It doesn't really follow though that everything that can be written in bash should be done in bash. > He submitted patch seems unneededly large. The diffstat shows 9 files changed, 203 insertions, 92 deletions. Most of those are very simple refactorings of existing code. > incomplete addition of the long option of builtins What do you mean? What is missing? > an incomplete support for the XDG base directories, which should > actually be discussed separately. XDG does not specify the ~/.local and ~/.local/lib directories. Only the XDG Data Directory defaults to ~/.local/share if unset. That implies a ~/.local directory tree that mirrors that of /usr. Seemed simple enough so I just used that path. However, it is not actually specified anywhere and there are no variables for those directories. So I don't think there's anything that needs to be supported here. Also, it appears the matter of XDG variables has already been decided: https://savannah.gnu.org/support/?108134 https://savannah.gnu.org/patch/?10431 > It does seem your personal hangup not giving a filename extension to > the script files, which ended up with mixed script files to be sourced > and executable files. Whether to use file extensions or not is the user's choice. Bash should work correctly regardless of what the file name is. Besides, using file extensions does not actually prevent false positives. Scripts often end in .sh and .bash too. I have named them that way before. File extensions do not enforce any hard separation between executables and libraries. Directories do that. > If you think that is the problem, your suggestion doesn't actually > solve the problem of module managers. I didn't think it was a problem at first. I just thought it was unnecessary. Bash already knows how to do it. We should make it do it for us. Now I do see it as a problem to be solved. Bash has a restricted shell mode which, among many other things, prohibits slashes in file names passed to the source builtin. If things are as you claim and the module managers really do resolve the paths themselves in order to pass an absolute path to source, that means they are all incompatible with bash's restricted shells. The proposed native implementation of the module loader is not. > Module managers will have to implement it by themselves to satisfy > their needs (which is obviously different from your ergonomics) > even if your feature is added to Bash. That's true. When I mentioned ergonomics, I wasn't really talking about the module managers though. I was talking from the perspective of a user who just launched a terminal emulator, got a bash prompt and now wants to source some custom functions. > Is this your rebuttal to Lawrence's "The sourced files that can be > written with your feature available are exactly the same as the ones > that can be written right now. Much like the periodic requests for > XDG-organized startup files.". No. It was not actually a rebuttal at all. It was my response to the exact text I quoted in the message. Specifically, this text: > Much like the periodic requests for XDG-organized startup files I'd really appreciate it if my contribution wasn't regarded as just the latest iteration in the infinite loop of annoying XDG Base Directory implementation requests from users. > If you avoid discussion by showing the relation with the authority, > it seems a proof of lacking a straightforward counter argument I avoided discussion because I started to feel like I wasn't being taken seriously. I was discussing the matter with you in good faith before that. > Chet mentioned the additional variable for the locations to search, > but not a new builtin or a flag. That's true. I did that of my own initiative. After some discussion in the help-bash list, I began to think that a builtin was justified. Then after discussing it with you I changed my mind and rewrote the patch so that it's an option for the source builtin instead of an entirely new builtin. You made excellent points and you convinced me that a new builtin was the wrong approach. I understand that it's not exactly what was discussed. However, I did have a reason for doing it that way. I think the logic behind the way source uses PATH is somewhat confusing and adding a new variable on top of all that would only confuse it further. For that reason, I added an option instead. If you
Re: Re: [PATCH 0/4] Add import builtin
2024年5月6日(月) 14:28 Matheus Afonso Martins Moreira : > > I fail to see how this could possibly save "thousands and thousands > > of lines of code". > > How many lines of code were needed to implement the module managers? > Probably a lot of lines. I guessed it was in the "thousands of lines" > ballpark. I thought that part "it potentially reduces thousands and thousands of lines of code" in [1] was a part of describing "what Matheus thought before submitting the patch", but now we shared that the situation in module managers is not like that. Isn't it? [1] https://lists.gnu.org/archive/html/bug-bash/2024-05/msg00053.html Anyway, it's never true that thousands of lines are reduced by the suggested feature. > However many lines that is, this feature would allow me > to reduce them all to zero by not actually needing a > module manager. It's trivial that your code reduces to zero because you designed your builtin to satisfy your needs. That doesn't show anything about its generality. > At the very least, it will save users from having to > implement an import function themselves. > They could still do it but they won't have to. That argument would apply to any other useful shell functions, but I don't think we should make everything builtin. > > You keep talking about this proposal as if it would spark a huge > > sea change in script maintenance, but I just don't see it, at all. > > A native way to source libraries. Built into bash, available to all users. That's the source builtin. > With the ergonomics you expect it to have. With good defaults, no setup. It's just your expectation of the ergonomics but not ours. The suggestion would be more useful for sure, but it doesn't mean it's the best. You haven't made any survey on existing implementations. > That's an incredibly huge change. If it were really "incredibly huge", I would try to block this change to carefully think about the impact in the future, other possibilities, and a possible better solution (e.g. with shell-function implementations or with a possibly different interface of a builtin). However, don't worry, I don't think the actual impact is that large... > Especially considering how little code > was required to make it happen. The submitted patch seems unneededly large. It also touches something else including incomplete addition of the long option of builtins, and an incomplete support for the XDG base directories, which should actually be discussed separately. > People see bash as a language that scales down instead of up. > The shellcheck tool helps a lot with shell script development but > managing complexity is still quite difficult. What's wrong with it? Even on this list, I think people's attitude about the future of Bash varies, but I don't think the community thinks Bash should replace or compete with Python or other general purpose scripting languages. The shell language is not a language intended to scale up in general, though it is free to attempt that in personal projects. I think Bash might acquire a necessary feature in the future, but I don't think we should hastily add every unnecessary feature just because that seems useful. Honestly, if we think about the necessity, I don't think the suggested feature is indispensable. > This could really change that. > > > AFAICT the only thing this proposal addresses is your personal > > hangup about using PATH to find sourced files > > It's not a personal hangup. It does seem your personal hangup not giving a filename extension to the script files, which ended up with mixed script files to be sourced and executable files. > Alternatively, you reinvent part of the functionality of source > by resolving the path yourself and giving it an absolute path. > None of these solutions seem right to me. If you think that is the problem, your suggestion doesn't actually solve the problem of module managers. Module managers will have to implement it by themselves to satisfy their needs (which is obviously different from your ergonomics) even if your feature is added to Bash. > > Much like the periodic requests for XDG-organized startup files > > I think I deserve at least a little more credit than that. > [...] _the bash maintainer_ > replied to my email saying he thought it was a > reasonable feature. Is this your rebuttal to Lawrence's "The sourced files that can be written with your feature available are exactly the same as the ones that can be written right now. Much like the periodic requests for XDG-organized startup files.". If you avoid discussion by showing the relation with the authority, it seems a proof of lacking a straightforward counter argument. In addition, as far as I understand, Chet mentioned the additional variable for the locations to search, but not a new builtin or a flag. > I interpreted that as a strong > signal that this would be a welcome contribution. I don't think a welcome contribution means the merge without any reviews and discussions. If
Re: Re: Re: Re: [PATCH 0/4] Add import builtin
2024年5月5日(日) 13:36 Matheus Afonso Martins Moreira : > > If your purpose is just to solve a small inconvenience of the `source' > > builtin mixing the namespaces of local scripts, "libraries", and > > executables, I think the suggested `source -i' or `source -l' would be > > fine. I think no additional reasoning is needed. > > That is my purpose! OK. > My solution to the file extensions problem for example is to > just not have file extensions at all, This is not normal. I think that is the source of your problem. Even though it is not strict, executable files (including shell scripts intended to be executed in a separate process) in PATH usually do not have the filename extensions. On the other hand, the scripts files intended to be sourced would typically have a filename extension of .sh or .bash (or even double extensions such as `.theme.sh,' `.plugin.sh', and `.alias.sh' depending on the type of the module. In this way, the namespace of the script files to be sourced and executable files are "roughly" separated. Of course, it is not strict and users can still have an executable script with a filename extension. In some cases, we would have a set of script files to be sourced without extensions, but those script files are usually intended to be managed by a specific module manager/loader that resolves the path by itself (such as /examples/functions/autoload and bash-completion _comp_load). Nevertheless, this makes the proposed change less convincing more or less..Do you think you submitted the patch if you would have had script files with filename extensions from the beginning? If you followed the typical arrangement of script files to be sourced, the problem you faced shouldn't have been that serious. > > However, in that case, I don't see much difference from > > « PATH= source » (as far as the module just defines a set of > > functions). > > It's true that the code is more or less the same from the perspective > of module managers. However, building this into bash does provide > a subtle benefit: separation between executable and module paths. > > Chet Ramey outlined it in his email: > > No need to ensure that they'll not attempt to run external commands. > The builtin is therefore less limited than a pure PATH solution. Yes, but that's implied my phrase ``as far as the module just defines a set of functions''. In case, I note that the functions defined in the sourced script files can call external commands after the sourcing completes because the shell function uses "the value of PATH of the current dynamic context" but not "the value of PATH when the function is defined". Anyway, I agree it is a problem that the sourced script cannot call the external commands if the script wants to do actual processing (such as initializations) instead of just defining a set of functions and variables. Nevertheless, it is technically possible to implement the proper identification of the script file in a shell function with a few dozens of lines, though it wouldn't be a single line implementation. > This would be most useful for a module manager that doesn't resolve > the module path by itself. I still don't think it is useful as I already wrote in the previous reply. I don't think there is a demand to reduce a few lines or a few dozens of lines from the module manager. Also, the benefit in the module manager seems too specific. Not many people try to implement the module manager. The language wouldn't be designed solely for module managers. The module managers could be an important piece of a language, but that's not all the important aspects of a language. If you were a developer of a module manager and faced a serious problem in implementing it, which is impossible to solve with an existing language feature set, the feature request would have been understood. However, you just seem to raise this example as a hypothetical project, which seems hardly convincing. > I agree that a one line of code reduction is underwhelming > but that's not the only reason to include it. The users are the > main beneficiaries. This gives users a simple way to load > modules without using any module managers at all. > From the perspective of the user, it potentially reduces > thousands and thousands of lines of code. I'll reply to it in a corresponding thread by Lawrence. > Still, I did and still do hope that it will make life easier > for the maintainers of the module managers too. If you still hope that, I believe your patches would be blocked until we test the design by the actual implementation of module managers based on it and show it's validity. Furthermore, I think it wouldn't get into Bash because I don't think it's possible to show it. This feature is simply unnecessary for module managers. Sure it might be used to reduce a small amount of code, but it's not an indispensable feature. It's not sufficient to justify the change. > > Would you try to exclude the possibility > > of a module manager in the
Re: Re: [PATCH 0/4] Add import builtin
> Your proposition could not be 'builtin', you want a new 'model' with > 'packages/module' Yes. However, that was because I did not really know bash module managers existed. I immediately adopted a conservative approach once I was informed of their existence. I do not intend to develop the import builtin patch set anymore, I have switched to the source option patch set. > Another option is to create a fork of a project (here bash) implement your > hack, > provide it (github kind) then see the stats, if your new bash skyrocket, > may be your hack will be back ported. Forking bash is not an option for me. Its ubiquitousness is a major reason why I use it. > All that to say, I am not too sure that distro (and installer of all sort) > will be willing to get a fatter bash for higher risk of bugs, hack, secu, > name it, > and would surely ask this feature to be optional, > then always requiring an init line to enable it. Making it optional is definitely possible. I'll work on that if needed. I have made the defaults compile time configurable. I think including the user's home directory is very useful, it certainly can't be worse than including the current directory. However, I made it easy to change should anyone want or need to do so. I'd like to note that bash has a restricted shell mode which disallows many things, including the sourcing of files via their absolute paths. I made sure that both the import builtin and source --library supported that. I was told that many bash module managers supply an absolute path to source, making them incompatible with restricted shells. Reading the documentation now, it says that restricted mode also disallows overriding PATH. I can also make it so that setting or unsetting BASH_LIBRARIES_PATH is also prohibited. This should make this solution attractive from a security perspective. Administrators can set the bash libraries path and disallow changes to it.
Re: Re: [PATCH 0/4] Add import builtin
On Mon, May 6, 2024 at 7:28 AM Matheus Afonso Martins Moreira < math...@matheusmoreira.com> wrote: > Yet the feature has been described as "irritating"! > I really don't understand the cause for this > and it's making me feel really unwelcome. > I think it is not personnal, you proposed something, and other told you what you propose is overkill due to the simplicity to do the same with no change in bash, and a 1liner of code in your top level project file. Your proposition could not be 'builtin', you want a new 'model' with 'packages/module' (not saying library on purpose, way too much for me). Starting from there your model need at least an init line to say you want bash operating in your model 'packages/module'. Form there your new model can be initialized with a 1liner, either a dynloadable builtin (.so file you provide), or an init file (.sh no +x) you source. At this point whatever technic, you have your 'import'. Is that big of a deal to ask your developers to comply with your model and init your 'packages/module' paradigm bringing 'import' in a 1 line in their top script (here script mean +x executable bash source file). TBH, I have a packages system for both bash and ksh since decades, they all start by an init line at top level, and they never required any shell hack, and they do far more that intended here, repos, versioning, dependencis, multi-arch (run time context) etc... I think it is very good to be enthusiastic about hacking a free software, a good start point is to fix bugs, even tiny one, even simple docco. Another option is to create a fork of a project (here bash) implement your hack, provide it (github kind) then see the stats, if your new bash skyrocket, may be your hack will be back ported. You could adverstise your new bash in stko, each one asking for a package manager in bash you could reply with your new invention, boosting the stats. All that to say, I am not too sure that distro (and installer of all sort) will be willing to get a fatter bash for higher risk of bugs, hack, secu, name it, and would surely ask this feature to be optional, then always requiring an init line to enable it. So I guess it will take a long time before seeing that in the shell, but I may be wrong.
Re: Re: [PATCH 0/4] Add import builtin
> I fail to see how this could possibly save "thousands and thousands > of lines of code". How many lines of code were needed to implement the module managers? Probably a lot of lines. I guessed it was in the "thousands of lines" ballpark. However many lines that is, this feature would allow me to reduce them all to zero by not actually needing a module manager. And the benefit would be multiplied by all the users of bash which is probably the most ubiquitous shell there is. That's a lot of benefit. At the very least, it will save users from having to implement an import function themselves. They could still do it but they won't have to. > You keep talking about this proposal as if it would spark a huge > sea change in script maintenance, but I just don't see it, at all. A native way to source libraries. Built into bash, available to all users. With the ergonomics you expect it to have. With good defaults, no setup. That's an incredibly huge change. Especially considering how little code was required to make it happen. People see bash as a language that scales down instead of up. The shellcheck tool helps a lot with shell script development but managing complexity is still quite difficult. This could really change that. > AFAICT the only thing this proposal addresses is your personal > hangup about using PATH to find sourced files It's not a personal hangup. Manipulating the PATH has consequences. Either you add the library directories to the PATH and risk false positives, or you delete the other directories and make sourced scripts unable to run commands. Alternatively, you reinvent part of the functionality of source by resolving the path yourself and giving it an absolute path. None of these solutions seem right to me. I think the best solution is to just avoid all that by adding another variable. This approach resolves all the above concerns. It also reuses bash's pathname resolution code and has the added benefit of being native to bash and available to all users, eliminating the requirement that they implement this themselves or install an external dependency just to load libraries. > The sourced files that can be written with your feature available > are exactly the same as the ones that can be written right now. It's possible but it's not as easy or ergonomic as it could be. > Much like the periodic requests for XDG-organized startup files I think I deserve at least a little more credit than that. This was not some simple drive-by feature request. I implemented the feature, debugged the code, tested it and sent a patch with my full rationale. I did so after asking the community what they thought about this and after _the bash maintainer_ replied to my email saying he thought it was a reasonable feature. I interpreted that as a strong signal that this would be a welcome contribution. In my very first email ever to these lists, I made it clear that I intended to contribute this patch. I was not requesting it, I intended to show my work from the outset. Now I'll be the first to admit that this first iteration was not perfect. People raised issues and concerns, they were absolutely valid and I tried to address them in good faith to the best of my ability. I even learned new things from these replies and I'm thankful for that. But I don't think it's fair at all to just dismiss it as a "request". The code has been written and as far as I can tell it works and makes bash better than it used to be. I even made sure to separate the commits into logical changes so that the the maintainer would be able to cherry pick the general refactoring improvements even if the overall feature was rejected in the end. It was my intention to do at least some good even if this turned out to be a stupid idea in the end. My only request here is that you seriously consider the work of a fellow software developer for merging into master. That's all. > BASH_SOURCE_PATH might be convenient > but is not groundbreaking and probably > doesn't merit significant changes to the shell. I can't speak for others but I'd say this feature is going to be quite ground breaking for me. It's going to significantly and permanently change the way I use bash. I'm going to write lots of little libraries. I'll release them as free software too. My dotfiles repository is AGPLv3. > even convinced it merits a new "source" option. Why not? The addition of this new builtin turned out to be a significant change, much bigger than I anticipated. I quickly agreed that it would be better as an option to the existing source builtin which is a much more conservative solution. I've even sent the new patchset. It is no longer a significant change. It's not even a significant amount of code. It adds a useful feature, and does so in a way that does not cause any incompatibility. Yet the feature has been described as "irritating"! I really don't understand the cause for this and it's making me feel really unwelcome.
Re: [PATCH 0/4] Add import builtin
On Sun, May 5, 2024 at 9:47 PM Greg Wooledge wrote: > On Sun, May 05, 2024 at 03:32:04PM -0400, Lawrence Velázquez wrote: > > > The idea to add a BASH_SOURCE_PATH variable that gets searched before, or > instead of, PATH when using the source builtin -- that sounds good. I > don't really understand the concepts behind the rest of the discussion. > > Well even this is unclear 'BASH_SOURCE_PATH get searched before PATH' or 'BASH_SOURCE_PATH get searched instead of' or even 'BASH_SOURCE_PATH get searched after PATH' Each have valid reasons to exist... Anyway if this is the only desire then a simple In module system init .sh (used by .rc or other .sh) IPATH=... ; alias xyz_import ='PATH="$IPATH" source' ; alias xyz_type ='PATH="$IPATH" type' Above the setup is for 'instead of PATH', 'PATH="$IPATH:$PATH" source' for before PATH and so on. Then you can use xyz_import foo.sh or xyz_type foo.sh BTW I didn't red all the patches, but I wonder what the semantic of the builtin 'type' becomes in your implementation, I guess that on top of currently defined concepts (file, function, alias, builtin) you now add 'library (better name needed)' with all the docco and jazz about it. The risk/profit (or even ROI) seems not favorable, i.e the implementation, the QA tests, the docco. For something that can be done in a 1 liner in an .rc file, I am really not convinced.
Re: [PATCH 0/4] Add import builtin
On Sun, May 05, 2024 at 03:32:04PM -0400, Lawrence Velázquez wrote: > Much like the periodic requests for XDG-organized startup files, a > BASH_SOURCE_PATH might be convenient but is not groundbreaking and > probably doesn't merit significant changes to the shell. I'm not > even convinced it merits a new "source" option. I don't really have any strong opinions on this issue, but the proposed patches seem a bit overkill-ish to me. The idea to add a BASH_SOURCE_PATH variable that gets searched before, or instead of, PATH when using the source builtin -- that sounds good. I don't really understand the concepts behind the rest of the discussion.
Re: [PATCH 0/4] Add import builtin
On Sun, May 5, 2024, at 12:35 AM, Matheus Afonso Martins Moreira wrote: > I agree that a one line of code reduction is underwhelming > but that's not the only reason to include it. The users are the > main beneficiaries. This gives users a simple way to load > modules without using any module managers at all. > From the perspective of the user, it potentially reduces > thousands and thousands of lines of code. I fail to see how this could possibly save "thousands and thousands of lines of code". You keep talking about this proposal as if it would spark a huge sea change in script maintenance, but I just don't see it, at all. AFAICT the only thing this proposal addresses is your personal hangup about using PATH to find sourced files; it doesn't help with authoring reusable "libraries". The sourced files that can be written with your feature available are exactly the same as the ones that can be written right now. Much like the periodic requests for XDG-organized startup files, a BASH_SOURCE_PATH might be convenient but is not groundbreaking and probably doesn't merit significant changes to the shell. I'm not even convinced it merits a new "source" option. -- vq
Re: Re: Re: [PATCH 0/4] Add import builtin
On Sat, May 4, 2024 at 4:44 AM Matheus Afonso Martins Moreira < math...@matheusmoreira.com> wrote: > > By "library system" I just mean the exact mechanism through which > bash will load a "library". By "library", I mean ordinary scripts > whose purpose is to collect related functions and variables > for reuse by other scripts or interactive bash users. > May be that's why the term 'library' is not very well suitable as there are other ways to load functions and variables in a shell context, i.e shared libraries/objets dynamic builtins, so the 'import got to cover all of none. In this case the import would find the shared libs in the restricted path IMPORT_PATH along with the scripts, and then a 'library' could either be text script or binary .so a.out. Sounds more like a pandora box :-) > By introducing the "module/library system" I want to do the following: > > 1. Add a builtin primitive that can be used to load libraries > 2. Establish a convention for where bash will look for libraries > 3. Separate the libraries from the commands/executables > If its all that simple may this 3 liners to stick in your.rc file or hide it in yet another . findable script shopt -s expand_aliases # Some may dislike this xyz_import='for xyz in ${XYZ_IMPORT_PATH//:/\/$1 }/$1;do xyz=$(realpath -q $xyz);[ -r "$xyz" ]&&. $xyz&done' alias xyz_import='source /dev/stdin <<< "$xyz_import"' 1. It create a new primitive (well a command in shell parser vocable) xyz_import 2. It Establish a convention for where bash will look for libraries XYZ_IMPORT_PATH 3. Separate the libraries from the commands/executables by looking in the $XYZ_IMPORT_PATH dir set only Murphy's law Note the I namespaced all this with xyz/XYZ, change for your taste, but beware of other 'import' While testing this I discover (and forgot) that I installed the 'imagemagick' package (linux debian) which in turn setup an alternative path on 'import' $ ll /usr/bin/import lrwxrwxrwx 1 root root 24 Feb 26 07:43 /usr/bin/import -> /etc/alternatives/import $ ll /etc/alternatives/import lrwxrwxrwx 1 root root 23 Feb 26 07:43 /etc/alternatives/import -> /usr/bin/import-im6.q16 So I guess it is wise to stay away from 'import' name.
Re: Re: Re: Re: [PATCH 0/4] Add import builtin
On Sun, May 5, 2024 at 7:36 AM Matheus Afonso Martins Moreira wrote: > I certainly intend to use it as one should it be merged. If it's not you should try turning this into a loadable builtin. An `include' command that lets you selectively import variables/functions from a larger collection and namespace them, restrict commands that can be invoked to a smaller set than what a PATH search would turn up, etc. would be nice to have.
Re: Re: Re: Re: [PATCH 0/4] Add import builtin
> If your purpose is just to solve a small inconvenience of the `source' > builtin mixing the namespaces of local scripts, "libraries", and > executables, I think the suggested `source -i' or `source -l' would be > fine. I think no additional reasoning is needed. That is my purpose! I think I went a bit too far when trying to advocate for the feature. In my mind, this solution already creates a module system. I certainly intend to use it as one should it be merged. So I thought it would be a good argument to justify its inclusion. However, it sparked a much wider discussion which I was unprepared for. I'm going to learn more about the systems in order to discuss them more coherently. I was thinking about creating a new thread in help-bash and inviting the maintainers of every project that was cited to discuss it in more detail. It's my intention to work with everyone. > The question is whether you would still value `source -i' if it were > not useful for module managers at all. It would still be an extremely valuable feature for me. > To me, you seem to raise thebar by yourself. Where is your bar? I was just trying to convince everyone that it would be a good feature for inclusion. I think I went a bit too far there. > Can I call what you describe the "module loader"? > Let me call the above the "module manager". Yes, I think those are more precise terms. I agree with them. > I understand that the purpose of the *present* patch is the module > loader, but I thought you tried to prepare the primitive useful for a > unique module manager. Yes. I think it was a mistake for me to pursue that line of reasoning. For my use case, this module loader is the only primitive needed. My module management consists of cloning my dotfiles repository which can be found here: https://github.com/matheusmoreira/.files This configures all my applications including bash and also installs all my scripts in ~/.local/bin. These scripts are growing in complexity so I thought about ways to modularize them, extract common and useful functions and make them independently loadable by other scripts. So I thought: I have ~/.local/bin, why not ~/.local/lib/bash? I can just put the function definitions in module files, and put those module files in ~/.local/lib/bash. Then I just gotta get bash to load those modules. Getting bash to load those modules led to this patch. That is the exact use case supported by this proposed feature. For a moment I actually thought it was so simple that it ought to work for everything and for everyone. I mean, it's the exact same approach used by bash to find commands and executables. It's also got precedent in other Linux and *nix software. The GNU dynamic linker and loader for example uses LD_LIBRARY_PATH to achieve the exact same goal. Simple can be deceptive though. I should probably at least learn about the existing solutions before trying to discuss them. Otherwise I'll just end up putting my foot in my mouth. > The source builtin is already the primitive feature that can be used > to develop a module manager on top of it. > For these reasons, most module managers actually resolve > the path by itself using their rules and specify *the absolute path* > to the source builtin. I think I understand now. Yeah, it looks like the existing module managers have quite complex name resolution requirements. My solution to the file extensions problem for example is to just not have file extensions at all, thereby eliminating the need to do any file name processing to begin with. This is compatible with a simple implementation that just sources the given file name. This is a good thing: the patch will not conflict with existing systems. Absolute path names will still get loaded properly. I was hoping that this feature would at least be of some use to module managers but depending on the complexity of their path resolution algorithms there might be no sensible way for them to make any use of it. It's probably just wishful thinking on my part. > However, in that case, I don't see much difference from > « PATH= source » (as far as the module just defines a set of > functions). It's true that the code is more or less the same from the perspective of module managers. However, building this into bash does provide a subtle benefit: separation between executable and module paths. Chet Ramey outlined it in his email: https://lists.gnu.org/archive/html/bug-bash/2024-05/msg00038.html > PATH=$BASH_IMPORT_PATH:$PATH source > or > PATH=$BASH_IMPORT_PATH source > > You could force the latter if you are sure that the sourced files will > not attempt to run external commands. The builtin would allow forcing the latter while leaving PATH alone. No need to ensure that they'll not attempt to run external commands. The builtin is therefore less limited than a pure PATH solution. This would be most useful for a module manager that doesn't resolve the module path by itself. You noted that most of them
Re: Re: Re: [PATCH 0/4] Add import builtin
If your purpose is just to solve a small inconvenience of the `source' builtin mixing the namespaces of local scripts, "libraries", and executables, I think the suggested `source -i' or `source -l' would be fine. I think no additional reasoning is needed. In this case, the "#pragma once" feature wouldn't be needed or should be a separate flag. You can of course add extra reasoning about the necessity of this small improvement, but the problem is that I don't think those arguments are valid. If your goal is to facilitate the primitive parts needed for library management, I don't think the current suggestion would actually help. The source builtin is already the primitive feature that can be used to develop a module manager on top of it. I don't think any additions to the source builtin is useful for developing a module manager because the typical use cases by the module managers are different from your assumptions (as will be discussed later in this reply). This is a YAGNI feature, which hasn't been tested by real use cases of the intended usage. Then, you don't have a motivation to modify the source builtin or add a new builtin at present. The question is whether you would still value `source -i' if it were not useful for module managers at all. To me, you seem to raise the bar by yourself. Where is your bar? 2024年5月4日(土) 11:44 Matheus Afonso Martins Moreira : > I think we were unable to reach an understanding because we were both > using the same words to talk about different things. Can I call what you describe the "module loader"? Then, > Those are problems better > solved by Linux distribution packagers or a custom package manager for bash. > I may be wrong but I believe that is the role many of those bash frameworks > are fulfilling. Let me call the above the "module manager". I understand that the purpose of the *present* patch is the module loader, but I thought you tried to prepare the primitive useful for a unique module manager. This is because you mention that a language should have only one module system so that the library developers do not need to care about the variation. The variations in the module managers is a problem since the library itself needs to be adjusted under the rule of the module manager (for dependency resolution, etc). This is a general problem for a programming language, and recent programming languages have respective standard ways of module management. But maybe you've been discussing something else. > So at least to me this is all about the "import" primitive. > Which particular form it takes is up to debate, it's something > that's worth discussing and getting right before it's released > due to the difficulty in changing such core APIs after the fact. > However, the fact is that I think many of those other considerations > are actually out of scope! I understand you are not going to develop the module manager but just want to focus on the module-loader part. Nevertheless, I think you can agree that we want to discuss the actual use cases of the "import" primitive in order to shape the needed core API in a usable form (Without mentioning the use cases, what would be discussed?). Besides, you seem to assume the future uses of the "import" primitive in module managers. Then, we cannot avoid the discussion about the use cases in the module managers. > Those are problems better > solved by Linux distribution packagers or a custom package manager for bash. > I may be wrong but I believe that is the role many of those bash frameworks > are fulfilling. In order to do that, they _had_ to create an import primitive > for themselves because bash lacked such facilities. My intention is to fix > the lack of the import facilities, not to replace those frameworks. Yes, we had to create the "import" command by ourselves, but the situation doesn't change at all even after the suggested modification. . > Ideally, they'll be using bash's native import under the hood! Yes, module managers still need to implement their own "import" command while using the proposed "import" primitive under the hood, and it's simply interchangeable with the source builtin we already have. * Module managers typically try to identify the file under more detailed rules, which cannot be implemented by just the `source -i' builtin. For example, module managers allow dropping the filename extension from the specified name; the "import moduleA" command would search the file "moduleA", "moduleA.sh", or "moduleA.bash". Or some other managers identify the version of a module based on the requested range. Some frameworks try to first identify the system version of the module and fall back to the bundled version depending on some conditions. Those rules depend on the module manager. Also, some module managers want to manage the actual paths of the modules that are loaded. For these reasons, most module managers actually resolve the path by itself using their rules and specify *the absolute path* to the
Re: Re: Re: [PATCH 0/4] Add import builtin
> If the purpose is to introduce a standard module system in Bash, > I'll have to be opposed to the change because I think the current > suggestion for `source -i' wouldn't help satisfy that purpose at all. I think we were unable to reach an understanding because we were both using the same words to talk about different things. I think I have a different idea of what constitutes a "module/library system" and it's causing everyone to think that I want more out of this patch than I actually do. By "library system" I just mean the exact mechanism through which bash will load a "library". By "library", I mean ordinary scripts whose purpose is to collect related functions and variables for reuse by other scripts or interactive bash users. A library is a container for functions/variables, and the library system is the exact API scripts use to fill up those containers with code and data. So at least to me this is all about the "import" primitive. Which particular form it takes is up to debate, it's something that's worth discussing and getting right before it's released due to the difficulty in changing such core APIs after the fact. However, the fact is that I think many of those other considerations are actually out of scope! The include guard has potential to be a language feature. This is a generally useful feature since libraries are usually meant to be included only once. This allows the source statement to be idempotent, meaning `source x; source x` does not run the script twice and therefore produces no additional side effects. An override via a --force option can be provided to allow control over this in the cases where it is intended and desirable. It should also be easy to implement, just need to make a set of loaded scripts and only execute them if forced to or if the script is not in the set, ensuring that it is added to the set later. Bash already has hash table support so it should be a simple matter of using the data structure. On the other hand, central repositories are a completely external concern, as is the installation and management of libraries. Those are problems better solved by Linux distribution packagers or a custom package manager for bash. I may be wrong but I believe that is the role many of those bash frameworks are fulfilling. In order to do that, they _had_ to create an import primitive for themselves because bash lacked such facilities. My intention is to fix the lack of the import facilities, not to replace those frameworks. Ideally, they'll be using bash's native import under the hood! By introducing the "module/library system" I want to do the following: 1. Add a builtin primitive that can be used to load libraries 2. Establish a convention for where bash will look for libraries 3. Separate the libraries from the commands/executables The proposed import builtin accomplishes goal 1. The BASH_IMPORT_PATH variable accomplishes goal 2. The fact import will look for libraries _only_ in BASH_IMPORT_PATH accomplishes goal 3. Which paths are contained in BASH_IMPORT_PATH is completely undefined. Linux distributions might add their own paths. Users might do the same. Maybe the bash frameworks will take control over that variable in order to run their commands so that they can ensure only their packages are loadable by bash. Someone might make a "bashenv" tool for isolating a set of bash libraries. All these usages are enabled by the builtin. A uniform interface to library loading will make it easier to develop library code: there is one bash native way to import a dependency, not one specific import mechanism for each framework. The frameworks can still manipulate the load paths however they want, but the code will be more uniform. Maybe it's wishful thinking but perhaps they'll even end up being portable between the frameworks. > However, if the purpose is solely to solve the ambiguous search paths > of the `source' builtin, I think a flag to the source builtin is a > reasonable suggestion. That is the purpose behind this patch! That's what I meant by "library system". A system that's built into bash through which libraries can be loaded. Solving the ambiguous search paths issue is a prerequisite for it, but an issue of equal importance is the separation of the load paths for libraries and commands. This will allow the library loading paths to be freely manipulated without affecting the way that scripts work. > This is my personal preference for the name, > but the current simple feature of restricting > the search paths doesn't feel` import'. > I'd think it can simply be BASH_SOURCE_PATH. > The flag can also be something other than `-i' > or` --import', like `source -l ' to mean > the "library". BASH_SOURCE_PATH and `source -l|--library` are good names. BASH_LIBRARIES_PATH would be consistent with --library as well as existing variables such as BASH_LOADABLES_PATH. > I feel we should ask the package maintainers to include those files. I think the fact
Re: [PATCH 0/4] Add import builtin
Date:Fri, 3 May 2024 09:18:09 -0400 From:Chet Ramey Message-ID: <842de6ec-c7f9-47fb-ab21-e25c0bfd8...@case.edu> | How is this any different than | | PATH=$BASH_IMPORT_PATH:$PATH source | or | PATH=$BASH_IMPORT_PATH source | | You could force the latter if you are sure that the sourced files will | not attempt to run external commands. Another safer way might be findfile() { local - P IFS=: case "$1" in */*)printf %s "$1"; return;; esac set -f for P in ${BASH_IMPORT_PATH:-.} do if test -f "${P:-.}/$1" then printf %s "${P:-.}/$1" return fi done printf %s "$1" } And then . "$(findfile whatever)" relying upon the error message from '.' if whatever isn't found (and use whatever name you like instead of "findfile"). An alternative I hate to even mention, as it is so hacky (and has mostly been deleted from most of its descendants) is the ash shell %func PATH hack: if an entry in $PATH ends in %func and the search for a command reaches that entry, and a file exists in the directory named (with the "%func" deleted) with the name of the command being sought, then the shell will (would) source that file, and if after doing that a function with the name of the command being sought had appeared, then run that function as the command. Otherwise, just continue with the PATH search (more than one %func entry was possible). So I agree, "import" is definitely not needed, and if it were really to be deemed useful functionality, "import" is the wrong name. kre
Re: Re: Re: [PATCH 0/4] Add import builtin
I think we can separate the discussion about the module system and the source builtin. What is the primary purpose or the reasoning behind the suggestion? If the purpose is to introduce a standard module system in Bash, I'll have to be opposed to the change because I think the current suggestion for `source -i' wouldn't help satisfy that purpose at all. At least, it is immature or insufficient to be used as a module system. There are many things to consider, including the include guard I already mentioned, a central repository to avoid conflicts in the library names, etc. You also need to fight against existing module frameworks to convince them about introducing a mechanism that might beat them. If one has to implement a module system using a set of shell functions based on `source -i', the situation doesn't change from the current one with many module systems based on the source builtin. However, if the purpose is solely to solve the ambiguous search paths of the `source' builtin, I think a flag to the source builtin is a reasonable suggestion. Currently, the command `source ' might hit three different types of files: 1. a file in the current working directory 2. a script file (that is supposed to be sourced) in PATH 3. this is not intended, but an executable file that is not supposed to be sourced. To make the source builtin find type 1, one can use `source ./'. However, there is no way to force type 2 without being affected by type 1 or 3 when the library is not found and/or there is a conflicting name. Then, we can prepare a separate variable BASH_IMPORT_PATH for the search paths for script files to source, and add a flag of the source builtin that forces searching only BASH_IMPORT_PATH. It's similar to `unset -v/-f/-n' where the command `unset ' can ambiguously remove a variable or a function, but `one can specify a type through -v/-f/-n. This is my personal preference for the name, but the current simple feature of restricting the search paths doesn't feel `import'. I'd think it can simply be BASH_SOURCE_PATH. The flag can also be something other than `-i' or `--import', like `source -l ' to mean the "library". 2024年5月4日(土) 3:00 Matheus Afonso Martins Moreira : > > No, those files need to be distributed by the Bash package of > > distributions, and the path needs to be properly set up. > > Then I don't think that would be the ideal solution. I feel we should ask the package maintainers to include those files. As for the loadable builtins, even though the recent versions of Bash install loadable builtins in $prefix/lib/bash when installed by « ./configure && make install », most package maintainers do not include them in the (main) package for some reason. As a result, even if Bash provides useful loadable builtins, the script writers cannot assume their existence, which is a problem. Currently, the files under /examples/functions are not installed even by « ./configure & make install », but I think useful shell functions can also be installed in e.g. $prefix/share/bash/functions, and also included in the packages of the distributions. > It's embarrassing but the truth is I was not even aware of these projects. Don't worry. You are here to ask the community about that. > My intention was simply to add a feature I wanted to bash. > I experienced difficulty with maintaining a growing collection > of personal scripts, had this idea, coded it up and sent patches. If it were the personal purposes, you could start it with a shell function implementation. There is no need to modify the upstream Bash for personal uses. It's not too late to ask for standardization when you need to share your framework with others. > > I also think the variation is actually needed because the assumed > > search paths are different for different libraries. We cannot simply > > merge all those implementations into a single command because each > > library wants to limit BASH_IMPORT_PATH to the locations they provide. > > Why is this required? > > > Then, it's identical to `PATH= source'. I also think the > > variation is not a problem. The separation of the domain is useful. > > Please elaborate on this point. How is it useful? I assume the case where different module systems coexist. In particular, interactive frameworks and applications need to be loaded in a single instance of Bash even when they are not integrated with each other. The different module systems do not need to cooperate with each other but should be allowed to coexist in a session and work without interfering with each other. For example, when module X managed by system A requests another module Y, we want to find module Y provided by system A and exclude the modules provided by system B (even when no module is provided with the conflicting name Y in system B). The idea is the same as yours to separate the namespace of the executable files and the script files to source. > > If desired, the developer can choose one module framework > >
Re: Re: Re: [PATCH 0/4] Add import builtin
> it doesn't need to be implemented as a builtin It doesn't need to be implemented this way.. But it could be. It's true that a whole new builtin was overkill but the discussion still pointed to a better solution in the form of source --import. This is a more conservative approach but it's still a builtin which means advantages such as widespread availability, PATH preservation, general ergonomics. > Yes, that is a problem in directly using the source builtin, but I > think the original intention for the design of `.' and `source' is > that the library shouldn't have the same name as exiting commands. > Again, this is related to the improper setup of the library. Then, > there is always the possibility of a name conflict between different > libraries that share their names even if it doesn't conflict with > executable files. Yeah, but sourcing an executable file can be more > problematic than sourcing a different library. It's an issue of namespaces. I think it's wrong for libraries to share the same namespace as executables and commands. By placing them in separate file system locations and searching by means of different PATH variables, separate namespaces are established and kept isolated from each other, making such clashes all but impossible and also giving greater freedom to library authors. > However, I shall note that some shell programs are intended to be used > as both a library and a separate program. > For the above reason, I think you still need to search for both types of > files. I understand now. Looks like filtering by executable attribute was not such a good idea after all. > But what I wanted to say is that the `import' builtin should be an > opt-in feature, i.e., it should be disabled by default to avoid > conflicts with existing `import'. That makes sense and I agree. I think the better solution is to add this functionality as an option to source instead. This way, existing code can continue to define their own import functions and no clashes should occur. > No, those files need to be distributed by the Bash package of > distributions, and the path needs to be properly set up. Then I don't think that would be the ideal solution. > [1] > https://github.com/niieani/bash-oo-framework?tab=readme-ov-file#using-import > [2] > https://github.com/akinomyoga/ble.sh/wiki/Manual-%C2%A78-Miscellaneous#user-content-fn-ble-import > [3] > https://github.com/basherpm/basher?tab=readme-ov-file#sourcing-files-from-a-package-into-current-shell > [4] https://github.com/modernish/modernish?tab=readme-ov-file#simple-form > [5] > https://github.com/bash-bastion/basalt/blob/main/docs/reference/api.md#basaltload > [6] https://github.com/ko1nksm/modulesh/blob/master/README.md#import > [7] > https://github.com/scop/bash-completion/blob/c48854850f702604aeb600ae496fb6b2eb840f8e/bash_completion#L3127 > [8] > https://github.com/ohmybash/oh-my-bash/blob/9cfb35c946953cb8cc1511cce47986cdd630852a/oh-my-bash.sh#L52 It's embarrassing but the truth is I was not even aware of these projects. Truly, it was not my intention to just override everyone else's work. I apologize if I came across that way because of my ignorance. My intention was simply to add a feature I wanted to bash. I experienced difficulty with maintaining a growing collection of personal scripts, had this idea, coded it up and sent patches. I had the foresight to email help-bash first and ask what others thought of the idea, my impression was that the idea was well received despite some perfectly valid concerns. > Is your design of the `import' builtin based on any real frameworks? It certainly is not. Nor would I claim to have any real frameworks of my own. All I have is a growing collection of scripts in my dotfiles repository. I was hoping to make it more organized by adding this feature to bash. I suppose I could say I based this design on the system I implemented in the programming language I created. I'm far from being any kind of authority on the subject but I did study the library systems of numerous other languages in order to do it. So it might not be informed by large scale usage but it's not based on nothing either. > Also, if you are going to propose "the standard mechanism", you will > have to survey those implementations to investigate what would be > demanded by the real use cases. I'd be happy to discuss the matter with everyone. I'm sure their expertise will be invaluable. The reason I did not do it was ignorance. I literally did not know they existed. > I also think the variation is actually needed because the assumed > search paths are different for different libraries. We cannot simply > merge all those implementations into a single command because each > library wants to limit BASH_IMPORT_PATH to the locations they provide. Why is this required? > Then, it's identical to `PATH= source'. I also think the > variation is not a problem. The separation of the domain is useful.
Re: Re: [PATCH 0/4] Add import builtin
> How is this any different than The main advantage would be availability of this mechanism by default in all new versions of bash. This would make it "native" to the language, the path of least resistance to reusing bash code. Users will be able to just place the scripts in the appropriate locations and import them. > You could force the latter if you are sure that the sourced files will > not attempt to run external commands. This is also a big advantage: the proposed builtin does not have this limitation. It preserves PATH and so it can import the reusable shell scripts from the library locations while commands and the source builtin continue to work as normal. > You could even make this an alias if you want. Yes, but then it would require every user to program this facility into their shells. I think it would be great if this requirement could be avoided. Building it into bash would make it very ergonomic. One of the issues raised in the ensuing discussion was the fact POSIX enumerates the words which shells are allowed to interpret specially, and the fact that "import" is not among them. Indeed, it looks like others have developed shell scripting frameworks which also use the word "import" to implement similar functionality. I agree that it is a major issue and in response I suggested changing the patch from a new builtin to an option for source: source -i some-file source --import some-file When given this option, source would behave identically to this new builtin: it will search for some-file in the paths designated by BASH_IMPORT_PATH only, preserving PATH. This solution does not introduce a new builtin and preserves backwards compatibility fully since the new behavior is only enabled when the --import option is passed. As the maintainer of GNU bash, do you think this is a good idea? Should I implement this and submit an updated patch set for community review and comments? Thanks for the feedback, Matheus
Re: Re: [PATCH 0/4] Add import builtin
2024年5月3日(金) 14:45 Matheus Afonso Martins Moreira : > This is suboptimal. In case the library script cannot found > in the intended directories, it will needlessly search every > other entry in PATH for it, despite the fact they will contain > only unsuitable executables and programs. There is no doubt that it is more optimal to skip the unnecessary search, but it doesn't need to be implemented as a new builtin. The question is whether such a micro-optimization deserves a new builtin. As far as the scripts are properly set up, the search failure shouldn't happen. This micro-optimization would only have an effect in the situation where the shell program does not work. Usually, we do not care about the performance in a situation where we need to report an error. > It also raises the possibility of false positives: > finding a different executable with the same name > and sourcing it, causing hard to debug problems. Yes, that is a problem in directly using the source builtin, but I think the original intention for the design of `.' and `source' is that the library shouldn't have the same name as exiting commands. Again, this is related to the improper setup of the library. Then, there is always the possibility of a name conflict between different libraries that share their names even if it doesn't conflict with executable files. Yeah, but sourcing an executable file can be more problematic than sourcing a different library. > > [...], but you can/should put the files without adding the > > executable permission to avoid the confusion you mention. > > That's true and a good point. It was my intention to > reduce the number of candidate directory entries as > much as possible. Would you say that it would never > be appropriate for a shell script library to be executable? As far as it is not intended to be an executable file, yes. By "an executable file", I mean a file that will be executed in a separate process. However, I shall note that some shell programs are intended to be used as both a library and a separate program. This is also pointed out by Phi. For example, `modernish' from the modernish framework is basically intended to be a script to source but can also be used as a separate program. When it is used as a separate program, for example, it can be used to retrieve information about the library and setups and can also be used to run tests. The main file of my framework, `ble.sh', also behaves in a similar manner, though I do not give the executable permission to it by default and instead instruct the user to use `bash /path/to/ble.sh [options]'. Nevertheless, I know that some users put a symbolic link to `ble.sh' in ~/bin or somwhere and adds the executable permission to `ble.sh'. > It might be useful to reverse that condition: make it so > only non-executable files can be imported instead. > What do you think? For the above reason, I think you still need to search for both types of files. > What if instead of a new builtin, we added options to source? > This: > > import some-file > > Could become this: > > source -i some-file > source --import some-file I think this is more acceptable compared to the new `import' builtin, but I still think it can be a shell function (or an alias to work around libraries not using `declare -g' as Chet mentioned). > > If this builtin would be included, I think this should be a loadable > > builtin that the user can enable as an option. > > That's a good idea. When I studied the source code, > there were comments saying the builtins could be > turned off and even programatically detected > via the enable builtin. I made use of those > facilities so the import builtin should already > have these properties. Yes, all the builtins can be enabled/disabled by the `enable' builtin. But what I wanted to say is that the `import' builtin should be an opt-in feature, i.e., it should be disabled by default to avoid conflicts with existing `import'. > I'm not sure if it's a dynamically loadable module, but it probably could be. It's not in the current patch but can be modified to be a loadable builtin. > > it should better be a script file in /examples/functions > > In this case, would every script automatically > have access to the import function? No, those files need to be distributed by the Bash package of distributions, and the path needs to be properly set up. > > so simple that I doubt it should be defined as a separate library > > file. It can be copied directly into the script file. > > It could, but that opens the door to variation. >From your perspective, I understand you are trying to invent the standard. However, it seems to me that you are trying to add even another variation (which is less functional than the existing implementations) to the market. https://xkcd.com/927/ You are overwriting `import' of the Bash Infinity framework [1]. As other implementations, Bash Line Editor has `ble-import' [2]. The Basher framework has
Re: [PATCH 0/4] Add import builtin
On 5/2/24 6:22 PM, Matheus Afonso Martins Moreira wrote: This patch set introduces a new "import" builtin which behaves just like the source builtin but only looks up executables in the BASH_IMPORT_PATH variable. How is this any different than PATH=$BASH_IMPORT_PATH:$PATH source or PATH=$BASH_IMPORT_PATH source You could force the latter if you are sure that the sourced files will not attempt to run external commands. You could even make this an alias if you want. I'd hesitate to make it a function, unless you're sure that no file you source uses `declare' to create variables, since those will be local to the function by default. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/ OpenPGP_signature.asc Description: OpenPGP digital signature
Re: Re: [PATCH 0/4] Add import builtin
> You can prepare a separate directory for the script files to source > and put the directory name at the beginning of PATH, e.g., > PATH=~/.config/bash/functions:$PATH. This is suboptimal. In case the library script cannot found in the intended directories, it will needlessly search every other entry in PATH for it, despite the fact they will contain only unsuitable executables and programs. It also raises the possibility of false positives: finding a different executable with the same name and sourcing it, causing hard to debug problems. My main objective is to create an entirely separate search space for the bash libraries so that importing can be counted on to be both efficient and safe. Overloading the existing source builtin would also accomplish that goal if PATH is not searched. > you seem to assume the script files to source have the executable > permissions, but you can/should put the files without adding the > executable permission to avoid the confusion you mention. That's true and a good point. It was my intention to reduce the number of candidate directory entries as much as possible. Would you say that it would never be appropriate for a shell script library to be executable? It might be useful to reverse that condition: make it so only non-executable files can be imported instead. What do you think? > In addition, BASH_LIBRARY_PATH (or BASH_SOURCE_PATH) for the source > builtin seems already in the ``list'' [1]. The new builtin would > become unnecessary If it is implemented. I'm very happy that it was added to the list of planned features. Still, it was my intention to contribute the patches from the start. If nothing comes of this, at least I've gained experience with the bash code base, facillitating future contributions. > We need to be careful in adding a new builtin name since existing > users might already have an executable file "import", which would be > hidden by the suggested new builtin. The name "import" is not listed > in POSIX XCU 2.9.1 (1b), the list of command names that a shell > implementation might process specially. That's a very good point, I was not aware of that! What if instead of a new builtin, we added options to source? This: import some-file Could become this: source -i some-file source --import some-file More verbose, but it would avoid the aforementioned issue. When given the import option, source could behave as import. > If this builtin would be included, I think this should be a loadable > builtin that the user can enable as an option. That's a good idea. When I studied the source code, there were comments saying the builtins could be turned off and even programatically detected via the enable builtin. I made use of those facilities so the import builtin should already have these properties. I'm not sure if it's a dynamically loadable module but it probably could be. > it should better be a script file in /examples/functions In this case, would every script automatically have access to the import function? > I've checked the discussion in help-bash [2]. The above arguments seem > to be already mentioned in the original discussion. You say you've > included everyone's thoughts [3,4], but no one seems to have > recommended adding a new builtin. That's true. I took initiative and implemented an alternative solution when objections to overloading the behavior of the existing source builtin began to surface. I thought they were really good points, so I approached the problem from a different angle. Different concerns regarding this proposal also surfaced, such as the standardization issue. They also have merit and I will try to address them as well. For example, I think the "add --import option to source" is starting to emerge as a promising solution. > so simple that I doubt it should be defined as a separate library > file. It can be copied directly into the script file. It could, but that opens the door to variation. I think a simple, standard and predictable include/import/source mechanism is of paramount importance if a true library ecosystem is to form around it. Variation in such critical infrastructure has led to enormous pain for developers working in other languages which have multiple semi-compatible or incompatible module systems for example. They end up having to support several systems. > Even if it wouldvbe defined in a library script file, > you need to anyway specify a path > in BASH_IMPORT_PATH to use that function. With sensible defaults, this problem is mitigated if not completely eliminated. It's important that it be flexible and user overridable, but most people will be well served by well chosen default paths such as: ~/.local/usr/lib/bash:/usr/lib/bash This allows libraries to be packaged by Linux distributions and installed system wide, and also allows users to install bash code inside their home directories and immediately become productive. Thanks for the feedback,
Re: Re: [PATCH 0/4] Add import builtin
> This is debatable. Augmenting PATH with a directory containing > nonexecutable scripts for sourcing is IMO not that confusing. That was my original intention but there were objections to overloading the source builtin with even more behavior. I thought it was a good point so I decided to prototype this feature as a new builtin, which avoids that issue but also comes with its own tradeoffs. > I really don't think "'source' with a different search path" merits > a separate builtin. There is one advantage: the behavior will be clear to every user. Since it's a new bash-specific builtin, its behavior does not vary depending on the POSIX compatibility modes. It can also evolve different semantics than the source builtin. > Perhaps "source" could diverge from "." on this, > in which case there wouldn't be a POSIX conformance issue. I agree. If this does get implemented on top of source, I think it would be great if the dot operator was unaffected. > If "import" were qualitatively different from "source" (say it > integrated some sort of namespace functionality), then it would be > more compelling. I was hoping this point would be brought up during discussion. It's something I wanted to do but I don't have a fully formed idea yet and I'm also not sure how to implement it either. I was thinking about extending the restricted shell semantics when importing rather than sourcing. For example, make all variables local to the script being evaluated, but bind the functions to the calling script's namespace. Import could have flags to control which names/types get imported and which don't which I think could be very useful. Thanks for the feedback, Matheus
Re: Re: [PATCH 0/4] Add import builtin
> By the name "import", I expect also something like an include guard, > i.e., it loads the same file only once at most. This is an excellet idea. I'll try to implement it. Matheus
Re: [PATCH 0/4] Add import builtin
On Fri, May 3, 2024 at 5:26 AM Koichi Murase wrote: > > > By the name "import", I expect also something like an include guard, > i.e., it loads the same file only once at most. I have a > shell-function implementation,`ble-import', in my framework. It > doesn't support namespace, but it supports the include guard. It also > accepts a setting for the paths to search. It also has a feature like > `with-eval-after-load' of elisp (or the "onload" event). > > -- > Koichi > > I don't think we need yet another builtin named 'import' for all the reason mentioned in the mail thread. Setting BASH_IMPORT_PATH in an .rc file is not less confusing than simply setting PATH in the same .rc file. In the case one mix'n'match dir setup in both PATH and BASH_IMPORT_PATH, and in case of mix'n'match -x more setting of a .sh files, then all sort of documentation must be done to explicitly tells which case takes precedence etc... I prefere by far to handle $PATH myself in my .rc and place myself my 'shell packages' in my hierarchies. Note that a package (an import) generally is non executable, as some mentioned, yet beeing able to 'run' a package can be interesting in some case, for instance a pacakge run can display its embedded documentation, useful during development (yet debatable) My package management have the same feature as @Koichi one, i.e a C like #pragma once. I add a 'force' option to my 'import', this is for interactive 'import', to bring more functions (global, alias), yet during bring-up one may fix a package an force a reload. Some packages, on the other hand, are to be used 'imported' by other packages and as such I have versioning mechanism, so 'import' can tell about new version available from the git repos, or even an auto update from git (when suitable) etc... and indeed it is possible for the import to tell which minimal version is needed for the 'import'. So doing an 'import' feature, may be to be on par with python/perl/nameit, require more than just a new ENV var and the hack to use it. Cheers
Re: [PATCH 0/4] Add import builtin
2024年5月3日(金) 11:17 Lawrence Velázquez : > If "import" were qualitatively different from "source" (say it > integrated some sort of namespace functionality), then it would be > more compelling. That sounds interesting. It's a bit unrelated to the main discussion, but I was wondering if it is possible to allow expansions in the function name in the function definition "function ". Zsh allows it: $ zsh -c 'ns=mynamespace; function $ns/util1 { echo This is util1; }; mynamespace/util1' This is util1 This is just a hypothetical feature, but if we have a PATH-like variable (e.g. BASH_FUNCTION_PATH or BASH_FUNCTION_NAMESPACE) for the function name search, one can set « local BASH_FUNCTION_PATH=mynamespace » to make `mynamespace/util1' visible with the name `util1'. But a problem of such a variable-based approach is that the namespace is resolved by a dynamic condition (i.e. the variable in the context when it is called) instead of the lexical context (i.e. where the caller is defined or to which namespace the caller belongs). Maybe `.' in BASH_FUNCTION_PATH can be treated as any namespace the caller belongs to. By the name "import", I expect also something like an include guard, i.e., it loads the same file only once at most. I have a shell-function implementation,`ble-import', in my framework. It doesn't support namespace, but it supports the include guard. It also accepts a setting for the paths to search. It also has a feature like `with-eval-after-load' of elisp (or the "onload" event). -- Koichi
Re: [PATCH 0/4] Add import builtin
2024年5月3日(金) 9:56 Matheus Afonso Martins Moreira : > The source builtin uses the PATH variable for resolving file names > which means they would have to be placed alongside normal executables > which could cause confusion. You can prepare a separate directory for the script files to source and put the directory name at the beginning of PATH, e.g., PATH=~/.config/bash/functions:$PATH. As Lawrence has pointed out, you seem to assume the script files to source have the executable permissions, but you can/should put the files without adding the executable permission to avoid the confusion you mention. The source builtin finds the file regardless of the executable permission. In this way, it is clear to both the users and Bash that those files are not executable. In addition, BASH_LIBRARY_PATH (or BASH_SOURCE_PATH) for the source builtin seems already in the ``list'' [1]. The new builtin would become unnecessary If it is implemented. [1] https://lists.gnu.org/archive/html/help-bash/2024-04/msg00022.html > This patch set introduces a new "import" builtin which behaves just like > the source builtin but only looks up executables in the BASH_IMPORT_PATH > variable. We need to be careful in adding a new builtin name since existing users might already have an executable file "import", which would be hidden by the suggested new builtin. The name "import" is not listed in POSIX XCU 2.9.1 (1b), the list of command names that a shell implementation might process specially. If this builtin would be included, I think this should be a loadable builtin that the user can enable as an option. The loadable builtins are included in /examples/loadables in the source tree of Bash. The location of the loadable builtin files can be specified by BASH_LOADABLES_PATH and loaded by the `enable' builtin. However, as pointed out by Dale, what is done by this new feature can just be implemented by a shell function. In this case, it is generally recommended to implement it as a shell function. If you want to include it in Bash, it should better be a script file in /examples/functions (instead of a loadable module in /examples/loadables). But considering the simplicity of the shell function implementation by Dale and the fact that the source builtin essentially covers the feature, I'm not sure if it's worth providing. I've checked the discussion in help-bash [2]. The above arguments seem to be already mentioned in the original discussion. You say you've included everyone's thoughts [3,4], but no one seems to have recommended adding a new builtin. [2] https://lists.gnu.org/archive/html/help-bash/2024-04/threads.html#00016 [3] https://lists.gnu.org/archive/html/help-bash/2024-05/msg0.html [4] https://lists.gnu.org/archive/html/help-bash/2024-05/msg1.html Reply to [4] 2024年5月3日(金) 9:56 Matheus Afonso Martins Moreira : > Bash is powerful enough to do it with a function, no doubt about it. > The thing is that approach begs the question of how to source that > function which is also a reusable library function. This chicken and > egg problem is why I believe a library facility is something that's > better off as a native feature of the language. The function « import() { PATH=$BASH_IMPORT_PATH source "$@"; } » is so simple that I doubt it should be defined as a separate library file. It can be copied directly into the script file. Even if it would be defined in a library script file, you need to anyway specify a path in BASH_IMPORT_PATH to use that function. I don't feel much difference between specifying two paths (set BASH_IMPORT_PATH and source /path/to/import.sh) and specifying only the former (set BASH_IMPORT_PATH and source import.sh).
Re: [PATCH 0/4] Add import builtin
On Thu, May 2, 2024, at 9:40 PM, Dale R. Worley wrote: > It seems like you could get much the same effect with this device: > > -- > t1 contains: > > # Where I am doing this testing. > BASH_IMPORT_PATH=$HOME/temp/import/t2 > > echo "Note PATH does not contain '.'" > echo "PATH=$PATH" > echo "BASH_IMPORT_PATH=$BASH_IMPORT_PATH" > > function import () { > local PATH="$BASH_IMPORT_PATH" > source "$1" > } You probably want something like local PATH=$BASH_IMPORT_PATH:$PATH otherwise the sourced file will not be able to find the usual external utilities. Even then, the additional function scope will interfere with top-level "declare" commands. -- vq
Re: [PATCH 0/4] Add import builtin
On Thu, May 2, 2024, at 6:22 PM, Matheus Afonso Martins Moreira wrote: > Bash scripts can be hard to get right so reusing proven solutions > as shell script libraries is of immense value. However, the existing > shell script sourcing mechanisms are suboptimal for this task. > The source builtin uses the PATH variable for resolving file names > which means they would have to be placed alongside normal executables > which could cause confusion. This is debatable. Augmenting PATH with a directory containing nonexecutable scripts for sourcing is IMO not that confusing. > This patch set introduces a new "import" builtin which behaves just like > the source builtin but only looks up executables in the BASH_IMPORT_PATH > variable. I really don't think "'source' with a different search path" merits a separate builtin. This could be accomplished by creating a new path variable and modifying "source" to use it. (Perhaps "source" could diverge from "." on this, in which case there wouldn't be a POSIX conformance issue.) Put another way, "." already has an identical synonym in "source". If it's deemed desirable to fiddle with sourcing behavior, I think it makes more sense to utilize "source" than to introduce a third, almost-but-not-quite-identical synonym. If "import" were qualitatively different from "source" (say it integrated some sort of namespace functionality), then it would be more compelling. -- vq
Re: [PATCH 0/4] Add import builtin
It seems like you could get much the same effect with this device: -- t1 contains: # Where I am doing this testing. BASH_IMPORT_PATH=$HOME/temp/import/t2 echo "Note PATH does not contain '.'" echo "PATH=$PATH" echo "BASH_IMPORT_PATH=$BASH_IMPORT_PATH" function import () { local PATH="$BASH_IMPORT_PATH" source "$1" } import t2 echo "T2_VARIABLE=$T2_VARIABLE" -- t2 contains: echo "Executing t2" T2_VARIABLE=t2_value -- Test execution: $ bash ./t1 Note PATH does not contain '.' PATH=/home/worley/bin/x86_64:/home/worley/bin:/usr/local/bin:/usr/bin:/bin:/usr/ucb:/etc:/usr/etc:/usr/X11R6/bin:/usr/hosts:/usr/games:/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin BASH_IMPORT_PATH=/home/worley/temp/import/t2 Executing t2 T2_VARIABLE=t2_value $ -- Dale