Add support for weston-terminal (#384)

* add support for weston-terminal

* move NonExclusiveTemporaryFileOwner to utils

* move wrapCommandForTerminalEmulator to utils
This commit is contained in:
Cyano Hao 2024-04-17 12:49:37 +08:00 committed by GitHub
parent 5fce5cead7
commit c90f0bc313
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 147 additions and 90 deletions

View File

@ -22,6 +22,7 @@
#include "qt_utils/utils.h" #include "qt_utils/utils.h"
#include "../utils.h" #include "../utils.h"
#include "../common.h" #include "../common.h"
#include "settings.h"
enum RunProgramFlag { enum RunProgramFlag {
RPF_PAUSE_CONSOLE = 0x0001, RPF_PAUSE_CONSOLE = 0x0001,
@ -103,7 +104,7 @@ private:
int mSyntaxCheckIssueCount; int mSyntaxCheckIssueCount;
Compiler* mBackgroundSyntaxChecker; Compiler* mBackgroundSyntaxChecker;
Runner* mRunner; Runner* mRunner;
TemporaryFileOwner mTempFileOwner; PNonExclusiveTemporaryFileOwner mTempFileOwner;
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QRecursiveMutex mCompileMutex; QRecursiveMutex mCompileMutex;
QRecursiveMutex mBackgroundSyntaxCheckMutex; QRecursiveMutex mBackgroundSyntaxCheckMutex;

View File

@ -2360,7 +2360,7 @@ void DebugTarget::run()
} + mArguments; } + mArguments;
QString cmd; QString cmd;
QStringList arguments; QStringList arguments;
std::unique_ptr<QTemporaryFile> fileOwner; PNonExclusiveTemporaryFileOwner fileOwner;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (pSettings->environment().useCustomTerminal()) { if (pSettings->environment().useCustomTerminal()) {
std::tie(cmd, arguments, fileOwner) = wrapCommandForTerminalEmulator( std::tie(cmd, arguments, fileOwner) = wrapCommandForTerminalEmulator(

View File

@ -125,6 +125,17 @@
} }
] ]
}, },
{
"group": "Special Purpose",
"terminals": [
{
"name": "Wayland Terminal",
"path": "weston-terminal",
"argsPattern": "$term --shell $tmpfile.sh",
"comment": "integration with Weston compositor, for minimal Live CD/USB"
}
]
},
{ {
"group": "With minor issue", "group": "With minor issue",
"terminals": [ "terminals": [

View File

@ -6545,83 +6545,3 @@ void Settings::Languages::setNoDebugDirectivesWhenGenerateASM(bool newNoDebugDir
{ {
mNoDebugDirectivesWhenGenerateASM = newNoDebugDirectivesWhenGenerateASM; 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" || patternItem == "$unix_command") {
// “$command” is for compatibility; previously used on multiple Unix terms
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::BourneAgainShellPretty);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$dos_command") {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCommandPrompt);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$lpCommandLine") {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCreateProcess);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$tmpfile" || patternItem == "$tmpfile.command") {
// “$tmpfile” is for compatibility; previously used on macOS Terminal.app
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, EscapeArgumentRule::BourneAgainShellPretty);
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 if (patternItem == "$tmpfile.bat") {
temproryFile = std::make_unique<QTemporaryFile>(QDir::tempPath() + "/redpanda_XXXXXX.bat");
if (temproryFile->open()) {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCommandPrompt);
escapedArgs.append(escaped);
}
temproryFile->write(escapedArgs.join(' ').toLocal8Bit());
temproryFile->write("\r\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, parseArguments(argsPattern, Settings::Environment::terminalArgsPatternMagicVariables(), false), payloadArgsWithArgv0);
}

View File

@ -1615,11 +1615,6 @@ private:
Languages mLanguages; Languages mLanguages;
}; };
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; extern Settings* pSettings;
#endif // SETTINGS_H #endif // SETTINGS_H

View File

@ -44,7 +44,7 @@ EnvironmentProgramsWidget::~EnvironmentProgramsWidget()
} }
auto EnvironmentProgramsWidget::resolveExecArguments(const QString &terminalPath, const QString &argsPattern) auto EnvironmentProgramsWidget::resolveExecArguments(const QString &terminalPath, const QString &argsPattern)
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>> -> std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner>
{ {
return wrapCommandForTerminalEmulator(terminalPath, argsPattern, platformCommandForTerminalArgsPreview()); return wrapCommandForTerminalEmulator(terminalPath, argsPattern, platformCommandForTerminalArgsPreview());
} }

View File

@ -17,6 +17,7 @@
#ifndef ENVIRONMENTPROGRAMSWIDGET_H #ifndef ENVIRONMENTPROGRAMSWIDGET_H
#define ENVIRONMENTPROGRAMSWIDGET_H #define ENVIRONMENTPROGRAMSWIDGET_H
#include "settings.h"
#include "settingswidget.h" #include "settingswidget.h"
#include "utils.h" #include "utils.h"
@ -34,7 +35,7 @@ public:
private: private:
auto resolveExecArguments(const QString &terminalPath, const QString &argsPatter) auto resolveExecArguments(const QString &terminalPath, const QString &argsPatter)
-> std::tuple<QString, QStringList, std::unique_ptr<QTemporaryFile>>; -> std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner>;
void updateCommandPreview(const QString &terminalPath, const QString &argsPatter); void updateCommandPreview(const QString &terminalPath, const QString &argsPatter);
void autoDetectAndUpdateArgumentsPattern(const QString &terminalPath); void autoDetectAndUpdateArgumentsPattern(const QString &terminalPath);

View File

@ -14,6 +14,8 @@
#include "parser/cppparser.h" #include "parser/cppparser.h"
#include "compiler/executablerunner.h" #include "compiler/executablerunner.h"
#include <QComboBox> #include <QComboBox>
#include "utils/escape.h"
#include "utils/parsearg.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QDesktopServices> #include <QDesktopServices>
#include <windows.h> #include <windows.h>
@ -25,6 +27,22 @@ using pIsWow64Process2_t = BOOL (WINAPI *)(
); );
#endif #endif
NonExclusiveTemporaryFileOwner::NonExclusiveTemporaryFileOwner(std::unique_ptr<QTemporaryFile> &tempFile) :
filename(tempFile ? tempFile->fileName() : QString())
{
if (tempFile) {
tempFile->flush();
tempFile->setAutoRemove(false);
tempFile = nullptr;
}
}
NonExclusiveTemporaryFileOwner::~NonExclusiveTemporaryFileOwner()
{
if (!filename.isEmpty())
QFile::remove(filename);
}
FileType getFileType(const QString &filename) FileType getFileType(const QString &filename)
{ {
if (filename.endsWith(".s",PATH_SENSITIVITY)) { if (filename.endsWith(".s",PATH_SENSITIVITY)) {
@ -635,3 +653,96 @@ QByteArray stringToByteArray(const QString &content, bool isUTF8)
else else
return content.toLocal8Bit(); return content.toLocal8Bit();
} }
std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner> 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" || patternItem == "$unix_command") {
// “$command” is for compatibility; previously used on multiple Unix terms
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::BourneAgainShellPretty);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$dos_command") {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCommandPrompt);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$lpCommandLine") {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCreateProcess);
escapedArgs.append(escaped);
}
wrappedArgs.push_back(escapedArgs.join(' '));
} else if (patternItem == "$tmpfile" || patternItem == "$tmpfile.command") {
// “$tmpfile” is for compatibility; previously used on macOS Terminal.app
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, EscapeArgumentRule::BourneAgainShellPretty);
escapedArgs.append(escaped);
}
temproryFile->write(escapedArgs.join(' ').toUtf8());
temproryFile->write("\n");
QFile(temproryFile->fileName()).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
}
wrappedArgs.push_back(temproryFile->fileName());
} else if (patternItem == "$tmpfile.sh") {
temproryFile = std::make_unique<QTemporaryFile>(QDir::tempPath() + "/redpanda_XXXXXX.command");
if (temproryFile->open()) {
QStringList escapedArgs = {"exec"};
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, false, EscapeArgumentRule::BourneAgainShellPretty);
escapedArgs.append(escaped);
}
temproryFile->write("#!/bin/sh\n");
temproryFile->write(escapedArgs.join(' ').toUtf8());
temproryFile->write("\n");
QFile(temproryFile->fileName()).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
}
wrappedArgs.push_back(temproryFile->fileName());
} else if (patternItem == "$tmpfile.bat") {
temproryFile = std::make_unique<QTemporaryFile>(QDir::tempPath() + "/redpanda_XXXXXX.bat");
if (temproryFile->open()) {
QStringList escapedArgs;
for (int i = 0; i < payloadArgsWithArgv0.length(); i++) {
auto &arg = payloadArgsWithArgv0[i];
auto escaped = escapeArgument(arg, i == 0, EscapeArgumentRule::WindowsCommandPrompt);
escapedArgs.append(escaped);
}
temproryFile->write(escapedArgs.join(' ').toLocal8Bit());
temproryFile->write("\r\n");
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::make_unique<NonExclusiveTemporaryFileOwner>(temproryFile)};
return {wrappedArgs[0], wrappedArgs.mid(1), std::make_unique<NonExclusiveTemporaryFileOwner>(temproryFile)};
}
std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner> wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0)
{
return wrapCommandForTerminalEmulator(terminal, parseArguments(argsPattern, Settings::Environment::terminalArgsPatternMagicVariables(), false), payloadArgsWithArgv0);
}

View File

@ -35,7 +35,6 @@
using SimpleIni = CSimpleIniA; using SimpleIni = CSimpleIniA;
using PSimpleIni = std::shared_ptr<SimpleIni>; using PSimpleIni = std::shared_ptr<SimpleIni>;
using TemporaryFileOwner = std::unique_ptr<QTemporaryFile>;
enum class FileType{ enum class FileType{
GAS, // GNU assembler source file (.s) GAS, // GNU assembler source file (.s)
@ -116,6 +115,21 @@ enum class ProblemCaseValidateType {
IgnoreSpaces IgnoreSpaces
}; };
struct NonExclusiveTemporaryFileOwner {
const QString filename;
// take ownership
explicit NonExclusiveTemporaryFileOwner(std::unique_ptr<QTemporaryFile> &tempFile);
NonExclusiveTemporaryFileOwner(const NonExclusiveTemporaryFileOwner &) = delete;
NonExclusiveTemporaryFileOwner(NonExclusiveTemporaryFileOwner &&) = delete;
NonExclusiveTemporaryFileOwner& operator=(const NonExclusiveTemporaryFileOwner &) = delete;
NonExclusiveTemporaryFileOwner& operator=(NonExclusiveTemporaryFileOwner &&) = delete;
~NonExclusiveTemporaryFileOwner();
};
using PNonExclusiveTemporaryFileOwner = std::unique_ptr<NonExclusiveTemporaryFileOwner>;
FileType getFileType(const QString& filename); FileType getFileType(const QString& filename);
bool programHasConsole(const QString& filename); bool programHasConsole(const QString& filename);
@ -180,4 +194,8 @@ QByteArray stringToByteArray(const QString& content, bool isUTF8);
#define __builtin_unreachable() (__assume(0)) #define __builtin_unreachable() (__assume(0))
#endif #endif
std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner> wrapCommandForTerminalEmulator(const QString &terminal, const QStringList &argsPattern, const QStringList &payloadArgsWithArgv0);
std::tuple<QString, QStringList, PNonExclusiveTemporaryFileOwner> wrapCommandForTerminalEmulator(const QString &terminal, const QString &argsPattern, const QStringList &payloadArgsWithArgv0);
#endif // UTILS_H #endif // UTILS_H