fish-shell/src/future_feature_flags.cpp
ridiculousfish 1127d7d68f clang-format C++ files
No functional change (hopefully!)
2022-06-01 10:02:09 -07:00

76 lines
2.8 KiB
C++

#include "config.h" // IWYU pragma: keep
#include "future_feature_flags.h"
#include <cwchar>
#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);
}
}
}
}
}
}