Sublime Forum

Move caret to beginning or end of selection without losing selection

#1

Hi, I would like the following functionality: when a region of text is selected, be able to move the caret to the end or beginning of the selected region without losing the selection. (This could be useful to tweak the endpoints of the selection, with shift + arrow keys.) These would be my dream key bindings:

alt+right arrow -> move to end of selected region when selected region is present, without losing selection (instead of moving forward one word and losing selection)
alt+left arrow -> move to end of selected region when selected region is present, without losing selection (instead of moving backward one word and losing selection)

Thanks!

0 Likes

#2

There may or may not be a plugin for this on Package Control already (probably with more functionality) but here’s an example that does something like this:

import sublime
import sublime_plugin

class ChangeSelectionEndpointCommand(sublime_plugin.TextCommand):
    def run(self, edit, begin):
        new_sel = []
        for sel in self.view.sel():
            reverse = (sel.a < sel.b) if begin else (sel.b < sel.a)
            new_sel.append(sublime.Region(sel.b, sel.a) if reverse else sel)

        self.view.sel().clear()
        self.view.sel().add_all(new_sel)

Basically, when invoked it looks at every selection, and reverses the beginning and end of the selection (which changes the end at which the caret is positioned) based on the value of the parameter that you pass in. To use, you can select Tools > Developer > New Plugin... from the menu, then replace the stub file contents with this text and save it.

Key bindings like the following will activate it as you describe above. The contexts make the binding only active while there is a selection (i.e. when selection_empty is false) so that the default bindings will still work as expected.

{
    "keys": ["alt+left"], "command": "change_selection_endpoint",
    "args": { "begin": true },
    "context": [
        { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": false },
    ]
},
{
    "keys": ["alt+right"], "command": "change_selection_endpoint",
    "args": { "begin": false },
    "context": [
        { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": false },
    ]
},

Here I’ve set match_all to false, which means that in cases when there is more than one caret, as long as one of them has a selection the command will trigger and the caret position will jump (any caret without a selection will be visibly unchanged).

To me at least, this seems to make the most sense for this operation. If you like, you can set match_all to true in the bindings, in which case if there are multiple carets, all of them have to have a selection for the command to trigger.

2 Likes

Looking for advice on how to factor plugins
#3

You can also try the “Normalize and toggle region ends” feature of MultiEditUtils.

Example

2 Likes

#4

@OdatNurd: your solution works for me :slight_smile:.

@r-stein: Thanks, I will take a look at that package!

0 Likes