add items to history

This commit is contained in:
Mike Griese
2025-07-03 15:27:50 -05:00
parent b6e3b8a3ee
commit b0c862dd67
7 changed files with 73 additions and 39 deletions

View File

@@ -36,7 +36,17 @@ internal sealed class RunHistoryService : IRunHistoryService
public void AddRunHistoryItem(string item)
{
_appStateModel.RunHistory.Add(item);
// insert at the beginning of the list
if (string.IsNullOrWhiteSpace(item))
{
return; // Do not add empty or whitespace items
}
_appStateModel.RunHistory.Remove(item);
// Add the item to the front of the history
_appStateModel.RunHistory.Insert(0, item);
AppStateModel.SaveState(_appStateModel);
}
}

View File

@@ -16,14 +16,16 @@ namespace Microsoft.CmdPal.Ext.Shell;
internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDisposable
{
private readonly Action<string>? _addToHistory;
private CancellationTokenSource? _cancellationTokenSource;
private Task? _currentUpdateTask;
public FallbackExecuteItem(SettingsManager settings)
public FallbackExecuteItem(SettingsManager settings, Action<string>? addToHistory)
: base(new NoOpCommand(), Resources.shell_command_display_title)
{
Title = string.Empty;
Icon = Icons.RunV2;
_addToHistory = addToHistory;
}
public override void UpdateQuery(string query)
@@ -152,7 +154,7 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos
if (exeExists)
{
// TODO we need to probably get rid of the settings for this provider entirely
var exeItem = ShellListPage.CreateExeItem(exe, args, fullExePath);
var exeItem = ShellListPage.CreateExeItem(exe, args, fullExePath, _addToHistory);
Title = exeItem.Title;
Subtitle = exeItem.Subtitle;
Icon = exeItem.Icon;
@@ -161,7 +163,7 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos
}
else if (pathIsDir)
{
var pathItem = new PathListItem(exe, query);
var pathItem = new PathListItem(exe, query, _addToHistory);
Title = pathItem.Title;
Subtitle = pathItem.Subtitle;
Icon = pathItem.Icon;
@@ -170,7 +172,7 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos
}
else if (System.Uri.TryCreate(searchText, UriKind.Absolute, out var uri))
{
Command = new OpenUrlCommand(searchText) { Result = CommandResult.Dismiss() };
Command = new OpenUrlWithHistoryCommand(searchText, _addToHistory) { Result = CommandResult.Dismiss() };
Title = searchText;
}
else

View File

@@ -167,7 +167,7 @@ public class ShellListPageHelpers
}
}
internal static ListItem? ListItemForCommandString(string query)
internal static ListItem? ListItemForCommandString(string query, Action<string>? addToHistory)
{
var li = new ListItem();
@@ -213,7 +213,7 @@ public class ShellListPageHelpers
if (exeExists)
{
// TODO we need to probably get rid of the settings for this provider entirely
var exeItem = ShellListPage.CreateExeItem(exe, args, fullExePath);
var exeItem = ShellListPage.CreateExeItem(exe, args, fullExePath, addToHistory);
li.Command = exeItem.Command;
li.Title = exeItem.Title;
li.Subtitle = exeItem.Subtitle;
@@ -222,7 +222,7 @@ public class ShellListPageHelpers
}
else if (pathIsDir)
{
var pathItem = new PathListItem(exe, query);
var pathItem = new PathListItem(exe, query, addToHistory);
li.Command = pathItem.Command;
li.Title = pathItem.Title;
li.Subtitle = pathItem.Subtitle;
@@ -231,7 +231,7 @@ public class ShellListPageHelpers
}
else if (System.Uri.TryCreate(searchText, UriKind.Absolute, out var uri))
{
li.Command = new OpenUrlCommand(searchText) { Result = CommandResult.Dismiss() };
li.Command = new OpenUrlWithHistoryCommand(searchText) { Result = CommandResult.Dismiss() };
li.Title = searchText;
}
else

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
internal sealed partial class OpenUrlWithHistoryCommand : OpenUrlCommand
{
private readonly Action<string>? _addToHistory;
private readonly string _url;
public OpenUrlWithHistoryCommand(string url, Action<string>? addToHistory = null)
: base(url)
{
_addToHistory = addToHistory;
_url = url;
}
public override CommandResult Invoke()
{
_addToHistory?.Invoke(_url);
var result = base.Invoke();
return result;
}
}

View File

@@ -279,14 +279,14 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable
cancellationToken.ThrowIfCancellationRequested();
}
private static ListItem PathToListItem(string path, string originalPath, string args = "")
private static ListItem PathToListItem(string path, string originalPath, string args = "", Action<string>? addToHistory = null)
{
var pathItem = new PathListItem(path, originalPath);
var pathItem = new PathListItem(path, originalPath, addToHistory);
// Is this path an executable? If so, then make a RunExeItem
if (IsExecutable(path))
{
var exeItem = new RunExeItem(Path.GetFileName(path), args, path);
var exeItem = new RunExeItem(Path.GetFileName(path), args, path, addToHistory);
exeItem.MoreCommands = [
.. exeItem.MoreCommands,
@@ -317,12 +317,12 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable
.ToArray();
}
internal static RunExeItem CreateExeItem(string exe, string args, string fullExePath)
internal static RunExeItem CreateExeItem(string exe, string args, string fullExePath, Action<string>? addToHistory)
{
// PathToListItem will return a RunExeItem if it can find a executable.
// It will ALSO add the file search commands to the RunExeItem.
return PathToListItem(fullExePath, exe, args) as RunExeItem ??
new RunExeItem(exe, args, fullExePath);
return PathToListItem(fullExePath, exe, args, addToHistory) as RunExeItem ??
new RunExeItem(exe, args, fullExePath, addToHistory);
}
private void CreateAndAddExeItems(string exe, string args, string fullExePath)
@@ -334,7 +334,7 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable
}
else
{
_exeItem = CreateExeItem(exe, args, fullExePath);
_exeItem = CreateExeItem(exe, args, fullExePath, AddToHistory);
}
}
@@ -499,7 +499,7 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable
{
var hist = _historyService.GetRunHistory();
var histItems = hist
.Select(h => (h, ShellListPageHelpers.ListItemForCommandString(h)))
.Select(h => (h, ShellListPageHelpers.ListItemForCommandString(h, AddToHistory)))
.Where(tuple => tuple.Item2 != null)
.Select(tuple => (tuple.h, tuple.Item2!))
.ToList();
@@ -516,6 +516,18 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable
_loadedInitialHistory = true;
}
internal void AddToHistory(string commandString)
{
if (string.IsNullOrWhiteSpace(commandString))
{
return; // Do not add empty or whitespace items
}
_historyService.AddRunHistoryItem(commandString);
LoadInitialHistory();
}
public void Dispose()
{
_cancellationTokenSource?.Cancel();

View File

@@ -67,23 +67,3 @@ internal sealed partial class PathListItem : ListItem
});
}
}
internal sealed partial class OpenUrlWithHistoryCommand : OpenUrlCommand
{
private readonly Action<string>? _addToHistory;
private readonly string _url;
public OpenUrlWithHistoryCommand(string url, Action<string>? addToHistory = null)
: base(url)
{
_addToHistory = addToHistory;
_url = url;
}
public override CommandResult Invoke()
{
_addToHistory?.Invoke(_url);
var result = base.Invoke();
return result;
}
}

View File

@@ -29,10 +29,10 @@ public partial class ShellCommandsProvider : CommandProvider
Icon = Icons.RunV2;
Settings = _settingsManager.Settings;
_fallbackItem = new FallbackExecuteItem(_settingsManager);
_shellListPage = new ShellListPage(_settingsManager, _historyService);
_fallbackItem = new FallbackExecuteItem(_settingsManager, _shellListPage.AddToHistory);
_shellPageItem = new CommandItem(_shellListPage)
{
Icon = Icons.RunV2,