User to user discussion and support for UltraEdit, UEStudio, UltraCompare, and other IDM applications.

Help with writing and running scripts
11 posts Page 1 of 1
Hi,

I have a script for html/xml tag completion. But the script does not work in UEStudio '11.

Please could somebody help me to modify this script to get it working properly also with UEStudio '11.

The script is the UltraEdit Tag Completion Script written by Rob Dawson.

Thanks, Samir
Script does not work in UEStudio '11 does not describe what is not working. Explain on an example what the script should do and what it currently does.

Is there any error message printed by JavaScript interpreter into the output window because of a syntax error in script or an unknown command or property? Open the output window before executing the script.

Why do use that script at all? For UltraEdit a scripting solution is needed, but UEStudio has this feature built-in. There is in HTML toolbar of UEStudio the Close Tag command which UltraEdit does not have.

I restored UEStudio v11.00.0.1009 from an archive, opened an XML file, removed two closing tags on a block and executed the script written by Rob Dawson twice and it worked fine and added the two missing closing tags.
Best regards from Austria
Original tag:
Code: Select all
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em></a></p>

After deleting two closing tags "</a></p>" the result is as follows:
Code: Select all
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em>

After executed the script written by Rob Dawson twice, the result is as follows:
Code: Select all
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em></a></em>

Please help me to get the actual result.
I wrote into a *.html file the following three lines:

Code: Select all
<p>First paragraph</p>
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em>
<p>Third paragraph</p>

Then I set caret to end of line 2 and executed the script the first time. The result was:

Code: Select all
<p>First paragraph</p>
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em></a>
<p>Third paragraph</p>

With </a> inserted and caret still blinking at end of second line, I executed the script a second time. The result was:

Code: Select all
<p>First paragraph</p>
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em></a></p>
<p>Third paragraph</p>

So the script is working perfect (using UE v22.20.0.49).
Best regards from Austria
But the script is not working properly in UEStudio '11.
I analyzed the script with my/your example with UEStudio v11.00.0.1011 and found out that the script indeed produces the wrong result if there are two start tags with no character between in active file and the end tag for the outer element is missing at current position of the caret.

The difference on result is caused by the fact that UES v11.00 sets caret to begin of found string on running upwards a Perl regular expression find with search string <[^!%?>][^>]*>, for example beginning of <em>, while UE v22.20.0.49 sets caret to end of string found by the upwards search.

The difference on search behavior can be easily seen by copying and pasting into a new file:

Code: Select all
<p class="list-item1 parahangblk1"><a id="toc-loc" href="@@@.html#loc"><em>List of Contributors</em>

Now running 3 times a Perl regular expression find in upwards direction with search string <[^!%?>][^>]*> started from end of file results in getting selected

  • with UE v22.20.0.49 the strings </em> and <em> and <a id="toc-loc" href="@@@.html#loc"> with caret each time blinking at end of those 3 strings
and

  • with UES v11.00.0.1011 the strings </em> and <em> and <a id="toc-loc" href="@@@.html#loc"><em> with caret each time blinking at beginning of those 3 strings.
The additionally selected <em> causes the wrong result with UES v11.00.

As it is not possible from within the script to find out if the current version of UE/UES sets caret to begin or end of found string, I introduced a global boolean variable gl_bCaretAtBegin at top of the script after the introducing comment block which must be initialized with value true for UES v11.00 and with false for UE v22.20. And I made some other small improvements on the script written by Rob Dawson.

Code: Select all
/*
     This script adds HTML/XML tag-completion functionality to the UltraEdit text editor. For details
     of how to install and use UltraEdit scripts see here:

          http://www.ultraedit.com/support/tutorials_power_tips/ultraedit/scripting_engine_tutorial.html

     The script searches backwards through the active document looking for HTML/XML style tags that have
     been opened but not yet closed - the first such tag that is found will have an appropriate closing
     tag inserted into the document at the cursor location.

     HTML/XML/JSP comments, CDATA sections, DOCTYPE declarations and special JSP directives / scriptlets /
     declarations are all ignored.

     The default configuration will ignore the 9 'self-closing' HTML tags contained in the 'ignoredTags'
     array near the top of the code - when used in an HTML document these tags should not be closed, however
     in XHTML/XML documents all tags must be closed, so this line should be modified or commented out
     according to your needs.

     For the latest version of this script visit:
          http://codebox.org.uk/pages/ultraedit-scripts/html-xml-tag-auto-complete

     For licensing information go to:
          http://codebox.org.uk/pages/about

 */

var gl_bCaretAtBegin = true;

if (CODEBOX === undefined){
    var CODEBOX = {};
}

