Using "offset"

I’m in the process of setting up a new text-heavy website and recognize I need some scripted routines to automate the process. Assistance in the scripting appreciated.

The word processing is being done in Scrivener, an excellent Mac-only writing environment, superior to MS Word and similar environments. Scrivener exports into not only Word format but also HTML, and its automated HTML generates pretty good CSS. However, with 50 to 100 very similar documents I’d like them all to point to the same CSS style formating file where I can tweak the CSS standards beyond the typography possible in Scrivener.

Despite the fact I have very low level skills in AppleScript, I’ve created an AppleScript to open the HTML files in BBEdit and automate some standardization. As well this routine, it needs to go further. Here’s a fragment of coding that does work. It’s a simple search-and-replace routine.

tell application "BBEdit 6.5.3"
	activate
	replace "class=\"p1\"" using "class=\"issue\"" searching in text 1 of text window 1 options {search mode:literal, starting at top:false, wrap around:false, reverse:false, case sensitive:false, match words:false, extend selection:false}
end tell 

I need to amplify this to look for unpredictable stuff that sits between two predictable delimiters ” say, “<style” and “” and either replace all the stuff between the delimiters with something else, or remove the delimiters and the stuff in between.

I’ve been told by some I need to learn and use Regular Expressions (RegEx) to accomplish this. However, that’s something like learning to fly a jet fighter just to go down to the corner store for a litre of milk ” way too much power and complexity for a fairly simple task.

Others have told me “offset” tools in AppleScript will accomplish the task. I sense they may be right, but my knowledge of AppleScript syntax is so primitive I don’t know how to adapt the coding snippets they’ve supplied me ” specifically how to identify the two delimiters, how to identify what should replace what lies between the delimiters and how to get the code to work within BBEdit.

Here’s one of two “offset” routines I’ve been supplied. I need help in identifying whether this code is actually useful for the task at hand, and equally important, how to adapt it appropriately. My experiments have all run into inexplicable error messages. To repeat: how to identify the two delimiters, how to identify what should replace what lies between the delimiters and how to get the code to work within BBEdit, applying the routine to 50 and more HTML documents.

on run -- example
	display dialog "\"" & (GetSubText of "This is some testing text" from "some " to " text") & "\""
end run

to GetSubText of SomeText from StartItem to enditem
	(*
	get a substring from SomeText, from StartItem to EndItem
		parameters -	SomeText [mixed]: the text to get the substring from
				StartItem [mixed]: the starting item (or 1 for the beginning)
				EndItem [mixed]: the ending item (or -1 for the end)
		returns [text]:	the substring, or "" if not found
	*)
	set SomeText to SomeText as text
	if StartItem is in {1, "1", ""} then
		set Here to 1
	else
		offset of StartItem in SomeText
		if result is 0 then
			return ""
		else
			set Here to result + (length of StartItem)
		end if
	end if
	if enditem is in {-1, "-1", ""} then
		set There to -1
	else
		offset of enditem in (text Here thru -1 of SomeText)
		if result is 0 then
			return ""
		else
			set There to (Here + result) - 2
		end if
	end if
	return (text Here thru There of SomeText)
end GetSubText 

Much appreciated.

I think most scripters would use AppleScript’s text item delimiters to do what you want to do.

You might find these tutorials useful:

Tutorial for using AppleScript’s Text Item Delimiters

and

A Tutorial on Parsing HTML from a Web Site using AppleScript’s Text Item Delimiters

Hi,

additionally to Adam’s recommendations,
this is your subroutine with text item delimiters, behaving the same way including the 1 and -1 parameters


on run -- example
	display dialog "\"" & (GetSubText of "This is some testing text" from "some " to " text") & "\""
end run

to GetSubText of SomeText from StartItem to enditem
	copy SomeText to OrigText
	set TID to text item delimiters
	if StartItem is not 1 then
		set text item delimiters to StartItem
		try
			set SomeText to text items 2 thru -1 of SomeText as text
		end try
	end if
	if enditem is not -1 then
		set text item delimiters to enditem
		set SomeText to text item 1 of SomeText
	end if
	set text item delimiters to TID
	if SomeText is OrigText then return ""
	return SomeText
end GetSubText

