aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-03-09 23:59:50 -0800
committerJade Lovelace <lix@jade.fyi>2024-03-11 14:14:43 -0700
commitbe2b87ed4dda865406096196804b784f4c293687 (patch)
treec4793e79fcbb4e3c29ad27931a072969c75b054d /src
parentb06a39211460033305c5264a456161c75ed88425 (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
Diffstat (limited to 'src')
-rw-r--r--src/libcmd/repl-interacter.cc22
-rw-r--r--src/libcmd/repl-interacter.hh9
-rw-r--r--src/libcmd/repl.cc8
-rw-r--r--src/libutil/experimental-features.cc21
-rw-r--r--src/libutil/experimental-features.hh1
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,
};
/**