Skip to content

Contiguous scope #2101

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

Draft
wants to merge 41 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
fdcd03e
Started working on contiguous scope modifier
AndreasArvidsson Dec 5, 2023
f223d84
Merge branch 'main' into contiguous_scope
AndreasArvidsson Dec 5, 2023
b549ca5
more work
AndreasArvidsson Dec 5, 2023
a71f017
Change continuous scope modifier into continuous scope type
AndreasArvidsson Dec 6, 2023
da8d6ec
Added tests
AndreasArvidsson Dec 6, 2023
a3fa351
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Dec 6, 2023
53351e8
Moved tests
AndreasArvidsson Dec 6, 2023
d370690
Added comment
AndreasArvidsson Dec 6, 2023
48f97ee
cleanup
AndreasArvidsson Dec 6, 2023
e2ec5c8
more cleanup
AndreasArvidsson Dec 6, 2023
d1020a8
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
02a295e
Import
AndreasArvidsson Dec 6, 2023
9d75ead
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
48c7a65
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
fa57ab2
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
c943542
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
c26d704
Update packages/cursorless-engine/src/processTargets/modifiers/scopeH…
AndreasArvidsson Dec 6, 2023
e0b6b5b
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Dec 6, 2023
2988adb
rename
AndreasArvidsson Dec 6, 2023
c2f942b
Merge
AndreasArvidsson Dec 6, 2023
34cbbb1
update
AndreasArvidsson Dec 6, 2023
8b5a95f
Use proximal and distal
AndreasArvidsson Dec 7, 2023
bd86a64
Continues target
AndreasArvidsson Dec 7, 2023
5a905ea
Added tests
AndreasArvidsson Dec 7, 2023
6612818
cleanup
AndreasArvidsson Dec 7, 2023
2852e37
Merge branch 'main' into contiguous_scope
AndreasArvidsson Dec 7, 2023
d3eb687
clean up
AndreasArvidsson Dec 8, 2023
fe7e8e5
Merge branch 'contiguous_scope' of github.com:cursorless-dev/cursorle…
AndreasArvidsson Dec 8, 2023
2f15dc6
Only do contiguous for comments
AndreasArvidsson Dec 14, 2023
0ccdcc6
cleanup
AndreasArvidsson Dec 14, 2023
fd93230
Merge branch 'main' into contiguous_scope
AndreasArvidsson Dec 14, 2023
d898f26
cleanup
AndreasArvidsson Dec 14, 2023
ea5a542
Update test
AndreasArvidsson Dec 14, 2023
66731e4
Added predicate
AndreasArvidsson Dec 15, 2023
58bfb9a
Merge branch 'main' into contiguous_scope
AndreasArvidsson Dec 15, 2023
b6ac60f
Added comment facets
AndreasArvidsson Dec 15, 2023
17b0507
Remove pattern argument from contiguous predicate
AndreasArvidsson Feb 26, 2024
6f0de5c
Merge branch 'main' into contiguous_scope
AndreasArvidsson Feb 26, 2024
9f156a6
Update scope fixtures
AndreasArvidsson Feb 26, 2024
38ab206
Merge branch 'main' into contiguous_scope
AndreasArvidsson Jun 14, 2024
883eb1e
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Jun 14, 2024
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
15 changes: 15 additions & 0 deletions data/fixtures/scopes/java/comment.block.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Hello world
*/
---

[Content] =
[Removal] =
[Domain] = 0:0-2:2
>--
0| /*
1| Hello world
2| */
--<

[Insertion delimiter] = "\n"
15 changes: 15 additions & 0 deletions data/fixtures/scopes/java/comment.block2.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Hello world
*/
---

[Content] =
[Removal] =
[Domain] = 0:0-2:2
>---
0| /**
1| * Hello world
2| */
--<

[Insertion delimiter] = "\n"
13 changes: 13 additions & 0 deletions data/fixtures/scopes/java/comment.block3.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Hello
// World
---

[Content] =
[Removal] =
[Domain] = 0:0-1:8
>--------
0| // Hello
1| // World
--------<

