Sunday, September 27, 2020

#1 2020-02-08 03:54:49 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

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:

Applescript:

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

Last edited by ldicroce (2020-02-09 03:49:30 am)

Offline

 

#2 2020-02-08 06:03:03 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11697
Website

Re: Changing content of paragraph "on the fly"

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

Applescript:

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

Last edited by StefanK (2020-02-09 03:26:08 am)


regards

Stefan

Offline

 

#3 2020-02-08 08:47:33 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 620

Re: Changing content of paragraph "on the fly"

ldicroce wrote:

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?



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.

Applescript:

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

Last edited by peavine (2020-02-08 10:56:32 am)


2018 Mac mini - macOS Catalina

Offline

 

#4 2020-02-08 09:55:47 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

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

Thanks again !!

Offline

 

#5 2020-02-08 10:15:03 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 620

Re: Changing content of paragraph "on the fly"

ldicroce wrote:

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.


2018 Mac mini - macOS Catalina

Offline

 

#6 2020-02-08 01:58:18 pm

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

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 .... ;-)


peavine wrote:
ldicroce wrote:

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.

Offline

 

#7 2020-02-08 07:25:10 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

ldicroce wrote:

Applescript:

       set mytext2 to (text from character 1 to character 5 of mytext)



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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#8 2020-02-09 01:41:43 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

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

Shane Stanley wrote:


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

Offline

 

#9 2020-02-09 02:55:08 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#10 2020-02-09 03:20:11 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4569

Re: Changing content of paragraph "on the fly"

@ldicroce

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

Applescript:

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

Offline

 

#11 2020-02-09 03:47:10 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

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



Yvan Koenig wrote:

@ldicroce

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

Applescript:

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

Last edited by ldicroce (2020-02-09 03:49:51 am)

Offline

 

#12 2020-02-09 05:26:00 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

ldicroce wrote:


I want to replace the first "x" characters of each (long) paragraph.



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

Applescript:

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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#13 2020-02-09 10:31:27 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

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

Shane Stanley wrote:


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

Applescript:

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

Last edited by ldicroce (2020-02-09 10:31:52 am)

Offline

 

#14 2020-02-09 11:51:06 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4569

Re: Changing content of paragraph "on the fly"

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

Applescript:

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

Offline

 

#15 2020-02-09 04:26:56 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

You need to define two variables, something like:

Applescript:

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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#16 2020-02-10 12:50:15 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

Thanks to all. Learning more and more ...
L.


Yvan Koenig wrote:


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

Offline

 

#17 2020-02-10 01:44:31 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4569

Re: Changing content of paragraph "on the fly"

Shane Stanley wrote:

You need to define two variables, something like:

Applescript:

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




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

Offline

 

#18 2020-02-13 12:14:57 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

I didn't expect this!!!

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

Applescript:

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 ...

Applescript:

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

Offline

 

#19 2020-02-13 01:05:24 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

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.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#20 2020-02-13 07:55:29 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 620

Re: Changing content of paragraph "on the fly"

ldicroce wrote:

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



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

Last edited by peavine (2020-02-13 11:13:00 am)


2018 Mac mini - macOS Catalina

Offline

 

#21 2020-02-13 08:43:26 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 620

Re: Changing content of paragraph "on the fly"

To test something longer, I created a text file with 19000 paragraphs alternating the following:

OK
This line is too long


I then ran the following scripts in Script Geek with only 1 repetition:

Applescript:

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

tell current application to set myText to read file "Save:Temp:TestFile.txt"

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

Applescript:

set myText to read file "Save:Temp:TestFile.txt"

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

The results reported by Script Geek were:

ApplescriptObjC  -   0.27 seconds
Basic AppleScript  -   11.84 seconds

This surprised me, so I ran the both scripts in Script Editor. They worked as expected and the times reported by Script Geek seemed ballpark correct.

BTW, the following line only took 4 milliseconds to run:

Applescript:

set myText to read file "Save:Temp:TestFile.txt"

Last edited by peavine (2020-02-13 11:13:20 am)


2018 Mac mini - macOS Catalina

Offline

 

#22 2020-02-13 11:17:22 am

ldicroce
Member
Registered: 2017-11-25
Posts: 206

Re: Changing content of paragraph "on the fly"

Thanks !
I got similar results with my new iMac. The results I reported earlier were done my my laptop which is older.
L.

peavine wrote:
ldicroce wrote:

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


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

