/ src / modules / cmdpal / Microsoft.CmdPal.UI.ViewModels / RecentCommandsManager.cs
RecentCommandsManager.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.Text.Json.Serialization;
 6  using CommunityToolkit.Mvvm.ComponentModel;
 7  
 8  namespace Microsoft.CmdPal.UI.ViewModels;
 9  
10  public partial class RecentCommandsManager : ObservableObject, IRecentCommandsManager
11  {
12      [JsonInclude]
13      internal List<HistoryItem> History { get; set; } = [];
14  
15      private readonly Lock _lock = new();
16  
17      public RecentCommandsManager()
18      {
19      }
20  
21      public int GetCommandHistoryWeight(string commandId)
22      {
23          lock (_lock)
24          {
25              var entry = History
26              .Index()
27              .Where(item => item.Item.CommandId == commandId)
28              .FirstOrDefault();
29  
30              // These numbers are vaguely scaled so that "VS" will make "Visual Studio" the
31              // match after one use.
32              // Usually it has a weight of 84, compared to 109 for the VS cmd prompt
33              if (entry.Item is not null)
34              {
35                  var index = entry.Index;
36  
37                  // First, add some weight based on how early in the list this appears
38                  var bucket = index switch
39                  {
40                      var i when index <= 2 => 35,
41                      var i when index <= 10 => 25,
42                      var i when index <= 15 => 15,
43                      var i when index <= 35 => 10,
44                      _ => 5,
45                  };
46  
47                  // Then, add weight for how often this is used, but cap the weight from usage.
48                  var uses = Math.Min(entry.Item.Uses * 5, 35);
49  
50                  return bucket + uses;
51              }
52  
53              return 0;
54          }
55      }
56  
57      public void AddHistoryItem(string commandId)
58      {
59          lock (_lock)
60          {
61              var entry = History
62              .Where(item => item.CommandId == commandId)
63              .FirstOrDefault();
64              if (entry is null)
65              {
66                  var newitem = new HistoryItem() { CommandId = commandId, Uses = 1 };
67                  History.Insert(0, newitem);
68              }
69              else
70              {
71                  History.Remove(entry);
72                  entry.Uses++;
73                  History.Insert(0, entry);
74              }
75  
76              if (History.Count > 50)
77              {
78                  History.RemoveRange(50, History.Count - 50);
79              }
80          }
81      }
82  }
83  
84  public interface IRecentCommandsManager
85  {
86      int GetCommandHistoryWeight(string commandId);
87  
88      void AddHistoryItem(string commandId);
89  }