mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-26 03:44:25 +08:00
Compare commits
2 Commits
5be4537b2c
...
17873f0f43
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17873f0f43 | ||
|
|
4051b5cd74 |
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
@@ -637,10 +637,10 @@ jobs:
|
|||||||
dotnet publish LanMountainDesktop/LanMountainDesktop.csproj \
|
dotnet publish LanMountainDesktop/LanMountainDesktop.csproj \
|
||||||
-c Release \
|
-c Release \
|
||||||
-o ./publish/macos-${{ matrix.arch }}-app \
|
-o ./publish/macos-${{ matrix.arch }}-app \
|
||||||
--self-contained \
|
--self-contained:false \
|
||||||
-r osx-${{ matrix.arch }} \
|
-r osx-${{ matrix.arch }} \
|
||||||
|
-p:SelfContained=false \
|
||||||
-p:PublishSingleFile=false \
|
-p:PublishSingleFile=false \
|
||||||
-p:SelfContained=true \
|
|
||||||
-p:DebugType=none \
|
-p:DebugType=none \
|
||||||
-p:DebugSymbols=false \
|
-p:DebugSymbols=false \
|
||||||
-p:SkipAirAppHostBuild=true \
|
-p:SkipAirAppHostBuild=true \
|
||||||
@@ -651,6 +651,17 @@ jobs:
|
|||||||
-p:FileVersion=${{ needs.prepare.outputs.assembly_version }} \
|
-p:FileVersion=${{ needs.prepare.outputs.assembly_version }} \
|
||||||
-p:InformationalVersion=${{ needs.prepare.outputs.informational_version }}
|
-p:InformationalVersion=${{ needs.prepare.outputs.informational_version }}
|
||||||
|
|
||||||
|
- name: Optimize and Guard macOS Payload
|
||||||
|
run: |
|
||||||
|
arch="${{ matrix.arch }}"
|
||||||
|
publishDir="publish/macos-${arch}-app"
|
||||||
|
|
||||||
|
pwsh ./LanMountainDesktop/scripts/Optimize-PublishPayload.ps1 \
|
||||||
|
-PublishDir "$publishDir" \
|
||||||
|
-RuntimeIdentifier "osx-${arch}" \
|
||||||
|
-AssertClean
|
||||||
|
shell: bash
|
||||||
|
|
||||||
- name: Package Payload Zip
|
- name: Package Payload Zip
|
||||||
run: |
|
run: |
|
||||||
release_dir="$PWD/release-assets"
|
release_dir="$PWD/release-assets"
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ Rebuild the settings window as an independent Fluent shell with a custom titleba
|
|||||||
|
|
||||||
- Keep the existing independent settings-window lifecycle: open-or-focus, no owner anchor, own taskbar entry.
|
- Keep the existing independent settings-window lifecycle: open-or-focus, no owner anchor, own taskbar entry.
|
||||||
- Use a 48 DIP titlebar with Back, pane toggle, icon/title, search, restart action, more menu, and caption-button spacer.
|
- Use a 48 DIP titlebar with Back, pane toggle, icon/title, search, restart action, more menu, and caption-button spacer.
|
||||||
|
- Keep the titlebar and content area on one shared full-window background layer; the custom titlebar must remain transparent and must not paint a contrasting strip.
|
||||||
|
- Avoid a visible titlebar bottom divider that makes the titlebar read as a separate color band.
|
||||||
- Keep `FANavigationView` as the primary navigation surface with `OpenPaneLength` around 283 DIP.
|
- Keep `FANavigationView` as the primary navigation surface with `OpenPaneLength` around 283 DIP.
|
||||||
|
- Keep `FANavigationView` pane and content template backgrounds transparent in the settings shell so the navigation control does not reintroduce a second surface color.
|
||||||
- Move the compact/minimal pane toggle from the navigation footer into the titlebar.
|
- Move the compact/minimal pane toggle from the navigation footer into the titlebar.
|
||||||
- Add search over built-in settings pages and settings expanders; selecting a result navigates, expands, focuses, and highlights.
|
- Add search over built-in settings pages and settings expanders; selecting a result navigates, expands, focuses, and highlights.
|
||||||
- Add `auto` system material mode and make it the default.
|
- Add `auto` system material mode and make it the default.
|
||||||
|
|||||||
@@ -0,0 +1,276 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using LanMountainDesktop.Appearance;
|
||||||
|
using LanMountainDesktop.Models;
|
||||||
|
using LanMountainDesktop.PluginSdk;
|
||||||
|
using LanMountainDesktop.Services;
|
||||||
|
using LanMountainDesktop.Services.Settings;
|
||||||
|
using LanMountainDesktop.Settings.Core;
|
||||||
|
using LanMountainDesktop.Shared.Contracts;
|
||||||
|
using LanMountainDesktop.ViewModels;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Tests;
|
||||||
|
|
||||||
|
public sealed class MaterialColorSettingsPageViewModelTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Load_SelectsSavedNoneMaterialMode()
|
||||||
|
{
|
||||||
|
var facade = new FakeSettingsFacade(CreateThemeState(ThemeAppearanceValues.MaterialNone));
|
||||||
|
var materialService = new FakeMaterialColorService(CreateSnapshot(ThemeAppearanceValues.MaterialNone));
|
||||||
|
|
||||||
|
var viewModel = new MaterialColorSettingsPageViewModel(facade, materialService);
|
||||||
|
|
||||||
|
Assert.Equal(ThemeAppearanceValues.MaterialNone, viewModel.SelectedSystemMaterialMode.Value);
|
||||||
|
Assert.Contains(viewModel.SystemMaterialModes, option => option.Value == ThemeAppearanceValues.MaterialAuto);
|
||||||
|
Assert.Contains(viewModel.SystemMaterialModes, option => option.Value == ThemeAppearanceValues.MaterialNone);
|
||||||
|
Assert.Contains(viewModel.SystemMaterialModes, option => option.Value == ThemeAppearanceValues.MaterialMica);
|
||||||
|
Assert.Contains(viewModel.SystemMaterialModes, option => option.Value == ThemeAppearanceValues.MaterialAcrylic);
|
||||||
|
Assert.Equal(0, facade.ThemeSaveCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MaterialSnapshotRefresh_KeepsExplicitNoneSelection()
|
||||||
|
{
|
||||||
|
var facade = new FakeSettingsFacade(CreateThemeState(ThemeAppearanceValues.MaterialNone));
|
||||||
|
var materialService = new FakeMaterialColorService(CreateSnapshot(ThemeAppearanceValues.MaterialNone));
|
||||||
|
var viewModel = new MaterialColorSettingsPageViewModel(facade, materialService);
|
||||||
|
|
||||||
|
materialService.RaiseChanged(CreateSnapshot(ThemeAppearanceValues.MaterialAuto));
|
||||||
|
|
||||||
|
Assert.Equal(ThemeAppearanceValues.MaterialNone, viewModel.SelectedSystemMaterialMode.Value);
|
||||||
|
Assert.Equal(0, facade.ThemeSaveCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(ThemeAppearanceValues.MaterialNone)]
|
||||||
|
[InlineData(ThemeAppearanceValues.MaterialAuto)]
|
||||||
|
[InlineData(ThemeAppearanceValues.MaterialMica)]
|
||||||
|
[InlineData(ThemeAppearanceValues.MaterialAcrylic)]
|
||||||
|
public void UserSelection_SavesRequestedMaterialMode(string targetMode)
|
||||||
|
{
|
||||||
|
var initialMode = targetMode == ThemeAppearanceValues.MaterialNone
|
||||||
|
? ThemeAppearanceValues.MaterialAuto
|
||||||
|
: ThemeAppearanceValues.MaterialNone;
|
||||||
|
var facade = new FakeSettingsFacade(CreateThemeState(initialMode));
|
||||||
|
var materialService = new FakeMaterialColorService(CreateSnapshot(initialMode));
|
||||||
|
var viewModel = new MaterialColorSettingsPageViewModel(facade, materialService);
|
||||||
|
|
||||||
|
viewModel.SelectedSystemMaterialMode = viewModel.SystemMaterialModes.Single(option =>
|
||||||
|
option.Value == targetMode);
|
||||||
|
|
||||||
|
Assert.Equal(targetMode, facade.ThemeState.SystemMaterialMode);
|
||||||
|
Assert.Equal(1, facade.ThemeSaveCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ThemeAppearanceSettingsState CreateThemeState(string materialMode)
|
||||||
|
{
|
||||||
|
return new ThemeAppearanceSettingsState(
|
||||||
|
IsNightMode: false,
|
||||||
|
ThemeColor: "#FF445566",
|
||||||
|
UseSystemChrome: false,
|
||||||
|
CornerRadiusStyle: GlobalAppearanceSettings.CornerRadiusStyleRounded,
|
||||||
|
ThemeColorMode: ThemeAppearanceValues.ColorModeDefaultNeutral,
|
||||||
|
SystemMaterialMode: materialMode,
|
||||||
|
SelectedWallpaperSeed: null,
|
||||||
|
ThemeMode: ThemeAppearanceValues.ThemeModeLight,
|
||||||
|
ThemeWallpaperColorSource: ThemeAppearanceValues.WallpaperColorSourceAuto,
|
||||||
|
UseNativeWallpaperChangeEvents: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MaterialColorSnapshot CreateSnapshot(string materialMode)
|
||||||
|
{
|
||||||
|
var seed = Color.Parse("#FF3B82F6");
|
||||||
|
var palette = new LanMountainDesktop.Models.MaterialColorPalette(
|
||||||
|
seed,
|
||||||
|
Color.Parse("#FF64748B"),
|
||||||
|
seed,
|
||||||
|
Colors.White,
|
||||||
|
Color.Parse("#FF60A5FA"),
|
||||||
|
Color.Parse("#FF93C5FD"),
|
||||||
|
Color.Parse("#FFBFDBFE"),
|
||||||
|
Color.Parse("#FF2563EB"),
|
||||||
|
Color.Parse("#FF1D4ED8"),
|
||||||
|
Color.Parse("#FF1E40AF"),
|
||||||
|
Color.Parse("#FFF8FAFC"),
|
||||||
|
Color.Parse("#FFFFFFFF"),
|
||||||
|
Color.Parse("#FFF1F5F9"),
|
||||||
|
Color.Parse("#FF0F172A"),
|
||||||
|
Color.Parse("#FF334155"),
|
||||||
|
Color.Parse("#FF64748B"),
|
||||||
|
seed,
|
||||||
|
Color.Parse("#FF0F172A"),
|
||||||
|
Colors.White,
|
||||||
|
seed,
|
||||||
|
Color.Parse("#22000000"),
|
||||||
|
Color.Parse("#33000000"),
|
||||||
|
Color.Parse("#443B82F6"),
|
||||||
|
seed,
|
||||||
|
Color.Parse("#4464748B"),
|
||||||
|
Color.Parse("#663B82F6"));
|
||||||
|
var surface = new MaterialSurfaceSnapshot(
|
||||||
|
MaterialSurfaceRole.SettingsWindowBackground,
|
||||||
|
Color.Parse("#FFF8FAFC"),
|
||||||
|
Color.Parse("#22000000"),
|
||||||
|
0,
|
||||||
|
1);
|
||||||
|
var surfaces = new Dictionary<MaterialSurfaceRole, MaterialSurfaceSnapshot>
|
||||||
|
{
|
||||||
|
[MaterialSurfaceRole.SettingsWindowBackground] = surface,
|
||||||
|
[MaterialSurfaceRole.DockBackground] = surface with { Role = MaterialSurfaceRole.DockBackground },
|
||||||
|
[MaterialSurfaceRole.DesktopComponentHost] = surface with { Role = MaterialSurfaceRole.DesktopComponentHost },
|
||||||
|
[MaterialSurfaceRole.OverlayPanel] = surface with { Role = MaterialSurfaceRole.OverlayPanel }
|
||||||
|
};
|
||||||
|
|
||||||
|
return new MaterialColorSnapshot(
|
||||||
|
IsNightMode: false,
|
||||||
|
ThemeColorMode: ThemeAppearanceValues.ColorModeDefaultNeutral,
|
||||||
|
ThemeWallpaperColorSource: ThemeAppearanceValues.WallpaperColorSourceAuto,
|
||||||
|
ColorSourceKind: MaterialColorSourceKind.Neutral,
|
||||||
|
ResolvedSeedSource: "neutral",
|
||||||
|
CornerRadiusTokens: new AppearanceCornerRadiusTokens(
|
||||||
|
new CornerRadius(2),
|
||||||
|
new CornerRadius(4),
|
||||||
|
new CornerRadius(6),
|
||||||
|
new CornerRadius(8),
|
||||||
|
new CornerRadius(10),
|
||||||
|
new CornerRadius(12),
|
||||||
|
new CornerRadius(14),
|
||||||
|
new CornerRadius(8)),
|
||||||
|
UserThemeColor: seed.ToString(),
|
||||||
|
SelectedWallpaperSeed: null,
|
||||||
|
EffectiveSeedColor: seed,
|
||||||
|
AccentColor: seed,
|
||||||
|
MonetPalette: new MonetPalette([seed], seed, seed, seed, seed, seed, seed),
|
||||||
|
Palette: palette,
|
||||||
|
WallpaperSeedCandidates: [seed],
|
||||||
|
SystemMaterialMode: materialMode,
|
||||||
|
AvailableSystemMaterialModes:
|
||||||
|
[
|
||||||
|
ThemeAppearanceValues.MaterialAuto,
|
||||||
|
ThemeAppearanceValues.MaterialNone,
|
||||||
|
ThemeAppearanceValues.MaterialMica,
|
||||||
|
ThemeAppearanceValues.MaterialAcrylic
|
||||||
|
],
|
||||||
|
CanChangeSystemMaterial: true,
|
||||||
|
UseSystemChrome: false,
|
||||||
|
ResolvedWallpaperPath: null,
|
||||||
|
UseNativeWallpaperChangeEvents: true,
|
||||||
|
NativeWallpaperChangeEventsActive: false,
|
||||||
|
WallpaperPollingActive: false,
|
||||||
|
Surfaces: surfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FakeSettingsFacade(ThemeAppearanceSettingsState themeState) : ISettingsFacadeService
|
||||||
|
{
|
||||||
|
private readonly FakeThemeAppearanceService _theme = new(themeState);
|
||||||
|
private readonly FakeRegionSettingsService _region = new();
|
||||||
|
private readonly FakeWallpaperSettingsService _wallpaper = new();
|
||||||
|
|
||||||
|
public ThemeAppearanceSettingsState ThemeState => _theme.State;
|
||||||
|
public int ThemeSaveCount => _theme.SaveCount;
|
||||||
|
|
||||||
|
public ISettingsService Settings => throw new NotSupportedException();
|
||||||
|
public ISettingsCatalog Catalog => throw new NotSupportedException();
|
||||||
|
public IGridSettingsService Grid => throw new NotSupportedException();
|
||||||
|
public IWallpaperSettingsService Wallpaper => _wallpaper;
|
||||||
|
public IWallpaperMediaService WallpaperMedia => throw new NotSupportedException();
|
||||||
|
public IThemeAppearanceService Theme => _theme;
|
||||||
|
public IStatusBarSettingsService StatusBar => throw new NotSupportedException();
|
||||||
|
public ITextCapsuleSettingsService TextCapsule => throw new NotSupportedException();
|
||||||
|
public IWeatherSettingsService Weather => throw new NotSupportedException();
|
||||||
|
public IRegionSettingsService Region => _region;
|
||||||
|
public IPrivacySettingsService Privacy => throw new NotSupportedException();
|
||||||
|
public IUpdateSettingsService Update => throw new NotSupportedException();
|
||||||
|
public ILauncherCatalogService LauncherCatalog => throw new NotSupportedException();
|
||||||
|
public ILauncherPolicyService LauncherPolicy => throw new NotSupportedException();
|
||||||
|
public IPluginManagementSettingsService PluginManagement => throw new NotSupportedException();
|
||||||
|
public IPluginCatalogSettingsService PluginCatalog => throw new NotSupportedException();
|
||||||
|
public IApplicationInfoService ApplicationInfo => throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FakeThemeAppearanceService(ThemeAppearanceSettingsState state) : IThemeAppearanceService
|
||||||
|
{
|
||||||
|
public ThemeAppearanceSettingsState State { get; private set; } = state;
|
||||||
|
public int SaveCount { get; private set; }
|
||||||
|
|
||||||
|
public ThemeAppearanceSettingsState Get() => State;
|
||||||
|
|
||||||
|
public void Save(ThemeAppearanceSettingsState state)
|
||||||
|
{
|
||||||
|
SaveCount++;
|
||||||
|
State = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonetPalette BuildPalette(bool nightMode, string? wallpaperPath, string? preferredSeedColor = null)
|
||||||
|
{
|
||||||
|
var seed = Color.Parse(preferredSeedColor ?? "#FF3B82F6");
|
||||||
|
return new MonetPalette([seed], seed, seed, seed, seed, seed, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FakeRegionSettingsService : IRegionSettingsService
|
||||||
|
{
|
||||||
|
public RegionSettingsState Get() => new("en-US", null);
|
||||||
|
|
||||||
|
public void Save(RegionSettingsState state)
|
||||||
|
{
|
||||||
|
_ = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeZoneService GetTimeZoneService() => new();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FakeWallpaperSettingsService : IWallpaperSettingsService
|
||||||
|
{
|
||||||
|
public WallpaperSettingsState Get() => new(null, "SolidColor", "#FFFFFFFF", "Fill", 300);
|
||||||
|
|
||||||
|
public void Save(WallpaperSettingsState state)
|
||||||
|
{
|
||||||
|
_ = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FakeMaterialColorService(MaterialColorSnapshot snapshot) : IMaterialColorService
|
||||||
|
{
|
||||||
|
private MaterialColorSnapshot _snapshot = snapshot;
|
||||||
|
|
||||||
|
public event EventHandler<MaterialColorSnapshot>? MaterialColorChanged;
|
||||||
|
|
||||||
|
public MaterialColorSnapshot GetMaterialColorSnapshot() => _snapshot;
|
||||||
|
|
||||||
|
public MaterialColorSnapshot BuildMaterialColorPreview(ThemeAppearanceSettingsState pendingState)
|
||||||
|
{
|
||||||
|
_ = pendingState;
|
||||||
|
return _snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyThemeResources(IResourceDictionary resources)
|
||||||
|
{
|
||||||
|
_ = resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MaterialSurfaceSnapshot GetSurface(MaterialSurfaceRole role)
|
||||||
|
{
|
||||||
|
return _snapshot.Surfaces[role];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyWindowMaterial(Window window, MaterialSurfaceRole role)
|
||||||
|
{
|
||||||
|
_ = window;
|
||||||
|
_ = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshWallpaperColors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RaiseChanged(MaterialColorSnapshot snapshot)
|
||||||
|
{
|
||||||
|
_snapshot = snapshot;
|
||||||
|
MaterialColorChanged?.Invoke(this, snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
93
LanMountainDesktop.Tests/SettingsWindowShellVisualTests.cs
Normal file
93
LanMountainDesktop.Tests/SettingsWindowShellVisualTests.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Tests;
|
||||||
|
|
||||||
|
public sealed class SettingsWindowShellVisualTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void SettingsWindow_UsesOneFullWindowBackgroundBehindTitlebarAndContent()
|
||||||
|
{
|
||||||
|
var xaml = ReadRepositoryFile("LanMountainDesktop", "Views", "SettingsWindow.axaml");
|
||||||
|
|
||||||
|
Assert.Contains("x:Name=\"RootGrid\"", xaml);
|
||||||
|
Assert.Contains("Background=\"Transparent\"", ExtractElementStart(xaml, "<Grid x:Name=\"RootGrid\""));
|
||||||
|
Assert.Contains("Grid.RowSpan=\"2\"", xaml);
|
||||||
|
Assert.Contains("Background=\"{DynamicResource AdaptiveSettingsWindowBackgroundBrush}\"", xaml);
|
||||||
|
Assert.Contains("Background=\"{DynamicResource AdaptiveSettingsWindowTintBrush}\"", xaml);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SettingsWindow_TitlebarDoesNotPaintASeparateSurfaceBand()
|
||||||
|
{
|
||||||
|
var xaml = ReadRepositoryFile("LanMountainDesktop", "Views", "SettingsWindow.axaml");
|
||||||
|
var titlebar = ExtractElementStart(xaml, "<Border x:Name=\"WindowTitleBarHost\"");
|
||||||
|
|
||||||
|
Assert.Contains("Background=\"Transparent\"", titlebar);
|
||||||
|
Assert.Contains("BorderBrush=\"Transparent\"", titlebar);
|
||||||
|
Assert.Contains("BorderThickness=\"0\"", titlebar);
|
||||||
|
Assert.DoesNotContain("BorderThickness=\"0,0,0,1\"", titlebar);
|
||||||
|
Assert.DoesNotContain("AdaptiveSettingsWindowBackgroundBrush", titlebar);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SettingsWindow_NavigationShellBackgroundsAreTransparent()
|
||||||
|
{
|
||||||
|
var xaml = ReadRepositoryFile("LanMountainDesktop", "Views", "SettingsWindow.axaml");
|
||||||
|
|
||||||
|
Assert.Contains("Classes=\"settings-navigation-view\"", xaml);
|
||||||
|
Assert.Contains("<SolidColorBrush x:Key=\"NavigationViewContentBackground\" Color=\"Transparent\" />", xaml);
|
||||||
|
Assert.Contains("<SolidColorBrush x:Key=\"NavigationViewContentGridBorderBrush\" Color=\"Transparent\" />", xaml);
|
||||||
|
Assert.Contains("<SolidColorBrush x:Key=\"NavigationViewDefaultPaneBackground\" Color=\"Transparent\" />", xaml);
|
||||||
|
Assert.Contains("<SolidColorBrush x:Key=\"NavigationViewExpandedPaneBackground\" Color=\"Transparent\" />", xaml);
|
||||||
|
Assert.Contains("<SolidColorBrush x:Key=\"NavigationViewTopPaneBackground\" Color=\"Transparent\" />", xaml);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NavigationStyles_KeepSettingsNavigationTemplateTransparent()
|
||||||
|
{
|
||||||
|
var styles = ReadRepositoryFile("LanMountainDesktop", "Styles", "NavigationStyles.axaml");
|
||||||
|
|
||||||
|
Assert.Contains("ui|FANavigationView.settings-navigation-view", styles);
|
||||||
|
Assert.Contains("Grid#RootGrid", styles);
|
||||||
|
Assert.Contains("Grid#ContentGrid", styles);
|
||||||
|
Assert.Contains("Grid#PaneRoot", styles);
|
||||||
|
Assert.Contains("Border#NavigationViewBorder", styles);
|
||||||
|
Assert.Contains("Border#ContentGridBorder", styles);
|
||||||
|
Assert.Contains("Border#PaneBorder", styles);
|
||||||
|
Assert.Contains("<Setter Property=\"Background\" Value=\"Transparent\" />", styles);
|
||||||
|
Assert.Contains("<Setter Property=\"BorderBrush\" Value=\"Transparent\" />", styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractElementStart(string source, string startToken)
|
||||||
|
{
|
||||||
|
var start = source.IndexOf(startToken, StringComparison.Ordinal);
|
||||||
|
Assert.True(start >= 0, $"Could not find '{startToken}'.");
|
||||||
|
|
||||||
|
var end = source.IndexOf('>', start);
|
||||||
|
Assert.True(end > start, $"Could not find end of '{startToken}'.");
|
||||||
|
|
||||||
|
return source.Substring(start, end - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ReadRepositoryFile(params string[] segments)
|
||||||
|
{
|
||||||
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||||
|
while (directory is not null)
|
||||||
|
{
|
||||||
|
var candidate = Path.Combine(new[] { directory.FullName }.Concat(segments).ToArray());
|
||||||
|
if (File.Exists(candidate))
|
||||||
|
{
|
||||||
|
return File.ReadAllText(candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(Path.Combine(directory.FullName, "LanMountainDesktop.slnx")))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
directory = directory.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException($"Could not locate repository file '{Path.Combine(segments)}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -116,6 +116,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ui|FANavigationView.settings-navigation-view">
|
<Style Selector="ui|FANavigationView.settings-navigation-view">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
<DoubleTransition Property="Opacity" Duration="0:0:0.2" Easing="0.05,0.75,0.10,1.00" />
|
<DoubleTransition Property="Opacity" Duration="0:0:0.2" Easing="0.05,0.75,0.10,1.00" />
|
||||||
@@ -123,6 +124,23 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ui|FANavigationView.settings-navigation-view /template/ Grid#RootGrid,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Grid#ContentGrid,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Grid#ContentRoot,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Grid#PaneRoot,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Grid#PaneContentGrid">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ui|FANavigationView.settings-navigation-view /template/ Border#NavigationViewBorder,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Border#ContentGridBorder,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Border#PaneBorder,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Border#PaneContentGridBorder,
|
||||||
|
ui|FANavigationView.settings-navigation-view /template/ Border#TopPaneBorder">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ui|FANavigationView.settings-navigation-view /template/ Border#NavigationViewBorder">
|
<Style Selector="ui|FANavigationView.settings-navigation-view /template/ Border#NavigationViewBorder">
|
||||||
<Setter Property="Transitions">
|
<Setter Property="Transitions">
|
||||||
<Transitions>
|
<Transitions>
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public sealed partial class MaterialColorSettingsPageViewModel : ViewModelBase
|
|||||||
private readonly LocalizationService _localizationService = new();
|
private readonly LocalizationService _localizationService = new();
|
||||||
private readonly string _languageCode;
|
private readonly string _languageCode;
|
||||||
private bool _isInitializing;
|
private bool _isInitializing;
|
||||||
|
private bool _isSynchronizingSystemMaterialMode;
|
||||||
private string? _selectedWallpaperSeed;
|
private string? _selectedWallpaperSeed;
|
||||||
|
|
||||||
public MaterialColorSettingsPageViewModel(
|
public MaterialColorSettingsPageViewModel(
|
||||||
@@ -307,7 +308,7 @@ public sealed partial class MaterialColorSettingsPageViewModel : ViewModelBase
|
|||||||
|
|
||||||
partial void OnSelectedSystemMaterialModeChanged(SelectionOption value)
|
partial void OnSelectedSystemMaterialModeChanged(SelectionOption value)
|
||||||
{
|
{
|
||||||
if (_isInitializing || value is null)
|
if (_isInitializing || _isSynchronizingSystemMaterialMode || value is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -452,15 +453,33 @@ public sealed partial class MaterialColorSettingsPageViewModel : ViewModelBase
|
|||||||
|
|
||||||
private void RefreshMaterialModes(MaterialColorSnapshot snapshot)
|
private void RefreshMaterialModes(MaterialColorSnapshot snapshot)
|
||||||
{
|
{
|
||||||
SystemMaterialModes = snapshot.AvailableSystemMaterialModes
|
var selectedValue = ThemeAppearanceValues.NormalizeSystemMaterialMode(
|
||||||
|
SelectedSystemMaterialMode?.Value ?? snapshot.SystemMaterialMode);
|
||||||
|
var snapshotValue = ThemeAppearanceValues.NormalizeSystemMaterialMode(snapshot.SystemMaterialMode);
|
||||||
|
|
||||||
|
SystemMaterialModes = ThemeAppearanceValues.NormalizeAvailableMaterialModes(snapshot.AvailableSystemMaterialModes)
|
||||||
.Select(value => new SelectionOption(value, ResolveMaterialLabel(value)))
|
.Select(value => new SelectionOption(value, ResolveMaterialLabel(value)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
if (!SystemMaterialModes.Any(option =>
|
var nextSelection = SystemMaterialModes.FirstOrDefault(option =>
|
||||||
string.Equals(option.Value, SelectedSystemMaterialMode?.Value, StringComparison.OrdinalIgnoreCase)))
|
string.Equals(option.Value, selectedValue, StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? SystemMaterialModes.FirstOrDefault(option =>
|
||||||
|
string.Equals(option.Value, snapshotValue, StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? SystemMaterialModes.FirstOrDefault()
|
||||||
|
?? new SelectionOption(ThemeAppearanceValues.MaterialNone, MaterialNoneText);
|
||||||
|
|
||||||
|
if (!string.Equals(SelectedSystemMaterialMode?.Value, nextSelection.Value, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
!ReferenceEquals(SelectedSystemMaterialMode, nextSelection))
|
||||||
{
|
{
|
||||||
SelectedSystemMaterialMode = SystemMaterialModes.FirstOrDefault()
|
_isSynchronizingSystemMaterialMode = true;
|
||||||
?? new SelectionOption(ThemeAppearanceValues.MaterialNone, MaterialNoneText);
|
try
|
||||||
|
{
|
||||||
|
SelectedSystemMaterialMode = nextSelection;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isSynchronizingSystemMaterialMode = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,11 +67,20 @@
|
|||||||
|
|
||||||
<Grid x:Name="RootGrid"
|
<Grid x:Name="RootGrid"
|
||||||
Classes="settings-scope"
|
Classes="settings-scope"
|
||||||
Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}"
|
Background="Transparent"
|
||||||
RowDefinitions="Auto,*">
|
RowDefinitions="Auto,*">
|
||||||
|
|
||||||
|
<Border Grid.RowSpan="2"
|
||||||
|
Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}"
|
||||||
|
IsHitTestVisible="False" />
|
||||||
|
|
||||||
|
<Border Grid.RowSpan="2"
|
||||||
|
Background="{DynamicResource AdaptiveSettingsWindowTintBrush}"
|
||||||
|
IsHitTestVisible="False" />
|
||||||
|
|
||||||
<ui:FANavigationView x:Name="RootNavigationView"
|
<ui:FANavigationView x:Name="RootNavigationView"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
|
Classes="settings-navigation-view"
|
||||||
Margin="0"
|
Margin="0"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
PaneDisplayMode="Auto"
|
PaneDisplayMode="Auto"
|
||||||
@@ -90,6 +99,11 @@
|
|||||||
<ui:FANavigationView.Resources>
|
<ui:FANavigationView.Resources>
|
||||||
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
||||||
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
|
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
|
||||||
|
<SolidColorBrush x:Key="NavigationViewDefaultPaneBackground" Color="Transparent" />
|
||||||
|
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="Transparent" />
|
||||||
|
<SolidColorBrush x:Key="NavigationViewMinimalPaneBackground" Color="Transparent" />
|
||||||
|
<SolidColorBrush x:Key="NavigationViewPaneBackground" Color="Transparent" />
|
||||||
|
<SolidColorBrush x:Key="NavigationViewTopPaneBackground" Color="Transparent" />
|
||||||
</ui:FANavigationView.Resources>
|
</ui:FANavigationView.Resources>
|
||||||
|
|
||||||
<Grid x:Name="SettingsContentGrid"
|
<Grid x:Name="SettingsContentGrid"
|
||||||
@@ -155,9 +169,9 @@
|
|||||||
<Border x:Name="WindowTitleBarHost"
|
<Border x:Name="WindowTitleBarHost"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Height="48"
|
Height="48"
|
||||||
Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}"
|
Background="Transparent"
|
||||||
BorderBrush="{DynamicResource AdaptiveSettingsWindowBorderBrush}"
|
BorderBrush="Transparent"
|
||||||
BorderThickness="0,0,0,1"
|
BorderThickness="0"
|
||||||
PointerPressed="OnTitleBarDragZonePointerPressed">
|
PointerPressed="OnTitleBarDragZonePointerPressed">
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto"
|
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
|
|||||||
@@ -134,10 +134,6 @@ function Remove-NonTargetRuntimeDirectories {
|
|||||||
[Parameter(Mandatory = $true)][string]$Rid
|
[Parameter(Mandatory = $true)][string]$Rid
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($Rid -notlike "win-*") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$runtimeRoots = @(Get-ChildItem -LiteralPath $Root -Recurse -Directory -Filter "runtimes" -ErrorAction SilentlyContinue)
|
$runtimeRoots = @(Get-ChildItem -LiteralPath $Root -Recurse -Directory -Filter "runtimes" -ErrorAction SilentlyContinue)
|
||||||
$removed = 0
|
$removed = 0
|
||||||
foreach ($runtimeRoot in $runtimeRoots) {
|
foreach ($runtimeRoot in $runtimeRoots) {
|
||||||
@@ -152,25 +148,43 @@ function Remove-NonTargetRuntimeDirectories {
|
|||||||
Write-Host "Removed non-target runtime directories: $removed"
|
Write-Host "Removed non-target runtime directories: $removed"
|
||||||
}
|
}
|
||||||
|
|
||||||
function Assert-WindowsPayloadClean {
|
function Assert-PayloadClean {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)][string]$Root,
|
[Parameter(Mandatory = $true)][string]$Root,
|
||||||
[Parameter(Mandatory = $true)][string]$Rid
|
[Parameter(Mandatory = $true)][string]$Rid
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($Rid -notlike "win-*") {
|
$violations = [System.Collections.Generic.List[string]]::new()
|
||||||
|
|
||||||
|
if ($Rid -like "win-*") {
|
||||||
|
$forbiddenExtensions = @(".pdb", ".so", ".dylib", ".a")
|
||||||
|
$forbiddenBundledRuntimeFiles = @(
|
||||||
|
"coreclr.dll",
|
||||||
|
"hostfxr.dll",
|
||||||
|
"hostpolicy.dll",
|
||||||
|
"System.Private.CoreLib.dll"
|
||||||
|
)
|
||||||
|
} elseif ($Rid -like "osx-*") {
|
||||||
|
$forbiddenExtensions = @(".pdb", ".so", ".a")
|
||||||
|
$forbiddenBundledRuntimeFiles = @(
|
||||||
|
"libcoreclr.dylib",
|
||||||
|
"libhostfxr.dylib",
|
||||||
|
"libhostpolicy.dylib",
|
||||||
|
"System.Private.CoreLib.dll"
|
||||||
|
)
|
||||||
|
} elseif ($Rid -like "linux-*") {
|
||||||
|
$forbiddenExtensions = @(".pdb", ".dylib", ".dll", ".a")
|
||||||
|
$forbiddenBundledRuntimeFiles = @(
|
||||||
|
"libcoreclr.so",
|
||||||
|
"libhostfxr.so",
|
||||||
|
"libhostpolicy.so",
|
||||||
|
"System.Private.CoreLib.dll"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Write-Host "Unknown RID platform for payload clean assertion: $Rid — skipping."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$violations = [System.Collections.Generic.List[string]]::new()
|
|
||||||
$forbiddenExtensions = @(".pdb", ".so", ".dylib", ".a")
|
|
||||||
$forbiddenBundledRuntimeFiles = @(
|
|
||||||
"coreclr.dll",
|
|
||||||
"hostfxr.dll",
|
|
||||||
"hostpolicy.dll",
|
|
||||||
"System.Private.CoreLib.dll"
|
|
||||||
)
|
|
||||||
|
|
||||||
Get-ChildItem -LiteralPath $Root -Recurse -File -ErrorAction SilentlyContinue |
|
Get-ChildItem -LiteralPath $Root -Recurse -File -ErrorAction SilentlyContinue |
|
||||||
Where-Object { $forbiddenExtensions -contains $_.Extension.ToLowerInvariant() } |
|
Where-Object { $forbiddenExtensions -contains $_.Extension.ToLowerInvariant() } |
|
||||||
ForEach-Object {
|
ForEach-Object {
|
||||||
@@ -183,7 +197,6 @@ function Assert-WindowsPayloadClean {
|
|||||||
$violations.Add((Get-RelativePathCompat -Root $Root -Path $_.FullName))
|
$violations.Add((Get-RelativePathCompat -Root $Root -Path $_.FullName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Get-ChildItem -LiteralPath $Root -Recurse -Directory -Filter "runtimes" -ErrorAction SilentlyContinue |
|
Get-ChildItem -LiteralPath $Root -Recurse -Directory -Filter "runtimes" -ErrorAction SilentlyContinue |
|
||||||
ForEach-Object {
|
ForEach-Object {
|
||||||
Get-ChildItem -LiteralPath $_.FullName -Directory -ErrorAction SilentlyContinue |
|
Get-ChildItem -LiteralPath $_.FullName -Directory -ErrorAction SilentlyContinue |
|
||||||
@@ -195,10 +208,10 @@ function Assert-WindowsPayloadClean {
|
|||||||
|
|
||||||
if ($violations.Count -gt 0) {
|
if ($violations.Count -gt 0) {
|
||||||
$sample = ($violations | Select-Object -First 50) -join [Environment]::NewLine
|
$sample = ($violations | Select-Object -First 50) -join [Environment]::NewLine
|
||||||
throw "Windows publish payload contains forbidden files or runtime directories for ${Rid}:$([Environment]::NewLine)$sample"
|
throw "Publish payload contains forbidden files or runtime directories for ${Rid}:$([Environment]::NewLine)$sample"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Windows payload guard passed for $Rid."
|
Write-Host "Payload guard passed for $Rid."
|
||||||
}
|
}
|
||||||
|
|
||||||
function Assert-WindowsPayloadContainsRequiredHosts {
|
function Assert-WindowsPayloadContainsRequiredHosts {
|
||||||
@@ -258,7 +271,7 @@ Remove-NonTargetRuntimeDirectories -Root $resolvedPublishDir -Rid $RuntimeIdenti
|
|||||||
Write-PayloadAudit -Root $resolvedPublishDir
|
Write-PayloadAudit -Root $resolvedPublishDir
|
||||||
|
|
||||||
if ($AssertClean) {
|
if ($AssertClean) {
|
||||||
Assert-WindowsPayloadClean -Root $resolvedPublishDir -Rid $RuntimeIdentifier
|
Assert-PayloadClean -Root $resolvedPublishDir -Rid $RuntimeIdentifier
|
||||||
if ($RuntimeIdentifier -like "win-*") {
|
if ($RuntimeIdentifier -like "win-*") {
|
||||||
Assert-WindowsPayloadContainsRequiredHosts -Root $resolvedPublishDir
|
Assert-WindowsPayloadContainsRequiredHosts -Root $resolvedPublishDir
|
||||||
}
|
}
|
||||||
|
|||||||
109
ago --name-only --oneline
Normal file
109
ago --name-only --oneline
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS
|
||||||
|
|
||||||
|
Commands marked with * may be preceded by a number, _N.
|
||||||
|
Notes in parentheses indicate the behavior if _N is given.
|
||||||
|
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.
|
||||||
|
|
||||||
|
h H Display this help.
|
||||||
|
q :q Q :Q ZZ Exit.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MMOOVVIINNGG
|
||||||
|
|
||||||
|
e ^E j ^N CR * Forward one line (or _N lines).
|
||||||
|
y ^Y k ^K ^P * Backward one line (or _N lines).
|
||||||
|
ESC-j * Forward one file line (or _N file lines).
|
||||||
|
ESC-k * Backward one file line (or _N file lines).
|
||||||
|
f ^F ^V SPACE * Forward one window (or _N lines).
|
||||||
|
b ^B ESC-v * Backward one window (or _N lines).
|
||||||
|
z * Forward one window (and set window to _N).
|
||||||
|
w * Backward one window (and set window to _N).
|
||||||
|
ESC-SPACE * Forward one window, but don't stop at end-of-file.
|
||||||
|
ESC-b * Backward one window, but don't stop at beginning-of-file.
|
||||||
|
d ^D * Forward one half-window (and set half-window to _N).
|
||||||
|
u ^U * Backward one half-window (and set half-window to _N).
|
||||||
|
ESC-) RightArrow * Right one half screen width (or _N positions).
|
||||||
|
ESC-( LeftArrow * Left one half screen width (or _N positions).
|
||||||
|
ESC-} ^RightArrow Right to last column displayed.
|
||||||
|
ESC-{ ^LeftArrow Left to first column.
|
||||||
|
F Forward forever; like "tail -f".
|
||||||
|
ESC-F Like F but stop when search pattern is found.
|
||||||
|
r ^R ^L Repaint screen.
|
||||||
|
R Repaint screen, discarding buffered input.
|
||||||
|
---------------------------------------------------
|
||||||
|
Default "window" is the screen height.
|
||||||
|
Default "half-window" is half of the screen height.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SSEEAARRCCHHIINNGG
|
||||||
|
|
||||||
|
/_p_a_t_t_e_r_n * Search forward for (_N-th) matching line.
|
||||||
|
?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line.
|
||||||
|
n * Repeat previous search (for _N-th occurrence).
|
||||||
|
N * Repeat previous search in reverse direction.
|
||||||
|
ESC-n * Repeat previous search, spanning files.
|
||||||
|
ESC-N * Repeat previous search, reverse dir. & spanning files.
|
||||||
|
^O^N ^On * Search forward for (_N-th) OSC8 hyperlink.
|
||||||
|
^O^P ^Op * Search backward for (_N-th) OSC8 hyperlink.
|
||||||
|
^O^L ^Ol Jump to the currently selected OSC8 hyperlink.
|
||||||
|
ESC-u Undo (toggle) search highlighting.
|
||||||
|
ESC-U Clear search highlighting.
|
||||||
|
&_p_a_t_t_e_r_n * Display only matching lines.
|
||||||
|
---------------------------------------------------
|
||||||
|
Search is case-sensitive unless changed with -i or -I.
|
||||||
|
A search pattern may begin with one or more of:
|
||||||
|
^N or ! Search for NON-matching lines.
|
||||||
|
^E or * Search multiple files (pass thru END OF FILE).
|
||||||
|
^F or @ Start search at FIRST file (for /) or last file (for ?).
|
||||||
|
^K Highlight matches, but don't move (KEEP position).
|
||||||
|
^R Don't use REGULAR EXPRESSIONS.
|
||||||
|
^S _n Search for match in _n-th parenthesized subpattern.
|
||||||
|
^W WRAP search if no match found.
|
||||||
|
^L Enter next character literally into pattern.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JJUUMMPPIINNGG
|
||||||
|
|
||||||
|
g < ESC-< * Go to first line in file (or line _N).
|
||||||
|
G > ESC-> * Go to last line in file (or line _N).
|
||||||
|
p % * Go to beginning of file (or _N percent into file).
|
||||||
|
t * Go to the (_N-th) next tag.
|
||||||
|
T * Go to the (_N-th) previous tag.
|
||||||
|
{ ( [ * Find close bracket } ) ].
|
||||||
|
} ) ] * Find open bracket { ( [.
|
||||||
|
ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>.
|
||||||
|
ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>.
|
||||||
|
---------------------------------------------------
|
||||||
|
Each "find close bracket" command goes forward to the close bracket
|
||||||
|
matching the (_N-th) open bracket in the top line.
|
||||||
|
Each "find open bracket" command goes backward to the open bracket
|
||||||
|
matching the (_N-th) close bracket in the bottom line.
|
||||||
|
|
||||||
|
m_<_l_e_t_t_e_r_> Mark the current top line with <letter>.
|
||||||
|
M_<_l_e_t_t_e_r_> Mark the current bottom line with <letter>.
|
||||||
|
'_<_l_e_t_t_e_r_> Go to a previously marked position.
|
||||||
|
'' Go to the previous position.
|
||||||
|
^X^X Same as '.
|
||||||
|
ESC-m_<_l_e_t_t_e_r_> Clear a mark.
|
||||||
|
---------------------------------------------------
|
||||||
|
A mark is any upper-case or lower-case letter.
|
||||||
|
Certain marks are predefined:
|
||||||
|
^ means beginning of the file
|
||||||
|
$ means end of the file
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CCHHAANNGGIINNGG FFIILLEESS
|
||||||
|
|
||||||
|
:e [_f_i_l_e] Examine a new file.
|
||||||
|
^X^V Same as :e.
|
||||||
|
:n * Examine the (_N-th) next file from the command line.
|
||||||
|
:p * Examine the (_N-th) previous file from the command line.
|
||||||
|
:x * Examine the first (or _N-th) file from the command line.
|
||||||
|
^O^O Open the currently selected OSC8 hyperlink.
|
||||||
|
:d Delete the current file from the command line list.
|
||||||
|
= ^G :f Print current file name.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MMIISSCCEELLLLAANNEEOOUUSS CCOOMMMMAANNDDSS
|
||||||
|
|
||||||
109
ago --name-only --stat
Normal file
109
ago --name-only --stat
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS
|
||||||
|
|
||||||
|
Commands marked with * may be preceded by a number, _N.
|
||||||
|
Notes in parentheses indicate the behavior if _N is given.
|
||||||
|
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.
|
||||||
|
|
||||||
|
h H Display this help.
|
||||||
|
q :q Q :Q ZZ Exit.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MMOOVVIINNGG
|
||||||
|
|
||||||
|
e ^E j ^N CR * Forward one line (or _N lines).
|
||||||
|
y ^Y k ^K ^P * Backward one line (or _N lines).
|
||||||
|
ESC-j * Forward one file line (or _N file lines).
|
||||||
|
ESC-k * Backward one file line (or _N file lines).
|
||||||
|
f ^F ^V SPACE * Forward one window (or _N lines).
|
||||||
|
b ^B ESC-v * Backward one window (or _N lines).
|
||||||
|
z * Forward one window (and set window to _N).
|
||||||
|
w * Backward one window (and set window to _N).
|
||||||
|
ESC-SPACE * Forward one window, but don't stop at end-of-file.
|
||||||
|
ESC-b * Backward one window, but don't stop at beginning-of-file.
|
||||||
|
d ^D * Forward one half-window (and set half-window to _N).
|
||||||
|
u ^U * Backward one half-window (and set half-window to _N).
|
||||||
|
ESC-) RightArrow * Right one half screen width (or _N positions).
|
||||||
|
ESC-( LeftArrow * Left one half screen width (or _N positions).
|
||||||
|
ESC-} ^RightArrow Right to last column displayed.
|
||||||
|
ESC-{ ^LeftArrow Left to first column.
|
||||||
|
F Forward forever; like "tail -f".
|
||||||
|
ESC-F Like F but stop when search pattern is found.
|
||||||
|
r ^R ^L Repaint screen.
|
||||||
|
R Repaint screen, discarding buffered input.
|
||||||
|
---------------------------------------------------
|
||||||
|
Default "window" is the screen height.
|
||||||
|
Default "half-window" is half of the screen height.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SSEEAARRCCHHIINNGG
|
||||||
|
|
||||||
|
/_p_a_t_t_e_r_n * Search forward for (_N-th) matching line.
|
||||||
|
?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line.
|
||||||
|
n * Repeat previous search (for _N-th occurrence).
|
||||||
|
N * Repeat previous search in reverse direction.
|
||||||
|
ESC-n * Repeat previous search, spanning files.
|
||||||
|
ESC-N * Repeat previous search, reverse dir. & spanning files.
|
||||||
|
^O^N ^On * Search forward for (_N-th) OSC8 hyperlink.
|
||||||
|
^O^P ^Op * Search backward for (_N-th) OSC8 hyperlink.
|
||||||
|
^O^L ^Ol Jump to the currently selected OSC8 hyperlink.
|
||||||
|
ESC-u Undo (toggle) search highlighting.
|
||||||
|
ESC-U Clear search highlighting.
|
||||||
|
&_p_a_t_t_e_r_n * Display only matching lines.
|
||||||
|
---------------------------------------------------
|
||||||
|
Search is case-sensitive unless changed with -i or -I.
|
||||||
|
A search pattern may begin with one or more of:
|
||||||
|
^N or ! Search for NON-matching lines.
|
||||||
|
^E or * Search multiple files (pass thru END OF FILE).
|
||||||
|
^F or @ Start search at FIRST file (for /) or last file (for ?).
|
||||||
|
^K Highlight matches, but don't move (KEEP position).
|
||||||
|
^R Don't use REGULAR EXPRESSIONS.
|
||||||
|
^S _n Search for match in _n-th parenthesized subpattern.
|
||||||
|
^W WRAP search if no match found.
|
||||||
|
^L Enter next character literally into pattern.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JJUUMMPPIINNGG
|
||||||
|
|
||||||
|
g < ESC-< * Go to first line in file (or line _N).
|
||||||
|
G > ESC-> * Go to last line in file (or line _N).
|
||||||
|
p % * Go to beginning of file (or _N percent into file).
|
||||||
|
t * Go to the (_N-th) next tag.
|
||||||
|
T * Go to the (_N-th) previous tag.
|
||||||
|
{ ( [ * Find close bracket } ) ].
|
||||||
|
} ) ] * Find open bracket { ( [.
|
||||||
|
ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>.
|
||||||
|
ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>.
|
||||||
|
---------------------------------------------------
|
||||||
|
Each "find close bracket" command goes forward to the close bracket
|
||||||
|
matching the (_N-th) open bracket in the top line.
|
||||||
|
Each "find open bracket" command goes backward to the open bracket
|
||||||
|
matching the (_N-th) close bracket in the bottom line.
|
||||||
|
|
||||||
|
m_<_l_e_t_t_e_r_> Mark the current top line with <letter>.
|
||||||
|
M_<_l_e_t_t_e_r_> Mark the current bottom line with <letter>.
|
||||||
|
'_<_l_e_t_t_e_r_> Go to a previously marked position.
|
||||||
|
'' Go to the previous position.
|
||||||
|
^X^X Same as '.
|
||||||
|
ESC-m_<_l_e_t_t_e_r_> Clear a mark.
|
||||||
|
---------------------------------------------------
|
||||||
|
A mark is any upper-case or lower-case letter.
|
||||||
|
Certain marks are predefined:
|
||||||
|
^ means beginning of the file
|
||||||
|
$ means end of the file
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CCHHAANNGGIINNGG FFIILLEESS
|
||||||
|
|
||||||
|
:e [_f_i_l_e] Examine a new file.
|
||||||
|
^X^V Same as :e.
|
||||||
|
:n * Examine the (_N-th) next file from the command line.
|
||||||
|
:p * Examine the (_N-th) previous file from the command line.
|
||||||
|
:x * Examine the first (or _N-th) file from the command line.
|
||||||
|
^O^O Open the currently selected OSC8 hyperlink.
|
||||||
|
:d Delete the current file from the command line list.
|
||||||
|
= ^G :f Print current file name.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MMIISSCCEELLLLAANNEEOOUUSS CCOOMMMMAANNDDSS
|
||||||
|
|
||||||
44
ago --stat --format=short
Normal file
44
ago --stat --format=short
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS
|
||||||
|
|
||||||
|
Commands marked with * may be preceded by a number, _N.
|
||||||
|
Notes in parentheses indicate the behavior if _N is given.
|
||||||
|
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.
|
||||||
|
|
||||||
|
h H Display this help.
|
||||||
|
q :q Q :Q ZZ Exit.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MMOOVVIINNGG
|
||||||
|
|
||||||
|
e ^E j ^N CR * Forward one line (or _N lines).
|
||||||
|
y ^Y k ^K ^P * Backward one line (or _N lines).
|
||||||
|
ESC-j * Forward one file line (or _N file lines).
|
||||||
|
ESC-k * Backward one file line (or _N file lines).
|
||||||
|
f ^F ^V SPACE * Forward one window (or _N lines).
|
||||||
|
b ^B ESC-v * Backward one window (or _N lines).
|
||||||
|
z * Forward one window (and set window to _N).
|
||||||
|
w * Backward one window (and set window to _N).
|
||||||
|
ESC-SPACE * Forward one window, but don't stop at end-of-file.
|
||||||
|
ESC-b * Backward one window, but don't stop at beginning-of-file.
|
||||||
|
d ^D * Forward one half-window (and set half-window to _N).
|
||||||
|
u ^U * Backward one half-window (and set half-window to _N).
|
||||||
|
ESC-) RightArrow * Right one half screen width (or _N positions).
|
||||||
|
ESC-( LeftArrow * Left one half screen width (or _N positions).
|
||||||
|
ESC-} ^RightArrow Right to last column displayed.
|
||||||
|
ESC-{ ^LeftArrow Left to first column.
|
||||||
|
F Forward forever; like "tail -f".
|
||||||
|
ESC-F Like F but stop when search pattern is found.
|
||||||
|
r ^R ^L Repaint screen.
|
||||||
|
R Repaint screen, discarding buffered input.
|
||||||
|
---------------------------------------------------
|
||||||
|
Default "window" is the screen height.
|
||||||
|
Default "half-window" is half of the screen height.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SSEEAARRCCHHIINNGG
|
||||||
|
|
||||||
|
/_p_a_t_t_e_r_n * Search forward for (_N-th) matching line.
|
||||||
|
?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line.
|
||||||
|
n * Repeat previous search (for _N-th occurrence).
|
||||||
|
N * Repeat previous search in reverse direction.
|
||||||
0
how 6a65087
Normal file
0
how 6a65087
Normal file
Reference in New Issue
Block a user