When editing a script with Script Editor, I often need to disable code sections and, in the past, I have used block comments for this purpose. I found this a bit cumbersome at times and wrote the following script for use in temporarily disabling sections of a script.
This script works as a toggle. If any line in the selection begins with the specified comment characters, then the comment characters are removed from the beginning of all lines in the selection. Otherwise, comment characters are added to the beginning of every line in the selection.
-- Revised 2022.02.23
on main()
set commentCharacters to "# " -- must begin with "--" or "#"
tell application "Script Editor" to tell document 1
set allCode to contents
set characterRange to character range of selection
set characterRange to getCharacterRange(allCode, characterRange) of me
set selection to characterRange
set selectedCode to contents of selection
end tell
set commentCharactersExist to false
set selectedCode to paragraphs of selectedCode
repeat with aParagraph in selectedCode
set theParagraph to contents of aParagraph
try
repeat while text 1 of theParagraph is in {tab, space}
set theParagraph to text 2 thru -1 of theParagraph
end repeat
on error
set theParagraph to tab
end try
set contents of aParagraph to theParagraph
if theParagraph begins with commentCharacters then set commentCharactersExist to true
end repeat
if commentCharactersExist then
set selectedCode to removeComment(commentCharacters, selectedCode)
else
set selectedCode to addComment(commentCharacters, selectedCode)
end if
set text item delimiters to {linefeed}
set selectedCode to selectedCode as text
set text item delimiters to {""}
tell application "Script Editor" to tell document 1
set contents of selection to selectedCode
set {c1, c2} to character range of selection
set selection to insertion point c1
end tell
end main
on addComment(commentCharacters, selectedCode)
if selectedCode = {} then set selectedCode to {tab}
repeat with aParagraph in selectedCode
set contents of aParagraph to (commentCharacters & aParagraph)
end repeat
return selectedCode
end addComment
on removeComment(commentCharacters, selectedCode)
if selectedCode = {} then set selectedCode to {tab}
repeat with aParagraph in selectedCode
if aParagraph begins with commentCharacters then
try
set contents of aParagraph to (text ((count commentCharacters) + 1) thru -1 of aParagraph)
on error
set contents of aParagraph to tab
end try
end if
end repeat
return selectedCode
end removeComment
on getCharacterRange(allCode, characterRange)
set {c1, c2} to characterRange
if c2 = 0 then set c2 to 1
if item c2 of allCode is in {return, linefeed} then set c2 to (c2 - 1) -- remove linefeed at end of selection
set c1Set to false
set runningTotal to 0
set allCode to paragraphs of allCode
repeat with aParagraph in allCode
set aParagraph to contents of aParagraph
set runningTotal to runningTotal + (count aParagraph) + 1
if c1Set = false and runningTotal > c1 then
set c1 to runningTotal - (count aParagraph)
set c1Set to true
end if
if c1Set = true and runningTotal > c2 then
set c2 to runningTotal
exit repeat
end if
end repeat
return {c1 - 1, c2 - 1}
end getCharacterRange
main()
I’ve been using the above script without issue until a recent update of Catalina. Now, when run by way of FastScripts and on a somewhat intermittent basis, a colon is added to the beginning or end of the comment characters. For example:
set testOne to “aa”
:## set testTwo to “bb”
:## set testThree to 1
:## set testFour to 2
I changed the comment characters to “–” but the issue persisted. I do not have this issue when the script is 1) run from within Script Editor, 2) run as an Automator service, 3) run as an app on the desktop. I emailed Daniel of FastScripts but he was unable to reproduce the issue.
Anyone have any idea why those colons are being inserted? Thanks.
FastScripts uses the same component instance of AppleScript for all scripts it runs, so things like text item delimiters are common to all scripts. Your code contains:
set selectedText to selectedList as text
That’s coercing a list to text, which means it will use whatever your TIDs are at that time.
Thanks Shane. Upon further investigation, I found a script, which I run by way of FastScripts, in which I had set the text item delimiter to a colon but had not reset the text item delimiter at the end of the script. As you surmise, that was the root cause of this issue. I fixed that and all is working well.
I’ve been attempting to get this script to work with Script Debugger but without success. It appears that ‘content’ has to be changed to ‘source text’ and that ‘character range’ and ‘selection’ are supported but apparently ‘paragraph’ is not. Anyways, I thought someone who is familiar with scripting Script Debugger might be able to suggest a fix or perhaps advise that my script won’t work with Script Debugger.
Your script would need to be modified to work with Script Debugger. But I’m not sure why you’d bother, given it has toolbar buttons and menu commands (which you can assign keyboard shortcuts to) that already do the job faster (and in some cases more cleanly).
Shane. I was aware there are toolbar buttons to add and remove comment characters but I didn’t know there are menu items for this. I tested these and they work great.
I do like my script’s ability to set the format of the comment characters, which I find to be a small convenience when editing a script. However, as things go, this is a minor matter and not worth the time it would appear to take to modify my script. I thought it might be an easy fix.
The native ability of Script Debugger to add and remove comments is great and that’s what I use. However, I wanted to learn a little about scripting Script Debugger and decided to rewrite the above script for use with Script Debugger just for learning purposes.
I’ve gotten everything fixed but cannot overcome one issue. I need to have the script select a particular paragraph (or range of paragraphs) of the script but can’t seem to manage that. The equivalent code in Script Editor would be:
tell application "Script Editor" to tell document 1
set selection to paragraph 2 -- reposition the selection
end tell
The above doesn’t work in Script Debugger and so I looked at the Script Debugger dictionary, which contains:
So, there does not appear to be a Script-Debugger equivalent to the Script Editor code and I thought perhaps I could get the character range of the numbered paragraph and then use that with the selection commmand but that didn’t work either.
Anyone have an ideas how to get the following to work:
tell application "Script Debugger" to tell document 1
set selection to paragraph 2 -- reposition the selection
end tell
You need to get the source text as a string, and do your selection calculations based on that. It’s a bit tedious (but relatively fast because there are minimal Apple events).
The following version of my script works with Script Debugger.
-- revised 2022.07.26
on main()
set commentCharacters to "# " -- must begin with "--" or "#"
tell application "Script Debugger" to tell document 1
set allCode to source text
set characterRange to character range of selection
set characterRange to getCharacterRange(allCode, characterRange) of me
set selection to characterRange
set selectedCode to selection
end tell
set commentCharactersExist to false
set selectedCode to paragraphs of selectedCode
repeat with aParagraph in selectedCode
set theParagraph to contents of aParagraph
try
repeat while text 1 of theParagraph is in {tab, space}
set theParagraph to text 2 thru -1 of theParagraph
end repeat
on error
set theParagraph to ""
end try
set contents of aParagraph to theParagraph
if theParagraph begins with commentCharacters then set commentCharactersExist to true
end repeat
if commentCharactersExist then
set selectedCode to removeComment(commentCharacters, selectedCode)
else
set selectedCode to addComment(commentCharacters, selectedCode)
end if
set text item delimiters to {linefeed}
set selectedCode to selectedCode as text
set text item delimiters to {""}
tell application "Script Debugger" to tell document 1
set contents of selection to selectedCode
set selection to {item 1 of characterRange, 0} -- remove selection
-- set selection to {item 1 of characterRange, ((count selectedCode) + 1)} -- keep selection
end tell
end main
on addComment(commentCharacters, selectedCode)
if selectedCode = {} then return {commentCharacters}
repeat with aParagraph in selectedCode
set contents of aParagraph to (commentCharacters & aParagraph)
end repeat
return selectedCode
end addComment
on removeComment(commentCharacters, selectedCode)
set commentCharactersCount to ((count commentCharacters) + 1)
repeat with aParagraph in selectedCode
if aParagraph begins with commentCharacters then
try
set contents of aParagraph to text commentCharactersCount thru -1 of aParagraph
on error
set contents of aParagraph to ""
end try
end if
end repeat
return selectedCode
end removeComment
on getCharacterRange(allCode, characterRange)
set {c1, c2} to characterRange
set {c1, c2} to {c1, c1 + c2 - 1}
set c1Set to false
set runningTotal to 0
set allCode to paragraphs of allCode
repeat with aParagraph in allCode
set runningTotal to runningTotal + (count aParagraph) + 1
if c1Set = false and runningTotal ≥ c1 then
set c1 to runningTotal - (count aParagraph)
set c1Set to true
end if
if c1Set = true and runningTotal ≥ c2 then
set c2 to runningTotal
exit repeat
end if
end repeat
return {c1, (c2 - c1)}
end getCharacterRange
main()
The script contained below works with Script Debugger and is faster than the earlier version. The script does not add comment characters to lines that are blank or contain whitespace only, although this behavior is changed by editing the line that contains the following comment:
-- revised 2022.09.23
use framework "Foundation"
use scripting additions
on main()
set commentCharacters to "# " -- must begin with "--" or "#"
tell application id "com.latenightsw.ScriptDebugger8" to tell document 1
set allCode to source text
set {cr1, cr2} to character range of selection
set {pr1, pr2} to getParagraphRange(allCode, cr1, cr2) of me
set selection to {pr1, pr2}
set selectedCode to selection
end tell
set selectedCode to current application's NSString's stringWithString:selectedCode
set trimmedCode to getTrimmedCode(selectedCode)
set editedCode to getEditedCode(trimmedCode, commentCharacters)
tell application id "com.latenightsw.ScriptDebugger8" to tell document 1
set contents of selection to editedCode
set selection to {pr1, 0}
end tell
end main
on getParagraphRange(theString, cr1, cr2)
set theString to current application's NSString's stringWithString:theString
set paragraphRange to theString's paragraphRangeForRange:{(cr1 - 1), cr2}
set theParagraphs to {((paragraphRange's location) + 1), paragraphRange's |length|}
return theParagraphs
end getParagraphRange
on getTrimmedCode(theString)
set thePattern to "(?m)^\\h+"
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:"" options:1024 range:{0, theString's |length|()})
return theString
end getTrimmedCode
on getEditedCode(theString, theCharacters)
set thePattern to "(?m)^" & theCharacters
set theRange to theString's rangeOfString:thePattern options:1024
if theRange's |length|() > 0 then -- comment characters exist`
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:"" options:1024 range:{0, theString's |length|()})
else
set thePattern to "(?m)^(.+)$" -- change "+" to "*" to comment blank lines
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:(theCharacters & "$1") options:1024 range:{0, theString's |length|()})
end if
return theString as text
end getEditedCode
main()
The script contained below works with Script Editor and is faster than the earlier version. The script does not add comment characters to lines that are blank or contain whitespace only, although this behavior is changed by editing the line that contains the following comment:
This script contains a bug which occurs when a blank line is selected with the line ending but without any preceding or subsequent text. The impact of this bug is relatively small.
-- revised 2022.09.23
use framework "Foundation"
use scripting additions
on main()
set commentCharacters to "# " -- must begin with "--" or "#"
tell application "Script Editor" to tell document 1
set allCode to contents
set {cr1, cr2} to character range of selection
set {pr1, pr2} to getParagraphRange(allCode, cr1, cr2) of me
set selection to {pr1, pr2}
set selectedCode to contents of selection
end tell
set selectedCode to current application's NSString's stringWithString:selectedCode
set trimmedCode to getTrimmedCode(selectedCode)
set editedCode to getEditedCode(trimmedCode, commentCharacters)
tell application "Script Editor" to tell document 1
set contents of selection to editedCode
set selection to insertion point (pr1 + 1)
end tell
end main
on getParagraphRange(theString, cr1, cr2)
set cr2 to cr2 - cr1
set theString to current application's NSString's stringWithString:theString
set paragraphRange to theString's paragraphRangeForRange:{cr1, cr2}
set {pr1, pr2} to {(paragraphRange's location), paragraphRange's |length|}
return {pr1, pr2 + pr1}
end getParagraphRange
on getTrimmedCode(theString)
set thePattern to "(?m)^\\h+"
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:"" options:1024 range:{0, theString's |length|()})
return theString
end getTrimmedCode
on getEditedCode(theString, theCharacters)
set thePattern to "(?m)^" & theCharacters
set theRange to theString's rangeOfString:thePattern options:1024
if theRange's |length|() > 0 then -- comment characters exist
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:"" options:1024 range:{0, theString's |length|()})
else
set thePattern to "(?m)^(.+)$" -- change "+" to "*" to comment blank lines
set theString to (theString's stringByReplacingOccurrencesOfString:thePattern withString:(theCharacters & "$1") options:1024 range:{0, theString's |length|()})
end if
return theString as text
end getEditedCode
main()