@@ -421,18 +421,38 @@ class CommandInput final
421421
422422 message = parseExpressions (message.trim ());
423423
424- auto tokens = StringArray::fromTokens (message, true );
424+ auto argv = StringArray::fromTokens (message, true );
425+
426+ // Wrapped editor->getCurrentCanvas() to make it easier to log null canvas error
427+ auto getCurrentCanvas = [this , pd](bool logError = false ) -> Canvas* {
428+ if (Canvas* cnv = editor->getCurrentCanvas ())
429+ return cnv;
430+
431+ if (logError)
432+ pd->logError (" No canvas open" );
433+
434+ return nullptr ;
435+ };
436+
437+ // Post error if argv has only one arg (argv can change during command execution)
438+ auto isObjectNameProvided = [pd](StringArray& argv) -> bool {
439+ if (argv.size () == 1 ) {
440+ pd->logError (" No object query provided" );
441+ return false ;
442+ }
443+ return true ;
444+ };
425445
426446 // Global or canvas message
427- if (!tokens [0 ].startsWith (" ;" ) && (consoleTargetName == " >" || consoleTargetName == " lua >" || tokens [0 ] == " >" || tokens [0 ] == " deselect" || tokens [0 ] == " clear" ))
447+ if (!argv [0 ].startsWith (" ;" ) && (consoleTargetName == " >" || consoleTargetName == " lua >" || argv [0 ] == " >" || argv [0 ] == " deselect" || argv [0 ] == " clear" ))
428448 {
429- auto selector = hash (tokens [0 ]);
449+ auto selector = hash (argv [0 ]);
430450 switch (selector) {
431451 case hash (" sel" ):
432452 case hash (" select" ): {
433- if (auto * cnv = editor-> getCurrentCanvas () ) {
434- if (tokens [1 ].containsOnly (" 0123456789" )) {
435- int index = tokens [1 ].getIntValue ();
453+ if (auto * cnv = getCurrentCanvas (true ); isObjectNameProvided (argv) && cnv ) {
454+ if (argv [1 ].containsOnly (" 0123456789" )) {
455+ int index = argv [1 ].getIntValue ();
436456 if (index >= 0 && index < cnv->objects .size ()) {
437457 // move the window if it needs to be moved
438458 editor->highlightSearchTarget (cnv->objects [index]->getPointer (), true );
@@ -441,22 +461,22 @@ class CommandInput final
441461 result.add ({1 , " Object index out of bounds" });
442462 }
443463 } else {
444- auto objects = findObjects (cnv, tokens [1 ]);
445- for (auto * object : objects) {
464+ auto objects = findObjects (cnv, argv [1 ]);
465+ for (auto * object: objects) {
446466 cnv->setSelected (object, true );
447467 cnv->updateSidebarSelection ();
448468 }
449- if (objects.empty ()) pd->logError (" No object found for: " + tokens [1 ]);
469+ if (objects.empty ()) pd->logError (" No object found for: " + argv [1 ]);
450470 // TODO: fix highlighting!
451471 // if(objects.size()) editor->highlightSearchTarget(objects[0]->getPointer(), true);
452472 }
473+ updateCommandInputTarget ();
453474 }
454- updateCommandInputTarget ();
455475 break ;
456476 }
457477 case hash (" >" ):
458478 case hash (" deselect" ): {
459- if (auto * cnv = editor-> getCurrentCanvas ()) {
479+ if (auto * cnv = getCurrentCanvas (true )) {
460480 cnv->deselectAll ();
461481 cnv->updateSidebarSelection ();
462482 }
@@ -465,7 +485,7 @@ class CommandInput final
465485 }
466486 case hash (" ls" ):
467487 case hash (" list" ): {
468- if (auto * cnv = editor-> getCurrentCanvas ()) {
488+ if (auto * cnv = getCurrentCanvas (true )) {
469489 auto names = getUniqueObjectNames (cnv);
470490 for (auto & [name, object] : names) {
471491 if (allGuis.contains (object->gui ->getType ())) {
@@ -479,10 +499,10 @@ class CommandInput final
479499 }
480500 case hash (" find" ):
481501 case hash (" search" ): {
482- if (auto * cnv = editor-> getCurrentCanvas () ) {
502+ if (auto * cnv = getCurrentCanvas (true ); isObjectNameProvided (argv) && cnv ) {
483503 auto names = getUniqueObjectNames (cnv);
484504 for (auto & [name, object] : names) {
485- auto query = tokens [1 ];
505+ auto query = argv [1 ];
486506 query = query.trimCharactersAtEnd (" *" ); // No need for wildcards here
487507 auto text = object->gui ->getText ();
488508 if (text.contains (query) || name.contains (query)) {
@@ -494,7 +514,6 @@ class CommandInput final
494514 }
495515 }
496516 }
497-
498517 break ;
499518 }
500519 case hash (" reset" ): {
@@ -506,7 +525,7 @@ class CommandInput final
506525 case hash (" clear" ): {
507526 commandHistory.clear ();
508527 editor->sidebar ->clearConsole ();
509- if (auto * cnv = editor-> getCurrentCanvas ()) {
528+ if (auto * cnv = getCurrentCanvas ()) {
510529 cnv->deselectAll ();
511530 cnv->updateSidebarSelection ();
512531 }
@@ -516,34 +535,31 @@ class CommandInput final
516535 case hash (" cnv" ):
517536 case hash (" canvas" ):
518537 {
519- if (auto * cnv = editor-> getCurrentCanvas ())
538+ if (auto * cnv = getCurrentCanvas (true ))
520539 {
521540 auto patchPtr = cnv->patch .getPointer ();
522- if (patchPtr && tokens .size () == 1 && tokens [1 ].containsOnly (" 0123456789-e." )) {
523- pd->sendDirectMessage (patchPtr.get (), tokens [1 ].getFloatValue ());
524- } else if (patchPtr && tokens .size () == 1 ) {
525- pd->sendDirectMessage (patchPtr.get (), tokens [1 ], {});
541+ if (patchPtr && argv .size () == 1 && argv [1 ].containsOnly (" 0123456789-e." )) {
542+ pd->sendDirectMessage (patchPtr.get (), argv [1 ].getFloatValue ());
543+ } else if (patchPtr && argv .size () == 1 ) {
544+ pd->sendDirectMessage (patchPtr.get (), argv [1 ], {});
526545 } else if (patchPtr) {
527546 SmallArray<pd::Atom> atoms;
528- for (int i = 2 ; i < tokens .size (); i++) {
529- if (tokens [i].containsOnly (" 0123456789-e." )) {
530- atoms.add (pd::Atom (tokens [i].getFloatValue ()));
547+ for (int i = 2 ; i < argv .size (); i++) {
548+ if (argv [i].containsOnly (" 0123456789-e." )) {
549+ atoms.add (pd::Atom (argv [i].getFloatValue ()));
531550 } else {
532- atoms.add (pd::Atom (pd->generateSymbol (tokens [i])));
551+ atoms.add (pd::Atom (pd->generateSymbol (argv [i])));
533552 }
534553 }
535- pd->sendDirectMessage (patchPtr.get (), tokens [1 ], std::move (atoms));
554+ pd->sendDirectMessage (patchPtr.get (), argv [1 ], std::move (atoms));
536555 }
537556 cnv->patch .deselectAll ();
538557 }
539- else {
540- pd->logError (" No canvas open" );
541- }
542558 }
543559 case hash (" script" ):
544560 {
545- auto script = pd::Library::findFile (tokens [1 ] + " .lua" );
546- if (script.existsAsFile ()) {
561+ auto script = pd::Library::findFile (argv [1 ] + " .lua" );
562+ if (script.existsAsFile ()) {
547563 lua->executeScript (script.getFullPathName ());
548564 }
549565 else {
@@ -553,52 +569,52 @@ class CommandInput final
553569 }
554570 case hash (" man" ):
555571 {
556- switch (hash (tokens [1 ]))
572+ switch (hash (argv [1 ]))
557573 {
558574 case hash (" man" ):
559575 pd->logMessage (" Prints manual for command. Usage: man <command>" );
560576 break ;
561577
562578 case hash (" ?" ):
563579 case hash (" help" ):
564- pd->logMessage (tokens [2 ] + " : Show help" );
580+ pd->logMessage (argv [2 ] + " : Show help" );
565581 break ;
566582
567583 case hash (" script" ):
568- pd->logMessage (tokens [2 ] + " : Excute a Lua script from your search path. Usage: script <filename>" );
584+ pd->logMessage (argv [2 ] + " : Excute a Lua script from your search path. Usage: script <filename>" );
569585 break ;
570586
571587 case hash (" cnv" ):
572588 case hash (" canvas" ):
573- pd->logMessage (tokens [2 ] + " : Send a message to current canvas. Usage: " + tokens [2 ] + " <message>" );
589+ pd->logMessage (argv [2 ] + " : Send a message to current canvas. Usage: " + argv [2 ] + " <message>" );
574590 break ;
575591
576592 case hash (" clear" ):
577- pd->logMessage (tokens [2 ] + " : Clear console and command history" );
593+ pd->logMessage (argv [2 ] + " : Clear console and command history" );
578594 break ;
579595
580596 case hash (" reset" ):
581- pd->logMessage (tokens [2 ] + " : Reset Lua interpreter state" );
597+ pd->logMessage (argv [2 ] + " : Reset Lua interpreter state" );
582598 break ;
583599
584600 case hash (" sel" ):
585601 case hash (" select" ):
586- pd->logMessage (tokens [2 ] + " : Select an object by ID or index. After selecting objects, you can send messages to them. Usage: " + tokens [2 ] + " <id> or " + tokens [2 ] + " <index>" );
602+ pd->logMessage (argv [2 ] + " : Select an object by ID or index. After selecting objects, you can send messages to them. Usage: " + argv [2 ] + " <id> or " + argv [2 ] + " <index>" );
587603 break ;
588604
589605 case hash (" >" ):
590606 case hash (" deselect" ):
591- pd->logMessage (tokens [2 ] + " : Deselects all on current canvas" );
607+ pd->logMessage (argv [2 ] + " : Deselects all on current canvas" );
592608 break ;
593609
594610 case hash (" ls" ):
595611 case hash (" list" ):
596- pd->logMessage (tokens [2 ] + " : Print a list of all object IDs on current canvas" );
612+ pd->logMessage (argv [2 ] + " : Print a list of all object IDs on current canvas" );
597613 break ;
598614
599615 case hash (" find" ):
600616 case hash (" search" ):
601- pd->logMessage (tokens [2 ] + " : Search object IDs on current canvas. Usage: " + tokens [2 ] + " <id>." );
617+ pd->logMessage (argv [2 ] + " : Search object IDs on current canvas. Usage: " + argv [2 ] + " <id>." );
602618 break ;
603619 }
604620 }
@@ -610,92 +626,86 @@ class CommandInput final
610626 }
611627 default : {
612628 // Match a "name > message" pattern
613- if (tokens .size () >= 2 && tokens [1 ] == " >" )
629+ if (argv .size () >= 2 && argv [1 ] == " >" )
614630 {
615- auto target = tokens [0 ];
616- if (tokens .size () == 2 )
631+ auto target = argv [0 ];
632+ if (argv .size () == 2 )
617633 {
618- if (auto * cnv = editor-> getCurrentCanvas ()) {
634+ if (auto * cnv = getCurrentCanvas (true )) {
619635 auto objects = findObjects (cnv, target);
620636 for (auto * object : objects) {
621637 cnv->setSelected (object, true );
622638 cnv->updateSidebarSelection ();
623639 }
624- if (objects.empty ()) pd->logError (" No object found for: " + tokens[1 ]);
625-
640+ if (objects.empty ()) pd->logError (" No object found for: " + argv[1 ]);
626641 }
627642 break ;
628643 }
629-
630- tokens.removeRange (0 , 2 );
631644
632- if (auto * cnv = editor->getCurrentCanvas ()) {
645+ argv.removeRange (0 , 2 );
646+
647+ if (auto * cnv = getCurrentCanvas (true )) {
633648 auto objects = findObjects (cnv, target);
634- for (auto * object : objects) {
635- if (auto * cnv = editor->getCurrentCanvas ())
636- {
637- auto objPtr = object->getPointer ();
638- if (objPtr && tokens.size () == 1 && tokens[0 ].containsOnly (" 0123456789-e." )) {
639- pd->sendDirectMessage (objPtr, tokens[0 ].getFloatValue ());
640- } else if (objPtr && tokens.size () == 1 ) {
641- pd->sendDirectMessage (objPtr, tokens[0 ], {});
642- } else if (objPtr) {
643- SmallArray<pd::Atom> atoms;
644- for (int i = 1 ; i < tokens.size (); i++) {
645- if (tokens[i].containsOnly (" 0123456789-e." )) {
646- atoms.add (pd::Atom (tokens[i].getFloatValue ()));
647- } else {
648- atoms.add (pd::Atom (pd->generateSymbol (tokens[i])));
649- }
649+ for (auto * object: objects) {
650+ auto objPtr = object->getPointer ();
651+ if (objPtr && argv.size () && argv[0 ].containsOnly (" 0123456789-e." )) {
652+ pd->sendDirectMessage (objPtr, argv[0 ].getFloatValue ());
653+ } else if (objPtr && argv.size ()) {
654+ pd->sendDirectMessage (objPtr, argv[0 ], {});
655+ } else if (objPtr) {
656+ SmallArray<pd::Atom> atoms;
657+ for (int i = 1 ; i < argv.size (); i++) {
658+ if (argv[i].containsOnly (" 0123456789-e." )) {
659+ atoms.add (pd::Atom (argv[i].getFloatValue ()));
660+ } else {
661+ atoms.add (pd::Atom (pd->generateSymbol (argv[i])));
650662 }
651- pd->sendDirectMessage (objPtr, tokens[0 ], std::move (atoms));
652663 }
664+ pd->sendDirectMessage (objPtr, argv[0 ], std::move (atoms));
653665 }
654666 }
655- if (objects.empty ()) pd->logError (" No object found for: " + tokens [1 ]);
667+ if (objects.empty ()) pd->logError (" No object found for: " + argv [1 ]);
656668 }
657669 }
658670
659- if (!tokens .size ()) break ;
660- tokens .getReference (0 ) = tokens [0 ].trimCharactersAtStart (" ;" );
671+ if (!argv .size ()) break ;
672+ argv .getReference (0 ) = argv [0 ].trimCharactersAtStart (" ;" );
661673 SmallArray<pd::Atom> atoms;
662- for (int i = 2 ; i < tokens .size (); i++) {
663- if (tokens [i].containsOnly (" 0123456789-e." )) {
664- atoms.add (pd::Atom (tokens [i].getFloatValue ()));
674+ for (int i = 2 ; i < argv .size (); i++) {
675+ if (argv [i].containsOnly (" 0123456789-e." )) {
676+ atoms.add (pd::Atom (argv [i].getFloatValue ()));
665677 } else {
666- atoms.add (pd::Atom (pd->generateSymbol (tokens [i])));
678+ atoms.add (pd::Atom (pd->generateSymbol (argv [i])));
667679 }
668680 }
669681 pd->lockAudioThread ();
670- pd->sendMessage (tokens [0 ].toRawUTF8 (), tokens[1 ].toRawUTF8 (), std::move (atoms));
682+ pd->sendMessage (argv [0 ].toRawUTF8 (), tokens[1 ].toRawUTF8 (), std::move (atoms));
671683 pd->unlockAudioThread ();
672684 break ;
673685 }
674686 }
675687 } else { // object message
676- if (auto * cnv = editor-> getCurrentCanvas ()) {
688+ if (auto * cnv = getCurrentCanvas (true )) {
677689 for (auto * obj : cnv->getSelectionOfType <Object>()) {
678- if (tokens .size () == 1 && tokens [0 ].containsOnly (" 0123456789-e." )) {
679- pd->sendDirectMessage (obj->getPointer (), tokens [0 ].getFloatValue ());
680- } else if (tokens .size () == 1 ) {
681- pd->sendDirectMessage (obj->getPointer (), tokens [0 ], {});
690+ if (argv .size () == 1 && argv [0 ].containsOnly (" 0123456789-e." )) {
691+ pd->sendDirectMessage (obj->getPointer (), argv [0 ].getFloatValue ());
692+ } else if (argv .size () == 1 ) {
693+ pd->sendDirectMessage (obj->getPointer (), argv [0 ], {});
682694 } else {
683695 SmallArray<pd::Atom> atoms;
684- for (int i = 1 ; i < tokens .size (); i++) {
685- if (tokens [i].containsOnly (" 0123456789-e." )) {
686- atoms.add (pd::Atom (tokens [i].getFloatValue ()));
696+ for (int i = 1 ; i < argv .size (); i++) {
697+ if (argv [i].containsOnly (" 0123456789-e." )) {
698+ atoms.add (pd::Atom (argv [i].getFloatValue ()));
687699 } else {
688- atoms.add (pd::Atom (pd->generateSymbol (tokens [i])));
700+ atoms.add (pd::Atom (pd->generateSymbol (argv [i])));
689701 }
690702 }
691- pd->sendDirectMessage (obj->getPointer (), tokens [0 ], std::move (atoms));
703+ pd->sendDirectMessage (obj->getPointer (), argv [0 ], std::move (atoms));
692704 }
693-
694705 }
695706 }
696707 }
697-
698- return result;
708+ return result;
699709 }
700710
701711 ~CommandInput () override
0 commit comments