Skip to content

Commit

Permalink
Grow selection stops at binding pairs
Browse files Browse the repository at this point in the history
* Fixes #2033
  • Loading branch information
PEZ committed Jun 1, 2023
1 parent 19d64e6 commit 6018813
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Changes to Calva.

## [Unreleased]

- [Grow selection considers ”form pairs” in bindings](https://github.com/BetterThanTomorrow/calva/issues/2033)

## [2.0.366] - 2023-06-01

- [Add a `$selection-closing-brackets` custom REPL snippets variable](https://github.com/BetterThanTomorrow/calva/issues/2212)
Expand Down
57 changes: 33 additions & 24 deletions src/cursor-doc/paredit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { validPair } from './clojure-lexer';
import { ModelEdit, EditableDocument, ModelEditSelection } from './model';
import { LispTokenCursor } from './token-cursor';
import { backspaceOnWhitespace } from './backspace-on-whitespace';
import _ = require('lodash');
import { currentForm } from '../api/ranges';

// NB: doc.model.edit returns a Thenable, so that the vscode Editor can compose commands.
// But don't put such chains in this module because that won't work in the repl-console.
Expand Down Expand Up @@ -961,9 +963,9 @@ export function growSelection(
start: number = doc.selection.anchor,
end: number = doc.selection.active
) {
const startC = doc.getTokenCursor(start),
endC = doc.getTokenCursor(end),
emptySelection = startC.equals(endC);
const startC = doc.getTokenCursor(start);
const endC = doc.getTokenCursor(end);
const emptySelection = startC.equals(endC);

if (emptySelection) {
const currentFormRange = startC.rangeForCurrentForm(start);
Expand All @@ -976,31 +978,38 @@ export function growSelection(
startC.backwardUpList();
endC.forwardList();
growSelectionStack(doc, [startC.offsetStart, endC.offsetEnd]);
return;
}
if (isInPairsList(startC, bindingForms)) {
const pairRange = currentSexpsRange(doc, startC, start, true);
if (!_.isEqual(pairRange, [start, end])) {
growSelectionStack(doc, pairRange);
return;
}
}
if (startC.backwardList()) {
// we are in an sexpr.
endC.forwardList();
endC.previous();
} else {
if (startC.backwardList()) {
// we are in an sexpr.
endC.forwardList();
endC.previous();
} else {
if (startC.backwardDownList()) {
startC.backwardList();
if (emptySelection) {
endC.set(startC);
endC.forwardList();
endC.next();
}
startC.previous();
} else if (startC.downList()) {
if (emptySelection) {
endC.set(startC);
endC.forwardList();
endC.next();
}
startC.previous();
if (startC.backwardDownList()) {
startC.backwardList();
if (emptySelection) {
endC.set(startC);
endC.forwardList();
endC.next();
}
startC.previous();
} else if (startC.downList()) {
if (emptySelection) {
endC.set(startC);
endC.forwardList();
endC.next();
}
startC.previous();
}
growSelectionStack(doc, [startC.offsetStart, endC.offsetEnd]);
}
growSelectionStack(doc, [startC.offsetStart, endC.offsetEnd]);
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/extension-test/unit/cursor-doc/paredit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,30 @@ describe('paredit', () => {
new ModelEditSelection(a[0], a[1])
);
});
it('grows selection to binding pairs', () => {
const a = docFromTextNotation('(a (let [b c |e| f]))');
const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active);
const b = docFromTextNotation('(a (let [b c |e f|]))');
const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active);
paredit.growSelection(a);
expect(a.selectionStack).toEqual([aSelection, bSelection]);
});
it('grows selection to all of binding box when binding pairs are selected', () => {
const a = docFromTextNotation('(a (let [b c |e f|]))');
const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active);
const b = docFromTextNotation('(a (let [|b c e f|]))');
const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active);
paredit.growSelection(a);
expect(a.selectionStack).toEqual([aSelection, bSelection]);
});
it('grows selection to the binding box when all binding pairs are selected', () => {
const a = docFromTextNotation('(a (let [|b c e f|]))');
const aSelection = new ModelEditSelection(a.selection.anchor, a.selection.active);
const b = docFromTextNotation('(a (let |[b c e f]|))');
const bSelection = new ModelEditSelection(b.selection.anchor, b.selection.active);
paredit.growSelection(a);
expect(a.selectionStack).toEqual([aSelection, bSelection]);
});
});

describe('dragSexpr', () => {
Expand Down

0 comments on commit 6018813

Please sign in to comment.