Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add skeleton code for OSC 7 #8921

Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ horiz
HORZ
hostable
hostlib
hostname
HPA
HPAINTBUFFER
HPCON
Expand Down
1 change: 1 addition & 0 deletions .github/actions/spelling/patterns/patterns.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
https://freedesktop.org/[-a-zA-Z0-9?&=\/_#]*
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}[Uu]?[Ll]{0,2}\b
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,12 @@ bool Terminal::SetTaskbarProgress(const size_t state, const size_t progress) noe
return true;
}

// Method Description:
// - Updates the current working directory.
// Arguments:
// - uri: The new working directory. Note that the uri is expected to be valid on Windows.
// Return Value:
// - true
bool Terminal::SetWorkingDirectory(std::wstring_view uri) noexcept
{
_workingDirectory = uri;
Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,18 @@ bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param) noexcept
return _ModeParamsHelper(param, false);
}

// Method Description:
// - Updates the current working directory.
// Arguments:
// - hostname: The hostname
// - path: The path. Note that the path may not be valid on Windows.
// Return Value:
// - true
bool TerminalDispatch::SetWorkingDirectory(const std::wstring_view /*hostname*/, const std::wstring_view /*path*/) noexcept
{
return true;
}

// Method Description:
// - Start a hyperlink
// Arguments:
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc
bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECSET
bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECRST

bool SetWorkingDirectory(const std::wstring_view hostname, const std::wstring_view path) noexcept override;

bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) noexcept override;
bool EndHyperlink() noexcept override;

Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
const VTParameter parameter1,
const VTParameter parameter2) = 0;

virtual bool SetWorkingDirectory(const std::wstring_view hostname, const std::wstring_view path) = 0;

virtual bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) = 0;
virtual bool EndHyperlink() = 0;

Expand Down
10 changes: 10 additions & 0 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2374,6 +2374,16 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy
return success;
}

// Method Description:
// - Ascribes to the ITermDispatch interface
// - Not actually used in conhost
// Return Value:
// - false (so that the command gets flushed to terminal)
bool AdaptDispatch::SetWorkingDirectory(const std::wstring_view /*hostname*/, const std::wstring_view /*path*/) noexcept
{
return false;
}

// Method Description:
// - Starts a hyperlink
// Arguments:
Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/adaptDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ namespace Microsoft::Console::VirtualTerminal
const VTParameter parameter1,
const VTParameter parameter2) override; // DTTERM_WindowManipulation

bool SetWorkingDirectory(const std::wstring_view hostname, const std::wstring_view path) noexcept override;

bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override;
bool EndHyperlink() override;

Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/termDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons
const VTParameter /*parameter1*/,
const VTParameter /*parameter2*/) noexcept override { return false; }

bool SetWorkingDirectory(const std::wstring_view /*hostname*/, const std::wstring_view /*path*/) noexcept override { return false; }

bool AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) noexcept override { return false; }
bool EndHyperlink() noexcept override { return false; }

Expand Down
56 changes: 56 additions & 0 deletions src/terminal/parser/OutputStateMachineEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "ascii.hpp"
#include "../../types/inc/utils.hpp"

#include <Shlwapi.h>

using namespace Microsoft::Console;
using namespace Microsoft::Console::VirtualTerminal;

Expand Down Expand Up @@ -741,6 +743,17 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCRCC);
break;
}
case OscActionCodes::SetWorkingDirectory:
{
std::wstring hostname;
std::wstring path;
success = _ParseFileUri(string, hostname, path);
if (success && !path.empty())
{
success = _dispatch->SetWorkingDirectory(hostname, path);
}
break;
}
case OscActionCodes::Hyperlink:
{
std::wstring params;
Expand Down Expand Up @@ -907,6 +920,49 @@ try
}
CATCH_LOG_RETURN_FALSE()

#pragma warning(push)
#pragma warning(disable : 26477) // Suppress USE_NULLPTR_NOT_CONSTANT

// Routine Description:
// - Given a file URI string, attempts to parse the URI encoded.
// The spec of the file URI is https://freedesktop.org/wiki/Specifications/file-uri-spec/.
// The file URIs are of the form:
// file://<hostname>/<path>
bool OutputStateMachineEngine::_ParseFileUri(const std::wstring_view string,
std::wstring& hostname,
std::wstring& path) const
{
if (string.size() < 8)
{
return false;
}

const auto prefix = string.substr(0, 7);
if (!prefix.compare(L"file://") == 0)
{
// We don't support URI format other than "file://".
return false;
}

size_t current = 7;
size_t nextSlash = string.find(L"/", current);
if (nextSlash == std::wstring::npos)
{
// Invalid URI. Ignore it.
return false;
}

hostname = string.substr(current, nextSlash - current);
current = nextSlash;
std::wstring _path = std::wstring(string.substr(current, std::wstring::npos));
UrlUnescapeInPlace(path.data(), 0);
path = _path;

return true;
}

