AliasManager.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using CommunityToolkit.Mvvm.ComponentModel;
  6  using CommunityToolkit.Mvvm.Messaging;
  7  using Microsoft.CmdPal.Core.ViewModels.Messages;
  8  
  9  namespace Microsoft.CmdPal.UI.ViewModels;
 10  
 11  public partial class AliasManager : ObservableObject
 12  {
 13      private readonly TopLevelCommandManager _topLevelCommandManager;
 14  
 15      // REMEMBER, CommandAlias.SearchPrefix is what we use as keys
 16      private readonly Dictionary<string, CommandAlias> _aliases;
 17  
 18      public AliasManager(TopLevelCommandManager tlcManager, SettingsModel settings)
 19      {
 20          _topLevelCommandManager = tlcManager;
 21          _aliases = settings.Aliases;
 22  
 23          if (_aliases.Count == 0)
 24          {
 25              PopulateDefaultAliases();
 26          }
 27      }
 28  
 29      private void AddAlias(CommandAlias a) => _aliases.Add(a.SearchPrefix, a);
 30  
 31      public bool CheckAlias(string searchText)
 32      {
 33          if (_aliases.TryGetValue(searchText, out var alias))
 34          {
 35              try
 36              {
 37                  var topLevelCommand = _topLevelCommandManager.LookupCommand(alias.CommandId);
 38                  if (topLevelCommand is not null)
 39                  {
 40                      WeakReferenceMessenger.Default.Send<ClearSearchMessage>();
 41  
 42                      WeakReferenceMessenger.Default.Send<PerformCommandMessage>(topLevelCommand.GetPerformCommandMessage());
 43                      return true;
 44                  }
 45              }
 46              catch
 47              {
 48              }
 49          }
 50  
 51          return false;
 52      }
 53  
 54      private void PopulateDefaultAliases()
 55      {
 56          this.AddAlias(new CommandAlias(":", "com.microsoft.cmdpal.registry", true));
 57          this.AddAlias(new CommandAlias("$", "com.microsoft.cmdpal.windowsSettings", true));
 58          this.AddAlias(new CommandAlias("=", "com.microsoft.cmdpal.calculator", true));
 59          this.AddAlias(new CommandAlias(">", "com.microsoft.cmdpal.shell", true));
 60          this.AddAlias(new CommandAlias("<", "com.microsoft.cmdpal.windowwalker", true));
 61          this.AddAlias(new CommandAlias("??", "com.microsoft.cmdpal.websearch", true));
 62          this.AddAlias(new CommandAlias("file", "com.microsoft.indexer.fileSearch", false));
 63          this.AddAlias(new CommandAlias(")", "com.microsoft.cmdpal.timedate", true));
 64      }
 65  
 66      public string? KeysFromId(string commandId)
 67      {
 68          return _aliases
 69              .Where(kv => kv.Value.CommandId == commandId)
 70              .Select(kv => kv.Value.Alias)
 71              .FirstOrDefault();
 72      }
 73  
 74      public CommandAlias? AliasFromId(string commandId)
 75      {
 76          return _aliases
 77              .Where(kv => kv.Value.CommandId == commandId)
 78              .Select(kv => kv.Value)
 79              .FirstOrDefault();
 80      }
 81  
 82      public void UpdateAlias(string commandId, CommandAlias? newAlias)
 83      {
 84          if (string.IsNullOrEmpty(commandId))
 85          {
 86              // do nothing?
 87              return;
 88          }
 89  
 90          // If we already have _this exact alias_, do nothing
 91          if (newAlias is not null &&
 92              _aliases.TryGetValue(newAlias.SearchPrefix, out var existingAlias))
 93          {
 94              if (existingAlias.CommandId == commandId)
 95              {
 96                  return;
 97              }
 98          }
 99  
100          List<CommandAlias> toRemove = [];
101          foreach (var kv in _aliases)
102          {
103              // Look for the old aliases for the command, and remove it
104              if (kv.Value.CommandId == commandId)
105              {
106                  toRemove.Add(kv.Value);
107              }
108  
109              // Look for the alias belonging to another command, and remove it
110              if (newAlias is not null && kv.Value.Alias == newAlias.Alias && kv.Value.CommandId != commandId)
111              {
112                  toRemove.Add(kv.Value);
113  
114                  // Remove alias from other TopLevelViewModels it may be assigned to
115                  var topLevelCommand = _topLevelCommandManager.LookupCommand(kv.Value.CommandId);
116                  if (topLevelCommand is not null)
117                  {
118                      topLevelCommand.AliasText = string.Empty;
119                  }
120              }
121          }
122  
123          foreach (var alias in toRemove)
124          {
125              // REMEMBER, SearchPrefix is what we use as keys
126              _aliases.Remove(alias.SearchPrefix);
127          }
128  
129          if (newAlias is not null)
130          {
131              AddAlias(newAlias);
132          }
133      }
134  }