Changing content of paragraph "on the fly"

I have a text in a variable which is composed by 2 (or more) paragraphs.
I would like to replace a complete paragraph (when it is too long) without converting the all initial string into a list. Is that possible?

The script below triggers an error:

set mytext to "Luciano" & linefeed & "Luciano_Luciano"
set countParagraph to count of paragraph of mytext
repeat with i from 1 to countParagraph
	if length of paragraph i of mytext > 10 then
		set mytext2 to (text from character 1 to character 5 of mytext)
		set (content of paragraph i of mytext) to mytext2 --> How to set the paragraph content?
	end if
end repeat

Split the text into paragraphs, then modify the single paragraphs and join them at the end.

contents of to modify the list is crucial when using the repeat with … in syntax

set mytext to "Luciano" & linefeed & "Luciano_Luciano"
set allParagraphs to paragraphs of mytext
repeat with aParagraph in allParagraphs
	if length of aParagraph > 10 then
		set contents of aParagraph to text 1 thru 5 of aParagraph -- edited
	end if
end repeat
set {TID, text item delimiters} to {text item delimiters, linefeed}
set theResult to allParagraphs as text
set text item delimiters to TID

ldicroce’s post has 2 requirements: that the contents of a paragraph be changed “on the fly” and that this be done without converting the initial string to a list.

Stefan’s script works “on the fly” but uses a list. My script below does not use a list (except to count paragraphs) but does not operate “on the fly”. Also, it’s slow because it concatenates text.

Stefan’s script works great and, FWIW, is the one I would use, although I’m sure ldicroce has a reason for his specific requirements.

set mytext to "Luciano" & linefeed & "Luciano_Luciano"

set myText2 to ""

set countParagraph to count paragraphs of mytext

repeat with i from 1 to countParagraph
	set aParagraph to paragraph i of mytext
	if length of aParagraph > 10 then
		set myText2 to myText2 & text 1 thru 5 of mytext & linefeed
	else
		set myText2 to myText2 & aParagraph & linefeed
	end if
end repeat

set myText2 to text 1 thru -2 of myText2

Thanks to both. I will check which of the two methods is faster.

Thanks again !!

ldicroce. You’re most welcome.

I enjoy playing around with Script Geek and tested Stefan’s and my script. With the text specified in line 1 of your original post, the two scripts were essentially equal as to time. I then substituted a string that probably contained 100 paragraphs, and Stefan’s script was (as expected) faster. The difference was about 10 percent.

Is good to know since the input string I am using as 19.000 paragraph !!!
Thanks again !
L.
PS: Maybe Shane will come up with some of this magic script that are even faster … :wink:

Are you sure that’s what you want? You’re replacing all long paragraphs with the first five characters of the first paragraph.

Yes! It won’t be 5 chars, it will be most likely 50.
It is part of larger project. I am using Ubersicht to display things on my monitor in a window-less and dynamic manner. A kind of personalised “Notification” system.
I have put some part (including my Calendar, To do…) together. See here:

https://funkyimg.com/i/326KH.jpg

I understand that, but your sample script will put the same five characters for every long paragraph. Is that what you wanted?

@ldicroce

I guess that Shane Stanley try to tell you that the correct code would be :

set mytext to "Luciano" & linefeed & "Lucyano_Luciano"
set allParagraphs to paragraphs of mytext
repeat with aParagraph in allParagraphs
	if length of aParagraph > 10 then
		set contents of aParagraph to text 1 thru 5 of aParagraph -- was wrongly mytext
	end if
end repeat
set {TID, text item delimiters} to {text item delimiters, linefeed}
set theResult to allParagraphs as text
set text item delimiters to TID
theResult

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 9 février 2020 10:19:37

Absolutely correct. Thanks Yvan.
I want to replace the first “x” characters of each (long) paragraph.

In that case you could use a regex search/replace:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions

set myText to "Luciano" & linefeed & "Lucyano_Luciano"
set myText to current application's NSString's stringWithString:myText
set myText to (myText's stringByReplacingOccurrencesOfString:"(.{5}).{6,}" withString:"$1" options:(current application's NSRegularExpressionSearch) range:{0, myText's |length|()}) as text

Thanks, even tough I do get everything the code does. But I will search for info on stringByReplacingOccurrencesOfString command.
Thanks !
L

I assumed that I understood what it did so I tried a more general syntax:

set beg to 5
set myString to "(.{" & beg & "}).{" & (beg + 1) & ",}"
set myText to (myText's stringByReplacingOccurrencesOfString:(myString) withString:"$1" options:(current application's NSRegularExpressionSearch) range:{0, myText's |length|()}) as text

Alas, it works with beg from 2 thru 7 but doesn’t with beg greater than 7.
What is wrong in my attempt ?

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 9 février 2020 18:51:01

You need to define two variables, something like:

set maxLen to 10 -- alowable length
set trimLen to 5 -- length to trim to
set myString to "(.{" & trimLen & "}).{" & (maxLen - trimLen + 1) & ",}"
set myText to (myText's stringByReplacingOccurrencesOfString:(myString) withString:"$1" options:(current application's NSRegularExpressionSearch) range:{0, myText's |length|()}) as text

Thanks to all. Learning more and more …
L.

Thank you Shane.
Now it’s clear.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 10 février 2020 08:44:24

I didn’t expect this!!!

1000 repetition of this, takes 5 seconds on my MacBook (2015).

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions
repeat 1000 times
	set myText to "Luciano" & linefeed & "Luciano_Luciano"
	set myText to current application's NSString's stringWithString:myText
	set myText to (myText's stringByReplacingOccurrencesOfString:"(.{5}).{6,}" withString:"$1" options:(current application's NSRegularExpressionSearch) range:{0, myText's |length|()}) as text
end repeat

While 100000 repetition of this takes 3 seconds. So, 2 order of magnitude faster !!
Is that true or I am doing something wrong …

repeat 100000 times
	set mytext to "Luciano" & linefeed & "Luciano_Luciano"
	set allParagraphs to paragraphs of mytext
	repeat with aParagraph in allParagraphs
		if length of aParagraph > 10 then
			set contents of aParagraph to text 1 thru 5 of aParagraph -- was wrongly mytext
		end if
	end repeat
	set {TID, text item delimiters} to {text item delimiters, linefeed}
	set theResult to allParagraphs as text
	set text item delimiters to TID
	theResult
end repeat

That sounds reasonable.

You’re only dealing with two paragraphs. I suspect you’ll see different results with 19,000, or even just a couple of thousand.

I ran the two scripts without modification in Script Geek and the timings on my computer were:

ApplescriptObjC - 1.54 seconds

Basic AppleScript - 1.36 seconds