From c3fe0035121bce5528b138c600b543bdc8dad24e Mon Sep 17 00:00:00 2001 From: Tsu Jan Date: Mon, 20 Jun 2022 22:16:48 +0430 Subject: [PATCH] Fixed command parsing with `-e` option By using `QStringList` instead of `QString`. Fixes https://github.com/lxqt/qterminal/issues/335 and fixes https://github.com/lxqt/qterminal/issues/665 --- src/main.cpp | 52 ++++++++++++++++++++++++++++++++++++++---- src/properties.h | 2 +- src/terminalconfig.cpp | 29 ++++++++++++++--------- src/terminalconfig.h | 12 +++++----- src/termwidget.cpp | 13 ++++------- 5 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 581be135..52a78504 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,7 +72,50 @@ QTerminalApp * QTerminalApp::m_instance = nullptr; exit(code); } -void parse_args(int argc, char* argv[], QString& workdir, QString & shell_command, out bool& dropMode) +QStringList parse_command(const QString& str) +{ + const QRegularExpression separator(QString::fromLatin1(R"('|(? index) + { + list << str.mid(index, nextIndex - index).replace(escapedSpace, QStringLiteral(" ")); + } + if (match.capturedLength() == 0) + { // end of string ("\z") is matched + break; + } + index = nextIndex + match.capturedLength(); + auto c = str.at(index - 1); // last matched character + if (!c.isSpace()) + { // a single quote or an unescaped double quote is matched + nextIndex = str.indexOf(c == QLatin1Char('\'') ? singleQuote : doubleQuote, index, &match); + if (nextIndex == -1) + { // the quote is not closed + break; + } + else + { + if (nextIndex > index) + { + list << str.mid(index, nextIndex - index).replace(escapedSpace, QStringLiteral(" ")); + } + index = nextIndex + match.capturedLength(); + } + } + } + return list; +} + +void parse_args(int argc, char* argv[], QString& workdir, QStringList & shell_command, out bool& dropMode) { int next_option; dropMode = false; @@ -87,13 +130,13 @@ void parse_args(int argc, char* argv[], QString& workdir, QString & shell_comman workdir = QString::fromLocal8Bit(optarg); break; case 'e': - shell_command = QString::fromLocal8Bit(optarg); + shell_command << parse_command(QString::fromLocal8Bit(optarg)); // #15 "Raw" -e params // Passing "raw" params (like konsole -e mcedit /tmp/tmp.txt") is more preferable - then I can call QString("qterminal -e ") + cmd_line in other programs while (optind < argc) { //printf("arg: %d - %s\n", optind, argv[optind]); - shell_command += QLatin1Char(' ') + QString::fromLocal8Bit(argv[optind++]); + shell_command << QString::fromLocal8Bit(argv[optind++]); } break; case 'd': @@ -141,7 +184,8 @@ int main(int argc, char *argv[]) app->registerOnDbus(); #endif - QString workdir, shell_command; + QString workdir; + QStringList shell_command; bool dropMode; parse_args(argc, argv, workdir, shell_command, dropMode); diff --git a/src/properties.h b/src/properties.h index 7e600335..ff97df32 100644 --- a/src/properties.h +++ b/src/properties.h @@ -50,7 +50,7 @@ class Properties QPoint mainWindowPosition; QByteArray mainWindowState; //ShortcutMap shortcuts; - QString shell; + QStringList shell; QFont font; QString colorScheme; QString guiStyle; diff --git a/src/terminalconfig.cpp b/src/terminalconfig.cpp index f61e014c..1497a298 100644 --- a/src/terminalconfig.cpp +++ b/src/terminalconfig.cpp @@ -8,7 +8,7 @@ #include "properties.h" #include "termwidget.h" -TerminalConfig::TerminalConfig(const QString & wdir, const QString & shell) +TerminalConfig::TerminalConfig(const QString & wdir, const QStringList & shell) { m_workingDirectory = wdir; m_shell = shell; @@ -32,20 +32,20 @@ QString TerminalConfig::getWorkingDirectory() return QTerminalApp::Instance()->getWorkingDirectory(); } -QString TerminalConfig::getShell() +QStringList TerminalConfig::getShell() { - if (!m_shell.trimmed().isEmpty()) - return m_shell.trimmed(); - if (!Properties::Instance()->shell.trimmed().isEmpty()) - return Properties::Instance()->shell.trimmed(); + if (!m_shell.isEmpty()) + return m_shell; + if (!Properties::Instance()->shell.isEmpty()) + return Properties::Instance()->shell; QByteArray envShell = qgetenv("SHELL"); if (envShell.constData() != nullptr) { QString shellString = QString::fromLocal8Bit(envShell).trimmed(); if (!shellString.isEmpty()) - return shellString; + return QStringList{shellString}; } - return QString(); + return QStringList(); } void TerminalConfig::setWorkingDirectory(const QString &val) @@ -53,7 +53,7 @@ void TerminalConfig::setWorkingDirectory(const QString &val) m_workingDirectory = val; } -void TerminalConfig::setShell(const QString &val) +void TerminalConfig::setShell(const QStringList &val) { m_shell = val; } @@ -87,16 +87,23 @@ static QString variantToString(const QVariant& variant, QString &defaultVal) return defaultVal; } +static QStringList variantToStringList(const QVariant& variant, QStringList &defaultVal) +{ + if (variant.type() == QVariant::StringList) + return qvariant_cast(variant); + return defaultVal; +} + TerminalConfig TerminalConfig::fromDbus(const QHash &termArgs) { QString wdir = QString(); - QString shell(Properties::Instance()->shell); + QStringList shell(Properties::Instance()->shell); if (termArgs.contains(QLatin1String(DBUS_ARG_WORKDIR))) { wdir = variantToString(termArgs[QLatin1String(DBUS_ARG_WORKDIR)], wdir); } if (termArgs.contains(QLatin1String(DBUS_ARG_SHELL))) { - shell = variantToString(termArgs[QLatin1String(DBUS_ARG_SHELL)], shell); + shell = variantToStringList(termArgs[QLatin1String(DBUS_ARG_SHELL)], shell); } return TerminalConfig(wdir, shell); } diff --git a/src/terminalconfig.h b/src/terminalconfig.h index 5823fae8..4afd18fc 100644 --- a/src/terminalconfig.h +++ b/src/terminalconfig.h @@ -11,15 +11,15 @@ class TermWidget; class TerminalConfig { public: - TerminalConfig(const QString & wdir, const QString & shell); + TerminalConfig(const QString & wdir, const QStringList & shell); TerminalConfig(const TerminalConfig &cfg); TerminalConfig(); QString getWorkingDirectory(); - QString getShell(); + QStringList getShell(); void setWorkingDirectory(const QString &val); - void setShell(const QString &val); + void setShell(const QStringList &val); void provideCurrentDirectory(const QString &val); #ifdef HAVE_QDBUS @@ -29,10 +29,10 @@ class TerminalConfig private: - // True when + // True when QString m_currentDirectory; QString m_workingDirectory; - QString m_shell; + QStringList m_shell; }; -#endif \ No newline at end of file +#endif diff --git a/src/termwidget.cpp b/src/termwidget.cpp index f2c48613..f4536148 100644 --- a/src/termwidget.cpp +++ b/src/termwidget.cpp @@ -55,16 +55,13 @@ TermWidgetImpl::TermWidgetImpl(TerminalConfig &cfg, QWidget * parent) setWorkingDirectory(cfg.getWorkingDirectory()); - QString shell = cfg.getShell(); + QStringList shell = cfg.getShell(); if (!shell.isEmpty()) { - //qDebug() << "Shell program:" << shell; - QStringList parts = shell.split(QRegExp(QStringLiteral("\\s+")), Qt::SkipEmptyParts); - //qDebug() << parts; - setShellProgram(parts.at(0)); - parts.removeAt(0); - if (parts.count()) - setArgs(parts); + setShellProgram(shell.at(0)); + shell.removeAt(0); + if (!shell.isEmpty()) + setArgs(shell); } setMotionAfterPasting(Properties::Instance()->m_motionAfterPaste);