Implement ConEmu's OSC 9;9 to set the CWD (#8330)

<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

This PR implement the OSC 9;9 

|Sequence|Descriptoin|
| :------------- | :----------: |
|ESC ] 9 ; 9 ; “cwd” ST | Inform ConEmu about shell current working directory.|


<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

#8214

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [X] Closes #8166
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
This commit is contained in:
Chester Liu 2021-01-12 02:01:38 +08:00 committed by GitHub
parent 49d008537f
commit e557a867ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 25 deletions

View file

@ -1115,6 +1115,13 @@ namespace winrt::TerminalApp::implementation
if (profileGuid.has_value())
{
const auto settings{ winrt::make<TerminalSettings>(_settings, profileGuid.value(), *_bindings) };
const auto workingDirectory = terminalTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
settings.StartingDirectory(workingDirectory);
}
_CreateNewTabFromSettings(profileGuid.value(), settings);
}
}
@ -1638,6 +1645,12 @@ namespace winrt::TerminalApp::implementation
{
profileFound = true;
controlSettings = { winrt::make<TerminalSettings>(_settings, current_guid.value(), *_bindings) };
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
controlSettings.StartingDirectory(workingDirectory);
}
realGuid = current_guid.value();
}
// TODO: GH#5047 - In the future, we should get the Profile of

View file

@ -2460,6 +2460,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return _settings.ProfileName();
}
hstring TermControl::WorkingDirectory() const
{
hstring hstr{ _terminal->GetWorkingDirectory() };
return hstr;
}
// Method Description:
// - Given a copy-able selection, get the selected text from the buffer and send it to the
// Windows Clipboard (CascadiaWin32:main.cpp).

View file

@ -106,6 +106,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
hstring Title();
hstring GetProfileName() const;
hstring WorkingDirectory() const;
bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference<CopyFormat>& formats);
void PasteTextFromClipboard();

View file

@ -110,6 +110,8 @@ namespace Microsoft.Terminal.TerminalControl
UInt64 TaskbarState { get; };
UInt64 TaskbarProgress { get; };
String WorkingDirectory { get; };
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
}

View file

@ -65,6 +65,9 @@ namespace Microsoft::Terminal::Core
virtual bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept = 0;
virtual bool SetWorkingDirectory(std::wstring_view uri) noexcept = 0;
virtual std::wstring_view GetWorkingDirectory() noexcept = 0;
protected:
ITerminalApi() = default;
};

View file

@ -117,6 +117,8 @@ public:
bool EndHyperlink() noexcept override;
bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept override;
bool SetWorkingDirectory(std::wstring_view uri) noexcept override;
std::wstring_view GetWorkingDirectory() noexcept override;
#pragma endregion
#pragma region ITerminalInput
@ -253,6 +255,7 @@ private:
size_t _hyperlinkPatternId;
std::wstring _workingDirectory;
#pragma region Text Selection
// a selection is represented as a range between two COORDs (start and end)
// the pivot is the COORD that remains selected when you extend a selection in any direction

View file

@ -618,3 +618,14 @@ bool Terminal::SetTaskbarProgress(const size_t state, const size_t progress) noe
}
return true;
}
bool Terminal::SetWorkingDirectory(std::wstring_view uri) noexcept
{
_workingDirectory = uri;
return true;
}
std::wstring_view Terminal::GetWorkingDirectory() noexcept
{
return _workingDirectory;
}

View file

@ -417,43 +417,55 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
const auto parts = Utils::SplitString(string, L';');
unsigned int subParam = 0;
// For now, the only ConEmu action we support is setting the taskbar state/progress,
// which has a sub param value of 4
if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam) || subParam != 4)
if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam))
{
return false;
}
if (parts.size() >= 2)
// 4 is SetProgressBar, which sets the taskbar state/progress.
if (subParam == 4)
{
// A state parameter is defined, parse it out
const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state);
if (!stateSuccess)
if (parts.size() >= 2)
{
return false;
}
if (parts.size() >= 3)
{
// A progress parameter is also defined, parse it out
const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress);
if (!progressSuccess)
// A state parameter is defined, parse it out
const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state);
if (!stateSuccess)
{
return false;
}
if (parts.size() >= 3)
{
// A progress parameter is also defined, parse it out
const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress);
if (!progressSuccess)
{
return false;
}
}
}
if (state > TaskbarMaxState)
{
// state is out of bounds, return false
return false;
}
if (progress > TaskbarMaxProgress)
{
// progress is greater than the maximum allowed value, clamp it to the max
progress = TaskbarMaxProgress;
}
return _terminalApi.SetTaskbarProgress(state, progress);
}
// 9 is SetWorkingDirectory, which informs the terminal about the current working directory.
else if (subParam == 9)
{
if (parts.size() >= 2)
{
return _terminalApi.SetWorkingDirectory(til::at(parts, 1));
}
}
if (state > TaskbarMaxState)
{
// state is out of bounds, return false
return false;
}
if (progress > TaskbarMaxProgress)
{
// progress is greater than the maximum allowed value, clamp it to the max
progress = TaskbarMaxProgress;
}
return _terminalApi.SetTaskbarProgress(state, progress);
return false;
}
// Routine Description: