Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Is it possible to use Grep pattern with IndexOf()?

Explorer ,
Apr 07, 2023 Apr 07, 2023

I use this code to find and select the next occurrence of a search string from cursor point, is it possible to do this with grep search patterns?

 

var doc = app.activeDocument;
var insertionPoint = doc.selection[0].insertionPoints[0];

// Get the text content following the insertion point
var text = insertionPoint.parent.characters.itemByRange(insertionPoint.index + 1, -1).contents;

// Convert the text content to a string
var textString = new String(text);

// Define the search string
var searchString = "ali";

// Find the next occurrence of the search string from the insertion point
var nextSearchString = textString.indexOf(searchString);

// Check if the search string is found
if (nextSearchString >= 0) {
// If found, move the insertion point to the next search string
foundtext = insertionPoint.parent.characters.itemByRange(insertionPoint.index + 1 + nextSearchString, insertionPoint.index + 1 + nextSearchString + searchString.length - 1);

// Select the next search string
foundtext.select();

}

 

TOPICS
Scripting
900
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Apr 07, 2023 Apr 07, 2023

Or if you just want to select the next found instance of the grep?

var doc = app.activeDocument;
var insertionPoint = doc.selection[0].insertionPoints[0];

// Get the text content following the insertion point
var textFromCursor = insertionPoint.parent.characters.itemByRange(insertionPoint.index + 1, -1);

// reset grep prefs
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;

// the find grep (note: must escape backslash)
app.findGrepPreferences.find
...
Translate
Community Expert ,
Apr 07, 2023 Apr 07, 2023

Hi @ali u, yes it is possible, if I understand you correctly. See below. You just set the findWhat to a grep and set the changeTo, and run the script. Your code to get the text from the cursor position seems to work fine (I just removed contents because we want a Text object not a String—Text objects have findGrep and changeGrep methods).

- Mark

function main() {

    var doc = app.activeDocument;
    var insertionPoint = doc.selection[0].insertionPoints[0];

    // Get the text content following the insertion point
    var textFromCursor = insertionPoint.parent.characters.itemByRange(insertionPoint.index + 1, -1);
    
    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    // the find grep (note: must escape backslash)
    app.findGrepPreferences.findWhat = '\\bali\\b';

    // the change string
    app.changeGrepPreferences.changeTo = 'Ali';

    // do this if you want to process the results yourself
    var found = textFromCursor.findGrep();

    // do this if you just want to make the changes
    textFromCursor.changeGrep();
    
    alert(found[0].length + ' found.');

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Find Grep From Cursor Position');

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 07, 2023 Apr 07, 2023

Or if you just want to select the next found instance of the grep?

var doc = app.activeDocument;
var insertionPoint = doc.selection[0].insertionPoints[0];

// Get the text content following the insertion point
var textFromCursor = insertionPoint.parent.characters.itemByRange(insertionPoint.index + 1, -1);

// reset grep prefs
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;

// the find grep (note: must escape backslash)
app.findGrepPreferences.findWhat = '\\bali\\b';

// the change string
app.changeGrepPreferences.changeTo = 'Ali';

// do this if you want to process the results yourself
var found = textFromCursor.findGrep();

found[0][0].showText();
found[0][0].select();
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2023 Apr 10, 2023

@m1b 

Thank you very much, this does what I want. I was wondering if it is somehow possible to use grep patterns with IndexOf() but I guess thats not possible, and probably not needed.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 10, 2023 Apr 10, 2023

@ali u, in javascript indexOf is a method of String (and some others) which is a Javascript native object. But indexOf isn't a method of Text, which is an Indesign DOM object. In your case you were getting the "contents" of the Text, which returns a String, and then you can use indexOf with that. You were already using the itemByRange method of Text, which seems appropriate to me. I don't quite understand where you would use indexOf and grep together. In native Extendscript you can use search method of String with a RegExp, or the exec method of a RegExp with a string (eg. myStory.contents). As usual, there are various ways of achieving the same goal.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2023 Apr 10, 2023

@m1bif you have time can you explain why there are two [0]'s, i would've thought there is only one array that is the list of found instances of search string?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 10, 2023 Apr 10, 2023

@ali u that's a good question! I was surprised by that, too. The results of textFromCursor.findGrep sit inside an Array with only that one element, with the actual results inside this array. This is not the normal result—normally it would be as you say, a single level array of findGrep results. The only thing I noticed, which doesn't explain why though, is that doing textFromCursor.parentTextFrames returns a similar result (an array with only one element which is an array of text frames). Performing, say insertionPoint.parent.texts[0].findGrep(), returns a normal array of results, so perhaps it is something that happens due to the call to Text.characters.itemByName.

 

Sorry I don't know. Might even be a bug.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 11, 2023 Apr 11, 2023

thank you very much, i guess there are mysteries everywhere 🙂

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2023 Apr 11, 2023

Or maybe because of itemByRange()? Like when you use everyItem()?

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2023 Apr 11, 2023

@Robert at ID-Tasker, yes that was my thought at first, too. But there isn't strong evidence. In the case of findGrep with everyItem(), you can see the find results grouped logically. I just don't know what the high-level grouping of one group would mean in the context of a range of Characters.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2023 Apr 11, 2023

So there is only found[0] and all the results are there?

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 11, 2023 Apr 11, 2023
LATEST

Yep.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 08, 2023 Apr 08, 2023

Is "insertionPoint.index + 1" really needed to address character after it?

As InsertionPoint always preceedes Character - you can use its index as an index of the next character? Or in JS it works differently? 

Or am I missing something? 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 08, 2023 Apr 08, 2023

Hi Robert, no you're correct about how it works. The reason for adding +1 to the index here is so that the script will find the next instance if the selected text is already a found instance. For example, if I run the above script and it finds and selects the first "ali", without the +1, subsequent executions of the script will keep finding that same instance of "ali".

 

The downside, as you noticed, is that if the user puts the cursor literally at the start of an instance of "ali" and runs script it won't find that instance, because it starts searching from the "l". However, I think this is acceptable in most cases. To fix it, we'd need to remove the +1, and check if the found instance is selected, and if so, ignore it and go to the next.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 08, 2023 Apr 08, 2023

Thanks for the clarification 🙂

 

But OP's request is "from cursor point"?

So Loop should "move" cursor AFTER processing 1st occurrence - not before? 

 

Ok, you may be right @m1b  ... or not😉 

 

@ali u could you please clarify your request?

Do you want to find & change ALL instances of "ali" - including the one right after the InsertionPoint - or ignore the 1st one and only change the rest? 2nd, 3rd, ...

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2023 Apr 10, 2023

@Robert at ID-Tasker 

I only want to find the first one after cursor once, including the one right after the InsertionPoint, so +1 is not needed in my situation. I wasn't even avare in my original code that it won't find the first one if it is right after the InsertionPoint, usually the cursor won't be there, but thanks for pointing that out.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines