-
Notifications
You must be signed in to change notification settings - Fork 381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement BASH_COMPLETION_FINALIZE_HOOKS
#739
base: main
Are you sure you want to change the base?
Conversation
@calestyo Could you review it? |
Will take a while... |
Okay I did a "review" now,.. though admittedly it was more testing rather than reviewing (I'm really not that much of an expert with bash specific shell language features).. Some things I've noticed about the general hook functionality:
Some things about
But as for my simple tests... all seemed to work (other than Thanks, |
(didn't check with your two most recent commits, but AFAICS, these anyway just rename stuff) |
With side effects above, I especially meant:
|
Thanks for your review. @scop Sorry for making long discussion. You can just skip the section of "Bash language discussion". Bash language discussionFirst, for the comments on
When we pass uncontrolled strings (that would be picked up from something the user did not prepare) that are not intended to be executed to
Should I explain it one by one? bash-completion/bash_completion Line 307 in 27308a1
bash-completion/bash_completion Line 343 in 27308a1
bash-completion/bash_completion Line 345 in 27308a1
bash-completion/bash_completion Line 361 in 27308a1
In these lines, bash-completion/bash_completion Line 960 in 27308a1
bash-completion/bash_completion Line 966 in 27308a1
bash-completion/bash_completion Line 973 in 27308a1
In particular, we do not pass any strings generated by completions to
This is also the same as the previous comment:
No, you should carefully look at the quoting. Also, it should be noted that the quoting is unneeded in the right-hand side of the variable assignments, after the case keyword, and in the conditional commands (unless it contains |
Bash language discussionThese are also the points or just questions that I feel are caused by the lack of your Bash knowledge or the lack of programming experience:
If you don't want to run them for every completion, you can just keep the array
Oh, really? I'm sourcing the updated
If we didn't remove the trap handler, yes, the bash-completion/bash_completion Line 973 in 27308a1
As for the callees,
I don't see the point. Doesn't it apply to all the functions
If you are talking about the dynamic unset (i.e., the unset on the previous-scope variable placeholder), that doesn't apply to the unset of the array element; More precisely the array-element unset doesn't remove the variable placeholder nor set the variable unset state unless the subscript is
I don't see the point again the same as the second previous comment. Doesn't that also apply to any global variables
This is also similar to the other cases. If we start to care about it, we cannot use any kind of hook functions. We might run it inside a subshell, but that means we don't allow the hook functions modifying the state of the parent shell. Or do you suggesting developing a general-purpose IPC scheme for the shell? That's overcomplicated for bash-completion and even for the shell scripting itself. If you are suggesting a completely separated sandbox environment for the command execution inside the same process, you should ask Chet, which I'm pretty sure that it will be rejected. Edit: There was an oversight.
Yes. |
And these points are something that I think we can discuss:
Maybe. Preparing the default (empty) setup is my preference. Is there anything more than preferences?
Yes, this one is also what I thought in implementing this function. I think we may e.g. extend the usage of
Yes, that is just for completeness and consistency with
Thanks for pointing it out. That is just a mistake. I actually have already fixed it in 8809534c (Yeah, I have mixed the changes in one commit, but I will squash all of these changes at some point, so I have just become lazy here). |
For the eval-related matter, to avoid confusion like this, we can use name references if we could update the requirements on the Bash version to 4.3+, yet that doesn't yet eliminate all the occurrence of
Edit: d06a9b4 I have added
Edit: f1f454b I have decided to just give the associative/index array attributes to the configuration variables |
I hadn't said that there were injection holes,… I’ve asked whether there could be! ;-)
Well I didn't mean to spread FUD, just wanted to point out, whether this has been checked thoroughly.
Sure, and these were the things I had in mind. I mean especially the words that are completed may not be under the control of the user (e.g. git branch/tag names and similar).
Of course
Unless of course, it would contain a string from the first kind (uncontrolled strings).
Quite smart... I wouldn't even had thought about that. The read-only status is never "inherited" like when calling
What could happen there?
Sure, unless of course, $1 would be an uncontrolled string. I did the validation again... first for
Isn't that arithmetic expansion subject to field splitting? So in principle, if one uses like many
I'm too blind to find what happens with
Doesn't that already protect from any shenanigans with read-only vars?
I see why it's safe with respect to the use of I'd guess here
But why are you doing it that way? To support associative arrays?
AFAIU, bash’s Same for:
and similar uses of Which is, I guess, why it's save to use e.g.
Couldn't you use
I had written before, that I wonder whether the
First, is there an
Yeah,... I... kinda missed that ^^
Well |
Oh and some more about
|
Now for the other functions:
These were clear before... You rightly assume that I got mostly scared by:
(and also by the but as you say:
That doesn't really contain the contents.
Same as above and for all cases of
The main point I had been missing here was that
Shouldn't
Well the former might be the case... not sure about the latter, but it was around 02:00 in the night when I reviewed it first and I guess I was a bit too tired after the Fantastic Beasts movie in the cinema (not that the movie would have been tiring ^^).
Well it's clear that one can leave it empty. What I meant is, how do you intend to get a user hook that is called whenever I'd assume your intention is to use
What I meant was the following, but I guess I simply misunderstood what you meant with command (i.e. any real shell command and not just a simple command)):
So I just meant to handle it gracefully (i.e. silently), when the function/program didn't exist... but since it's any shell command... I guess there's nothing we can do about it.
So I guess that also means that And I blindly assume that it's then also guaranteed that
I somehow thought I'd had seen (when trying around) that any functions (not just completion functions were trapped on return and had
Answers my question from before... so I guess that should also be completely fine.
I would have rather thought about some general words in the documentation that describes that whole feature, telling that care must be used on the shell commands used as hooks, that internal variables should all be |
No that was just about personal taste... seems you've already changed that.
But then please give some example like tutorials. E.g. I didn't even know about
Well I personally, but again just a matter of taste, wouldn't do any auto-anchoring. That's how BREs/EREs/PCREs work by themsevels. OTOH, patterns, by themselves, are anchored so I would keep it like that.
I think I'm fine now with all the
Not sure whether that's really better... because now, these don't show up when e.g. completing |
OK, then that's fine! I think I need to enclose these Bash lectures inside @calestyo Here's my template for the Bash language discussion. <details><summary>Bash language discussion</summary>
Note: We need an empty line after the `<details>` line to use GFM inside `<details></details>`
</details> Some Bash language discussion
Right, it's never inherited. The readonly attribute is just the concept of shell but not the one defined by the operating system.
See this: $ function f { local i=$1; while ((--i)); do echo $i; done; }
$ f 10
9
8
7
6
5
4
3
2
1
$ declare -gr i='a[$(echo This is Attacker >&2)]'
$ f 10
bash: local: i: readonly variable
This is Attacker
bash: i: readonly variable
Word splitting doesn't occur inside the arithmetic command
The indexed array in Bash is sparse, i.e., the indices are not necessarily $ arr[10]=1
$ declare -p arr
declare -a arr=([10]="1")
$ echo ${#arr[@]}
1
Right, and that's the motivation for introducing the conditional command
Right, and again that's the raison d'être for
Currently, it does allow any commands including the ones that are not simple commands.
Bash first finds
If the string to search is stored in the variable, quoting the value isn't that easy. In a naive implementation, one needs to check the characters one by one in a loop. Or perform escaping in the loop of special characters that need to be quoted. Or use
No. This is the third time you ask about the word splitting inside the arithmetic command
Ah, OK. Good point. I haven't thought about
What do you mean? The above line in the code is unrelated to the protection from external readonly variables.
That's also possible, but I would like to keep it possible to specify
I haven't assumed that someone would specify the command that needs external commands because spawning a process for each element has too much cost. The shell command that I had in my mind is a builtin command/construct or a shell function where the local variables are available through the dynamic scoping. If one wants to spawn an external command, one can include
Well, that's intentional; I didn't intend to make it a complete sentence when I have written that (although making it a complete sentence is also another valid choice of course). That's just the same as $ aaaaaa
bash: aaaaaa: command not found
Actually, I intend that the predicate always returns 0 or 1 unless there is a bug in the code. The error message is just to detect the wrong usage (note that exit status 2 typically means the wrong usage, i.e., a bug at the caller side). I wouldn't like to ensure any well-defined status after something went south by bugs, but if I were to support any, I would recover the original contents of the array rather than keeping the already half-modified contents. Touching (i.e., compactifying) the modified array after detecting exceptions seems to make the debugging harder, so I currently don't feel it's a good idea. Would you like to have a mechanism to cancel the modification in the middle of the loop? Maybe I can support it with another special exit status e.g. 3, 27, etc. In that case, I think we shouldn't output any error messages. (edit: I have supported the exit status 27 7d7b961)
I don't feel that's very useful. The resulting array just contains multiple same strings. For example, that's not the default of
Hmm, I'm again against the idea. The glob patterns in the shell is always the exact matching, e.g., in pathname expansions and in the right-hand side of
Maybe I miss your point, but with the current implementation, these are mutually exclusive, and the last-specified one does win. (edit: I have updated the description 1eb7a6e)
Thanks for the suggestion, I'd modify it in that way. (edit: updated 1eb7a6e)
I just feel it's verbose. I generally prefer concise, necessary and sufficient description.
Ah, right. This is an oversight in the change c8ec2ca. (edit: ba1f944)
That's not the scope of this PR as I have replied in the original issue. To put it explicitly, this PR doesn't provide the feature of modifying the behavior of
No,
I wouldn't like the slient failure unless it's not controllable. For the present case, the user can just register the hook when the command exists.
It's guaranteed unless some functions set their own
I don't know, but that seems like general points that we need to care about when writing shell functions that would work with other frameworks but not the special points we need to be aware of in writing these hooks.
This is just an idea that I had. I just wrote it in case you are interested enough so that you could take a glance at the implementation of edit: I have changed the function name so that it can be used through _comp_xfunc ARRAY filter -mF arr hello
What would you suggest then? The reason that I kept the attribute is that, otherwise, the users need to set it by themselves every time they set the hook to the associative array |
d65cb92
to
7b48387
Compare
Bash language discussion> What do you mean? The above line in the code is unrelated to the protection from external readonly variables.I got the wrong line of code, I had meant this: bash-completion/bash_completion Line 304 in 157fbf9
But anyway... that of course doesn't protect (from read-only issues) either.
Sure, but I mean a shell could choose to inherit it e.g. via using non-valid POISX variable names in the environment with which another shell is invoked. IIRC that's what bash does when exporting functions. Anyway.. I guess the point about read-only is settled.
Fair enough.
You do really make this quite perfectionist. 😊👍
Okay, but then I'd suggest to drop the
Well I have no particular expectations… just noted it and wanted to see what you think of it.
What I'd perhaps do is to define exit statuses like the following:
That would give you the freedom to add any further future functionality, should it ever be needed, without causing possible breakage.
With "mutually exclusive" I meant in the sense, that you don't get an error if more than one is specified.
Do you see any other "simple" way of getting what I desire (within the currently proposed framework), other than by setting a hook for any command that might do hostname completion? Also, if the hook kicks in just based on the command, e.g. one that does exclusion of completions, might also just exclude such that match the string, but are perhaps from a completely different completed part of the command. For example if I'd set for Probably not such a big problem for me, as hostnames give rather typical patterns... but still. I mean that was why I always thought it was nice to also do this on a per function base.
I actually think it's really nice. What I meant was rather that any other normal (possibly interested) user (who didn't follow this ticket) of this will likely not search for the goodies in the code - that's why some small documentation or tutorial could be nice "How to hook into completions?" which then give the example of:
Well I guess this is also just a matter of personal taste, so I leave that up to you as the developer of this. |
Thanks, I have updated the descriptions and the error message. e5ccbd7
I don't think there is a way you think simple. I think the simplest way in this situation is actually to replace If you want to track the upstream definition, you may use the approach mentioned in #720 (comment). Or, if you are using ble/function#advice after _known_hosts_real "_comp_xfunc ARRAY filter -E COMPREPLY '^example'" Actually,
Right, so the PR doesn't exactly satisfy your needs in this sense.
Yes, I think we can add documentation for this stuff if this would finally go into |
bash-completion/completions/ARRAY Line 17 in e5ccbd7
That reads a bit unusual... exit statuses should be all other ones, so either Bash language discussionI cannot test that right now since I'm away a few days over Easter... but...
Maybe I just miss something, but you set up the return trap in These however also call If so, wouldn't it be possible to use the user hook from
I still think it should get merged, because it does satisfy some of my use cases. |
That would of course work, too. |
Thanks, I'll later modify it. (edit: fixed d8bccad) Bash language discussion
No, it's not called as I explained in the following reply.
It's technically possible by giving all the functions the trace attribute or by running Bash in the debug mode ( |
0b334d7
to
59e69cb
Compare
Hmm I see. And AFAIU, you didn't like the idea of e.g. manually calling a hook from functions of interest?! |
59e69cb
to
c36cea8
Compare
c36cea8
to
ec17753
Compare
Let me comment on the current situation of this technical experiment on the The approach by the |
93c2a86
to
912688e
Compare
I'm not sure if it is robust, but I posted a possible solution in #786 (comment). |
Any expectation whether and when any of this might get merged? |
We need to discuss and make a consensus. As for the "finalize" hook, I think we are positive in merging as far as the abovementioned problem is fixed in a robust way with sufficient testing. The bugfix I submitted to Bash would be in Bash 5.3, but it will take at least ten years for Bash <= 5.2 to go away from the market, so we need an additional mechanism to work around the problem. Currently, I feel the third solution in #786 (comment) would be the cleanest, but I haven't carefully tested it. As for |
But I guess that would make it in practise mostly useless or better said: much harder to use.
|
I didn't mean to create a Bash library that contains only one function In that sense, even if we would include it in Some people might be careful finding the utility possibly in the documentation and use it if
This hears like the reason that we would include the array in |
912688e
to
90395db
Compare
90395db
to
3e9fae5
Compare
3e9fae5
to
21c1a88
Compare
- deal with nested completion initializations - rename the function `_comp_{return_hook => finalize}` - add an associative array `BASH_COMPLETION_FINALIZE_CMD_HOOKS` originally suggested as `_comp_return_hooks` in Ref. [1] - add a new array `BASH_COMPLETION_FINALIZE_HOOKS` [1] scop#720 (comment)
21c1a88
to
8d41bf5
Compare
This is an experimental implementation of hooks mentioned in #720 (comment).
This is still a stub; the design should be considered well, tests and documentation need to be added, etc. Nevertheless, I'd like to hear your thoughts in the current status.
RETURN
handling that I now recognize. I initially thought the proper handling might be more complicated, but it finally ended with this form._comp_array_filter
. I'm not sure whether Ville would finally find it reasonable to include the function in bash-completion, but I tried to make the interface minimal (one function_comp_array_filter
) yet make the function versatile as @calestyo would be likely to request. In any way, this function can be used for the array manipulations of general cases.