fish-shell/src/future_feature_flags.cpp
Aaron Gyes 14d2a6d8ff IWYU-guided #include rejiggering.
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.
2022-08-20 23:55:18 -07:00

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);
}
}
}
}
}
}