Saulius Antanavicius
Saulius Antanavicius

Reputation: 1381

Applescript find, replace and style

I've been trying to get this simple script to work, it's supposed to search for a string, replace it while applying some styling, e.g. setting the text bold and red.

Here's what I have so far:

tell application "Finder"
    set fl to files of folder POSIX file "/Users/Sc/Desktop/app/" as alias list
end tell
repeat with f in fl
    tell application "TextEdit"

        open f


        set text of front document to replace_chars(text of front document, "a", "0000") of me
    end tell
end repeat

on replace_chars(this_text, search_string, replacement_string)
    set AppleScript's text item delimiters to the search_string
    set the item_list to every text item of this_text
    set the size of replacement_string to 14
    set AppleScript's text item delimiters to the replacement_string

    set this_text to the item_list as string
    set AppleScript's text item delimiters to ""
    return this_text
end replace_chars

However this produces an error, I understand why, but not sure how to go about styling it before replacement, any help would be appreciated.

Upvotes: 1

Views: 1314

Answers (3)

JMichaelTX
JMichaelTX

Reputation: 1807

Since the other posters both noted how poorly suited TextEdit is for this task, allow me to make an "out of the box" suggestion: Use MS Word

The Find and Replace tool in Word can easily handle this task, and much more complicated replacements.

If you have a lot of source documents in RTF format, you could open them in Word, make the changes, and save back to the same (or different) RTF file. It would be very easy to create a Word VBA macro to do this.

You could then either write an AppleScript to open each RTF file in Word and run the macro, or you could do all of the processing using a master Word VBA. You could do it in either way, but I would choose the all VBA route since, IMO, it is a much better language for processing MS documents than AppleScript.

Of course, this requires that you have MS Word installed. I'm still running MS Office 2011 on all of my Macs, and don't plan to upgrade to Office 2016 for a while. Word 2011 works very well.

Good luck.

Upvotes: 0

foo
foo

Reputation: 3259

TextEdit uses Cocoa Scripting's standard Text Suite implementation, which is pretty naff at the best of times. If you're doing whole-word replacement, the following should work:

tell application "TextEdit"
    set aRef to a reference to (every word of document 1 where it is "OLDWORD")
    set aRef's color to {65535, 0, 0}
    set aRef's contents to "NEWWORD"
end tell

The same approach should also work for single-character or whole-paragraph replacement; just modify the every word of... query appropriately. In each case though, you must match exactly one word/character/paragraph and replace it with exactly one word/character/paragraph, otherwise you'll get hilarious off-by-N errors throughout subsequent matches[1] due to Cocoa Scripting being made of dumb and incompetent[2] (e.g. try changing a recurring word to two new words, e.g. "foo" -> "boo boo" to see what I mean).

Also, unlike Text Suite implementations found in better written apps, Cocoa Scripting's Text Suite provides no way to describe to text ranges (e.g. text (character i) thru (character j) of.../text i thru j of...), so it's impossible to tell TextEdit to match, say, "oo" in "baboon", "fool", "spitoon", etc. If you need to match arbitrary character ranges, you'll have to get the text into AppleScript and calculate the start and end of each match yourself.


[1] When making multiple replacements, CS's Text Suite first calculates the positions of all of the text ranges that need changed, and then performs each substitution starting at the first match and finishing at the last. Thus, any differences in the length of the new vs old text mean all of the remaining match indexes it already calculated are no longer correct because the characters previously at that position have now shifted to the left or right. To do the job right, CS should've calculated all the positions from first to last, and then replaced them starting at the last and working backwards to the first.

[2] (CocoaScripting.framework was originally designed by Cocoa developers who didn't understand how AppleScript works, and since then has been maintained by AppleScript developers who don't understand either. So it goes.)

Upvotes: 2

vadian
vadian

Reputation: 285059

TextEdit is not the best tool to search and replace styled text, for example the free TextWrangler has more powerful skills to do that.

Anyway, try this, it affects only one opened document in TextEdit

The "algorithm" is to calculate the offset of the search string, replace it with the replace string and keeps the location in a repeat loop. At the end reassign the changed text to the text object of TextEdit and change the style at the stored locations to {font: Helvetica Bold, size: 24 and color: red}.

property searchString : "a"
property replaceString : "0000"

tell application "TextEdit"
    set completed to false
    set ranges to {}
    set theText to text of front document
    set theSize to size of text of front document
    repeat while completed is false
        tell current application to set o to offset of searchString in theText
        if o is 0 then
            set completed to true
        else
            tell theText to set newText to text 1 thru (o - 1) & replaceString & text (o + (length of searchString)) thru -1
            set end of ranges to o
            copy newText to theText
        end if
    end repeat
    set text of front document to theText
    set size of text of front document to theSize
    repeat with aRange in ranges
        tell characters aRange thru (aRange + (length of replaceString) - 1) of front document
            set size to 24
            set its color to {65535, 0, 0}
            set font to "Helvetica Bold"
        end tell
    end repeat
end tell

Upvotes: 1

Related Questions