CODEBOX.tagComplete = function(){
    var closedTags = [], tag, haveRestored = false, parts = [];
    var whitespaceRegex = /^\s+|\s+$/g;
    var ignoredTags = ['area', 'base', 'basefont', 'br', 'hr', 'input', 'img', 'link' , 'meta']; // Comment this line out to stop ignoring them

    var doc = UltraEdit.activeDocument;
    var previousPos = doc.currentPos;
    var currentPos;

 // Remember where we start from
    var restorePosn = (function(col, line){
            return function(){
                doc.gotoLine(line, col);
                haveRestored = true;
           };
       })((typeof(UltraEdit.activeDocumentIdx) == "undefined") ? doc.currentColumnNum + 1 : doc.currentColumnNum, doc.currentLineNum);

 // Set up the find options
    UltraEdit.perlReOn();
    doc.findReplace.matchCase  = false;
    doc.findReplace.matchWord  = false;
    doc.findReplace.regExp     = true;
    doc.findReplace.searchDown = false;
    doc.findReplace.mode       = 0;
    if (typeof(doc.findReplace.searchInColumn) == "boolean"){
        doc.findReplace.searchInColumn=false;
    }

    function extractTagName(tag){
        if (tag.charAt(0) === '/'){
         // Strip out the leading slash character if its a closing tag
            tag = tag.substring(1);
        } else {
         // Remove any attributes if its an opening tag
            tag = tag.split(/\s/)[0];
        }
        return tag;
    }

    function isIgnoredTag(tag){
     // Is this tag one of the 'ignored' ones listed above
        if (typeof(ignoredTags) !== 'undefined'){
            tag = extractTagName(tag);
            for(var i=0, l=ignoredTags.length; i<l; i++){
                if (ignoredTags[i] === tag){
                    return true;
                }
            }
        }
        return false;
    }

    while (true) {
        previousPos = currentPos;
        tag = getNextTag();
        if (!isIgnoredTag(tag)){
            currentPos = doc.currentPos;

            if (previousPos <= currentPos){
             // Our search has hit the top of the document and begun again from the bottom, so stop
                break;
            }

            if (tag.length > 0){
                if (tag.charAt(0) === '/'){
                 // This is a closing tag, eg </div> - push it onto the stack and continue searching
                    closedTags.push(extractTagName(tag));

                } else if (tag.charAt(tag.length - 1) === '/'){
                 // This is an empty element, eg <div /> - ignore and continue
                } else {
                 /* If the tag has attributes we want to remove them, so split tag contents on
                    whitespace and take the first part */
                    tag = extractTagName(tag);

                    if ((closedTags.length > 0) && (tag === closedTags[closedTags.length - 1])){
                     /* This is an opening tag but there is already a corresponding closing tag, so just
                        pop the entry off the stack and continue moving back through the document */
                        closedTags.pop();

                    } else {
                     /* This looks like an opening tag that has no corresponding close tag, so move back
                        to where we started from and write one. */
                        restorePosn();
                        doc.write('</' + tag + '>');
                        break;
                    }
                }
            }
        }
    };

    if (!haveRestored) {
        restorePosn();
    }

    function getNextTag(){
     /* Search backwards through the document looking for text inside angle-brackets, ignoring
        anything that looks like an XML/HTML comment, a CDATA tag, a DOCTYPE declaration, or
        any of the special JSP directives  */
        function trim(txt){
            return txt.replace(whitespaceRegex, '');
        }
        doc.findReplace.find("<[^!%?>][^>]*>");
        var match = doc.selection;
     // Cancel the selection with caret set at beginning of tag.
        if (gl_bCaretAtBegin){
            doc.key("RIGHT ARROW");
            doc.key("LEFT ARROW");
        }

        if (match.length > 2){
         // remove the brackets and just return what's inside
            return trim(match.substring(1, match.length - 1));
        } else {
            return '';
        }
    }

};

CODEBOX.tagComplete();
Best regards from Austria
Thanks Mofi. The script is working perfect now using UES v11, but works very slow on large file.

I have written a macro solution. The macro solution uses 2 macros.

First macro with name 1 is:

Code: Select all
InsertMode
ColumnModeOff
HexOff
Key Ctrl+HOME
Loop 9999
PerlReOn
Find RegExp "<([a-z][\w-]*)(?: [^>]+?)?/>"
Replace All ""
IfNotFound
ExitLoop
EndIf
EndLoop
Loop 9999
PerlReOn
Find RegExp "<([a-z][\w-]*)(?: [^>]+?)?>[^<]*?</\1>"
Replace All ""
IfNotFound
ExitLoop
EndIf
EndLoop

The second macro is:

Code: Select all
InsertMode
ColumnModeOff
HexOff
SelectToTop
Copy
NewFile
Paste
Key Ctrl+HOME
PlayMacro 1 "1"
Key Ctrl+END
PerlReOn
Find RegExp Up "(?<=<)([a-z][\w-]*)"
ClearClipboard
Clipboard 2
Copy
CloseFile NoSave
Clipboard 1
Cut
Clipboard 1
Paste
"</"
Clipboard 2
Paste
">"
ClearClipboard
Clipboard 0

I want this concept for script. How to code the script working like this macro?
Well, you could open View - Views/Lists - Tag List. The default tag list file contains the two groups UE/UES Macro Commands and UE/UES Script Commands. The descriptions of the commands existing as macro command and as scripting command are identical.

Using the tag list UE/UES Script Commands it should be no problem for you to convert your two macros into a script with a JavaScript function for first macro called from main script code. You should (must) give the JavaScript function a better name than 1.

In scripts variables can be used for selected strings instead of using the user clipboards as variable storage. But you can of course also use the user clipboards.

Please read also JavaScript tutorial, power tips and more, especially the post with the most common mistakes made on writing a script.
Best regards from Austria
I do not know anything about the script environment. I have only recorded manual executions into a macro. Please give as much benefit if you have to script. I want to know more. How to record a script like a macro record in UEStudio?
Scripts can't be recorded. Script code must be written in a text editor or IDE. This requires basic skills in writing JavaScript code. The referenced announcement topic contains lots of links to tutorials. Yes, for writing scripts it is necessary to read and learn something as I and every other JavaScript code writer needed also to do. Good luck on extending your skills into area of JavaScript code writing.
Best regards from Austria
Thanks for advice.

Sure, I am trying to learn JavaScript.
11 posts Page 1 of 1