forked from qt-creator/qt-creator
Lua: Create Process bindings
Change-Id: I4b8cca8433df306acdb13e9651c08ab1e01ffa82 Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -10,10 +10,24 @@ using namespace Utils;
|
||||
|
||||
namespace Lua::Internal {
|
||||
|
||||
FilePath toFilePath(std::variant<FilePath, QString> &&v)
|
||||
{
|
||||
return std::visit(
|
||||
[](auto &&arg) -> FilePath {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, QString>)
|
||||
return FilePath::fromUserInput(arg);
|
||||
else
|
||||
return arg;
|
||||
},
|
||||
v);
|
||||
}
|
||||
|
||||
void setupProcessModule()
|
||||
{
|
||||
registerProvider("Process", [](sol::state_view lua) -> sol::object {
|
||||
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
|
||||
QObject *guard = pluginSpec->connectionGuard.get();
|
||||
|
||||
sol::table async = lua.script("return require('async')", "_process_").get<sol::table>();
|
||||
sol::function wrap = async["wrap"];
|
||||
@@ -46,6 +60,100 @@ void setupProcessModule()
|
||||
process["runInTerminal"] = wrap(process["runInTerminal_cb"]);
|
||||
process["commandOutput"] = wrap(process["commandOutput_cb"]);
|
||||
|
||||
process["create"] = [](const sol::table ¶meter) {
|
||||
const auto cmd = toFilePath(parameter.get<std::variant<FilePath, QString>>("command"));
|
||||
|
||||
const QStringList arguments
|
||||
= parameter.get_or<QStringList, const char *, QStringList>("arguments", {});
|
||||
const std::optional<FilePath> workingDirectory = parameter.get<std::optional<FilePath>>(
|
||||
"workingDirectory");
|
||||
|
||||
const auto stdOut = parameter.get<std::optional<sol::function>>("stdout");
|
||||
const auto stdErr = parameter.get<std::optional<sol::function>>("stderr");
|
||||
const auto stdIn = parameter.get<sol::optional<QString>>("stdin");
|
||||
|
||||
auto p = std::make_unique<Process>();
|
||||
|
||||
p->setCommand({cmd, arguments});
|
||||
if (workingDirectory)
|
||||
p->setWorkingDirectory(*workingDirectory);
|
||||
if (stdIn)
|
||||
p->setWriteData(stdIn->toUtf8());
|
||||
if (stdOut) {
|
||||
// clang-format off
|
||||
QObject::connect(p.get(), &Process::readyReadStandardOutput,
|
||||
p.get(),
|
||||
[p = p.get(), cb = *stdOut]() {
|
||||
void_safe_call(cb, p->readAllStandardOutput());
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
if (stdErr) {
|
||||
// clang-format off
|
||||
QObject::connect(p.get(), &Process::readyReadStandardError,
|
||||
p.get(),
|
||||
[p = p.get(), cb = *stdErr]() {
|
||||
void_safe_call(cb, p->readAllStandardError());
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
process.new_usertype<Process>(
|
||||
"Process",
|
||||
sol::no_constructor,
|
||||
"start_cb",
|
||||
[guard](Process *process, sol::function callback) {
|
||||
if (process->state() != QProcess::NotRunning)
|
||||
callback(false, "Process is already running");
|
||||
|
||||
struct Connections
|
||||
{
|
||||
QMetaObject::Connection startedConnection;
|
||||
QMetaObject::Connection doneConnection;
|
||||
};
|
||||
std::shared_ptr<Connections> connections = std::make_shared<Connections>();
|
||||
|
||||
// clang-format off
|
||||
connections->startedConnection
|
||||
= QObject::connect(process, &Process::started,
|
||||
guard, [callback, process, connections]() {
|
||||
process->disconnect(connections->doneConnection);
|
||||
callback(true);
|
||||
},
|
||||
Qt::SingleShotConnection);
|
||||
connections->doneConnection
|
||||
= QObject::connect(process, &Process::done,
|
||||
guard, [callback, process, connections]() {
|
||||
process->disconnect(connections->startedConnection);
|
||||
callback(false, process->errorString());
|
||||
},
|
||||
Qt::SingleShotConnection);
|
||||
// clang-format on
|
||||
process->start();
|
||||
},
|
||||
"stop_cb",
|
||||
[](Process *process, sol::function callback) {
|
||||
if (process->state() != QProcess::Running)
|
||||
callback(false, "Process is not running");
|
||||
|
||||
// clang-format off
|
||||
QObject::connect(process, &Process::done,
|
||||
process, [callback, process]() {
|
||||
callback(true);
|
||||
process->disconnect();
|
||||
},
|
||||
Qt::SingleShotConnection);
|
||||
// clang-format on
|
||||
process->stop();
|
||||
},
|
||||
"isRunning",
|
||||
&Process::isRunning);
|
||||
|
||||
process["Process"]["start"] = wrap(process["Process"]["start_cb"]);
|
||||
process["Process"]["stop"] = wrap(process["Process"]["stop_cb"]);
|
||||
|
||||
return process;
|
||||
});
|
||||
}
|
||||
|
@@ -14,4 +14,38 @@ function process.runInTerminal(cmd) end
|
||||
---@return string output The output of the command.
|
||||
function process.commandOutput(cmd) end
|
||||
|
||||
---@class Process
|
||||
process.Process = {}
|
||||
|
||||
---@class ProcessParameters
|
||||
---@field command FilePath The command to run.
|
||||
---@field arguments? string[] The arguments to pass to the command.
|
||||
---@field workingDirectory? FilePath The working directory for the command.
|
||||
---@field stdin? string The input to write to stdin.
|
||||
---@field stdout? function The callback to call when the process writes to stdout.
|
||||
---@field stderr? function The callback to call when the process writes to stderr.
|
||||
process.ProcessParameters = {}
|
||||
|
||||
---Creates a new process object.
|
||||
---@param parameters ProcessParameters
|
||||
---@return Process
|
||||
function process.create(parameters) end
|
||||
|
||||
---Start the process.
|
||||
---@async
|
||||
---@return boolean isRunning Whether the process was started successfully.
|
||||
function process.Process:start() end
|
||||
|
||||
---Stop the process.
|
||||
---@async
|
||||
---@return boolean didStop Whether the process was stopped successfully.
|
||||
---@return number exitCode The exit code of the process.
|
||||
---@return string error The error message if the process could not be stopped.
|
||||
function process.Process:stop() end
|
||||
|
||||
---Returns whether the process is running.
|
||||
---@return boolean isRunning Whether the process is running.
|
||||
function process.Process:isRunning() end
|
||||
|
||||
---
|
||||
return process
|
||||
|
Reference in New Issue
Block a user