diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 685a98838..40440b2e7 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -29,6 +29,7 @@ namespace winrt::TerminalApp::implementation _currentNestedCommands = winrt::single_threaded_vector(); _allCommands = winrt::single_threaded_vector(); _tabActions = winrt::single_threaded_vector(); + _commandLineHistory = winrt::single_threaded_vector(); _switchToMode(CommandPaletteMode::ActionMode); @@ -303,21 +304,9 @@ namespace winrt::TerminalApp::implementation } else if (key == VirtualKey::Enter) { - // Action, TabSwitch or TabSearchMode Mode: Dispatch the action of the selected command. - if (_currentMode != CommandPaletteMode::CommandlineMode) - { - const auto selectedCommand = _filteredActionsView().SelectedItem(); - if (const auto filteredCommand = selectedCommand.try_as()) - { - _dispatchCommand(filteredCommand); - } - } - // Commandline Mode: Use the input to synthesize an ExecuteCommandline action - else if (_currentMode == CommandPaletteMode::CommandlineMode) - { - _dispatchCommandline(); - } - + const auto selectedCommand = _filteredActionsView().SelectedItem(); + const auto filteredCommand = selectedCommand.try_as(); + _dispatchCommand(filteredCommand); e.Handled(true); } else if (key == VirtualKey::Escape) @@ -538,7 +527,7 @@ namespace winrt::TerminalApp::implementation case CommandPaletteMode::TabSwitchMode: return _tabActions; case CommandPaletteMode::CommandlineMode: - return winrt::single_threaded_vector(); + return _commandLineHistory; default: return _allCommands; } @@ -555,7 +544,11 @@ namespace winrt::TerminalApp::implementation // - void CommandPalette::_dispatchCommand(winrt::TerminalApp::FilteredCommand const& filteredCommand) { - if (filteredCommand) + if (_currentMode == CommandPaletteMode::CommandlineMode) + { + _dispatchCommandline(filteredCommand); + } + else if (filteredCommand) { if (filteredCommand.Command().HasNestedCommands()) { @@ -628,32 +621,48 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Dispatch the current search text as a ExecuteCommandline action. // Arguments: - // - + // - filteredCommand - Selected filtered command - might be null // Return Value: // - - void CommandPalette::_dispatchCommandline() + void CommandPalette::_dispatchCommandline(winrt::TerminalApp::FilteredCommand const& command) { - auto cmdline{ _getTrimmedInput() }; - if (cmdline.empty()) + const auto filteredCommand = command ? command : _buildCommandLineCommand(_getTrimmedInput()); + if (filteredCommand.has_value()) { - return; + if (_commandLineHistory.Size() == CommandLineHistoryLength) + { + _commandLineHistory.RemoveAtEnd(); + } + _commandLineHistory.InsertAt(0, filteredCommand.value()); + + TraceLoggingWrite( + g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider + "CommandPaletteDispatchedCommandline", + TraceLoggingDescription("Event emitted when the user runs a commandline in the Command Palette"), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); + + if (_dispatch.DoAction(filteredCommand.value().Command().Action())) + { + _close(); + } + } + } + + std::optional CommandPalette::_buildCommandLineCommand(std::wstring const& commandLine) + { + if (commandLine.empty()) + { + return std::nullopt; } // Build the ExecuteCommandline action from the values we've parsed on the commandline. - ExecuteCommandlineArgs args{ cmdline }; + ExecuteCommandlineArgs args{ commandLine }; ActionAndArgs executeActionAndArgs{ ShortcutAction::ExecuteCommandline, args }; - - TraceLoggingWrite( - g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider - "CommandPaletteDispatchedCommandline", - TraceLoggingDescription("Event emitted when the user runs a commandline in the Command Palette"), - TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), - TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); - - if (_dispatch.DoAction(executeActionAndArgs)) - { - _close(); - } + Command command{}; + command.Action(executeActionAndArgs); + command.Name(commandLine); + return winrt::make(command); } // Method Description: @@ -698,7 +707,9 @@ namespace winrt::TerminalApp::implementation _lastFilterTextWasEmpty = _searchBox().Text().empty(); _updateFilteredActions(); - _filteredActionsView().SelectedIndex(0); + + // In the command line mode we want the user to explicitly select the command + _filteredActionsView().SelectedIndex(_currentMode == CommandPaletteMode::CommandlineMode ? -1 : 0); if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode) { @@ -871,7 +882,7 @@ namespace winrt::TerminalApp::implementation // We want to present the commands sorted, // unless we are in the TabSwitcherMode and TabSearchMode, // in which we want to preserve the original order (to be aligned with the tab view) - if (_currentMode != CommandPaletteMode::TabSearchMode && _currentMode != CommandPaletteMode::TabSwitchMode) + if (_currentMode != CommandPaletteMode::TabSearchMode && _currentMode != CommandPaletteMode::TabSwitchMode && _currentMode != CommandPaletteMode::CommandlineMode) { std::sort(actions.begin(), actions.end(), FilteredCommand::Compare); } @@ -887,12 +898,6 @@ namespace winrt::TerminalApp::implementation // - void CommandPalette::_updateFilteredActions() { - if (_currentMode == CommandPaletteMode::CommandlineMode) - { - _filteredActions.Clear(); - return; - } - auto actions = _collectFilteredActions(); // Make _filteredActions look identical to actions, using only Insert and Remove. diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index ae7b6dde0..364443cb5 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -117,12 +117,17 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Controls::ListView::SizeChanged_revoker _sizeChangedRevoker; void _dispatchCommand(winrt::TerminalApp::FilteredCommand const& command); - void _dispatchCommandline(); + void _dispatchCommandline(winrt::TerminalApp::FilteredCommand const& command); + std::optional _buildCommandLineCommand(std::wstring const& commandLine); + void _dismissPalette(); void _scrollToIndex(uint32_t index); uint32_t _getNumVisibleItems(); + static constexpr int CommandLineHistoryLength = 10; + Windows::Foundation::Collections::IVector _commandLineHistory{ nullptr }; + friend class TerminalAppLocalTests::TabTests; }; }