Skip to content

Commit 4ce79d7

Browse files
authored
Implement OSC 7 for setting the CWD (#20019)
This adds support for OSC 7 which is the same as OSC 9;9 but using file URIs. As per the previous discussion in #8214, the problem is that WSL shells emit URIs that can't work because the hostname in the URI translates to an UNC path with an non-existing hostname. In my opinion this doesn't deter the fact though that OSC 7 works just fine for a native Windows application. In the future we should consider trying to detect WSL file URIs and translating it to the `--cd` argument for `wsl.exe`. All of the heavy lifting for parsing the URI is done by `PathCreateFromUrlW`. It just had to be plugged into the OSC 9;9 code. Closes #3158 ## Validation Steps Performed * Launch fish-shell in WSL * Duplicate tab works ✅ * (And because it doesn't work without using `IsValidDirectory` I know that OSC 7 works ✅)
1 parent 69e4590 commit 4ce79d7

File tree

16 files changed

+46
-28
lines changed

16 files changed

+46
-28
lines changed

src/cascadia/TerminalApp/AppActionHandlers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,7 @@ namespace winrt::TerminalApp::implementation
14751475
WI_IsAnyFlagSet(source, SuggestionsSource::CommandHistory | SuggestionsSource::QuickFixes);
14761476
if (const auto& control{ _GetActiveControl() })
14771477
{
1478-
currentWorkingDirectory = control.CurrentWorkingDirectory();
1478+
currentWorkingDirectory = control.WorkingDirectory();
14791479

14801480
if (shouldGetContext)
14811481
{

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,8 +1600,7 @@ namespace winrt::TerminalApp::implementation
16001600

16011601
// Replace the Starting directory with the CWD, if given
16021602
const auto workingDirectory = control.WorkingDirectory();
1603-
const auto validWorkingDirectory = !workingDirectory.empty();
1604-
if (validWorkingDirectory)
1603+
if (Utils::IsValidDirectory(workingDirectory.c_str()))
16051604
{
16061605
controlSettings.DefaultSettings()->StartingDirectory(workingDirectory);
16071606
}
@@ -3555,8 +3554,7 @@ namespace winrt::TerminalApp::implementation
35553554
profile = GetClosestProfileForDuplicationOfProfile(profile);
35563555
controlSettings = Settings::TerminalSettings::CreateWithProfile(_settings, profile);
35573556
const auto workingDirectory = tabImpl->GetActiveTerminalControl().WorkingDirectory();
3558-
const auto validWorkingDirectory = !workingDirectory.empty();
3559-
if (validWorkingDirectory)
3557+
if (Utils::IsValidDirectory(workingDirectory.c_str()))
35603558
{
35613559
controlSettings.DefaultSettings()->StartingDirectory(workingDirectory);
35623560
}

src/cascadia/TerminalApp/TerminalPaneContent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ namespace winrt::TerminalApp::implementation
102102

103103
args.Profile(::Microsoft::Console::Utils::GuidToString(_profile.Guid()));
104104
// If we know the user's working directory use it instead of the profile.
105-
if (const auto dir = _control.WorkingDirectory(); !dir.empty())
105+
if (const auto dir = _control.WorkingDirectory(); ::Microsoft::Console::Utils::IsValidDirectory(dir.c_str()))
106106
{
107107
args.StartingDirectory(dir);
108108
}

src/cascadia/TerminalControl/ControlCore.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,11 +2420,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
24202420
return *context;
24212421
}
24222422

2423-
winrt::hstring ControlCore::CurrentWorkingDirectory() const
2424-
{
2425-
return winrt::hstring{ _terminal->GetWorkingDirectory() };
2426-
}
2427-
24282423
bool ControlCore::QuickFixesAvailable() const noexcept
24292424
{
24302425
return _cachedQuickFixes && _cachedQuickFixes.Size() > 0;

src/cascadia/TerminalControl/ControlCore.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
191191

192192
void ContextMenuSelectCommand();
193193
void ContextMenuSelectOutput();
194-
195-
winrt::hstring CurrentWorkingDirectory() const;
196194
#pragma endregion
197195

198196
#pragma region ITerminalInput

src/cascadia/TerminalControl/ICoreState.idl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,5 @@ namespace Microsoft.Terminal.Control
6060
void SelectOutput(Boolean goUp);
6161
IVector<ScrollMark> ScrollMarks { get; };
6262

63-
String CurrentWorkingDirectory { get; };
64-
6563
};
6664
}

src/cascadia/TerminalControl/TermControl.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,10 +3719,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
37193719
{
37203720
return _core.CommandHistory();
37213721
}
3722-
winrt::hstring TermControl::CurrentWorkingDirectory() const
3723-
{
3724-
return _core.CurrentWorkingDirectory();
3725-
}
37263722

37273723
void TermControl::UpdateWinGetSuggestions(Windows::Foundation::Collections::IVector<hstring> suggestions)
37283724
{

src/cascadia/TerminalControl/TermControl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
117117
void ScrollToMark(const Control::ScrollToMarkDirection& direction);
118118
void SelectCommand(const bool goUp);
119119
void SelectOutput(const bool goUp);
120-
121-
winrt::hstring CurrentWorkingDirectory() const;
122120
#pragma endregion
123121

124122
void ScrollViewport(int viewTop);

src/terminal/adapter/ITermDispatch.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
8282
virtual void BackIndex() = 0; // DECBI
8383
virtual void ForwardIndex() = 0; // DECFI
8484
virtual void SetWindowTitle(std::wstring_view title) = 0; // DECSWT, OscWindowTitle
85+
virtual void SetCurrentWorkingDirectory(const std::wstring_view uri) = 0; // OSC 7
8586
virtual void HorizontalTabSet() = 0; // HTS
8687
virtual void ForwardTab(const VTInt numTabs) = 0; // CHT, HT
8788
virtual void BackwardsTab(const VTInt numTabs) = 0; // CBT
@@ -156,13 +157,9 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
156157
virtual void EndHyperlink() = 0;
157158

158159
virtual void DoConEmuAction(const std::wstring_view string) = 0;
159-
160160
virtual void DoITerm2Action(const std::wstring_view string) = 0;
161-
162161
virtual void DoFinalTermAction(const std::wstring_view string) = 0;
163-
164162
virtual void DoVsCodeAction(const std::wstring_view string) = 0;
165-
166163
virtual void DoWTAction(const std::wstring_view string) = 0;
167164

168165
virtual StringHandler DefineSixelImage(const VTInt macroParameter,

src/terminal/adapter/adaptDispatch.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,6 +2615,27 @@ void AdaptDispatch::SetWindowTitle(std::wstring_view title)
26152615
_api.SetWindowTitle(title);
26162616
}
26172617

2618+
// OSC 7 - Set Current Working Directory
2619+
// While ConEmu's OSC 9;9 works well for native Windows paths,
2620+
// OSC 7 uses file URIs, which may not always work.
2621+
void AdaptDispatch::SetCurrentWorkingDirectory(std::wstring_view uri)
2622+
{
2623+
// Ensure that the URI has a null terminator.
2624+
std::wstring path{ uri };
2625+
2626+
// PathCreateFromUrlW supports writing to the input pointer,
2627+
// and the resulting path can never be longer than the URI.
2628+
const auto ptr = path.data();
2629+
auto len = gsl::narrow<DWORD>(path.size());
2630+
THROW_IF_FAILED(PathCreateFromUrlW(ptr, ptr, &len, 0));
2631+
path.resize(len);
2632+
2633+
if (til::is_legal_path(path))
2634+
{
2635+
_api.SetWorkingDirectory(path);
2636+
}
2637+
}
2638+
26182639
//Routine Description:
26192640
// HTS - sets a VT tab stop in the cursor's current column.
26202641
//Arguments:

0 commit comments

Comments
 (0)