JavaScript tutorial, power tips and more

JavaScript tutorial, power tips and more

262
MasterMaster
262

    Apr 19, 2007#1

    JavaScript tutorials and references
    UltraEdit power tips and re-usable scripts on this website:
    User tools to use while developing UE scripts:
    • There is a power tip on this site on Configure UltraEdit with javascript lint
      JavaScript Lint checks any JavaScript source code for common mistakes without actually running the script - so it can also check scripts to be used in UE
    Re-usable scripts submitted by users in this forum:
    User submitted answers to scripting FAQ's

    (Edited May 13, 2007: JavaScript Lint and Mozilla links added).
    (Edited June 21, 2007: Link to power tip: Scripting Access to the Output Window).
    (Edited September 18, 2008: Extra power tip links added as well as links to re-usable scripts).

    6,602548
    Grand MasterGrand Master
    6,602548

      List of UltraEdit / UEStudio script commands and most common mistakes

      Mar 07, 2009#2

      The scripting commands are documented in help of UltraEdit / UEStudio on page Scripting commands. Just open the help, switch to the Index tab, enter Scripting commands and press key RETURN.

      The standard tag list file taglist.uet (ANSI encoded) respectively taglistu.uet (Unicode encoded) contains also lots of tags for inserting all the scripting commands with the various parameters. Just click on View - Views/Lists - Tag List (on using menu mode) and select the tag group UE/UES Script Commands to see them. Double clicking on an item in this list inserts the command with the parameters and places the cursor where you have to enter something (first). It is also possible to select a text in the script file before inserting a tag around the selection.

      And standard javascript.uew (in very old UE: wordfile.uew) contains in the JavaScript language definition also all special UltraEdit scripting commands and properties. So if you develop an UltraEdit script, the syntax highlighting, auto-correction and auto-complete features can also help you to avoid typing mistakes. If you have disabled auto-completion, you can manually use it with Ctrl+Space after typing the first two to three characters of a command.


      Common mistakes:
      1. Script copied from a forum post does not work

        If a script copied from a forum post does not do work, open Output Window by moving the mouse pointer over its tab in case of an auto-hidden docked output window, or click in menu Window on Output Window to see it. Does it contain the following lines?

        Code: Select all

        An error occurred on line 1:
        
        Script failed.
        Yes, then the script file is most likely not an ASCII/ANSI file (or a UTF-8 encoded file without BOM). The script file is most likely a Unicode file with a hidden BOM (byte order mark) at top of the file. JavaScript interpreter does not support Unicode files. See next post for a step by step introduction on how to create and use a script posted in the forum.
         
      2. Backslashes in strings are not escaped

        In JavaScript the backslash \ in a string has a special meaning, see the JavaScript tutorials. For that reason every backslash in a string (single or double quoted text) must be escaped with an additional backslash character to be interpreted as literal character, for example "C:\\Temp\\Test.txt". When using a Perl regular expression find/replace and searching also for a backslash in file, the backslash must be escaped for the Perl regular expression engine and then both backslashes must be escaped additionally with 2 backslashes because of JavaScript string interpretation. Example:

        Code: Select all

        // Define the Perl regular expression engine to use for regexp searches.
        UltraEdit.perlReOn();
        // Define once all search parameters (with downwards compatibility code).
        UltraEdit.activeDocument.findReplace.matchCase=false;
        UltraEdit.activeDocument.findReplace.matchWord=false;
        UltraEdit.activeDocument.findReplace.regExp=true;
        UltraEdit.activeDocument.findReplace.searchAscii=false;
        UltraEdit.activeDocument.findReplace.searchDown=true;
        if (typeof(UltraEdit.activeDocument.findReplace.mode) != "undefined")
        {
           UltraEdit.activeDocument.findReplace.mode=0;
        }
        if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) != "undefined")
        {
           UltraEdit.activeDocument.findReplace.searchInColumn=false;
        }
        
        // Find "C:\Temp\*.txt" in the current file (simplified).
        UltraEdit.activeDocument.findReplace.find("C:\\\\Temp\\\\.*\\.txt");
        The Perl regular expression JavaScript string "C:\\\\Temp\\\\.*\\.txt" is interpreted by JavaScript interpreter and passed to Perl regular expression engine of UltraEdit as C:\\Temp\\.*\.txt which interprets this regular expression string as search string C:\Temp\.*.txt to find in active file whereby .* means any character except newline characters 0 or more times and all other characters literally as specified.
         
      3. Define the working environment for your scripts

        Whenever possible write your scripts without depending on internal defaults of UE/UES/UEm. Define once in your script all find/replace parameters before running the first find/replace. Define also always the regular expression engine once before running any search even when the search is a non regular expression search. And define the editing mode - insert or overstrike mode, normal or column editing mode, hex edit mode on or off.
         
      4. Missing round brackets on function call

        Many functions do not require a parameter like

        if (UltraEdit.activeDocument.isSel())
        {
        // Whatever should be done when there is a selection.
        }


        But the round brackets are required for every function call. Using if (UltraEdit.activeDocument.isSel) without the round brackets is valid JavaScript code and does not produce an error, but the IF condition is now always true. Why?
        Because using just the function name without the round brackets returns the value true or false depending on existence of function isSel which is true for all versions of UE/UES/UEm/UEM/UEX supporting scripts. In other words a function name without round brackets is a test if the function is defined when executing the current script. This can be used to make script downwards compatible as demonstrated by some of the user contributed scripts like HexCopy.js or MergeTextFiles.js (see user-submitted scripts), but missing round brackets after a function name are often just a mistake.
         
      5. Passing a number to one of the write functions instead of a string

        All write functions (commands) require that the passed parameter is a string. JavaScript automatically converts values of number or boolean variables to a string when concatenating a string (defined in the script code or value of a string variable) with the value of a number or a boolean variable. So for example

        var nFileCount = 20;
        UltraEdit.activeDocument.write("File count is: "+nFileCount);
        var sMessage = "Number of files is: ";
        UltraEdit.outputWindow.write(sMessage+nFileCount);


        is absolutely valid code because the JavaScript engine converts the value of the number variable first to a string (using decimal system), then concatenates the two strings and passes the resulting string to function write. But using

        var nFileCount = 20;
        UltraEdit.activeDocument.write(nFileCount);


        does not work because the value of the number variable is passed as integer value and not as string to function write. The solution is to use explicitly the method (function) toString() to convert the value to a string before passing it to the function write as shown below:

        UltraEdit.activeDocument.write(nFileCount.toString());
         
      6. First element of document array has index 0, but property length is the number of opened documents starting with number 1

        Often a script code is executed on all opened files like

        for (var nDocIndex = 0; nDocIndex < UltraEdit.document.length; nDocIndex++)
        {
        // Whatever should be done on all opened files.
        }


        Important here is that nDocIndex < UltraEdit.document.length is used and not nDocIndex <= UltraEdit.document.length because the document index numbering starts with 0, but the number of elements of an array (= number of opened files for the document array) starts with 1.
         
      7. Opening a file already opened from within script does not result in reloading file content and making the file active

        When a file is opened already and modified and you open this file again, a message prompt is shown asking you if you want to reload the file and loose all changes. Whatever you choose the result is that the re-opened file is the active one. When a file is opened and not modified and you re-open it, the file just becomes the active one.

        But the behavior for opening a file which is opened already using the script command UltraEdit.open(""); is completely different in versions of UltraEdit prior v16.10.0.1021. If the file is opened already in such a version of UltraEdit, nothing is done. The file content is never reloaded and also the file becomes never active in those versions of UE. So when your script contains the command UltraEdit.open(""); it should always check before if the file to open is not already opened in UE/UES/UEM/UEP. This can be done using function GetFileIndex and the if condition in your script:

        Code: Select all

        function GetFileIndex (sFullNameOfFile)
        {
           // Is the passed value not a string because simply nothing passed?
           if (typeof(sFullNameOfFile) != "string")
           {
              // With UltraEdit v16.00 and later there is a property which holds active document index.
              if (typeof(UltraEdit.activeDocumentIdx) == "number") return UltraEdit.activeDocumentIdx;
              sFullNameOfFile = UltraEdit.activeDocument.path;
           }
           else if (!sFullNameOfFile.length) // It is a string. Is the string empty?
           {
              if (typeof(UltraEdit.activeDocumentIdx) == "number") return UltraEdit.activeDocumentIdx;
              sFullNameOfFile = UltraEdit.activeDocument.path;
           }
           // Windows file systems are not case sensitive. So best make all file
           // names lowercase before comparing the name of the file to search
           // for with the names of the already opened files. Users of UEX should
           // use a case sensitive file name comparison and therefore don't need
           // toLowerCase() here and in the following loop.
           var sFileNameToCompare = sFullNameOfFile.toLowerCase();
        
           // Compare the name of the file to search for with the (lowercase) file
           // names of all already opened files. Return the document index of the
           // file already opened when found.
           for (var nDocIndex = 0; nDocIndex < UltraEdit.document.length; nDocIndex++)
           {
              if (UltraEdit.document[nDocIndex].path.toLowerCase() == sFileNameToCompare)
              {
                 return nDocIndex;
              }
           }
           return -1; // This file is not open.
        }

        Code: Select all

        var nActiveDocIndex = GetFileIndex(sFileNameToOpen);
        if (nActiveDocIndex < 0) UltraEdit.open(sFileNameToOpen);
        else
        {
           UltraEdit.document[nActiveDocIndex].top();
           UltraEdit.document[nActiveDocIndex].setActive();
        }
        BTW: Function GetFileIndex is just a more general version of getActiveDocumentIndex which returns the same result when calling GetFileIndex without any parameter or with an empty string.
         
      8. Closing a file does not make any other file active

        When closing a file manually, the last active file or the file with the nearest open file tab left the just closed file or another file according to configuration setting After current tab is closed, move to: (UE v16.20 and later) becomes automatically active. But this does not happen when closing a file from within a script. The command UltraEdit.document[nIndexOfNewActiveFile].setActive(); must be used to make a file active after closing a file.

        Extra hint: Avoid closing files with a document index number lower the document index of the active file, especially when the script works with multiple documents at once. The effects on the document array can be unpredictable.
         
      9. UltraEdit.activeDocument.isEof() returns true only when the cursor reaches the end of file

        Function UltraEdit.activeDocument.isEof() returns only boolean true when the cursor in the file reaches the end of the file. When using the find/replace command in a loop to do something from top of the file to end of the file, the command UltraEdit.activeDocument.isEof() can't be used as exit condition for the loop because the cursor is not changed when no string is found anymore. Use the result of the find/replace itself to exit the loop when the find/replace could not find a string anymore, see also next point.
         
      10. Find/Replace are always only from current cursor position to end/top of file

        All searches and replaces from within a script (or macro) are always executed only from current cursor position to end of file (searching downwards) or top of the file (searching upwards). The configuration setting Continue find at End of File and the replace all option Replace All is from top of file are never active for finds/replaces executed from within a script (or macro) to avoid endless loops. If you want to search/replace something in entire file, simply move the cursor first to top of file using script command UltraEdit.activeDocument.top(); respectively UltraEdit.document[x].top();
         
      11. UltraEdit.activeDocument.key("DOWN ARROW"); can result in an endless loop

        When working on a file with a script line by line using command UltraEdit.activeDocument.key("DOWN ARROW"); in a loop and UltraEdit.activeDocument.isEof() == false as loop condition make sure that the last line of the file has also a line termination or the cursor never reaches the end of the file and therefore the result is an endless loop. You can use following code:

        Code: Select all

        // Move cursor to end of the file.
        UltraEdit.activeDocument.bottom();
        // Is the cursor not at column 1, the last line has no line termination.
        if (UltraEdit.activeDocument.isColNumGt(1))
        {
           // Inserting a line below at end of file inserts the line termination
           // character(s) depending on the type of line terminators of this file.
           UltraEdit.activeDocument.insertLine();
           // If the last line of the file has preceding whitespaces (spaces/tabs)
           // and auto-indent feature is enabled, the inserted line has now also
           // the same number of spaces/tabs. Those inserted whitespaces must be
           // deleted to get just the line termination at end of the file.
           if (UltraEdit.activeDocument.isColNumGt(1))
           {
              UltraEdit.activeDocument.deleteToStartOfLine();
           }
        }
        
        UltraEdit.activeDocument.top();
        while (UltraEdit.activeDocument.isEof() == false)
        {
           // Whatever should be done on this line.
           UltraEdit.activeDocument.key("DOWN ARROW");
        }

        How to create a script from a post in the forum?

        Mar 17, 2012#3

        This is a step by step introduction on how to create and use a script posted in the forum.
        1. Create a new file in UltraEdit by pressing Ctrl+N if a new file is not already displayed after starting UltraEdit.
        2. Make sure the new file is an ASCII/ANSI file with DOS or UNIX line terminators. If you see on the status bar at bottom of the UltraEdit window in a box just DOS or just UNIX without a preceding U-, U8-, UBE- or UESC- and also no UTF-16, UTF-8, UTF-16BE or UESC, the new file is an ASCII/ANSI file with DOS respectively UNIX line terminators. Otherwise you would need the commands in submenu File - Conversions to convert the file to ASCII with DOS or UNIX line terminators. The integrated JavaScript interpreter does not support Unicode files, especially not with a hidden BOM (byte order mark) at top of the script file. See note below.
        3. Select the script code in your browser window and press Ctrl+C.
        4. Switch back to UltraEdit and press Ctrl+V to paste the code into the new file.
        5. Press F12 to open Save As dialog. Make sure that Line Terminator option is set to Default, DOS or UNIX and Format option is set to Default or ANSI/ASCII. Save the script file to any folder you want. A good place is usually the Scripts folder in the UltraEdit program files directory if you have write access to this folder with your account. But you can use also any other folder.
        6. Open Scripting - Script List and add the just saved script to this list.
        7. Open the file(s) on which you want to run the script if the script requires opened file(s).
        8. Open menu Scripting and click on the name of the script file.
        9. The script is now executed and a small dialog with a Cancel button is displayed to break script execution.
        10. If output window is not open, open it with Window - Output Window and check if you can see Script succeeded in the output window and not an error message.
        The printing of the status messages to output window can be turned off by disabling setting Show status information in output window at Advanced - Settings or Configuration - Scripting. But don't have this option disabled on developing a script because then also error messages from JavaScript interpreter are not written to the output window. And while developing a script it is advisable to have the output window permanently visible to see error messages. Make it visible by clicking on Window - Output Window if not displayed at all, or by clicking on the small pin symbol on top right corner of the window if auto-hiding is enabled.

        Note:

        Instead of ASCII/ANSI encoding it is also possible to save an UltraEdit/UEStudio script as UTF-8 encoded file without BOM.

        But the usage of Unicode characters in a script is very limited in UltraEdit for Windows < v24.00 and UEStudio < v17.00. For details on Unicode usage in scripts in older versions of UE/UES see the topics:
        Other script topics dealing with Unicode characters can be found by using advanced forum search and searching in the Scripts forum only for the word Unicode producing this results list.

        Starting with UE v21.30.0.1016 and UES v14.40.0.1012 it is also possible to execute a script encoded as UTF-8 with BOM or UTF-16 LE. But this does not mean Unicode characters not present in standard ANSI code page according to Windows language settings can be used in strings in the script for writing them into a file. UltraEdit/UEStudio just detects the file encoding for a Unicode encoded script, convert the script internally to UTF-16 LE, creates a byte stream by taking just all odd bytes from Unicode byte stream and runs the JavaScript interpreter with this byte stream. In other words a UTF-8 or UTF-16 encoded Greek omega with hexadecimal code value 0x2126 in the script is finally for the JavaScript interpreter a single byte with hexadecimal value 0x26 which is the ampersand character.

        Full Unicode support in scripts and macros is available since UltraEdit for Windows v24.00.0.42 and UEStudio v17.00.0.16. The script file can be UTF-8 or UTF-16 encoded with UE v24.00 or UES v17.00 or any later version. Unicode characters in strings are interpreted correct on execution of the script. There are also no limitations anymore on processing data in Unicode files as prior UE v24.00 and UES v17.00.

          Usage of the multi-line prompt text of getValue and getString

          Jun 14, 2012#4

          With UE v18.10.0.1014 the dialog displayed on usage of scripting commands getValue and getString or macro commands GetValue and GetString has a prompt text area height of three lines. This can be used simply for longer prompt texts like in following example.

          UltraEdit.getValue("Please enter a value in range of 20 to 200 for number of lines to process:",1);

          But as script writer you have also control over the line break using \n in the prompt text as demonstrated with following examples:

          UltraEdit.getValue("\n\nHow many lines to process (20-200)?",1);

          UltraEdit.getValue("Search for files also in subdirectories?
          \nEnter value 0 for NO.\nEnter any other value for YES.",1);

          UltraEdit.getValue("Script: IncrementNumbersInBlock.js
          \n\nEnter initial value for the incremented numbers in block:",1);

          The result for these 4 commands is:

          getvalue_multiline_prompt.png (2.65KiB)
          Image with the 4 dialogs displayed for the 4 getValue commands.

          Macro writers can also make use of line breaks. Just make the line break(s) in macro editor within the prompt text in double quotes. For example the third example in macro editor would be:

          GetValue "Search for files also in subdirectories?
          Enter value 0 for NO.
          Enter any other value for YES."