diff options
author | Jade Lovelace <lix@jade.fyi> | 2024-03-09 23:59:50 -0800 |
---|---|---|
committer | Jade Lovelace <lix@jade.fyi> | 2024-03-11 14:14:43 -0700 |
commit | be2b87ed4dda865406096196804b784f4c293687 (patch) | |
tree | c4793e79fcbb4e3c29ad27931a072969c75b054d | |
parent | b06a39211460033305c5264a456161c75ed88425 (diff) |
add automated usage mode to the repl
This is definitely not a stable thing, but it does feel slightly crimes
to put it as an experimental feature. Shrug, up for bikeshedding.
Change-Id: I6ef176e3dee6fb1cac9c0a7a60d553a2c63ea728
-rw-r--r-- | src/libcmd/repl-interacter.cc | 22 | ||||
-rw-r--r-- | src/libcmd/repl-interacter.hh | 9 | ||||
-rw-r--r-- | src/libcmd/repl.cc | 8 | ||||
-rw-r--r-- | src/libutil/experimental-features.cc | 21 | ||||
-rw-r--r-- | src/libutil/experimental-features.hh | 1 |
5 files changed, 59 insertions, 2 deletions
diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index 18c1cad0f..829383add 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -1,4 +1,6 @@ #include <cstdio> +#include <iostream> +#include <string> #ifdef READLINE #include <readline/history.h> @@ -183,4 +185,24 @@ ReadlineLikeInteracter::~ReadlineLikeInteracter() write_history(historyFile.c_str()); } +AutomationInteracter::Guard AutomationInteracter::init(detail::ReplCompleterMixin *) +{ + return Guard([] {}); +} + +// ASCII ENQ character +constexpr const char * automationPrompt = "\x05"; + +bool AutomationInteracter::getLine(std::string & input, ReplPromptType promptType) +{ + std::cout << std::unitbuf; + std::cout << automationPrompt; + if (!std::getline(std::cin, input)) { + // reset failure bits on EOF + std::cin.clear(); + return false; + } + return true; +} + }; diff --git a/src/libcmd/repl-interacter.hh b/src/libcmd/repl-interacter.hh index cc70efd07..c31b1a1e6 100644 --- a/src/libcmd/repl-interacter.hh +++ b/src/libcmd/repl-interacter.hh @@ -45,4 +45,13 @@ public: virtual ~ReadlineLikeInteracter() override; }; +class AutomationInteracter : public virtual ReplInteracter +{ +public: + AutomationInteracter() = default; + virtual Guard init(detail::ReplCompleterMixin * repl) override; + virtual bool getLine(std::string & input, ReplPromptType promptType) override; + virtual ~AutomationInteracter() override = default; +}; + }; diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 5809ab285..9e5599152 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -121,6 +121,12 @@ std::string removeWhitespace(std::string s) return s; } +static box_ptr<ReplInteracter> makeInteracter() { + if (experimentalFeatureSettings.isEnabled(Xp::ReplAutomation)) + return make_box_ptr<AutomationInteracter>(); + else + return make_box_ptr<ReadlineLikeInteracter>(getDataDir() + "/nix/repl-history"); +} NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalState> state, std::function<NixRepl::AnnotatedValues()> getValues) @@ -128,7 +134,7 @@ NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalS , debugTraceIndex(0) , getValues(getValues) , staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get())) - , interacter(make_box_ptr<ReadlineLikeInteracter>(getDataDir() + "/nix/repl-history")) + , interacter(makeInteracter()) { } diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index 782331283..d1e1d7423 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -12,7 +12,19 @@ struct ExperimentalFeatureDetails std::string_view description; }; -constexpr std::array<ExperimentalFeatureDetails, 14> xpFeatureDetails = {{ +/** + * If two different PRs both add an experimental feature, and we just + * used a number for this, we *woudln't* get merge conflict and the + * counter will be incremented once instead of twice, causing a build + * failure. + * + * By instead defining this instead as 1 + the bottom experimental + * feature, we either have no issue at all if few features are not added + * at the end of the list, or a proper merge conflict if they are. + */ +constexpr size_t numXpFeatures = 1 + static_cast<size_t>(Xp::ReplAutomation); + +constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails = {{ { .tag = Xp::CaDerivations, .name = "ca-derivations", @@ -219,6 +231,13 @@ constexpr std::array<ExperimentalFeatureDetails, 14> xpFeatureDetails = {{ Allow the use of the `read-only` parameter in [local store](@docroot@/command-ref/new-cli/nix3-help-stores.md#local-store) URIs. )", }, + { + .tag = Xp::ReplAutomation, + .name = "repl-automation", + .description = R"( + Makes the repl not use readline/editline, print ENQ (U+0005) when ready for a command, and take commands followed by newline. + )", + }, }}; static_assert( diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index add592ae6..cc841c0a6 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -31,6 +31,7 @@ enum struct ExperimentalFeature DynamicDerivations, ParseTomlTimestamps, ReadOnlyLocalStore, + ReplAutomation, }; /** |