I’ve moved a lot closer to my destination – to isolate random text in a BBEdit file between two delimiters and manipulate it in some way. I’m very new to AppleScript so much of this is likely laughably inefficient. The GetSubText handler in the heart of the following is not of my authorship, but it does isolate the intended text. (Thanks to Red Menace for the handler). However I’m stymied in figuring out how to take the results of these maneuvers over to the text in BBEdit.

Hints on how to make this code more efficient appreciated.

tell application "BBEdit 6.5.3"
	activate
	
	(* objective is to isolate a variable string of text between two predictable delimiters and then replace with a new standard  *)
	
	set SomeText to text 1 of text window 1 -- correctly fetches full text in current BBEdit window
	set StartItem to "<style type=\"text/css\">" -- first delimiter
	set enditem to "</style>" -- last delimiter
	set ChangeText to "xxx" -- the intended replacement string
	
end tell

(* AppleScript correctly sets Target to the variable string if "end tell" PRECEDES the following, but generates a "doesn't understand the GetSubText message" if "end tell" is moved after the following statement. Which is why I make a second call to BBEdit at the end of the script. *)

set Target to GetSubText of SomeText from StartItem to enditem -- correctly sets Target to the variable string

to GetSubText of SomeText from StartItem to enditem -- this handler does its job
	(*
	get a substring from SomeText, from StartItem to EndItem
		parameters -	SomeText [mixed]: the text to get the substring from
				StartItem [mixed]: the starting item (or 1 for the beginning)
				EndItem [mixed]: the ending item (or -1 for the end)
		returns [text]:	the substring, or "" if not found
	*)
	set SomeText to SomeText as text
	if StartItem is in {1, "1", ""} then
		set Here to 1
	else
		offset of StartItem in SomeText
		if result is 0 then
			return ""
		else
			set Here to result + (length of StartItem)
		end if
	end if
	if enditem is in {-1, "-1", ""} then
		set There to -1
	else
		offset of enditem in (text Here thru -1 of SomeText)
		if result is 0 then
			return ""
		else
			set There to (Here + result) - 2
		end if
	end if
	return (text Here thru There of SomeText)
end GetSubText

tell application "BBEdit 6.5.3"
	activate
	
	replace Target using ChangeText searching in text 1 of text window 1 -- has no effect on the active BBEdit window.
	
end tell

Hi There,

I’m not sure where you are having a problem. I opened the script, made a new text file in TextWrangler, Free version of BBEdit, and the script seems to work fine. With the following in the text

blah blah blah

I get

xxx

After running the script

Greetings

And I get the opposite, no change to the file, including trying your exact phrase as the only text within TextWrangler. Strange.

Thanks to prompts from Red_Menace, this problem is solved. The following not only works but is also more readable, more logical. Very satisfying to finally get this working.


tell application "BBEdit 6.5.3"
activate

(* objective is to isolate a variable string of text between two predictable delimiters and then replace with a new standard *)

set SomeText to text 1 of text window 1 -- correctly fetches full text in current BBEdit window
set StartItem to "<style type=\"text/css\">" -- first delimiter
set enditem to "</style>" -- last delimiter
set ChangeText to "xxx" -- the intended replacement string

tell me to set Target to GetSubText of SomeText from StartItem to enditem -- the "tell me" instruction informs AppleScript to look within the current script for the handler, not within the BBEdit document.

replace Target using ChangeText options {starting at top:true} searching in text 1 of text window 1 -- For this script to function it's critical to set the options to start searching for "Target" from the top.

end tell

to GetSubText of SomeText from StartItem to enditem -- this handler isolates the random text between the two delimiters. Written by Red_Menace, sometimes found at Mac dot com.
(*
get a substring from SomeText, from StartItem to EndItem
parameters -	SomeText mixed: the text to get the substring from
StartItem mixed: the starting item (or 1 for the beginning)
EndItem mixed: the ending item (or -1 for the end)
returns text:	the substring, or "" if not found
*)
set SomeText to SomeText as text
if StartItem is in {1, "1", ""} then
set Here to 1
else
offset of StartItem in SomeText
if result is 0 then
return ""
else
set Here to result + (length of StartItem)
end if
end if
if enditem is in {-1, "-1", ""} then
set There to -1
else
offset of enditem in (text Here thru -1 of SomeText)
if result is 0 then
return ""
else
set There to (Here + result) - 2
end if
end if
return (text Here thru There of SomeText)
end GetSubText