From 8ce12cd032ae83cd071fbaefb1dcf70ecf3545d0 Mon Sep 17 00:00:00 2001 From: Sebastian Walter Date: Fri, 18 Sep 2026 15:57:18 +0200 Subject: [PATCH] feat: add custom file associations support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added `CustomFileAssociations` class with a JSON‑serializable `Associations` dictionary. - Refactored extension handling in `TextMateHelper.GetScope` to a switch statement. - Implemented loading of `custom_file_associations.json` to map specific files to custom extensions, including safe JSON deserialization with error handling. - Added `System.Text.Json` import to support deserialization. --- src/Models/ExternalTool.cs | 5 ++++ src/Models/TextMateHelper.cs | 47 ++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs index f9660e8346..c963107408 100644 --- a/src/Models/ExternalTool.cs +++ b/src/Models/ExternalTool.cs @@ -110,6 +110,11 @@ public class ExternalToolCustomization public List Excludes { get; set; } = new List(); } + public class CustomFileAssociations + { + [JsonPropertyName("associations")] public Dictionary Associations { get; set; } = new Dictionary(); + } + public class ExternalToolsFinder { public List Tools diff --git a/src/Models/TextMateHelper.cs b/src/Models/TextMateHelper.cs index bdddeb1b54..13abbadf46 100644 --- a/src/Models/TextMateHelper.cs +++ b/src/Models/TextMateHelper.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.IO; - +using System.Text.Json; using Avalonia; using Avalonia.Platform; using Avalonia.Styling; @@ -39,12 +39,45 @@ public static class GrammarUtility public static string GetScope(string file, RegistryOptions reg) { var extension = Path.GetExtension(file); - if (extension == ".h") - extension = ".cpp"; - else if (extension is ".resx" or ".plist" or ".manifest" or ".sln" or ".slnx") - extension = ".xml"; - else if (extension == ".command") - extension = ".sh"; + + switch (extension) + { + case ".h": + extension = ".cpp"; + break; + case ".resx" or ".plist" or ".manifest" or ".sln" or ".slnx": + extension = ".xml"; + break; + case ".command": + extension = ".sh"; + break; + default: + + if (!string.IsNullOrEmpty(extension)) + { + var customFileAssociations = Path.Combine(Native.OS.BasicDirectories.ConfigDir, "custom_file_associations.json"); + + try + { + if (File.Exists(customFileAssociations)) + { + using var stream = File.OpenRead(customFileAssociations); + var fileAssociations = JsonSerializer.Deserialize(stream) ?? new CustomFileAssociations(); + + if (fileAssociations.Associations.TryGetValue(file, out var ext)) + { + extension = ext; + } + } + } + catch + { + // Ignore + } + } + + break; + } foreach (var grammar in s_extraGrammars) {