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

Changing color of text found with regex

Explorer ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Hi,

I have multiple text layers in the document. I would like to filter through the contents of each text layer with regex and change the color of the found result.

In the example below I would like to find all the hastags in the text layer and change the color to blue.

Example:

This is a really long piece of text copy and #hashtag more copy here #anotherhastag #hashtagNo3

I've written a few scripts for indesign that involve GREP(regex) and it's fairly simple to change the color of the found results. I can't seem to find a solution for this in photoshop.

Thanks

TOPICS
Actions and scripting

Views

5.4K

Translate

Translate

Report

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
Adobe
Community Expert ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

I recommend abandoning the idea to do this in Photoshop, Indesign is oriented towards sophisticated text editing, so better to do it there.

In Photoshop changing parts of text within a Type Layer necessitates using AM code that can become quite unwieldy in my experience.

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Thanks for the quick response.Unfortunately, I have to use photoshop for this job. So I'm stuck with photoshop. By "AM code" do you mean action manager? Any pointers in that direction will be very helpful.

Unfortunately, I can only use photoshop for this job. So I'm stuck with photoshop. By "AM code" do you mean action manager? Any pointers in that direction will be very helpful.

Thanks

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Yes, I meant Action Manager code.

Try recording changing the color of one word in a larger text in a Type Layer with ScriptingListener.plugin and see how well manageable the resulting code seems to you.

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

I forgot to add: If there is any possibility that some parts within the type layer vary at all with regard to type properties (size, leading, font etc.) do include some such varying elements in your test.

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Will give that a shot. Thank you.

One thing I am stumbling upon in my tests is finding a word with regex and affecting just those results. Any tips on how I would go about that? For example, in a regex search like this "foundText" ends up as just plain text. I can't seem to affect the properties of that "foundText". Like color size etc. Is this the right approach? Is there a better way?

var foundText = textLayer.match(new RegExp("#hashtag", "i"))

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

The foundText (the result of the match) is a String, it is not part of the actual Type Layer.

Votes

Translate

Translate

Report

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
Guide ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Here is an example changing text when the text layer is selected. Changing colour of a section of text has been done in the past by xbytor

and he might chip in, but I would not attempt it!

if(activeDocument.activeLayer.kind == LayerKind.TEXT){

var textContent = activeDocument.activeLayer.textItem.contents;

activeDocument.activeLayer.textItem.contents = textContent.replace(/mine/ig,"his");

}

Votes

Translate

Translate

Report

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
Advisor ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Somebody mention me?

SourceForge is acting up so you will need to download xtools:

SourceForge

The files of interest are xtools/xlib/Text.jsx  and xtools/xlib/TextTest.jsx. It can be done but it requires a bit of work.

Here is the relevant code from TextTest.jsx that shows you how it's done.

var layer = doc.layers[layerName];
  doc.activeLayer = layer;
  var opts = new TextOptions(layer.textItem);
  opts.contents = "123567875688\radsfasfasdfasdfasdf\n(&#^&^#$";

  // construct the styles
  var s1 = new TextStyle("ArialMT");
  var s2 = new TextStyle("Courier-Bold", 30, Text.toRGBColor(0, 255, 0));

  // this style will use the default font...
  var s3 = new TextStyle(undefined, 42, Text.toRGBColor(255, 0, 0));

  // superscript test
  var s0 = new TextStyle(s1);
  s0.baseline = PSString.superScript;

  // Now create the set of ranges to apply the styles over
  var ranges = new TextStyleRanges();
  ranges.add(new TextStyleRange(0, 1, s0));
  ranges.add(new TextStyleRange(1, opts.contents.length, s1));
  ranges.add(new TextStyleRange(5, 10, s2));
  ranges.add(new TextStyleRange(7, 15, s3));
  ranges.add(new TextStyleRange(25, undefined, s2));

  opts.ranges = ranges;
  Text.modifyTextLayer(doc, opts, doc.layers[layerName]);

As somebody said before, InDesign is a more appropriate tool.

Votes

Translate

Translate

Report

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 ,
Sep 27, 2017 Sep 27, 2017

Copy link to clipboard

Copied

Wow. Thanks for sharing these scripts. They are incredibly helpful. Very much appreciated.

Votes

Translate

Translate

Report

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 ,
Sep 27, 2017 Sep 27, 2017

Copy link to clipboard

Copied

Question: What is the best way for me to get the text ranges from the text layer with a regex search. My current solution returns a string which isn't very helpful. Is regex the right approach or is there a better way?

Example:

Below are the contents of the text layer and I want to find all the hashtags.

This is a really long piece of text copy and #hashtag more copy here #anotherhastag #hashtagNo3

