From 274f5a74f557ef59e6414822acd31e3bb6865482 Mon Sep 17 00:00:00 2001 From: Don-Vito Date: Wed, 25 Nov 2020 22:30:36 +0200 Subject: [PATCH] Add "recent commands" to Command Palette in commandline mode (#8317) ## Summary of the Pull Request Add a history to command palette in the command line mode. Few considerations/limitations 1. In-memory, 10 entries hard-coded 2. MRU 3. List rather than set 4. The user needs explicitly select command from the history ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/issues/8296 * [x] CLA signed. * [x] Tests added/passed * [ ] Documentation updated - irrelevant * [ ] Schema updated - irrelevant * [ ] I've discussed this with core contributors already. ## Validation Steps Performed * Manual testing --- src/cascadia/TerminalApp/CommandPalette.cpp | 89 +++++++++++---------- src/cascadia/TerminalApp/CommandPalette.h | 7 +- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 685a98838f0..40440b2e7fe 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()); - // Build the ExecuteCommandline action from the values we've parsed on the commandline. - ExecuteCommandlineArgs args{ cmdline }; - 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)); - 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(); + } + } + } - if (_dispatch.DoAction(executeActionAndArgs)) + std::optional CommandPalette::_buildCommandLineCommand(std::wstring const& commandLine) + { + if (commandLine.empty()) { - _close(); + return std::nullopt; } + + // Build the ExecuteCommandline action from the values we've parsed on the commandline. + ExecuteCommandlineArgs args{ commandLine }; + ActionAndArgs executeActionAndArgs{ ShortcutAction::ExecuteCommandline, args }; + 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 ae7b6dde0e6..364443cb590 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; }; }