From 9d877f2ac74d19a083a5b157248cb70337885d44 Mon Sep 17 00:00:00 2001 From: reionwong Date: Sun, 12 Sep 2021 20:08:03 +0800 Subject: [PATCH] Fix working directory --- qmltermwidget/lib/Session.cpp | 19 +++- qmltermwidget/lib/Session.h | 2 + qmltermwidget/lib/ShellCommand.cpp | 176 +++++++++++++++-------------- qmltermwidget/lib/ShellCommand.h | 52 +++------ src/qml/Terminal.qml | 2 +- src/qml/main.qml | 2 +- 6 files changed, 130 insertions(+), 123 deletions(-) diff --git a/qmltermwidget/lib/Session.cpp b/qmltermwidget/lib/Session.cpp index 3776fc5..5dff315 100644 --- a/qmltermwidget/lib/Session.cpp +++ b/qmltermwidget/lib/Session.cpp @@ -135,6 +135,21 @@ WId Session::windowId() const return 0; } +QString Session::validDirectory(const QString &dir) const +{ + QString validDir = dir; + if (validDir.isEmpty()) { + validDir = QDir::currentPath(); + } + + const QFileInfo fi(validDir); + if (!fi.exists() || !fi.isDir()) { + validDir = QDir::homePath(); + } + + return validDir; +} + void Session::setDarkBackground(bool darkBackground) { _hasDarkBackground = darkBackground; @@ -157,10 +172,12 @@ void Session::setProgram(const QString & program) { _program = ShellCommand::expand(program); } + void Session::setInitialWorkingDirectory(const QString & dir) { - _initialWorkingDir = ShellCommand::expand(dir); + _initialWorkingDir = validDirectory(ShellCommand::expand(dir)); } + void Session::setArguments(const QStringList & arguments) { _arguments = ShellCommand::expand(arguments); diff --git a/qmltermwidget/lib/Session.h b/qmltermwidget/lib/Session.h index b577d69..56a4007 100644 --- a/qmltermwidget/lib/Session.h +++ b/qmltermwidget/lib/Session.h @@ -524,6 +524,8 @@ private: bool updateForegroundProcessInfo(); WId windowId() const; + QString validDirectory(const QString &dir) const; + int _uniqueIdentifier; Pty *_shellProcess; diff --git a/qmltermwidget/lib/ShellCommand.cpp b/qmltermwidget/lib/ShellCommand.cpp index 5b86537..a4b9da0 100644 --- a/qmltermwidget/lib/ShellCommand.cpp +++ b/qmltermwidget/lib/ShellCommand.cpp @@ -1,38 +1,20 @@ /* - Copyright (C) 2007 by Robert Knight - - Rewritten for QT4 by e_k , Copyright (C)2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. + SPDX-FileCopyrightText: 2007-2008 Robert Knight + SPDX-License-Identifier: GPL-2.0-or-later */ // Own #include "ShellCommand.h" -//some versions of gcc(4.3) require explicit include +// some versions of gcc(4.3) require explicit include #include +// Qt +#include -using namespace Konsole; - -// expands environment variables in 'text' -// function copied from kdelibs/kio/kio/kurlcompletion.cpp -static bool expandEnv(QString & text); +using Konsole::ShellCommand; -ShellCommand::ShellCommand(const QString & fullCommand) +ShellCommand::ShellCommand(const QString &fullCommand) { bool inQuotes = false; @@ -58,111 +40,133 @@ ShellCommand::ShellCommand(const QString & fullCommand) } } } -ShellCommand::ShellCommand(const QString & command , const QStringList & arguments) + +ShellCommand::ShellCommand(const QString &aCommand, const QStringList &aArguments) { - _arguments = arguments; + _arguments = aArguments; - if ( !_arguments.isEmpty() ) { - _arguments[0] = command; + if (!_arguments.isEmpty()) { + _arguments[0] = aCommand; } } + QString ShellCommand::fullCommand() const { - return _arguments.join(QLatin1Char(' ')); + QStringList quotedArgs(_arguments); + for (int i = 0; i < quotedArgs.count(); i++) { + QString arg = quotedArgs.at(i); + bool hasSpace = false; + for (int j = 0; j < arg.count(); j++) { + if (arg[j].isSpace()) { + hasSpace = true; + } + } + if (hasSpace) { + quotedArgs[i] = QLatin1Char('\"') + arg + QLatin1Char('\"'); + } + } + return quotedArgs.join(QLatin1Char(' ')); } + QString ShellCommand::command() const { - if ( !_arguments.isEmpty() ) { + if (!_arguments.isEmpty()) { return _arguments[0]; - } else { - return QString(); } + return QString(); } + QStringList ShellCommand::arguments() const { return _arguments; } -bool ShellCommand::isRootCommand() const -{ - Q_ASSERT(0); // not implemented yet - return false; -} -bool ShellCommand::isAvailable() const -{ - Q_ASSERT(0); // not implemented yet - return false; -} -QStringList ShellCommand::expand(const QStringList & items) + +QStringList ShellCommand::expand(const QStringList &items) { QStringList result; + result.reserve(items.size()); - for(const QString &item : items) { + for (const QString &item : items) { result << expand(item); } return result; } -QString ShellCommand::expand(const QString & text) + +QString ShellCommand::expand(const QString &text) { QString result = text; expandEnv(result); return result; } +bool ShellCommand::isValidEnvCharacter(const QChar &ch) +{ + const ushort code = ch.unicode(); + return isValidLeadingEnvCharacter(ch) || ('0' <= code && code <= '9'); +} + +bool ShellCommand::isValidLeadingEnvCharacter(const QChar &ch) +{ + const ushort code = ch.unicode(); + return (code == '_') || ('A' <= code && code <= 'Z'); +} + /* * expandEnv * * Expand environment variables in text. Escaped '$' characters are ignored. * Return true if any variables were expanded */ -static bool expandEnv( QString & text ) +bool ShellCommand::expandEnv(QString &text) { - // Find all environment variables beginning with '$' - // - int pos = 0; + // Current path + if (text == "$PWD") { + text = QDir::currentPath(); + return true; + } + + const QLatin1Char dollarChar('$'); + const QLatin1Char backslashChar('\\'); + int dollarPos = 0; bool expanded = false; - while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) { + // find and expand all environment variables beginning with '$' + while ((dollarPos = text.indexOf(dollarChar, dollarPos)) != -1) { + // if '$' is the last character, there is no way of expanding + if (dollarPos == text.length() - 1) { + break; + } - // Skip escaped '$' - // - if ( pos > 0 && text.at(pos-1) == QLatin1Char('\\') ) { - pos++; + // skip escaped '$' + if (dollarPos > 0 && text.at(dollarPos - 1) == backslashChar) { + dollarPos++; + continue; } - // Variable found => expand - // - else { - // Find the end of the variable = next '/' or ' ' - // - int pos2 = text.indexOf( QLatin1Char(' '), pos+1 ); - int pos_tmp = text.indexOf( QLatin1Char('/'), pos+1 ); - - if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) { - pos2 = pos_tmp; - } - if ( pos2 == -1 ) { - pos2 = text.length(); - } + // if '$' is followed by an invalid leading character, skip this '$' + if (!isValidLeadingEnvCharacter(text.at(dollarPos + 1))) { + dollarPos++; + continue; + } - // Replace if the variable is terminated by '/' or ' ' - // and defined - // - if ( pos2 >= 0 ) { - int len = pos2 - pos; - QString key = text.mid( pos+1, len-1); - QString value = - QString::fromLocal8Bit( qgetenv(key.toLocal8Bit().constData()) ); - - if ( !value.isEmpty() ) { - expanded = true; - text.replace( pos, len, value ); - pos = pos + value.length(); - } else { - pos = pos2; - } - } + int endPos = dollarPos + 1; + Q_ASSERT(endPos < text.length()); + while (endPos < text.length() && isValidEnvCharacter(text.at(endPos))) { + endPos++; + } + + const int len = endPos - dollarPos; + const QString key = text.mid(dollarPos + 1, len - 1); + const QString value = QString::fromLocal8Bit(qgetenv(key.toLocal8Bit().constData())); + + if (!value.isEmpty()) { + text.replace(dollarPos, len, value); + expanded = true; + dollarPos = dollarPos + value.length(); + } else { + dollarPos = endPos; } } diff --git a/qmltermwidget/lib/ShellCommand.h b/qmltermwidget/lib/ShellCommand.h index 3a5804a..6a8118d 100644 --- a/qmltermwidget/lib/ShellCommand.h +++ b/qmltermwidget/lib/ShellCommand.h @@ -1,22 +1,6 @@ /* - Copyright (C) 2007 by Robert Knight - - Rewritten for QT4 by e_k , Copyright (C)2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. + SPDX-FileCopyrightText: 2007-2008 Robert Knight + SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef SHELLCOMMAND_H @@ -25,8 +9,8 @@ // Qt #include -namespace Konsole { - +namespace Konsole +{ /** * A class to parse and extract information about shell commands. * @@ -48,18 +32,19 @@ namespace Konsole { * * */ -class ShellCommand { +class ShellCommand +{ public: /** * Constructs a ShellCommand from a command line. * - * @param fullCommand The command line to parse. + * @param aCommand The command line to parse. */ - ShellCommand(const QString & fullCommand); + explicit ShellCommand(const QString &aCommand); /** - * Constructs a ShellCommand with the specified @p command and @p arguments. + * Constructs a ShellCommand with the specified @p aCommand and @p aArguments. */ - ShellCommand(const QString & command , const QStringList & arguments); + ShellCommand(const QString &aCommand, const QStringList &aArguments); /** Returns the command. */ QString command() const; @@ -71,22 +56,21 @@ public: */ QString fullCommand() const; - /** Returns true if this is a root command. */ - bool isRootCommand() const; - /** Returns true if the program specified by @p command() exists. */ - bool isAvailable() const; - /** Expands environment variables in @p text .*/ - static QString expand(const QString & text); + static QString expand(const QString &text); /** Expands environment variables in each string in @p list. */ - static QStringList expand(const QStringList & items); + static QStringList expand(const QStringList &items); + + static bool isValidEnvCharacter(const QChar &ch); + + static bool isValidLeadingEnvCharacter(const QChar &ch); private: + static bool expandEnv(QString &text); + QStringList _arguments; }; - } #endif // SHELLCOMMAND_H - diff --git a/src/qml/Terminal.qml b/src/qml/Terminal.qml index be01560..4a0082c 100644 --- a/src/qml/Terminal.qml +++ b/src/qml/Terminal.qml @@ -44,7 +44,7 @@ Page { signal keyPressed(var event) signal terminalClosed() - property string path + property string path: "$PWD" property alias terminal: _terminal readonly property QMLTermSession session: _session diff --git a/src/qml/main.qml b/src/qml/main.qml index 982aa88..cacc120 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -202,7 +202,7 @@ FishUI.Window { } Component.onCompleted: { - openTab("$HOME") + openTab("$PWD") } function openNewTab() {