#pragma warning(pop)

#pragma warning(push)
#pragma warning(disable : 26445) // Suppress lifetime check for a reference to gsl::span or std::string_view

Expand Down
5 changes: 5 additions & 0 deletions src/terminal/parser/OutputStateMachineEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ namespace Microsoft::Console::VirtualTerminal
SetWindowTitle = 2,
SetWindowProperty = 3, // Not implemented
SetColor = 4,
SetWorkingDirectory = 7, // No functionality is implemented
Hyperlink = 8,
ConEmuAction = 9,
SetForegroundColor = 10,
Expand All @@ -185,6 +186,10 @@ namespace Microsoft::Console::VirtualTerminal
std::wstring& content,
bool& queryClipboard) const noexcept;

bool _ParseFileUri(const std::wstring_view string,
std::wstring& hostname,
std::wstring& path) const;

static constexpr std::wstring_view hyperlinkIDParameter{ L"id=" };
bool _ParseHyperlink(const std::wstring_view string,
std::wstring& params,
Expand Down
48 changes: 48 additions & 0 deletions src/terminal/parser/ut_parser/OutputEngineTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,13 @@ class StatefulDispatch final : public TermDispatch
return true;
}

bool SetWorkingDirectory(const std::wstring_view hostname, const std::wstring_view path) noexcept override
{
_cwdHostname = hostname;
_cwdPath = path;
return true;
}

bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept override
{
_hyperlinkMode = true;
Expand Down Expand Up @@ -1539,6 +1546,8 @@ class StatefulDispatch final : public TermDispatch
bool _setDefaultCursorColor;
DWORD _defaultCursorColor;
bool _setColorTableEntry;
std::wstring _cwdHostname;
std::wstring _cwdPath;
bool _hyperlinkMode;
std::wstring _copyContent;
std::wstring _uri;
Expand Down Expand Up @@ -3298,6 +3307,45 @@ class StateMachineExternalTest final
pDispatch->ClearState();
}

TEST_METHOD(TestOsc7SetWorkingDirectory)
{
auto dispatch = std::make_unique<StatefulDispatch>();
auto pDispatch = dispatch.get();
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
StateMachine mach(std::move(engine));

// Initial CWD should be empty
VERIFY_IS_TRUE(pDispatch->_cwdHostname.empty());
VERIFY_IS_TRUE(pDispatch->_cwdPath.empty());

// Try Unix paths
mach.ProcessString(L"\x1b]7;file://localhost/usr/local/bin\x9c");
VERIFY_ARE_EQUAL(L"localhost", pDispatch->_cwdHostname);
VERIFY_ARE_EQUAL(L"/usr/local/bin", pDispatch->_cwdPath);

mach.ProcessString(L"\x1b]7;file:///usr/local/bin\x9c");
VERIFY_IS_TRUE(pDispatch->_cwdHostname.empty());
VERIFY_ARE_EQUAL(L"/usr/local/bin", pDispatch->_cwdPath);

// Try Windows paths
mach.ProcessString(L"\x1b]7;file://WIN-DESKTOP-1/C:/\x9c");
VERIFY_ARE_EQUAL(L"WIN-DESKTOP-1", pDispatch->_cwdHostname);
VERIFY_ARE_EQUAL(L"/C:/", pDispatch->_cwdPath);

mach.ProcessString(L"\x1b]7;file:///C:/\x9c");
VERIFY_IS_TRUE(pDispatch->_cwdHostname.empty());
VERIFY_ARE_EQUAL(L"/C:/", pDispatch->_cwdPath);

// Try Cygwin paths
mach.ProcessString(L"\x1b]7;file://WIN-DESKTOP-1/c\x9c");
VERIFY_ARE_EQUAL(L"WIN-DESKTOP-1", pDispatch->_cwdHostname);
VERIFY_ARE_EQUAL(L"/c", pDispatch->_cwdPath);

mach.ProcessString(L"\x1b]7;file:///c\x9c");
VERIFY_IS_TRUE(pDispatch->_cwdHostname.empty());
VERIFY_ARE_EQUAL(L"/c", pDispatch->_cwdPath);
}

TEST_METHOD(TestAddHyperlink)
{
auto dispatch = std::make_unique<StatefulDispatch>();
Expand Down