Script to find out which end tag is missing next at current caret position and insert it

Script to find out which end tag is missing next at current caret position and insert it

62
Advanced UserAdvanced User
62

    Apr 02, 2016#1

    I have some sample text to replace by (<([a-z][\w-]*)(?: [^>]+?)? />|<([a-z][\w-]*)(?: [^>]+?)?/>|<!--|-->) and <([a-z][\w-]*)(?: [^>]+?)?>[^<]*?</\1>

    Code: Select all

    <html>
    <head>
    <title>Routledge</title>
    <link href="aa.css" rel="stylesheet" type="text/css"/>
    </head>
    <body>
    <p class="copyrightt1">First published 2012 by Ashgate Publishing</p>
    <p class="copyrightt">Published 2016 by Routledge</p>
    <p class="copyright">2 Park Square, Milton Park, Abingdon, Oxon OX14 4RN</p>
    <p class="copyright"><a id="p1"/>711 Third Avenue, New York, NY 10017, USA</p>
    <p class="copyrightt"><em>Routledge is an imprint of the Taylor & Francis Group, an informa business</em></p>
    Copyright &#x00A9; Julie Paquin 2012</p>
    </body>
    </html>
    
    after replace

    Code: Select all

    <html>
    
    <body>
    
    
    
    
    
    Copyright &#x00A9; Julie Paquin 2012</p>
    </body>
    </html>
    
    I want to select all text, copy, then open a new file, paste and replace all by (<([a-z][\w-]*)(?: [^>]+?)? />|<([a-z][\w-]*)(?: [^>]+?)?/>|<!--|-->) and <([a-z][\w-]*)(?: [^>]+?)?>[^<]*?</\1> in loop, when complete all search and replace, then select all text, cut, close new file without saving and paste into previous file.

    6,686585
    Grand MasterGrand Master
    6,686585

      Apr 02, 2016#2

      This time I don't post the script code, put I post the steps to create the code in hope you learn how to write such simple scripts next time by yourself.
      1. Create a new file with Ctrl+N if there is not already a new and empty file opened.
      2. Click on View - Views/Lists - Tag List to open Tag List view and select from drop down list at top of this view UE/UES Script Commands.
      3. This script should be designed to run on active file. Therefore it is advisable to make sure there is a file opened in UE/UES on execution of this script. This can be done with inserting into the new file following block not defined as tag (or template) by default.

        Code: Select all

        if (UltraEdit.document.length > 0)  // Is any file opened?
        {
           
        }
        The caret should be set to end of line 3 after inserting this block into the new file which means at column 4 as there are 3 leading spaces on line 3.
      4. It is advisable to save the new file now with any file name with file extension .js to enable syntax highlighting for the file and enable special tab/indent settings if there is a special configuration for *.js files.
      5. Next we must make sure that the script runs always with same environment. Therefore we look in Tag List view for Insert mode on and double click on this tag. After inserting the appropriate command, press key RETURN for a new line and 3 spaces with auto-indent feature enabled.
      6. Next command from tag list to double click is Column mode off and again key RETURN must be pressed.
      7. We need for the replaces the Perl regular expression engine and double click therefore in tag list on Regex engine Perl and press RETURN.
      8. The replaces should be always made on entire active file. Therefore we should make sure that the caret is positioned at top of the file. So we double click in list on Goto top of file and press key RETURN.
      9. We need to define the options for the Perl regular expression replaces to execute on active file.
        This can be done by double clicking in tag list on Replace opt: (default). A code block is inserted this time which must be additionally indented properly.
      10. regExp=false must be modified to regExp=true and replaceAll=false to replaceAll=true as we want to run two Perl regular expression Replace All on entire file.
      11. Back at column 4 of line 17 (last but one line) the replace command must be inserted next into the script file. Double click in tag list on Replace command.
      12. The caret is blinking already at correct position for entering the search string. Here we have to insert (<([a-z][\w-]*)(?: [^>]+?)? />|<([a-z][\w-]*)(?: [^>]+?)?/>|<!--|-->) and escape each backslash in this regular expression string with an additional backslash. So the search string is finally in script file: (<([a-z][\\w-]*)(?: [^>]+?)? />|<([a-z][\\w-]*)(?: [^>]+?)?/>|<!--|-->)
      13. After pressing key END and key RETURN one more double click on Replace command in tag list inserts one more replace command line where we insert second search string and escape each backslash to get finally <([a-z][\\w-]*)(?: [^>]+?)?>[^<]*?</\\1> as search string between the first pair of double quotes.
      14. Next we have to put each replace command within a while loop and therefore insert on both replace command lines while( at beginning after the 3 indent spaces and ) at end before the semicolon.
      15. The little script is already finished as copying entire file content to a new file, run the replaces there and copying the result back to active file are unnecessary steps for this task. So press Ctrl+S to save the script file.
      16. Click on Window - Output Windows to open this window if not already visible as errors in script are written to the output window on execution.
      17. Click on Scripting - Scripts and add the just created script file still opened to the Script List.
      18. Open the example file and click in menu Scripting on the just created and added script.
      The script coding and testing is done now for UEStudio v11.00.0.1011 for this little script with 19 lines.
      Best regards from an UC/UE/UES for Windows user from Austria

      62
      Advanced UserAdvanced User
      62

        Apr 05, 2016#3

        Thanks Mofi for advice.

        I tried to write a script as follow your instruction. And I tried to auto close tag.

        My script is:

        if (UltraEdit.document.length > 0)
        {
           UltraEdit.insertMode();
           UltraEdit.columnModeOff();
           UltraEdit.perlReOn();
           UltraEdit.activeDocument.selectToTop();
           UltraEdit.activeDocument.copy();
           UltraEdit.newFile();
           UltraEdit.insertMode();
           UltraEdit.columnModeOff();
           UltraEdit.perlReOn();
           UltraEdit.activeDocument.paste();
           UltraEdit.activeDocument.top();
           UltraEdit.activeDocument.findReplace.mode=0;
           UltraEdit.activeDocument.findReplace.matchCase=false;
           UltraEdit.activeDocument.findReplace.matchWord=false;
           UltraEdit.activeDocument.findReplace.regExp=true;
           UltraEdit.activeDocument.findReplace.searchDown=true;
           UltraEdit.activeDocument.findReplace.searchInColumn=false;
           UltraEdit.activeDocument.findReplace.preserveCase=false;
           UltraEdit.activeDocument.findReplace.replaceAll=true;
           UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
           while(UltraEdit.activeDocument.findReplace.replace("(<([a-z][\\w-]*)(?: [^>]+?)? />|<([a-z][\\w-]*)(?: [^>]+?)?/>|<!--|-->)", ""));
           while(UltraEdit.activeDocument.findReplace.replace("<([a-z][\\w-]*)(?: [^>]+?)?>[^<]*?</\\1>", ""));

           UltraEdit.activeDocument.bottom();
           UltraEdit.insertMode();
           UltraEdit.columnModeOff();
           UltraEdit.perlReOn();
           UltraEdit.activeDocument.findReplace.searchDown=false;
           UltraEdit.activeDocument.findReplace.find("(?<=<)([a-z][\\w-]*)");
           UltraEdit.selectClipboard(9);
           UltraEdit.activeDocument.copy();
           UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
           UltraEdit.selectClipboard(8);
           UltraEdit.activeDocument.cut();
           UltraEdit.selectClipboard(8);
           UltraEdit.activeDocument.paste();
           UltraEdit.activeDocument.write("</");
           UltraEdit.selectClipboard(9);
           UltraEdit.activeDocument.paste();
           UltraEdit.activeDocument.write(">");
           UltraEdit.clearClipboard();
           UltraEdit.selectClipboard(0);

        }

        But it does not work. I think, this script is not valid. Script part formatted with red color works very good. But when adding green formatted code, the result is not as expected.

        How to improve the script to get second part also working as expected?

        6,686585
        Grand MasterGrand Master
        6,686585

          Apr 06, 2016#4

          The three scripting commands:

          Code: Select all

          UltraEdit.insertMode();
          UltraEdit.columnModeOff();
          UltraEdit.perlReOn();
          are member functions of object UltraEdit in UltraEdit for Windows which means those three commands define insert mode on, column mode off and usage of Perl regular expression engine for entire instance of UltraEdit/UEStudio independent on which file is active. When you click with mouse on Column - Column Mode, the column mode is enabled for all files and not just for the currently active file. The same is true for insert or overstrike mode toggled with key Ins (on English keyboard). Therefore there is no need to call these member functions of UltraEdit object several times.

          I'm not sure what you want to achieve with the green formatted code lines. After copying content of active file into a new file (for whatever reason) and running there the replaces which nearly delete everything (for whatever reason), the caret is moved in this new file now containing nearly nothing anymore to bottom of file and run a Perl regular expression search upwards to find a start tag. This tag is copied to clipboard 9 and then the new file is closed.

          You expect the previous file becomes now active again, but this is not guaranteed in scripting environment. It depends on version of UE/UES and configuration setting After current tab is closed, move to.

          Therefore it is better to determine document index number of active file before opening the new file and work with document array after closing the new file.

          Script code (not tested):

          Code: Select all

          function getActiveDocumentIndex()
          {
             // There is an active document index property since UE v16.00 / UES v10.00.
             if (typeof(UltraEdit.activeDocumentIdx) == "number")
             {
                return UltraEdit.activeDocumentIdx;
             }
             // Workaround solution for UE < v16.00 and UES < v10.00.
             for (var i = 0; i < UltraEdit.document.length; i++)
             {
                if (UltraEdit.activeDocument.path == UltraEdit.document[i].path)
                {
                   return i;
                }
             }
             return (-1);
          }
          
          if (UltraEdit.document.length > 0)
          {
             UltraEdit.insertMode();
             if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
             else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
             UltraEdit.perlReOn();
             var nActiveDocIndex = getActiveDocumentIndex();
          
             UltraEdit.activeDocument.selectToTop();
             UltraEdit.selectClipboard(9);
             UltraEdit.activeDocument.copy();
          
             UltraEdit.newFile();
             UltraEdit.activeDocument.paste();
             UltraEdit.activeDocument.top();
             UltraEdit.activeDocument.findReplace.mode=0;
             UltraEdit.activeDocument.findReplace.matchCase=false;
             UltraEdit.activeDocument.findReplace.matchWord=false;
             UltraEdit.activeDocument.findReplace.regExp=true;
             UltraEdit.activeDocument.findReplace.searchDown=true;
             UltraEdit.activeDocument.findReplace.searchInColumn=false;
             UltraEdit.activeDocument.findReplace.preserveCase=false;
             UltraEdit.activeDocument.findReplace.replaceAll=true;
             UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
             while(UltraEdit.activeDocument.findReplace.replace("(<([a-z][\\w-]*)(?: [^>]+?)? />|<([a-z][\\w-]*)(?: [^>]+?)?/>|<!--|-->)", ""));
             while(UltraEdit.activeDocument.findReplace.replace("<([a-z][\\w-]*)(?: [^>]+?)?>[^<]*?</\\1>", ""));
          
             UltraEdit.activeDocument.bottom();
             UltraEdit.activeDocument.findReplace.searchDown=false;
             UltraEdit.activeDocument.findReplace.find("(?<=<)([a-z][\\w-]*)");
             UltraEdit.activeDocument.copy();
             UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
          
             UltraEdit.selectClipboard(8);
             UltraEdit.document[nActiveDocIndex].cut();
             UltraEdit.document[nActiveDocIndex].paste();
             UltraEdit.document[nActiveDocIndex].write("</");
             UltraEdit.clearClipboard();
             UltraEdit.selectClipboard(9);
             UltraEdit.document[nActiveDocIndex].paste();
             UltraEdit.document[nActiveDocIndex].write(">");
             UltraEdit.clearClipboard();
             UltraEdit.selectClipboard(0);
          }
          
          Best regards from an UC/UE/UES for Windows user from Austria

          62
          Advanced UserAdvanced User
          62

            Apr 06, 2016#5

            I have tried your last suggested script. It work like:

            Initial content:

            <p><i>sam<em>sam</em>sam|

            After first script execution:

            <p><i>sam<em>sam</em>sam</i>|

            After second script execution:

            <p><i>sam<em>sam</em>sam</i></p>|

            After third script execution:

            <p><i>sam<em>sam</em>sam</i></p></<p><i>sam<em>sam</em>sam</i></p>>|

            When upwards find for a start tag does not found anything, then nothing should be inserted at caret position in active file. So content after third script execution should be still:

            <p><i>sam<em>sam</em>sam</i></p>|

            6,686585
            Grand MasterGrand Master
            6,686585

              Apr 09, 2016#6

              Code: Select all

              function getActiveDocumentIndex()
              {
                 // There is an active document index property since UE v16.00 / UES v10.00.
                 if (typeof(UltraEdit.activeDocumentIdx) == "number")
                 {
                    return UltraEdit.activeDocumentIdx;
                 }
                 // Workaround solution for UE < v16.00 and UES < v10.00.
                 for (var i = 0; i < UltraEdit.document.length; i++)
                 {
                    if (UltraEdit.activeDocument.path == UltraEdit.document[i].path)
                    {
                       return i;
                    }
                 }
                 return (-1);
              }
              
              if (UltraEdit.document.length > 0)  // Is any file opened?
              {
                 // Define the environment for the script.
                 UltraEdit.insertMode();
                 if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
                 else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
                 UltraEdit.perlReOn();
              
                 // Get document index of active file.
                 var nActiveDocIndex = getActiveDocumentIndex();
              
                 // Get current line and column number in active file?
                 var nCurrentLine = UltraEdit.activeDocument.currentLineNum;
                 var nCurrentColumn = UltraEdit.activeDocument.currentColumnNum;
              
                 // The next line can be removed when using UltraEdit for
                 // Windows v16.00 or UEStudio v10.00 or any later version.
                 if (typeof(UltraEdit.activeDocumentIdx) == "undefined") nCurrentColumn++;
              
                 // Select everything from current caret position to top of file.
                 UltraEdit.activeDocument.selectToTop();
              
                 // Is something selected because the caret was not positioned at top of the file?
                 if (UltraEdit.activeDocument.isSel())
                 {
                    // Copy the selected block via user clipboard 9 into a new file.
                    UltraEdit.selectClipboard(9);
                    UltraEdit.activeDocument.copy();
                    UltraEdit.newFile();
                    UltraEdit.activeDocument.paste();
                    UltraEdit.clearClipboard();
                    UltraEdit.selectClipboard(0);
              
                    // Move the caret in the new file to top of the file.
                    UltraEdit.activeDocument.top();
              
                    // Define the parameters for Perl regular expression Replace All.
                    UltraEdit.activeDocument.findReplace.mode=0;
                    UltraEdit.activeDocument.findReplace.matchCase=false;
                    UltraEdit.activeDocument.findReplace.matchWord=false;
                    UltraEdit.activeDocument.findReplace.regExp=true;
                    UltraEdit.activeDocument.findReplace.searchDown=true;
                    UltraEdit.activeDocument.findReplace.searchInColumn=false;
                    UltraEdit.activeDocument.findReplace.preserveCase=false;
                    UltraEdit.activeDocument.findReplace.replaceAll=true;
                    UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
              
                    // Remove all empty elements.
                    while (UltraEdit.activeDocument.findReplace.replace("(<([a-z][\\w-]*)(?: [^>]+?)? />|<([a-z][\\w-]*)(?: [^>]+?)?/>|<!--|-->)", ""));
              
                    // Remove all elements with a start and an end tag not checking
                    // if each end tag really correspond to correct start tag as it
                    // is impossible with regular expression finds to take nesting
                    // of tags into account.
              
                    // Comment by Mofi: This is not really working in all possible use
                    // cases which is the reason why whenever somebody posts a question
                    // asking for using regular expression finds/replaces on HTML, XHTML
                    // or XML content on Stack Overflow the advanced users answer with:
                    // Don't use regex, use an HTML, XHTML or XML parser (or an HTML
                    // validator for this task).
              
                    while (UltraEdit.activeDocument.findReplace.replace("<([a-z][\\w-]*)(?: [^>]+?)?>[^<]*?</\\1>", ""));
              
                    // Define a variable for an end tag being initialized only
                    // if a start tag is found by the Perl regular expression
                    // searching upwards from bottom of new file.
                    var sEndTag;
                    UltraEdit.activeDocument.bottom();
                    UltraEdit.activeDocument.findReplace.searchDown=false;
                    if (UltraEdit.activeDocument.findReplace.find("(?<=<)([a-z][\\w-]*)"))
                    {
                       // Create the variable object now in memory as string variable
                       // and assign the end tag for the start tag found in new file.
                       sEndTag = "</" + UltraEdit.activeDocument.selection + ">";
                    }
              
                    // Close the new file without saving it.
                    UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
              
                    // Set caret in initial active file on script start back to initial
                    // position resulting also in canceling the selection in this file.
                    UltraEdit.document[nActiveDocIndex].gotoLine(nCurrentLine,nCurrentColumn);
              
                    if (sEndTag != null)    // Is there a missing end tag?
                    {
                       UltraEdit.document[nActiveDocIndex].write(sEndTag);
                    }
                 }
              }
              
              Best regards from an UC/UE/UES for Windows user from Austria

              62
              Advanced UserAdvanced User
              62

                Apr 12, 2016#7

                :P Thank you very much again, Mofi.