[Insertion delimiter] = "\n"
10 changes: 10 additions & 0 deletions data/fixtures/scopes/java/comment.line.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Hello world
---

[Content] =
[Removal] =
[Domain] = 0:0-0:14
>--------------<
0| // Hello world

[Insertion delimiter] = "\n"
13 changes: 13 additions & 0 deletions data/fixtures/scopes/javascript.core/comment.block3.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Hello
// World
---

[Content] =
[Removal] =
[Domain] = 0:0-1:8
>--------
0| // Hello
1| // World
--------<

[Insertion delimiter] = "\n"
13 changes: 13 additions & 0 deletions data/fixtures/scopes/python/comment.block.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Hello
# World
---

[Content] =
[Removal] =
[Domain] = 0:0-1:7
>-------
0| # Hello
1| # World
-------<

[Insertion delimiter] = "\n"
10 changes: 10 additions & 0 deletions data/fixtures/scopes/python/comment.line.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Hello world
---

[Content] =
[Removal] =
[Domain] = 0:0-0:13
>-------------<
0| # Hello world

[Insertion delimiter] = "\n"
13 changes: 13 additions & 0 deletions data/fixtures/scopes/talon/comment.block.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Hello
# World
---

[Content] =
[Removal] =
[Domain] = 0:0-1:7
>-------
0| # Hello
1| # World
-------<

[Insertion delimiter] = "\n"
10 changes: 10 additions & 0 deletions data/fixtures/scopes/talon/comment.line.scope
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Hello world
---

[Content] =
[Removal] =
[Domain] = 0:0-0:13
>-------------<
0| # Hello world

