2

I wrote an Automator Service (intended for use on any selected text in any application) that modifies the length of the selection given a number/length that the user specifies. Here's a snippet of relevant code that excludes all the other features/niceties of the service:

--Figure out whether the selection must be lengthened or shrunk
set lengthen to false
set mod_length to 0
if character_count is equal to 0 or n is greater than character_count then
    set lengthen to true
    set mod_length to n - character_count
else
    set mod_length to character_count - n
    --This is a trick to make sure arrowing affects the right side of the selection
    key code 124 using {shift down}
    key code 123 using {shift down}
end if

repeat mod_length times
    if lengthen is true then
        --arrow to the right
        key code 124 using {shift down}
    else
        --arrow to the left
        key code 123 using {shift down}
    end if
end repeat

The service works great in most applications, except Terminal.app (because the arrow keys are used to move the cursor on the command line and not the size of the currently active selection). Ideally, this would actually work in Terminal, because that's usually where I need to use this service.

So is there a way to modify the length of selected text on any line in the history in a Terminal.app window (assuming the first selected character is position 1) using an automator service (and applescript inside that service) in a way that doesn't use the arrow keys? E.g. I select the output of a command and run the service to adjust the length of the selection to a length I've supplied.

Background:

The reason I'm doing this is because my work involves DNA manipulation/modification and as a part of the debug process for these scripts, I sometimes need to briefly observe what has happened at a specific position in a DNA string output on the command line - quickly and dirtily - just to confirm an intended change had the intended result. So this is just a quick way to visually find a coordinate in a long DNA string. I eventually intend to modify this service in such a way that only certain characters are counted in the determination of the length of the selection (e.g. don't count numbers, spaces, newlines, etc).

  • The code you've posted does not compile and besides that character_count and n are not defined. So even if the code you posted compiled, it would still fail as is. That said, I read your other question that you deleted about an hour ago and the bottom line is what you what to achieve in Terminal is not possible. – user3439894 Feb 21 '18 at 20:00
  • I wish to commend you on the revised question. This is immeasurably better than what you posted before, and it's easy to understand what you're wanting to do now. I'm sorry that it may all be for nought since, as @user3439894 said, it's not achievable in this manner. But from what you wrote under Background, it sounds like you're essentially comparing the DNA text before and after modification, is that right ? If that's your real objective, have you considered doing this without text selections, but through pattern matching or command-line tools (diff for instance) ? – CJK Feb 22 '18 at 2:37
  • Hmmm... Are you sure it's not possible? I can change the length of the selected text by editing the 'len' attribute of "Selected text range" in the Accessibility Inspector. I edited the selection length from 29 to 31 in this test case: dropbox.com/s/bn2z6ewmdj4mfai/… – hepcat72 Feb 22 '18 at 21:29
  • Sorry for the delay. You didn’t tag me in your reply so I didn’t get notified. Accessibility Inspector may very well be able to adjust the attribute, but AppleScript cannot because the class of that attribute is one that simply doesn’t exist in AppleScript. If you write a script in AppleScript-ObjC or Cocoa, you probably could do it because you’d have access to their data types. But that requires learning Objective-C, which is on my to do list, but not something I have yet done. Why exactly do you need to adjust selection lengths ? – CJK Feb 24 '18 at 13:32
  • @CJK - I write code and use various command line tools for DNA manipulation. I frequently need to find a position in a dna string that is on the command line amidst tons of other debug output to either confirm a modification or see what happened at a position. I typically do this via copy/paste into something that can show me the dna with cords and then I usually have to visually count <40 characters to the spot I’m looking for. It’s not always a simple character count either. Some strings have spaces. Some are aligned with gaps. Selecting the string and then using the service is much faster. – hepcat72 Feb 25 '18 at 15:10
0

So as I've learned, there are/were only 3 ways to manipulate the selection in Terminal by entering/using a length value (or via a series of keyboard presses).

  1. Accessibility Inspector shows that it should be possible to programmatically manipulate the selection length, because you can edit an existing selection length using the len field in the "Selected Text Range" in the "Advanced" section by clicking edit and entering a new number, as seen in the screen-cap: https://www.dropbox.com/s/bn2z6ewmdj4mfai/Accessibility_Inspector-selected_text_len.png?dl=0

