Redesign terminal settings
This commit is contained in:
parent
9557dd8378
commit
7b5fa255da
|
@ -270,7 +270,7 @@ void CompilerManager::run(
|
|||
} + splitProcessCommand(arguments);
|
||||
if (pSettings->environment().useCustomTerminal()) {
|
||||
auto [filename, args, fileOwner] = wrapCommandForTerminalEmulator(
|
||||
pSettings->environment().terminalPathForExec(),
|
||||
pSettings->environment().terminalPath(),
|
||||
pSettings->environment().terminalArgumentsPattern(),
|
||||
execArgs
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"terminals": [
|
||||
{
|
||||
"name": "UTF-8 compatible Console Host",
|
||||
"path": "./OpenConsole.exe",
|
||||
"path": "%*APP_DIR*%/OpenConsole.exe",
|
||||
"argsPattern": "$term -- $argv"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3625,6 +3625,7 @@ void Settings::Environment::doLoad()
|
|||
|
||||
// check saved terminal path
|
||||
mTerminalPath = stringValue("terminal_path", "");
|
||||
mTerminalPath.replace("%*APP_DIR*%",pSettings->dirs().appDir());
|
||||
mTerminalArgumentsPattern = stringValue("terminal_arguments_pattern", "");
|
||||
|
||||
checkAndSetTerminal();
|
||||
|
@ -3689,15 +3690,6 @@ QString Settings::Environment::terminalPath() const
|
|||
return mTerminalPath;
|
||||
}
|
||||
|
||||
QString Settings::Environment::terminalPathForExec() const
|
||||
{
|
||||
if (getPathUnixExecSemantics(mTerminalPath) == UnixExecSemantics::RelativeToCwd) {
|
||||
QDir appDir(pSettings->dirs().appDir());
|
||||
return appDir.absoluteFilePath(mTerminalPath);
|
||||
} else
|
||||
return mTerminalPath;
|
||||
}
|
||||
|
||||
void Settings::Environment::setTerminalPath(const QString &terminalPath)
|
||||
{
|
||||
mTerminalPath = terminalPath;
|
||||
|
@ -3775,8 +3767,10 @@ void Settings::Environment::setIconZoomFactor(double newIconZoomFactor)
|
|||
|
||||
QString Settings::Environment::queryPredefinedTerminalArgumentsPattern(const QString &executable) const
|
||||
{
|
||||
QString execName = extractFileName(executable);
|
||||
for (const TerminalItem& item: loadTerminalList()) {
|
||||
if (item.terminal.compare(executable,PATH_SENSITIVITY)==0) return item.param;
|
||||
QString termName = extractFileName(item.terminal);
|
||||
if (termName.compare(execName,PATH_SENSITIVITY)==0) return item.param;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
@ -3793,19 +3787,30 @@ void Settings::Environment::setUseCustomTerminal(bool newUseCustomTerminal)
|
|||
|
||||
void Settings::Environment::checkAndSetTerminal()
|
||||
{
|
||||
if (!mUseCustomTerminal) return;
|
||||
if (!mTerminalPath.isEmpty() && !mTerminalArgumentsPattern.isEmpty()) return;
|
||||
if (isTerminalValid()) return;
|
||||
|
||||
QStringList pathList = getExecutableSearchPaths();
|
||||
QList<TerminalItem> terminalList = loadTerminalList();
|
||||
for (const QString &dirPath: pathList) {
|
||||
QDir dir{dirPath};
|
||||
for (const TerminalItem& termItem:terminalList) {
|
||||
QString absoluteTerminalPath = dir.absoluteFilePath(termItem.terminal);
|
||||
QString term=termItem.terminal;
|
||||
term.replace("%*APP_DIR*%",pSettings->dirs().appDir());
|
||||
QFileInfo info{term};
|
||||
QString absoluteTerminalPath;
|
||||
if (info.isAbsolute()) {
|
||||
absoluteTerminalPath = info.absoluteFilePath();
|
||||
if(fileExists(absoluteTerminalPath)) {
|
||||
mTerminalPath = absoluteTerminalPath;
|
||||
mTerminalArgumentsPattern = termItem.param;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
for (const QString &dirPath: pathList) {
|
||||
QDir dir{dirPath};
|
||||
absoluteTerminalPath = dir.absoluteFilePath(termItem.terminal);
|
||||
if(fileExists(absoluteTerminalPath)) {
|
||||
mTerminalPath = absoluteTerminalPath;
|
||||
mTerminalArgumentsPattern = termItem.param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3835,11 +3840,12 @@ QList<Settings::Environment::TerminalItem> Settings::Environment::loadTerminalLi
|
|||
for (const auto &terminalGroup: terminalListDocument.array()) {
|
||||
const QJsonArray &terminals = terminalGroup.toObject()["terminals"].toArray();
|
||||
for (const auto &terminal_: terminals) {
|
||||
const QJsonObject &terminal = terminal_.toObject();
|
||||
const QString &path = terminal["path"].toString();
|
||||
const QString &termExecutable = QFileInfo(path).fileName();
|
||||
const QString &pattern = terminal["argsPattern"].toString();
|
||||
const QJsonObject& terminal = terminal_.toObject();
|
||||
QString path = terminal["path"].toString();
|
||||
QString termExecutable = QFileInfo(path).fileName();
|
||||
QString pattern = terminal["argsPattern"].toString();
|
||||
Settings::Environment::TerminalItem terminalItem;
|
||||
path.replace("%*APP_DIR*%", pSettings->dirs().appDir());
|
||||
terminalItem.terminal = path;
|
||||
terminalItem.param = pattern;
|
||||
result.append(terminalItem);
|
||||
|
@ -3848,6 +3854,36 @@ QList<Settings::Environment::TerminalItem> Settings::Environment::loadTerminalLi
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Settings::Environment::isTerminalValid()
|
||||
{
|
||||
// don't use custom terminal
|
||||
if (!mUseCustomTerminal) return true;
|
||||
// terminal patter is empty
|
||||
if (mTerminalArgumentsPattern.isEmpty()) return false;
|
||||
|
||||
QStringList patternItems = splitProcessCommand(mTerminalArgumentsPattern);
|
||||
|
||||
if (!(patternItems.contains("$argv")
|
||||
|| patternItems.contains("$command")
|
||||
|| patternItems.contains("$tmpfile"))) {
|
||||
// program not referenced
|
||||
return false;
|
||||
}
|
||||
QFileInfo termPathInfo{mTerminalPath};
|
||||
if (termPathInfo.isAbsolute()) {
|
||||
return termPathInfo.exists();
|
||||
} else {
|
||||
QStringList pathList = getExecutableSearchPaths();
|
||||
for (const QString &dirName: pathList) {
|
||||
QDir dir{dirName};
|
||||
QString absoluteTerminalPath = dir.absoluteFilePath(mTerminalPath);
|
||||
QFileInfo absTermPathInfo(absoluteTerminalPath);
|
||||
if (absTermPathInfo.exists()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Settings::Environment::doSave()
|
||||
{
|
||||
//Appearance
|
||||
|
@ -3862,7 +3898,10 @@ void Settings::Environment::doSave()
|
|||
|
||||
saveValue("current_folder",mCurrentFolder);
|
||||
saveValue("default_open_folder",mDefaultOpenFolder);
|
||||
saveValue("terminal_path",mTerminalPath);
|
||||
QString terminalPath = mTerminalPath;
|
||||
terminalPath.replace(pSettings->dirs().appDir(), "%*APP_DIR*%");
|
||||
|
||||
saveValue("terminal_path",terminalPath);
|
||||
saveValue("terminal_arguments_pattern",mTerminalArgumentsPattern);
|
||||
#ifdef Q_OS_WINDOWS
|
||||
saveValue("use_custom_terminal",mUseCustomTerminal);
|
||||
|
@ -6347,3 +6386,50 @@ void Settings::Languages::setNoDebugDirectivesWhenGenerateASM(bool newNoDebugDir
|
|||
{
|
||||
mNoDebugDirectivesWhenGenerateASM = newNoDebugDirectivesWhenGenerateASM;
|
||||
}
|
||||
|
||||
std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>> wrapCommandForTerminalEmulator(const QString &terminal, const QStringList &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
{
|
||||
QStringList wrappedArgs;
|
||||
std::unique_ptr<QTemporaryFile> temproryFile;
|
||||
for (const QString &patternItem : argsPattern) {
|
||||
if (patternItem == "$term")
|
||||
wrappedArgs.append(terminal);
|
||||
else if (patternItem == "$integrated_term")
|
||||
wrappedArgs.append(includeTrailingPathDelimiter(pSettings->dirs().appDir())+terminal);
|
||||
else if (patternItem == "$argv")
|
||||
wrappedArgs.append(payloadArgsWithArgv0);
|
||||
else if (patternItem == "$command") {
|
||||
QStringList escapedArgs;
|
||||
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
|
||||
auto &arg = payloadArgsWithArgv0[i];
|
||||
auto escaped = escapeArgument(arg, i == 0);
|
||||
escapedArgs.append(escaped);
|
||||
}
|
||||
wrappedArgs.push_back(escapedArgs.join(' '));
|
||||
} else if (patternItem == "$tmpfile") {
|
||||
temproryFile = std::make_unique<QTemporaryFile>(QDir::tempPath() + "/redpanda_XXXXXX.command");
|
||||
if (temproryFile->open()) {
|
||||
QStringList escapedArgs;
|
||||
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
|
||||
auto &arg = payloadArgsWithArgv0[i];
|
||||
auto escaped = escapeArgument(arg, i == 0);
|
||||
escapedArgs.append(escaped);
|
||||
}
|
||||
temproryFile->write(escapedArgs.join(' ').toUtf8());
|
||||
temproryFile->write("\n");
|
||||
temproryFile->flush();
|
||||
QFile(temproryFile->fileName()).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
|
||||
}
|
||||
wrappedArgs.push_back(temproryFile->fileName());
|
||||
} else
|
||||
wrappedArgs.push_back(patternItem);
|
||||
}
|
||||
if (wrappedArgs.empty())
|
||||
return {QString(""), QStringList{}, std::move(temproryFile)};
|
||||
return {wrappedArgs[0], wrappedArgs.mid(1), std::move(temproryFile)};
|
||||
}
|
||||
|
||||
std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>> wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
{
|
||||
return wrapCommandForTerminalEmulator(terminal, splitProcessCommand(argsPattern), payloadArgsWithArgv0);
|
||||
}
|
||||
|
|
|
@ -575,7 +575,6 @@ public:
|
|||
void setIconSet(const QString &newIconSet);
|
||||
|
||||
QString terminalPath() const;
|
||||
QString terminalPathForExec() const;
|
||||
void setTerminalPath(const QString &terminalPath);
|
||||
|
||||
QString AStylePath() const;
|
||||
|
@ -610,6 +609,7 @@ public:
|
|||
QList<TerminalItem> loadTerminalList() const;
|
||||
|
||||
private:
|
||||
bool isTerminalValid();
|
||||
void checkAndSetTerminal();
|
||||
|
||||
//Appearance
|
||||
|
@ -1623,6 +1623,10 @@ private:
|
|||
};
|
||||
|
||||
|
||||
std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>> wrapCommandForTerminalEmulator(const QString &terminal, const QStringList &argsPattern, const QStringList &payloadArgsWithArgv0);
|
||||
|
||||
std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>> wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0);
|
||||
|
||||
extern Settings* pSettings;
|
||||
|
||||
#endif // SETTINGS_H
|
||||
|
|
|
@ -43,16 +43,9 @@ EnvironmentProgramsWidget::~EnvironmentProgramsWidget()
|
|||
auto EnvironmentProgramsWidget::resolveExecArguments(const QString &terminalPath, const QString &argsPattern)
|
||||
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>
|
||||
{
|
||||
QString terminalPathForExec;
|
||||
if (getPathUnixExecSemantics(terminalPath) == UnixExecSemantics::RelativeToCwd) {
|
||||
QDir appDir(pSettings->dirs().appDir());
|
||||
terminalPathForExec = appDir.absoluteFilePath(terminalPath);
|
||||
} else
|
||||
terminalPathForExec = terminalPath;
|
||||
|
||||
QString shell = defaultShell();
|
||||
QStringList payloadArgs{shell, "-c", "echo hello; sleep 3"};
|
||||
return wrapCommandForTerminalEmulator(terminalPathForExec, argsPattern, payloadArgs);
|
||||
return wrapCommandForTerminalEmulator(terminalPath, argsPattern, payloadArgs);
|
||||
}
|
||||
|
||||
void EnvironmentProgramsWidget::updateCommandPreview(const QString &terminalPath, const QString &argsPattern)
|
||||
|
@ -61,7 +54,7 @@ void EnvironmentProgramsWidget::updateCommandPreview(const QString &terminalPath
|
|||
for (auto &arg : arguments)
|
||||
arg = escapeArgument(arg, false);
|
||||
|
||||
ui->labelCmdPreviewResult->setText(escapeArgument(filename, true) + " " + arguments.join(' '));
|
||||
ui->labelCmdPreviewResult->setPlainText(escapeArgument(filename, true) + " " + arguments.join(' '));
|
||||
}
|
||||
|
||||
void EnvironmentProgramsWidget::autoDetectAndUpdateArgumentsPattern(const QString &terminalPath)
|
||||
|
|
|
@ -82,13 +82,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelCmdPreviewResult">
|
||||
<property name="text">
|
||||
<string>term -e sh -c "echo hello; sleep 3"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QToolButton" name="btnTest">
|
||||
<property name="toolTip">
|
||||
|
@ -103,6 +96,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPlainTextEdit" name="labelCmdPreviewResult">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -590,18 +590,6 @@ QColor alphaBlend(const QColor &lower, const QColor &upper) {
|
|||
);
|
||||
}
|
||||
|
||||
UnixExecSemantics getPathUnixExecSemantics(const QString &path)
|
||||
{
|
||||
QFileInfo pathInfo(path);
|
||||
if (pathInfo.isRelative()) {
|
||||
if (path.contains('/'))
|
||||
return UnixExecSemantics::RelativeToCwd;
|
||||
else
|
||||
return UnixExecSemantics::SearchInPath;
|
||||
} else
|
||||
return UnixExecSemantics::Absolute;
|
||||
}
|
||||
|
||||
QStringList getExecutableSearchPaths()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
|
@ -723,53 +711,6 @@ QString escapeArgument(const QString &arg, [[maybe_unused]] bool isFirstArg)
|
|||
#endif
|
||||
}
|
||||
|
||||
auto wrapCommandForTerminalEmulator(const QString &terminal, const QStringList &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>
|
||||
{
|
||||
QStringList wrappedArgs;
|
||||
std::unique_ptr<QTemporaryFile> temproryFile;
|
||||
for (const QString &patternItem : argsPattern) {
|
||||
if (patternItem == "$term")
|
||||
wrappedArgs.push_back(terminal);
|
||||
else if (patternItem == "$argv")
|
||||
wrappedArgs.append(payloadArgsWithArgv0);
|
||||
else if (patternItem == "$command") {
|
||||
QStringList escapedArgs;
|
||||
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
|
||||
auto &arg = payloadArgsWithArgv0[i];
|
||||
auto escaped = escapeArgument(arg, i == 0);
|
||||
escapedArgs.append(escaped);
|
||||
}
|
||||
wrappedArgs.push_back(escapedArgs.join(' '));
|
||||
} else if (patternItem == "$tmpfile") {
|
||||
temproryFile = std::make_unique<QTemporaryFile>(QDir::tempPath() + "/redpanda_XXXXXX.command");
|
||||
if (temproryFile->open()) {
|
||||
QStringList escapedArgs;
|
||||
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
|
||||
auto &arg = payloadArgsWithArgv0[i];
|
||||
auto escaped = escapeArgument(arg, i == 0);
|
||||
escapedArgs.append(escaped);
|
||||
}
|
||||
temproryFile->write(escapedArgs.join(' ').toUtf8());
|
||||
temproryFile->write("\n");
|
||||
temproryFile->flush();
|
||||
QFile(temproryFile->fileName()).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
|
||||
}
|
||||
wrappedArgs.push_back(temproryFile->fileName());
|
||||
} else
|
||||
wrappedArgs.push_back(patternItem);
|
||||
}
|
||||
if (wrappedArgs.empty())
|
||||
return {QString(""), QStringList{}, std::move(temproryFile)};
|
||||
return {wrappedArgs[0], wrappedArgs.mid(1), std::move(temproryFile)};
|
||||
}
|
||||
|
||||
auto wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>
|
||||
{
|
||||
return wrapCommandForTerminalEmulator(terminal, splitProcessCommand(argsPattern), payloadArgsWithArgv0);
|
||||
}
|
||||
|
||||
QString defaultShell()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
|
|
@ -115,12 +115,6 @@ enum class ProblemCaseValidateType {
|
|||
IgnoreSpaces
|
||||
};
|
||||
|
||||
enum class UnixExecSemantics {
|
||||
Absolute,
|
||||
RelativeToCwd,
|
||||
SearchInPath,
|
||||
};
|
||||
|
||||
FileType getFileType(const QString& filename);
|
||||
QStringList splitProcessCommand(const QString& cmd);
|
||||
|
||||
|
@ -173,18 +167,10 @@ void saveComboHistory(QComboBox* cb,const QString& text);
|
|||
|
||||
QColor alphaBlend(const QColor &lower, const QColor &upper);
|
||||
|
||||
UnixExecSemantics getPathUnixExecSemantics(const QString &path);
|
||||
|
||||
QStringList getExecutableSearchPaths();
|
||||
|
||||
QString escapeArgument(const QString &arg, bool isFirstArg);
|
||||
|
||||
auto wrapCommandForTerminalEmulator(const QString &terminal, const QStringList &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>;
|
||||
|
||||
auto wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0)
|
||||
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>;
|
||||
|
||||
QString defaultShell();
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
Loading…
Reference in New Issue