"Book Title" Capitalize

"Book Title" Capitalize

21
Basic UserBasic User
21

    Sep 30, 2008#1

    I have written a little JavaScript that converts a selected text, into a "Book Title"-like capitalized text. E.g. "The end of the game" is replaced with "The End of the Game". A list of articles ("the", "a", etc.) and prepositions ("at", "on", etc.) are *not* capped.

    The code should be a nice addition to the already existing Format menu, "To Upper Case", "To Lower Case", "Capitalize" and "Invert Case" functions already in UE. I'll be posting the code later in the thread.

    Since this is my first JavaScript vs. UE code I have come across a few things I don't understand, because these things would work in ANSI C, or D or PHP, but do not in JS.

    Issues:
    • Selected text is lower cased, but the text variable ignores the *current* state of the selected text:

      Code: Select all

      UltraEdit.activeDocument.toLower();               // Lower case selected text
      var text = UltraEdit.activeDocument.selection;    // Remember selected text
      UltraEdit.outputWindow.write( text );             // Output "text" to console
      
      The manual states that .selection: "** This is a READ ONLY property of the active/specified document". As I understand it this is actually not "read only", but in fact .selection is a state remembered at launch time of the script, and this state is *not* updated.

      If I understand this correctly... then what use is something like toLower() if you have no access to the changed selection? Would you have to manually "re-select" the changed text?
    • Overwriting a single char in a string array?

      Code: Select all

      var text = UltraEdit.activeDocument.selection;
      var words = text.split(" ");
      
      // Trying to change the capitalization of the 1st word's 1st letter
      // E.g. words[0] = "end" -> words[0][0].toLocaleUpperCase() yields  "E"
      words[0][0] = words[0][0].toLocaleUpperCase();
      
      But for some reason JS does not let you overwrite the single char in words[0][0]. What is up with that?

      I did something like this to fix the problem:

      Code: Select all

      words[0] = words[0][0].toLocaleUpperCase() + words[0].slice(1);
    Thanks...

      Sep 30, 2008#2

      Another thing that would help make the source code of JS a lot easier to read would be a alias-like command to shorten all the UltraEdit method calls. E.g.:

      Code: Select all

      alias UltraEdit.activeDocument  UaD
      alias UltraEdit.outputWindow    UoW
      
      This would let neat up: UltraEdit.activeDocument.hexOff(); to UaD.hexOff();.

      "D" lets you do this and C's macros would probably also let you do it. But does JavaScript have something like that?

      Update:
      The downloadable JavaScript at IDM javadoc_func.js, actually uses such an alias in it's code:

      Code: Select all

      var doc = UltraEdit.activeDocument;
      doc.selectLine();
      
      This is nice... my aliases would then look like this:

      Code: Select all

      var UaD = UltraEdit.activeDocument;
      var UoW = UltraEdit.outputWindow;
      
      Though a more convenient and conform alias naming would probably be:

      Code: Select all

      var doc = UltraEdit.activeDocument;
      var out = UltraEdit.outputWindow;
      
      Nice! :)

        Oct 02, 2008#3

        Well... my JavaScript works as it is, so I am posting the code now.

        Update: ae_book_title_capitalize.js - v2 - 10/2/2008:

        Code: Select all

        /*
         *   ae_book_title_capitalize.js
         *  -----------------------------
         *      by AEon (C) 2008            http://www.planetquake.com/aeons
         *                                  Code Provided as is, use at your own risk.
         *  Creation Date:  9/29/2008
         *  Last Modified:  10/2/2008
         *
         *  Purpose: Capitalize selected text into "Book Title" style: Upper case
         *           the 1st letter of each word, but keep all articles and
         *           prepositions in lower case.
         *           E.g.:  "The end of the game"  ->  "The End of the Game"
         *
         *  Install: This JavaScript is intended to be run from UltraEdit v13+.
         *           Install the script via Scripting menu, Scripts..., Add button.
         *
         *  Usage:   Select the "title text" you want to capitalize, then run
         *           this script. Selected text is replaced by "capped" text.
         *
         *  Note:    - Should no text be selected warning dialog box is shown.
         *           - Only key (articles & prepositions) words are lower cased.
         *           - For all other words only the 1st letter is upper cased!
         *           - You can also select multiple lines.
         *           - Words *need* to be separated by spaces or tabs.
         *           - Multiple lines, spaces or tabs allowed.
         *           - Tabs are replaced by spaces!
         */
        
        // Method aliases, to improve readability
        var ue  = UltraEdit;
        var doc = UltraEdit.activeDocument;
        var out = UltraEdit.outputWindow;
        
        
        // Function that caps the first letter of a word, and returns it.
        function cap_1st_letter( word )
        {
            if( word === "" )           // Empty words have to be ignored!
                return word;
            else
                return word[0].toLocaleUpperCase() + word.slice(1);
        }
        
        
        // If no text is selected, open warning dialog!
        if( doc.isSel() )
        {
            // Environment housekeeping (temporarily controls the modes)
            ue.insertMode();            // Ensure insert mode
            ue.columnModeOff();         // Turn off column mode
            doc.hexOff();               // Turn off hex mode
        
            // Remember selection in "text"
            var text = doc.selection;
        
            // Replacing the tabs with spaces (JS replace)
            text = text.replace(/\t/g, ' ');
        
            // Split text into words at spaces " ", create words array
            var words = text.split(" ");
        
            // Constant literal array with all the articles and prepositions
            // that should stay in lower case!
            const art_prep = [  "a",   "an", "and", "as",  "at",  "but", "by",
                                "for", "in", "nor", "of",  "off", "on",  "or",
                                "out", "per", "so", "the", "to",  "up",  "via",
                                "vs.", "yet"    ];
        
            // Initialize an Associative Array.
            //  Quickly check if current word is in art_prep[] list!
            var ap_arr = new Array();
            for( var i = 0; i < art_prep.length; i++ )
                ap_arr[ art_prep[i] ] = 1;
        
            // 1st word (index 0) does not need to be checked.
            //  -> Always upper case 1st letter of 1st word!
            var btc_text = cap_1st_letter( words[0] );
        
            // Loop through 2nd, 3rd, etc. words of selection
            for( var w = 1; w < words.length; w++ )
            {
                // If word is *not* in art_prep, upper case first letter!
                // Else if the word is recognized, enforce lower case!
                if( ap_arr[ words[w].toLocaleLowerCase() ] !== 1 )
                    words[w] = cap_1st_letter( words[w] );
                else
                    words[w] = words[w].toLocaleLowerCase();
        
                // Concatenate new capped string
                btc_text += " " + words[w];
            }
        
            // Write back (into the selection) the "Book Capped" Title
            doc.write( btc_text );
        }
        else
            ue.messageBox(  "To - Book Title Capitalize - a title, " +
                            " *first* select some text!",
                            "Warning: Book Title Capitalize" );
        
        Note: For those interested I am using a Associative Array to let me very quickly check if a word is an article or a preposition from the list.

        Here is some test code to try out the above JavaScript:

        Code: Select all

        THE END OF THE MOVIE HAS YET TO BE SEEN
        
        A HAS AN HAS AND HAS AS HAS AT HAS BUT HAS BY HAS
        FOR HAS IN HAS NOR HAS OF HAS OFF HAS ON HAS OR HAS
        OUT HAS PER HAS SO HAS THE HAS TO HAS UP HAS VIA HAS
        VS. HAS YET HAS
        Hope this is of some use. Suggestions for improvements welcome.

        262
        MasterMaster
        262

          Oct 02, 2008#4

          Very neat! Some suggestions for further development could be:
          - the ability to preserve specific (or all?) abbreviations as capital letters (like UK, USA).
          - the ability to handle names like McDonald, O'Brien, where a letter "inside" the word must be capitalized.

          21
          Basic UserBasic User
          21

            Oct 02, 2008#5

            :)

            I used one shortcut in all this, lower-casing everything first. The idea behind this was to fix possible all upper-case words, or other "typing junk" to receive a consistent output. But your examples are quite interesting, it had not occurred to me to think of names.

            The best way, and this would automatically include your examples, would be to *not* lower-case everything, and to only do the "minimum" amount of changes to the words. E.g. for a compare with the "key words" lower-case word by word temporarily, e.g. "IN" would be "in", and then lower-cased to stay "in". But to USA or UK etc., a "trivial" upper-casing of the 1st letter would be done, thus changing nothing.

            I'll change the code to use the latter path.

            Update: I updated the code above to v2. The corrections were surprisingly simple to do and should now do exactly what you wanted.