--Applescript direct -- Script to close a begin/end block -- Ramon Figueroa-Centeno March 10, 2009 tell application "TeXShop" -- The linefeed character. set linefeed to ASCII character 10 set the front_document to the front document -- set the front_document to document #DOCUMENTNAME# -- The whole text of the document set whole_document to (the text of the front_document) as string -- If the front document is not saved dump its -- content to a temporary file and use that if the front_document is modified then tell me set texpath to do shell script "mktemp /tmp/XXXXXXXX" set TMP to POSIX file texpath open for access TMP with write permission write whole_document to TMP close access TMP end tell else set texpath to the path of the front_document -- set texpath to the #FILEPATH# end if -- The offset of the selection set selection_offset to offset of the selection of the front_document -- Move the insertion point to the beginning of the selected word. -- Unless we are at the end of a line. -- If one removes " " (space) from the list the insertion point moves to the -- beginning of the line. try if the character (selection_offset + 1) of the whole_document is not in {linefeed, return} then repeat until (selection_offset = 0) or ¬ (character selection_offset of the whole_document is in {linefeed, return, " "}) set selection_offset to selection_offset - 1 end repeat set the offset of the selection of the front_document to selection_offset end if on error -- It appears that we are at the end of the file! end try -- Stop if the insertion point is at the beginning of the document if selection_offset = 0 then return end if -- The document up to the selection set partial_document to ¬ (characters 1 thru (selection_offset) of the whole_document) as string -- Let selection_line_number be the number of the line of the start of the current selection set selection_line_number to count paragraphs of the partial_document set report to "selection line: " & selection_line_number & return -- The total number of lines set total_lines to count paragraphs of the whole_document set report to report & "total # of lines: " & total_lines & return -- The "command" is a shell script that does this: -- delete all comments: -- sed 's/%.*$//' (or sed '/%.*$/ s/%.*$//' for speed) set command to " | sed '/%.*$/ s/%.*$//'" -- replace all "\" with a linefeed character: -- tr -s "\\" "\n" set command to command & " | tr -s \"\\\\\" \"\\n\"" -- delete everything after and including the first "}": -- sed 's/}.*//' (or sed '/}.*/ s/}.*//' for speed) set command to command & " | sed '/}.*/ s/}.*//'" -- keep only the lines that start with "begin{" or "end{": -- egrep -e '^begin{|^end{' set command to command & " | egrep -e '^begin{|^end{'" -- replace all "{" by spaces: -- tr -s "{" " " set command to command & " | tr -s \"{\" \" \"" -- shell command to convert returns (\r) to line feeds (\n) set mac2unix to "tr \\\\r \\\\n" --select insertion point before the selection set length of the selection of the front_document to 0 -- Divide the line of the selection into two chunks -- one before and another after the beginning of the selection try set firstLineChunk to the last paragraph of the partial_document on error set firstLineChunk to "" end try set the_line to paragraph selection_line_number of the whole_document try set secondLineChunk to characters ((count of the firstLineChunk) + 1) ¬ thru (count of the_line) of the_line as string on error set secondLineChunk to "" end try -- Set list_1 to a list that contains strings, each with two words -- the first word is "begin" or "end" and the second is the -- name of the corresponding environment set list_1 to {} set command_2 to ¬ mac2unix & " < " & (quoted form of texpath) ¬ & " | head -n " & (selection_line_number - 1) & command tell me to set parsed to do shell script command_2 if parsed is not "" then set list_1 to list_1 & (paragraphs of parsed) end if set command_2 to ¬ "echo " & (quoted form of firstLineChunk) & " | " & mac2unix & command tell me to set parsed to do shell script command_2 if parsed is not "" then set list_1 to list_1 & (paragraphs of parsed) end if -- If list_1 is empty then there is no environment to close if (count of list_1) = 0 then beep say "There are no environments before this point." --display dialog "There are no environments before this point." buttons {"OK"} default button 1 with icon caution return end if set flips to 0 repeat with i from (count list_1) to 1 by -1 if word 1 of item i of list_1 is "end" then set flips to flips + 1 else set flips to flips - 1 end if if flips = -1 -- The next line does this: -- The next line does this: -- but handles starred commands correctly tell me to to set environment_name to do shell script ¬ "echo \"" & (item i of list_1) & "\" | sed '/.* / s/.* //'" exit repeat end if end repeat if not (flips = -1) then beep say "I did not find an open environment!" --display dialog "I did not find an open environment!" buttons {"OK"} default button 1 with icon caution return end if -- Now we check to see if the environment we are in is already closed set list_2 to {} set command_2 to ¬ "echo " & (quoted form of secondLineChunk) & " | " & mac2unix & command tell me to set parsed to do shell script command_2 if parsed is not "" then set list_2 to paragraphs of parsed end if set command_2 to ¬ mac2unix & " < " & (quoted form of texpath) ¬ & " | tail -n +" & (selection_line_number + 1) & command tell me to set parsed to do shell script command_2 if parsed is not "" then set list_2 to list_2 & (paragraphs of parsed) end if set close_environment to true if (count of list_2) > 0 then set flips to 0 repeat with i from 1 to (count list_2) if word 1 of item i of list_2 is "begin" then set flips to flips + 1 else set flips to flips - 1 end if if flips = -1 then -- The next line does this: -- set environment_name_2 to word 2 of item i of list_2 -- but handles starred commands correctly set environment_name_2 to do shell script ¬ "echo \"" & (item i of list_2) & "\" | sed '/.* / s/.* //'" if environment_name_2 = environment_name then beep activate display dialog "The environment \"" & environment_name ¬ & "\"" & return & "you are working on is already closed." & return ¬ & "Do you still want to close it?" buttons {"No", "Yes"} ¬ default button "No" with icon note set close_environment to (button returned of the result is not "No") end if exit repeat end if end repeat end if -- Close the environment if close_environment then if the_line = "" then set the content of the selection of the front_document to ¬ "\\end{" & environment_name & "}" else -- If we are at the beginning of a line then close the environment -- and then enter a return. Otherwise, enter a return before doing so. if (character selection_offset of the whole_document is in {linefeed, return}) then set the content of the selection of the front_document to ¬ "\\end{" & environment_name & "}" & linefeed else set the content of the selection of the front_document to ¬ linefeed & "\\end{" & environment_name & "}" & linefeed end if end if end if -- If a temporary file was created delete it. try do shell script "rm " & POSIX path of TMP end try end tell