Add Open in Notepad++ and static Windows shell verbs without embedding IContextMenu on right-click.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-26 14:24:00 +02:00
parent e2916aef9c
commit 66ea25993f
16 changed files with 1290 additions and 3 deletions

View File

@@ -0,0 +1,22 @@
using Explorer.Application;
namespace Explorer.Application.Tests;
public class NotepadPlusPlusLocatorTests
{
[Fact]
public void Finds_notepad_plus_plus_on_PATH()
{
var found = NotepadPlusPlusLocator.Find(
fileExists: p => p.Equals(@"D:\apps\notepad++.exe", StringComparison.OrdinalIgnoreCase),
pathVariable: @"C:\Windows;D:\apps");
Assert.Equal(@"D:\apps\notepad++.exe", found);
}
[Fact]
public void Returns_null_when_missing()
{
Assert.Null(NotepadPlusPlusLocator.Find(fileExists: _ => false, pathVariable: @"C:\none"));
Assert.Contains("Notepad++", NotepadPlusPlusLocator.MissingHint, StringComparison.OrdinalIgnoreCase);
}
}

View File

@@ -0,0 +1,75 @@
using Explorer.Application;
using Explorer.Domain.Abstractions;
namespace Explorer.Application.Tests;
public class ShellContextVerbFilterTests
{
[Fact]
public void Keeps_third_party_open_with_and_hides_workbench_duplicates()
{
Assert.True(ShellContextVerbFilter.ShouldInclude("Open with Notepad++", "Open with &Notepad++"));
Assert.True(ShellContextVerbFilter.ShouldInclude("edit", "Edit"));
Assert.True(ShellContextVerbFilter.ShouldInclude("openas", "Open with"));
Assert.False(ShellContextVerbFilter.ShouldInclude("open", "Open"));
Assert.False(ShellContextVerbFilter.ShouldInclude("cut", "Cu&t"));
Assert.False(ShellContextVerbFilter.ShouldInclude("properties", "P&roperties"));
Assert.False(ShellContextVerbFilter.ShouldInclude(null, "Open in Cursor"));
Assert.False(ShellContextVerbFilter.ShouldInclude(null, "Open in Notepad++"));
Assert.False(ShellContextVerbFilter.ShouldInclude(null, "Edit with Notepad++"));
Assert.Equal("Open with Notepad++", ShellContextVerbFilter.CanonicalLabel("Open with &Notepad++"));
}
[Fact]
public void Prune_drops_empty_submenus_and_builtin_rows()
{
var items = new[]
{
new ShellContextVerb("verb:open", "Open"),
new ShellContextVerb("verb:npp", "Open with &Notepad++"),
new ShellContextVerb("verb:zip", "7-Zip", [
new ShellContextVerb("verb:zip.add", "Add to archive…")
]),
new ShellContextVerb("verb:empty", "Empty", [])
};
var pruned = ShellContextVerbFilter.Prune(items);
Assert.Equal(2, pruned.Count);
Assert.Equal("Open with &Notepad++", pruned[0].Label);
Assert.Equal("7-Zip", pruned[1].Label);
Assert.Single(pruned[1].Children!);
}
[Fact]
public void MergeByLabel_adds_missing_third_party_verbs()
{
var merged = ShellContextVerbFilter.MergeByLabel(
[new ShellContextVerb("cmd:1", "PDF24")],
[new ShellContextVerb("static:0", "Open with &Notepad++"), new ShellContextVerb("cmd:2", "PDF24")]);
Assert.Equal(2, merged.Count);
Assert.Equal("PDF24", merged[0].Label);
Assert.Equal("Open with &Notepad++", merged[1].Label);
}
[Fact]
public void Command_split_and_expand_runs_once_per_file_for_percent_one()
{
Assert.True(ShellVerbCommand.TrySplit(
@"""C:\Program Files\Notepad++\notepad++.exe"" ""%1""",
out var exe,
out var args));
Assert.Equal(@"C:\Program Files\Notepad++\notepad++.exe", exe);
var invocations = ShellVerbCommand.ExpandInvocations(args, [@"C:\a.txt", @"C:\b c.txt"]);
Assert.Equal(2, invocations.Count);
Assert.Equal(@"""C:\a.txt""", invocations[0].Trim());
Assert.Contains(@"C:\b c.txt", invocations[1], StringComparison.Ordinal);
}
[Fact]
public void Percent_star_keeps_one_invocation()
{
var invocations = ShellVerbCommand.ExpandInvocations("%*", [@"C:\a.txt", @"C:\b.txt"]);
Assert.Single(invocations);
Assert.Contains(@"C:\a.txt", invocations[0], StringComparison.Ordinal);
Assert.Contains(@"C:\b.txt", invocations[0], StringComparison.Ordinal);
}
}