Skip to content

Commit

Permalink
[ainulindale] Expand commands in the AppLogic, not on each page
Browse files Browse the repository at this point in the history
  TerminalPage is the thing that ends up expanding iterable Command. It does
  this largely with copies - it makes a new map, a new vector, copies the
  Commands over, and does the work there before setting up the cmdpal.

  Except, it's not making a copy of the Commands, it's making a copy of the
  vector, with winrt objects all pointing at the Command objects that are
  ultimately owned by CascadiaSettings.

  This doesn't matter if there's only one TerminalPage - we'll only ever do that once.

  If there's many, on different threads, then one tpage will end up expanding
  the subcommands of one Command while another tpage is ALSO iterating on those
  subcommands. Hence why I'm getting `hresult_changed_state`s

(cherry picked from commit 2122eec)
  • Loading branch information
zadjii-msft committed Feb 7, 2023
1 parent f06e484 commit 2822c36
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 85 deletions.
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ namespace winrt::TerminalApp::implementation
}

_settings = std::move(newSettings);

_settings.ExpandCommands();

hr = (_warnings.Size()) == 0 ? S_OK : S_FALSE;
}
catch (const winrt::hresult_error& e)
Expand Down
83 changes: 2 additions & 81 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,36 +97,6 @@ namespace winrt::TerminalApp::implementation
return S_OK;
}

// Function Description:
// - Recursively check our commands to see if there's a keybinding for
// exactly their action. If there is, label that command with the text
// corresponding to that key chord.
// - Will recurse into nested commands as well.
// Arguments:
// - settings: The settings who's keybindings we should use to look up the key chords from
// - commands: The list of commands to label.
static void _recursiveUpdateCommandKeybindingLabels(CascadiaSettings settings,
IMapView<winrt::hstring, Command> commands)
{
for (const auto& nameAndCmd : commands)
{
const auto& command = nameAndCmd.Value();
if (command.HasNestedCommands())
{
_recursiveUpdateCommandKeybindingLabels(settings, command.NestedCommands());
}
else
{
// If there's a keybinding that's bound to exactly this command,
// then get the keychord and display it as a
// part of the command in the UI.
// We specifically need to do this for nested commands.
const auto keyChord{ settings.ActionMap().GetKeyBindingForAction(command.ActionAndArgs().Action(), command.ActionAndArgs().Args()) };
command.RegisterKey(keyChord);
}
}
}

winrt::fire_and_forget TerminalPage::SetSettings(CascadiaSettings settings, bool needRefreshUI)
{
_settings = settings;
Expand Down Expand Up @@ -2974,50 +2944,6 @@ namespace winrt::TerminalApp::implementation
}
}

// This is a helper to aid in sorting commands by their `Name`s, alphabetically.
static bool _compareSchemeNames(const ColorScheme& lhs, const ColorScheme& rhs)
{
std::wstring leftName{ lhs.Name() };
std::wstring rightName{ rhs.Name() };
return leftName.compare(rightName) < 0;
}

