Key binding to toggle Comment/Uncomment

Ironically, the selection expansion is the problem in both cases. Just happens to be two very different problems. :crazy_face:

The Select Lines command handles emoji just fine, but it accounts for almost half the run time of the entire dmbrown-fuzzywan script. Combining the two approaches — call it dmbrown-fuzzywan-peavine, or dfp for short :stuck_out_tongue: — shaves off 10–20ms, but pure peavine is still twice as fast. And dfp doesn’t persist the selection. Sigh


FWIW, I thought one of the four NSString properties that normalize strings might allow my script to work with emoji’s but that wasn’t the case. As far as I can tell, the four normalize properties simply ignore emojis, although my knowledge on this topic is quite limited.

Normalize accented letters, which apparently are already 16-bit code units. This works as I would expect.

Normalize emojis, which doesn’t appear to do anything as regards the precomposed properties.

Hmm. Since count (characters of (theString as text)) gives a different result — “:slightly_smiling_face:” has a length of 2 and count of 1 — that gives me a starting point.

The difference between the count and length of everything prior to cr1 could be used as an adjustment factor. Something like this:

on getParagraphRange(theCode, cr1, cr2)
	
	set theCode to current application's NSString's stringWithString:theCode
	
	-- Adjustment factor for characters wider than one UTF-16 code unit, like emoji.
	set leftString to characters 1 thru (cr1 - 1) of (theCode as text) as string
	set leftString to current application's NSString's stringWithString:leftString	
	set codeUnitFactor to (leftString's |length|()) - (count (characters of (leftString as text)))

	-- Adjust something (?) here.
	
	set paragraphRange to theCode's paragraphRangeForRange:{(cr1 - 1), cr2}
	return {((paragraphRange's location) + 1), paragraphRange's |length|}
	
end getParagraphRange

That gives me the right numbers — “:slightly_smiling_face:” has a an adjustment factor of 1, and “:raised_hand_with_fingers_splayed:t2:” has a factor of 3 due to the skin tone modifier — but using it to adjust cr1 doesn’t have the effect I expected. It looks like the original selection itself is off by codeUnitFactor, so that needs to be adjusted somehow. I’m not sure if it’s possible.

I rewrote my script in post 9 to incorporate the selection ASObjC range property, as suggested by Shane. This cleans up the code a bit but does not alter the basic operation of the script.

use framework "Foundation"
use scripting additions

on main()
	set commentCharacters to "--"
	tell application "Script Debugger" to tell document 1
		set allCode to source text
		set {cr1, cr2} to selection ASObjC range
		set {pr1, pr2} to getParagraphRange(allCode, cr1, cr2) of me
		set selection ASObjC range to {pr1, pr2}
		set selectedCode to selection
		set {editedCode, editCount, editAction} to getEditedCode(selectedCode, commentCharacters) of me
		set contents of selection to editedCode
		set pr2 to (pr2 + ((count commentCharacters) * editCount * editAction))
		set selection ASObjC range to {pr1, pr2}
	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, cr2}
	return {paragraphRange's location, paragraphRange's |length|}
end getParagraphRange

on getEditedCode(theString, theCharacters)
	set removeString to current application's NSMutableString's stringWithString:theString
	set addString to current application's NSMutableString's stringWithString:theString
	set removeCount to removeString's replaceOccurrencesOfString:("(?m)^(\\h*)" & theCharacters) withString:"$1" options:1024 range:{0, removeString's |length|()}
	set addCount to addString's replaceOccurrencesOfString:"(?m)^(\\h*)" withString:(theCharacters & "$1") options:1024 range:{0, addString's |length|()}
	if removeCount is equal to addCount then return {removeString as text, removeCount, "-1"}
	return {addString as text, addCount, "1"}
end getEditedCode

main()
1 Like

Applying the adjustment factor to cr1 or pr1 either makes things much, much worse, or in some cases (subtracting it from cr1) has no effect at all. And since cr1 is setting pr1 (I think?), I don’t get why the effects are wildly different. I’m clearly not understanding how that part works.

You shouldn’t be using any adjustment at all – just use selection ASObjC range to get the selection range in the right units to begin with.

fuzzywan. Can you test my revised script in post 24 with a script that contains emojis. I think it may have resolved that issue. I didn’t fully understand the operation of the selection ASObjC range property and may have confused matters.

It’s the zero-based range in 16-bit units – that’s what NSString works in.

Basically, if you’re going to manipulate text using normal AppleScript, use selection; if you’re going to be converting it to an NSString and manipulating it using ASObjC, use selection ASObjC range.

2 Likes

I’ll be damned. I’d made some changes based on Shane’s selection ASObjC range suggestion, but I must have missed part of it because it was working exactly the same as the original.

I see it now. Missed both of the set selection ASObjC range to {pr1, pr2} lines.

Anyway, it’s working perfectly now. :grinning:

1 Like

I’ve been half following along; do you mind posting the final version?

I’m using peavine’s latest version, unmodified: post #24.

1 Like

how does one run this script (post #24) on a different script — i.e. not on itself :slight_smile: ? Do I have to use a tool like FastScript to do it?

EDIT> just discovered the User Scripts Folder, and it hot-loads new scripts, nice. now I just need to assign a keyboard control
 I wonder if Apples Shortcuts Settings are up for that?!

EDIT 2> it is, yay, something working for once.

You can set keyboard shortcuts for the Scripts menu right in Script Debugger’s settings. Very handy.

1 Like

thanks, that’s even better!