@@ -16,6 +16,8 @@ public class Main : IPlugin, IPluginI18n, ISettingProvider
1616 private static readonly Regex RegBrackets = MainRegexHelper . GetRegBrackets ( ) ;
1717 private static readonly Regex ThousandGroupRegex = MainRegexHelper . GetThousandGroupRegex ( ) ;
1818 private static readonly Regex NumberRegex = MainRegexHelper . GetNumberRegex ( ) ;
19+ private static readonly Regex PowRegex = new ( @"\bpow(\((?:[^()\[\]]|\((?<Depth>)|\)(?<-Depth>)|\[(?<Depth>)|\](?<-Depth>))*(?(Depth)(?!))\))" , RegexOptions . Compiled | RegexOptions . RightToLeft ) ;
20+
1921
2022 private static Engine MagesEngine ;
2123 private const string Comma = "," ;
@@ -43,11 +45,23 @@ public void Init(PluginInitContext context)
4345
4446 public List < Result > Query ( Query query )
4547 {
46- if ( ! CanCalculate ( query ) )
48+ if ( string . IsNullOrWhiteSpace ( query . Search ) )
4749 {
4850 return new List < Result > ( ) ;
4951 }
5052
53+ if ( ! IsBracketComplete ( query . Search ) )
54+ {
55+ return new List < Result >
56+ {
57+ new Result
58+ {
59+ Title = Localize . flowlauncher_plugin_calculator_expression_not_complete ( ) ,
60+ IcoPath = "Images/calculator.png"
61+ }
62+ } ;
63+ }
64+
5165 try
5266 {
5367 var expression = NumberRegex . Replace ( query . Search , m => NormalizeNumber ( m . Value ) ) ;
@@ -60,7 +74,7 @@ public List<Result> Query(Query query)
6074 do
6175 {
6276 previous = expression ;
63- expression = Regex . Replace ( previous , @"\bpow\s*\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)" , "($1^$2)" ) ;
77+ expression = PowRegex . Replace ( previous , PowMatchEvaluator ) ;
6478 } while ( previous != expression ) ;
6579 // WORKAROUND END
6680
@@ -131,6 +145,57 @@ public List<Result> Query(Query query)
131145 return new List < Result > ( ) ;
132146 }
133147
148+ private static string PowMatchEvaluator ( Match m )
149+ {
150+ // m.Groups[1].Value will be `(...)` with parens
151+ var contentWithParen = m . Groups [ 1 ] . Value ;
152+ // remove outer parens. `(min(2,3), 4)` becomes `min(2,3), 4`
153+ var argsContent = contentWithParen . Substring ( 1 , contentWithParen . Length - 2 ) ;
154+
155+ var bracketCount = 0 ;
156+ var splitIndex = - 1 ;
157+
158+ // Find the top-level comma that separates the two arguments of pow.
159+ for ( var i = 0 ; i < argsContent . Length ; i ++ )
160+ {
161+ switch ( argsContent [ i ] )
162+ {
163+ case '(' :
164+ case '[' :
165+ bracketCount ++ ;
166+ break ;
167+ case ')' :
168+ case ']' :
169+ bracketCount -- ;
170+ break ;
171+ case ',' when bracketCount == 0 :
172+ splitIndex = i ;
173+ break ;
174+ }
175+
176+ if ( splitIndex != - 1 )
177+ break ;
178+ }
179+
180+ if ( splitIndex == - 1 )
181+ {
182+ // This indicates malformed arguments for pow, e.g., pow(5) or pow().
183+ // Return original string to let Mages handle the error.
184+ return m . Value ;
185+ }
186+
187+ var arg1 = argsContent . Substring ( 0 , splitIndex ) . Trim ( ) ;
188+ var arg2 = argsContent . Substring ( splitIndex + 1 ) . Trim ( ) ;
189+
190+ // Check for empty arguments which can happen with stray commas, e.g., pow(,5)
191+ if ( string . IsNullOrEmpty ( arg1 ) || string . IsNullOrEmpty ( arg2 ) )
192+ {
193+ return m . Value ;
194+ }
195+
196+ return $ "({ arg1 } ^{ arg2 } )";
197+ }
198+
134199 /// <summary>
135200 /// Parses a string representation of a number using the system's current culture.
136201 /// </summary>
@@ -208,21 +273,6 @@ private string GetGroupSeparator(string decimalSeparator)
208273 return decimalSeparator == Dot ? Comma : Dot ;
209274 }
210275
211- private bool CanCalculate ( Query query )
212- {
213- if ( string . IsNullOrWhiteSpace ( query . Search ) )
214- {
215- return false ;
216- }
217-
218- if ( ! IsBracketComplete ( query . Search ) )
219- {
220- return false ;
221- }
222-
223- return true ;
224- }
225-
226276 private string GetDecimalSeparator ( )
227277 {
228278 string systemDecimalSeparator = CultureInfo . CurrentCulture . NumberFormat . NumberDecimalSeparator ;
@@ -249,6 +299,11 @@ private static bool IsBracketComplete(string query)
249299 {
250300 leftBracketCount -- ;
251301 }
302+
303+ if ( leftBracketCount < 0 )
304+ {
305+ return false ;
306+ }
252307 }
253308
254309 return leftBracketCount == 0 ;
0 commit comments