// Method Description:
// - Takes a mapping of names->commands and expands them
// Arguments:
// - <none>
// Return Value:
// - <none>
IMap<winrt::hstring, Command> TerminalPage::_ExpandCommands(IMapView<winrt::hstring, Command> commandsToExpand,
IVectorView<Profile> profiles,
IMapView<winrt::hstring, ColorScheme> schemes)
{
auto warnings{ winrt::single_threaded_vector<SettingsLoadWarnings>() };

std::vector<ColorScheme> sortedSchemes;
sortedSchemes.reserve(schemes.Size());

for (const auto& nameAndScheme : schemes)
{
sortedSchemes.push_back(nameAndScheme.Value());
}
std::sort(sortedSchemes.begin(),
sortedSchemes.end(),
_compareSchemeNames);

auto copyOfCommands = winrt::single_threaded_map<winrt::hstring, Command>();
for (const auto& nameAndCommand : commandsToExpand)
{
copyOfCommands.Insert(nameAndCommand.Key(), nameAndCommand.Value());
}

Command::ExpandCommands(copyOfCommands,
profiles,
{ sortedSchemes },
warnings);

return copyOfCommands;
}
// Method Description:
// - Repopulates the list of commands in the command palette with the
// current commands in the settings. Also updates the keybinding labels to
Expand All @@ -3028,15 +2954,10 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_UpdateCommandsForPalette()
{
auto copyOfCommands = _ExpandCommands(_settings.GlobalSettings().ActionMap().NameMap(),
_settings.ActiveProfiles().GetView(),
_settings.GlobalSettings().ColorSchemes());

_recursiveUpdateCommandKeybindingLabels(_settings, copyOfCommands.GetView());

// Update the command palette when settings reload
const auto& expanded{ _settings.GlobalSettings().ActionMap().ExpandedCommands() };
auto commandsCollection = winrt::single_threaded_vector<Command>();
for (const auto& nameAndCommand : copyOfCommands)
for (const auto& nameAndCommand : expanded)
{
commandsCollection.Append(nameAndCommand.Value());
}
Expand Down
4 changes: 0 additions & 4 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,6 @@ namespace winrt::TerminalApp::implementation
void _UpdateCommandsForPalette();
void _SetBackgroundImage(const winrt::Microsoft::Terminal::Settings::Model::IAppearanceConfig& newAppearance);

static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, Microsoft::Terminal::Settings::Model::Command> _ExpandCommands(Windows::Foundation::Collections::IMapView<winrt::hstring, Microsoft::Terminal::Settings::Model::Command> commandsToExpand,
Windows::Foundation::Collections::IVectorView<Microsoft::Terminal::Settings::Model::Profile> profiles,
Windows::Foundation::Collections::IMapView<winrt::hstring, Microsoft::Terminal::Settings::Model::ColorScheme> schemes);

void _DuplicateFocusedTab();
void _DuplicateTab(const TerminalTab& tab);

Expand Down
75 changes: 75 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,4 +854,79 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
cmd->ActionAndArgs(action);
AddAction(*cmd);
}

void ActionMap::_recursiveUpdateCommandKeybindingLabels()
{
const auto& commands{ _ExpandedMapCache };

for (const auto& nameAndCmd : commands)
{
const auto& command = nameAndCmd.Value();
if (command.HasNestedCommands())
{
_recursiveUpdateCommandKeybindingLabels();
}
else
{
// If there's a keybinding that's bound to exactly this command,
// then get the keychord and display it as a
// part of the command in the UI.
// We specifically need to do this for nested commands.
const auto keyChord{ GetKeyBindingForAction(command.ActionAndArgs().Action(),
command.ActionAndArgs().Args()) };
command.RegisterKey(keyChord);
}
}
}

// This is a helper to aid in sorting commands by their `Name`s, alphabetically.
static bool _compareSchemeNames(const ColorScheme& lhs, const ColorScheme& rhs)
{
std::wstring leftName{ lhs.Name() };
std::wstring rightName{ rhs.Name() };
return leftName.compare(rightName) < 0;
}

void ActionMap::ExpandCommands(const winrt::Windows::Foundation::Collections::IVectorView<Model::Profile>& profiles,
const winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, Model::ColorScheme>& schemes)
{
// TODO in review - It's a little weird to stash the expanded commands
// into a separate map. Is it possible to just replace the name map with
// the post-expanded commands?
//
// WHILE also making sure that upon re-saving the commands, we don't
// actually serialize the results of the expansion. I don't think it is.

auto warnings{ winrt::single_threaded_vector<SettingsLoadWarnings>() };

std::vector<Model::ColorScheme> sortedSchemes;
sortedSchemes.reserve(schemes.Size());

for (const auto& nameAndScheme : schemes)
{
sortedSchemes.push_back(nameAndScheme.Value());
}
std::sort(sortedSchemes.begin(),
sortedSchemes.end(),
_compareSchemeNames);

auto copyOfCommands = winrt::single_threaded_map<winrt::hstring, Model::Command>();

const auto& commandsToExpand{ NameMap() };
for (const auto& nameAndCommand : commandsToExpand)
{
copyOfCommands.Insert(nameAndCommand.Key(), nameAndCommand.Value());
}

Command::ExpandCommands(copyOfCommands,
profiles,
winrt::param::vector_view<Model::ColorScheme>{ sortedSchemes },
warnings);

_ExpandedMapCache = copyOfCommands;
}
Windows::Foundation::Collections::IMapView<hstring, Model::Command> ActionMap::ExpandedCommands()
{
return _ExpandedMapCache.GetView();
}
}
8 changes: 8 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void DeleteKeyBinding(const Control::KeyChord& keys);
void RegisterKeyBinding(Control::KeyChord keys, Model::ActionAndArgs action);

Windows::Foundation::Collections::IMapView<hstring, Model::Command> ExpandedCommands();
void ExpandCommands(const Windows::Foundation::Collections::IVectorView<Model::Profile>& profiles,
const Windows::Foundation::Collections::IMapView<winrt::hstring, Model::ColorScheme>& schemes);

private:
std::optional<Model::Command> _GetActionByID(const InternalActionID actionID) const;
std::optional<Model::Command> _GetActionByKeyChordInternal(const Control::KeyChord& keys) const;
Expand All @@ -90,11 +94,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void _TryUpdateName(const Model::Command& cmd, const Model::Command& oldCmd, const Model::Command& consolidatedCmd);
void _TryUpdateKeyChord(const Model::Command& cmd, const Model::Command& oldCmd, const Model::Command& consolidatedCmd);

void _recursiveUpdateCommandKeybindingLabels();

Windows::Foundation::Collections::IMap<hstring, Model::ActionAndArgs> _AvailableActionsCache{ nullptr };
Windows::Foundation::Collections::IMap<hstring, Model::Command> _NameMapCache{ nullptr };
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _GlobalHotkeysCache{ nullptr };
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _KeyBindingMapCache{ nullptr };

Windows::Foundation::Collections::IMap<hstring, Model::Command> _ExpandedMapCache{ nullptr };

std::unordered_map<winrt::hstring, Model::Command> _NestedCommands;
std::vector<Model::Command> _IterableCommands;
std::unordered_map<Control::KeyChord, InternalActionID, KeyChordHash, KeyChordEquality> _KeyMap;
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/ActionMap.idl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace Microsoft.Terminal.Settings.Model
Windows.Foundation.Collections.IMapView<String, Command> NameMap { get; };
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Command> KeyBindings { get; };
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Command> GlobalHotkeys { get; };

Windows.Foundation.Collections.IMapView<String, Command> ExpandedCommands { get; };
};

[default_interface] runtimeclass ActionMap : IActionMapView
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1214,3 +1214,8 @@ void CascadiaSettings::_validateThemeExists()
}
}
}

void CascadiaSettings::ExpandCommands()
{
_globals->ExpandCommands(ActiveProfiles().GetView(), GlobalSettings().ColorSchemes());
}
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/CascadiaSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Model::DefaultTerminal CurrentDefaultTerminal() noexcept;
void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal);

void ExpandCommands();

private:
static const std::filesystem::path& _settingsPath();
static const std::filesystem::path& _releaseSettingsPath();
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/CascadiaSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,7 @@ namespace Microsoft.Terminal.Settings.Model
static Boolean IsDefaultTerminalSet { get; };
IObservableVector<DefaultTerminal> DefaultTerminals { get; };
DefaultTerminal CurrentDefaultTerminal;

void ExpandCommands();
}
}
6 changes: 6 additions & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,9 @@ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Microso
{
return _themes.GetView();
}

void GlobalAppSettings::ExpandCommands(const winrt::Windows::Foundation::Collections::IVectorView<Model::Profile>& profiles,
const winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, Model::ColorScheme>& schemes)
{
_actionMap->ExpandCommands(profiles, schemes);
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void AddTheme(const Model::Theme& theme);
Model::Theme CurrentTheme() noexcept;

void ExpandCommands(const Windows::Foundation::Collections::IVectorView<Model::Profile>& profiles,
const Windows::Foundation::Collections::IMapView<winrt::hstring, Model::ColorScheme>& schemes);

INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");

#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
Expand Down

1 comment on commit 2822c36

@github-actions
Copy link

Choose a reason for hiding this comment

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

@check-spelling-bot Report

🔴 Please review

See the 📜action log for details.

Unrecognized words (5)

APeasant
applogic
connectecd
onarch
wehn

Previously acknowledged words that are now absent CLA demoable everytime Hirots inthread reingest unmark :arrow_right:
To accept ✔️ these unrecognized words as correct and remove the previously acknowledged and now absent words, run the following commands

... in a clone of the git@github.com:microsoft/terminal.git repository
on the dev/migrie/oop/3/ainulindale branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.21/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/4119066402/attempts/1'
Errors (1)

See the 📜action log for details.

❌ Errors Count
❌ forbidden-pattern 1

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. If it doesn't work for you, you can manually add (one word per line) / remove items to expect.txt and the excludes.txt files.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.