Skip to content

Commit a44b2f9

Browse files
committed
Merge branch 'main' into pokey/keyboard-parser
2 parents 48ab4e9 + bc9cf96 commit a44b2f9

File tree

159 files changed

+4508
-862
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

159 files changed

+4508
-862
lines changed

data/playground/go/branch.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package p
2+
3+
func switches(x any) {
4+
switch x {
5+
case 1:
6+
// bar
7+
case 2:
8+
x = nil
9+
case "s":
10+
case 4, "t":
11+
x = 7
12+
// qux
13+
case 5:
14+
// foo
15+
fallthrough
16+
default:
17+
panic("x")
18+
}
19+
switch x := x.(type) {
20+
case int:
21+
x++
22+
case string, struct{}:
23+
println(x)
24+
default:
25+
panic(x)
26+
}
27+
switch {
28+
case x == 1:
29+
panic("one")
30+
case false:
31+
// unreachable
32+
}
33+
}
34+
35+
func ifElseChains(x int) {
36+
if y := 0; x == 1 {
37+
// foo
38+
} else if z:=0; x == 2 {
39+
x--
40+
x--
41+
x--
42+
} else if z:=0; x == 2 {
43+
x--
44+
x--
45+
x--
46+
} else if x == 3 {
47+
x++
48+
} else if x == 3 {
49+
x++
50+
} else {
51+
x *= 2
52+
}
53+
54+
if x == 4{
55+
x++
56+
}
57+
}

packages/common/src/types/Position.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Range } from "..";
1+
import { Range, TextDocument } from "..";
22

33
export class Position {
44
/**
@@ -151,3 +151,19 @@ export class Position {
151151
return this.concise();
152152
}
153153
}
154+
155+
/**
156+
* adjustPosition returns a new position that is offset by the given amount.
157+
* It corrects line and character positions to remain valid in doc.
158+
* @param doc The document
159+
* @param pos The position to adjust
160+
* @param by The amount to adjust by
161+
* @returns The adjusted position
162+
*/
163+
export function adjustPosition(
164+
doc: TextDocument,
165+
pos: Position,
166+
by: number,
167+
): Position {
168+
return doc.positionAt(doc.offsetAt(pos) + by);
169+
}

packages/cursorless-engine/src/languages/TreeSitterQuery/queryPredicateOperators.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Range } from "@cursorless/common";
1+
import { Range, adjustPosition } from "@cursorless/common";
22
import { z } from "zod";
33
import { makeRangeFromPositions } from "../../util/nodeSelectors";
44
import { MutableQueryCapture } from "./QueryCapture";
@@ -139,6 +139,26 @@ class ShrinkToMatch extends QueryPredicateOperator<ShrinkToMatch> {
139139
}
140140
}
141141