The "Selected Text Range" Property/Attribute(?) does not appear to be accessible in AppleScript, though if it was accessible, it would be here: (text area of (scroll area 1 of (splitter group 1 of (front window)))) if you have enabled UI elements in your Applescript. It might be possible to access these values, as @CJK indicated in the comments via Objective-C. Applescript however, even if it could access the variable, likely wouldn't have the ability to alter it.

One useful feature to see what applescript can manipulate or has access to is to simply return attributes or return properties. For example:

tell application "System Events"
    if UI elements enabled is false then
        set UI elements enabled to true
        if UI elements enabled is false then error "Can't do it"
    end if
    tell application process "Terminal"
        tell window 1
            tell splitter group 1
                tell scroll area 1
                    --return properties
                    return attributes
                end tell
            end tell
        end tell
    end tell
end tell
  1. This method, as of OS X 10.8 no longer works, but making a selection in Terminal using the keyboard used to be possible, as described here. All you had to do was hit Command-Option-Return, navigate to the region you want to select with the arrow keys, hit return, select from the cursor position using the arrow keys, and hit return. I searched for the ability to re-enable this feature, but came up dry.

  2. There is a way to select text in the Terminal using the keyboard, but it's very limited. You can select text between "marks" using Command-Shift-A (not including the lines that the marks are on). Marks are added by default on every command prompt line. However, you can add marks by right-clicking a selection and typing Command-U. Marks are only per-line however, not specific to the selection start/stop on a line. If you right-click any unselected text that is soft-wrapped (i.e. multi-line string) and add a mark, a separate mark is added for every soft-wrapped line. You cannot select text between multiple marks, nor is it possible to add marks via applescript, thus it's not possible to use this to adjust a selection length programmatically. More info on marks can be found here.

I had also explored what the arrow keys are supposed to be able to do, since shift-{left,right}-arrow for me enters the strings ";2C" and ";2D" with a beep on the command line for me. So I removed those entries from the table in Terminal -> Preferences -> Profiles -> Keyboard to prevent that. I had hoped it would allow me to select text (at least on the current line prompt) using shift-arrow but all it did was move the cursor without selecting.

However, given the goal of this endeavor (to see where a coordinate is in a selected string), you can accomplish this via a dialog box from the Automator service using an Applescript. All you have to do is present the selection in a dialog box and if the target length is longer than the selection, you have to fill the remaining characters with a dummy character ('N' for DNA).

You can do this strategy conditionally, only when Terminal is the frontmost application. Note, this is not the entire script - just a snippet, but you can see the entire script here, which contains lots of bells & whistles unrelated to this question.

--Check the length of the selected text passed in
set character_count to count characters of ((input as string) as string)

set lengthen to false
set mod_length to character_count - n
--Figure out whether the selection must be lengthened or shrunk
if character_count is equal to 0 or n is greater than character_count then
    set lengthen to true
    set mod_length to n - character_count
end if

--See if we're in Terminal
set isTerminal to ((name of first process where it is frontmost) as string) is equal to "Terminal"

if isTerminal is true then
    if lengthen is true then
        set substr to (input as string)
        repeat mod_length times
            set substr to substr & "N"
        end repeat
    else
        set substr to text 1 thru n of (input as string)
        set substr to substr & (text (n + 1) thru character_count of (input as string))
    end if
    ignoring application responses
        display dialog "Length " & n & " is selected below:" default answer substr buttons {"OK"} default button 1 with title "Selected Character Position"
    end ignoring
end if

--Trick to make sure arrow presses affect the right side of the selection instead of the left
if not (character_count is equal to 0 or n is greater than character_count) then
    key code 124 using {shift down}
    key code 123 using {shift down}
    key code 124 using {shift down}
end if

repeat mod_length times
    if lengthen is true then
        key code 124 using {shift down}
    else
        key code 123 using {shift down}
    end if
end repeat
delay 1

That will effectively accomplish the end-goal. Unfortunately, the position has to be marked with a text marker in a variable-width type face since dialog boxes don't allow formatting or automatic selection of text.

  • I improved the solution. Note, I had to use ignoring application responses so that the arrow keys could operate on the selection in the dialog. The delay at the end keeps the dialog from immediately disappearing. – hepcat72 Feb 28 '18 at 21:51
  • BTW, I have used this strategy to create the services detailed in this gist: gist.github.com/hepcat72/3319f03f3b9e75ad2fa6e7f3d63c690b – hepcat72 Mar 5 '18 at 22:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .