mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-24 23:24:10 +08:00

Let's hope this doesn't causes build failures for e.g. musl: I just know it's good on macOS and our Linux CI. It's been a long time. One fix this brings, is I discovered we #include assert.h or cassert in a lot of places. If those ever happen to be in a file that doesn't include common.h, or we are before common.h gets included, we're unawaringly working with the system 'assert' macro again, which may get disabled for debug builds or at least has different behavior on crash. We undef 'assert' and redefine it in common.h. Those were all eliminated, except in one catch-22 spot for maybe.h: it can't include common.h. A fix might be to make a fish_assert.h that *usually* common.h exports.
77 lines
2.8 KiB
C++
77 lines
2.8 KiB
C++
#include "config.h" // IWYU pragma: keep
|
|
|
|
#include "future_feature_flags.h"
|
|
|
|
#include <cwchar>
|
|
#include <string>
|
|
|
|
#include "wcstringutil.h"
|
|
|
|
features_t::features_t() {
|
|
for (const metadata_t &md : metadata) {
|
|
this->set(md.flag, md.default_value);
|
|
}
|
|
}
|
|
|
|
/// The set of features applying to this instance.
|
|
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 (historical, can no longer be changed)", 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, false},
|
|
{ampersand_nobg_in_token, L"ampersand-nobg-in-token", L"3.4",
|
|
L"& only backgrounds if followed by a separator", true, false},
|
|
};
|
|
|
|
const struct features_t::metadata_t *features_t::metadata_for(const wchar_t *name) {
|
|
assert(name && "null flag name");
|
|
for (const auto &md : metadata) {
|
|
if (!std::wcscmp(name, md.name)) return &md;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void features_t::set_from_string(const wcstring &str) {
|
|
wcstring_list_t entries = split_string(str, L',');
|
|
const wchar_t *whitespace = L"\t\n\v\f\r ";
|
|
for (wcstring entry : entries) {
|
|
if (entry.empty()) continue;
|
|
|
|
// Trim leading and trailing whitespace
|
|
entry.erase(0, entry.find_first_not_of(whitespace));
|
|
entry.erase(entry.find_last_not_of(whitespace) + 1);
|
|
|
|
const wchar_t *name = entry.c_str();
|
|
bool value = true;
|
|
// A "no-" prefix inverts the sense.
|
|
if (string_prefixes_string(L"no-", name)) {
|
|
value = false;
|
|
name += const_strlen("no-");
|
|
}
|
|
// Look for a feature with this name. If we don't find it, assume it's a group name and set
|
|
// all features whose group contain it. Do nothing even if the string is unrecognized; this
|
|
// is to allow uniform invocations of fish (e.g. disable a feature that is only present in
|
|
// 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)) {
|
|
// 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")) {
|
|
if (!md.read_only) {
|
|
this->set(md.flag, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|