-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Improve OSC 9;9 parsing logic & add tests #8934
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -474,7 +474,19 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept | |
{ | ||
if (parts.size() >= 2) | ||
{ | ||
return _terminalApi.SetWorkingDirectory(til::at(parts, 1)); | ||
const auto path = til::at(parts, 1); | ||
// The path should be surrounded with '"' according to the documentation of ConEmu. | ||
// An example: 9;"D:/" | ||
if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3) | ||
{ | ||
return _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2)); | ||
} | ||
else | ||
{ | ||
// If we fail to find the surrounding quotation marks, we'll give the path a try anyway. | ||
// ConEmu also does this. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is why I thought I was doing it right. ConEmu won't blame users for forgetting |
||
return _terminalApi.SetWorkingDirectory(path); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ namespace TerminalCoreUnitTests | |
TEST_METHOD(AddHyperlinkCustomIdDifferentUri); | ||
|
||
TEST_METHOD(SetTaskbarProgress); | ||
TEST_METHOD(SetWorkingDirectory); | ||
}; | ||
}; | ||
|
||
|
@@ -388,3 +389,59 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress() | |
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1)); | ||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80)); | ||
} | ||
|
||
void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory() | ||
{ | ||
Terminal term; | ||
DummyRenderTarget emptyRT; | ||
term.Create({ 100, 100 }, 0, emptyRT); | ||
|
||
auto& stateMachine = *(term._stateMachine); | ||
|
||
// Test setting working directory using OSC 9;9 | ||
// Initial CWD should be empty | ||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); | ||
|
||
// Invalid sequences should not change CWD | ||
stateMachine.ProcessString(L"\x1b]9;9\x9c"); | ||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9\"\x9c"); | ||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x9c"); | ||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty()); | ||
|
||
// Valid sequences should change CWD | ||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\"); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files"); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文"); | ||
|
||
// Test OSC 9;9 sequences without quotation marks | ||
stateMachine.ProcessString(L"\x1b]9;9;C:\\\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\"); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files"); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文"); | ||
|
||
// These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these. | ||
stateMachine.ProcessString(L"\x1b]9;9;\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the future I think we should consider this an invalid sequence, especially after we figure out the way to identify WSL profiles and make OSC 7 work. Right now I'm not sure how to do with it. |
||
|
||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\""); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\""); | ||
|
||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x9c"); | ||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\""); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this is actually making OSC 9;9 even more Win32-specific. Since
"
is an invalid dir name on WIndows, but is a valid dir name on Linux.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be specific, when we see a path provided by OSC 9;9 , for example,
"D:"
on Windows, the actual path is guaranteed to beD:
because neither"
nor:
is valid character in dir names on Windows. But on Linux, you can create a dir that's literally named"D:"
bymkdir "\"D:\""
.I can't blame ConEmu for designing the sequence this way since it's a Win32 native application at the very beginning. Just to point it out.
Also CC @Maximus5 for awareness.
Update: on second thought, maybe I'm a bit paranoid about this. The CWD should always be an absolute path, right? There's almost no chance an absolute path would both start and end with
"
to cause the confusion. I sincerely hope the confusion I described only exist in my imagination.