Shortcuts for basic line manipulation


As mentioned in the thread Shortcuts for delete / copy / move line?, I think it would be useful to have direct basic line manipulation for

  • selecting,
  • deleting,
  • duplicating,
  • (evtl. copying) and
  • moving up/down

a line without having to previously select the line in Script Debugger.



So what should happen where the continuation character (¬) is used: should any such commands still be based on paragraphs/lines, or on statements, or on statements only if in the first (or last) line, or some other rule? I’m interested in suggestions and precedents.

My feeling is that a move selection should move all and only whatever is selected, whereas a move invoked from the cursor position should move the entire statement in which the cursor is placed.

Not aware of any precedents as I don’t know of anything else that uses the line continuation character (I never use it myself, and I always remove it whenever its auto-added for me).

Where did move selection come from? :confused:

In the script that you wrote in the previous thread, and in most text editors that have this feature, the one and the same operation to move the line at the cursor also works to move a selected range of text.

I think if you implement the first, you should get the latter for free.

Sorry for cross-posting, I’ll do it only to consolidate the discussion on this Feature Request thread:

In my opinion: This commands should handle a line (= between column 0/1 and CR).
This is the way the editors that I used und use (right now, daily: BBEdit on the Mac, Eclipse, Ultra Edit, Visual Studio Code and the editor from the SAP GUI on a PC) work.

Regarding the continuation character in AppleScript: I haven’t wrote enough AppleScript to have a feeling what is right or wrong.
However my first thought would be to ignore it - you could also write everything in one really long line - and go with the line in this case too.

Thanks for mentioning this, Phil!
As a newbie - with AppleScript and Script Debugger - I hadn’t the courage to ask for it (it’s just my second or third posting here! :wink: ) but I had it in the back of my mind :wink:

That’s right, all of the editors I mentioned work their magic on a line and/or a selection as well.
For duplicating and moving is this really handy, I use it all the time!

I’m not sure I follow. That script I wrote moves any lines that are covered by part of the selection, not just the selected text – is that what you mean?

Yes, sorry, that’s exactly what I meant. I don’t think anyone’s asking to pull a selected part of a line around.

Is it too much to ask for it both ways? :smile:

I see real use cases both:

  1. for the entire statement
    • When you want to operate on, well, the entire statement.
  2. just selecting the one statement segment with an continuation char (just that one “line”)
    • When you want to just delete/copy that one line segment, like on a multi-line display dialog statement.

I actually use both of these a lot.

FWIW, after accuracy, one of my main objectives in writing code is readability. I find that using the continuation character to separate major phrases of the statement onto separate lines greatly improves readability, and facilitates making changes/deletions.

It’s never too much to ask :smile:

But there are a limited number of shortcuts available, so it’s a question of whether a “smart” option, which normally selects lines only, but the entire statement if the first or last line is selected (in other words, when the result would be unlikely to even compile), would be more useful than having to remember two lots of shortcuts.

OK, that sounds great to me. With the “smart option”, I would just need one shortcut/tool.

One minor suggestion: Select the entire statement only if the top line has focus.
There are plenty of times when I want to delete just the last line.
I guess if it was “super smart” it would recognize it was the last line, and also delete the continuation character on the prior line (if the operation was a delete). :wink:

BTW, I’d be happy with just one shortcut to trigger the process, and then an autopopup with a 1-char trigger of the operation (C- Copy; X - Cut; D - Delete; M - Move; R - Replace with Clipboard; ESC - Cancel). Just an idea…

So something like this behavior (for a cut)?

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

tell application id "com.latenightsw.ScriptDebugger7"
	tell document 1
		set scriptText to source text
		set {theLocation, theLength} to (get character range of selection)
	end tell
end tell
set theLocation to theLocation - 1 -- for zero-based counting
set scriptText to current application's NSString's stringWithString:scriptText

set {location:theLocation, |length|:theLength} to (scriptText's paragraphRangeForRange:{theLocation, theLength})
set hasBreakChar to ((scriptText's substringToIndex:(theLocation + theLength - 1))'s hasSuffix:"¬")
set followsBreakChar to theLocation > 2 and ((scriptText's substringToIndex:(theLocation - 1))'s hasSuffix:"¬")

	if hasBreakChar and not followsBreakChar then
		set theLength to theLength + 1
		set {location:theLocation, |length|:theLength} to (scriptText's paragraphRangeForRange:{theLocation, theLength})
		set hasBreakChar to ((scriptText's substringToIndex:(theLocation + theLength - 1))'s hasSuffix:"¬")
		exit repeat
	end if
end repeat
tell application id "com.latenightsw.ScriptDebugger7"
	tell document 1
		if not hasBreakChar and followsBreakChar then
			set selection to {theLocation - 1, 1}
			set selection to ""
			set selection to {theLocation, theLength}
			set selection to ""
			set selection to {theLocation + 1, theLength}
			set selection to ""
		end if
	end tell
end tell

A quick tests shows it is smart, and works fast.
One note: it is a “delete” rather than a “cut” since it puts nothing on the clipboard.

Good catch. So after the repeat, add:

set thePasteboard to current application's NSPasteboard's generalPasteboard()
-- clear it, then write new contents
thePasteboard's clearContents()
thePasteboard's writeObjects:{scriptText's substringWithRange:{theLocation, theLength}}

Now the question: How would you expect move up/down to behave?

Erm. Length and (zero-based) location in characters vs. ASObjC equivalent units. Assumption of order in a list coerced from record. :face_with_raised_eyebrow:

That’s not an issue here. paragraphRangeForRange: is returning a Cocoa range, which I’m then using to extract a substring from a Cocoa string. It could be an issue at the beginning of the script, except that for historical reasons Script Debugger’s character range is one-based but still based on unichar units.

I’ll wear that, even though I know it won’t be an issue here :grinning: Amended above.

But its input the first time it’s used is derived from Script Debugger’s character range result. I don’t see anything in Script Debugger’s dictionary to suggest that the unit sizes in a point are anything other than AS characters, but I’ll take your word for it if they are. :slight_smile:

It was a very late decision when it became obvious that a more traditional scripting implementation wasn’t going to be feasible. It’s arguably more forgivable in a code editor, but it’s something to be looked at in future.