Skip to content
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: work around shopt -s patsub_replacement newly supported in Bash 5.2 #1074

Merged
merged 9 commits into from
Dec 24, 2023

Conversation

akinomyoga
Copy link
Collaborator

The main fixes are the last three commits: caeedee, cfdcc93, and c188381. See the commit messages.

The other commits are relatively trivial fixes overlapping with the above ones: 87c535a, 59ad04d, 85203cb, a15f630, 21d28ad.

@akinomyoga akinomyoga changed the title Work around shopt -s patsub_replacement newly supported in Bash 5.2 fix: work around shopt -s patsub_replacement newly supported in Bash 5.2 Nov 28, 2023
@akinomyoga akinomyoga force-pushed the patsub_replacement branch 2 times, most recently from e7401f2 to bc2bef0 Compare November 29, 2023 02:59
@akinomyoga akinomyoga marked this pull request as ready for review December 3, 2023 10:38
test/runLint Outdated
@@ -61,3 +64,9 @@ gitgrep "$cmdstart"'unset [^-]' 'Explicitly specify "unset -v/-f"'

gitgrep "$cmdstart"'((set|shopt)\s+[+-][a-z]+\s+posix\b|(local\s+)?POSIXLY_CORRECT\b)' \
'fiddling with posix mode breaks keybindings with some bash versions'

gitgrep '\$\{([^{}\n]|\{.*\})+/([^{}\n]|\{.*\})+/([^{}"\n]|\{.*\})*\$.*\}' \
'$rep of ${var/pat/$rep} needs to be double-quoted for shopt -s patsub_replacement (bash >= 5.2)'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit message of 5b959a7 details a case why we should be rather using _comp_compgen than double quoting. Should we update this to suggest that, too?

Looks good to me otherwise, pre-approved and good to merge with this addressed (or not addressed if that's the right thing to do).

Copy link
Collaborator Author

@akinomyoga akinomyoga Dec 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This becomes long, so in commit db5015a, I added a new subsection in doc/styleguide.md under the quoting section and added pointers to the related lint items.

@akinomyoga akinomyoga force-pushed the patsub_replacement branch 3 times, most recently from c35af29 to db5015a Compare December 24, 2023 14:14
The construct "${cur/^!/$spoolfile}" appears to try to replace the
beginning `!` with "$spoolfile" because cur starts with `!` in this
context.  However, this does not work because ^ does not mean the
beginning of the string.  We may instead use "${cur/#!/$spoolfile}".
In addition, `eval` can be applied to only the content of `spoolfile`,
which was originally extracted from the mutt output of the form
`spoolfile="..."`.  After expanding the escape sequences in
$spoolfile, we combine it with `cur`.
The raw assignment can be affected by word splitting and pathname
expansions.
The construct cur="${cur/#!/$spoolfile}" tries to replace the first
character of `cur` with the content of $spoolfile.  However, this has
a problem that the characters `&` in $spoolfile can be unexpectedly
replaced with the matched string when `shopt -s patsub_replacement`
(bash >= 5.2) is enabled.

In principle, we can rewrite it to `cur=${cur/#!/"$spoolfile"}`, but
we can use a simpler solution this time.  In this context, `cur` is
ensured to start with `!`, so we can directly replace
${cur/#!/$spoolfile} with $spoolfile${cur:1}.
To add a prefix to every element in an array, we have used the
following construct:

  arr=("${arr[@]/#/$prefix}")

However, this can be broken when `shopt -s patsub_replacement` (bash
>= 5.2) is turned on.  In bash >= 5.2, patsub_replacement is enabled
by default.  In particular, the characters `&` contained in $prefix,
if any, will be replaced with the matched string.  To avoid the
unexpected patsub_replacement, one may think about quoting the
replacement as

  arr=("${arr[@]/#/"$prefix"}")

However, this has another problem in bash < 4.3 or when `shopt -s
compat42` is turned on.  In such a case, the inner double quotations
are treated literally so that the `PREFIX` instead of ``"PREFIX"` is
prefixed to elements.  To avoid this situation the outer double
quotations might be removed, but this has even another problem of the
pathname expansions and IFS.  We here instead use _comp_compgen:

  _comp_compgen -Rv arr -- -P "$prefix" -W '"${arr[@]}"'

This patch also contains similar cases for a suffix.
In bash >= 4.3 with `shopt -s compat42` enabled, ${var/pat/$'...'}
would produce extra single quotations around the replacements.  The mr
completion uses $'\n' to insert delimiter, but the delimiter does not
need to be the newline in this context.  In this patch, we can instead
insert a space.
@akinomyoga akinomyoga force-pushed the patsub_replacement branch 2 times, most recently from 32f0088 to 2a11209 Compare December 24, 2023 15:07
@akinomyoga
Copy link
Collaborator Author

32f0088d..2a11209b: I added a change for ret => REPLY (#987).

@akinomyoga akinomyoga merged commit 652e98f into scop:master Dec 24, 2023
7 checks passed
@akinomyoga akinomyoga deleted the patsub_replacement branch December 24, 2023 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants