Tapatalk

Is there a way to convert specific keywords to code snippets?

Is there a way to convert specific keywords to code snippets?

31
NewbieNewbie
31

    Jan 16, 2020#1

    Hey guys,

    I'm writing a lot of Kontakt Script Processor code and was thinking about a way to make my job easier. Here's an example of what I have in mind:
    To create a button on the UI, resize it and reposition it in KSP, you would write something like this:

    Code: Select all

    declare ui_switch $Switch
    $TempID := get_ui_id($Switch)
    set_control_par($TempID,$CONTROL_PAR_POS_X,200)
    set_control_par($TempID,$CONTROL_PAR_POS_Y,100)
    set_control_par($TempID,$CONTROL_PAR_WIDTH,80)
    set_control_par($TempID,$CONTROL_PAR_HEIGHT,20)
    
    Now, wouldn't it be much easier to just write something like this ...

    Code: Select all

    create switch $Switch(200,100,80,20)
    ... and let UltraEdit convert that to the code that I mentioned above?

    Basically something like the template feature, but it needs to happen on the push of a button and the text needs to be written to a new file. So I would have my file "Script.txt" open in UltraEdit, execute the mentioned functionality and then UltraEdit would create or overwrite a new file in the same directory called "Script_final.txt", copy each line of code from the first file to the second one but if it should stumble upon something like "create switch", it would replace that line with something else.

    If this something that could be achieved with UE's scripting feature or is there any other function in UE that's better suited for the job?

    What I want is that the inserted code goes into a new file. So that file A (the one that I'm working with) looks like this:

    Code: Select all

    create switch $Switch1(200,100,80,20)
    create switch $Switch2(200,100,80,20)
    create switch $Switch3(200,100,80,20)
    
    and file B that is interpreted by KSP will look like this:

    Code: Select all

    declare ui_switch $Switch1
    $TempID := get_ui_id($Switch1)
    set_control_par($TempID,$CONTROL_PAR_POS_X,200)
    set_control_par($TempID,$CONTROL_PAR_POS_Y,100)
    set_control_par($TempID,$CONTROL_PAR_WIDTH,80)
    set_control_par($TempID,$CONTROL_PAR_HEIGHT,20)
    declare ui_switch $Switch2
    $TempID := get_ui_id($Switch2)
    set_control_par($TempID,$CONTROL_PAR_POS_X,200)
    set_control_par($TempID,$CONTROL_PAR_POS_Y,100)
    set_control_par($TempID,$CONTROL_PAR_WIDTH,80)
    set_control_par($TempID,$CONTROL_PAR_HEIGHT,20)
    declare ui_switch $Switch3
    $TempID := get_ui_id($Switch3)
    set_control_par($TempID,$CONTROL_PAR_POS_X,200)
    set_control_par($TempID,$CONTROL_PAR_POS_Y,100)
    set_control_par($TempID,$CONTROL_PAR_WIDTH,80)
    set_control_par($TempID,$CONTROL_PAR_HEIGHT,20)
    
    Any help is highly appreciated. Thanks in advance.

    Best,
    Glaciac

    6,685587
    Grand MasterGrand Master
    6,685587

      Jan 17, 2020#2

      Yes, this task can be done with a macro or a script which can be executed with all the methods which exist nowadays to run a script or macro.

      Here is a script solution on which the active file can contain also other lines and spaces/tabs can exist between most elements.

      Code: Select all

      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         // Define environment for this script.
         UltraEdit.insertMode();
         if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
         else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
         var nLine = UltraEdit.activeDocument.currentLineNum;
         var nColumn = UltraEdit.activeDocument.currentColumnNum;
      
         UltraEdit.activeDocument.selectAll();  // Select everything in active file.
         if (UltraEdit.activeDocument.isSel())  // Is the file not empty?
         {
            // Get all strings matching this case-sensitive regular
            // expression search string into an array of string.
            var asCreateSwitches = UltraEdit.activeDocument.selection.match(/create[\t ]+switch[\t ]+\$\w+\(\d+[\t ,]+\d+[\t ,]+\d+[\t ,]+\d+[\t ,]*\)/g);
            // Cancel the selection and set caret back to initial position.
            UltraEdit.activeDocument.gotoLine(nLine,nColumn);
      
            if (asCreateSwitches)   // Was any search string found in file at all.
            {
               var asSwitchBlocks = [];
               // Convert each found string into the appropriate block.
               for (var nSwitch = 0; nSwitch < asCreateSwitches.length; nSwitch++)
               {
                  var sSwitchBlock = asCreateSwitches[nSwitch].replace(/^create[\t ]+switch[\t ]+(\$\w+)\((\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]*\)$/,
                                      "declare ui_switch $1\r\n\$TempID := get_ui_id($1)\r\nset_control_par(\$TempID,\$CONTROL_PAR_POS_X,$2)\r\nset_control_par(\$TempID,\$CONTROL_PAR_POS_Y,$3)\r\nset_control_par(\$TempID,\$CONTROL_PAR_WIDTH,$4)\r\nset_control_par(\$TempID,\$CONTROL_PAR_HEIGHT,$5)\r\n");
                  asSwitchBlocks.push(sSwitchBlock);
               }
               // Create a new file with DOS line terminators and write
               // all blocks joined to a single string into this file.
               UltraEdit.newFile();
               UltraEdit.activeDocument.unixMacToDos();
               UltraEdit.activeDocument.write(asSwitchBlocks.join(""));
            }
         }
      }
      
      A macro selecting everything in active file, copying to a user clipboard, creating a new file, pasting the copied block, moving caret to top and running one Perl regular expression replace all could be also used for this task.

      I would suggest as Perl regular expression search string:

      Code: Select all

      ^[\t ]*create[\t ]+switch[\t ]+(\$\w+)\((\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]*\)[\t ]*(\r?\n)
      The appropriate Perl regular expression replace string would be:

      Code: Select all

      declare ui_switch \1\6\$TempID := get_ui_id(\1)\6set_control_par(\$TempID,\$CONTROL_PAR_POS_X,\2)\6set_control_par(\$TempID,\$CONTROL_PAR_POS_Y,\3)\6set_control_par(\$TempID,\$CONTROL_PAR_WIDTH,\4)\6set_control_par(\$TempID,\$CONTROL_PAR_HEIGHT,\5)\6
      A macro containing just this Perl regular expression Find and Replace All commands could be run also on active file to convert the lines with the create switch instructions to the appropriate code blocks.
      Best regards from an UC/UE/UES for Windows user from Austria

      31
      NewbieNewbie
      31

        Jan 17, 2020#3

        Wow, that's a lot of information. Thanks a lot for investing so much time into it, Mofi! I will go through everything carefully (I don't know anything about regular expressions so it will take me a while to study them) and then come back to you.
        Again, thanks a lot for your help!
        Best,
        Glaciac

        6,685587
        Grand MasterGrand Master
        6,685587

          Jan 18, 2020#4

          I read once more your initial post and wrote this commented script which copies entire active file into a new file and replaces directly in clipboard already each create switch instruction by the appropriate block before pasting the modified file content into a new file saved with input file name with _final inserted left to the file extension. The indentations on each create switch instruction is taken over as indentation on the lines of the appropriate code block.

          Code: Select all

          if (UltraEdit.document.length > 0)  // Is any file opened?
          {
             // Define environment for this script.
             UltraEdit.insertMode();
             if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
             else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
          
             // Get current line and column number in active file.
             var nLine = UltraEdit.activeDocument.currentLineNum;
             var nColumn = UltraEdit.activeDocument.currentColumnNum;
          
             UltraEdit.activeDocument.selectAll();  // Select everything in active file.
             if (UltraEdit.activeDocument.isSel())  // Is the file not empty?
             {
                // Copy everything to user clipboard 9.
                UltraEdit.selectClipboard(9);
                UltraEdit.activeDocument.copy();
          
                // Cancel the selection and set caret back to initial position.
                UltraEdit.activeDocument.gotoLine(nLine,nColumn);
          
                // Get full qualified file name of active file.
                var sFullFileName = UltraEdit.activeDocument.path;
          
                // Create a new file with encoding (ASCII/ANSI) and
                // line termination type (DOS) as set in configuration.
                UltraEdit.newFile();
          
                // Replace all create switch instructions in clipboard
                // by the appropriate block directly in clipboard.
                UltraEdit.clipboardContent = UltraEdit.clipboardContent.replace(/^([\t ]*)create[\t ]+switch[\t ]+(\$\w+)\((\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]*\)/gm,
                                          "$1declare ui_switch $2\r\n$1\$TempID := get_ui_id($2)\r\n$1set_control_par(\$TempID,\$CONTROL_PAR_POS_X,$3)\r\n$1set_control_par(\$TempID,\$CONTROL_PAR_POS_Y,$4)\r\n$1set_control_par(\$TempID,\$CONTROL_PAR_WIDTH,$5)\r\n$1set_control_par(\$TempID,\$CONTROL_PAR_HEIGHT,$6)");
          
                // Paste the modifid file content into the new file.
                UltraEdit.activeDocument.paste();
          
                // Clear user clipboard 9 to free memory and make the
                // operating system clipboard the active clipboard.
                UltraEdit.clearClipboard();
                UltraEdit.selectClipboard(0);
          
                // Move caret to top of the new file.
                UltraEdit.activeDocument.top();
          
                // Has the input file a name at all?
                if (sFullFileName.length)
                {
                   // Insert _final left to file extension of input file name.
                   sFullFileName = sFullFileName.replace(/(\.[^.]*)$/,"_final$1");
                   // Save the new file with that file name.
                   UltraEdit.saveAs(sFullFileName);
                }
          //      else UltraEdit.saveAs("");
             }
          }
          
          The comment script command line UltraEdit.saveAs(""); near end of the script can be uncommented to open the Save as window on which you have to enter the file name for the new file in case of active file on script start is a new, unnamed file.

          The same task can be done also using an UltraEdit macro which was first recorded by me with UltraEdit for Windows v26.20.0.68 and next edited to add the additional conditions and command lines.

          Code: Select all

          InsertMode
          ColumnModeOff
          HexOff
          SelectAll
          IfSel
          PerlReOn
          Clipboard 9
          Copy
          IfNameIs ""
          NewFile
          Paste
          ClearClipboard
          Top
          Find RegExp "^([\t ]*)create[\t ]+switch[\t ]+(\$\w+)\((\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]*\)"
          Replace All "\1declare ui_switch \2\r\n\1\$TempID := get_ui_id(\2)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_POS_X,\3)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_POS_Y,\4)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_WIDTH,\5)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_HEIGHT,\6)\");"
          Else
          Clipboard 8
          CopyFilePath
          NewFile
          Paste
          Top
          Find RegExp "(\.[^.]*)$"
          Replace "_final\1"
          SelectAll
          Copy
          Clipboard 9
          Paste
          ClearClipboard
          Top
          Find RegExp "^([\t ]*)create[\t ]+switch[\t ]+(\$\w+)\((\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]+(\d+)[\t ,]*\)"
          Replace All "\1declare ui_switch \2\r\n\1\$TempID := get_ui_id(\2)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_POS_X,\3)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_POS_Y,\4)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_WIDTH,\5)\r\n\1set_control_par(\$TempID,\$CONTROL_PAR_HEIGHT,\6)\");"
          Clipboard 8
          SaveAs "^c"
          ClearClipboard
          EndIf
          Clipboard 0
          EndIf
          There is no support for variables in macro environment and content of clipboard cannot be changed directly by a macro. For that reason the condition IfNameIs "" is used in the macro to either process the content of a new, unnamed file with no name or of a named file. For a named file the new file is saved also with _final inserted left to file extension in file name. The replace is done on content of new file after pasting it from clipboard instead of the clipboard directly. The initial position of caret in active file cannot be saved by the macro and restored, except with using a bookmark or other special tricks which are not used by this macro code.

          It is not possible to add comments to the code of a macro which can be pasted into the multi-line text edit field in Edit/Create Macro window. However, the command SaveAs "" can be added to above macro code above the line with command Else to open the Save as window on which you have to enter the file name for the new file in case of active file on script start is a new, unnamed file.

          The script and the macro code are not written for processing the data of a named file which does not have a file extension at all as in this case inserting _final left to file extension fails respectively is done somewhere in file path if the file path contains a folder name with a dot. Such a special use case handling for named files with no file extension could be added to script and macro code, but I think that is not really necessary.

          The meaning of the Perl regular expression search string is:

          ^ ... start each search at beginning of a line.

          (...) ... is a marking (capturing) group which means the string matched by the expression inside the round brackets can be back-referenced with \1 or with $1 for the first marking group (first pair of round brackets), \2 or with $2 for the second marking group, and so on (up to nine by default, more with a different syntax).

          [\t ]* ... defines a character class with horizontal tab and normal space which is applied 0 or more times. The expression [\t ]* in search string in first marking group is used to match zero or more indenting tabs/spaces and back-reference this string with zero or more characters several times in replace string with \1 or $1 to take over the indent from create switch instruction to each line of the appropriate block.

          [\t ]+ ...  defines a character class with horizontal tab and normal space which is applied 1 or more times.

          \$ ... the character $ has several special meanings in Perl regular expression search and replace strings. It must be escaped with a backslash to get it interpreted as literal character $.

          \w+ ... \w references a predefined character class which matches any word character according to Unicode standard. The multiplier + means again one or more times.

          \( ... the opening round bracket has a special meaning in a Perl regular expression search string and must be also escaped for that reason with a backslash to be interpreted as literal character to find.

          \d+ ... \d references a predefined character class which matches any digit according to Unicode standard. The multiplier + means again one or more times.

          [\t ,]+ ... defines a character class with horizontal tab and normal space and comma which is applied one or more times.

          [\t ,]* ... defines a character class with horizontal tab and normal space and comma which is applied zero or more times.

          \) ... the closing round bracket has a special meaning in a Perl regular expression search string and must be escaped for that reason with a backslash to be interpreted as literal character to find.
          Best regards from an UC/UE/UES for Windows user from Austria

          31
          NewbieNewbie
          31

            Jan 28, 2020#5

            Hi Mofi,

            Wow, thanks again for your super helpful instructions. I just quickly tested your latest script and it seems to work like a charm! Exactly what I've been looking for! Now I'll dig deeper into regular expressions, but I'm pretty sure I'll get the hang of it thanks to your detailed explanations.

            Thanks again, I really appreciate it!

            Best,
            Klaus