diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs index 7586d466fd..87419b7857 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs @@ -9,4 +9,6 @@ namespace Microsoft.CmdPal.Ext.Shell; internal sealed class Icons { internal static IconInfo RunV2 { get; } = IconHelpers.FromRelativePath("Assets\\Run.svg"); + + internal static IconInfo Folder { get; } = new("📁"); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs new file mode 100644 index 0000000000..d5464d2227 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs @@ -0,0 +1,45 @@ +// 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 PathListItem : ListItem +{ + private readonly Lazy _icon; + private readonly bool _isDirectory; + + public override IIconInfo? Icon { get => _icon.Value; set => base.Icon = value; } + + public PathListItem(string path) + : base(new OpenUrlCommand(path)) + { + var fileName = Path.GetFileName(path); + _isDirectory = Directory.Exists(path); + if (_isDirectory) + { + path = path + "\\"; + fileName = fileName + "\\"; + } + + Title = fileName; + Subtitle = path; + TextToSuggest = path; + MoreCommands = [ + new CommandContextItem(new CopyTextCommand(path)) + ]; + + _icon = new Lazy(() => + { + var iconStream = ThumbnailHelper.GetThumbnail(path).Result; + var icon = iconStream != null ? IconInfo.FromStream(iconStream) : + _isDirectory ? Icons.Folder : Icons.RunV2; + return icon; + }); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/RunMainPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/RunMainPage.cs new file mode 100644 index 0000000000..42b9315cb9 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/RunMainPage.cs @@ -0,0 +1,117 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Shell; + +internal sealed partial class RunMainPage : DynamicListPage +{ + private readonly List _pathItems = new(); + + public RunMainPage() + { + Name = "Open"; // LOC! + Title = "Run commands"; // LOC! + Icon = Icons.RunV2; + + EmptyContent = new CommandItem() + { + Title = "Run commands", + Icon = Icons.RunV2, + }; + } + + public override void UpdateSearchText(string oldSearch, string newSearch) + { + // If the search text is the start of a path to a file (it might be a unc path), then we want to list all the files that start with that text: + + // 1. Check if the search text is a valid path + // 2. If it is, then list all the files that start with that text + var searchText = newSearch.Trim(); + if (string.IsNullOrEmpty(searchText) || string.IsNullOrWhiteSpace(searchText)) + { + _pathItems.Clear(); + RaiseItemsChanged(); + return; + } + + // Check if the search text is a valid path + if (Path.IsPathRooted(searchText) && Path.GetDirectoryName(searchText) is string directoryName) + { + // Check if the directory exists + if (Directory.Exists(directoryName)) + { + // Get all the files in the directory that start with the search text + var files = Directory.GetFileSystemEntries(directoryName, $"{Path.GetFileName(searchText)}*"); + + // Create a list of commands for each file + var commands = files.Select(PathToListItem).ToList(); + + // Add the commands to the list + ListHelpers.InPlaceUpdateList(_pathItems, commands); + } + } + + // we should also handle just drive roots, ala c:\ or d:\ + else if (searchText.Length == 2 && searchText[1] == ':') + { + // Check if the drive exists + if (Directory.Exists(searchText + "\\")) + { + // Get all the files in the directory that start with the search text + var files = Directory.GetFileSystemEntries(searchText + "\\", "*"); + + // Create a list of commands for each file + var commands = files.Select(PathToListItem).ToList(); + + // Add the commands to the list + ListHelpers.InPlaceUpdateList(_pathItems, commands); + } + } + + // Check if the search text is a valid UNC path + else if (searchText.StartsWith(@"\\", System.StringComparison.CurrentCultureIgnoreCase) && searchText.Contains(@"\\")) + { + // Check if the directory exists + if (Directory.Exists(searchText)) + { + // Get all the files in the directory that start with the search text + var files = Directory.GetFileSystemEntries(searchText, "*"); + + // Create a list of commands for each file + var commands = files.Select(PathToListItem).ToList(); + + // Add the commands to the list + ListHelpers.InPlaceUpdateList(_pathItems, commands); + } + } + + RaiseItemsChanged(); + } + + private ListItem PathToListItem(string path) + { + // var iconStream = ThumbnailHelper.GetThumbnail(path).Result; + // var icon = iconStream != null ? IconInfo.FromStream(iconStream) : Icons.RunV2; + // var fileName = Path.GetFileName(path); + // var isDirectory = Directory.Exists(path); + // if (isDirectory) + // { + // path = path + "\\"; + // fileName = fileName + "\\"; + // icon = Icons.Folder; + // } + return new PathListItem(path); + } + + public override IListItem[] GetItems() + { + return _pathItems.ToArray(); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs index 9e98e036d4..8d301f5fd0 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs @@ -13,6 +13,7 @@ namespace Microsoft.CmdPal.Ext.Shell; public partial class ShellCommandsProvider : CommandProvider { private readonly CommandItem _shellPageItem; + private readonly CommandItem _runMainPageItem; private readonly SettingsManager _settingsManager = new(); private readonly FallbackCommandItem _fallbackItem; @@ -34,9 +35,18 @@ public partial class ShellCommandsProvider : CommandProvider new CommandContextItem(Settings.SettingsPage), ], }; + _runMainPageItem = new CommandItem(new RunMainPage()) + { + Icon = Icons.RunV2, + Title = "Run 2 electric boogaloo", // LOC! + Subtitle = Resources.cmd_plugin_description, + MoreCommands = [ + new CommandContextItem(Settings.SettingsPage), + ], + }; } - public override ICommandItem[] TopLevelCommands() => [_shellPageItem]; + public override ICommandItem[] TopLevelCommands() => [_shellPageItem, _runMainPageItem]; public override IFallbackCommandItem[]? FallbackCommands() => [_fallbackItem]; }