Highlighted

Find the line of a character in a paragraph text

New Here ,
Oct 13, 2020

Copy link to clipboard

Copied

I have a paragraph text, and I need to find the number of the line of a given word.

 

By word, I mean that I have numbers in the midle of the text, they never repeat, and they go from 2 to 100+ (the end number can vary, depending on the text I'm using).

 

Any idea how can I find the number of the line where this character is?

Assuming the text style is constant throughout, there is a solution I've used in some of my scripts but it's rather convoluted. It's easier to do with scripting but here's a solution using expressions. Whether it will work with whatever reason you want to use the line number for I can't say.

Basically you find the height of the text on one and two lines, then use that to calculate the number of lines of text when everything after the first instance of the search word has been found.

If you need the original VERSES layer to be visisble and untouched, you'll need to make a dupe of that layer (so it has same style) which can be turned off and has this expression on the source text:

if (time == 0) "hello";
else if (time >0 && time < 2) "hello\nworld";
else {
	myText = thisComp.layer("VERSES").text.sourceText;
	search = "help";
	ind = myText.indexOf("help");
	if (ind == -1) "";
	else myText.substring(0, ind+search.length);
}

Then you'll need this expression somewhere that will give you the line number from the info produced by that last expression:

theLayer = thisComp.layer("VERSES 2");
firstLine = theLayer.sourceRectAtTime(t = 0, includeExtents = false).height;
secondLine = theLayer.sourceRectAtTime(t = 1, includeExtents = false).height - firstLine;
searchLine = theLayer.sourceRectAtTime(t = 2, includeExtents = false).height;
theLine = Math.floor((searchLine - firstLine)/secondLine) + 1;

It's not ideal but it does mostly work, with some exceptions like if you had only line returns or lower case characters at the top of the text that throw off the calculations. With scripting you can more discretely make these changes, grab the values, make your calculations then restore the original state.

TOPICS
Expressions, How to, Scripting

Views

102

Likes

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

Find the line of a character in a paragraph text

New Here ,
Oct 13, 2020

Copy link to clipboard

Copied

I have a paragraph text, and I need to find the number of the line of a given word.

 

By word, I mean that I have numbers in the midle of the text, they never repeat, and they go from 2 to 100+ (the end number can vary, depending on the text I'm using).

 

Any idea how can I find the number of the line where this character is?

Assuming the text style is constant throughout, there is a solution I've used in some of my scripts but it's rather convoluted. It's easier to do with scripting but here's a solution using expressions. Whether it will work with whatever reason you want to use the line number for I can't say.

Basically you find the height of the text on one and two lines, then use that to calculate the number of lines of text when everything after the first instance of the search word has been found.

If you need the original VERSES layer to be visisble and untouched, you'll need to make a dupe of that layer (so it has same style) which can be turned off and has this expression on the source text:

if (time == 0) "hello";
else if (time >0 && time < 2) "hello\nworld";
else {
	myText = thisComp.layer("VERSES").text.sourceText;
	search = "help";
	ind = myText.indexOf("help");
	if (ind == -1) "";
	else myText.substring(0, ind+search.length);
}

Then you'll need this expression somewhere that will give you the line number from the info produced by that last expression:

theLayer = thisComp.layer("VERSES 2");
firstLine = theLayer.sourceRectAtTime(t = 0, includeExtents = false).height;
secondLine = theLayer.sourceRectAtTime(t = 1, includeExtents = false).height - firstLine;
searchLine = theLayer.sourceRectAtTime(t = 2, includeExtents = false).height;
theLine = Math.floor((searchLine - firstLine)/secondLine) + 1;

It's not ideal but it does mostly work, with some exceptions like if you had only line returns or lower case characters at the top of the text that throw off the calculations. With scripting you can more discretely make these changes, grab the values, make your calculations then restore the original state.

TOPICS
Expressions, How to, Scripting

Views

103

Likes

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
Oct 13, 2020 0
Adobe Community Professional ,
Oct 13, 2020

Copy link to clipboard

Copied

You can retrieve the source text from a layer but you can't tell how the lines will break so there is no way I know of to figure out what line a word is on. Font size, scale, and the size of the text area are all variables that have no direct relationship to the word count. I'm not even sure you can efficiently count words. 

Likes

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
Reply
Loading...
Oct 13, 2020 0
New Here ,
Oct 13, 2020

Copy link to clipboard

Copied

Thanks for your reply Rick. Count words is possible, just in case someone ever need it:

(replace "VERSES" with the name of the layer where your text is)

 

myText = thisComp.layer("VERSES").text.sourceText;

myText = myText.replace(/(^\s*)|(\s*$)/gi,"");

myText = myText.replace(/[ ]{2,}/gi," ");

myText = myText.replace(/\n /,"\n");

myText = myText.split(' ').length;

Likes

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
Reply
Loading...
Oct 13, 2020 0
Most Valuable Participant ,
Oct 13, 2020

Copy link to clipboard

Copied

I concur with Rick - unless you do all the formatting yourself, there is no way to access those things. To efficiently work with such stuff you have to use conventional line text, not auto-flowing paragraph text.

 

Mylenium

Likes

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
Reply
Loading...
Oct 13, 2020 0
New Here ,
Oct 13, 2020

Copy link to clipboard

Copied

Thanks Mylenium!

AE know where a character is on the text, it knows how to find a line ... I wish there was a way to cross that information.

Likes

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
Reply
Loading...
Oct 13, 2020 0
Engaged ,
Oct 14, 2020

Copy link to clipboard

Copied

Assuming the text style is constant throughout, there is a solution I've used in some of my scripts but it's rather convoluted. It's easier to do with scripting but here's a solution using expressions. Whether it will work with whatever reason you want to use the line number for I can't say.

Basically you find the height of the text on one and two lines, then use that to calculate the number of lines of text when everything after the first instance of the search word has been found.

If you need the original VERSES layer to be visisble and untouched, you'll need to make a dupe of that layer (so it has same style) which can be turned off and has this expression on the source text:

if (time == 0) "hello";
else if (time >0 && time < 2) "hello\nworld";
else {
	myText = thisComp.layer("VERSES").text.sourceText;
	search = "help";
	ind = myText.indexOf("help");
	if (ind == -1) "";
	else myText.substring(0, ind+search.length);
}

Then you'll need this expression somewhere that will give you the line number from the info produced by that last expression:

theLayer = thisComp.layer("VERSES 2");
firstLine = theLayer.sourceRectAtTime(t = 0, includeExtents = false).height;
secondLine = theLayer.sourceRectAtTime(t = 1, includeExtents = false).height - firstLine;
searchLine = theLayer.sourceRectAtTime(t = 2, includeExtents = false).height;
theLine = Math.floor((searchLine - firstLine)/secondLine) + 1;

It's not ideal but it does mostly work, with some exceptions like if you had only line returns or lower case characters at the top of the text that throw off the calculations. With scripting you can more discretely make these changes, grab the values, make your calculations then restore the original state.

Likes

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
Reply
Loading...
Oct 14, 2020 0
New Here ,
Oct 14, 2020

Copy link to clipboard

Copied

This. Is. Amazing. Thank you so much Paul! I did several tests in diferent scenarios and texts, and it works. I though I knew expressions enough, but this is beyond me for now.

 

So, if I want the search for the word to start after ie. character 3 in the thext, cna I just change the 0 on this line to 3?

else myText.substring(0, ind+search.length);

 

Likes

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
Reply
Loading...
Oct 14, 2020 0
Engaged ,
Oct 14, 2020

Copy link to clipboard

Copied

So this line finds the index (i.e. the start character) of the search string on the text):

ind = myText.indexOf("help");

then this line creates a version of the textfrom the start (0) up to the found index, then adds the length of the search string to it so it's all the text from the start to the end of the search string:

else myText.substring(0, ind+search.length);

 

So I don't think changing that will do what you want. You want to ignore the first 3 characters in the string when doing the search? like because those first three characters also contain the search string?

 

I believe indexOf accepts a second parameter which defines where the search starts from, so maybe this is what you're looking for?

ind = myText.indexOf(search, 3);

 

There's also lastIndexOf() if you just want to find the last instance of the search term in the text.

 

It's not all that complex really. The first expression is creating something similar to three sourceText keyframes, one at 0 secs that just contains one line of text, one between 0 and 2 secs that contains two lines of text, and one at 2 secs onwards that contains all the text up to and including the search word.

Then the second expression grabs the height of the text at those three times, subtracts the first height from the second to find the typical height of a line plus the distance between the lines (which a single line on its own doesn't have), again subtracts the first line height from the bigger block of text that goes up to and includes the search word, divides what remains by the worked out height of a single line, then adds 1 for the removed first line.

Likes

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
Reply
Loading...
Oct 14, 2020 0
Engel_75 LATEST
New Here ,
Oct 14, 2020

Copy link to clipboard

Copied

Got it. Thanks for the explanation. Using the start offset on indexOf makes a lot of sense.

Likes

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
Reply
Loading...
Oct 14, 2020 0