[Insertion delimiter] = "\n"
3 changes: 3 additions & 0 deletions packages/common/src/scopeSupportFacets/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const javaScopeSupport: LanguageScopeSupportFacetMap = {
"argument.actual": supported,
"argument.actual.iteration": supported,

"comment.line": supported,
"comment.block": supported,

element: notApplicable,
tags: notApplicable,
attribute: notApplicable,
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/scopeSupportFacets/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const pythonScopeSupport: LanguageScopeSupportFacetMap = {
"argument.formal": supportedLegacy,
"argument.formal.iteration": supportedLegacy,

"comment.line": supported,
"comment.block": supported,
"branch.if": supported,
"branch.if.iteration": supported,
"branch.switchCase": supported,
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/scopeSupportFacets/talon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ const { supported } = ScopeSupportFacetLevel;

export const talonScopeSupport: LanguageScopeSupportFacetMap = {
command: supported,

"comment.line": supported,
"comment.block": supported,
};
14 changes: 14 additions & 0 deletions packages/common/src/util/itertools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,17 @@ export function isEmptyIterable(iterable: Iterable<unknown>): boolean {

return true;
}

/**
* Returns the first element of the given iterable, or `undefined` if the
* iterable is empty
* @param iterable The iterable to get the first element of
* @returns The first element of the iterable, or `undefined` if the iterable
* is empty
*/
export function next<T>(generator: Iterable<T>): T | undefined {
for (const value of generator) {
return value;
}
return undefined;
}
29 changes: 26 additions & 3 deletions packages/cursorless-engine/src/languages/LanguageDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import {
import { basename, dirname, join } from "path";
import { TreeSitterScopeHandler } from "../processTargets/modifiers/scopeHandlers";
import { ide } from "../singletons/ide.singleton";
import { TreeSitter } from "../typings/TreeSitter";
import type { TreeSitter } from "../typings/TreeSitter";
import { matchAll } from "../util/regex";
import { TreeSitterQuery } from "./TreeSitterQuery";
import { validateQueryCaptures } from "./TreeSitterQuery/validateQueryCaptures";
import type { ScopeHandler } from "../processTargets/modifiers/scopeHandlers/scopeHandler.types";
import { ContiguousScopeHandler } from "../processTargets/modifiers/scopeHandlers/ContiguousScopeHandler";

/**
* Represents a language definition for a single language, including the
Expand Down Expand Up @@ -70,12 +72,21 @@ export class LanguageDefinition {
* undefined if the given scope type / language id combination is still using
* legacy pathways
*/
getScopeHandler(scopeType: ScopeType) {
getScopeHandler(scopeType: ScopeType): ScopeHandler | undefined {
if (!this.query.captureNames.includes(scopeType.type)) {
return undefined;
}

return new TreeSitterScopeHandler(this.query, scopeType as SimpleScopeType);
const scopeHandler = new TreeSitterScopeHandler(
this.query,
scopeType as SimpleScopeType,
);

if (useContiguousScopeHandler(scopeType)) {
return new ContiguousScopeHandler(scopeHandler);
}

return scopeHandler;
}
}

Expand Down Expand Up @@ -168,6 +179,18 @@ async function readQueryFileAndImports(
return Object.values(rawQueryStrings).join("\n");
}

/**
* Returns true if the given scope type should use a contiguous scope handler.
*/
function useContiguousScopeHandler(scopeType: ScopeType): boolean {
switch (scopeType.type) {
case "comment":
return true;
default:
return false;
}
}

function validateImportSyntax(
file: string,
relativeImportPath: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export interface QueryCapture {
* content ranges. */
readonly allowMultiple: boolean;

/** Whether this scope should expand contiguously to its siblings. */
readonly contiguous: boolean;

/** The insertion delimiter to use if any */
readonly insertionDelimiter: string | undefined;
}
Expand Down Expand Up @@ -63,6 +66,7 @@ export interface MutableQueryCapture extends QueryCapture {
readonly document: TextDocument;
range: Range;
allowMultiple: boolean;
contiguous: boolean;
insertionDelimiter: string | undefined;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class TreeSitterQuery {
range: getNodeRange(node),
insertionDelimiter: undefined,
allowMultiple: false,
contiguous: false,
})),
}),
)
Expand Down Expand Up @@ -113,6 +114,7 @@ export class TreeSitterQuery {
.map(({ range }) => range)
.reduce((accumulator, range) => range.union(accumulator)),
allowMultiple: captures.some((capture) => capture.allowMultiple),
contiguous: captures.some((capture) => capture.contiguous),
insertionDelimiter: captures.find(
(capture) => capture.insertionDelimiter != null,
)?.insertionDelimiter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import assert from "assert";

interface TestCase {
name: string;
captures: Omit<QueryCapture, "allowMultiple" | "insertionDelimiter">[];
captures: Omit<
QueryCapture,
"allowMultiple" | "contiguous" | "insertionDelimiter"
>[];
isValid: boolean;
expectedErrorMessageIds: string[];
}
Expand Down Expand Up @@ -192,6 +195,7 @@ suite("checkCaptureStartEnd", () => {
testCase.captures.map((capture) => ({
...capture,
allowMultiple: false,
contiguous: false,
insertionDelimiter: undefined,
})),
messages,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ class AllowMultiple extends QueryPredicateOperator<AllowMultiple> {
}
}

/** Indicates that it's okay for this scope to extend contiguously through its siblings of same type. */
class Contiguous extends QueryPredicateOperator<Contiguous> {
name = "contiguous!" as const;
schema = z.tuple([q.node]);

run(nodeInfo: MutableQueryCapture) {
nodeInfo.contiguous = true;

return true;
}
}

/**
* A predicate operator that logs a node, for debugging.
*/
Expand Down Expand Up @@ -254,6 +266,7 @@ export const queryPredicateOperators = [
new ChildRange(),
new ShrinkToMatch(),
new AllowMultiple(),
new Contiguous(),
new InsertionDelimiter(),
new SingleOrMultilineDelimiter(),
new HasMultipleChildrenOfType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function fillOutCapture(capture: NameRange): MutableQueryCapture {
return {
...capture,
allowMultiple: false,
contiguous: false,
insertionDelimiter: undefined,
document: null as unknown as TextDocument,
node: null as unknown as SyntaxNode,
Expand Down
Loading
Loading