diff --git a/doc_src/language.rst b/doc_src/language.rst index 824cad052..159fa30f9 100644 --- a/doc_src/language.rst +++ b/doc_src/language.rst @@ -1586,7 +1586,7 @@ You can see the current list of features via ``status features``:: Here is what they mean: -- ``stderr-nocaret`` was introduced in fish 3.0 (and made the default in 3.3). It makes ``^`` an ordinary character instead of denoting an stderr redirection, to make dealing with quoting and such easier. Use ``2>`` instead. +- ``stderr-nocaret`` was introduced in fish 3.0 (and made the default in 3.3). It makes ``^`` an ordinary character instead of denoting an stderr redirection, to make dealing with quoting and such easier. Use ``2>`` instead. This can no longer be turned off since fish 3.5. The flag can still be tested for compatibility, but a ``no-stderr-nocaret`` value will simply be ignored. - ``qmark-noglob`` was also introduced in fish 3.0. It makes ``?`` an ordinary character instead of a single-character glob. Use a ``*`` instead (which will match multiple characters) or find other ways to match files like ``find``. - ``regex-easyesc`` was introduced in 3.1. It makes it so the replacement expression in ``string replace -r`` does one fewer round of escaping. Before, to escape a backslash you would have to use ``string replace -ra '([ab])' '\\\\\\\\$1'``. After, just ``'\\\\$1'`` is enough. Check your ``string replace`` cals if you use this anywhere. - ``ampersand-nobg-in-token`` was introduced in fish 3.4. It makes it so a ``&`` i no longer interpreted as the backgrounding operator in the middle of a token, so dealing with URLs becomes easier. Either put spaces or a semicolon after the ``&``. This is recommended formatting anyway, and ``fish_indent`` will have done it for you already. diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 0f6253624..688205132 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1937,16 +1937,10 @@ static void test_feature_flags() { say(L"Testing future feature flags"); using ft = features_t; ft f; - do_test(f.test(ft::stderr_nocaret)); - f.set(ft::stderr_nocaret, true); - do_test(f.test(ft::stderr_nocaret)); - f.set(ft::stderr_nocaret, false); - do_test(!f.test(ft::stderr_nocaret)); - f.set_from_string(L"stderr-nocaret,nonsense"); do_test(f.test(ft::stderr_nocaret)); f.set_from_string(L"stderr-nocaret,no-stderr-nocaret,nonsense"); - do_test(!f.test(ft::stderr_nocaret)); + do_test(f.test(ft::stderr_nocaret)); // Ensure every metadata is represented once. size_t counts[ft::flag_count] = {}; diff --git a/src/future_feature_flags.cpp b/src/future_feature_flags.cpp index df287b9af..d33fa8b63 100644 --- a/src/future_feature_flags.cpp +++ b/src/future_feature_flags.cpp @@ -16,12 +16,12 @@ features_t::features_t() { features_t features_t::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", true}, - {qmark_noglob, L"qmark-noglob", L"3.0", L"? no longer globs", false}, + {stderr_nocaret, L"stderr-nocaret", L"3.0", L"^ no longer redirects stderr", true, true /* read-only */}, + {qmark_noglob, L"qmark-noglob", L"3.0", L"? no longer globs", false, false}, {string_replace_backslash, L"regex-easyesc", L"3.1", L"string replace -r needs fewer \\'s", - true}, + true, false}, {ampersand_nobg_in_token, L"ampersand-nobg-in-token", L"3.4", - L"& only backgrounds if followed by a separator", false}, + L"& only backgrounds if followed by a separator", false, false}, }; const struct features_t::metadata_t *features_t::metadata_for(const wchar_t *name) { @@ -55,11 +55,17 @@ void features_t::set_from_string(const wcstring &str) { // future versions). // The special name 'all' may be used for those who like to live on the edge. if (const metadata_t *md = metadata_for(name)) { - this->set(md->flag, value); + // Only change it if it's not read-only. + // Don't complain if it is, this is typically set from a variable. + if (!md->read_only) { + this->set(md->flag, value); + } } else { for (const metadata_t &md : metadata) { if (std::wcsstr(md.groups, name) || !std::wcscmp(name, L"all")) { - this->set(md.flag, value); + if (!md.read_only) { + this->set(md.flag, value); + } } } } diff --git a/src/future_feature_flags.h b/src/future_feature_flags.h index 9ddb5efc4..12fd897cb 100644 --- a/src/future_feature_flags.h +++ b/src/future_feature_flags.h @@ -63,6 +63,9 @@ class features_t { /// Default flag value. const bool default_value; + + /// Whether the value can still be changed or not. + const bool read_only; }; /// The metadata, indexed by flag. diff --git a/tests/checks/features-nocaret1.fish b/tests/checks/features-nocaret1.fish index a7230e594..c0b18c671 100644 --- a/tests/checks/features-nocaret1.fish +++ b/tests/checks/features-nocaret1.fish @@ -1,2 +1,2 @@ #RUN: %fish --features 'no-stderr-nocaret' -c 'status test-feature stderr-nocaret; echo nocaret: $status' -# CHECK: nocaret: 1 +# CHECK: nocaret: 0 diff --git a/tests/checks/features-nocaret3.fish b/tests/checks/features-nocaret3.fish index 4f353d2b6..ed4575452 100644 --- a/tests/checks/features-nocaret3.fish +++ b/tests/checks/features-nocaret3.fish @@ -1,2 +1,2 @@ #RUN: %fish --features 'no-stderr-nocaret' -c 'echo -n careton:; echo ^/dev/null' -# CHECK: careton: +# CHECK: careton:^/dev/null diff --git a/tests/checks/features-nocaret5.fish b/tests/checks/features-nocaret5.fish deleted file mode 100644 index 67db8e58a..000000000 --- a/tests/checks/features-nocaret5.fish +++ /dev/null @@ -1,2 +0,0 @@ -#RUN: %fish --features no-stderr-nocaret -c 'cat /abavojijsdfhdsjhfuihifoisj ^&1' -# CHECK: {{cat|/abavojijsdfhdsjhfuihifoisj}}: {{.*}}