How Make Macro that Swaps Word from Word List?

I'm trying to make a macro that will take a word(s) in the clipboard, search a predesignated TXT file, find that word(s) in the list, and copy the word(s) that's directly one line below it. If there's a space in the next line then or the word isn't in the list, then do nothing. The word or words must match exactly to what's in the line but ignores capitalization.

Here's an example of how this works. I come across this sentence:

The affect caused him to be drowsy for days.

I copy "affect," trigger the macro, it looks through a TXT file until it finds "affect," copies what's on the next line down which is "effect," and copies "effect" into the clipboard. I can then program the macro to paste "effect" in the place of "affect."

The TXT file would simply show:
affect
effect

which
that

whilst
whlie

...and so on.

I tried having ChatGPT 4 write an AppleScript, but, unsurprising, it didn't work. Here's what it gave me:

set theFilePath to "/path/to/your/textfile.txt" -- set the path to your txt file here

-- get the word to find from the clipboard
set theWordToFind to the clipboard

-- read the file
set theFileReference to open for access file theFilePath
set theFileContent to read theFileReference
close access theFileReference

-- split the file content into lines
set theLines to paragraphs of theFileContent

-- iterate over the lines to find the word and get the following word
set foundWord to false
set nextWord to ""
repeat with i from 1 to count theLines
    set theLine to item i of theLines
    set theWords to words of theLine
    if foundWord then
        if theLine is not equal to "" then
            set nextWord to first item of theWords
            exit repeat
        end if
    else if theWords contains theWordToFind then
        set foundWord to true
    end if
end repeat

-- check if the word was found and if the following word exists
if foundWord and nextWord is not equal to "" then
    set the clipboard to nextWord
    display dialog "The word following '" & theWordToFind & "' is '" & nextWord & "'. It has been copied to the clipboard."
else
    display dialog "The word '" & theWordToFind & "' was not found in the file, or there was no word following it."
end if

Any help on this would be much appreciated.

Here's one way of doing it:

Substitute.kmmacros (4.2 KB)

Select the suspicious word and run the macro and it will substitute "effect" for "affect" in your example text. Or any of the other two substitutions you cite.

I think the pattern is clear enough to add more (and it doesn't matter how many you add) but just in case:

s = substitute
/[text] = what to look for in the selection
/[replace] = what to replace
/; = end of item
2 Likes

@mrpasini This works great! Is it possible to make it case sensitive? For example, if "whilst" is the first word of the sentence have "While" replace "Whilst" without having to have a second line with s/Whilst/While/;?

For clarity, I'm probably going to have a few hundred words in this list, if that matters.

Yes. It is case sensitive now. So just add your case option:

s/Whilst/While/;

alternately you can combine them with:

s/([Ww])hilst/$1hile/;

which saves the initial letter and changes the rest.

To make it case insensitive (which you don't want), you'd close each option with /i; instead of `/;' (for Ignore case).

1 Like

@mrpasini Ah, thanks! That definitely helps.

I'm running into one small problem, and I'm not sure if there's a fix for it. This macro is going to be used for editing books, and in the publishing industry, we use track changes and have the inserted word(s) after the deleted word(s). Here's an example.


The macro is putting the new words before the deleted words. Any ideas?

Thank you again for all your help. I REALLY appreciate it!

Try this for example

s/(affect)/$1effect/;
s/(Affect)/$1Effect/;
s/(bubble wrap)/$1Bubble Wrap/;

which uses two entries where case may change (since we don't know if it did) and one entry for simpler substitutions.

The styling depends on your word processor but isn't out of the question.