Skip to main content
Community Expert
December 16, 2025
Question

Script that converts selected text to a GREP find - Experimental script

  • December 16, 2025
  • 2 replies
  • 394 views

I started working on this script some time ago and it's since fallen to the wayside - I'm not using it. But I was tinkering around some unused and unfinished script projects 

 

I've taken it as far as I can go in terms of a learning curve for me - if anyone wants it or wants to tinker with it and make it better feel free.


All it was meant to do is give a starting point to a GREP search for people not familiar with GREP to give them a leg up on the starting point of the GREP. 

But I feel it could be more robust.

 

#target indesign

(function () {

    if (app.documents.length === 0) {
        alert("No document open.");
        return;
    }

    if (app.selection.length === 0 || !app.selection[0].hasOwnProperty("contents")) {
        alert("Please select some text.");
        return;
    }

    var txt = app.selection[0].contents;
    var grep = "";

    var i = 0;

    function isDigit(c) { return /\d/.test(c); }
    function isLower(c) { return /[a-z]/.test(c); }
    function isUpper(c) { return /[A-Z]/.test(c); }
    function isLetter(c) { return /[A-Za-z]/.test(c); }
    function isSpace(c) { return /\s/.test(c); }

    while (i < txt.length) {
        var c = txt[i];

        // DIGITS (collapse runs)
        if (isDigit(c)) {
            var start = i;
            while (i < txt.length && isDigit(txt[i])) i++;
            var count = i - start;
            grep += (count === 1) ? "\\d" : "\\d{" + count + "}";
            continue;
        }

        // LOWERCASE LETTERS
        if (isLower(c)) {
            var start = i;
            while (i < txt.length && isLower(txt[i])) i++;
            var count = i - start;
            grep += (count === 1) ? "[a-z]" : "[a-z]{" + count + "}";
            continue;
        }

        // UPPERCASE LETTERS
        if (isUpper(c)) {
            var start = i;
            while (i < txt.length && isUpper(txt[i])) i++;
            var count = i - start;
            grep += (count === 1) ? "[A-Z]" : "[A-Z]{" + count + "}";
            continue;
        }

        // SPACES
        if (isSpace(c)) {
            while (i < txt.length && isSpace(txt[i])) i++;
            grep += "\\s+";
            continue;
        }

        // ESCAPED GREP METACHARACTERS
        if (/[\\.^$*+?()[\]{}|]/.test(c)) {
            grep += "\\" + c;
            i++;
            continue;
        }

        // EVERYTHING ELSE (commas, hyphens, slashes, etc.)
        grep += c;
        i++;
    }

    // Push to Find GREP
    app.findGrepPreferences = NothingEnum.nothing;
    app.findGrepPreferences.findWhat = grep;

    alert("Generated GREP:\n\n" + grep);

})();

 
This is another iteration of the same thing 

#target indesign

(function () {

    if (app.documents.length === 0) {
        alert("No document open.");
        return;
    }

    if (app.selection.length === 0 || !app.selection[0].hasOwnProperty("contents")) {
        alert("Please select some text.");
        return;
    }

    var txt = app.selection[0].contents;
    var grep = "";
    var i = 0;

    function isDigit(c) { return /\d/.test(c); }
    function isLower(c) { return /[a-z]/.test(c); }
    function isUpper(c) { return /[A-Z]/.test(c); }
    function isLetter(c) { return /[A-Za-z]/.test(c); }
    function isSpace(c) { return /\s/.test(c); }

    while (i < txt.length) {
        var c = txt[i];

        /* =========================
           NUMBERS (smart handling)
           ========================= */

        if (isDigit(c)) {
            var start = i;
            while (i < txt.length && /[\d,.]/.test(txt[i])) i++;
            var token = txt.substring(start, i);

            // Comma-grouped number
            if (/^\d{1,3}(,\d{3})+$/.test(token)) {
                grep += "\\d{1,3}(,\\d{3})*";
                continue;
            }

            // Decimal number
            if (/^\d+(\.\d+)?$/.test(token)) {
                grep += "\\d+(\\.\\d+)?";
                continue;
            }

            // Plain digits
            grep += "\\d{" + token.replace(/\D/g, "").length + "}";
            continue;
        }

        /* =========================
           LETTERS
           ========================= */

        if (isLower(c)) {
            var start = i;
            while (i < txt.length && isLower(txt[i])) i++;
            grep += "[a-z]{" + (i - start) + "}";
            continue;
        }

        if (isUpper(c)) {
            var start = i;
            while (i < txt.length && isUpper(txt[i])) i++;
            grep += "[A-Z]{" + (i - start) + "}";
            continue;
        }

        /* =========================
           SPACES
           ========================= */

        if (isSpace(c)) {
            while (i < txt.length && isSpace(txt[i])) i++;
            grep += "\\s+";
            continue;
        }

        /* =========================
           ESCAPED METACHARACTERS
           ========================= */

        if (/[\\.^$*+?()[\]{}|]/.test(c)) {
            grep += "\\" + c;
            i++;
            continue;
        }

        /* =========================
           EVERYTHING ELSE
           ========================= */

        grep += c;
        i++;
    }

    app.findGrepPreferences = NothingEnum.nothing;
    app.findGrepPreferences.findWhat = grep;

    alert("Generated GREP:\n\n" + grep);

})();



2 replies

Kasyan Servetsky
Legend
December 16, 2025

Thanks for posting it!

By the way, the isLetter function is defined, but is never called.

— Kas

Community Expert
December 16, 2025

Good spot you’re right 
isLetter() is currently unused.
It was left in intentionally for a follow-up version that collapses mixed-case words into a single GREP token. Safe to remove for now, or wire it in as a mixed-case handler.

This is what happens when you abandon things I guess 😄 

m1b
Community Expert
Community Expert
December 16, 2025

Hi @Eugene Tyson thanks for sharing. It's a great idea and I'm sure it was fun to code. Your algorithm tends to generate grep that is very prescriptive. An improvement (an exercise for someone?) could be to read two lists compiled by the user: match all the strings in this list A, and match none of the strings in list B. This would give the grep generator a lot more to focus on, but I fear the coding would not be trivial.

- Mark

 

(As a complement to Eugene's script, I would heartily recommend @Peter Kahrel's wonderful Grep Editor due to its preview capability.)

Community Expert
December 16, 2025

Oh @Peter Kahrel GREP editor is a wonder. I use it regularly.

 

I just wanted to see if it was possible to select some text and generate some basic GREP with it - as some people I know don't use GREP or know how to do it and it's a bit complex for some. 

So I thought of maybe a little bit to get started with - learn as you go stuff. 

 

But yes - there are better solutions 😄 

m1b
Community Expert
Community Expert
December 16, 2025

Actually, Eugene, I don't know of any better solutions for what you aimed to do with this script. I think it's a brilliant idea and I'd love to see someone take it to the next level, as you hinted at in your post. It would be a really cool way for a non-grep savvy user to get a starting point.

 

Now that I think about it, all you plug-in developers out there: why not create a plug-in that access a suitable LLM to create the grep? User would type:

Match "x" or "y" or "z" unless it is preceded by "a" or "b" or "c"

 and chatGPT gave me this:

(?<![abc])[xyz]

I mean, that would be great for beginners to grep.