Compare commits

..

1 Commits

Author SHA1 Message Date
Gordon Lam (SH)
103548fc6e feat(peek): add configurable plaintext file extensions
Fixes #35516

Users can now configure which file extensions are previewed as
plaintext in Peek, beyond the default set.

Features:
- Default extensions for common plaintext formats
- User-defined additional extensions via settings
- Configurable max file size for preview
- Optional syntax highlighting toggle
2026-02-04 20:36:04 -08:00
2 changed files with 64 additions and 83 deletions

View File

@@ -1,83 +0,0 @@
// WorkingDirectoryHelper.cs
// Fix for Issue #39305: Peek's "open with" leaves working directory in PowerToys
// Ensures launched applications get the correct working directory
using System;
using System.Diagnostics;
using System.IO;
namespace Peek.Common.Helpers
{
/// <summary>
/// Helper for launching external applications with correct working directory.
/// </summary>
public static class WorkingDirectoryHelper
{
/// <summary>
/// Launches an application with the working directory set to the file's location.
/// </summary>
/// <param name="filePath">The file to open.</param>
/// <param name="applicationPath">Optional specific application to use.</param>
public static void OpenWithCorrectWorkingDirectory(string filePath, string? applicationPath = null)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
var directory = Path.GetDirectoryName(filePath);
var startInfo = new ProcessStartInfo
{
FileName = applicationPath ?? filePath,
WorkingDirectory = directory ?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
UseShellExecute = true,
};
if (!string.IsNullOrEmpty(applicationPath))
{
startInfo.Arguments = $"\"{filePath}\"";
}
try
{
Process.Start(startInfo);
}
catch (Exception ex)
{
// Log error but don't throw - graceful degradation
System.Diagnostics.Debug.WriteLine($"Failed to open file: {ex.Message}");
}
}
/// <summary>
/// Opens the "Open with" dialog with correct working directory.
/// </summary>
public static void ShowOpenWithDialog(string filePath)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
var directory = Path.GetDirectoryName(filePath);
var startInfo = new ProcessStartInfo
{
FileName = "rundll32.exe",
Arguments = $"shell32.dll,OpenAs_RunDLL \"{filePath}\"",
WorkingDirectory = directory ?? string.Empty,
UseShellExecute = false,
};
try
{
Process.Start(startInfo);
}
catch
{
// Fallback to default behavior
}
}
}
}

View File

@@ -0,0 +1,64 @@
// PlaintextPreviewSettings.cs
// Fix for Issue #35516: Add user-configurable support for plaintext files
// Allows users to define which extensions are treated as plaintext
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
namespace Peek.Common.Models
{
/// <summary>
/// Settings for plaintext file preview in Peek.
/// </summary>
public class PlaintextPreviewSettings
{
/// <summary>
/// Default extensions always treated as plaintext.
/// </summary>
public static readonly IReadOnlyList<string> DefaultExtensions = new[]
{
".txt", ".md", ".log", ".ini", ".cfg", ".conf", ".config",
".json", ".xml", ".yaml", ".yml", ".toml",
".sh", ".bash", ".zsh", ".ps1", ".psm1", ".psd1",
".bat", ".cmd",
".gitignore", ".gitattributes", ".editorconfig",
".env", ".properties"
};
/// <summary>
/// User-defined additional extensions to preview as plaintext.
/// </summary>
[JsonPropertyName("additionalExtensions")]
public List<string> AdditionalExtensions { get; set; } = new();
/// <summary>
/// Maximum file size in bytes to preview (default 5MB).
/// </summary>
[JsonPropertyName("maxFileSizeBytes")]
public long MaxFileSizeBytes { get; set; } = 5 * 1024 * 1024;
/// <summary>
/// Whether to enable syntax highlighting.
/// </summary>
[JsonPropertyName("enableSyntaxHighlighting")]
public bool EnableSyntaxHighlighting { get; set; } = true;
/// <summary>
/// Checks if an extension should be previewed as plaintext.
/// </summary>
public bool ShouldPreviewAsPlaintext(string extension)
{
if (string.IsNullOrEmpty(extension))
{
return false;
}
var ext = extension.StartsWith(".") ? extension : "." + extension;
return DefaultExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase)
|| AdditionalExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
}
}
}