From e10b9254ed6211ba8a8fdcc1047d9fe25724e7c4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 16 Sep 2025 16:31:06 +0800 Subject: [PATCH] Add workaround for log & ln function --- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 4 +- .../Flow.Launcher.Plugin.Calculator/Main.cs | 63 +++++++++++++++++-- .../MainRegexHelper.cs | 6 ++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs index 3f403b24e..146552323 100644 --- a/Flow.Launcher.Test/Plugins/CalculatorTest.cs +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -53,10 +53,12 @@ namespace Flow.Launcher.Test.Plugins [TestCase(@"min(1,-1,-2)", "-2")] [TestCase(@"max(1,-1,-2)", "1")] [TestCase(@"sqrt(16)", "4")] - [TestCase(@"sin(pi)", "0")] + [TestCase(@"sin(pi)", "0.0000000000")] [TestCase(@"cos(0)", "1")] [TestCase(@"tan(0)", "0")] + [TestCase(@"log10(100)", "2")] [TestCase(@"log(100)", "2")] + [TestCase(@"log2(8)", "3")] [TestCase(@"ln(e)", "1")] [TestCase(@"abs(-5)", "5")] // Constants diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index 42cbafb43..9d5e4700f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -16,6 +16,8 @@ namespace Flow.Launcher.Plugin.Calculator private static readonly Regex ThousandGroupRegex = MainRegexHelper.GetThousandGroupRegex(); private static readonly Regex NumberRegex = MainRegexHelper.GetNumberRegex(); private static readonly Regex PowRegex = MainRegexHelper.GetPowRegex(); + private static readonly Regex LogRegex = MainRegexHelper.GetLogRegex(); + private static readonly Regex LnRegex = MainRegexHelper.GetLnRegex(); private static readonly Regex FunctionRegex = MainRegexHelper.GetFunctionRegex(); private static Engine MagesEngine; @@ -67,12 +69,36 @@ namespace Flow.Launcher.Plugin.Calculator // https://github.com/FlorianRappl/Mages/issues/132 // We bypass it by rewriting any pow(x,y) expression to the equivalent (x^y) expression // before the engine sees it. This loop handles nested calls. - string previous; - do { - previous = expression; - expression = PowRegex.Replace(previous, PowMatchEvaluator); - } while (previous != expression); + string previous; + do + { + previous = expression; + expression = PowRegex.Replace(previous, PowMatchEvaluator); + } while (previous != expression); + } + // WORKAROUND END + + // WORKAROUND START: The 'log' & 'ln' function in Mages v3.0.0 are broken. + // https://github.com/FlorianRappl/Mages/issues/137 + // We bypass it by rewriting any log & ln expression to the equivalent (log10 & log) expression + // before the engine sees it. This loop handles nested calls. + { + string previous; + do + { + previous = expression; + expression = LogRegex.Replace(previous, LogMatchEvaluator); + } while (previous != expression); + } + { + string previous; + do + { + previous = expression; + expression = LnRegex.Replace(previous, LnMatchEvaluator); + } while (previous != expression); + } // WORKAROUND END var result = MagesEngine.Interpret(expression); @@ -200,6 +226,33 @@ namespace Flow.Launcher.Plugin.Calculator return $"({arg1}^{arg2})"; } + private static string LogMatchEvaluator(Match m) + { + // m.Groups[1].Value will be `(...)` with parens + var contentWithParen = m.Groups[1].Value; + var argsContent = contentWithParen[1..^1]; + + // log is unary — if malformed, return original to let Mages handle it + var arg = argsContent.Trim(); + if (string.IsNullOrEmpty(arg)) return m.Value; + + // log(x) -> log10(x) (natural log) + return $"(log10({arg}))"; + } + + private static string LnMatchEvaluator(Match m) + { + // m.Groups[1].Value will be `(...)` with parens + var contentWithParen = m.Groups[1].Value; + var argsContent = contentWithParen[1..^1]; + + // ln is unary — if malformed, return original to let Mages handle it + var arg = argsContent.Trim(); + if (string.IsNullOrEmpty(arg)) return m.Value; + + // ln(x) -> log(x) (natural log) + return $"(log({arg}))"; + } private static string NormalizeNumber(string numberStr, bool isFunctionPresent, string decimalSep, string groupSep) { if (isFunctionPresent) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs b/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs index 0746e4556..a8b582ccc 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs @@ -13,6 +13,12 @@ internal static partial class MainRegexHelper [GeneratedRegex(@"\bpow(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] public static partial Regex GetPowRegex(); + [GeneratedRegex(@"\blog(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetLogRegex(); + + [GeneratedRegex(@"\bln(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetLnRegex(); + [GeneratedRegex(@"\b(sqrt|pow|factorial|abs|sign|ceil|floor|round|exp|log|log2|log10|min|max|lt|eq|gt|sin|cos|tan|arcsin|arccos|arctan|isnan|isint|isprime|isinfty|rand|randi|type|is|as|length|throw|catch|eval|map|clamp|lerp|regex|shuffle)\s*\(", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] public static partial Regex GetFunctionRegex(); }