forked from lix-project/lix
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
This commit is contained in:
parent
b06a392114
commit
be2b87ed4d
|
@ -1,4 +1,6 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef READLINE
|
#ifdef READLINE
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
@ -183,4 +185,24 @@ ReadlineLikeInteracter::~ReadlineLikeInteracter()
|
||||||
write_history(historyFile.c_str());
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,4 +45,13 @@ public:
|
||||||
virtual ~ReadlineLikeInteracter() override;
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,6 +121,12 @@ std::string removeWhitespace(std::string s)
|
||||||
return 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,
|
NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalState> state,
|
||||||
std::function<NixRepl::AnnotatedValues()> getValues)
|
std::function<NixRepl::AnnotatedValues()> getValues)
|
||||||
|
@ -128,7 +134,7 @@ NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalS
|
||||||
, debugTraceIndex(0)
|
, debugTraceIndex(0)
|
||||||
, getValues(getValues)
|
, getValues(getValues)
|
||||||
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get()))
|
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get()))
|
||||||
, interacter(make_box_ptr<ReadlineLikeInteracter>(getDataDir() + "/nix/repl-history"))
|
, interacter(makeInteracter())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,19 @@ struct ExperimentalFeatureDetails
|
||||||
std::string_view description;
|
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,
|
.tag = Xp::CaDerivations,
|
||||||
.name = "ca-derivations",
|
.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.
|
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(
|
static_assert(
|
||||||
|
|
|
@ -31,6 +31,7 @@ enum struct ExperimentalFeature
|
||||||
DynamicDerivations,
|
DynamicDerivations,
|
||||||
ParseTomlTimestamps,
|
ParseTomlTimestamps,
|
||||||
ReadOnlyLocalStore,
|
ReadOnlyLocalStore,
|
||||||
|
ReplAutomation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue