Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#610 Multi Cursor for paredit #1606

Open
wants to merge 54 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
a482351
fixes #1607 selection api cleanup
riotrah Mar 20, 2022
815e4bf
reformat + undo auto import organize
riotrah Mar 26, 2022
87c6d49
Multi Cursor for paredit Expand selection and shrink selection
riotrah Mar 19, 2022
4616405
2nd attempt multi cursor paredit start
riotrah Mar 20, 2022
b090921
Make most multi cursor work, tons of tests changes
riotrah Mar 28, 2022
5f12aea
Experiment with mixing native delete/backspace with paredit per-cursor
riotrah Apr 1, 2022
0b377a8
Fix spelling mistake
riotrah Apr 1, 2022
d00a3c2
prettier format files
riotrah Apr 1, 2022
5594bc4
prettier format (again lol)
riotrah Apr 2, 2022
5c8a408
Post forward or up commands rebase fixes; multi cursor seems to work!
riotrah Apr 2, 2022
57a1d9a
Add more cspell exceptions
riotrah Apr 2, 2022
2bcc6e7
Double each example in test-date/paredit-sandbox for multi cursor tests
riotrah Apr 2, 2022
40f2612
Format
riotrah Apr 2, 2022
46d4fce
Fix unit test watcher not capturing changes
riotrah Apr 7, 2022
6f8a758
Add whole-project format step before compile
riotrah Apr 7, 2022
8fd9345
Update text notations utils for new syntax; cleanup
riotrah Apr 7, 2022
49f77e8
Add textNotationFromDoc debug unit test util + test for it
riotrah Apr 7, 2022
230dff6
Add distance/isSelection/isCursor utility props to ModelEditSelection
riotrah Apr 7, 2022
2242e08
Remove naive EditableDocument .delete() .backspace() single cursor args
riotrah Apr 7, 2022
4f77f77
Make ModelEdit generic with edit fn as type param + utils, fix dead code
riotrah Apr 7, 2022
071b4d2
Simplify overloaded paredit funcs
riotrah Apr 7, 2022
6c5a74a
Create exported functions for killForward/BackwardList/Sexp, fix multi
riotrah Apr 7, 2022
308d3e7
Merge branch 'dev' into rayat-amperity/issue610
riotrah Apr 7, 2022
c79490c
Update changelog. Fixes #610
riotrah Apr 7, 2022
bcf8838
Merge branch 'rayat-amperity/issue610' of https://github.com/rayat-am…
PEZ Apr 8, 2022
e991540
Add command for getting textnotation from doc
PEZ Apr 8, 2022
464f041
Merge pull request #1 from BetterThanTomorrow/rayat-amperity-rayat-am…
rayat-amperity Apr 8, 2022
61087b5
Remove cursor when-contexts. Let's hope no one's mad !
riotrah Apr 7, 2022
1e44247
Fix Expand Selection selects only open parens bug
riotrah Apr 8, 2022
0877a1e
Merge branch 'dev' into rayat-amperity/issue610
PEZ Apr 9, 2022
43f67f3
Change newline text-notation `•` -> `§`
PEZ Apr 9, 2022
dfed45e
Add link to text-notation video
PEZ Apr 9, 2022
7c7a926
Add some multi-cursor tests
PEZ Apr 9, 2022
fc51d29
Add command for creating doc from text-notation
PEZ Apr 9, 2022
7a06377
Update changelog [skip ci]
PEZ Apr 9, 2022
0d37220
Add failing test for docFromTextNotation
PEZ Apr 9, 2022
f5651f3
Update changelog
PEZ Apr 9, 2022
ace972e
Add tests exposing docFromTextNotation bug
PEZ Apr 9, 2022
62a922f
Fix tNToDoc regressions
riotrah Apr 10, 2022
7f133a2
Add a selection smorgasboard test
PEZ Apr 10, 2022
ac76eb1
Add more tests barf and splice
PEZ Apr 10, 2022
5d5c1e4
Add some tests for Wrap Sexp
PEZ Apr 10, 2022
180c757
Add some tests for kill-right
PEZ Apr 10, 2022
bccbafb
Merge branch 'dev' into rayat-amperity/issue610
riotrah Apr 14, 2022
29da58e
Simplify tasks.json
riotrah Apr 14, 2022
98750bd
Add some paredit related utils
riotrah Apr 14, 2022
394c9fe
Start experimental multi cursor copy-paste paredit
riotrah Apr 14, 2022
cd90fa9
Some cleanup, spelling
riotrah Apr 14, 2022
345e8cd
Decouple textNotationFromDoc into textNotationFromTextAndSelection
riotrah Apr 14, 2022
d33bedd
Make 'Multi-cursors maintain balanced delimiters" pass
riotrah Apr 14, 2022
ead4af0
Latest multi cursor tests pass
riotrah Apr 15, 2022
a095c45
Add test for one-line text-notation w trailing cursor
PEZ Apr 18, 2022
86dff85
Remove funny precompile command
PEZ Apr 18, 2022
5975c48
Use dev tasks.json
PEZ Apr 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
"ahlbrecht",
"alnum",
"Alsos",
"analyse",
"analysing",
"arglist",
"arglists",
"autoindent",
"avli",
"Batsov",
"behaviour",
"bencode",
Expand All @@ -24,11 +26,15 @@
"calva",
"Calva's",
"calvapretty",
"ccls",
"chmod",
"cibuilds",
"circleci",
"clangd",
"classpath",
"clientrc",
"cljc",
"cljd",
"cljfmt",
"cljfx",
"cljify",
Expand All @@ -44,7 +50,9 @@
"Cognitect",
"Configurability",
"cospaia",
"cpcache",
"Dallo",
"darcs",
"datafication",
"debugable",
"debugadapter",
Expand All @@ -68,10 +76,12 @@
"Elisp",
"enablement",
"enablements",
"ensime",
"entrypoint",
"errored",
"ESPACEIALLY",
"être",
"eunit",
"eval",
"evals",
"falsesomething",
Expand All @@ -82,6 +92,7 @@
"filipe",
"fipp",
"foob",
"fslckout",
"FUBAR",
"gifs",
"Girardi",
Expand Down Expand Up @@ -139,6 +150,7 @@
"parinfer",
"pidfile",
"piggieback",
"pijul",
"polyrepos",
"postrelease",
"pprint",
Expand Down Expand Up @@ -189,6 +201,7 @@
"unpromote",
"unpromoted",
"unsets",
"uuidv",
"visibles",
"vsce",
"vscodevim",
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
Changes to Calva.

## [Unreleased]
- [Multi cursor support for Paredit](https://github.com/BetterThanTomorrow/calva/issues/610)
- [Remove when-contexts as a way to control when commands move by sexp or by word](https://github.com/BetterThanTomorrow/calva/pull/1606#issuecomment-1086567905)

## [2.0.267] - 2022-04-13
- [Add command for formatting away multiple space between forms on the same line](https://github.com/BetterThanTomorrow/calva/issues/1677)
- [Merge LSP + NREPL completions and goToDefintion](https://github.com/BetterThanTomorrow/calva/issues/1498)

## [2.0.266] - 2022-04-11
- Fix: [Jump between source/test does not work properly with multiple workspace folders](https://github.com/BetterThanTomorrow/calva/issues/1219)
- [New diagnostics command, Print TextNotation from current document](https://github.com/BetterThanTomorrow/calva/issues/1675) (See [this CalvaTV video](https://www.youtube.com/watch?v=Sy3arG-Degw))
- [New diagnostics command, Create untitled document from TextNotation](https://github.com/BetterThanTomorrow/calva/issues/1676)

## [2.0.265] - 2022-04-08
- [Update paredit sexp forward/backward command labels](https://github.com/BetterThanTomorrow/calva/issues/1660)
Expand Down
16 changes: 8 additions & 8 deletions docs/site/customizing.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The versions used are configurable via the VS Code settings `calva.jackInDepende

## Key bindings

Most of Calva's commands have default keybindings. They are only defaults, though, and you can change keybindings as you wish. To facilitate precision in binding keys Calva keeps some [when clause contexts](https://code.visualstudio.com/api/references/when-clause-contexts) updated.
Most of Calva's commands have default keybindings. They are only defaults, though, and you can change keybindings as you wish. To facilitate precision in binding keys Calva keeps some [when clause contexts](https://code.visualstudio.com/api/references/when-clause-contexts) updated.

### When Clause Contexts

Expand All @@ -87,15 +87,15 @@ The following contexts are available with Calva:
* `calva:outputWindowActive`: `true` when the [Output/REPL window](output.md) has input focus
* `calva:replHistoryCommandsActive`: `true` when the cursor is in the Output/REPL window at the top level after the last prompt
* `calva:outputWindowSubmitOnEnter`: `true` when the cursor is adjacent after the last top level form in the Output/REPL window
* `calva:cursorInString`: `true` when the cursor/caret is in a string or a regexp
* `calva:cursorInComment`: `true` when the cursor is in, or adjacent to a line comment
* `calva:cursorBeforeComment`: `true` when the cursor is adjacent before a line comment
* `calva:cursorAfterComment`: `true` when the cursor is adjacent after a line comment
* `calva:cursorAtStartOfLine`: `true` when the cursor is at the start of a line including any leading whitespace
* `calva:cursorAtEndOfLine`: `true` when the cursor is at the end of a line including any trailing whitespace
<!-- * `calva:cursorInString`: `true` when the cursor/caret is in a string or a regexp -->
<!-- * `calva:cursorInComment`: `true` when the cursor is in, or adjacent to a line comment -->
<!-- * `calva:cursorBeforeComment`: `true` when the cursor is adjacent before a line comment -->
<!-- * `calva:cursorAfterComment`: `true` when the cursor is adjacent after a line comment -->
<!-- * `calva:cursorAtStartOfLine`: `true` when the cursor is at the start of a line including any leading whitespace -->
<!-- * `calva:cursorAtEndOfLine`: `true` when the cursor is at the end of a line including any trailing whitespace -->
* `calva:showReplUi`: `false` when Calva's REPL UI is disabled through the corresponding setting

### Some Custom Bindings
### Some Custom Bindings

Here is a collection of custom keybindings from here and there.

Expand Down
38 changes: 24 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
},
"printEngine": {
"type": "string",
"description": "The print engine to use. 'calva' means that the nREPL server will first plain print it and then Calva will prettify. The other options will make the server use the chosen printer-function to print the result, and Calva will not reformat it. To use some other function (on the server), configure `printFn` instead. To use the `nREPL` default (the equivalent of `clojure.core/pr`), set neither this nore `printFn`.",
"description": "The print engine to use. 'calva' means that the nREPL server will first plain print it and then Calva will prettify. The other options will make the server use the chosen printer-function to print the result, and Calva will not reformat it. To use some other function (on the server), configure `printFn` instead. To use the `nREPL` default (the equivalent of `clojure.core/pr`), set neither this nor `printFn`.",
"enum": [
"calva",
"pprint",
Expand Down Expand Up @@ -917,6 +917,16 @@
"title": "Toggle nREPL Logging Enabled",
"category": "Calva Diagnostics"
},
{
"command": "calva.diagnostics.printTextNotationFromDocument",
"title": "Print TextNotation from the current document to Calva says",
"category": "Calva Diagnostics"
},
{
"command": "calva.diagnostics.createDocumentFromTextNotation",
"title": "Create a new Clojure Document from TextNotation",
"category": "Calva Diagnostics"
},
{
"command": "calva.linting.resolveMacroAs",
"title": "Resolve Macro As",
Expand Down Expand Up @@ -1895,28 +1905,28 @@
"mac": "ctrl+left",
"win": "alt+left",
"linux": "alt+left",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment || calva:cursorBeforeComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.backwardSexp",
"mac": "alt+left",
"win": "ctrl+left",
"linux": "ctrl+left",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment || calva:cursorBeforeComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.forwardSexp",
"mac": "ctrl+right",
"win": "alt+right",
"linux": "alt+right",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment || calva:cursorAfterComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.forwardSexp",
"mac": "alt+right",
"win": "ctrl+right",
"linux": "ctrl+right",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment || calva:cursorAfterComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.forwardDownSexp",
Expand Down Expand Up @@ -2009,14 +2019,14 @@
"mac": "ctrl+w",
"win": "shift+alt+right",
"linux": "shift+alt+right",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.sexpRangeContraction",
"mac": "ctrl+shift+w",
"win": "shift+alt+left",
"linux": "shift+alt+left",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.slurpSexpForward",
Expand Down Expand Up @@ -2068,22 +2078,22 @@
{
"command": "paredit.dragSexprBackward",
"key": "ctrl+shift+alt+b",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.dragSexprForward",
"key": "ctrl+shift+alt+f",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/ && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /original|strict/"
},
{
"command": "paredit.dragSexprBackward",
"key": "alt+up",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /strict/ && config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /strict/ && config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.dragSexprForward",
"key": "alt+down",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /strict/ && config.calva.paredit.hijackVSCodeDefaults && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap =~ /strict/ && config.calva.paredit.hijackVSCodeDefaults"
},
{
"command": "paredit.dragSexprBackwardUp",
Expand Down Expand Up @@ -2190,12 +2200,12 @@
{
"command": "paredit.deleteForward",
"key": "delete",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap == strict && !editorReadOnly && !editorHasMultipleSelections && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap == strict && !editorReadOnly && !editorHasMultipleSelections"
},
{
"command": "paredit.deleteBackward",
"key": "backspace",
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap == strict && !editorReadOnly && !editorHasMultipleSelections && !calva:cursorInComment"
"when": "calva:keybindingsEnabled && editorLangId == clojure && editorTextFocus && paredit:keyMap == strict && !editorReadOnly && !editorHasMultipleSelections"
},
{
"command": "paredit.forceDeleteForward",
Expand Down Expand Up @@ -2729,7 +2739,7 @@
"calva-lib-test": "node ./out/cljs-lib/test/cljs-lib-tests.js",
"integration-test": "node ./out/extension-test/integration/runTests.js",
"unit-test": "npx mocha --require ts-node/register 'src/extension-test/unit/**/*-test.ts'",
"unit-test-watch": "npx mocha --watch --require ts-node/register 'src/extension-test/unit/**/*-test.ts'",
"unit-test-watch": "npx mocha --watch --require ts-node/register --watch-extensions ts --watch-files src 'src/extension-test/unit/**/*-test.ts'",
"publish": "bb publish.clj",
"prettier-format": "npx prettier --write './**/*.{ts,js,json}'",
"prettier-check": "npx prettier --check './**/*.{ts,js,json}'",
Expand Down
7 changes: 4 additions & 3 deletions src/calva-fmt/src/providers/ontype_formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getConfig } from '../../../config';
import * as util from '../../../utilities';

export class FormatOnTypeEditProvider implements vscode.OnTypeFormattingEditProvider {
async provideOnTypeFormattingEdits(
provideOnTypeFormattingEdits(
document: vscode.TextDocument,
_position: vscode.Position,
ch: string,
Expand All @@ -22,10 +22,11 @@ export class FormatOnTypeEditProvider implements vscode.OnTypeFormattingEditProv
if (tokenCursor.withinComment()) {
return undefined;
}
return paredit.backspace(mDoc).then((fulfilled) => {
paredit.close(mDoc, ch);
void paredit.backspace(mDoc).then((fulfilled) => {
void paredit.close(mDoc, ch);
return undefined;
});
return;
} else {
return undefined;
}
Expand Down
36 changes: 19 additions & 17 deletions src/cursor-doc/cursor-context.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { EditableDocument } from './model';

export const allCursorContexts = [
'calva:cursorInString',
'calva:cursorInComment',
'calva:cursorAtStartOfLine',
'calva:cursorAtEndOfLine',
'calva:cursorBeforeComment',
'calva:cursorAfterComment',
// 'calva:cursorInString',
// 'calva:cursorInComment',
// 'calva:cursorAtStartOfLine',
// 'calva:cursorAtEndOfLine',
// 'calva:cursorBeforeComment',
// 'calva:cursorAfterComment',
] as const;

export type CursorContext = typeof allCursorContexts[number];
Expand All @@ -15,7 +15,7 @@ export type CursorContext = typeof allCursorContexts[number];
* Returns true if documentOffset is either at the first char of the token under the cursor, or
* in the whitespace between the token and the first preceding EOL, otherwise false
*/
export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selection.active) {
export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selections[0].active) {
const tokenCursor = doc.getTokenCursor(offset);
let startOfLine = false;
// only at start if we're in ws, or at the 1st char of a non-ws sexp
Expand All @@ -33,7 +33,7 @@ export function isAtLineStartInclWS(doc: EditableDocument, offset = doc.selectio
* Returns true if position is after the last char of the last lisp token on the line, including
* any trailing whitespace or EOL, otherwise false
*/
export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selection.active) {
export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selections[0].active) {
const tokenCursor = doc.getTokenCursor(offset);
if (tokenCursor.getToken().type === 'eol') {
return true;
Expand All @@ -56,27 +56,29 @@ export function isAtLineEndInclWS(doc: EditableDocument, offset = doc.selection.
return false;
}

// TODO: setting the vscode ext context for cursor context might not work for multi-cursor
export function determineContexts(
doc: EditableDocument,
offset = doc.selection.active
): CursorContext[] {
offset = doc.selections[0].active
): readonly CursorContext[] {
const tokenCursor = doc.getTokenCursor(offset);
const contexts: CursorContext[] = [];
// const contexts: CursorContext[] = [];
const contexts: readonly CursorContext[] = allCursorContexts;

if (isAtLineStartInclWS(doc)) {
contexts.push('calva:cursorAtStartOfLine');
// contexts.push('calva:cursorAtStartOfLine');
} else if (isAtLineEndInclWS(doc)) {
contexts.push('calva:cursorAtEndOfLine');
// contexts.push('calva:cursorAtEndOfLine');
}

if (tokenCursor.withinString()) {
contexts.push('calva:cursorInString');
// contexts.push('calva:cursorInString');
} else if (tokenCursor.withinComment()) {
contexts.push('calva:cursorInComment');
// contexts.push('calva:cursorInComment');
}

// Compound contexts
if (contexts.includes('calva:cursorInComment')) {
/* if (contexts.includes('calva:cursorInComment')) {
if (contexts.includes('calva:cursorAtEndOfLine')) {
tokenCursor.forwardWhitespace(false);
if (tokenCursor.getToken().type != 'comment') {
Expand All @@ -88,7 +90,7 @@ export function determineContexts(
contexts.push('calva:cursorBeforeComment');
}
}
}
} */

return contexts;
}
Loading