mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-19 09:58:08 -05:00
Use Char[] for Connection stdin (#19655)
This makes it possible to pass through non-null-terminated strings. This is needed for the tmux control mode which passes string slices.
This commit is contained in:
@@ -120,9 +120,9 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
return ConnectionState::Failed;
|
||||
}
|
||||
|
||||
void DebugTapConnection::_OutputHandler(const std::wstring_view str)
|
||||
void DebugTapConnection::_OutputHandler(const winrt::array_view<const char16_t> str)
|
||||
{
|
||||
auto output = til::visualize_control_codes(str);
|
||||
auto output = til::visualize_control_codes(winrt_array_to_wstring_view(str));
|
||||
// To make the output easier to read, we introduce a line break whenever
|
||||
// an LF control is encountered. But at this point, the LF would have
|
||||
// been converted to U+240A (␊), so that's what we need to search for.
|
||||
@@ -130,7 +130,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
output.insert(++lfPos, L"\r\n");
|
||||
}
|
||||
TerminalOutput.raise(output);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(output));
|
||||
}
|
||||
|
||||
// Called by the DebugInputTapConnection to print user input
|
||||
@@ -138,7 +138,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
auto clean{ til::visualize_control_codes(str) };
|
||||
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };
|
||||
TerminalOutput.raise(formatted);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(formatted));
|
||||
}
|
||||
|
||||
// Wire us up so that we can forward input through
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
|
||||
private:
|
||||
void _PrintInput(const std::wstring_view data);
|
||||
void _OutputHandler(const std::wstring_view str);
|
||||
void _OutputHandler(const winrt::array_view<const char16_t> str);
|
||||
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::TerminalOutput_revoker _outputRevoker;
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::StateChanged_revoker _stateChangedRevoker;
|
||||
|
||||
@@ -94,9 +94,15 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
// - helper that will write an unterminated string (generally, from a resource) to the output stream.
|
||||
// Arguments:
|
||||
// - str: the string to write.
|
||||
void AzureConnection::_WriteStringWithNewline(std::wstring str)
|
||||
{
|
||||
str.append(L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(str));
|
||||
}
|
||||
|
||||
void AzureConnection::_WriteStringWithNewline(const std::wstring_view str)
|
||||
{
|
||||
TerminalOutput.raise(str + L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(str + L"\r\n"));
|
||||
}
|
||||
|
||||
// Method description:
|
||||
@@ -112,7 +118,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
catch (const std::exception& runtimeException)
|
||||
{
|
||||
// This also catches the AzureException, which has a .what()
|
||||
TerminalOutput.raise(_colorize(91, til::u8u16(std::string{ runtimeException.what() })));
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(_colorize(91, til::u8u16(std::string{ runtimeException.what() }))));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -162,13 +168,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
_currentInputMode = mode;
|
||||
|
||||
TerminalOutput.raise(L"> \x1b[92m"); // Make prompted user input green
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"> \x1b[92m")); // Make prompted user input green
|
||||
|
||||
_inputEvent.wait(inputLock, [this, mode]() {
|
||||
return _currentInputMode != mode || _isStateAtOrBeyond(ConnectionState::Closing);
|
||||
});
|
||||
|
||||
TerminalOutput.raise(L"\x1b[m");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\x1b[m"));
|
||||
|
||||
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||
{
|
||||
@@ -211,19 +217,19 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
if (_userInput.size() > 0)
|
||||
{
|
||||
_userInput.pop_back();
|
||||
TerminalOutput.raise(L"\x08 \x08"); // overstrike the character with a space
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\x08 \x08")); // overstrike the character with a space
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TerminalOutput.raise(data); // echo back
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(data)); // echo back
|
||||
|
||||
switch (_currentInputMode)
|
||||
{
|
||||
case InputMode::Line:
|
||||
if (data.size() > 0 && gsl::at(data, 0) == UNICODE_CARRIAGERETURN)
|
||||
{
|
||||
TerminalOutput.raise(L"\r\n"); // we probably got a \r, so we need to advance to the next line.
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\r\n")); // we probably got a \r, so we need to advance to the next line.
|
||||
_currentInputMode = InputMode::None; // toggling the mode indicates completion
|
||||
_inputEvent.notify_one();
|
||||
break;
|
||||
@@ -429,7 +435,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
|
||||
// Pass the output to our registered event handlers
|
||||
TerminalOutput.raise(_u16Str);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(_u16Str));
|
||||
break;
|
||||
}
|
||||
case WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE:
|
||||
@@ -772,7 +778,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto shellType = _ParsePreferredShellType(settingsResponse);
|
||||
_WriteStringWithNewline(RS_(L"AzureRequestingTerminal"));
|
||||
const auto socketUri = _GetTerminal(shellType);
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\r\n"));
|
||||
|
||||
//// Step 8: connecting to said terminal
|
||||
{
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
std::optional<::Microsoft::Terminal::Azure::Tenant> _currentTenant;
|
||||
|
||||
void _writeInput(const std::wstring_view str);
|
||||
void _WriteStringWithNewline(std::wstring str);
|
||||
void _WriteStringWithNewline(const std::wstring_view str);
|
||||
void _WriteCaughtExceptionRecord();
|
||||
winrt::Windows::Data::Json::JsonObject _SendRequestReturningJson(std::wstring_view uri, const winrt::Windows::Web::Http::IHttpContent& content = nullptr, winrt::Windows::Web::Http::HttpMethod method = nullptr, const winrt::Windows::Foundation::Uri referer = nullptr);
|
||||
|
||||
@@ -477,31 +477,28 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
const auto failureText = RS_fmt(L"ProcessFailedToLaunch", _formatStatus(hr), _commandline);
|
||||
TerminalOutput.raise(failureText);
|
||||
auto failureText = RS_fmt(L"ProcessFailedToLaunch", _formatStatus(hr), _commandline);
|
||||
|
||||
// If the path was invalid, let's present an informative message to the user
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_DIRECTORY))
|
||||
{
|
||||
const auto badPathText = RS_fmt(L"BadPathText", _startingDirectory);
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(badPathText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_fmt(L"BadPathText", _startingDirectory));
|
||||
}
|
||||
// If the requested action requires elevation, display appropriate message
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_ELEVATION_REQUIRED))
|
||||
{
|
||||
const auto elevationText = RS_(L"ElevationRequired");
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(elevationText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_(L"ElevationRequired"));
|
||||
}
|
||||
// If the requested executable was not found, display appropriate message
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||||
{
|
||||
const auto fileNotFoundText = RS_(L"FileNotFound");
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(fileNotFoundText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_(L"FileNotFound"));
|
||||
}
|
||||
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(failureText));
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
|
||||
// Tear down any state we may have accumulated.
|
||||
@@ -520,7 +517,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto msg1 = RS_fmt(L"ProcessExited", _formatStatus(status));
|
||||
const auto msg2 = RS_(L"CtrlDToClose");
|
||||
const auto msg = fmt::format(FMT_COMPILE(L"\r\n{}\r\n{}\r\n"), msg1, msg2);
|
||||
TerminalOutput.raise(msg);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(msg));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -792,7 +789,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
try
|
||||
{
|
||||
TerminalOutput.raise(wstr);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(wstr));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
prettyPrint << wch;
|
||||
}
|
||||
}
|
||||
TerminalOutput.raise(prettyPrint.str());
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(prettyPrint.str()));
|
||||
}
|
||||
|
||||
void EchoConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||
Failed
|
||||
};
|
||||
|
||||
delegate void TerminalOutputHandler(String output);
|
||||
delegate void TerminalOutputHandler(Char[] output);
|
||||
|
||||
interface ITerminalConnection
|
||||
{
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
#include <DefaultSettings.h>
|
||||
#include <unicode.hpp>
|
||||
#include <utils.hpp>
|
||||
#include <WinUser.h>
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
@@ -2238,13 +2236,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto noticeArgs = winrt::make<NoticeEventArgs>(NoticeLevel::Info, RS_(L"TermControlReadOnly"));
|
||||
RaiseNotice.raise(*this, std::move(noticeArgs));
|
||||
}
|
||||
void ControlCore::_connectionOutputHandler(const hstring& hstr)
|
||||
void ControlCore::_connectionOutputHandler(const winrt::array_view<const char16_t> str)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_terminal->Write(hstr);
|
||||
_terminal->Write(winrt_array_to_wstring_view(str));
|
||||
}
|
||||
|
||||
if (!_pendingResponses.empty())
|
||||
|
||||
@@ -349,7 +349,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _raiseReadOnlyWarning();
|
||||
void _updateAntiAliasingMode();
|
||||
void _connectionOutputHandler(const hstring& hstr);
|
||||
void _connectionOutputHandler(winrt::array_view<const char16_t> str);
|
||||
void _connectionStateChangedHandler(const TerminalConnection::ITerminalConnection&, const Windows::Foundation::IInspectable&);
|
||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||
void _setOpacity(const float opacity, const bool focused = true);
|
||||
|
||||
@@ -28,10 +28,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
PreviewConnection::PreviewConnection() noexcept = default;
|
||||
|
||||
void PreviewConnection::Start() noexcept
|
||||
void PreviewConnection::Start()
|
||||
{
|
||||
// Send the preview text
|
||||
TerminalOutput.raise(fmt::format(PreviewText, _displayPowerlineGlyphs ? PromptTextPowerline : PromptTextPlain));
|
||||
const auto prompt = _displayPowerlineGlyphs ? PromptTextPowerline : PromptTextPlain;
|
||||
const auto text = fmt::format(FMT_COMPILE(PreviewText), prompt);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(text));
|
||||
}
|
||||
|
||||
void PreviewConnection::Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) noexcept
|
||||
@@ -50,7 +51,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
}
|
||||
|
||||
void PreviewConnection::DisplayPowerlineGlyphs(bool d) noexcept
|
||||
void PreviewConnection::DisplayPowerlineGlyphs(bool d)
|
||||
{
|
||||
if (_displayPowerlineGlyphs != d)
|
||||
{
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
PreviewConnection() noexcept;
|
||||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& settings) noexcept;
|
||||
void Start() noexcept;
|
||||
void Start();
|
||||
void WriteInput(const winrt::array_view<const char16_t> buffer);
|
||||
void Resize(uint32_t rows, uint32_t columns) noexcept;
|
||||
void Close() noexcept;
|
||||
|
||||
void DisplayPowerlineGlyphs(bool d) noexcept;
|
||||
void DisplayPowerlineGlyphs(bool d);
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; }
|
||||
|
||||
@@ -104,13 +104,14 @@ namespace ControlUnitTests
|
||||
auto _addInputCallback(const winrt::com_ptr<MockConnection>& conn,
|
||||
std::deque<std::wstring>& expectedOutput)
|
||||
{
|
||||
conn->TerminalOutput([&](const hstring& hstr) {
|
||||
conn->TerminalOutput([&](const winrt::array_view<const char16_t> str) {
|
||||
VERIFY_IS_GREATER_THAN(expectedOutput.size(), 0u);
|
||||
const auto actual = winrt_array_to_wstring_view(str);
|
||||
const auto expected = expectedOutput.front();
|
||||
expectedOutput.pop_front();
|
||||
Log::Comment(fmt::format(L"Received: \"{}\"", TerminalCoreUnitTests::TestUtils::ReplaceEscapes(hstr.c_str())).c_str());
|
||||
Log::Comment(fmt::format(L"Expected: \"{}\"", TerminalCoreUnitTests::TestUtils::ReplaceEscapes(expected)).c_str());
|
||||
VERIFY_ARE_EQUAL(expected, hstr);
|
||||
Log::Comment(fmt::format(L"Received: \"{}\"", til::visualize_nonspace_control_codes(std::wstring{ actual })).c_str());
|
||||
Log::Comment(fmt::format(L"Expected: \"{}\"", til::visualize_nonspace_control_codes(expected)).c_str());
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
});
|
||||
|
||||
return std::move(wil::scope_exit([&]() {
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace ControlUnitTests
|
||||
void Start() noexcept {};
|
||||
void WriteInput(const winrt::array_view<const char16_t> data)
|
||||
{
|
||||
TerminalOutput.raise(winrt_array_to_wstring_view(data));
|
||||
TerminalOutput.raise(data);
|
||||
}
|
||||
void Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept {}
|
||||
void Close() noexcept {}
|
||||
|
||||
@@ -109,50 +109,6 @@ public:
|
||||
return iter;
|
||||
};
|
||||
|
||||
// Function Description:
|
||||
// - Replaces all escapes with the printable symbol for that escape
|
||||
// character. This makes log parsing easier for debugging, as the literal
|
||||
// escapes won't be written to the console output.
|
||||
// Arguments:
|
||||
// - str: the string to escape.
|
||||
// Return Value:
|
||||
// - A modified version of that string with non-printable characters replaced.
|
||||
static std::string ReplaceEscapes(const std::string& str)
|
||||
{
|
||||
std::string escaped = str;
|
||||
auto replaceFn = [&escaped](const std::string& search, const std::string& replace) {
|
||||
size_t pos = escaped.find(search, 0);
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
escaped.replace(pos, search.length(), replace);
|
||||
pos = escaped.find(search, pos + replace.length());
|
||||
}
|
||||
};
|
||||
replaceFn("\x1b", "^\x5b"); // ESC
|
||||
replaceFn("\x08", "^\x48"); // BS
|
||||
replaceFn("\x0A", "^\x4A"); // LF
|
||||
replaceFn("\x0D", "^\x4D"); // CR
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Replaces all escapes with the printable symbol for that escape
|
||||
// character. This makes log parsing easier for debugging, as the literal
|
||||
// escapes won't be written to the console output.
|
||||
// Arguments:
|
||||
// - wstr: the string to escape.
|
||||
// Return Value:
|
||||
// - A modified version of that string with non-printable characters replaced.
|
||||
static std::wstring ReplaceEscapes(const std::wstring& wstr)
|
||||
{
|
||||
std::wstring escaped = wstr;
|
||||
std::replace(escaped.begin(), escaped.end(), L'\x1b', L'\x241b'); // ESC
|
||||
std::replace(escaped.begin(), escaped.end(), L'\x08', L'\x2408'); // BS
|
||||
std::replace(escaped.begin(), escaped.end(), L'\x0A', L'\x240A'); // LF
|
||||
std::replace(escaped.begin(), escaped.end(), L'\x0D', L'\x240D'); // CR
|
||||
return escaped;
|
||||
}
|
||||
|
||||
template<class... T>
|
||||
static bool VerifyLineContains(TextBufferCellIterator& actual, T&&... expectedContent)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user