-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
fix(bash): Fix bash completion for suggestions that contain special characters. #2126
Conversation
It would be nice to have this PR merged - many rclone users have noticed that we can't complete file names with spaces in :-( |
Sorry for the delay. I will be reviewing this next. |
That would be great! |
I think there may be some confusion here. |
…haracters. Special characters include whitepace, so this is more general than spf13#1743. This should also fix spf13#1740. I added some test cases to cobra-completion-testing. This PR makes them pass. It also doesn't trip any of the performance regression tests. I'm happy to submit those tests as a PR as well. - https://github.com/JeffFaer/cobra-completion-testing/tree/special_characters - JeffFaer/cobra-completion-testing@52254c1 Signed-off-by: Jeffrey Faer <[email protected]>
…uoting. Signed-off-by: Jeffrey Faer <[email protected]>
They're not going through compgen so they don't need it. Signed-off-by: Jeffrey Faer <[email protected]>
Signed-off-by: Jeffrey Faer <[email protected]>
ec43e79
to
9771cb0
Compare
I've updated these changes to reflect the behavior you're looking for. It automatically escapes the last completion suggestion. |
Hmm there's actually a bad interaction here with The bash completion script is handling a couple wordbreaks ( |
Signed-off-by: Jeffrey Faer <[email protected]>
I took a pass at a way to address the |
@@ -173,8 +169,9 @@ __%[1]s_process_completion_results() { | |||
__%[1]s_handle_completion_types | |||
fi | |||
|
|||
__%[1]s_handle_special_char "$cur" : | |||
__%[1]s_handle_special_char "$cur" = | |||
__%[1]s_handle_wordbreaks "$cur" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At surface value, this line looked wrong to me because I didn't think it was correct to handle wordbreaks like this when the user requested menu-completion. But after some manual testing I'm pleasantly surprised to find that this is correct, and menu-completion does still expect the same behavior as "regular" completion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't understand why this change was needed so for safety, I did not take it.
Signed-off-by: Jeffrey Faer <[email protected]>
The other ones should already have been quoted by the completion script. Signed-off-by: Jeffrey Faer <[email protected]>
398ef9f
to
7a9725b
Compare
@JeffFaer Thanks for the update! It looks really good. However, while testing with the updated program of marckhouzam/cobra-completion-testing#25 I'm noticing a subtle behaviour, that I feel is incorrect.
In the above case, when the user presses If the user where to escape the
Comparing it to
The same approach should apply to the other special characters: |
…ld print them to the command line (COMP_TYPE=9)
It sounds like you're looking to have special characters escaped as soon as they end up on the command line instead of after the full word has been completed. I've updated the PR to do that. PTAL. Escaping special characters as soon as they end up on the command line lets us simplify some of the wordbreak complexity, too |
|
||
63) | ||
# Type: Listing completions after successive tabs | ||
__%[1]s_handle_standard_completion_case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not escaping here so that the list of results on multiple tabs doesn't include any extra escape characters...is that the behavior you're expecting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you give an example of the behaviour you are referring too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testprog prefix special-chars bash<tab><tab>
The list of options it reports is not escaped (i.e. bash4>redirect
), but if you were to do bash4<tab>
you'd get the escaped version (bash4\>redirect
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should escape it in the list. I will do that in #1743
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I notice that zsh and fish don't show the escaping in their list. I'll think about it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you that we should not escape the completions when printing them as a menu
@JeffFaer I worked many hours trying to make sure this was safe to merge, and in the end I felt there were too many changes I didn't understand well enough so I tried to simplify the change as much as I could. By the time I was done and had something working, it looked a lot like #1743. So, I feel the fair thing to do is to go back to #1743 and make it work. I was able to do sort all this out thanks to the great tests you wrote in marckhouzam/cobra-completion-testing#25, so I want to merge that one also. I'm going to pause working on this one and see if we can get #1743 working. |
@@ -224,20 +225,28 @@ __%[1]s_handle_completion_types() { | |||
# completions at once on the command-line we must remove the descriptions. | |||
# https://github.com/spf13/cobra/issues/1508 | |||
local tab=$'\t' comp | |||
while IFS='' read -r comp; do | |||
for comp in "${completions[@]}"; do | |||
[[ -z $comp ]] && continue | |||
# Strip any description | |||
comp=${comp%%%%$tab*} | |||
# Only consider the completions that match | |||
if [[ $comp == "$cur"* ]]; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to do the escaping before we filter on "$cur"
so that when the user typed bash1\ s
it still matches the (escaped) completion
@@ -271,21 +286,49 @@ __%[1]s_handle_standard_completion_case() { | |||
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the loop above, we need to do the escaping before we filter on "$cur"
so that when the user typed bash1\ s
it still matches the (escaped) completion
|
||
63) | ||
# Type: Listing completions after successive tabs | ||
__%[1]s_handle_standard_completion_case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you that we should not escape the completions when printing them as a menu
local compgen_words="$(__%[1]s_escape_suggestions "${completions[@]}")" | ||
if [[ "${BASH_VERSION}" = 3* ]]; then | ||
# bash3 compgen doesn't handle escaped # symbols correctly. | ||
compgen_words="${compgen_words//\\#/#}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the end I decided not to escape the #
since the shell passes to the go program without problems.
Also avoid using 'printf -v' by using "read" patterns, inspired by PR spf13#2126 from of "Jeffrey Faer". Signed-off-by: Marc Khouzam <[email protected]> Co-authored-by: Jeffrey Faer <[email protected]>
@@ -224,20 +225,28 @@ __%[1]s_handle_completion_types() { | |||
# completions at once on the command-line we must remove the descriptions. | |||
# https://github.com/spf13/cobra/issues/1508 | |||
local tab=$'\t' comp | |||
while IFS='' read -r comp; do | |||
for comp in "${completions[@]}"; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why this was needed so I didn't take it.
__%[1]s_escape_compreply | ||
;; | ||
|
||
63) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was elegant. However, because it was still required to escape characters for COMP_TYPE==9 so that we could filter completion on what the user typed, I went with a different approach.
To avoid showing escaped characters in the menu list, I didn't escape the completions when there were more than one. We want to insert in the command-line the escape characters, and since we only insert in the command-line when there is a single completion (except for COMP_TYPE 37 or 42), that seemed like a good way to know when to escape or not.
;; | ||
|
||
*) | ||
# Type: complete (normal completion) | ||
__%[1]s_handle_standard_completion_case | ||
__%[1]s_escape_compreply |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked the elegance of trying to escape the characters at the end. But it turned out we also needed to escape them from within __%[1]s_handle_standard_completion_case
, so I decided to do everything from within that function.
# bash3 compgen doesn't handle escaped # symbols correctly. | ||
compgen_words="${compgen_words//\\#/#}" | ||
fi | ||
IFS=$'\n' read -ra COMPREPLY -d '' < <(IFS=$'\n'; compgen -W "${compgen_words}" -- "${cur}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended-up using the logic you wrote here (except for the BASH 3 stuff).
I gave you credit in the commit and put you as a co-author.
@JeffFaer Thanks again for your hard work. This was very tricky. The version I plan to commit is now posted in #1743 but I made you a co-author because I was able to get things working thanks to different part of your work as well. If you can give a spin to #1743 and see if you are happy with it, it would help me make sure I didn't forget something you might have noticed during your hard work. Thanks! I will close this PR in favor of #1743 |
Special characters include whitepace, so this is more general than
#1743. This should also fix #1740.
I added some test cases to cobra-completion-testing. This PR makes them
pass. It also doesn't trip any of the performance regression tests. I'm
happy to submit those tests as a PR as well.