mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-11 20:48:49 +00:00
Add support for feature flags
This introduces a new type features_t that exposes feature flags. The intent is to allow a deprecation/incremental adoption path. This is not a general purpose configuration mechanism, but instead allows for compatibility during the transition as features are added/removed. Each feature has a user-presentable short name and a short description. Their values are tracked in a struct features_t. We start with one feature stderr_nocaret, but it's not hooked up yet.
This commit is contained in:
parent
7cbc0c371a
commit
14f766b66d
5 changed files with 114 additions and 1 deletions
|
@ -58,6 +58,7 @@ SET(FISH_SRCS
|
|||
src/postfork.cpp src/proc.cpp src/reader.cpp src/sanity.cpp src/screen.cpp
|
||||
src/signal.cpp src/tnode.cpp src/tokenizer.cpp src/utf8.cpp src/util.cpp
|
||||
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp src/wutil.cpp
|
||||
src/future_feature_flags.cpp
|
||||
)
|
||||
|
||||
# Header files are just globbed.
|
||||
|
|
|
@ -118,7 +118,8 @@ FISH_OBJS := obj/autoload.o obj/builtin.o obj/builtin_bg.o obj/builtin_bind.o ob
|
|||
obj/parse_productions.o obj/parse_tree.o obj/parse_util.o obj/parser.o \
|
||||
obj/parser_keywords.o obj/path.o obj/postfork.o obj/proc.o obj/reader.o \
|
||||
obj/sanity.o obj/screen.o obj/signal.o obj/tinyexpr.o obj/tokenizer.o obj/tnode.o obj/utf8.o \
|
||||
obj/util.o obj/wcstringutil.o obj/wgetopt.o obj/wildcard.o obj/wutil.o
|
||||
obj/util.o obj/wcstringutil.o obj/wgetopt.o obj/wildcard.o obj/wutil.o \
|
||||
obj/future_feature_flags.o
|
||||
|
||||
FISH_INDENT_OBJS := obj/fish_indent.o obj/print_help.o $(FISH_OBJS)
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "expand.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "function.h"
|
||||
#include "future_feature_flags.h"
|
||||
#include "highlight.h"
|
||||
#include "history.h"
|
||||
#include "input.h"
|
||||
|
@ -1352,6 +1353,29 @@ static void test_utf8() {
|
|||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
// Ensure every metadata is represented once.
|
||||
size_t counts[ft::flag_count] = {};
|
||||
for (const auto &md : ft::metadata) {
|
||||
counts[md.flag]++;
|
||||
}
|
||||
for (size_t c : counts) {
|
||||
do_test(c == 1);
|
||||
}
|
||||
do_test(ft::metadata[ft::stderr_nocaret].name == wcstring(L"stderr-nocaret"));
|
||||
do_test(ft::metadata_for(L"stderr-nocaret") == &ft::metadata[ft::stderr_nocaret]);
|
||||
do_test(ft::metadata_for(L"not-a-flag") == nullptr);
|
||||
}
|
||||
|
||||
static void test_escape_sequences() {
|
||||
say(L"Testing escape_sequences");
|
||||
if (escape_code_length(L"") != 0) err(L"test_escape_sequences failed on line %d\n", __LINE__);
|
||||
|
@ -4611,6 +4635,7 @@ int main(int argc, char **argv) {
|
|||
if (should_test_function("cancellation")) test_cancellation();
|
||||
if (should_test_function("indents")) test_indents();
|
||||
if (should_test_function("utf8")) test_utf8();
|
||||
if (should_test_function("feature_flags")) test_feature_flags();
|
||||
if (should_test_function("escape_sequences")) test_escape_sequences();
|
||||
if (should_test_function("lru")) test_lru();
|
||||
if (should_test_function("expand")) test_expand();
|
||||
|
|
23
src/future_feature_flags.cpp
Normal file
23
src/future_feature_flags.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "config.h" // IWYU pragma: keep
|
||||
|
||||
#include <wchar.h>
|
||||
#include "future_feature_flags.h"
|
||||
|
||||
/// The set of features applying to this instance.
|
||||
static features_t global_features;
|
||||
|
||||
const features_t &fish_features() { return global_features; }
|
||||
|
||||
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"},
|
||||
};
|
||||
|
||||
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 (!wcscmp(name, md.name)) return &md;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
63
src/future_feature_flags.h
Normal file
63
src/future_feature_flags.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Flags to enable upcoming features
|
||||
#ifndef FISH_FUTURE_FEATURE_FLAGS_H
|
||||
#define FISH_FUTURE_FEATURE_FLAGS_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
class features_t {
|
||||
public:
|
||||
/// The list of flags.
|
||||
enum flag_t {
|
||||
/// Whether ^ is supported for stderr redirection.
|
||||
stderr_nocaret,
|
||||
|
||||
/// The number of flags.
|
||||
flag_count
|
||||
};
|
||||
|
||||
/// Return whether a flag is set.
|
||||
bool test(flag_t f) const {
|
||||
assert(f >= 0 && f < flag_count && "Invalid flag");
|
||||
return values[f];
|
||||
}
|
||||
|
||||
/// Set a flag.
|
||||
void set(flag_t f, bool value) {
|
||||
assert(f >= 0 && f < flag_count && "Invalid flag");
|
||||
values[f] = value;
|
||||
}
|
||||
|
||||
/// Metadata about feature flags.
|
||||
struct metadata_t {
|
||||
/// The flag itself.
|
||||
features_t::flag_t flag;
|
||||
|
||||
/// User-presentable short name of the feature flag.
|
||||
const wchar_t *name;
|
||||
|
||||
/// Comma-separated list of feature groups.
|
||||
const wchar_t *groups;
|
||||
|
||||
/// User-presentable description of the feature flag.
|
||||
const wchar_t *description;
|
||||
};
|
||||
|
||||
/// The metadata, indexed by flag.
|
||||
static const metadata_t metadata[flag_count];
|
||||
|
||||
/// Return the metadata for a particular name, or nullptr if not found.
|
||||
static const struct metadata_t *metadata_for(const wchar_t *name);
|
||||
|
||||
private:
|
||||
/// Values for the flags.
|
||||
bool values[flag_count] = {};
|
||||
};
|
||||
|
||||
/// Return the global set of features for fish. This is const to prevent accidental mutation.
|
||||
const features_t &fish_features();
|
||||
|
||||
/// Return the global set of features for fish, but mutable. In general fish features should be set
|
||||
/// at startup only.
|
||||
features_t &mutable_fish_features();
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue