diff options
author | Marcus Tillmanns <[email protected]> | 2023-03-10 13:55:17 +0100 |
---|---|---|
committer | Marcus Tillmanns <[email protected]> | 2023-03-16 06:08:09 +0000 |
commit | bd52e53dbfa7641098313edd56d885df69916f9f (patch) | |
tree | 161502368e1ebabb785bd9db668d028e65005fcd /src/plugins/terminal/shellintegration.cpp | |
parent | 3507229a007e3fd5f004a94f4c3857518ab1c9df (diff) |
Terminal: Add shell integration
Change-Id: Ic1e226b56f0103e5a6e7764073ab7ab241b67baa
Reviewed-by: Cristian Adam <[email protected]>
Diffstat (limited to 'src/plugins/terminal/shellintegration.cpp')
-rw-r--r-- | src/plugins/terminal/shellintegration.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/plugins/terminal/shellintegration.cpp b/src/plugins/terminal/shellintegration.cpp new file mode 100644 index 00000000000..fd4c1364696 --- /dev/null +++ b/src/plugins/terminal/shellintegration.cpp @@ -0,0 +1,143 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "shellintegration.h" + +#include <utils/environment.h> +#include <utils/filepath.h> +#include <utils/stringutils.h> + +#include <QLoggingCategory> + +Q_LOGGING_CATEGORY(integrationLog, "qtc.terminal.shellintegration", QtWarningMsg) + +using namespace Utils; + +namespace Terminal { + +struct FileToCopy +{ + FilePath source; + QString destName; +}; + +// clang-format off +struct +{ + struct + { + FilePath rcFile{":/terminal/shellintegrations/shellintegration-bash.sh"}; + } bash; + struct + { + QList<FileToCopy> files{ + {":/terminal/shellintegrations/shellintegration-env.zsh", ".zshenv"}, + {":/terminal/shellintegrations/shellintegration-login.zsh", ".zlogin"}, + {":/terminal/shellintegrations/shellintegration-profile.zsh", ".zprofile"}, + {":/terminal/shellintegrations/shellintegration-rc.zsh", ".zshrc"} + }; + } zsh; + struct + { + FilePath script{":/terminal/shellintegrations/shellintegration.ps1"}; + } pwsh; + +} filesToCopy; +// clang-format on + +bool ShellIntegration::canIntegrate(const Utils::CommandLine &cmdLine) +{ + if (cmdLine.executable().needsDevice()) + return false; // TODO: Allow integration for remote shells + + if (!cmdLine.arguments().isEmpty()) + return false; + + if (cmdLine.executable().baseName() == "bash") + return true; + + if (cmdLine.executable().baseName() == "zsh") + return true; + + if (cmdLine.executable().baseName() == "pwsh" + || cmdLine.executable().baseName() == "powershell") { + return true; + } + + return false; +} + +void ShellIntegration::onOsc(int cmd, const VTermStringFragment &fragment) +{ + QString d = QString::fromLocal8Bit(fragment.str, fragment.len); + const auto [command, data] = Utils::splitAtFirst(d, ';'); + + if (cmd == 1337) { + const auto [key, value] = Utils::splitAtFirst(command, '='); + if (key == QStringView(u"CurrentDir")) + emit currentDirChanged(FilePath::fromUserInput(value.toString()).path()); + + } else if (cmd == 7) { + emit currentDirChanged(FilePath::fromUserInput(d).path()); + } else if (cmd == 133) { + qCDebug(integrationLog) << "OSC 133:" << data; + } else if (cmd == 633 && command.length() == 1) { + if (command[0] == 'E') { + CommandLine cmdLine = CommandLine::fromUserInput(data.toString()); + emit commandChanged(cmdLine); + } else if (command[0] == 'D') { + emit commandChanged({}); + } else if (command[0] == 'P') { + const auto [key, value] = Utils::splitAtFirst(data, '='); + if (key == QStringView(u"Cwd")) + emit currentDirChanged(value.toString()); + } + } +} + +void ShellIntegration::prepareProcess(Utils::QtcProcess &process) +{ + Environment env = process.environment().hasChanges() ? process.environment() + : Environment::systemEnvironment(); + CommandLine cmd = process.commandLine(); + + if (!canIntegrate(cmd)) + return; + + env.set("VSCODE_INJECTION", "1"); + + if (cmd.executable().baseName() == "bash") { + const FilePath rcPath = filesToCopy.bash.rcFile; + const FilePath tmpRc = FilePath::fromUserInput( + m_tempDir.filePath(filesToCopy.bash.rcFile.fileName())); + rcPath.copyFile(tmpRc); + + cmd.addArgs({"--init-file", tmpRc.nativePath()}); + } else if (cmd.executable().baseName() == "zsh") { + for (const FileToCopy &file : filesToCopy.zsh.files) { + const auto copyResult = file.source.copyFile( + FilePath::fromUserInput(m_tempDir.filePath(file.destName))); + QTC_ASSERT_EXPECTED(copyResult, return); + } + + const Utils::FilePath originalZdotDir = FilePath::fromUserInput( + env.value_or("ZDOTDIR", QDir::homePath())); + + env.set("ZDOTDIR", m_tempDir.path()); + env.set("USER_ZDOTDIR", originalZdotDir.nativePath()); + } else if (cmd.executable().baseName() == "pwsh" + || cmd.executable().baseName() == "powershell") { + const FilePath rcPath = filesToCopy.pwsh.script; + const FilePath tmpRc = FilePath::fromUserInput( + m_tempDir.filePath(filesToCopy.pwsh.script.fileName())); + rcPath.copyFile(tmpRc); + + cmd.addArgs(QString("-noexit -command try { . \"%1\" } catch {}{1}").arg(tmpRc.nativePath()), + CommandLine::Raw); + } + + process.setCommand(cmd); + process.setEnvironment(env); +} + +} // namespace Terminal |