Skip to content

Commit

Permalink
Fixed command parsing with -e option
Browse files Browse the repository at this point in the history
By using `QStringList` instead of `QString`.

Fixes #335 and fixes #665
  • Loading branch information
tsujan authored and Chih-Hsuan Yen committed Aug 29, 2022
1 parent 60a2a52 commit bd3ff3d
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 30 deletions.
52 changes: 48 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"('|(?<!\\)(\\{2})*(\s|")|\z)"));
const QRegularExpression doubleQuote(QString::fromLatin1(R"((?<!\\)(\\{2})*")"));
const QRegularExpression escapedSpace(QString::fromLatin1(R"(\\(\\{2})*\s)"));
const QRegularExpression singleQuote(QStringLiteral("'"));

QStringList list;
QRegularExpressionMatch match;
int index = 0;
int nextIndex;
while((nextIndex = str.indexOf(separator, index, &match)) != -1)
{
if (nextIndex > 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;
Expand All @@ -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':
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Properties
QPoint mainWindowPosition;
QByteArray mainWindowState;
//ShortcutMap shortcuts;
QString shell;
QStringList shell;
QFont font;
QString colorScheme;
QString guiStyle;
Expand Down
29 changes: 18 additions & 11 deletions src/terminalconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,28 +32,28 @@ 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)
{
m_workingDirectory = val;
}

void TerminalConfig::setShell(const QString &val)
void TerminalConfig::setShell(const QStringList &val)
{
m_shell = val;
}
Expand Down Expand Up @@ -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<QStringList>(variant);
return defaultVal;
}

TerminalConfig TerminalConfig::fromDbus(const QHash<QString,QVariant> &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);
}
Expand Down
12 changes: 6 additions & 6 deletions src/terminalconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -29,10 +29,10 @@ class TerminalConfig


private:
// True when
// True when
QString m_currentDirectory;
QString m_workingDirectory;
QString m_shell;
QStringList m_shell;
};

#endif
#endif
13 changes: 5 additions & 8 deletions src/termwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit bd3ff3d

Please sign in to comment.