"Book Title" Capitalize

Help with writing and running scripts

"Book Title" Capitalize

Postby AEon » Tue Sep 30, 2008 7:24 am

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...
User avatar
AEon
Newbie
 
Posts: 9
Joined: Wed Sep 24, 2008 1:12 pm
Location: Bavarian Forest

Re: "Book Title" Capitalize

Postby AEon » Tue Sep 30, 2008 11:31 am

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! :)
User avatar
AEon
Newbie
 
Posts: 9
Joined: Wed Sep 24, 2008 1:12 pm
Location: Bavarian Forest

Re: "Book Title" Capitalize

Postby AEon » Thu Oct 02, 2008 8:43 am

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.
User avatar
AEon
Newbie
 
Posts: 9
Joined: Wed Sep 24, 2008 1:12 pm
Location: Bavarian Forest

Re: "Book Title" Capitalize

Postby jorrasdk » Thu Oct 02, 2008 9:27 am

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.
User avatar
jorrasdk
Master
Master
 
Posts: 275
Joined: Mon Mar 19, 2007 11:00 pm
Location: Denmark

Re: "Book Title" Capitalize

Postby AEon » Thu Oct 02, 2008 10:40 am

:)

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.
User avatar
AEon
Newbie
 
Posts: 9
Joined: Wed Sep 24, 2008 1:12 pm
Location: Bavarian Forest


Return to Scripts