mirror of
https://github.com/cursorless-dev/cursorless.git
synced 2024-10-04 21:07:21 +03:00
Simple node matcher improvements
This commit is contained in:
parent
681435e1cf
commit
2e0afe9af1
@ -50,6 +50,7 @@ export type ScopeType =
|
||||
| "class"
|
||||
| "arrowFunction"
|
||||
| "namedFunction"
|
||||
| "pair"
|
||||
| "ifStatement";
|
||||
export type PieceType = "subtoken" | "character";
|
||||
|
||||
|
@ -45,10 +45,10 @@ class Actions {
|
||||
}
|
||||
const editor = editors[0];
|
||||
|
||||
editor.selections = targets.map((target) => target.selection.selection);
|
||||
if (editor.viewColumn != null) {
|
||||
await commands.executeCommand(columnFocusCommands[editor.viewColumn]);
|
||||
}
|
||||
editor.selections = targets.map((target) => target.selection.selection);
|
||||
editor.revealRange(editor.selections[0]);
|
||||
};
|
||||
|
||||
|
@ -1,28 +1,14 @@
|
||||
import { SyntaxNode } from "tree-sitter";
|
||||
import { Position, Selection } from "vscode";
|
||||
|
||||
type NodeMatcher = (node: SyntaxNode) => boolean;
|
||||
|
||||
type NodeSelectionExtractor = (
|
||||
node: SyntaxNode,
|
||||
isInside: boolean
|
||||
) => Selection | null;
|
||||
|
||||
interface NodeDescriptor {
|
||||
matcher: NodeMatcher;
|
||||
extractor: NodeSelectionExtractor;
|
||||
}
|
||||
type NodeMatcher = (node: SyntaxNode, isInside: boolean) => Selection | null;
|
||||
|
||||
function hasType(...typeNames: string[]): NodeMatcher {
|
||||
return (node: SyntaxNode) => typeNames.includes(node.type);
|
||||
return (node: SyntaxNode, isInside: boolean) =>
|
||||
typeNames.includes(node.type) ? simpleSelectionExtractor(node) : null;
|
||||
}
|
||||
|
||||
const makeSimpleNodeDescriptor = (...typeNames: string[]) => ({
|
||||
matcher: hasType("pair"),
|
||||
extractor: simpleSelectionExtractor,
|
||||
});
|
||||
|
||||
function simpleSelectionExtractor(node: SyntaxNode, isInside: boolean) {
|
||||
function simpleSelectionExtractor(node: SyntaxNode) {
|
||||
return new Selection(
|
||||
new Position(node.startPosition.row, node.startPosition.column),
|
||||
new Position(node.endPosition.row, node.endPosition.column)
|
||||
@ -30,25 +16,25 @@ function simpleSelectionExtractor(node: SyntaxNode, isInside: boolean) {
|
||||
}
|
||||
|
||||
const nodeMatchers = {
|
||||
class: makeSimpleNodeDescriptor("class_declaration"),
|
||||
arrowFunction: makeSimpleNodeDescriptor("arrow_function"),
|
||||
pair: {
|
||||
matcher: hasType("pair"),
|
||||
extractor: (node: SyntaxNode, isInside: boolean) => {
|
||||
return new Selection(
|
||||
new Position(node.startPosition.row, node.startPosition.column),
|
||||
new Position(node.endPosition.row, node.endPosition.column)
|
||||
);
|
||||
},
|
||||
class: hasType("class_declaration"),
|
||||
arrowFunction: hasType("arrow_function"),
|
||||
pair: (node: SyntaxNode, isInside: boolean) => {
|
||||
if (node.type !== "pair") {
|
||||
return null;
|
||||
}
|
||||
return new Selection(
|
||||
new Position(node.startPosition.row, node.startPosition.column),
|
||||
new Position(node.endPosition.row, node.endPosition.column)
|
||||
);
|
||||
},
|
||||
namedFunction(node: SyntaxNode) {
|
||||
namedFunction(node: SyntaxNode, isInside: boolean) {
|
||||
// Simple case, eg
|
||||
// function foo() {}
|
||||
if (
|
||||
node.type === "function_declaration" ||
|
||||
node.type === "method_definition"
|
||||
) {
|
||||
return true;
|
||||
return simpleSelectionExtractor(node);
|
||||
}
|
||||
|
||||
// Class property defined as field definition with arrow
|
||||
@ -61,14 +47,14 @@ const nodeMatchers = {
|
||||
// @ts-ignore
|
||||
node.valueNode.type === "arrow_function"
|
||||
) {
|
||||
return true;
|
||||
return simpleSelectionExtractor(node);
|
||||
}
|
||||
|
||||
// eg:
|
||||
// const foo = () => "hello"
|
||||
if (node.type === "lexical_declaration") {
|
||||
if (node.namedChildCount !== 1) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
const child = node.firstNamedChild!;
|
||||
@ -78,13 +64,13 @@ const nodeMatchers = {
|
||||
// @ts-ignore
|
||||
child.valueNode.type === "arrow_function"
|
||||
) {
|
||||
return true;
|
||||
return simpleSelectionExtractor(node);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
},
|
||||
ifStatement: makeSimpleNodeDescriptor("if_statement"),
|
||||
ifStatement: hasType("if_statement"),
|
||||
};
|
||||
|
||||
export default nodeMatchers;
|
||||
|
@ -119,8 +119,12 @@ function getSelectionsFromMark(
|
||||
function transformSelection(
|
||||
context: ProcessedTargetsContext,
|
||||
transformation: Transformation,
|
||||
position: Position,
|
||||
selection: SelectionWithEditor
|
||||
): SelectionWithEditor {
|
||||
const isInside =
|
||||
position === "end" || position === "start" || position === "inside";
|
||||
|
||||
switch (transformation.type) {
|
||||
case "identity":
|
||||
return selection;
|
||||
@ -132,16 +136,11 @@ function transformSelection(
|
||||
const nodeMatcher = nodeMatchers[transformation.scopeType];
|
||||
|
||||
while (node != null) {
|
||||
if (nodeMatcher(node)) {
|
||||
const matchedSelection = nodeMatcher(node, isInside);
|
||||
if (matchedSelection != null) {
|
||||
return {
|
||||
editor: selection.editor,
|
||||
selection: new Selection(
|
||||
new vscode.Position(
|
||||
node.startPosition.row,
|
||||
node.startPosition.column
|
||||
),
|
||||
new vscode.Position(node.endPosition.row, node.endPosition.column)
|
||||
),
|
||||
selection: matchedSelection,
|
||||
};
|
||||
}
|
||||
console.log(node.type);
|
||||
|
Loading…
Reference in New Issue
Block a user