Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,15 +1454,17 @@ namespace winrt::TerminalApp::implementation
const auto source = realArgs.Source();
std::vector<Command> commandsCollection;
Control::CommandHistoryContext context{ nullptr };
winrt::hstring currentCommandline;
winrt::hstring currentWorkingDirectory;
winrt::hstring filter;

bool sortResults = source == SuggestionsSource::Scrollback;
Copy link
Contributor Author

@e82eric e82eric Jul 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the scroll back source having matches with the highest score and then the ordinal sort first felt like it had the best UX.


// If the user wanted to use the current commandline to filter results,
// OR they wanted command history (or some other source that
// requires context from the control)
// then get that here.
const bool shouldGetContext = realArgs.UseCommandline() ||
WI_IsAnyFlagSet(source, SuggestionsSource::CommandHistory | SuggestionsSource::QuickFixes);
WI_IsAnyFlagSet(source, SuggestionsSource::CommandHistory | SuggestionsSource::QuickFixes | SuggestionsSource::Scrollback);
if (const auto& control{ _GetActiveControl() })
{
currentWorkingDirectory = control.CurrentWorkingDirectory();
Expand All @@ -1472,7 +1474,9 @@ namespace winrt::TerminalApp::implementation
context = control.CommandHistory();
if (context)
{
currentCommandline = context.CurrentCommandline();
winrt::hstring currentCommandline = context.CurrentCommandline();
winrt::hstring currentWordPrefix = context.CurrentWordPrefix();
filter = source == SuggestionsSource::Scrollback ? currentWordPrefix : currentCommandline;
}
}
}
Expand All @@ -1496,7 +1500,7 @@ namespace winrt::TerminalApp::implementation
// their settings file. Ask the ActionMap for those.
if (WI_IsFlagSet(source, SuggestionsSource::Tasks))
{
const auto tasks = co_await _settings.GlobalSettings().ActionMap().FilterToSnippets(currentCommandline, currentWorkingDirectory);
const auto tasks = co_await _settings.GlobalSettings().ActionMap().FilterToSnippets(filter, currentWorkingDirectory);
// ----- we may be on a background thread here -----
for (const auto& t : tasks)
{
Expand All @@ -1510,20 +1514,41 @@ namespace winrt::TerminalApp::implementation
if (WI_IsFlagSet(source, SuggestionsSource::CommandHistory) &&
context != nullptr)
{
const auto recentCommands = Command::HistoryToCommands(context.History(), currentCommandline, false, hstring{ L"\ue81c" });
const auto recentCommands = Command::HistoryToCommands(context.History(), filter, false, hstring{ L"\ue81c" });
for (const auto& t : recentCommands)
{
commandsCollection.push_back(t);
}
}

// Don't add this to All, or figure out a way to make it experimental
if (source == SuggestionsSource::Scrollback)
{
if (const auto termControl{ _GetActiveControl() })
{
const auto scrollBackResults = termControl.SuggestionScrollBackSearch(realArgs.Regex());

std::unordered_set<winrt::hstring> seen;
seen.reserve(scrollBackResults.Size());
for (auto r : scrollBackResults)
{
if (seen.insert(r.Text).second)
{
auto c = Command::ScrollBackSuggestionToCommand(r.Text, filter, r.Row);
commandsCollection.push_back(c);
}
}
}
}

co_await wil::resume_foreground(Dispatcher());

// Open the palette with all these commands in it.
_OpenSuggestions(_GetActiveControl(),
winrt::single_threaded_vector<Command>(std::move(commandsCollection)),
SuggestionsMode::Palette,
currentCommandline);
filter,
sortResults);
}

void TerminalPage::_HandleColorSelection(const IInspectable& /*sender*/,
Expand Down
19 changes: 17 additions & 2 deletions src/cascadia/TerminalApp/FilteredCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,23 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;

namespace winrt::TerminalApp::implementation
{
// This class is a wrapper of IPaletteItem, that is used as an item of a filterable list in CommandPalette.
int32_t FilteredCommand::Ordinal()
{
return _ordinal;
}

FilteredCommand::FilteredCommand(const winrt::TerminalApp::IPaletteItem& item) :
FilteredCommand(item, 0)
{
}

// This class is a wrapper of PaletteItem, that is used as an item of a filterable list in CommandPalette.
// It manages a highlighted text that is computed by matching search filter characters to item name
FilteredCommand::FilteredCommand(const winrt::TerminalApp::IPaletteItem& item)
FilteredCommand::FilteredCommand(const winrt::TerminalApp::IPaletteItem& item, int32_t ordinal)
{
// Actually implement the ctor in _constructFilteredCommand
_constructFilteredCommand(item);
_ordinal = ordinal;
}

// We need to actually implement the ctor in a separate helper. This is
Expand Down Expand Up @@ -111,6 +122,10 @@ namespace winrt::TerminalApp::implementation

if (firstWeight == secondWeight)
{
if (first.Ordinal() != second.Ordinal())
{
return first.Ordinal() < second.Ordinal();
}
const auto firstName = first.Item().Name();
const auto secondName = second.Item().Name();
return til::compare_linguistic_insensitive(firstName, secondName) < 0;
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/FilteredCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace winrt::TerminalApp::implementation
{
FilteredCommand() = default;
FilteredCommand(const winrt::TerminalApp::IPaletteItem& item);
FilteredCommand(const winrt::TerminalApp::IPaletteItem& item, int32_t ordinal);

virtual void UpdateFilter(std::shared_ptr<fzf::matcher::Pattern> pattern);

Expand All @@ -29,13 +30,17 @@ namespace winrt::TerminalApp::implementation
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, NameHighlights, PropertyChanged.raise);
WINRT_OBSERVABLE_PROPERTY(int, Weight, PropertyChanged.raise);

public:
int32_t Ordinal();

protected:
void _constructFilteredCommand(const winrt::TerminalApp::IPaletteItem& item);

private:
std::shared_ptr<fzf::matcher::Pattern> _pattern;
void _update();
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _itemChangedRevoker;
int32_t _ordinal;

friend class TerminalAppLocalTests::FilteredCommandTests;
};
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/FilteredCommand.idl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ namespace TerminalApp
{
FilteredCommand();
FilteredCommand(IPaletteItem item);
FilteredCommand(IPaletteItem item, Int32 ordinal);

IPaletteItem Item { get; };
IVector<HighlightedRun> NameHighlights { get; };
Int32 Weight;
Int32 Ordinal { get; };
}
}
Loading