var foundText = textLayer.match(new RegExp("\S*#(?:\[[^\]]+\]|\S+)", "i")) 

Votes

Translate

Translate

Report

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
Enthusiast ,
Sep 27, 2017 Sep 27, 2017

Copy link to clipboard

Copied

I would use something like "IndexOf" but this will be more than 1 line of code.

Votes

Translate

Translate

Report

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
Guide ,
Sep 27, 2017 Sep 27, 2017

Copy link to clipboard

Copied

Something like...

var s = activeDocument.activeLayer.textItem.contents;

var re = /(?:^|\W)#(\w+)(?!\w)/g, match, matches = [];

while (match = re.exec(s)) {

  matches.push([[match[0].replace(/^\s+|\s+$/g,'')],[match.index+1],[match[0].replace(/^\s+|\s+$/g,'').length]]);

}

for(var a in matches){

    $.writeln("Word found = " + matches[0] + " start = " + matches[1] + " length = " +matches[2]);

    }

Votes

Translate

Translate

Report

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 ,
Sep 27, 2017 Sep 27, 2017

Copy link to clipboard

Copied

Thank you!

Votes

Translate

Translate

Report

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 ,
Oct 09, 2017 Oct 09, 2017

Copy link to clipboard

Copied

Hi xbytor2

Thank you for sharing all those scripts. I've been looking through the code and they've been a huge learning resource.

I tried to implement the TextTest.jsx script into my own version but I've been running into an issue.

When I run the below script I get this error: "Error: General Photoshop error occurred. This functionality may not be available in this version of Photoshop."

Is it something to do with this line in the script?

Text.modifyTextLayer(doc, opts, doc.layers[layerName]);

Here's the whole script.

//

// HashtagColor_v1.jsx

//

//============================================================================

//@includepath "~/Documents/xtools"

//

//@include "xlib/PSConstants.js"

//@include "xlib/stdlib.js"

//@include "xlib/Text.jsx"

//@include "xlib/Action.js"

//@include "xlib/xml/atn2xml.jsx"

//

function colorHashtag(doc) {

  var layerName = "Test Layer";

  var layer = doc.layers[layerName];

  doc.activeLayer = layer;

  var opts = new TextOptions(layer.textItem);

  opts.contents = layer.textItem.contents;

  //opts.contents = "123567875688\radsfasfasdfasdfasdf\n(&#^&^#$";

  // construct the styles

  var s1 = new TextStyle("ArialMT");

  var s2 = new TextStyle("Courier-Bold", 30, Text.toRGBColor(0, 255, 0));

  // this style will use the default font...

  var s3 = new TextStyle(undefined, 42, Text.toRGBColor(255, 0, 0));

  // superscript test

  var s0 = new TextStyle(s1);

  s0.baseline = PSString.superScript;

  // Now create the set of ranges to apply the styles over

  var ranges = new TextStyleRanges();

  ranges.add(new TextStyleRange(0, 1, s0));

  ranges.add(new TextStyleRange(1, opts.contents.length, s1));

  ranges.add(new TextStyleRange(5, 10, s2));

  ranges.add(new TextStyleRange(7, 15, s3));

  ranges.add(new TextStyleRange(25, undefined, s2));

  opts.ranges = ranges;

  Text.modifyTextLayer(doc, opts, doc.layers[layerName]);

}

Text.test = function(doc) {

  var doc;

  if (app.documents.length) {

    doc = app.activeDocument

  }

  colorHashtag(doc);

}

Text.test();

"HashtagColor_v1.jsx";

Votes

Translate

Translate

Report

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 ,
Oct 09, 2017 Oct 09, 2017

Copy link to clipboard

Copied

Upon further trial and error, I noticed that the "modifyTextLayer" function runs without issues on a text layer created by the script, but has issues with existing text layers created directly in the photoshop document.

So in your TextTest.jsx file, the newTextLayerDemo function creates a text layer. The rest of the script works when working with that text later. But in my version of the script, I am trying to work with an existing text layer in photoshop (ideally, the currently selected text layer), and I get that error.

Any thoughts or how to solve this?

Votes

Translate

Translate

Report

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
Enthusiast ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

So do you want to do something like Font Remaping script here: Magic scripts for Photoshop  but with searched text and colors instead font family?

I agree with others. This can be very difficult.

You need to:

1) read whole text layer action descriptor

2) find all your strings and position where they start and where is end of string

3) if text layer has multiple styles, there is list of these styles and index where they start and where they end. So you need to read this descriptor, make copy and change color and position indexes and then put this descriptors into list and this list replace in original layer descritor

4) finaly you can use "set descriptor" action manager code and change the layer.

Like this:

2017-09-26_184756.jpg

Before:

