From c83a29fb1824e0f4d11a662bdee62c3b057ab1c1 Mon Sep 17 00:00:00 2001 From: dcog989 Date: Wed, 23 Jul 2025 01:18:26 +0100 Subject: [PATCH] PR review changes --- .../Flow.Launcher.Plugin.Calculator/Main.cs | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index 2787adbbc..2894c2159 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -25,6 +25,8 @@ namespace Flow.Launcher.Plugin.Calculator @")+$", RegexOptions.Compiled); private static readonly Regex RegBrackets = new Regex(@"[\(\)\[\]]", RegexOptions.Compiled); private static readonly Regex ThousandGroupRegex = new Regex(@"\B(?=(\d{3})+(?!\d))"); + private static readonly Regex NumberRegex = new Regex(@"[\d\.,]+", RegexOptions.Compiled); + private static Engine MagesEngine; private const string comma = ","; private const string dot = "."; @@ -34,8 +36,15 @@ namespace Flow.Launcher.Plugin.Calculator private static Settings _settings; private static SettingsViewModel _viewModel; - private string _inputDecimalSeparator; - private bool _inputUsesGroupSeparators; + /// + /// Holds the formatting information for a single query. + /// This is used to ensure thread safety by keeping query state local. + /// + private class ParsingContext + { + public string InputDecimalSeparator { get; set; } + public bool InputUsesGroupSeparators { get; set; } + } public void Init(PluginInitContext context) { @@ -59,13 +68,11 @@ namespace Flow.Launcher.Plugin.Calculator return new List(); } - _inputDecimalSeparator = null; - _inputUsesGroupSeparators = false; + var context = new ParsingContext(); try { - var numberRegex = new Regex(@"[\d\.,]+"); - var expression = numberRegex.Replace(query.Search, m => NormalizeNumber(m.Value)); + var expression = NumberRegex.Replace(query.Search, m => NormalizeNumber(m.Value, context)); var result = MagesEngine.Interpret(expression); @@ -78,7 +85,7 @@ namespace Flow.Launcher.Plugin.Calculator if (!string.IsNullOrEmpty(result?.ToString())) { decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero); - string newResult = FormatResult(roundedResult); + string newResult = FormatResult(roundedResult, context); return new List { @@ -117,10 +124,10 @@ namespace Flow.Launcher.Plugin.Calculator /// /// Parses a string representation of a number, detecting its format. It uses structural analysis /// (checking for 3-digit groups) and falls back to system culture for ambiguous cases (e.g., "1,234"). - /// It sets instance fields to remember the user's format for later output formatting. + /// It populates the provided ParsingContext with the detected format for later use. /// /// A normalized number string with '.' as the decimal separator for the Mages engine. - private string NormalizeNumber(string numberStr) + private string NormalizeNumber(string numberStr, ParsingContext context) { var systemFormat = CultureInfo.CurrentCulture.NumberFormat; string systemDecimalSeparator = systemFormat.NumberDecimalSeparator; @@ -131,18 +138,18 @@ namespace Flow.Launcher.Plugin.Calculator // Unambiguous case: both separators are present. The last one wins as decimal separator. if (hasDot && hasComma) { - _inputUsesGroupSeparators = true; + context.InputUsesGroupSeparators = true; int lastDotPos = numberStr.LastIndexOf(dot); int lastCommaPos = numberStr.LastIndexOf(comma); if (lastDotPos > lastCommaPos) // e.g. 1,234.56 { - _inputDecimalSeparator = dot; + context.InputDecimalSeparator = dot; return numberStr.Replace(comma, string.Empty); } else // e.g. 1.234,56 { - _inputDecimalSeparator = comma; + context.InputDecimalSeparator = comma; return numberStr.Replace(dot, string.Empty).Replace(comma, dot); } } @@ -158,19 +165,19 @@ namespace Flow.Launcher.Plugin.Calculator // Ambiguous case: "1,234". Resolve using culture. if (systemDecimalSeparator == comma) { - _inputDecimalSeparator = comma; + context.InputDecimalSeparator = comma; return numberStr.Replace(comma, dot); } else { - _inputUsesGroupSeparators = true; + context.InputUsesGroupSeparators = true; return numberStr.Replace(comma, string.Empty); } } else { // Unambiguous decimal: "123,45" or "1,2,345" - _inputDecimalSeparator = comma; + context.InputDecimalSeparator = comma; return numberStr.Replace(comma, dot); } } @@ -184,18 +191,18 @@ namespace Flow.Launcher.Plugin.Calculator { if (systemDecimalSeparator == dot) { - _inputDecimalSeparator = dot; + context.InputDecimalSeparator = dot; return numberStr; } else { - _inputUsesGroupSeparators = true; + context.InputUsesGroupSeparators = true; return numberStr.Replace(dot, string.Empty); } } else { - _inputDecimalSeparator = dot; + context.InputDecimalSeparator = dot; return numberStr; // Already in Mages-compatible format } } @@ -204,10 +211,10 @@ namespace Flow.Launcher.Plugin.Calculator return numberStr; } - private string FormatResult(decimal roundedResult) + private string FormatResult(decimal roundedResult, ParsingContext context) { // Use the detected decimal separator from the input; otherwise, fall back to settings. - string decimalSeparator = _inputDecimalSeparator ?? GetDecimalSeparator(); + string decimalSeparator = context.InputDecimalSeparator ?? GetDecimalSeparator(); string groupSeparator = decimalSeparator == dot ? comma : dot; string resultStr = roundedResult.ToString(CultureInfo.InvariantCulture); @@ -216,7 +223,7 @@ namespace Flow.Launcher.Plugin.Calculator string integerPart = parts[0]; string fractionalPart = parts.Length > 1 ? parts[1] : string.Empty; - if (_inputUsesGroupSeparators) + if (context.InputUsesGroupSeparators) { integerPart = ThousandGroupRegex.Replace(integerPart, groupSeparator); }