Last edited by ldicroce (2020-02-14 01:15:25 am)

Offline

 

#23 2020-02-13 08:18:36 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6460

Re: Changing content of paragraph "on the fly"

peavine wrote:

ApplescriptObjC  -   0.27 seconds
Basic AppleScript  -   11.84 seconds



I suspect that latter figure would come down a lot if you used the script object technique, but probably not to near that of the regex approach.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#24 2020-02-13 09:54:14 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 620

Re: Changing content of paragraph "on the fly"

Thanks Shane for the response. I'm not familiar with the script-object technique and google was of little help. I did try utilizing the a-reference-to operator as suggested in the ASLG:

Applescript:


set myText to (paragraphs of (read file "Save:Temp:TestFile.txt"))
set myTextRef to a reference to myText

repeat with aParagraph in myTextRef
   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 myTextRef as text
set text item delimiters to TID
theResult

Utilizing the same text file as before, this script took 0.31 seconds in Script Geek, which is certainly surprising. Just to check, I ran this script in Script Editor, and it worked as expected and took less than a second to complete.

Last edited by peavine (2020-02-14 08:31:28 am)


2018 Mac mini - macOS Catalina

Offline

 

#25 2020-02-16 12:29:02 am

CK
Member
From:: UK
Registered: 2018-11-04
Posts: 143

Re: Changing content of paragraph "on the fly"

peavine wrote:

Thanks Shane for the response. I'm not familiar with the script-object technique and google was of little help. I did try utilizing the a-reference-to operator as suggested in the ASLG:

They're essentially the same technique: the list object being iterated over is passed into the repeat loop by reference, which confers two things: 1. the contents of the list is never evaluated in its entirety as it would be normally.  Instead each item is evaluated only as and when its data is retrieved; and 2. an object's data passed by value has had a copy of its data made, that serves as a snapshot of what that data looked like at that point in time.  As it's a copy, it means that any changes one makes to these data do not affect the original source.  However, data passed by reference doesn't copy the data; it passes the script a pointer to the address at which the data resides.  Therefore, when we access these data, they'll always reflect the data in its most current state; and any changes we make will be to the original source data.

On top of this, access times for list items passed by reference in AppleScript are--as you've seen--much, much quicker.  Here's another way to achieve the same thing:

Applescript:

set f to "/tmp/text.poo"
set sentences to the paragraphs of (read f)

repeat with sentence in a reference to my sentences
       tell the sentence to if its length > 10 then ¬
               set the contents to text 1 thru 5
end repeat

set text item delimiters to linefeed
set textContent to the sentences as text
set eof of f to 0
write the textContent to f

It's practically identical to your script, but instead of creating a new variable to hold a reference to the list, I just created a reference to it in the declaration of the repeat loop.  Here, the reference was created by the word my, which would have been sufficient for speed gains had we not needed to alter the contents of the original list.  To make changes, though, a reference to is necessary, or one can use a script object:

Applescript:

script
       property path: "/tmp/text.poo"
       property list: paragraphs of (read path)
end script

tell the result
       repeat with chunk in a reference to its list
               tell the chunk to if its length > 10 then set the contents to text 1 thru 5
       end repeat

       set my text item delimiters to linefeed
       set textContent to its list as text
       set eof of (its path) to 0
       write the textContent to its path
end tell

I got my powers of 2 wrong when creating my text.poo file, which accidentally ended up containing 256,000 lines.  It only took about three seconds to read from and write it back to the file.

On a minor note, I've observed virtually everyone on this site religiously saving the old tids and then restoring them back afterwards, which I get the sense is something being doing because everyone else is seen to do it.  It really isn't necessary.  I think Shane's gone over this before, but it's a left-over mantra from back when scripts used to all run within a single AppleScript instance.  Now, at least for Script Editor, Script Debugger, and any program calling out to osascript (Alfred, BTT, Keyboard Maestro), this is not the case.  The one program I'm aware of (because I use it) that does run successive scripts in a single instance is FastScripts.

Regardless, I would say that a better Good Practice habit to get into would be to forget about storing and resetting them, but always be conscientious to explicitly set the tids immediately before any line in a script that splits text using text items, or joins list items through coercion to text.  It uses fewer lines of code; is more readable; it ensures one always stays aware of when these text transformations are taking place; and it alleviates any need to worry about someone else's script, and whether or not they could have "forgotten" to reset their tids, leaving one free to focus on taking care of their own code in front of them.

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)