mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-16 11:11:03 +00:00
Compare commits
5 Commits
dev/lhecke
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b19458dd5 | ||
|
|
d77e3d5613 | ||
|
|
7b76ef8e7c | ||
|
|
21ce4bece0 | ||
|
|
ec36139bf6 |
@@ -8,6 +8,7 @@
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "SuggestionsControl.g.cpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::TerminalApp;
|
||||
@@ -19,6 +20,8 @@ using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
SuggestionsControl::SuggestionsControl()
|
||||
@@ -262,8 +265,8 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <unused>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void SuggestionsControl::_selectedCommandChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
winrt::fire_and_forget SuggestionsControl::_selectedCommandChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
const auto selectedCommand = _filteredActionsView().SelectedItem();
|
||||
const auto filteredCommand{ selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>() };
|
||||
@@ -281,11 +284,106 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
{
|
||||
PreviewAction.raise(*this, actionPaletteItem.Command());
|
||||
const auto& cmd = actionPaletteItem.Command();
|
||||
PreviewAction.raise(*this, cmd);
|
||||
|
||||
const auto description{ cmd.Description() };
|
||||
|
||||
if (SelectedItem())
|
||||
SelectedItem().SetValue(Automation::AutomationProperties::FullDescriptionProperty(), winrt::box_value(description));
|
||||
|
||||
if (!description.empty())
|
||||
{
|
||||
// If it's already open, then just re-target it and update the content immediately.
|
||||
if (_descriptionsView().Visibility() == Visibility::Visible)
|
||||
{
|
||||
_openTooltip(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, wait a bit before opening it.
|
||||
co_await winrt::resume_after(200ms);
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
_openTooltip(cmd);
|
||||
// DescriptionTip().IsOpen(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there's no description, then just close the tooltip.
|
||||
// DescriptionTip().IsOpen(false);
|
||||
_descriptionsView().Visibility(Visibility::Collapsed);
|
||||
_descriptionsBackdrop().Visibility(Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winrt::fire_and_forget SuggestionsControl::_openTooltip(Command cmd)
|
||||
{
|
||||
const auto description{ cmd.Description() };
|
||||
|
||||
if (!description.empty())
|
||||
{
|
||||
// DescriptionTip().Target(SelectedItem());
|
||||
// DescriptionTip().Title(cmd.Name());
|
||||
{
|
||||
// The Title
|
||||
_descriptionTitle().Inlines().Clear();
|
||||
Documents::Run titleRun;
|
||||
titleRun.Text(cmd.Name());
|
||||
_descriptionTitle().Inlines().Append(titleRun);
|
||||
}
|
||||
|
||||
// TODO! NOT REALLY TRUE ANYMORE
|
||||
// If you try to put a newline in the Subtitle, it'll _immediately
|
||||
// close the tooltip_. Instead, we'll need to build up the text as a
|
||||
// series of runs, and put them in the content.
|
||||
|
||||
_descriptionComment().Inlines().Clear();
|
||||
|
||||
// First, replace all "\r\n" with "\n"
|
||||
std::wstring filtered = description.c_str();
|
||||
|
||||
// replace all "\r\n" with "\n" in `filtered`
|
||||
std::wstring::size_type pos = 0;
|
||||
while ((pos = filtered.find(L"\r\n", pos)) != std::wstring::npos)
|
||||
{
|
||||
filtered.erase(pos, 1);
|
||||
}
|
||||
|
||||
// Split the filtered description on '\n`
|
||||
const auto lines = ::Microsoft::Console::Utils::SplitString(filtered.c_str(), L'\n');
|
||||
// For each line, build a Run + LineBreak, and add them to the text
|
||||
// block
|
||||
for (const auto& line : lines)
|
||||
{
|
||||
if (line.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Documents::Run textRun;
|
||||
textRun.Text(winrt::hstring{ line });
|
||||
_descriptionComment().Inlines().Append(textRun);
|
||||
_descriptionComment().Inlines().Append(Documents::LineBreak{});
|
||||
}
|
||||
|
||||
// // TODO! These were all feigned attempts to allow us to focus the content of the teachingtip.
|
||||
|
||||
// // We may want to keep IsTextSelectionEnabled in the XAML.
|
||||
// //
|
||||
// // I also have no idea if the FullDescriptionProperty thing worked at all.
|
||||
// _toolTipContent().AllowFocusOnInteraction(true);
|
||||
// _toolTipContent().IsTextSelectionEnabled(true);
|
||||
// DescriptionTip().SetValue(Automation::AutomationProperties::FullDescriptionProperty(), winrt::box_value(description));
|
||||
|
||||
_descriptionsView().Visibility(Visibility::Visible);
|
||||
_descriptionsBackdrop().Visibility(Visibility::Visible);
|
||||
_recalculateTopMargin();
|
||||
}
|
||||
co_return;
|
||||
}
|
||||
|
||||
void SuggestionsControl::_previewKeyDownHandler(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e)
|
||||
{
|
||||
@@ -1027,13 +1125,43 @@ namespace winrt::TerminalApp::implementation
|
||||
if (_direction == TerminalApp::SuggestionsDirection::TopDown)
|
||||
{
|
||||
Controls::Grid::SetRow(_searchBox(), 0);
|
||||
Controls::Grid::SetRow(_descriptionsBackdrop(), 2);
|
||||
}
|
||||
else // BottomUp
|
||||
{
|
||||
Controls::Grid::SetRow(_searchBox(), 4);
|
||||
Controls::Grid::SetRow(_descriptionsBackdrop(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SuggestionsControl::_recalculateTopMargin()
|
||||
{
|
||||
auto currentMargin = Margin();
|
||||
|
||||
const til::size actualSize{ til::math::rounding, ActualWidth(), ActualHeight() };
|
||||
const til::size descriptionSize{ til::math::rounding, _descriptionsBackdrop().ActualWidth(), _descriptionsBackdrop().ActualHeight() };
|
||||
|
||||
// Now, position vertically.
|
||||
if (_direction == TerminalApp::SuggestionsDirection::TopDown)
|
||||
{
|
||||
// The control should open right below the cursor, with the list
|
||||
// extending below. This is easy, we can just use the cursor as the
|
||||
// origin (more or less)
|
||||
currentMargin.Top = (_anchor.Y /* - descriptionSize.height*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bottom Up.
|
||||
|
||||
// TODO! This is all wrong. It just jumps around randomly.
|
||||
|
||||
// Position at the cursor. The suggestions UI itself will maintain
|
||||
// its own offset such that it's always above its origin
|
||||
currentMargin.Top = (_anchor.Y - actualSize.height /*+ descriptionSize.height*/);
|
||||
}
|
||||
Margin(currentMargin);
|
||||
}
|
||||
|
||||
void SuggestionsControl::Open(TerminalApp::SuggestionsMode mode,
|
||||
const Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::Command>& commands,
|
||||
winrt::hstring filter,
|
||||
@@ -1052,6 +1180,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_space = space;
|
||||
|
||||
const til::size actualSize{ til::math::rounding, ActualWidth(), ActualHeight() };
|
||||
const til::size descriptionSize{ til::math::rounding, _descriptionsBackdrop().ActualWidth(), _descriptionsBackdrop().ActualHeight() };
|
||||
// Is there space in the window below the cursor to open the menu downwards?
|
||||
const bool canOpenDownwards = (_anchor.Y + characterHeight + actualSize.height) < space.Height;
|
||||
_setDirection(canOpenDownwards ? TerminalApp::SuggestionsDirection::TopDown :
|
||||
@@ -1078,13 +1207,13 @@ namespace winrt::TerminalApp::implementation
|
||||
// The control should open right below the cursor, with the list
|
||||
// extending below. This is easy, we can just use the cursor as the
|
||||
// origin (more or less)
|
||||
newMargin.Top = (_anchor.Y);
|
||||
newMargin.Top = (_anchor.Y /* - descriptionSize.height*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Position at the cursor. The suggestions UI itself will maintain
|
||||
// its own offset such that it's always above its origin
|
||||
newMargin.Top = (_anchor.Y - actualSize.height);
|
||||
newMargin.Top = (_anchor.Y - actualSize.height /* - descriptionSize.height*/);
|
||||
}
|
||||
Margin(newMargin);
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void _close();
|
||||
void _dismissPalette();
|
||||
|
||||
void _recalculateTopMargin();
|
||||
|
||||
void _filterTextChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
void _previewKeyDownHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
|
||||
void _keyUpHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
|
||||
@@ -110,7 +112,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _listItemClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::ItemClickEventArgs& e);
|
||||
void _listItemSelectionChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e);
|
||||
void _selectedCommandChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
winrt::fire_and_forget _selectedCommandChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
winrt::fire_and_forget _openTooltip(Microsoft::Terminal::Settings::Model::Command cmd);
|
||||
|
||||
void _moveBackButtonClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs&);
|
||||
void _updateCurrentNestedCommands(const winrt::Microsoft::Terminal::Settings::Model::Command& parentCommand);
|
||||
@@ -122,7 +125,6 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _commandsToFilter();
|
||||
std::wstring _getTrimmedInput();
|
||||
uint32_t _getNumVisibleItems();
|
||||
|
||||
friend class TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -112,15 +112,17 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="8*" />
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="7*" />
|
||||
<RowDefinition Height="2*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid x:Name="_backdrop"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
MinWidth="300"
|
||||
MaxWidth="300"
|
||||
MaxHeight="300"
|
||||
Margin="0"
|
||||
@@ -136,16 +138,16 @@
|
||||
Translation="0,0,32">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<!-- 0: Top-down _searchBox -->
|
||||
<RowDefinition Height="Auto" />
|
||||
<!-- Top-down _searchBox -->
|
||||
<!-- 1: Top-down ParentCommandName -->
|
||||
<RowDefinition Height="Auto" />
|
||||
<!-- Top-down ParentCommandName -->
|
||||
<!-- 2: Top-down UNUSED???????? -->
|
||||
<RowDefinition Height="Auto" />
|
||||
<!-- Top-down UNUSED???????? -->
|
||||
<!-- 3: _filteredActionsView -->
|
||||
<RowDefinition Height="*" />
|
||||
<!-- _filteredActionsView -->
|
||||
<!-- 4: bottom-up _searchBox -->
|
||||
<RowDefinition Height="Auto" />
|
||||
<!-- bottom-up _searchBox -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBox x:Name="_searchBox"
|
||||
@@ -207,8 +209,55 @@
|
||||
SelectionChanged="_listItemSelectionChanged"
|
||||
SelectionMode="Single" />
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
<!-- <Border Height="1" Grid.Row="1" /> -->
|
||||
<Grid x:Name="_descriptionsBackdrop"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
MaxWidth="300"
|
||||
Margin="0,6,0,0"
|
||||
Padding="0,4,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{ThemeResource FlyoutPresenterBackground}"
|
||||
BorderBrush="{ThemeResource FlyoutBorderThemeBrush}"
|
||||
BorderThickness="{ThemeResource FlyoutBorderThemeThickness}"
|
||||
CornerRadius="{ThemeResource OverlayCornerRadius}"
|
||||
PointerPressed="_backdropPointerPressed"
|
||||
Shadow="{StaticResource SharedShadow}"
|
||||
Translation="0,0,32">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<!-- 0: descriptions view -->
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel x:Name="_descriptionsView"
|
||||
Grid.Row="0"
|
||||
Margin="8,0,8,8"
|
||||
Orientation="Vertical"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock x:Name="_descriptionTitle"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
IsTextSelectionEnabled="True"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<ScrollViewer MaxHeight="64"
|
||||
VerticalScrollBarVisibility="Visible"
|
||||
VerticalScrollMode="Enabled"
|
||||
Visibility="Visible">
|
||||
<!-- <TextBlock Text="Foo bar bax"
|
||||
TextWrapping="WrapWholeWords" />-->
|
||||
<TextBlock x:Name="_descriptionComment"
|
||||
IsTextSelectionEnabled="True"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -27,6 +27,7 @@ static constexpr std::string_view ArgsKey{ "args" };
|
||||
static constexpr std::string_view IterateOnKey{ "iterateOn" };
|
||||
static constexpr std::string_view CommandsKey{ "commands" };
|
||||
static constexpr std::string_view KeysKey{ "keys" };
|
||||
static constexpr std::string_view DescriptionKey{ "description" };
|
||||
|
||||
static constexpr std::string_view ProfileNameToken{ "${profile.name}" };
|
||||
static constexpr std::string_view ProfileIconToken{ "${profile.icon}" };
|
||||
@@ -44,6 +45,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
command->_keyMappings = _keyMappings;
|
||||
command->_iconPath = _iconPath;
|
||||
command->_IterateOn = _IterateOn;
|
||||
command->_Description = _Description;
|
||||
|
||||
command->_originalJson = _originalJson;
|
||||
command->_nestedCommand = _nestedCommand;
|
||||
@@ -264,6 +266,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
auto nested = false;
|
||||
JsonUtils::GetValueForKey(json, IterateOnKey, result->_IterateOn);
|
||||
JsonUtils::GetValueForKey(json, DescriptionKey, result->_Description);
|
||||
|
||||
// For iterable commands, we'll make another pass at parsing them once
|
||||
// the json is patched. So ignore parsing sub-commands for now. Commands
|
||||
@@ -416,6 +419,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Json::Value cmdJson{ Json::ValueType::objectValue };
|
||||
JsonUtils::SetValueForKey(cmdJson, IconKey, _iconPath);
|
||||
JsonUtils::SetValueForKey(cmdJson, NameKey, _name);
|
||||
JsonUtils::SetValueForKey(cmdJson, DescriptionKey, _Description);
|
||||
|
||||
if (_ActionAndArgs)
|
||||
{
|
||||
@@ -436,6 +440,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// First iteration also writes icon and name
|
||||
JsonUtils::SetValueForKey(cmdJson, IconKey, _iconPath);
|
||||
JsonUtils::SetValueForKey(cmdJson, NameKey, _name);
|
||||
JsonUtils::SetValueForKey(cmdJson, DescriptionKey, _Description);
|
||||
}
|
||||
|
||||
if (_ActionAndArgs)
|
||||
@@ -664,8 +669,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
const auto parseElement = [&](const auto& element) {
|
||||
winrt::hstring completionText;
|
||||
winrt::hstring listText;
|
||||
winrt::hstring tooltipText;
|
||||
JsonUtils::GetValueForKey(element, "CompletionText", completionText);
|
||||
JsonUtils::GetValueForKey(element, "ListItemText", listText);
|
||||
JsonUtils::GetValueForKey(element, "ToolTip", tooltipText);
|
||||
|
||||
auto args = winrt::make_self<SendInputArgs>(
|
||||
winrt::hstring{ fmt::format(FMT_COMPILE(L"{:\x7f^{}}{}"),
|
||||
@@ -677,8 +684,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
auto c = winrt::make_self<Command>();
|
||||
c->_name = listText;
|
||||
c->_Description = tooltipText;
|
||||
c->_ActionAndArgs = actionAndArgs;
|
||||
|
||||
// Try to assign a sensible icon based on the result type. These are
|
||||
// roughly chosen to align with the icons in
|
||||
// https://github.com/PowerShell/PowerShellEditorServices/pull/1738
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None);
|
||||
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs);
|
||||
WINRT_PROPERTY(winrt::hstring, Description, L"");
|
||||
|
||||
private:
|
||||
Json::Value _originalJson;
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Command();
|
||||
|
||||
String Name { get; };
|
||||
String Description { get; };
|
||||
ActionAndArgs ActionAndArgs { get; };
|
||||
Microsoft.Terminal.Control.KeyChord Keys { get; };
|
||||
void RegisterKey(Microsoft.Terminal.Control.KeyChord keys);
|
||||
|
||||
@@ -24,12 +24,14 @@ try
|
||||
|
||||
_pProvider = pProvider;
|
||||
_pData = pData;
|
||||
_pData->LockConsole();
|
||||
_start = pData->GetViewport().Origin();
|
||||
_end = pData->GetViewport().Origin();
|
||||
_blockRange = false;
|
||||
_wordDelimiters = wordDelimiters;
|
||||
|
||||
UiaTracing::TextRange::Constructor(*this);
|
||||
_pData->UnlockConsole();
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
Reference in New Issue
Block a user