@@ -62,18 +62,10 @@ class LuaExpressionParser {
6262 }
6363
6464 // Function to execute an expression and return result as LuaResult (either double or string)
65- LuaResult executeExpression (String const & expression)
65+ LuaResult executeExpression (String const & expression, bool hasReturnValue )
6666 {
67- UnorderedSet<String> luaKeywords = {" if" , " for" , " while" , " function" , " local" };
68-
69- auto trimmedExpression = expression.trim ();
70- auto firstWord = trimmedExpression.upToFirstOccurrenceOf (" " , false , false );
71-
72- // Determine if the expression is a block by checking the first word
73- bool isBlock = luaKeywords.contains (firstWord) || trimmedExpression.containsChar (' =' ) || trimmedExpression.containsChar (' \n ' ) || trimmedExpression.contains (" end" );
74-
7567 String luaCode = " local __eval = function()" ;
76- if (!isBlock ) luaCode += " \n return " ;
68+ if (hasReturnValue ) luaCode += " \n return " ;
7769 luaCode += expression.trim (); // Append the expression without altering it
7870 luaCode += R"(
7971 end
@@ -380,6 +372,9 @@ class CommandInput final
380372 {
381373 String parsedMessage;
382374 int startPos = 0 ;
375+
376+ // if the lua expression is not at the start of the message, we expect a return value
377+ auto hasReturnValue = !message.startsWith (" {" );
383378
384379 while (startPos < message.length ()) {
385380 auto openBrace = message.indexOf (startPos, " {" );
@@ -400,7 +395,7 @@ class CommandInput final
400395
401396 lua->setCommandProcessor (this );
402397 String luaExpression = message.substring (openBrace + 1 , closeBrace);
403- auto result = lua->executeExpression (luaExpression);
398+ auto result = lua->executeExpression (luaExpression, hasReturnValue );
404399
405400 if (auto doubleResult = std::get_if<double >(&result)) {
406401 parsedMessage += String (*doubleResult);
@@ -418,7 +413,7 @@ class CommandInput final
418413 {
419414 SmallArray<std::pair<int , String>> result;
420415
421- message = parseExpressions (message);
416+ message = parseExpressions (message. trim () );
422417
423418 auto tokens = StringArray::fromTokens (message, true );
424419
@@ -538,6 +533,48 @@ class CommandInput final
538533 break ;
539534 }
540535 default : {
536+ // Match a "name > message" pattern
537+ if (tokens.size () >= 2 && tokens[1 ] == " >" )
538+ {
539+ auto target = tokens[0 ];
540+ if (tokens.size () == 2 )
541+ {
542+ if (auto * cnv = editor->getCurrentCanvas ()) {
543+ for (auto * object : findObjects (cnv, target)) {
544+ cnv->setSelected (object, true );
545+ cnv->updateSidebarSelection ();
546+ }
547+ }
548+ break ;
549+ }
550+
551+ tokens.removeRange (0 , 2 );
552+
553+ if (auto * cnv = editor->getCurrentCanvas ()) {
554+ for (auto * object : findObjects (cnv, target)) {
555+ if (auto * cnv = editor->getCurrentCanvas ())
556+ {
557+ auto objPtr = object->getPointer ();
558+ if (objPtr && tokens.size () == 1 && tokens[0 ].containsOnly (" 0123456789-e." )) {
559+ pd->sendDirectMessage (objPtr, tokens[0 ].getFloatValue ());
560+ } else if (objPtr && tokens.size () == 1 ) {
561+ pd->sendDirectMessage (objPtr, tokens[0 ], {});
562+ } else if (objPtr) {
563+ SmallArray<pd::Atom> atoms;
564+ for (int i = 1 ; i < tokens.size (); i++) {
565+ if (tokens[i].containsOnly (" 0123456789-e." )) {
566+ atoms.add (pd::Atom (tokens[i].getFloatValue ()));
567+ } else {
568+ atoms.add (pd::Atom (pd->generateSymbol (tokens[i])));
569+ }
570+ }
571+ pd->sendDirectMessage (objPtr, tokens[0 ], std::move (atoms));
572+ }
573+ }
574+ }
575+ }
576+ }
577+
541578 if (!tokens.size ()) break ;
542579 tokens.getReference (0 ) = tokens[0 ].trimCharactersAtStart (" ;" );
543580 SmallArray<pd::Atom> atoms;
0 commit comments