mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-06 05:34:59 +00:00
Merge branch 'dev/migrie/fhl/vscode-autocomplete-prototype' into dev/migrie/fhl/tasks-view-2022
This commit is contained in:
@@ -183,6 +183,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD} = {3C67784E-1453-49C2-9660-483E2CC7F7AD}
|
||||
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
||||
2
gitbranch.cmd
Normal file
2
gitbranch.cmd
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
git branch | D:\dev\private\OpenConsole\bin\x64\Debug\Scratch.exe --prefix "git checkout "
|
||||
@@ -50,6 +50,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
case ShortcutAction::SetColorScheme:
|
||||
case ShortcutAction::AdjustOpacity:
|
||||
case ShortcutAction::SendInput:
|
||||
{
|
||||
_RunRestorePreviews();
|
||||
break;
|
||||
@@ -150,6 +151,12 @@ namespace winrt::TerminalApp::implementation
|
||||
case ShortcutAction::AdjustOpacity:
|
||||
_PreviewAdjustOpacity(args.Args().try_as<AdjustOpacityArgs>());
|
||||
break;
|
||||
|
||||
case ShortcutAction::SendInput:
|
||||
{
|
||||
// _PreviewSendInput(args.Args().try_as<SendInputArgs>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// GH#9818 Other ideas for actions that could be preview-able:
|
||||
@@ -163,6 +170,27 @@ namespace winrt::TerminalApp::implementation
|
||||
_lastPreviewedAction = args;
|
||||
}
|
||||
|
||||
void TerminalPage::_PreviewSendInput(const Settings::Model::SendInputArgs& args)
|
||||
{
|
||||
const auto backup = _restorePreviewFuncs.empty();
|
||||
|
||||
_ApplyToActiveControls([&](const auto& control) {
|
||||
// // Stash a copy of the original opacity.
|
||||
// auto originalOpacity{ control.BackgroundOpacity() };
|
||||
|
||||
// Apply the new opacity
|
||||
control.PreviewInput(args.Input());
|
||||
|
||||
if (backup)
|
||||
{
|
||||
_restorePreviewFuncs.emplace_back([=]() {
|
||||
// On dismiss:
|
||||
control.PreviewInput(L"");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Handler for the CommandPalette::PreviewAction event. The Command
|
||||
// Palette will raise this even when an action is selected, but _not_
|
||||
|
||||
@@ -225,13 +225,17 @@ namespace winrt::TerminalApp::implementation
|
||||
void CommandPalette::_selectedCommandChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
const auto currentlyVisible{ Visibility() == Visibility::Visible };
|
||||
|
||||
const auto selectedCommand = _filteredActionsView().SelectedItem();
|
||||
const auto filteredCommand{ selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>() };
|
||||
if (_currentMode == CommandPaletteMode::TabSwitchMode)
|
||||
{
|
||||
_switchToTab(filteredCommand);
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode && filteredCommand != nullptr)
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode &&
|
||||
filteredCommand != nullptr &&
|
||||
currentlyVisible)
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
{
|
||||
@@ -956,6 +960,15 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_updateFilteredActions();
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode)
|
||||
{
|
||||
auto actions = _collectFilteredActions();
|
||||
_filteredActions.Clear();
|
||||
for (const auto& action : actions)
|
||||
{
|
||||
_filteredActions.Append(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1083,7 +1096,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
std::copy(begin(commandsToFilter), end(commandsToFilter), std::back_inserter(actions));
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode || _currentMode == CommandPaletteMode::CommandlineMode)
|
||||
else if (_currentMode == CommandPaletteMode::TabSearchMode ||
|
||||
_currentMode == CommandPaletteMode::ActionMode ||
|
||||
_currentMode == CommandPaletteMode::CommandlineMode)
|
||||
{
|
||||
for (const auto& action : commandsToFilter)
|
||||
{
|
||||
@@ -1369,4 +1384,30 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
ApplicationState::SharedInstance().RecentCommands(single_threaded_vector(std::move(newRecentCommands)));
|
||||
}
|
||||
|
||||
void CommandPalette::PositionManually(Windows::Foundation::Point origin, Windows::Foundation::Size size)
|
||||
{
|
||||
Controls::Grid::SetRow(_backdrop(), 0);
|
||||
Controls::Grid::SetColumn(_backdrop(), 0);
|
||||
Controls::Grid::SetRowSpan(_backdrop(), 2);
|
||||
Controls::Grid::SetColumnSpan(_backdrop(), 3);
|
||||
|
||||
// Set thie Max* versions here, otherwise when there are few results,
|
||||
// the cmdpal will _still_ be 300x300 and filled with empty space
|
||||
_backdrop().MaxWidth(size.Width);
|
||||
_backdrop().MaxHeight(size.Height);
|
||||
|
||||
_backdrop().HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
_backdrop().VerticalAlignment(VerticalAlignment::Stretch);
|
||||
|
||||
// // We can fake this. We're only using this method for the autocomplete
|
||||
// // version of the cmdpal. Set the BG to acrylic.
|
||||
// const auto colorControlStyle{ Resources().Lookup(winrt::box_value(L"CommandPaletteAcrylicBackground")).as<Windows::UI::Xaml::Style>() };
|
||||
// _backdrop().Style(colorControlStyle);
|
||||
|
||||
Windows::UI::Xaml::Thickness margins{};
|
||||
margins.Left = origin.X;
|
||||
margins.Top = origin.Y;
|
||||
_backdrop().Margin(margins);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void EnableTabSwitcherMode(const uint32_t startIdx, Microsoft::Terminal::Settings::Model::TabSwitcherMode tabSwitcherMode);
|
||||
void EnableTabSearchMode();
|
||||
|
||||
void PositionManually(Windows::Foundation::Point origin, Windows::Foundation::Size size);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace TerminalApp
|
||||
void EnableTabSwitcherMode(UInt32 startIdx, Microsoft.Terminal.Settings.Model.TabSwitcherMode tabSwitcherMode);
|
||||
void EnableTabSearchMode();
|
||||
|
||||
void PositionManually(Windows.Foundation.Point origin, Windows.Foundation.Size size);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, TabBase> SwitchToTabRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, String> CommandLineExecutionRequested;
|
||||
|
||||
@@ -215,7 +215,6 @@
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
@@ -243,7 +242,6 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
@@ -271,7 +269,6 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
|
||||
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border" />
|
||||
|
||||
@@ -287,6 +287,17 @@ namespace winrt::TerminalApp::implementation
|
||||
CommandPalette().SwitchToTabRequested({ this, &TerminalPage::_OnSwitchToTabRequested });
|
||||
CommandPalette().PreviewAction({ this, &TerminalPage::_PreviewActionHandler });
|
||||
|
||||
AutoCompleteMenu().PositionManually(Windows::Foundation::Point{ 0, 0 }, Windows::Foundation::Size{ 200, 300 });
|
||||
AutoCompleteMenu().RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) {
|
||||
if (AutoCompleteMenu().Visibility() == Visibility::Collapsed)
|
||||
{
|
||||
AutoCompletePopup().IsOpen(false);
|
||||
_FocusActiveControl(nullptr, nullptr);
|
||||
}
|
||||
});
|
||||
AutoCompleteMenu().DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
AutoCompleteMenu().PreviewAction({ this, &TerminalPage::_PreviewActionHandler });
|
||||
|
||||
// Settings AllowDependentAnimations will affect whether animations are
|
||||
// enabled application-wide, so we don't need to check it each time we
|
||||
// want to create an animation.
|
||||
@@ -1308,7 +1319,13 @@ namespace winrt::TerminalApp::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible &&
|
||||
cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
if (const auto p = AutoCompleteMenu(); p.Visibility() == Visibility::Visible &&
|
||||
cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
@@ -1476,6 +1493,8 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
|
||||
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
|
||||
|
||||
term.MenuChanged({ get_weak(), &TerminalPage::_ControlMenuChangedHandler });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -4233,4 +4252,49 @@ namespace winrt::TerminalApp::implementation
|
||||
_activated = activated;
|
||||
_updateThemeColors();
|
||||
}
|
||||
winrt::fire_and_forget TerminalPage::_ControlMenuChangedHandler(const IInspectable /*sender*/,
|
||||
const winrt::Microsoft::Terminal::Control::MenuChangedEventArgs args)
|
||||
{
|
||||
// co_await winrt::resume_background();
|
||||
|
||||
// May be able to fake this by not creating whole Commands for these
|
||||
// actions, instead just binding them at the cmdpal layer (like tab item
|
||||
// vs action item)
|
||||
// auto entries = control.MenuEntries();
|
||||
|
||||
// parse json
|
||||
auto commandsCollection = Command::ParsePowerShellMenuComplete(args.MenuJson(), args.ReplacementLength());
|
||||
|
||||
co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
||||
auto control{ _GetActiveControl() };
|
||||
if (!control)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
if (commandsCollection.Size() == 0)
|
||||
{
|
||||
AutoCompletePopup().IsOpen(false);
|
||||
AutoCompleteMenu().Visibility(Visibility::Collapsed);
|
||||
co_return;
|
||||
}
|
||||
// CommandPalette has an internal margin of 8, so set to -4,-4 to position closer to the actual line
|
||||
AutoCompleteMenu().PositionManually(Windows::Foundation::Point{ -4, -4 }, Windows::Foundation::Size{ 300, 300 });
|
||||
|
||||
// CommandPalette().EnableCommandPaletteMode(CommandPaletteLaunchMode::Action);
|
||||
|
||||
const til::point cursorPos{ control.CursorPositionInDips() };
|
||||
const auto characterSize{ control.CharacterDimensions() };
|
||||
|
||||
// Position relative to the actual term control
|
||||
AutoCompletePopup().HorizontalOffset(cursorPos.x);
|
||||
AutoCompletePopup().VerticalOffset(cursorPos.y + characterSize.Height);
|
||||
|
||||
AutoCompletePopup().IsOpen(true);
|
||||
// ~Make visible first, then set commands. Other way around and the list
|
||||
// doesn't actually update the first time (weird)~
|
||||
AutoCompleteMenu().SetCommands(commandsCollection);
|
||||
AutoCompleteMenu().Visibility(commandsCollection.Size() > 0 ? Visibility::Visible : Visibility::Collapsed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -423,6 +423,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _RunRestorePreviews();
|
||||
void _PreviewColorScheme(const Microsoft::Terminal::Settings::Model::SetColorSchemeArgs& args);
|
||||
void _PreviewAdjustOpacity(const Microsoft::Terminal::Settings::Model::AdjustOpacityArgs& args);
|
||||
void _PreviewSendInput(const Microsoft::Terminal::Settings::Model::SendInputArgs& args);
|
||||
winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs _lastPreviewedAction{ nullptr };
|
||||
std::vector<std::function<void()>> _restorePreviewFuncs{};
|
||||
|
||||
@@ -456,6 +457,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::fire_and_forget _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
|
||||
|
||||
winrt::fire_and_forget _ControlMenuChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::MenuChangedEventArgs args);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
||||
@@ -195,6 +195,18 @@
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<Popup x:Name="AutoCompletePopup"
|
||||
HorizontalOffset="200"
|
||||
IsOpen="False"
|
||||
ShouldConstrainToRootBounds="False"
|
||||
VerticalOffset="200">
|
||||
<local:CommandPalette x:Name="AutoCompleteMenu"
|
||||
VerticalAlignment="Stretch"
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
</Popup>
|
||||
|
||||
<!--
|
||||
A TeachingTip with IsLightDismissEnabled="True" will immediately
|
||||
dismiss itself if the window is unfocused (In Xaml Islands). This is
|
||||
@@ -226,4 +238,5 @@
|
||||
</mux:TeachingTip.Content>
|
||||
</mux:TeachingTip>
|
||||
</Grid>
|
||||
|
||||
</Page>
|
||||
|
||||
@@ -143,6 +143,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnPlayMidiNote = std::bind(&ControlCore::_terminalPlayMidiNote, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
_terminal->SetPlayMidiNoteCallback(pfnPlayMidiNote);
|
||||
|
||||
auto pfnMenuChanged = std::bind(&ControlCore::_terminalMenuChanged, this, std::placeholders::_1, std::placeholders::_2);
|
||||
_terminal->MenuChangedCallback(pfnMenuChanged);
|
||||
|
||||
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
|
||||
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
|
||||
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
|
||||
@@ -230,6 +233,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
});
|
||||
|
||||
// _updateMenu = std::make_shared<ThrottledFuncTrailing<winrt::hstring, int32_t>>(
|
||||
// _dispatcher,
|
||||
// UpdatePatternLocationsInterval,
|
||||
// [weakThis = get_weak()](const auto& menuJson, const auto& replaceLength) {
|
||||
// if (auto core{ weakThis.get() }; !core->_IsClosing())
|
||||
// {
|
||||
// auto args = winrt::make<MenuChangedEventArgs>(menuJson, replaceLength);
|
||||
// core->_MenuChangedHandlers(*core, args);
|
||||
// }
|
||||
// });
|
||||
|
||||
UpdateSettings(settings, unfocusedAppearance);
|
||||
}
|
||||
|
||||
@@ -1440,6 +1454,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ControlCore::_terminalMenuChanged(std::wstring_view menuJson, int32_t replaceLength)
|
||||
{
|
||||
// _updateMenu->Run(winrt::hstring{ menuJson }, replaceLength);
|
||||
// _MenuChangedHandlers(*this, nullptr);
|
||||
|
||||
auto args = winrt::make_self<MenuChangedEventArgs>(winrt::hstring{ menuJson }, replaceLength);
|
||||
_MenuChangedHandlers(*this, *args);
|
||||
}
|
||||
|
||||
bool ControlCore::HasSelection() const
|
||||
{
|
||||
return _terminal->IsSelectionActive();
|
||||
|
||||
@@ -232,6 +232,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs);
|
||||
TYPED_EVENT(UpdateSelectionMarkers, IInspectable, Control::UpdateSelectionMarkersEventArgs);
|
||||
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
|
||||
|
||||
TYPED_EVENT(MenuChanged, IInspectable, Control::MenuChangedEventArgs);
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
@@ -281,6 +283,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
|
||||
std::unique_ptr<til::throttled_func_trailing<>> _updatePatternLocations;
|
||||
std::shared_ptr<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>> _updateScrollBar;
|
||||
std::shared_ptr<ThrottledFuncTrailing<winrt::hstring, int32_t>> _updateMenu;
|
||||
|
||||
bool _setFontSizeUnderLock(int fontSize);
|
||||
void _updateFont(const bool initialUpdate = false);
|
||||
@@ -299,10 +302,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const int bufferSize);
|
||||
void _terminalCursorPositionChanged();
|
||||
void _terminalTaskbarProgressChanged();
|
||||
|
||||
void _terminalShowWindowChanged(bool showOrHide);
|
||||
void _terminalPlayMidiNote(const int noteNumber,
|
||||
const int velocity,
|
||||
const std::chrono::microseconds duration);
|
||||
|
||||
void _terminalMenuChanged(std::wstring_view menuJson, int32_t replaceLength);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
std::unique_ptr<MidiAudio> _midiAudio;
|
||||
|
||||
@@ -161,5 +161,9 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, ShowWindowArgs> ShowWindowChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, UpdateSelectionMarkersEventArgs> UpdateSelectionMarkers;
|
||||
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, MenuChangedEventArgs> MenuChanged;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,3 +14,4 @@
|
||||
#include "FoundResultsArgs.g.cpp"
|
||||
#include "ShowWindowArgs.g.cpp"
|
||||
#include "UpdateSelectionMarkersEventArgs.g.cpp"
|
||||
#include "MenuChangedEventArgs.g.cpp"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "FoundResultsArgs.g.h"
|
||||
#include "ShowWindowArgs.g.h"
|
||||
#include "UpdateSelectionMarkersEventArgs.g.h"
|
||||
#include "MenuChangedEventArgs.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
@@ -169,4 +170,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
WINRT_PROPERTY(bool, ClearMarkers, false);
|
||||
};
|
||||
|
||||
struct MenuChangedEventArgs : public MenuChangedEventArgsT<MenuChangedEventArgs>
|
||||
{
|
||||
public:
|
||||
MenuChangedEventArgs(const winrt::hstring menuJson, const int32_t replaceLength) :
|
||||
_MenuJson(menuJson),
|
||||
_ReplacementLength(replaceLength)
|
||||
{
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, MenuJson, L"");
|
||||
WINRT_PROPERTY(int32_t, ReplacementLength, 0);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,4 +83,10 @@ namespace Microsoft.Terminal.Control
|
||||
{
|
||||
Boolean ClearMarkers { get; };
|
||||
}
|
||||
|
||||
runtimeclass MenuChangedEventArgs
|
||||
{
|
||||
String MenuJson { get; };
|
||||
Int32 ReplacementLength { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,13 @@ namespace Microsoft.Terminal.Control
|
||||
Last
|
||||
};
|
||||
|
||||
struct MenuEntry
|
||||
{
|
||||
String Name;
|
||||
String Comment;
|
||||
String Input;
|
||||
};
|
||||
|
||||
// These are properties of the TerminalCore that should be queryable by the
|
||||
// rest of the app.
|
||||
interface ICoreState
|
||||
@@ -51,6 +58,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
|
||||
|
||||
|
||||
UInt64 OwningHwnd;
|
||||
|
||||
void AddMark(ScrollMark mark);
|
||||
|
||||
@@ -437,4 +437,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void TSFInputControl::_formatUpdatingHandler(CoreTextEditContext sender, const CoreTextFormatUpdatingEventArgs& /*args*/)
|
||||
{
|
||||
}
|
||||
|
||||
void TSFInputControl::ManuallyDisplayText(const winrt::hstring& text)
|
||||
{
|
||||
_focused = !text.empty();
|
||||
Canvas().Visibility(text.empty() ? Visibility::Collapsed : Visibility::Visible);
|
||||
|
||||
_inputBuffer.clear();
|
||||
// _editContext.NotifyFocusLeave();
|
||||
_activeTextStart = 0;
|
||||
_inComposition = false;
|
||||
|
||||
// HACK trim off leading DEL chars.
|
||||
std::wstring_view view{ text.c_str() };
|
||||
const auto strBegin = view.find_first_not_of(L"\x7f");
|
||||
if (strBegin != std::wstring::npos)
|
||||
{
|
||||
view = view.substr(strBegin*2);
|
||||
}
|
||||
|
||||
TextBlock().Text(winrt::hstring{ view });
|
||||
TextBlock().UpdateLayout();
|
||||
TryRedrawCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ClearBuffer();
|
||||
void TryRedrawCanvas();
|
||||
|
||||
void ManuallyDisplayText(const winrt::hstring& text);
|
||||
|
||||
void Close();
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace Microsoft.Terminal.Control
|
||||
void ClearBuffer();
|
||||
void TryRedrawCanvas();
|
||||
|
||||
void ManuallyDisplayText(String text);
|
||||
|
||||
|
||||
void Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,6 +388,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - <none>
|
||||
void TermControl::SendInput(const winrt::hstring& wstr)
|
||||
{
|
||||
PreviewInput(L"");
|
||||
_core.SendInput(wstr);
|
||||
}
|
||||
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
|
||||
@@ -3109,4 +3110,35 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
_core.ColorSelection(fg, bg, matchMode);
|
||||
}
|
||||
|
||||
Microsoft::Terminal::Core::Point TermControl::CursorPositionInDips()
|
||||
{
|
||||
// const auto cursorPosition{ _core.CursorPosition() };
|
||||
|
||||
const til::point cursorPos{ _core.CursorPosition() };
|
||||
|
||||
const til::size fontSize{ til::math::flooring, CharacterDimensions() };
|
||||
|
||||
// Convert text buffer cursor position to client coordinate position
|
||||
// within the window. This point is in _pixels_
|
||||
const til::point clientCursorPos{ cursorPos * fontSize };
|
||||
|
||||
// Get scale factor for view
|
||||
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
|
||||
const til::point clientCursorInDips{ til::math::flooring, clientCursorPos.x / scaleFactor, clientCursorPos.y / scaleFactor };
|
||||
|
||||
// + SwapChainPanel().Margin().Top
|
||||
auto padding{ GetPadding() };
|
||||
til::point relativeToOrigin{ til::math::flooring,
|
||||
clientCursorInDips.x + padding.Left,
|
||||
clientCursorInDips.y + padding.Top };
|
||||
return relativeToOrigin.to_core_point();
|
||||
}
|
||||
|
||||
void TermControl::PreviewInput(const winrt::hstring& text)
|
||||
{
|
||||
TSFInputControl().ManuallyDisplayText(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Windows::Foundation::Size CharacterDimensions() const;
|
||||
Windows::Foundation::Size MinimumSize();
|
||||
float SnapDimensionToGrid(const bool widthOrHeight, const float dimension);
|
||||
Microsoft::Terminal::Core::Point CursorPositionInDips();
|
||||
void PreviewInput(const winrt::hstring& text);
|
||||
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
@@ -78,6 +80,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ClearAllMarks();
|
||||
void ScrollToMark(const Control::ScrollToMarkDirection& direction);
|
||||
|
||||
Windows::Foundation::Collections::IVector<Control::MenuEntry> MenuEntries() const;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void ScrollViewport(int viewTop);
|
||||
@@ -146,6 +150,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs, _core, ShowWindowChanged);
|
||||
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(MenuChanged , IInspectable, Control::MenuChangedEventArgs, _core, MenuChanged);
|
||||
|
||||
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard);
|
||||
|
||||
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, MenuChangedEventArgs> MenuChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, Windows.UI.Xaml.RoutedEventArgs> Initialized;
|
||||
// This is an event handler forwarder for the underlying connection.
|
||||
@@ -95,5 +96,10 @@ namespace Microsoft.Terminal.Control
|
||||
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
|
||||
|
||||
void ColorSelection(SelectionColor fg, SelectionColor bg, Microsoft.Terminal.Core.MatchMode matchMode);
|
||||
|
||||
Microsoft.Terminal.Core.Point CursorPositionInDips { get; };
|
||||
|
||||
void PreviewInput(String text);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1389,6 +1389,11 @@ void Microsoft::Terminal::Core::Terminal::TaskbarProgressChangedCallback(std::fu
|
||||
_pfnTaskbarProgressChanged.swap(pfn);
|
||||
}
|
||||
|
||||
void Microsoft::Terminal::Core::Terminal::MenuChangedCallback(std::function<void(std::wstring_view, int32_t)> pfn) noexcept
|
||||
{
|
||||
_pfnMenuChanged.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Propagates an incoming set window visibility call from the PTY up into our window control layers
|
||||
// Arguments:
|
||||
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
|
||||
RenderSettings& GetRenderSettings() noexcept { return _renderSettings; };
|
||||
const RenderSettings& GetRenderSettings() const noexcept { return _renderSettings; };
|
||||
// const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry>& GetMenu() const;
|
||||
|
||||
const std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark>& GetScrollMarks() const;
|
||||
void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark,
|
||||
@@ -143,6 +144,11 @@ public:
|
||||
bool IsConsolePty() const override;
|
||||
bool IsVtInputEnabled() const override;
|
||||
void NotifyAccessibilityChange(const til::rect& changedRect) override;
|
||||
|
||||
void InvokeMenu(std::wstring_view menuJson, int32_t replaceLength) override;
|
||||
// void ClearMenu();
|
||||
// void AddToMenu(const Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry& menu);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void ClearMark();
|
||||
@@ -221,6 +227,8 @@ public:
|
||||
void SetShowWindowCallback(std::function<void(bool)> pfn) noexcept;
|
||||
void SetPlayMidiNoteCallback(std::function<void(const int, const int, const std::chrono::microseconds)> pfn) noexcept;
|
||||
|
||||
void MenuChangedCallback(std::function<void(std::wstring_view, int32_t)> pfn) noexcept;
|
||||
|
||||
void SetCursorOn(const bool isOn);
|
||||
bool IsCursorBlinkingAllowed() const noexcept;
|
||||
|
||||
@@ -320,6 +328,8 @@ private:
|
||||
std::function<void(bool)> _pfnShowWindowChanged;
|
||||
std::function<void(const int, const int, const std::chrono::microseconds)> _pfnPlayMidiNote;
|
||||
|
||||
std::function<void(std::wstring_view, int32_t)> _pfnMenuChanged;
|
||||
|
||||
RenderSettings _renderSettings;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::TerminalInput> _terminalInput;
|
||||
@@ -407,6 +417,8 @@ private:
|
||||
|
||||
std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark> _scrollMarks;
|
||||
|
||||
// std::vector<Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry> _menu;
|
||||
|
||||
static WORD _ScanCodeFromVirtualKey(const WORD vkey) noexcept;
|
||||
static WORD _VirtualKeyFromScanCode(const WORD scanCode) noexcept;
|
||||
static WORD _VirtualKeyFromCharacter(const wchar_t ch) noexcept;
|
||||
|
||||
@@ -332,3 +332,48 @@ void Terminal::NotifyAccessibilityChange(const til::rect& /*changedRect*/)
|
||||
{
|
||||
// This is only needed in conhost. Terminal handles accessibility in another way.
|
||||
}
|
||||
|
||||
// void Terminal::ClearMenu()
|
||||
// {
|
||||
// _menu.clear();
|
||||
|
||||
// if (_pfnMenuChanged)
|
||||
// {
|
||||
// _pfnMenuChanged();
|
||||
// }
|
||||
// }
|
||||
// void Terminal::AddToMenu(const Microsoft::Console::VirtualTerminal::DispatchTypes::MenuEntry& entry)
|
||||
// {
|
||||
// // entry;
|
||||
// // for (const auto& entry : menu)
|
||||
// // {
|
||||
// auto n = entry._name;
|
||||
// n;
|
||||
// auto a = 9;
|
||||
// a++;
|
||||
// a;
|
||||
|
||||
// _menu.push_back(entry);
|
||||
|
||||
// if (_pfnMenuChanged)
|
||||
// {
|
||||
// _pfnMenuChanged();
|
||||
// }
|
||||
// // }
|
||||
// }
|
||||
void Terminal::InvokeMenu(std::wstring_view menuJson, int32_t replaceLength)
|
||||
{
|
||||
// menu;
|
||||
// for (const auto& entry : menu)
|
||||
// {
|
||||
// auto n = entry._name;
|
||||
// n;
|
||||
// auto a = 9;
|
||||
// a++;
|
||||
// a;
|
||||
|
||||
// }
|
||||
// DebugBreak();
|
||||
if (_pfnMenuChanged)
|
||||
_pfnMenuChanged(menuJson, replaceLength);
|
||||
}
|
||||
|
||||
@@ -750,6 +750,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
BASIC_FACTORY(RenameTabArgs);
|
||||
BASIC_FACTORY(SwapPaneArgs);
|
||||
BASIC_FACTORY(SplitPaneArgs);
|
||||
BASIC_FACTORY(SendInputArgs);
|
||||
BASIC_FACTORY(SetFocusModeArgs);
|
||||
BASIC_FACTORY(SetFullScreenArgs);
|
||||
BASIC_FACTORY(SetMaximizedArgs);
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
|
||||
[default_interface] runtimeclass SendInputArgs : IActionArgs
|
||||
{
|
||||
SendInputArgs(String input);
|
||||
String Input { get; };
|
||||
};
|
||||
|
||||
|
||||
@@ -637,4 +637,38 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
return newCommands;
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::Collections::IVector<Model::Command> Command::ParsePowerShellMenuComplete(winrt::hstring json, int32_t replaceLength)
|
||||
{
|
||||
auto data = winrt::to_string(json);
|
||||
|
||||
std::string errs;
|
||||
static std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||
Json::Value root;
|
||||
if (!reader->parse(data.data(), data.data() + data.size(), &root, &errs))
|
||||
{
|
||||
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
||||
}
|
||||
|
||||
auto result = winrt::single_threaded_vector<Model::Command>();
|
||||
|
||||
auto backspaces = std::wstring(::base::saturated_cast<size_t>(replaceLength), L'\x7f');
|
||||
for (const auto& element : root)
|
||||
{
|
||||
winrt::hstring completionText;
|
||||
winrt::hstring listText;
|
||||
JsonUtils::GetValueForKey(element, "CompletionText", completionText);
|
||||
JsonUtils::GetValueForKey(element, "ListItemText", listText);
|
||||
|
||||
Model::SendInputArgs args{ winrt::hstring{ fmt::format(L"{}{}", backspaces, completionText.c_str()) } };
|
||||
Model::ActionAndArgs actionAndArgs{ ShortcutAction::SendInput, args };
|
||||
Model::Command command{};
|
||||
command.ActionAndArgs(actionAndArgs);
|
||||
command.Name(listText);
|
||||
|
||||
result.Append(command);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
hstring IconPath() const noexcept;
|
||||
void IconPath(const hstring& val);
|
||||
|
||||
static Windows::Foundation::Collections::IVector<Model::Command> ParsePowerShellMenuComplete(winrt::hstring json, int32_t replaceLength);
|
||||
|
||||
winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker propertyChangedRevoker;
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
Command();
|
||||
|
||||
String Name { get; };
|
||||
ActionAndArgs ActionAndArgs { get; };
|
||||
String Name;
|
||||
ActionAndArgs ActionAndArgs;
|
||||
Microsoft.Terminal.Control.KeyChord Keys { get; };
|
||||
void RegisterKey(Microsoft.Terminal.Control.KeyChord keys);
|
||||
String KeyChordText { get; };
|
||||
@@ -47,5 +47,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Windows.Foundation.Collections.IVectorView<Profile> profiles,
|
||||
Windows.Foundation.Collections.IVectorView<ColorScheme> schemes,
|
||||
Windows.Foundation.Collections.IVector<SettingsLoadWarnings> warnings);
|
||||
|
||||
static IVector<Command> ParsePowerShellMenuComplete(String json, Int32 replaceLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,3 +493,7 @@ void ConhostInternalGetSet::AddMark(const Microsoft::Console::VirtualTerminal::D
|
||||
{
|
||||
// Not implemented for conhost.
|
||||
}
|
||||
void ConhostInternalGetSet::InvokeMenu(std::wstring_view /*menuJson*/, int32_t /*replaceLength*/)
|
||||
{
|
||||
// Not implemented for conhost.
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
void NotifyAccessibilityChange(const til::rect& changedRect) override;
|
||||
|
||||
void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) override;
|
||||
void InvokeMenu(std::wstring_view menuJson, int32_t replaceLength) override;
|
||||
|
||||
private:
|
||||
Microsoft::Console::IIoProvider& _io;
|
||||
|
||||
@@ -515,4 +515,14 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
|
||||
// Other things we may want to think about in the future are listed in
|
||||
// GH#11000
|
||||
};
|
||||
struct MenuEntry
|
||||
{
|
||||
std::wstring _name;
|
||||
std::wstring _comment;
|
||||
std::wstring _input;
|
||||
MenuEntry(std::wstring_view name, std::wstring_view comment, std::wstring_view input) :
|
||||
_name{ name }, _comment{ comment }, _input{ input }
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,6 +139,8 @@ public:
|
||||
|
||||
virtual bool DoFinalTermAction(const std::wstring_view string) = 0;
|
||||
|
||||
virtual bool DoXtermJsAction(const std::wstring_view string) = 0;
|
||||
|
||||
virtual StringHandler DownloadDRCS(const VTInt fontNumber,
|
||||
const VTParameter startChar,
|
||||
const DispatchTypes::DrcsEraseControl eraseControl,
|
||||
|
||||
@@ -78,5 +78,6 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual void NotifyAccessibilityChange(const til::rect& changedRect) = 0;
|
||||
|
||||
virtual void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) = 0;
|
||||
virtual void InvokeMenu(std::wstring_view menuJson, int32_t replaceLength) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2561,6 +2561,51 @@ bool AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Performs a XtermJs action
|
||||
// - Ascribes to the ITermDispatch interface
|
||||
// - Currently, the actions we support are:
|
||||
// * TODO!
|
||||
// - Not actually used in conhost
|
||||
// Arguments:
|
||||
// - string: contains the parameters that define which action we do
|
||||
// Return Value:
|
||||
// - false in conhost, true for the SetMark action, otherwise false.
|
||||
bool AdaptDispatch::DoXtermJsAction(const std::wstring_view string)
|
||||
{
|
||||
// This is not implemented in conhost.
|
||||
if (_api.IsConsolePty())
|
||||
{
|
||||
// Flush the frame manually, to make sure marks end up on the right line, like the alt buffer sequence.
|
||||
_renderer.TriggerFlush(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto parts = Utils::SplitString(string, L';');
|
||||
|
||||
if (parts.size() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto action = til::at(parts, 0);
|
||||
|
||||
if (action == L"Completions")
|
||||
{
|
||||
unsigned int replacementChars = 0;
|
||||
bool succeeded = (parts.size() >= 3) &&
|
||||
(Utils::StringToUint(til::at(parts, 2), replacementChars));
|
||||
if (succeeded)
|
||||
{
|
||||
_api.InvokeMenu(parts.size() < 4 ? L"" : til::at(parts, 3),
|
||||
static_cast<int32_t>(replacementChars));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - DECDLD - Downloads one or more characters of a dynamically redefinable
|
||||
// character set (DRCS) with a specified pixel pattern. The pixel array is
|
||||
|
||||
@@ -134,6 +134,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
|
||||
bool DoFinalTermAction(const std::wstring_view string) override;
|
||||
|
||||
bool DoXtermJsAction(const std::wstring_view string) override;
|
||||
|
||||
StringHandler DownloadDRCS(const VTInt fontNumber,
|
||||
const VTParameter startChar,
|
||||
const DispatchTypes::DrcsEraseControl eraseControl,
|
||||
|
||||
@@ -847,6 +847,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
||||
success = _dispatch->DoFinalTermAction(string);
|
||||
break;
|
||||
}
|
||||
case OscActionCodes::XtermJsAction:
|
||||
{
|
||||
success = _dispatch->DoXtermJsAction(string);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// If no functions to call, overall dispatch was a failure.
|
||||
success = false;
|
||||
|
||||
@@ -189,6 +189,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
ResetBackgroundColor = 111, // Not implemented
|
||||
ResetCursorColor = 112,
|
||||
FinalTermAction = 133,
|
||||
XtermJsAction = 633,
|
||||
ITerm2Action = 1337,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../inc/LibraryIncludes.h"
|
||||
|
||||
// #include <windows.h>
|
||||
// #include <stdio.h>
|
||||
// #include <iostream>
|
||||
|
||||
#define GS L"\x1D"
|
||||
#define US L"\x1F"
|
||||
#define DEL L"\x7F"
|
||||
#define ST L"\x07"
|
||||
|
||||
std::wstring trim(const std::wstring& str,
|
||||
const std::wstring& whitespace = L" \t")
|
||||
{
|
||||
const auto strBegin = str.find_first_not_of(whitespace);
|
||||
if (strBegin == std::wstring::npos)
|
||||
return L""; // no content
|
||||
|
||||
const auto strEnd = str.find_last_not_of(whitespace);
|
||||
const auto strRange = strEnd - strBegin + 1;
|
||||
|
||||
return str.substr(strBegin, strRange);
|
||||
}
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
|
||||
int __cdecl wmain(int argc, WCHAR* argv[])
|
||||
{
|
||||
wprintf(L"\x1b]9001;0\x07");
|
||||
|
||||
std::wstring prefix{};
|
||||
std::wstring suffix{};
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
std::wstring arg{ argv[i] };
|
||||
if (arg == L"--prefix" && (i + 1) <= argc)
|
||||
{
|
||||
prefix = argv[i + 1];
|
||||
i++;
|
||||
}
|
||||
else if (arg == L"--suffix" && (i + 1) <= argc)
|
||||
{
|
||||
suffix = argv[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::wstring line; std::getline(std::wcin, line);)
|
||||
{
|
||||
std::wstring trimmed{ trim(line) };
|
||||
std::wstring command{ fmt::format(L"{}{}{}", prefix, trimmed, suffix) };
|
||||
std::wstring entry{ fmt::format(L"\x1b]9001;1;{}\x7f{}\x7f{}\x7f{}\x07", trimmed, L"a comment", command, L"whatever extras we want") };
|
||||
wprintf(entry.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user