2017-09-26_183731.jpg

After:

2017-09-26_183925.jpg

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Wow. This is very helpful. Thank you. I'm going to give it a crack and see where I end up.
Clearly, this looks like a "long walk for a ham sandwich". But it'll be worth the learning experience. I guess??

I'll hit you up with questions as I go along.

Jarda, what app/plugin did you use in your images? It looks incredibly helpful. Where can i get that?

Thanks again, c.pfaffenbichler,  SuperMerlinand Jarda Bereza.

Votes

Translate

Translate

Report

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
Enthusiast ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

It's my own tool. Not public yet, but maybe it could be public soon.

It's based on this code: GitHub - JavierAroche/descriptor-info: JSX module to recursively get all the properties in an Action...

And this code:

descriptor to JSON is already buil-in in Photoshop · Issue #10 · JavierAroche/descriptor-info · GitH...

So this should help you. You also can explore my script with align to baseline and text columns. I am getting here descriptor, changing it and then setting back. Magic scripts for Photoshop

Votes

Translate

Translate

Report

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 ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

Great. Thanks much,

Those are some great scripts. Congrats.

Votes

Translate

Translate

Report

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
Contributor ,
Sep 26, 2017 Sep 26, 2017

Copy link to clipboard

Copied

I have a TODO line to implement low level text manipulation in my extension. But, as my collegues suggested, the AM structure is a  bedrock layer under the swamp guarded by hydras. I don't have enough patience and passion and not smart enough to get to the lowest layers.

I wish Adobe would start the whole PS source code from scratch again and implement it a way which is allowing us to properly script the app.

Thanks xbytor2 for the .jsx code, ill try it!

Votes

Translate

Translate

Report

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
Enthusiast ,
Oct 09, 2017 Oct 09, 2017

Copy link to clipboard

Copied

I will tell you secret.

You can:

0) read layer actionDescriptor

1) use native function for converting actionDescriptor into JSON

2) use eval() on JSON string and create javascript object

3) modify regular JS object with well known object opertions. You need to do same thing as in my screenshot.

4) convert JS object into JSON string with ".toSource()" method

5) convert JSON string into ActionDescriptor with native function

6) and finally you can put modified descriptor into "executeAction"

I think I will create small library for this workflow.

Votes

Translate

Translate

Report

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 ,
Oct 10, 2017 Oct 10, 2017

Copy link to clipboard

Copied

Thanks Jarda. This is way above my punching weight, but I'm going to give it a shot. I have managed to get up to step 4. But I am struggling with the step 5 and 6. At the moment I'm keeping it pretty basic: change the color of the entire text to red. Once I get the core functionality working I'll jump into figuring out how to change text ranges to a different color.

Bear in mind that I've written the script referencing different sources across the forms. So it's probably not the cleanest and most efficient way to do it.

Any help on how I can get steps 5 and 6 working would be great.

Thanks

#include "./helpers/JSON.jsx"

// 0) read layer actionDescriptor

var ref = new ActionReference();

ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));

var desc = executeActionGet(ref)

var convertDesc = new ActionDescriptor();

convertDesc.putObject(stringIDToTypeID("object"), stringIDToTypeID("object"), desc);

var jsonDesc = executeAction(stringIDToTypeID("convertJSONdescriptor"), convertDesc, DialogModes.NO);

// 1) use native function for converting actionDescriptor into JSON

jsonDesc.getString(stringIDToTypeID("json"));

// 2) use eval() on JSON string and create javascript object

var obj = JSON.parse(jsonDesc.getString(stringIDToTypeID("json")));

// 3) modify regular JS object with well known object opertions. You need to do same thing as in my screenshot.

obj["textKey"]["textStyleRange"][0]["textStyle"]["baseParentStyle"]["color"]["red"] = 255;

// 4) convert JS object into JSON string with ".toSource()" method

var objToStr = JSON.stringify(obj);

alert(objToStr);

// 5) convert JSON string into ActionDescriptor with native function

// 6) and finally you can put modified descriptor into "executeAction"

Votes

Translate

Translate

Report

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
Enthusiast ,
Oct 10, 2017 Oct 10, 2017

Copy link to clipboard

Copied

Here is first version of my tool:

GitHub - jardicc/ActionManagerHumanizer: This tool will reveal for you occult mystery of Photoshop A...

Works good for me. You probably will need CC 2015.5 and higher

Keep in mind that pure AM will be faster something about 10-30ms per conversion into JS object and back.

Votes

Translate

Translate

Report

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 ,
Oct 10, 2017 Oct 10, 2017

Copy link to clipboard

Copied

Wow! Thank you. I'll play with it now.

Much appreciated.

Votes

Translate

Translate

Report

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