Using AppleScript to find and set an AS variable collects TMI (too much information)

Hello!

I create many text documents in BBEdit every day, and I have to extract and send variables over to Keyboard Maestro to paste in a web form. These documents start like this:

08:30-11:30 UWA

:: Item one
- the associated notes

:: Item two
- etc

I need to pull out variables:

StartTime: 08:30
EndTime: 11:30
ClientCode: UWA

I’ve been working with the following script:

set StartTime to “00:00”
set EndTime to “00:00”
set ClientCode to “AAA”

tell application “BBEdit”
set StartTime to find “(\A)([0-9]{2})(\:)([0-9]{2})” searching in text document 1 options {search mode:grep, wrap around:true} with selecting match
set EndTime to find “([0-9]{2})(\:)([0-9]{2})” searching in text document 1 options {search mode:grep, wrap around:false} with selecting match
set ClientCode to find “[A-Z]{3}” searching in text document 1 options {search mode:grep, wrap around:false} with selecting match
end tell

tell application “Keyboard Maestro Engine”
setvariable TicketTimeEntryBegin to StartTime
end tell

Running it, I keep getting the error:
“Can’t make characters 1 thru 5 of text document id 220 of application “BBEdit” into the expected type.”

Script Debugger tells me that variable StartTime has these three properties:
found: true
found object: characters 1 thru 5 of text document id 220
found text: “08:30”

So I’m getting the right found text “08:30” (and I’m getting the correct EndTime and Client Code), but there is a type mismatch when trying to get 08:30 over to a variable TicketTimeEntryBegin in Keyboard Maestro.

Now, when I use the following Execute AppleScript step in Keyboard Maestro to try to see what’s going on:

tell application “BBEdit”
find “(\A)([0-9]{2})(\:)([0-9]{2})” searching in text document 1 options {search mode:grep, wrap around:true} with selecting match
end tell

With: Save to variable: TicketTimeEntryBegin

the variable TicketTimeEntryBegin in Keyboard Maestro now contains:

found:true, found object:characters 1 thru 5 of text document id 220, found text:08:30

So it is getting the three properties of the variable mashed together.

How do I just get the found text 08:30, and not the rest?

Thanks!

  • eric

So, the result of find command is RECORD {found: true, found object: characters 1 thru 5 of text document id 220, found text: “08:30”}. You should request the key FOUND TEXT of find result:

set StartTime to found text of (find “(\A)([0-9]{2})(:)([0-9]{2})” searching in text document 1 options {search mode:grep, wrap around:true} with selecting match)

The same with other 2 variables.

Makes sense. Thank you so much!

If I might pile on…

given my document contents are as shown above:

08:30-11:30 UWA

:: Item one
- the associated notes

:: Item two
- etc

What would be the find expression to set a variable “TicketNotes” to everything after the first blank line (or the third line) to the end of the document?

Thanks!

Your not being very clear what range of text your looking for.
Maybe highlight it differently or insert some dummy text like

08:30-11:30 UWA

:: Item one

  • the associated notes >>>>—START CAPTURE ON NEXT LINE

:: Item two

  • etc

>>>>—END CAPTURE ON ABOVE LINE

Thanks. I realized all of my ticket notes always start on the 3rd line, and begin “::”. So I just used find to capture “::” to end of document.

I used the following:

“(?ms)::.*”

honestly I’m not 100% what the (?ms) does (copied from another script), but I think it is BBEdit’s Pattern modifiers:
m - allow ^ and $ to match at \r
s - allow . to match \r

Oh, I guess I do kinda know…

Eric’s original question has been answered, but I thought I would suggest alternate approaches FWIW. All of these use AppleScript rather than BBEdit to set the desired variables.

The first suggestion uses basic AppleScript but assumes that the date and client code are in the first line of the text document (which appears to be the case). This could also be done with text item delimiters but the following is simpler.

tell application "BBEdit" to set theText to contents of text document 1
set theText to first paragraph of theText
set startTime to text 1 thru 5 of theText --> "08:30"
set endTime to text 7 thru 11 of theText --> "11:30"
set clientCode to text 13 thru -1 of theText --> UWA

The second suggestion is a variant of the above, but it finds the time/client data on any line of the document (which is probably unnecessary):

use framework "Foundation"
use scripting additions

tell application "BBEdit" to set theText to contents of text document 1
set theString to current application's NSString's stringWithString:theText
set thePattern to "(?m)^\\d{2}:\\d{2}-\\d{2}:\\d{2}\\s\\w+$"
set theRange to theString's rangeOfString:thePattern options:(current application's NSRegularExpressionSearch)
set theText to (theString's substringWithRange:theRange) as text --> "08:30-11:30 UWA"
set startTime to text 1 thru 5 of theText --> "08:30"
set endTime to text 7 thru 11 of theText --> "11:30"
set clientCode to text 13 thru -1 of theText --> UWA

As to the OP’s second question, my suggestion is:

tell application "BBEdit" to set theText to contents of text document 1
set theList to paragraphs of theText
set {TID, text item delimiters} to {text item delimiters, linefeed}
set ticketNotes to (items 3 thru -1 of theList) as text
set text item delimiters to TID
return ticketNotes

This is all just SOLID GOLD for someone learning. I didn’t even think about having AppleScript search the text itself.

Any thoughts on what might be more efficient? Not that pulling out three variables is going to stress anything, but I’m curious.

Thanks!!

eric. I lengthened the text document to contain 167 paragraphs, and I edited your script to work on my computer. The test results were:

eric’s script - 12 milliseconds
peavine script one - 4 milliseconds
peavine script two - 3 milliseconds (with foundation in memory)
peavine script three - 3 milliseconds

My edit of your script, which refused to run otherwise, was:

tell application "BBEdit"
	set StartTime to found text of (find "([0-9]{2}):([0-9]{2})" searching in text document 1 options {search mode:grep, wrap around:true} with selecting match)
	set EndTime to found text of (find "([0-9]{2}):([0-9]{2})" searching in text document 1 options {search mode:grep, wrap around:true} with selecting match)
	set ClientCode to found text of (find "[A-Z]{3}" searching in text document 1 options {search mode:grep, wrap around:false} with selecting match)
end tell
set theInfo to StartTime & linefeed & EndTime & linefeed & ClientCode -- just for testing