142+
/**
143+
* A predicate operator that modifies the range of the match by trimming trailing whitespace,
144+
* similar to the javascript trimEnd function.
145+
*/
146+
class TrimEnd extends QueryPredicateOperator<TrimEnd> {
147+
name = "trim-end!" as const;
148+
schema = z.tuple([q.node]);
149+
150+
run(nodeInfo: MutableQueryCapture) {
151+
const { document, range } = nodeInfo;
152+
const text = document.getText(range);
153+
const whitespaceLength = text.length - text.trimEnd().length;
154+
nodeInfo.range = new Range(
155+
range.start,
156+
adjustPosition(document, range.end, -whitespaceLength),
157+
);
158+
return true;
159+
}
160+
}
161+
142162
/**
143163
* Indicates that it is ok for multiple captures to have the same domain but
144164
* different targets. For example, if we have the query `(#allow-multiple!
@@ -197,6 +217,7 @@ class InsertionDelimiter extends QueryPredicateOperator<InsertionDelimiter> {
197217
export const queryPredicateOperators = [
198218
new Log(),
199219
new NotType(),
220+
new TrimEnd(),
200221
new NotParentType(),
201222
new IsNthChild(),
202223
new ChildRange(),

packages/cursorless-engine/src/languages/getNodeMatcher.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import csharp from "./csharp";
1515
import go from "./go";
1616
import { patternMatchers as html } from "./html";
1717
import java from "./java";
18-
import { patternMatchers as json } from "./json";
1918
import latex from "./latex";
2019
import markdown from "./markdown";
2120
import php from "./php";
@@ -64,8 +63,6 @@ export const languageMatchers: Record<
6463
java,
6564
javascript: typescript,
6665
javascriptreact: typescript,
67-
json,
68-
jsonc: json,
6966
latex,
7067
markdown,
7168
php,

packages/cursorless-engine/src/languages/getTextFragmentExtractor.ts

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ import { notSupported } from "../util/nodeMatchers";
55
import { getNodeInternalRange, getNodeRange } from "../util/nodeSelectors";
66
import { LegacyLanguageId } from "./LegacyLanguageId";
77
import { getNodeMatcher } from "./getNodeMatcher";
8-
import { stringTextFragmentExtractor as htmlStringTextFragmentExtractor } from "./html";
9-
import { stringTextFragmentExtractor as jsonStringTextFragmentExtractor } from "./json";
108
import { stringTextFragmentExtractor as rubyStringTextFragmentExtractor } from "./ruby";
119
import { stringTextFragmentExtractor as scssStringTextFragmentExtractor } from "./scss";
12-
import { stringTextFragmentExtractor as typescriptStringTextFragmentExtractor } from "./typescript";
1310

1411
export type TextFragmentExtractor = (
1512
node: SyntaxNode,
@@ -128,32 +125,7 @@ const textFragmentExtractors: Record<
128125
"css",
129126
scssStringTextFragmentExtractor,
130127
),
131-
html: constructDefaultTextFragmentExtractor(
132-
"html",
133-
htmlStringTextFragmentExtractor,
134-
),
135-
java: constructDefaultTextFragmentExtractor(
136-
"java",
137-
constructHackedStringTextFragmentExtractor("java"),
138-
),
139-
javascript: constructDefaultTextFragmentExtractor(
140-
"javascript",
141-
typescriptStringTextFragmentExtractor,
142-
),
143-
javascriptreact: constructDefaultTextFragmentExtractor(
144-
"javascriptreact",
145-
typescriptStringTextFragmentExtractor,
146-
),
147-
jsonc: constructDefaultTextFragmentExtractor(
148-
"jsonc",
149-
jsonStringTextFragmentExtractor,
150-
),
151-
json: constructDefaultTextFragmentExtractor(
152-
"json",
153-
jsonStringTextFragmentExtractor,
154-
),
155128
latex: fullDocumentTextFragmentExtractor,
156-
markdown: fullDocumentTextFragmentExtractor,
157129
ruby: constructDefaultTextFragmentExtractor(
158130
"ruby",
159131
rubyStringTextFragmentExtractor,
@@ -167,16 +139,4 @@ const textFragmentExtractors: Record<
167139
scssStringTextFragmentExtractor,
168140
),
169141
rust: constructDefaultTextFragmentExtractor("rust"),
170-
typescript: constructDefaultTextFragmentExtractor(
171-
"typescript",
172-
typescriptStringTextFragmentExtractor,
173-
),
174-
typescriptreact: constructDefaultTextFragmentExtractor(
175-
"typescriptreact",
176-
typescriptStringTextFragmentExtractor,
177-
),
178-
xml: constructDefaultTextFragmentExtractor(
179-
"xml",
180-
htmlStringTextFragmentExtractor,
181-
),
182142
};
Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,11 @@
1-
import type { SyntaxNode } from "web-tree-sitter";
21
import { SimpleScopeTypeType } from "@cursorless/common";
3-
import { NodeMatcherAlternative, SelectionWithEditor } from "../typings/Types";
4-
import { typedNodeFinder } from "../util/nodeFinders";
5-
import {
6-
createPatternMatchers,
7-
leadingMatcher,
8-
matcher,
9-
patternMatcher,
10-
} from "../util/nodeMatchers";
11-
import { xmlElementExtractor, getNodeRange } from "../util/nodeSelectors";
12-
13-
const attribute = "*?.attribute!";
14-
15-
const getStartTag = patternMatcher(`*?.start_tag!`);
16-
const getEndTag = patternMatcher(`*?.end_tag!`);
17-
18-
const getTags = (selection: SelectionWithEditor, node: SyntaxNode) => {
19-
const startTag = getStartTag(selection, node);
20-
const endTag = getEndTag(selection, node);
21-
return startTag != null && endTag != null ? startTag.concat(endTag) : null;
22-
};
2+
import { NodeMatcherAlternative } from "../typings/Types";
3+
import { createPatternMatchers } from "../util/nodeMatchers";
234

245
const nodeMatchers: Partial<
256
Record<SimpleScopeTypeType, NodeMatcherAlternative>
267
> = {
27-
xmlElement: matcher(
28-
typedNodeFinder("element", "script_element", "style_element"),
29-
xmlElementExtractor,
30-
),
31-
xmlBothTags: getTags,
32-
xmlStartTag: getStartTag,
33-
xmlEndTag: getEndTag,
34-
attribute: attribute,
35-
collectionItem: attribute,
36-
name: "*?.tag_name!",
37-
collectionKey: ["*?.attribute_name!"],
38-
value: leadingMatcher(
39-
["*?.quoted_attribute_value!.attribute_value", "*?.attribute_value!"],
40-
["="],
41-
),
42-
string: "quoted_attribute_value",
43-
comment: "comment",
8+
collectionItem: "*?.attribute!",
449
};
4510

4611
export const patternMatchers = createPatternMatchers(nodeMatchers);
47-
48-
const textFragmentTypes = ["attribute_value", "raw_text", "text"];
49-
50-
export function stringTextFragmentExtractor(
51-
node: SyntaxNode,
52-
_selection: SelectionWithEditor,
53-
) {
54-
if (textFragmentTypes.includes(node.type)) {
55-
return getNodeRange(node);
56-
}
57-
58-
return null;
59-
}
Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,12 @@
1-
import {
2-
createPatternMatchers,
3-
argumentMatcher,
4-
leadingMatcher,
5-
conditionMatcher,
6-
trailingMatcher,
7-
matcher,
8-
cascadingMatcher,
9-
} from "../util/nodeMatchers";
10-
import { childRangeSelector } from "../util/nodeSelectors";
11-
import { patternFinder } from "../util/nodeFinders";
1+
import { argumentMatcher, createPatternMatchers } from "../util/nodeMatchers";
122

13-
import { NodeMatcherAlternative } from "../typings/Types";
143
import { SimpleScopeTypeType } from "@cursorless/common";
15-
16-
// Generated by the following command:
17-
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-java/master/src/node-types.json | jq '[.[] | select(.type == "statement" or .type == "declaration") | .subtypes[].type]'
18-
const STATEMENT_TYPES = [
19-
"annotation_type_declaration",
20-
"class_declaration",
21-
"enum_declaration",
22-
"import_declaration",
23-
"interface_declaration",
24-
"module_declaration",
25-
"package_declaration",
26-
"assert_statement",
27-
"break_statement",
28-
"continue_statement",
29-
"declaration",
30-
"do_statement",
31-
"enhanced_for_statement",
32-
"expression_statement",
33-
"for_statement",
34-
"if_statement",
35-
"labeled_statement",
36-
"local_variable_declaration",
37-
"return_statement",
38-
"switch_expression",
39-
"synchronized_statement",
40-
"throw_statement",
41-
"try_statement",
42-
"try_with_resources_statement",
43-
"while_statement",
44-
"yield_statement",
45-
46-
// exceptions
47-
// ";",
48-
// "block",
49-
"switch_statement",
50-
"method_declaration",
51-
"constructor_declaration",
52-
"field_declaration",
53-
];
4+
import { NodeMatcherAlternative } from "../typings/Types";
545

556
const nodeMatchers: Partial<
567
Record<SimpleScopeTypeType, NodeMatcherAlternative>
578
> = {
58-
statement: STATEMENT_TYPES,
59-
class: "class_declaration",
60-
className: "class_declaration[name]",
61-
ifStatement: "if_statement",
62-
string: "string_literal",
63-
comment: ["line_comment", "block_comment", "comment"],
64-
anonymousFunction: "lambda_expression",
65-
list: "array_initializer",
66-
functionCall: [
67-
"method_invocation",
68-
"object_creation_expression",
69-
"explicit_constructor_invocation",
70-
],
71-
functionCallee: cascadingMatcher(
72-
matcher(
73-
patternFinder("method_invocation"),
74-
childRangeSelector(["argument_list"], []),
75-
),
76-
matcher(
77-
patternFinder("object_creation_expression"),
78-
childRangeSelector(["argument_list"], []),
79-
),
80-
matcher(
81-
patternFinder("explicit_constructor_invocation"),
82-
childRangeSelector(["argument_list", ";"], []),
83-
),
84-
),
85-
map: "block",
86-
name: [
87-
"*[declarator][name]",
88-
"assignment_expression[left]",
89-
"*[name]",
90-
"formal_parameter.identifier!",
91-
],
92-
namedFunction: ["method_declaration", "constructor_declaration"],
93-
type: trailingMatcher([
94-
"generic_type.type_arguments.type_identifier",
95-
"generic_type.type_identifier",
96-
"generic_type.scoped_type_identifier.type_identifier",
97-
"type_identifier",
98-
"local_variable_declaration[type]",
99-
"array_creation_expression[type]",
100-
"formal_parameter[type]",
101-
"method_declaration[type]",
102-
]),
103-
functionName: [
104-
"method_declaration.identifier!",
105-
"constructor_declaration.identifier!",
106-
],
107-
value: leadingMatcher(
108-
[
109-
"*[declarator][value]",
110-
"assignment_expression[right]",
111-
"return_statement[0]",
112-
"*[value]",
113-
],
114-
["=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="],
115-
),
116-
condition: conditionMatcher("*[condition]"),
1179
argumentOrParameter: argumentMatcher("formal_parameters", "argument_list"),
118-
branch: ["switch_block_statement_group", "switch_rule"],
119-
["private.switchStatementSubject"]: "switch_expression[condition][0]",
12010
};
12111

12212
export default createPatternMatchers(nodeMatchers);

0 commit comments

Comments
 (0)