mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-21 11:31:15 -03:00
Add string-replace-fewer-backslashes feature
This disables an extra round of escaping in the `string replace -r`
replacement string.
Currently, to add a backslash to an a or b (to "escape" it):
string replace -ra '([ab])' '\\\\\\\$1' a
7 backslashes!
This removes one of the layers, so now 3 or 4 works (each one escaped
for the single-quotes, so pcre receives two, which it reads as one literal):
string replace -ra '([ab])' '\\\\$1' a
This is backwards-incompatible as replacement strings will change
meaning, so we put it behind a feature flag.
The name is kinda crappy, though.
Fixes #5474.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "builtin.h"
|
||||
#include "common.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "future_feature_flags.h"
|
||||
#include "io.h"
|
||||
#include "parse_util.h"
|
||||
#include "pcre2.h"
|
||||
@@ -933,8 +934,13 @@ class regex_replacer_t : public string_replacer_t {
|
||||
regex_replacer_t(const wchar_t *argv0, const wcstring &pattern, const wcstring &replacement_,
|
||||
const options_t &opts, io_streams_t &streams)
|
||||
: string_replacer_t(argv0, opts, streams),
|
||||
regex(argv0, pattern, opts.ignore_case, streams),
|
||||
replacement(interpret_escapes(replacement_)) {}
|
||||
regex(argv0, pattern, opts.ignore_case, streams) {
|
||||
if (feature_test(features_t::string_replace_backslash)) {
|
||||
replacement = replacement_;
|
||||
} else {
|
||||
replacement = interpret_escapes(replacement_);
|
||||
}
|
||||
}
|
||||
|
||||
bool replace_matches(const wcstring &arg) override;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ features_t &mutable_fish_features() { return global_features; }
|
||||
const features_t::metadata_t features_t::metadata[features_t::flag_count] = {
|
||||
{stderr_nocaret, L"stderr-nocaret", L"3.0", L"^ no longer redirects stderr"},
|
||||
{qmark_noglob, L"qmark-noglob", L"3.0", L"? no longer globs"},
|
||||
{string_replace_backslash, L"string-replace-fewer-backslashes", L"3.1", L"string replace -r needs fewer backslashes in the replacement"},
|
||||
};
|
||||
|
||||
const struct features_t::metadata_t *features_t::metadata_for(const wchar_t *name) {
|
||||
|
||||
@@ -17,6 +17,9 @@ class features_t {
|
||||
/// Whether ? is supported as a glob.
|
||||
qmark_noglob,
|
||||
|
||||
/// Whether string replace -r double-unescapes the replacement.
|
||||
string_replace_backslash,
|
||||
|
||||
/// The number of flags.
|
||||
flag_count
|
||||
};
|
||||
|
||||
1
tests/invocation/features-string-backslashes-off.invoke
Normal file
1
tests/invocation/features-string-backslashes-off.invoke
Normal file
@@ -0,0 +1 @@
|
||||
--features 'no-string-replace-fewer-backslashes' -C 'string replace -ra "\\\\" "\\\\\\\\" -- "a\b\c"'
|
||||
1
tests/invocation/features-string-backslashes-off.out
Normal file
1
tests/invocation/features-string-backslashes-off.out
Normal file
@@ -0,0 +1 @@
|
||||
a\b\c
|
||||
1
tests/invocation/features-string-backslashes.invoke
Normal file
1
tests/invocation/features-string-backslashes.invoke
Normal file
@@ -0,0 +1 @@
|
||||
--features 'string-replace-fewer-backslashes' -C 'string replace -ra "\\\\" "\\\\\\\\" -- "a\b\c"'
|
||||
1
tests/invocation/features-string-backslashes.out
Normal file
1
tests/invocation/features-string-backslashes.out
Normal file
@@ -0,0 +1 @@
|
||||
a\\b\\c
|
||||
@@ -6,5 +6,6 @@ test_function
|
||||
# Future Feature Flags
|
||||
stderr-nocaret off 3.0 ^ no longer redirects stderr
|
||||
qmark-noglob off 3.0 ? no longer globs
|
||||
string-replace-fewer-backslashes off 3.1 string replace -r needs fewer backslashes in the replacement
|
||||
1
|
||||
2
|
||||
|
||||
Reference in New Issue
Block a user