Rename the [Ee]xts dir to ext (#38852)

**WARNING:** This PR will probably blow up all in-flight PRs

at some point in the early days of CmdPal, two of us created seperate
`Exts` and `exts` dirs. Depending on what the casing was on the branch
that you checked one of those out from, it'd get stuck like that on your
PC forever.

Windows didn't care, so we never noticed.

But GitHub does care, and now browsing the source on GitHub is basically
impossible.

Closes #38081
This commit is contained in:
Mike Griese
2025-04-15 06:07:22 -05:00
committed by GitHub
parent 60f50d853b
commit 2b5181b4c9
379 changed files with 35 additions and 35 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,66 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1887_18142)">
<rect y="4.5" width="3.75" height="1.25" fill="url(#paint0_linear_1887_18142)"/>
<rect y="6.75" width="3.75" height="1.25" fill="url(#paint1_linear_1887_18142)"/>
<rect y="9" width="3.75" height="1.25" fill="url(#paint2_linear_1887_18142)"/>
<rect y="11.25" width="3.75" height="1.25" fill="url(#paint3_linear_1887_18142)"/>
<path d="M2.62973 4.60404C2.69939 4.25294 3.00745 4 3.36539 4H14.1219C14.5947 4 14.9495 4.43219 14.8575 4.89596L13.3694 12.396C13.2998 12.7471 12.9917 13 12.6338 13H1.8773C1.40448 13 1.04962 12.5678 1.14164 12.104L2.62973 4.60404Z" fill="url(#paint4_linear_1887_18142)"/>
<path opacity="0.8" d="M3.31 5.05188C3.34489 4.87639 3.49889 4.75 3.67781 4.75H13.6685C13.905 4.75 14.0824 4.9662 14.0363 5.19812L12.6943 11.9481C12.6594 12.1236 12.5054 12.25 12.3265 12.25H2.3358C2.09933 12.25 1.92189 12.0338 1.968 11.8019L3.31 5.05188Z" fill="url(#paint5_linear_1887_18142)"/>
<path opacity="0.8" fill-rule="evenodd" clip-rule="evenodd" d="M3.6776 4.75C3.49869 4.75 3.34469 4.87639 3.3098 5.05188L1.9678 11.8019C1.96623 11.8097 1.96492 11.8176 1.96387 11.8254L3.26085 5.30188C3.29574 5.12639 3.44974 5 3.62865 5H13.6194C13.8478 5 14.0212 5.20177 13.9911 5.42457L14.0361 5.19812C14.0822 4.9662 13.9048 4.75 13.6683 4.75H3.6776Z" fill="url(#paint6_linear_1887_18142)"/>
<g filter="url(#filter0_dd_1887_18142)">
<path d="M4.47597 6.85475C4.54535 6.50332 4.85356 6.25 5.21178 6.25L11.3792 6.25C11.8517 6.25 12.2065 6.68168 12.115 7.14525L11.5227 10.1453C11.4534 10.4967 11.1452 10.75 10.7869 10.75H4.61956C4.14704 10.75 3.79225 10.3183 3.88376 9.85475L4.47597 6.85475Z" fill="url(#paint7_linear_1887_18142)"/>
</g>
<path d="M5.14006 7.30488C5.17373 7.12799 5.32838 7 5.50844 7H10.912C11.1472 7 11.3243 7.21405 11.2804 7.44512L11.0424 8.69512C11.0087 8.87201 10.8541 9 10.674 9H5.2705C5.03528 9 4.85813 8.78595 4.90211 8.55488L5.14006 7.30488Z" fill="white"/>
</g>
<defs>
<filter id="filter0_dd_1887_18142" x="3.36914" y="5.75" width="9.26074" height="5.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.0833333"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1887_18142"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.25"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1887_18142" result="effect2_dropShadow_1887_18142"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1887_18142" result="shape"/>
</filter>
<linearGradient id="paint0_linear_1887_18142" x1="3.75" y1="5.39286" x2="3.14495e-08" y2="5.39286" gradientUnits="userSpaceOnUse">
<stop stop-color="#28AFEA" stop-opacity="0.8"/>
<stop offset="1" stop-color="#28AFEA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_1887_18142" x1="3.75" y1="7.64286" x2="3.14495e-08" y2="7.64286" gradientUnits="userSpaceOnUse">
<stop stop-color="#28AFEA" stop-opacity="0.8"/>
<stop offset="1" stop-color="#28AFEA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_1887_18142" x1="3.75" y1="9.89286" x2="3.14495e-08" y2="9.89286" gradientUnits="userSpaceOnUse">
<stop stop-color="#28AFEA" stop-opacity="0.8"/>
<stop offset="1" stop-color="#28AFEA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint3_linear_1887_18142" x1="3.75" y1="12.1429" x2="3.14495e-08" y2="12.1429" gradientUnits="userSpaceOnUse">
<stop stop-color="#28AFEA" stop-opacity="0.8"/>
<stop offset="1" stop-color="#28AFEA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint4_linear_1887_18142" x1="5.4463" y1="4" x2="7.3315" y2="13.4932" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CCBF4"/>
<stop offset="1" stop-color="#1493DF"/>
</linearGradient>
<linearGradient id="paint5_linear_1887_18142" x1="4.41381" y1="4.75" x2="7.74261" y2="12.255" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8F4FF"/>
</linearGradient>
<linearGradient id="paint6_linear_1887_18142" x1="4.4136" y1="4.75" x2="7.7424" y2="12.255" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8F4FF"/>
</linearGradient>
<linearGradient id="paint7_linear_1887_18142" x1="6.44166" y1="6.25" x2="7.22393" y2="11.0565" gradientUnits="userSpaceOnUse">
<stop stop-color="#3CCBF4"/>
<stop offset="1" stop-color="#1493DF"/>
</linearGradient>
<clipPath id="clip0_1887_18142">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,19 @@
<svg width="260" height="260" viewBox="0 0 260 260" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.7189 166.405L34.8123 80.9387C37.8287 65.8564 51.0714 55 66.4524 55H210.641C231.003 55 246.274 73.6283 242.281 93.5947L225.188 179.061C222.171 194.144 208.929 205 193.548 205H49.359C28.9972 205 13.7257 186.372 17.7189 166.405Z" fill="url(#paint0_linear_15_159)" stroke="url(#paint1_linear_15_159)" stroke-width="32.2667"/>
<path d="M66.3623 129.973L70.5337 110.506C73.7217 95.6287 86.8692 85 102.084 85H162.086C182.628 85 197.94 103.941 193.636 124.027L189.465 143.494C186.277 158.371 173.129 169 157.914 169H97.9127C77.3703 169 62.0581 150.059 66.3623 129.973Z" fill="url(#paint2_linear_15_159)"/>
<path d="M85.1317 114.211L85.7539 110.478C87.0504 102.699 93.7811 96.9971 101.668 96.9971H164.956C174.925 96.9971 182.509 105.949 180.87 115.783L180.248 119.516C178.951 127.295 172.22 132.997 164.334 132.997H101.045C91.0761 132.997 83.4927 124.045 85.1317 114.211Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_15_159" x1="148" y1="61" x2="130" y2="205" gradientUnits="userSpaceOnUse">
<stop stop-color="#CDEDFC"/>
<stop offset="1" stop-color="#BFE3F9"/>
</linearGradient>
<linearGradient id="paint1_linear_15_159" x1="46" y1="49" x2="268" y2="253" gradientUnits="userSpaceOnUse">
<stop stop-color="#3BCAF4"/>
<stop offset="1" stop-color="#006AAA"/>
</linearGradient>
<linearGradient id="paint2_linear_15_159" x1="93.9993" y1="73" x2="216.411" y2="214.919" gradientUnits="userSpaceOnUse">
<stop stop-color="#5ED0F2"/>
<stop offset="1" stop-color="#1494DF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,258 @@
// 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.ComponentModel;
using System.Diagnostics;
using System.IO;
using Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell.Commands;
internal sealed partial class ExecuteItem : InvokableCommand
{
private readonly SettingsManager _settings;
private readonly RunAsType _runas;
public string Cmd { get; internal set; } = string.Empty;
private static readonly char[] Separator = [' '];
public ExecuteItem(string cmd, SettingsManager settings, RunAsType type = RunAsType.None)
{
if (type == RunAsType.Administrator)
{
Name = Properties.Resources.cmd_run_as_administrator;
Icon = new IconInfo("\xE7EF"); // Admin Icon
}
else if (type == RunAsType.OtherUser)
{
Name = Properties.Resources.cmd_run_as_user;
Icon = new IconInfo("\xE7EE"); // User Icon
}
else
{
Name = Properties.Resources.generic_run_command;
Icon = new IconInfo("\uE751"); // Return Key Icon
}
Cmd = cmd;
_settings = settings;
_runas = type;
}
private static bool ExistInPath(string filename)
{
if (File.Exists(filename))
{
return true;
}
else
{
var values = Environment.GetEnvironmentVariable("PATH");
if (values != null)
{
foreach (var path in values.Split(';'))
{
var path1 = Path.Combine(path, filename);
var path2 = Path.Combine(path, filename + ".exe");
if (File.Exists(path1) || File.Exists(path2))
{
return true;
}
}
return false;
}
else
{
return false;
}
}
}
private void Execute(Func<ProcessStartInfo, Process?> startProcess, ProcessStartInfo info)
{
if (startProcess == null)
{
return;
}
try
{
startProcess(info);
}
catch (FileNotFoundException e)
{
var name = "Plugin: " + Properties.Resources.cmd_plugin_name;
var message = $"{Properties.Resources.cmd_command_not_found}: {e.Message}";
// GH TODO #138 -- show this message once that's wired up
// _context.API.ShowMsg(name, message);
}
catch (Win32Exception e)
{
var name = "Plugin: " + Properties.Resources.cmd_plugin_name;
var message = $"{Properties.Resources.cmd_command_failed}: {e.Message}";
ExtensionHost.LogMessage(new LogMessage() { Message = name + message });
// GH TODO #138 -- show this message once that's wired up
// _context.API.ShowMsg(name, message);
}
}
public static ProcessStartInfo SetProcessStartInfo(string fileName, string workingDirectory = "", string arguments = "", string verb = "")
{
var info = new ProcessStartInfo
{
FileName = fileName,
WorkingDirectory = workingDirectory,
Arguments = arguments,
Verb = verb,
};
return info;
}
private ProcessStartInfo PrepareProcessStartInfo(string command, RunAsType runAs = RunAsType.None)
{
command = Environment.ExpandEnvironmentVariables(command);
var workingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
// Set runAsArg
var runAsVerbArg = string.Empty;
if (runAs == RunAsType.OtherUser)
{
runAsVerbArg = "runAsUser";
}
else if (runAs == RunAsType.Administrator || _settings.RunAsAdministrator)
{
runAsVerbArg = "runAs";
}
if (Enum.TryParse<ExecutionShell>(_settings.ShellCommandExecution, out var executionShell))
{
ProcessStartInfo info;
if (executionShell == ExecutionShell.Cmd)
{
var arguments = _settings.LeaveShellOpen ? $"/k \"{command}\"" : $"/c \"{command}\" & pause";
info = SetProcessStartInfo("cmd.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.Powershell)
{
var arguments = _settings.LeaveShellOpen
? $"-NoExit \"{command}\""
: $"\"{command} ; Read-Host -Prompt \\\"{Resources.run_plugin_cmd_wait_message}\\\"\"";
info = SetProcessStartInfo("powershell.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.PowerShellSeven)
{
var arguments = _settings.LeaveShellOpen
? $"-NoExit -C \"{command}\""
: $"-C \"{command} ; Read-Host -Prompt \\\"{Resources.run_plugin_cmd_wait_message}\\\"\"";
info = SetProcessStartInfo("pwsh.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalCmd)
{
var arguments = _settings.LeaveShellOpen ? $"cmd.exe /k \"{command}\"" : $"cmd.exe /c \"{command}\" & pause";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalPowerShell)
{
var arguments = _settings.LeaveShellOpen ? $"powershell -NoExit -C \"{command}\"" : $"powershell -C \"{command}\"";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.WindowsTerminalPowerShellSeven)
{
var arguments = _settings.LeaveShellOpen ? $"pwsh.exe -NoExit -C \"{command}\"" : $"pwsh.exe -C \"{command}\"";
info = SetProcessStartInfo("wt.exe", workingDirectory, arguments, runAsVerbArg);
}
else if (executionShell == ExecutionShell.RunCommand)
{
// Open explorer if the path is a file or directory
if (Directory.Exists(command) || File.Exists(command))
{
info = SetProcessStartInfo("explorer.exe", arguments: command, verb: runAsVerbArg);
}
else
{
var parts = command.Split(Separator, 2);
if (parts.Length == 2)
{
var filename = parts[0];
if (ExistInPath(filename))
{
var arguments = parts[1];
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{filename} {arguments}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(filename, workingDirectory, arguments, runAsVerbArg);
}
}
else
{
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{command}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(command, verb: runAsVerbArg);
}
}
}
else
{
if (_settings.LeaveShellOpen)
{
// Wrap the command in a cmd.exe process
info = SetProcessStartInfo("cmd.exe", workingDirectory, $"/k \"{command}\"", runAsVerbArg);
}
else
{
info = SetProcessStartInfo(command, verb: runAsVerbArg);
}
}
}
}
else
{
throw new NotImplementedException();
}
info.UseShellExecute = true;
_settings.AddCmdHistory(command);
return info;
}
else
{
ExtensionHost.LogMessage(new LogMessage() { Message = "Error extracting setting" });
throw new NotImplementedException();
}
}
public override CommandResult Invoke()
{
try
{
Execute(Process.Start, PrepareProcessStartInfo(Cmd, _runas));
}
catch
{
ExtensionHost.LogMessage(new LogMessage() { Message = "Error starting the process " });
}
return CommandResult.Dismiss();
}
}

View File

@@ -0,0 +1,32 @@
// 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 Microsoft.CmdPal.Ext.Shell.Commands;
using Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
internal sealed partial class FallbackExecuteItem : FallbackCommandItem
{
private readonly ExecuteItem _executeItem;
public FallbackExecuteItem(SettingsManager settings)
: base(new ExecuteItem(string.Empty, settings), Resources.shell_command_display_title)
{
_executeItem = (ExecuteItem)this.Command!;
Title = string.Empty;
_executeItem.Name = string.Empty;
Subtitle = Properties.Resources.generic_run_command;
Icon = Icons.RunV2; // Defined in Icons.cs and contains the execute command icon.
}
public override void UpdateQuery(string query)
{
_executeItem.Cmd = query;
_executeItem.Name = string.IsNullOrEmpty(query) ? string.Empty : Properties.Resources.generic_run_command;
Title = query;
}
}

View File

@@ -0,0 +1,16 @@
// 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.
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public enum ExecutionShell
{
Cmd = 0,
Powershell = 1,
RunCommand = 2,
WindowsTerminalPowerShell = 3,
WindowsTerminalPowerShellSeven = 4,
WindowsTerminalCmd = 5,
PowerShellSeven = 6,
}

View File

@@ -0,0 +1,12 @@
// 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.
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public enum RunAsType
{
None,
Administrator,
OtherUser,
}

View File

@@ -0,0 +1,72 @@
// 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 Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public class SettingsManager : JsonSettingsManager
{
private static readonly string _namespace = "shell";
private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}";
private static readonly List<ChoiceSetSetting.Choice> _choices =
[
new ChoiceSetSetting.Choice(Resources.find_executable_file_and_run_it, "2"), // idk why but this is how PT Run did it? Maybe ordering matters there
new ChoiceSetSetting.Choice(Resources.run_command_in_command_prompt, "0"),
new ChoiceSetSetting.Choice(Resources.run_command_in_powershell, "1"),
new ChoiceSetSetting.Choice(Resources.run_command_in_powershell_seven, "6"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_cmd, "5"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_powershell, "3"),
new ChoiceSetSetting.Choice(Resources.run_command_in_windows_terminal_powershell_seven, "4"),
];
private readonly ToggleSetting _leaveShellOpen = new(
Namespaced(nameof(LeaveShellOpen)),
Resources.leave_shell_open,
Resources.leave_shell_open,
false); // TODO -- double check default value
private readonly ChoiceSetSetting _shellCommandExecution = new(
Namespaced(nameof(ShellCommandExecution)),
Resources.shell_command_execution,
Resources.shell_command_execution_description,
_choices);
public bool LeaveShellOpen => _leaveShellOpen.Value;
public string ShellCommandExecution => _shellCommandExecution.Value ?? string.Empty;
public bool RunAsAdministrator { get; set; }
public Dictionary<string, int> Count { get; } = [];
public void AddCmdHistory(string cmdName) => Count[cmdName] = Count.TryGetValue(cmdName, out var currentCount) ? currentCount + 1 : 1;
internal static string SettingsJsonPath()
{
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
Directory.CreateDirectory(directory);
// now, the state is just next to the exe
return Path.Combine(directory, "settings.json");
}
public SettingsManager()
{
FilePath = SettingsJsonPath();
Settings.Add(_leaveShellOpen);
Settings.Add(_shellCommandExecution);
// Load settings from file upon initialization
LoadSettings();
Settings.SettingsChanged += (s, a) => this.SaveSettings();
}
}

View File

@@ -0,0 +1,116 @@
// 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.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Shell.Commands;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell.Helpers;
public class ShellListPageHelpers
{
private static readonly CompositeFormat CmdHasBeenExecutedTimes = System.Text.CompositeFormat.Parse(Properties.Resources.cmd_has_been_executed_times);
private readonly SettingsManager _settings;
public ShellListPageHelpers(SettingsManager settings)
{
_settings = settings;
}
private ListItem GetCurrentCmd(string cmd)
{
ListItem result = new ListItem(new ExecuteItem(cmd, _settings))
{
Title = cmd,
Subtitle = Properties.Resources.cmd_plugin_name + ": " + Properties.Resources.cmd_execute_through_shell,
Icon = new IconInfo(string.Empty),
};
return result;
}
private List<ListItem> GetHistoryCmds(string cmd, ListItem result)
{
IEnumerable<ListItem?> history = _settings.Count.Where(o => o.Key.Contains(cmd, StringComparison.CurrentCultureIgnoreCase))
.OrderByDescending(o => o.Value)
.Select(m =>
{
if (m.Key == cmd)
{
// Using CurrentCulture since this is user facing
result.Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value);
return null;
}
var ret = new ListItem(new ExecuteItem(m.Key, _settings))
{
Title = m.Key,
// Using CurrentCulture since this is user facing
Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value),
Icon = new IconInfo("\uE81C"),
};
return ret;
}).Where(o => o != null).Take(4);
return history.Select(o => o!).ToList();
}
public List<ListItem> Query(string query)
{
ArgumentNullException.ThrowIfNull(query);
List<ListItem> results = new List<ListItem>();
var cmd = query;
if (string.IsNullOrEmpty(cmd))
{
results = ResultsFromlHistory();
}
else
{
var queryCmd = GetCurrentCmd(cmd);
results.Add(queryCmd);
var history = GetHistoryCmds(cmd, queryCmd);
results.AddRange(history);
}
foreach (var currItem in results)
{
currItem.MoreCommands = LoadContextMenus(currItem).ToArray();
}
return results;
}
public List<CommandContextItem> LoadContextMenus(ListItem listItem)
{
var resultlist = new List<CommandContextItem>
{
new(new ExecuteItem(listItem.Title, _settings, RunAsType.Administrator)),
new(new ExecuteItem(listItem.Title, _settings, RunAsType.OtherUser )),
};
return resultlist;
}
private List<ListItem> ResultsFromlHistory()
{
IEnumerable<ListItem> history = _settings.Count.OrderByDescending(o => o.Value)
.Select(m => new ListItem(new ExecuteItem(m.Key, _settings))
{
Title = m.Key,
// Using CurrentCulture since this is user facing
Subtitle = Properties.Resources.cmd_plugin_name + ": " + string.Format(CultureInfo.CurrentCulture, CmdHasBeenExecutedTimes, m.Value),
Icon = new IconInfo("\uE81C"),
}).Take(5);
return history.ToList();
}
}

View File

@@ -0,0 +1,12 @@
// 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 Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
internal sealed class Icons
{
internal static IconInfo RunV2 { get; } = IconHelpers.FromRelativePath("Assets\\Run.svg");
}

View File

@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<Nullable>enable</Nullable>
<RootNamespace>Microsoft.CmdPal.Ext.Shell</RootNamespace>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\Run.svg" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Update="Assets\Run.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="Assets\Run.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,28 @@
// 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 Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell.Pages;
internal sealed partial class ShellListPage : DynamicListPage
{
private readonly ShellListPageHelpers _helper;
public ShellListPage(SettingsManager settingsManager)
{
Icon = Icons.RunV2;
Id = "com.microsoft.cmdpal.shell";
Name = Resources.cmd_plugin_name;
PlaceholderText = Resources.list_placeholder_text;
_helper = new(settingsManager);
}
public override void UpdateSearchText(string oldSearch, string newSearch) => RaiseItemsChanged(0);
public override IListItem[] GetItems() => [.. _helper.Query(SearchText)];
}

View File

@@ -0,0 +1,279 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.CmdPal.Ext.Shell.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CmdPal.Ext.Shell.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Error running the command.
/// </summary>
public static string cmd_command_failed {
get {
return ResourceManager.GetString("cmd_command_failed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Command not found.
/// </summary>
public static string cmd_command_not_found {
get {
return ResourceManager.GetString("cmd_command_not_found", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to execute command through command shell.
/// </summary>
public static string cmd_execute_through_shell {
get {
return ResourceManager.GetString("cmd_execute_through_shell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to this command has been executed {0} times.
/// </summary>
public static string cmd_has_been_executed_times {
get {
return ResourceManager.GetString("cmd_has_been_executed_times", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Executes commands (e.g. &apos;ping&apos;, &apos;cmd&apos;).
/// </summary>
public static string cmd_plugin_description {
get {
return ResourceManager.GetString("cmd_plugin_description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run commands.
/// </summary>
public static string cmd_plugin_name {
get {
return ResourceManager.GetString("cmd_plugin_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run as administrator.
/// </summary>
public static string cmd_run_as_administrator {
get {
return ResourceManager.GetString("cmd_run_as_administrator", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run as different user.
/// </summary>
public static string cmd_run_as_user {
get {
return ResourceManager.GetString("cmd_run_as_user", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Find and run the executable file.
/// </summary>
public static string find_executable_file_and_run_it {
get {
return ResourceManager.GetString("find_executable_file_and_run_it", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run.
/// </summary>
public static string generic_run_command {
get {
return ResourceManager.GetString("generic_run_command", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Keep shell open.
/// </summary>
public static string leave_shell_open {
get {
return ResourceManager.GetString("leave_shell_open", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type the name of a command to run.
/// </summary>
public static string list_placeholder_text {
get {
return ResourceManager.GetString("list_placeholder_text", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in Command Prompt (cmd.exe).
/// </summary>
public static string run_command_in_command_prompt {
get {
return ResourceManager.GetString("run_command_in_command_prompt", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell (PowerShell.exe).
/// </summary>
public static string run_command_in_powershell {
get {
return ResourceManager.GetString("run_command_in_powershell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell 7 (pwsh.exe).
/// </summary>
public static string run_command_in_powershell_seven {
get {
return ResourceManager.GetString("run_command_in_powershell_seven", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in Command Prompt (cmd.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_cmd {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell (PowerShell.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_powershell {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_powershell", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run in PowerShell 7 (pwsh.exe) using Windows Terminal.
/// </summary>
public static string run_command_in_windows_terminal_powershell_seven {
get {
return ResourceManager.GetString("run_command_in_windows_terminal_powershell_seven", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Press Enter to continue.
/// </summary>
public static string run_plugin_cmd_wait_message {
get {
return ResourceManager.GetString("run_plugin_cmd_wait_message", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Settings.
/// </summary>
public static string settings_page_name {
get {
return ResourceManager.GetString("settings_page_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run commands.
/// </summary>
public static string shell_command_display_title {
get {
return ResourceManager.GetString("shell_command_display_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Command execution.
/// </summary>
public static string shell_command_execution {
get {
return ResourceManager.GetString("shell_command_execution", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All entries using the Windows Terminal force the Windows Terminal as the console host regardless of the system settings.
/// </summary>
public static string shell_command_execution_description {
get {
return ResourceManager.GetString("shell_command_execution_description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Run commands.
/// </summary>
public static string shell_command_name {
get {
return ResourceManager.GetString("shell_command_name", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="cmd_plugin_name" xml:space="preserve">
<value>Run commands</value>
</data>
<data name="cmd_plugin_description" xml:space="preserve">
<value>Executes commands (e.g. 'ping', 'cmd')</value>
</data>
<data name="cmd_has_been_executed_times" xml:space="preserve">
<value>this command has been executed {0} times</value>
</data>
<data name="cmd_execute_through_shell" xml:space="preserve">
<value>execute command through command shell</value>
</data>
<data name="cmd_run_as_administrator" xml:space="preserve">
<value>Run as administrator</value>
</data>
<data name="cmd_command_failed" xml:space="preserve">
<value>Error running the command</value>
</data>
<data name="cmd_command_not_found" xml:space="preserve">
<value>Command not found</value>
</data>
<data name="cmd_run_as_user" xml:space="preserve">
<value>Run as different user</value>
</data>
<data name="leave_shell_open" xml:space="preserve">
<value>Keep shell open</value>
</data>
<data name="shell_command_execution" xml:space="preserve">
<value>Command execution</value>
</data>
<data name="run_command_in_command_prompt" xml:space="preserve">
<value>Run in Command Prompt (cmd.exe)</value>
</data>
<data name="run_command_in_powershell" xml:space="preserve">
<value>Run in PowerShell (PowerShell.exe)</value>
</data>
<data name="find_executable_file_and_run_it" xml:space="preserve">
<value>Find and run the executable file</value>
</data>
<data name="run_command_in_powershell_seven" xml:space="preserve">
<value>Run in PowerShell 7 (pwsh.exe)</value>
</data>
<data name="run_command_in_windows_terminal_cmd" xml:space="preserve">
<value>Run in Command Prompt (cmd.exe) using Windows Terminal</value>
</data>
<data name="run_command_in_windows_terminal_powershell" xml:space="preserve">
<value>Run in PowerShell (PowerShell.exe) using Windows Terminal</value>
</data>
<data name="run_command_in_windows_terminal_powershell_seven" xml:space="preserve">
<value>Run in PowerShell 7 (pwsh.exe) using Windows Terminal</value>
</data>
<data name="run_plugin_cmd_wait_message" xml:space="preserve">
<value>Press Enter to continue</value>
<comment>"Enter" means the Enter key on the keyboard.</comment>
</data>
<data name="shell_command_execution_description" xml:space="preserve">
<value>All entries using the Windows Terminal force the Windows Terminal as the console host regardless of the system settings</value>
</data>
<data name="shell_command_name" xml:space="preserve">
<value>Run commands</value>
</data>
<data name="generic_run_command" xml:space="preserve">
<value>Run</value>
</data>
<data name="settings_page_name" xml:space="preserve">
<value>Settings</value>
</data>
<data name="list_placeholder_text" xml:space="preserve">
<value>Type the name of a command to run</value>
</data>
<data name="shell_command_display_title" xml:space="preserve">
<value>Run commands</value>
</data>
</root>

View File

@@ -0,0 +1,42 @@
// 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 Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CmdPal.Ext.Shell.Pages;
using Microsoft.CmdPal.Ext.Shell.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
public partial class ShellCommandsProvider : CommandProvider
{
private readonly CommandItem _shellPageItem;
private readonly SettingsManager _settingsManager = new();
private readonly FallbackCommandItem _fallbackItem;
public ShellCommandsProvider()
{
Id = "Run";
DisplayName = Resources.cmd_plugin_name;
Icon = Icons.RunV2;
Settings = _settingsManager.Settings;
_fallbackItem = new FallbackExecuteItem(_settingsManager);
_shellPageItem = new CommandItem(new ShellListPage(_settingsManager))
{
Icon = Icons.RunV2,
Title = Resources.shell_command_name,
Subtitle = Resources.cmd_plugin_description,
MoreCommands = [
new CommandContextItem(Settings.SettingsPage),
],
};
}
public override ICommandItem[] TopLevelCommands() => [_shellPageItem];
public override IFallbackCommandItem[]? FallbackCommands() => [_fallbackItem];
}