Search code examples
textreplaceapplescriptrepeatbbedit

How can you break a repeat when a separate condition is met?


Wanting to increase my AppleScript abilities and the usage of my repeat I was curious to know how I could step through a text file to manipulate the contents but I'm stuck on what to pass to break the loop when I run across another name.

Given then text file content of:

Bob
- bacon
- eggs
- waffle
Bacon ipsum dolor amet bresaola andouille flank, meatloaf salami biltong brisket.
James
- sausage
- omelet
Sausage short ribs sirloin landjaeger, biltong swine kielbasa prosciutto.
Bresaola landjaeger jowl alcatra.
Michael
- scrambled eggs
- cereal
- toast
Sam
- sausage
- pancakes

I wanted my output to resemble:

Bob
    1. Bob likes bacon
    2. Bob likes eggs
    3. Bob likes waffle
Bacon ipsum dolor amet bresaola andouille flank, meatloaf salami biltong brisket.
James
    1. James likes sausage
    2. James likes omelet
Sausage short ribs sirloin landjaeger, biltong swine kielbasa prosciutto.
Bresaola landjaeger jowl alcatra.
Michael
    1. Michael likes scrambled eggs
    2. Michael likes cereal
    3. Michael likes toast
Sam
    1. Sam likes sausage
    2. Sam likes pancakes

but when I script through the text I'm able to find the first name and dashed item but I'm having an issue trying to figure out how to break when another name is present:

the code:

tell application "BBEdit"
    activate
    set testCase to "repeatBreakfast.txt"
    select insertion point before first character of text document testCase
    set foodCount to 1
    repeat
        set theCustomer to find "^([A-Za-z]*)$" searching in text 1 of text document testCase options {search mode:grep, wrap around:false} with selecting match
        if theCustomer is not found then
            exit repeat
        else
            set theName to (grep substitution of "\\1") as string
            repeat
                set breakfastItem to find "^- (?=\\D)" searching in text 1 of text document testCase options {search mode:grep, wrap around:false} with selecting match
                if breakfastItem is not found then
                    exit repeat
                else
                    replace selection using ("\\t" & foodCount & ". " & theName & " likes ")
                    set foodCount to foodCount + 1
                end if
            end repeat
        end if
    end repeat
end tell

I get:

Bob
    1. Bob likes Bob likes bacon
    2. Bob likes Bob likes eggs
    3. Bob likes Bob likes waffle
Bacon ipsum dolor amet bresaola andouille flank, meatloaf salami biltong brisket.
James
    4. Bob likes James likes sausage
    5. Bob likes James likes omelet
Sausage short ribs sirloin landjaeger, biltong swine kielbasa prosciutto.
Bresaola landjaeger jowl alcatra.
Michael
    6. Bob likes Michael scrambled eggs
    7. Bob likes Michael cereal
    8. Bob likes Michael toast
Sam
    9. Bob likes sausage
    10. Bob likes pancakes

but when I try to insert a conditional for the next name:

if theCustomer is found then
    set foodCount to 1
    exit repeat
end if

I get:

Bob
    1. Bob likes Bob likes bacon
- Bob likes eggs
- Bob likes waffle
Bacon ipsum dolor amet bresaola andouille flank, meatloaf salami biltong brisket.
James
    1. James likes James likes sausage
- James likes omelet
Sausage short ribs sirloin landjaeger, biltong swine kielbasa prosciutto.
Bresaola landjaeger jowl alcatra.
Michael
    1. Michael likes Michael scrambled eggs
- Michael cereal
- Michael toast
Sam
    1. Sam likes sausage
- pancakes

In AppleScript and BBEdit how can I properly name and increment the text in my repeat loop?


Solution

  • A solution, the script need to get all customers instead of one at a time.

    After that, use lines between two customers to find a breakfast's item.

    tell application "BBEdit"
        activate
        set testCase to "repeatBreakfast.txt"
        set r to find "^([A-Za-z]*)$" searching in text document testCase options {search mode:grep, wrap around:false, starting at top:true, returning results:true, showing results:false}
        if r is found then
            set allCustomers to found matches of r
            set theCount to count allCustomers
            repeat with i from 1 to theCount
                set theCustomer to item i of allCustomers
                set theName to match_string of theCustomer
                set lineOfThisCustomer to result_line of theCustomer
                if i < theCount then
                    set lastLineOfThisCustomer to (result_line of item (i + 1) of allCustomers) - 1 -- the line before the next customer
                else
                    set lastLineOfThisCustomer to -1 -- it's the last customer, so use the last line of the document
                end if
    
                set foodCount to 1
                repeat
                    -- ** search  between this customer and the next customer **
                    set breakfastItem to find "^- (?=\\D)" searching in (lines lineOfThisCustomer thru lastLineOfThisCustomer of text document testCase) options {search mode:grep, wrap around:false} with selecting match
                    if breakfastItem is not found then exit repeat
                    replace selection using ("\\t" & foodCount & ". " & theName & " likes ")
                    set foodCount to foodCount + 1
                end repeat
            end repeat
        end if
    end tell
    

    Another solution, use the find command to get two customers.

    After that, use lines between these two customers to find a breakfast's item.

    tell application "BBEdit"
        activate
        set testCase to "repeatBreakfast.txt"
        select insertion point before first character of text document testCase
    
        set theCustomer to find "^([A-Za-z]*)$" searching in text document testCase options {search mode:grep, wrap around:false} with selecting match
        if theCustomer is found then
            set theName to (grep substitution of "\\1") as string
            repeat
                set lineOfThisCustomer to startLine of found object of theCustomer
    
                set theNextCustomer to find "^([A-Za-z]*)$" searching in text document testCase options {search mode:grep, wrap around:false} with selecting match
                if theNextCustomer is found then
                    set lastLineOfThisCustomer to (startLine of found object of theNextCustomer) - 1 -- the line before the next customer
                    set theName2 to (grep substitution of "\\1") as string
                else
                    set lastLineOfThisCustomer to -1 -- no other customer, so use the last line of the document
                end if
    
                set foodCount to 1
                repeat
                    -- ** search  between this customer and the next customer **
                    set breakfastItem to find "^- (?=\\D)" searching in (lines lineOfThisCustomer thru lastLineOfThisCustomer of text document testCase) options {search mode:grep, wrap around:false} with selecting match
                    if breakfastItem is not found then exit repeat
                    replace selection using ("\\t" & foodCount & ". " & theName & " likes ")
                    set foodCount to foodCount + 1
                end repeat
                if theNextCustomer is not found then exit repeat
                set theCustomer to theNextCustomer
                set theName to theName2
            end repeat
        end if
    end tell