Skip to content

Commit

Permalink
Added selectBetween motion
Browse files Browse the repository at this point in the history
Selects all text between user specified characters.
  • Loading branch information
haberdashPI committed Jan 17, 2024
1 parent 3de09a9 commit 9cd0bad
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Change Log

## [0.6.0]
- **Feature**: `selectBetween` allows selection between two or more characters.

## [0.5.1]
- **Feature**: `revealActive` reveal the active position of the primary cursor

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -5,7 +5,7 @@
[![Project Documentation](https://img.shields.io/badge/docs-dev-blue)](https://haberdashpi.github.io/vscode-selection-utilities/dev/README.html)

This extension provides a series of utilities for manipulating, saving and creating both single and
multiple selections, inspired by [Kakoune](http://kakoune.org/).
multiple selections, many of which are inspired by [Kakoune](http://kakoune.org/).

There are many commands, and they are designed to work together. They work well in conjunction with
[ModalKeys](https://github.com/haberdashPI/vscode-modal-keys). In particular the [Larkin](https://haberdashpi.github.io/vscode-modal-keys/stable/presets/larkin.html) presets available in ModalKeys make extensive use of all features from this extension.
Expand Down Expand Up @@ -35,7 +35,7 @@ paragrpah etc...).
### Saving selections

These commands save a selection for later, or add any arbitrary selection to a list of
soon-to-be multiple selections.
soon-to-be multiple selections.

![Saved Selection Animation](./docs/images/save_selection.gif)

Expand Down
33 changes: 25 additions & 8 deletions docs/motions.md
@@ -1,4 +1,4 @@
# Selection Motions
## Unit Selection Motions

There are two advantages to these motions over the built-in motions

Expand All @@ -10,7 +10,7 @@ Below are the pre-defined motions, all of which can be customized. For ultimate
flexibility, you can use the generic [`moveby`](#the-custom-moveby-command)
command. The units are defined by regex's (listed in the next section).

## Move cursor
### Move cursor

These commands move the cursor, without selecting.

Expand All @@ -24,7 +24,7 @@ These commands move the cursor, without selecting.
- "Move Cursor to Previous Subsection": `selection-utilities.moveToPreviousSubsection`
- "Move Cursor to Previous Section": `selection-utilities.moveToPreviousSection`

## Move selection
### Move selection

These commands adjust both the start and end of the selection, so that it surrounds the given unit.

Expand All @@ -41,7 +41,7 @@ These commands adjust both the start and end of the selection, so that it surrou
- "Move Selection to Previous Subsection": `selection-utilities.moveToPreviousSubsection`
- "Move Selection to Previous Section": `selection-utilities.moveToPreviousSection`

## Select to unit
### Select to unit

These commands adjust one end of the selection by the given unit.

Expand All @@ -61,7 +61,7 @@ These commands adjust one end of the selection by the given unit.
- "Move Cursor to Next Word": `selection-utilities.moveToNextWord`
- "Move Cursor to Next non-whitespace characters": `selection-utilities.moveToNextWORD`

## Custom Motions
### Custom Motions

You can define any units you wish to move the cursor by using `motionUnits`.

Expand Down Expand Up @@ -92,7 +92,7 @@ Note that some of the units employ multi-line matches using `regexs` instead of
`regex`. For more on how to define multi-line units, see the final subsection
below.

### The custom `moveBy` command
#### The custom `moveBy` command

The `moveby` command moves the cursor according to one of the regular expressions
you defined in your settings. It takes five optional arguments.
Expand Down Expand Up @@ -123,7 +123,7 @@ command in your `keybindings.json` file.
}
```

### The `narrowTo` command
#### The `narrowTo` command

The `narrowto` command shrinks the current boundaries of the current selection
until it is directly at the given boundaries of the regular expression. It
Expand All @@ -149,7 +149,7 @@ pressing `cmd+(` you could add the following to `keybindings.json`.
}
```

## Multi-line units
### Multi-line units

The units can work for multi-line matches. To use this feature, change the unit entry to use `regexs` instead of `regex`.

Expand Down Expand Up @@ -200,3 +200,20 @@ You could then select all code in the section using a keybinding like follows.
"key": "shift+cmd+0",
}
```

## Symmetric Selection Motion

The command `selection-utilities.selectBetween` can be used to select text between two
given characters. Note that this selection is non-syntactic, so it isn't smart about
e.g. nested parenthesis. None-the-less, this can be a useful command, e.g. when
there are no recognized syntactic brackets in a given type of file.

It's arguments are:

- `str`: Select text between pairs of the given string e.g. `str = "*"` would select "bob"
in the string "joe*bob*"
- `between`: An object that lets you select text that starts with `from` and ends with `to`:
in the string "joe x bob y", the argument `between = {from: "x", to: "y"}` would select
" bob ". (Only one of `str` or `between` should be defined for a given call)
- `inclusive`: Whether to include the surrounding pair in the selection: e.g. do you select
"bob" or "*bob*" in the above example.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -4,7 +4,7 @@
"publisher": "haberdashPI",
"repository": "https://github.com/haberdashPI/vscode-selection-utilities",
"description": "Kakaune-inspired collection of useful commands for manipulating selections.",
"version": "0.5.1",
"version": "0.5.2",
"icon": "logo.png",
"engines": {
"vscode": "^1.55.0"
Expand All @@ -22,6 +22,7 @@
"onCommand:selection-utilities.revealActive",
"onCommand:selection-utilities.expandWithinBrackets",
"onCommand:selection-utilities.expandAroundBrackets",
"onCommand:selection-utilities.selectBetween",
"onCommand:selection-utilities.focusPrimarySelection",
"onCommand:selection-utilities.appendToMemory",
"onCommand:selection-utilities.restoreAndClear",
Expand Down
51 changes: 48 additions & 3 deletions src/symmetricModifiers.ts
Expand Up @@ -12,6 +12,8 @@ export function registerSymmetricModifiers(context: vscode.ExtensionContext) {
registerCommand('selection-utilities.expandWithinBrackets', expandWithinBrackets));
context.subscriptions.push(vscode.commands.
registerCommand('selection-utilities.expandAroundBrackets', expandAroundBrackets));
context.subscriptions.push(vscode.commands.
registerCommand('selection-utilities.selectBetween', selectBetween));
}

interface InsertAroundArgs{
Expand All @@ -23,7 +25,7 @@ async function insertAround(args: InsertAroundArgs){
let editor = vscode.window.activeTextEditor;
if(editor){
let ed = editor;
let ranges = editor.selections.map(sel =>
let ranges = editor.selections.map(sel =>
new vscode.Range(sel.start, sel.end));

await editor.edit(builder => {
Expand Down Expand Up @@ -56,18 +58,61 @@ function deleteAround(args: {count?: number }){
editor.edit(builder => {
for(const sel of ed.selections){
builder.delete(new vscode.Range(
wrappedTranslate(sel.start, ed.document, -(args.count || 1)),
wrappedTranslate(sel.start, ed.document, -(args.count || 1)),
sel.start)
);
builder.delete(new vscode.Range(
sel.end,
sel.end,
wrappedTranslate(sel.end, ed.document, (args.count || 1)))
);
}
});
}
}

function selectBetween(args: {str?: string, between?: {from: string, to: string}, inclusive: false}){
let editor = vscode.window.activeTextEditor;
if(editor){
let ed = editor;
ed.selections = ed.selections.map(sel => {
let seekStart = args.str || args?.between?.from;
let seekEnd = args.str || args?.between?.to;
if(!seekStart || !seekEnd){
vscode.window.showErrorMessage("Expected either `str` or `between = {from, to}` field for `selectBetween`")
}else{
let start = new vscode.Range(wrappedTranslate(sel.start, ed.document, -seekStart.length), sel.start);
let end = new vscode.Range(sel.end, wrappedTranslate(sel.start, ed.document, seekEnd.length));
let startStr = ed.document.getText(start);
while(startStr.length === seekStart.length){
if(startStr === seekStart){ break; }
let startFrom = wrappedTranslate(start.end, ed.document, -1);
let startTo = wrappedTranslate(start.start, ed.document, -1);
start = new vscode.Range(startTo, startFrom);
startStr = ed.document.getText(start)
}

let endStr = ed.document.getText(end);
while(endStr.length === seekStart?.length){
if(endStr === seekEnd){ break; }
let endFrom = wrappedTranslate(end.end, ed.document, 1);
let endTo = wrappedTranslate(end.start, ed.document, 1);
end = new vscode.Range(endTo, endFrom);
endStr = ed.document.getText(end)
}

if(startStr === seekStart && endStr === seekEnd){
if(args.inclusive){
return new vscode.Selection(start.start, end.end);
}else{
return new vscode.Selection(start.end, end.start);
}
}
}
return sel;
});
}
}


function adjustSelections(args: {dir: string, count: number}){
let editor = vscode.window.activeTextEditor;
Expand Down
5 changes: 2 additions & 3 deletions src/util.ts
Expand Up @@ -16,15 +16,15 @@ export function compareSels(a: vscode.Selection, b: vscode.Selection){
export function wrappedTranslate(x: vscode.Position, doc: vscode.TextDocument, val: number){
if(val < 0){
let result = x
while(result.character + val < 0){
while(result.character + val < 0 && result.line >= 0){
val += 1;
result = result.translate(-1, 0);
result = result.translate(0, doc.lineAt(result).range.end.character)
}
return result.translate(0, val);
}else{
let result = x;
while(result.character + val > doc.lineAt(result).range.end.character){
while(result.character + val > doc.lineAt(result).range.end.character && result.line <= doc.lineCount+1){
val -= 1;
result = new vscode.Position(result.line+1, 0)
}
Expand All @@ -38,4 +38,3 @@ export function clampedLineTranslate(x: vscode.Position, doc: vscode.TextDocumen
else if(newline < 0) newline = 0;
return new vscode.Position(newline, 0);
}

0 comments on commit 9cd0bad

Please sign in to comment.