forked from quickshell/quickshell
feat(process): add Process.environment
This commit is contained in:
parent
65ad2a9877
commit
e06b07ac01
2
docs
2
docs
|
@ -1 +1 @@
|
||||||
Subproject commit 8b40a464af5c1338d842e61f8ec517d142454cbc
|
Subproject commit 1ca13d9ffded3fbddb0380c0d0df85304065efa9
|
|
@ -5,10 +5,12 @@
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qlist.h>
|
#include <qlist.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
|
#include <qmap.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qprocess.h>
|
#include <qprocess.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
#include <qtypes.h>
|
#include <qtypes.h>
|
||||||
|
#include <qvariant.h>
|
||||||
|
|
||||||
#include "../core/qmlglobal.hpp"
|
#include "../core/qmlglobal.hpp"
|
||||||
#include "datastream.hpp"
|
#include "datastream.hpp"
|
||||||
|
@ -35,6 +37,16 @@ QVariant Process::pid() const {
|
||||||
return QVariant::fromValue(this->process->processId());
|
return QVariant::fromValue(this->process->processId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QString> Process::command() const { return this->mCommand; }
|
||||||
|
|
||||||
|
void Process::setCommand(QList<QString> command) {
|
||||||
|
if (this->mCommand == command) return;
|
||||||
|
this->mCommand = std::move(command);
|
||||||
|
emit this->commandChanged();
|
||||||
|
|
||||||
|
this->startProcessIfReady();
|
||||||
|
}
|
||||||
|
|
||||||
QString Process::workingDirectory() const {
|
QString Process::workingDirectory() const {
|
||||||
if (this->mWorkingDirectory.isEmpty()) return QDir::current().absolutePath();
|
if (this->mWorkingDirectory.isEmpty()) return QDir::current().absolutePath();
|
||||||
else return this->mWorkingDirectory;
|
else return this->mWorkingDirectory;
|
||||||
|
@ -54,14 +66,20 @@ void Process::onGlobalWorkingDirectoryChanged() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QString> Process::command() const { return this->mCommand; }
|
QMap<QString, QVariant> Process::environment() const { return this->mEnvironment; }
|
||||||
|
|
||||||
void Process::setCommand(QList<QString> command) {
|
void Process::setEnvironment(QMap<QString, QVariant> environment) {
|
||||||
if (this->mCommand == command) return;
|
if (environment == this->mEnvironment) return;
|
||||||
this->mCommand = std::move(command);
|
this->mEnvironment = std::move(environment);
|
||||||
emit this->commandChanged();
|
emit this->environmentChanged();
|
||||||
|
}
|
||||||
|
|
||||||
this->startProcessIfReady();
|
bool Process::environmentCleared() const { return this->mClearEnvironment; }
|
||||||
|
|
||||||
|
void Process::setEnvironmentCleared(bool cleared) {
|
||||||
|
if (cleared == this->mClearEnvironment) return;
|
||||||
|
this->mClearEnvironment = cleared;
|
||||||
|
emit this->environmentClearChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataStreamParser* Process::stdoutParser() const { return this->mStdoutParser; }
|
DataStreamParser* Process::stdoutParser() const { return this->mStdoutParser; }
|
||||||
|
@ -167,8 +185,31 @@ void Process::startProcessIfReady() {
|
||||||
if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError);
|
if (this->mStderrParser == nullptr) this->process->closeReadChannel(QProcess::StandardError);
|
||||||
if (!this->mStdinEnabled) this->process->closeWriteChannel();
|
if (!this->mStdinEnabled) this->process->closeWriteChannel();
|
||||||
|
|
||||||
if (!this->mWorkingDirectory.isEmpty())
|
if (!this->mWorkingDirectory.isEmpty()) {
|
||||||
this->process->setWorkingDirectory(this->mWorkingDirectory);
|
this->process->setWorkingDirectory(this->mWorkingDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->mEnvironment.isEmpty() || this->mClearEnvironment) {
|
||||||
|
auto sysenv = QProcessEnvironment::systemEnvironment();
|
||||||
|
auto env = this->mClearEnvironment ? QProcessEnvironment() : sysenv;
|
||||||
|
|
||||||
|
for (auto& name: this->mEnvironment.keys()) {
|
||||||
|
auto value = this->mEnvironment.value(name);
|
||||||
|
if (!value.isValid()) continue;
|
||||||
|
|
||||||
|
if (this->mClearEnvironment) {
|
||||||
|
if (value.isNull()) {
|
||||||
|
if (sysenv.contains(name)) env.insert(name, sysenv.value(name));
|
||||||
|
} else env.insert(name, value.toString());
|
||||||
|
} else {
|
||||||
|
if (value.isNull()) env.remove(name);
|
||||||
|
else env.insert(name, value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->process->setProcessEnvironment(env);
|
||||||
|
}
|
||||||
|
|
||||||
this->process->start(cmd, args);
|
this->process->start(cmd, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qprocess.h>
|
#include <qprocess.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
|
@ -42,14 +43,6 @@ class Process: public QObject {
|
||||||
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged);
|
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged);
|
||||||
/// The process ID of the running process or `null` if `running` is false.
|
/// The process ID of the running process or `null` if `running` is false.
|
||||||
Q_PROPERTY(QVariant pid READ pid NOTIFY pidChanged);
|
Q_PROPERTY(QVariant pid READ pid NOTIFY pidChanged);
|
||||||
/// The working directory of the process. Defaults to [quickshell's working directory].
|
|
||||||
///
|
|
||||||
/// If the process is already running changing this property will affect the next
|
|
||||||
/// started process. If the property has been changed after starting a process it will
|
|
||||||
/// return the new value, not the one for the currently running process.
|
|
||||||
///
|
|
||||||
/// [quickshell's working directory]: ../../quickshell/quickshell#prop.workingDirectory
|
|
||||||
Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged);
|
|
||||||
/// The command to execute.
|
/// The command to execute.
|
||||||
///
|
///
|
||||||
/// If the process is already running changing this property will affect the next
|
/// If the process is already running changing this property will affect the next
|
||||||
|
@ -59,6 +52,57 @@ class Process: public QObject {
|
||||||
/// > [!INFO] You can use `["sh", "-c", <your command>]` to execute your command with
|
/// > [!INFO] You can use `["sh", "-c", <your command>]` to execute your command with
|
||||||
/// > the system shell.
|
/// > the system shell.
|
||||||
Q_PROPERTY(QList<QString> command READ command WRITE setCommand NOTIFY commandChanged);
|
Q_PROPERTY(QList<QString> command READ command WRITE setCommand NOTIFY commandChanged);
|
||||||
|
/// The working directory of the process. Defaults to [quickshell's working directory].
|
||||||
|
///
|
||||||
|
/// If the process is already running changing this property will affect the next
|
||||||
|
/// started process. If the property has been changed after starting a process it will
|
||||||
|
/// return the new value, not the one for the currently running process.
|
||||||
|
///
|
||||||
|
/// [quickshell's working directory]: ../../quickshell/quickshell#prop.workingDirectory
|
||||||
|
Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged);
|
||||||
|
/// Environment of the executed process.
|
||||||
|
///
|
||||||
|
/// This is a javascript object (json). Environment variables can be added by setting
|
||||||
|
/// them to a string and removed by setting them to null (except when [clearEnvironment] is true,
|
||||||
|
/// in which case this behavior is inverted, see [clearEnvironment] for details).
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// ```qml
|
||||||
|
/// environment: ({
|
||||||
|
/// ADDED: "value",
|
||||||
|
/// REMOVED: null,
|
||||||
|
/// "i'm different": "value",
|
||||||
|
/// })
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// > [!INFO] You need to wrap the returned object in () otherwise it won't parse due to javascript ambiguity.
|
||||||
|
///
|
||||||
|
/// If the process is already running changing this property will affect the next
|
||||||
|
/// started process. If the property has been changed after starting a process it will
|
||||||
|
/// return the new value, not the one for the currently running process.
|
||||||
|
///
|
||||||
|
/// [clearEnvironment]: #prop.clearEnvironment
|
||||||
|
Q_PROPERTY(QMap<QString, QVariant> environment READ environment WRITE setEnvironment NOTIFY environmentChanged);
|
||||||
|
/// If the process's environment should be cleared prior to applying [environment](#prop.environment).
|
||||||
|
/// Defaults to false.
|
||||||
|
///
|
||||||
|
/// If true, all environment variables will be removed before the [environment](#prop.environment)
|
||||||
|
/// object is applied, meaning the variables listed will be the only ones visible to the process.
|
||||||
|
/// This changes the behavior of `null` to pass in the system value of the variable if present instead
|
||||||
|
/// of removing it.
|
||||||
|
///
|
||||||
|
/// ```qml
|
||||||
|
/// clearEnvironment: true
|
||||||
|
/// environment: ({
|
||||||
|
/// ADDED: "value",
|
||||||
|
/// PASSED_FROM_SYSTEM: null,
|
||||||
|
/// })
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If the process is already running changing this property will affect the next
|
||||||
|
/// started process. If the property has been changed after starting a process it will
|
||||||
|
/// return the new value, not the one for the currently running process.
|
||||||
|
Q_PROPERTY(bool clearEnvironment READ environmentCleared WRITE setEnvironmentCleared NOTIFY environmentClearChanged);
|
||||||
/// The parser for stdout. If the parser is null the process's stdout channel will be closed
|
/// The parser for stdout. If the parser is null the process's stdout channel will be closed
|
||||||
/// and no further data will be read, even if a new parser is attached.
|
/// and no further data will be read, even if a new parser is attached.
|
||||||
Q_PROPERTY(DataStreamParser* stdout READ stdoutParser WRITE setStdoutParser NOTIFY stdoutParserChanged);
|
Q_PROPERTY(DataStreamParser* stdout READ stdoutParser WRITE setStdoutParser NOTIFY stdoutParserChanged);
|
||||||
|
@ -85,11 +129,17 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] QVariant pid() const;
|
[[nodiscard]] QVariant pid() const;
|
||||||
|
|
||||||
|
[[nodiscard]] QList<QString> command() const;
|
||||||
|
void setCommand(QList<QString> command);
|
||||||
|
|
||||||
[[nodiscard]] QString workingDirectory() const;
|
[[nodiscard]] QString workingDirectory() const;
|
||||||
void setWorkingDirectory(const QString& workingDirectory);
|
void setWorkingDirectory(const QString& workingDirectory);
|
||||||
|
|
||||||
[[nodiscard]] QList<QString> command() const;
|
[[nodiscard]] QMap<QString, QVariant> environment() const;
|
||||||
void setCommand(QList<QString> command);
|
void setEnvironment(QMap<QString, QVariant> environment);
|
||||||
|
|
||||||
|
[[nodiscard]] bool environmentCleared() const;
|
||||||
|
void setEnvironmentCleared(bool cleared);
|
||||||
|
|
||||||
[[nodiscard]] DataStreamParser* stdoutParser() const;
|
[[nodiscard]] DataStreamParser* stdoutParser() const;
|
||||||
void setStdoutParser(DataStreamParser* parser);
|
void setStdoutParser(DataStreamParser* parser);
|
||||||
|
@ -106,8 +156,10 @@ signals:
|
||||||
|
|
||||||
void runningChanged();
|
void runningChanged();
|
||||||
void pidChanged();
|
void pidChanged();
|
||||||
void workingDirectoryChanged();
|
|
||||||
void commandChanged();
|
void commandChanged();
|
||||||
|
void workingDirectoryChanged();
|
||||||
|
void environmentChanged();
|
||||||
|
void environmentClearChanged();
|
||||||
void stdoutParserChanged();
|
void stdoutParserChanged();
|
||||||
void stderrParserChanged();
|
void stderrParserChanged();
|
||||||
void stdinEnabledChanged();
|
void stdinEnabledChanged();
|
||||||
|
@ -126,8 +178,9 @@ private:
|
||||||
void startProcessIfReady();
|
void startProcessIfReady();
|
||||||
|
|
||||||
QProcess* process = nullptr;
|
QProcess* process = nullptr;
|
||||||
QString mWorkingDirectory;
|
|
||||||
QList<QString> mCommand;
|
QList<QString> mCommand;
|
||||||
|
QString mWorkingDirectory;
|
||||||
|
QMap<QString, QVariant> mEnvironment;
|
||||||
DataStreamParser* mStdoutParser = nullptr;
|
DataStreamParser* mStdoutParser = nullptr;
|
||||||
DataStreamParser* mStderrParser = nullptr;
|
DataStreamParser* mStderrParser = nullptr;
|
||||||
QByteArray stdoutBuffer;
|
QByteArray stdoutBuffer;
|
||||||
|
@ -135,4 +188,5 @@ private:
|
||||||
|
|
||||||
bool targetRunning = false;
|
bool targetRunning = false;
|
||||||
bool mStdinEnabled = false;
|
bool mStdinEnabled = false;
|
||||||
|
bool mClearEnvironment = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue