ResultHelper.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 System;
  6  using System.Collections.Generic;
  7  using System.Diagnostics;
  8  using System.Globalization;
  9  using System.Linq;
 10  using System.Text;
 11  using Microsoft.CmdPal.Ext.WindowsSettings.Commands;
 12  using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
 13  using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
 14  using Microsoft.CommandPalette.Extensions.Toolkit;
 15  
 16  namespace Microsoft.CmdPal.Ext.WindowsSettings;
 17  
 18  /// <summary>
 19  /// Helper class to easier work with List Items
 20  /// </summary>
 21  internal static class ResultHelper
 22  {
 23      internal static List<ListItem> GetResultList(
 24          in IEnumerable<Classes.WindowsSetting> list)
 25      {
 26          var resultList = new List<ListItem>(list.Count());
 27  
 28          foreach (var entry in list)
 29          {
 30              var result = new ListItem(new OpenSettingsCommand(entry))
 31              {
 32                  Icon = Icons.WindowsSettingsIcon,
 33                  Subtitle = entry.JoinedFullSettingsPath,
 34                  Title = entry.Name,
 35                  MoreCommands = ContextMenuHelper.GetContextMenu(entry).ToArray(),
 36              };
 37  
 38              // TODO GH #126 investigate tooltips
 39              // AddOptionalToolTip(entry, result);
 40  
 41              // There is a case with MMC snap-ins where we don't have .msc files fort them. Then we need to show the note for this results in subtitle too.
 42              // These results have mmc.exe as command and their note property is filled.
 43              if (entry.Command == "mmc.exe" && !string.IsNullOrEmpty(entry.Note))
 44              {
 45                  result.Subtitle += $"\u0020\u0020\u002D\u0020\u0020{Resources.Note}: {entry.Note}"; // "\u0020\u0020\u002D\u0020\u0020" = "<space><space><minus><space><space>"
 46              }
 47  
 48              // To not show duplicate entries we check the existing results on the list before adding the new entry. Example: Device Manager entry for Control Panel and Device Manager entry for MMC.
 49              if (!resultList.Any(x => x.Title == result.Title))
 50              {
 51                  resultList.Add(result);
 52              }
 53          }
 54  
 55          // TODO GH #127 --> Investigate scoring
 56  
 57          // SetScores(resultList, query);
 58          return resultList;
 59      }
 60  
 61      /// <summary>
 62      /// Checks if a setting <see cref="WindowsSetting"/> matches the search string <see cref="Query.Search"/> to filter settings by settings path.
 63      /// This method is called from the <see cref="Predicate{T}"/> method in <see cref="Main.Query(Query)"/> if the search string <see cref="Query.Search"/> contains the character ">".
 64      /// </summary>
 65      /// <param name="found">The WindowsSetting's result that should be checked.</param>
 66      /// <param name="queryString">The searchString entered by the user <see cref="Query.Search"/>s.</param>
 67      internal static bool FilterBySettingsPath(in Classes.WindowsSetting found, in string queryString)
 68      {
 69          if (!queryString.Contains('>'))
 70          {
 71              return false;
 72          }
 73  
 74          // Init vars
 75          var queryElements = queryString.Split('>');
 76  
 77          List<string> settingsPath = new List<string>();
 78          settingsPath.Add(found.Type);
 79          if (!(found.Areas is null))
 80          {
 81              settingsPath.AddRange(found.Areas);
 82          }
 83  
 84          // Compare query and settings path
 85          for (var i = 0; i < queryElements.Length; i++)
 86          {
 87              if (string.IsNullOrWhiteSpace(queryElements[i]))
 88              {
 89                  // The queryElement is an WhiteSpace. Nothing to compare.
 90                  break;
 91              }
 92  
 93              if (i < settingsPath.Count)
 94              {
 95                  if (!settingsPath[i].StartsWith(queryElements[i], StringComparison.CurrentCultureIgnoreCase))
 96                  {
 97                      return false;
 98                  }
 99              }
100              else
101              {
102                  // The user has entered more query parts than existing elements in settings path.
103                  return false;
104              }
105          }
106  
107          // Return "true" if <found> matches <queryString>.
108          return true;
109      }
110  }