Declarative language definition (#151)

* Unified types for array and map items

* Support deconstruct pattern

* Support deconstructed array

* Support arguments for plain javascript

* Added modifier regex

* Started working on new language matcher

* Improved matcher

* Enable strings

* Support empty strings

* Added support for fields

* Pours function and class names

* Added wildcard type

* Added optional types

* Added support for important node

* cleanup

* cleanup

* Clean up pojo matchers

* Added pattern documentation

* Added object pattern

* Support argument identifier for scope modifier name

* Added argument matcher

* , delimiter adjustment

* Implement argument matcher for other languages

* Added value to java

* Added support for multiple field names

* cleanup

* Use dot operator for sequential field names

* Updated java

* Better error message

* Added support for matcher to return multiple selections

* Added scope type attribute

* Added attribute keys

* cleanup finders

* cleanup

* Added attribute values

* cleanup

* Added comments to json

* Added field names to debug

* Sequential field names in own square brackets

* Adding tests

* More tests

* Updated tests

* Added more tests

* Added until and tween tests

* Added tests for jsx

* Fixed bug when changing language too fast

* Added tests for json

* Move sleep before selections

* Try catch in debug

* Increased sleep time

* Reworked every modifier

* tests cleanup

* Added tests for java

* Added tests for python

* More tests

* cleanup

* cleanup

* cleanup
This commit is contained in:
Andreas Arvidsson 2021-08-04 00:10:10 +02:00 committed by GitHub
parent 9f0405d5b4
commit 959646ee1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
156 changed files with 5037 additions and 624 deletions

View File

@ -86,7 +86,7 @@ export class TestCaseRecorder {
}
const subdirectory = await vscode.window.showInputBox({
prompt: "New Folder Name",
prompt: "New folder name. Use '/' for subdirectories.",
ignoreFocusOut: true,
validateInput: (input) => (input.trim().length > 0 ? null : "Required"),
});
@ -118,8 +118,7 @@ export class TestCaseRecorder {
let i = 2;
while (fs.existsSync(filePath)) {
filename += i++;
filePath = path.join(targetDirectory, `${filename}.yml`);
filePath = path.join(targetDirectory, `${filename}${i++}.yml`);
}
return filePath;

View File

@ -62,21 +62,26 @@ export type ScopeType =
| "arrowFunction"
| "class"
| "className"
| "collectionItem"
| "collectionKey"
| "comment"
| "dictionary"
| "functionCall"
| "functionName"
| "ifStatement"
| "list"
| "listElement"
| "name"
| "namedFunction"
| "pair"
| "pairKey"
| "regex"
| "statement"
| "string"
| "type"
| "value";
| "value"
| "xmlAttribute"
| "xmlElement"
| "xmlBothTags"
| "xmlEndTag"
| "xmlStartTag";
export type PieceType = "word" | "character";
export interface SurroundingPairModifier {
@ -317,22 +322,32 @@ export interface DecorationColorSetting {
highContrast: string;
}
export type NodeMatcherValue = {
node: SyntaxNode;
selection: SelectionWithContext;
};
export type NodeMatcherAlternative = NodeMatcher | string[] | string;
export type NodeMatcher = (
editor: vscode.TextEditor,
selection: SelectionWithEditor,
node: SyntaxNode
) => SelectionWithContext | null;
) => NodeMatcherValue[] | null;
/**
* Returns the desired relative of the provided node.
* Returns null if matching node not found.
**/
export type NodeFinder = (node: SyntaxNode) => SyntaxNode | null;
export type NodeFinder = (
node: SyntaxNode,
selection?: vscode.Selection
) => SyntaxNode | null;
/** Returns a selection for a given SyntaxNode */
/** Returns one or more selections for a given SyntaxNode */
export type SelectionExtractor = (
editor: vscode.TextEditor,
node: SyntaxNode
) => SelectionWithContext | null;
nodes: SyntaxNode
) => SelectionWithContext;
/** Represent a single edit/change in the document */
export interface Edit {

View File

@ -1,5 +1,5 @@
import * as vscode from "vscode";
import { SyntaxNode } from "web-tree-sitter";
import { SyntaxNode, TreeCursor } from "web-tree-sitter";
export function logBranchTypes(getNodeAtLocation: any) {
return (event: vscode.TextEditorSelectionChangeEvent) => {
@ -8,14 +8,38 @@ export function logBranchTypes(getNodeAtLocation: any) {
event.selections[0]
);
let node: SyntaxNode = getNodeAtLocation(location);
let node: SyntaxNode;
try {
node = getNodeAtLocation(location);
} catch (error) {
return;
}
const ancestors: SyntaxNode[] = [node];
while (node.parent != null) {
ancestors.unshift(node.parent);
node = node.parent;
}
ancestors.forEach((node, i) => console.debug(">".repeat(i + 1), node.type));
const print = (cursor: TreeCursor, depth: number) => {
const field = cursor.currentFieldName();
const fieldText = field != null ? `${field}: ` : "";
console.debug(">".repeat(depth + 1), `${fieldText}${cursor.nodeType}`);
};
const cursor = node.tree.walk();
print(cursor, 0);
for (let i = 1; i < ancestors.length; ++i) {
cursor.gotoFirstChild();
while (cursor.currentNode().id !== ancestors[i].id) {
if (!cursor.gotoNextSibling()) {
return;
}
}
print(cursor, i);
}
const leafText = ancestors[ancestors.length - 1].text
.replace(/\s+/g, " ")
.substring(0, 100);

View File

@ -25,7 +25,20 @@ export async function activate(context: vscode.ExtensionContext) {
throw new Error("Depends on pokey.parse-tree extension");
}
const { getNodeAtLocation } = await parseTreeExtension.activate();
const { getNodeAtLocation: getNodeAtLocationImpl } =
await parseTreeExtension.activate();
const getNodeAtLocation = (location: vscode.Location) => {
try {
return getNodeAtLocationImpl(location);
} catch (error) {
const document = vscode.window.activeTextEditor?.document;
if (document?.uri === location.uri) {
throw Error(`Language '${document.languageId}' is not implemented yet`);
}
throw error;
}
};
var isActive = vscode.workspace
.getConfiguration("cursorless")

View File

@ -0,0 +1,23 @@
# Pattern format documentation
## Format
`GRAND_PARENT_TYPE.*.CHILD_TYPE[FIELD]!?`
| Syntax | Description |
| ------------------ | ------------------------------------------ |
| TYPE | Match node type<br>`node.type` |
| Dot operator(`.`) | Type hierarchy between parent and child |
| Wildcard op(`*`) | Match any type |
| Important op(`!`) | Use this node as result instead of parent.<br>By default the leftmost/top node is used |
| Optional op(`?`) | Node is optional. Will match if available. |
| Field op(`[field]`) | Get child field node for resulting node.<br>Only evaluated on the resulting node at the end.<br>`node.childForFieldName(field)`|
## Multiple patterns
When using multiple patterns evaluation will be performed top to bottom and the first pattern too match will be used.
```js
[
"export_statement?.class_declaration",
"export_statement.class"
]
```

View File

@ -2,17 +2,13 @@ import { SyntaxNode } from "web-tree-sitter";
import {
cascadingMatcher,
composedMatcher,
createPatternMatchers,
matcher,
typeMatcher,
} from "../nodeMatchers";
import { NodeMatcher, ScopeType } from "../Types";
import {
getNameNode,
} from "../treeSitterUtils";
import {
nodeFinder,
typedNodeFinder,
} from "../nodeFinders";
import { getNameNode } from "../treeSitterUtils";
import { nodeFinder, typedNodeFinder } from "../nodeFinders";
import {
delimitedSelector,
selectWithLeadingDelimiter,
@ -22,117 +18,117 @@ import {
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-c-sharp/master/src/node-types.json \
// | jq '.[] | select(.type == "_expression") | [.subtypes[].type]'
const EXPRESSION_TYPES = [
"anonymous_method_expression",
"anonymous_object_creation_expression",
"array_creation_expression",
"as_expression",
"assignment_expression",
"await_expression",
"base_expression",
"binary_expression",
"boolean_literal",
"cast_expression",
"character_literal",
"checked_expression",
"conditional_access_expression",
"conditional_expression",
"default_expression",
"element_access_expression",
"element_binding_expression",
"generic_name",
"global",
"identifier",
"implicit_array_creation_expression",
"implicit_object_creation_expression",
"implicit_stack_alloc_array_creation_expression",
"initializer_expression",
"integer_literal",
"interpolated_string_expression",
"invocation_expression",
"is_expression",
"is_pattern_expression",
"lambda_expression",
"make_ref_expression",
"member_access_expression",
"null_literal",
"object_creation_expression",
"parenthesized_expression",
"postfix_unary_expression",
"prefix_unary_expression",
"query_expression",
"range_expression",
"real_literal",
"ref_expression",
"ref_type_expression",
"ref_value_expression",
"size_of_expression",
"stack_alloc_array_creation_expression",
"string_literal",
"switch_expression",
"this_expression",
"throw_expression",
"tuple_expression",
"type_of_expression",
"verbatim_string_literal",
"with_expression"
"anonymous_method_expression",
"anonymous_object_creation_expression",
"array_creation_expression",
"as_expression",
"assignment_expression",
"await_expression",
"base_expression",
"binary_expression",
"boolean_literal",
"cast_expression",
"character_literal",
"checked_expression",
"conditional_access_expression",
"conditional_expression",
"default_expression",
"element_access_expression",
"element_binding_expression",
"generic_name",
"global",
"identifier",
"implicit_array_creation_expression",
"implicit_object_creation_expression",
"implicit_stack_alloc_array_creation_expression",
"initializer_expression",
"integer_literal",
"interpolated_string_expression",
"invocation_expression",
"is_expression",
"is_pattern_expression",
"lambda_expression",
"make_ref_expression",
"member_access_expression",
"null_literal",
"object_creation_expression",
"parenthesized_expression",
"postfix_unary_expression",
"prefix_unary_expression",
"query_expression",
"range_expression",
"real_literal",
"ref_expression",
"ref_type_expression",
"ref_value_expression",
"size_of_expression",
"stack_alloc_array_creation_expression",
"string_literal",
"switch_expression",
"this_expression",
"throw_expression",
"tuple_expression",
"type_of_expression",
"verbatim_string_literal",
"with_expression",
];
function isExpression(node: SyntaxNode) {
return EXPRESSION_TYPES.includes(node.type);
return EXPRESSION_TYPES.includes(node.type);
}
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-c-sharp/master/src/node-types.json \
// | jq '.[] | select(.type == "_statement" or .type == "_declaration") | [.subtypes[].type]'
const STATEMENT_TYPES = [
"class_declaration",
"constructor_declaration",
"conversion_operator_declaration",
"delegate_declaration",
"destructor_declaration",
"enum_declaration",
"event_declaration",
"event_field_declaration",
"field_declaration",
"indexer_declaration",
"interface_declaration",
"method_declaration",
"namespace_declaration",
"operator_declaration",
"property_declaration",
"record_declaration",
"struct_declaration",
"using_directive",
"block",
"break_statement",
"checked_statement",
"continue_statement",
"do_statement",
"empty_statement",
"expression_statement",
"fixed_statement",
"for_each_statement",
"for_statement",
"goto_statement",
"if_statement",
"labeled_statement",
"local_declaration_statement",
"local_function_statement",
"lock_statement",
"return_statement",
"switch_statement",
"throw_statement",
"try_statement",
"unsafe_statement",
"using_statement",
"while_statement",
"yield_statement"
"class_declaration",
"constructor_declaration",
"conversion_operator_declaration",
"delegate_declaration",
"destructor_declaration",
"enum_declaration",
"event_declaration",
"event_field_declaration",
"field_declaration",
"indexer_declaration",
"interface_declaration",
"method_declaration",
"namespace_declaration",
"operator_declaration",
"property_declaration",
"record_declaration",
"struct_declaration",
"using_directive",
"block",
"break_statement",
"checked_statement",
"continue_statement",
"do_statement",
"empty_statement",
"expression_statement",
"fixed_statement",
"for_each_statement",
"for_statement",
"goto_statement",
"if_statement",
"labeled_statement",
"local_declaration_statement",
"local_function_statement",
"lock_statement",
"return_statement",
"switch_statement",
"throw_statement",
"try_statement",
"unsafe_statement",
"using_statement",
"while_statement",
"yield_statement",
];
const NAMED_FUNCTION_TYPES = [
"delegate_declaration",
"local_function_statement",
"method_declaration"
"method_declaration",
];
// Generated by the following command:
@ -143,11 +139,11 @@ const LIST_TYPES_WITH_INITIALIZERS_AS_CHILDREN = [
"array_creation_expression",
"implicit_array_creation_expression",
"implicit_stack_alloc_array_creation_expression",
"stack_alloc_array_creation_expression"
"stack_alloc_array_creation_expression",
];
const OBJECT_TYPES_WITH_INITIALIZERS_AS_CHILDREN = [
"implicit_object_creation_expression"
"implicit_object_creation_expression",
];
const findTypeNode = (node: SyntaxNode) => {
@ -158,85 +154,92 @@ const findTypeNode = (node: SyntaxNode) => {
// There appears to be no distinction between dictionaries and arrays as far as the syntax tree goes.
// that means some of the commands for maps may work on arrays, and some of the commands for arrays may work on maps.
const getChildInitializerNode = (node: SyntaxNode) =>
node.children.find((child) => child.type === "initializer_expression") ?? null;
node.children.find((child) => child.type === "initializer_expression") ??
null;
const getInitializerNode = (node: SyntaxNode) => node.childForFieldName("initializer");
const getInitializerNode = (node: SyntaxNode) =>
node.childForFieldName("initializer");
const makeDelimitedSelector = (leftType: string, rightType: string) => delimitedSelector(
(node) => node.type === "," || node.type === leftType || node.type === rightType,
", "
);
const makeDelimitedSelector = (leftType: string, rightType: string) =>
delimitedSelector(
(node) =>
node.type === "," || node.type === leftType || node.type === rightType,
", "
);
const getDictionaryMatchers = {
dictionary: cascadingMatcher(
composedMatcher([
typedNodeFinder(...OBJECT_TYPES_WITH_INITIALIZERS_AS_CHILDREN),
getChildInitializerNode
getChildInitializerNode,
]),
composedMatcher([
typedNodeFinder("object_creation_expression"),
getInitializerNode
getInitializerNode,
])
),
pair: matcher(
collectionKey: composedMatcher([
typedNodeFinder("assignment_expression"),
makeDelimitedSelector("{", "}")
),
pairKey: composedMatcher([
typedNodeFinder("assignment_expression"),
(node: SyntaxNode) => node.childForFieldName("left")
(node: SyntaxNode) => node.childForFieldName("left"),
]),
value: matcher(
(node: SyntaxNode) => node.childForFieldName("right")
),
value: matcher((node: SyntaxNode) => node.childForFieldName("right")),
list: cascadingMatcher(
composedMatcher([
typedNodeFinder(...LIST_TYPES_WITH_INITIALIZERS_AS_CHILDREN),
getChildInitializerNode
getChildInitializerNode,
]),
composedMatcher([
typedNodeFinder("object_creation_expression"),
(node: SyntaxNode) => node.childForFieldName("initializer")
(node: SyntaxNode) => node.childForFieldName("initializer"),
])
),
listElement: matcher(
collectionItem: matcher(
nodeFinder(
(node) =>
node.parent?.type === "initializer_expression" &&
isExpression(node)
(node.parent?.type === "initializer_expression" &&
isExpression(node)) ||
node.type === "assignment_expression"
),
makeDelimitedSelector("{", "}")
delimitedSelector(
(node) =>
node.type === "," ||
node.type === "[" ||
node.type === "]" ||
node.type === "}" ||
node.type === "{",
", "
)
),
string: typeMatcher("string_literal"),
};
const nodeMatchers: Record<ScopeType, NodeMatcher> = {
...getDictionaryMatchers,
ifStatement: typeMatcher("if_statement"),
class: typeMatcher("class_declaration"),
className: composedMatcher([
typedNodeFinder("class_declaration"),
getNameNode,
]),
statement: typeMatcher(...STATEMENT_TYPES),
arrowFunction: typeMatcher("lambda_expression"),
functionCall: typeMatcher("invocation_expression"),
argumentOrParameter: matcher(
nodeFinder(
(node) =>
(node.parent?.type === "argument_list") ||
(node.type === "parameter")
),
makeDelimitedSelector("(", ")")),
namedFunction: typeMatcher(...NAMED_FUNCTION_TYPES),
functionName: composedMatcher([
typedNodeFinder(...NAMED_FUNCTION_TYPES),
getNameNode,
]),
comment: matcher(typedNodeFinder("comment")),
type: matcher(findTypeNode, selectWithLeadingDelimiter),
name: matcher(getNameNode),
const nodeMatchers: Partial<Record<ScopeType, NodeMatcher>> = {
...getDictionaryMatchers,
ifStatement: typeMatcher("if_statement"),
class: typeMatcher("class_declaration"),
className: composedMatcher([
typedNodeFinder("class_declaration"),
getNameNode,
]),
statement: typeMatcher(...STATEMENT_TYPES),
arrowFunction: typeMatcher("lambda_expression"),
functionCall: typeMatcher("invocation_expression"),
argumentOrParameter: matcher(
nodeFinder(
(node) =>
node.parent?.type === "argument_list" || node.type === "parameter"
),
makeDelimitedSelector("(", ")")
),
namedFunction: typeMatcher(...NAMED_FUNCTION_TYPES),
functionName: composedMatcher([
typedNodeFinder(...NAMED_FUNCTION_TYPES),
getNameNode,
]),
comment: matcher(typedNodeFinder("comment")),
regex: matcher(typedNodeFinder("regex")),
type: matcher(findTypeNode, selectWithLeadingDelimiter),
name: matcher(getNameNode),
};
export default nodeMatchers;
export default createPatternMatchers(nodeMatchers);

View File

@ -1,41 +0,0 @@
import { SyntaxNode } from "web-tree-sitter";
import { getKeyNode, getValueNode } from "../treeSitterUtils";
import {
delimitedSelector,
selectWithLeadingDelimiter,
} from "../nodeSelectors";
import { composedMatcher, matcher, typeMatcher } from "../nodeMatchers";
import { nodeFinder, typedNodeFinder } from "../nodeFinders";
// Matchers for "plain old javascript objects", like those found in JSON
export function getPojoMatchers(
dictionaryTypes: string[],
listTypes: string[],
listElementMatcher: (node: SyntaxNode) => boolean
) {
return {
dictionary: typeMatcher(...dictionaryTypes),
pair: matcher(
nodeFinder((node) => node.type === "pair"),
delimitedSelector(
(node) => node.type === "," || node.type === "}" || node.type === "{",
", "
)
),
pairKey: composedMatcher([typedNodeFinder("pair"), getKeyNode]),
value: matcher(getValueNode, selectWithLeadingDelimiter),
list: typeMatcher(...listTypes),
listElement: matcher(
nodeFinder(
(node) =>
listTypes.includes(node.parent?.type ?? "") &&
listElementMatcher(node)
),
delimitedSelector(
(node) => node.type === "," || node.type === "[" || node.type === "]",
", "
)
),
string: typeMatcher("string"),
};
}

View File

@ -1,10 +1,19 @@
import { NodeMatcher, ScopeType } from "../Types";
import {
NodeMatcher,
NodeMatcherValue,
ScopeType,
SelectionWithEditor,
} from "../Types";
import json from "./json";
import python from "./python";
import typescript from "./typescript";
import csharp from "./csharp";
import java from "./java";
import { notSupported } from "../nodeMatchers";
import { SyntaxNode } from "web-tree-sitter";
import { selectionWithEditorFromRange } from "../selectionUtils";
export const nodeMatchers: Record<string, Record<ScopeType, NodeMatcher>> = {
const languageMatchers: Record<string, Record<ScopeType, NodeMatcher>> = {
csharp: csharp,
javascript: typescript,
javascriptreact: typescript,
@ -13,4 +22,46 @@ export const nodeMatchers: Record<string, Record<ScopeType, NodeMatcher>> = {
python,
typescript,
typescriptreact: typescript,
java,
};
export function getNodeMatcher(
languageId: string,
scopeType: ScopeType,
includeSiblings: boolean
): NodeMatcher {
const matchers = languageMatchers[languageId];
if (matchers == null) {
throw Error(`Language '${languageId}' is not implemented yet`);
}
const matcher = matchers[scopeType];
if (matcher == null) {
return notSupported;
}
if (includeSiblings) {
return matcherIncludeSiblings(matcher);
}
return matcher;
}
function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher {
return (
selection: SelectionWithEditor,
node: SyntaxNode
): NodeMatcherValue[] | null => {
const matches = matcher(selection, node);
if (matches == null) {
return null;
}
return matches
.flatMap((match) =>
match.node.parent!.namedChildren.flatMap((sibling) =>
matcher(
selectionWithEditorFromRange(selection, match.selection.selection),
sibling
)
)
)
.filter((match) => match != null) as NodeMatcherValue[];
};
}

70
src/languages/java.ts Normal file
View File

@ -0,0 +1,70 @@
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
} from "../nodeMatchers";
import { NodeMatcherAlternative, ScopeType } from "../Types";
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-java/master/src/node-types.json | jq '[.[] | select(.type == "statement" or .type == "declaration") | .subtypes[].type]'
const STATEMENT_TYPES = [
"annotation_type_declaration",
"class_declaration",
"enum_declaration",
"import_declaration",
"interface_declaration",
"module_declaration",
"package_declaration",
// ";",
"assert_statement",
"block",
"break_statement",
"continue_statement",
"declaration",
"do_statement",
"enhanced_for_statement",
"expression_statement",
"for_statement",
"if_statement",
"labeled_statement",
"local_variable_declaration",
"return_statement",
"switch_expression",
"synchronized_statement",
"throw_statement",
"try_statement",
"try_with_resources_statement",
"while_statement",
"yield_statement",
];
const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
statement: STATEMENT_TYPES,
class: "class_declaration",
className: "class_declaration[name]",
ifStatement: "if_statement",
string: "string_literal",
comment: "comment",
arrowFunction: "lambda_expression",
list: "array_initializer",
functionCall: "method_invocation",
dictionary: "block",
name: ["*[declarator][name]", "*[name]", "formal_parameter.identifier!"],
namedFunction: ["method_declaration", "constructor_declaration"],
type: [
"type_identifier",
"local_variable_declaration[type]",
"array_creation_expression[type]",
"formal_parameter[type]",
"method_declaration[type]",
],
functionName: [
"method_declaration.identifier!",
"constructor_declaration.identifier!",
],
value: valueMatcher("*[declarator][value]", "*[value]"),
collectionItem: argumentMatcher("array_initializer"),
argumentOrParameter: argumentMatcher("formal_parameters", "argument_list"),
};
export default createPatternMatchers(nodeMatchers);

View File

@ -1,40 +1,18 @@
import { SyntaxNode } from "web-tree-sitter";
import { getPojoMatchers } from "./getPojoMatchers";
import { notSupported } from "../nodeMatchers";
import { NodeMatcher, ScopeType } from "../Types";
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
} from "../nodeMatchers";
import { ScopeType, NodeMatcherAlternative } from "../Types";
// TODO figure out how to properly use super types
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-json/65bceef69c3b0f24c0b19ce67d79f57c96e90fcb/src/node-types.json \
// | jq '.[] | select(.type == _value) | [.subtypes[].type]'
const VALUE_TYPES = [
"array",
"false",
"null",
"number",
"object",
"string",
"true",
];
function isValue(node: SyntaxNode) {
return VALUE_TYPES.includes(node.type);
}
const nodeMatchers: Record<ScopeType, NodeMatcher> = {
...getPojoMatchers(["object"], ["array"], isValue),
ifStatement: notSupported,
class: notSupported,
className: notSupported,
statement: notSupported,
arrowFunction: notSupported,
functionCall: notSupported,
argumentOrParameter: notSupported,
namedFunction: notSupported,
functionName: notSupported,
comment: notSupported,
type: notSupported,
name: notSupported,
const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
dictionary: "object",
list: "array",
string: "string",
comment: "comment",
collectionKey: "pair[key]",
value: valueMatcher("*[value]"),
collectionItem: argumentMatcher("object", "array"),
};
export default nodeMatchers;
export default createPatternMatchers(nodeMatchers);

View File

@ -1,69 +1,10 @@
import { SyntaxNode } from "web-tree-sitter";
import { getPojoMatchers } from "./getPojoMatchers";
import {
cascadingMatcher,
composedMatcher,
matcher,
notSupported,
typeMatcher,
createPatternMatchers,
argumentMatcher,
valueMatcher,
} from "../nodeMatchers";
import { NodeFinder, NodeMatcher, ScopeType } from "../Types";
import {
getDefinitionNode,
getLeftNode,
getNameNode,
} from "../treeSitterUtils";
import {
nodeFinder,
typedNodeFinder,
findPossiblyWrappedNode,
} from "../nodeFinders";
import {
delimitedSelector,
selectWithLeadingDelimiter,
} from "../nodeSelectors";
// TODO figure out how to properly use super types
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/d6210ceab11e8d812d4ab59c07c81458ec6e5184/src/node-types.json \
// | jq '[.[] | select(.type == primary_expression or .type == expression) | .subtypes[].type]'
const EXPRESSION_TYPES = [
"attribute",
"await",
"binary_operator",
"boolean_operator",
"call",
"comparison_operator",
"concatenated_string",
"conditional_expression",
"dictionary",
"dictionary_comprehension",
"ellipsis",
"false",
"float",
"generator_expression",
"identifier",
"integer",
"lambda",
"list",
"list_comprehension",
"named_expression",
"none",
"not_operator",
"parenthesized_expression",
"primary_expression",
"set",
"set_comprehension",
"string",
"subscript",
"true",
"tuple",
"unary_operator",
];
function isExpression(node: SyntaxNode) {
return EXPRESSION_TYPES.includes(node.type);
}
import { NodeMatcherAlternative, ScopeType } from "../Types";
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/d6210ceab11e8d812d4ab59c07c81458ec6e5184/src/node-types.json \
@ -94,88 +35,36 @@ const STATEMENT_TYPES = [
"with_statement",
];
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/d6210ceab11e8d812d4ab59c07c81458ec6e5184/src/node-types.json \
// | jq '[.[] | select(.type == "parameter") | .subtypes[].type]'
const PARAMETER_TYPES = [
"default_parameter",
"dictionary_splat_pattern",
"identifier",
"list_splat_pattern",
"tuple_pattern",
"typed_default_parameter",
"typed_parameter",
];
const PARAMETER_LIST_TYPES = ["lambda_parameters", "parameters"];
// TODO: Don't hard code this
const LIST_ELEMENT_TYPES = [
...EXPRESSION_TYPES,
"list_splat",
"parenthesized_list_splat",
"yield",
];
// TODO: Don't hard code this
const ARGUMENT_TYPES = [
...EXPRESSION_TYPES,
"list_splat",
"dictionary_splat",
"parenthesized_expression",
"keyword_argument",
];
function possiblyDecoratedDefinition(...typeNames: string[]): NodeFinder {
return findPossiblyWrappedNode(
typedNodeFinder("decorated_definition"),
typedNodeFinder(...typeNames),
(node) => [getDefinitionNode(node)]
);
}
export const getTypeNode = (node: SyntaxNode) =>
node.children.find((child) => child.type === "type") ?? null;
const nodeMatchers: Record<ScopeType, NodeMatcher> = {
...getPojoMatchers(
["dictionary", "dictionary_comprehension"],
["list", "list_comprehension"],
(node) => LIST_ELEMENT_TYPES.includes(node.type)
),
ifStatement: typeMatcher("if_statement"),
class: matcher(possiblyDecoratedDefinition("class_definition")),
statement: typeMatcher(...STATEMENT_TYPES),
name: cascadingMatcher(
matcher(getNameNode),
matcher((node) => (node.type === "assignment" ? getLeftNode(node) : null))
),
functionName: composedMatcher([
typedNodeFinder("function_definition"),
getNameNode,
]),
className: composedMatcher([
typedNodeFinder("class_definition"),
getNameNode,
]),
arrowFunction: typeMatcher("lambda"),
functionCall: typeMatcher("call"),
argumentOrParameter: matcher(
nodeFinder(
(node) =>
(node.parent?.type === "argument_list" &&
ARGUMENT_TYPES.includes(node.type)) ||
(PARAMETER_LIST_TYPES.includes(node.parent?.type ?? "") &&
PARAMETER_TYPES.includes(node.type))
),
delimitedSelector(
(node) => node.type === "," || node.type === "(" || node.type === ")",
", "
)
),
namedFunction: matcher(possiblyDecoratedDefinition("function_definition")),
comment: typeMatcher("comment"),
type: matcher(getTypeNode, selectWithLeadingDelimiter),
const dictionaryTypes = ["dictionary", "dictionary_comprehension"];
const listTypes = ["list", "list_comprehension", "set"];
const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
dictionary: dictionaryTypes,
list: listTypes,
statement: STATEMENT_TYPES,
string: "string",
collectionKey: "pair[key]",
ifStatement: "if_statement",
arrowFunction: "lambda",
functionCall: "call",
comment: "comment",
class: "decorated_definition?.class_definition",
className: "class_definition[name]",
namedFunction: "decorated_definition?.function_definition",
functionName: "function_definition[name]",
type: ["function_definition[return_type]", "*[type]"],
name: [
"assignment[left]",
"typed_parameter.identifier!",
"parameters.identifier!",
"*[name]",
],
collectionItem: argumentMatcher(...dictionaryTypes, ...listTypes),
value: valueMatcher("assignment[right]", "*[value]"),
argumentOrParameter: argumentMatcher("parameters", "argument_list"),
};
export default nodeMatchers;
export default createPatternMatchers(nodeMatchers);

View File

@ -1,74 +1,18 @@
import { SyntaxNode } from "web-tree-sitter";
import { getPojoMatchers } from "./getPojoMatchers";
import {
cascadingMatcher,
composedMatcher,
matcher,
typeMatcher,
cascadingMatcher,
patternMatcher,
createPatternMatchers,
argumentMatcher,
} from "../nodeMatchers";
import { NodeMatcher, ScopeType, NodeFinder } from "../Types";
import {
getDeclarationNode,
getNameNode,
getValueNode,
} from "../treeSitterUtils";
import {
nodeFinder,
typedNodeFinder,
findPossiblyWrappedNode,
} from "../nodeFinders";
import {
delimitedSelector,
selectWithLeadingDelimiter,
} from "../nodeSelectors";
// TODO figure out how to properly use super types
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-typescript/4c20b54771e4b390ee058af2930feb2cd55f2bf8/typescript/src/node-types.json \
// | jq '.[] | select(.type == "primary_expression" or .type == "expression") | [.subtypes[].type]'
const EXPRESSION_TYPES = [
"array",
"arrow_function",
"as_expression",
"assignment_expression",
"augmented_assignment_expression",
"await_expression",
"binary_expression",
"call_expression",
"class",
"false",
"function",
"generator_function",
"identifier",
"import",
"internal_module",
"member_expression",
"meta_property",
"new_expression",
"non_null_expression",
"null",
"number",
"object",
"parenthesized_expression",
"primary_expression",
"regex",
"string",
"subscript_expression",
"super",
"template_string",
"ternary_expression",
"this",
"true",
"type_assertion",
"unary_expression",
"undefined",
"update_expression",
"yield_expression",
];
function isExpression(node: SyntaxNode) {
return EXPRESSION_TYPES.includes(node.type);
}
NodeMatcherAlternative,
ScopeType,
SelectionWithEditor,
} from "../Types";
import { selectWithLeadingDelimiter } from "../nodeSelectors";
import { patternFinder } from "../nodeFinders";
// Generated by the following command:
// > curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-typescript/4c20b54771e4b390ee058af2930feb2cd55f2bf8/typescript/src/node-types.json \
@ -110,113 +54,111 @@ const STATEMENT_TYPES = [
"with_statement",
];
function possiblyExportedDeclaration(...typeNames: string[]): NodeFinder {
return findPossiblyWrappedNode(
typedNodeFinder("export_statement"),
typedNodeFinder(...typeNames),
(node) => [getDeclarationNode(node), getValueNode(node)]
);
}
const getStartTag = patternMatcher("jsx_element.jsx_opening_element!");
const getEndTag = patternMatcher("jsx_element.jsx_closing_element!");
const findNamedArrowFunction = (node: SyntaxNode) => {
if (node.type !== "lexical_declaration" || node.namedChildCount !== 1) {
return null;
}
const child = node.firstNamedChild!;
return child.type === "variable_declarator" &&
getValueNode(child)!.type === "arrow_function"
? node
: null;
const getTags = (selection: SelectionWithEditor, node: SyntaxNode) => {
const startTag = getStartTag(selection, node);
const endTag = getEndTag(selection, node);
return startTag != null && endTag != null ? startTag.concat(endTag) : null;
};
const findClassPropertyArrowFunction = (node: SyntaxNode) =>
node.type === "public_field_definition" &&
getValueNode(node)!.type === "arrow_function"
? node
: null;
export const findTypeNode = (node: SyntaxNode) => {
const findTypeNode = (node: SyntaxNode) => {
const typeAnnotationNode = node.children.find((child) =>
["type_annotation", "opting_type_annotation"].includes(child.type)
);
return typeAnnotationNode?.lastChild ?? null;
};
const nodeMatchers: Record<ScopeType, NodeMatcher> = {
...getPojoMatchers(
["object"],
["array"],
(node) => isExpression(node) || node.type === "spread_element"
),
ifStatement: typeMatcher("if_statement"),
class: matcher(possiblyExportedDeclaration("class_declaration", "class")),
statement: matcher(possiblyExportedDeclaration(...STATEMENT_TYPES)),
arrowFunction: typeMatcher("arrow_function"),
functionCall: typeMatcher("call_expression", "new_expression"),
name: matcher(getNameNode),
functionName: cascadingMatcher(
composedMatcher([
typedNodeFinder("function_declaration", "method_definition"),
getNameNode,
]),
composedMatcher([findClassPropertyArrowFunction, getNameNode]),
composedMatcher([findNamedArrowFunction, getNameNode])
),
className: composedMatcher([
typedNodeFinder("class_declaration", "class"),
getNameNode,
]),
function valueMatcher() {
const pFinder = patternFinder("assignment_expression[right]", "*[value]");
return matcher(
(node: SyntaxNode) =>
node.type === "jsx_attribute" ? node.lastChild : pFinder(node),
selectWithLeadingDelimiter
);
}
const dictionaryTypes = ["object", "object_pattern"];
const listTypes = ["array", "array_pattern"];
const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
dictionary: dictionaryTypes,
list: listTypes,
string: ["string", "template_string"],
collectionKey: ["pair[key]", "jsx_attribute.property_identifier!"],
collectionItem: argumentMatcher(...dictionaryTypes, ...listTypes),
value: valueMatcher(),
ifStatement: "if_statement",
arrowFunction: "arrow_function",
name: [
"*[name]",
"optional_parameter.identifier!",
"required_parameter.identifier!",
],
comment: "comment",
regex: "regex",
className: ["class_declaration[name]", "class[name]"],
functionCall: ["call_expression", "new_expression"],
statement: STATEMENT_TYPES.map((type) => `export_statement?.${type}`),
class: [
"export_statement?.class_declaration", // export class | class
"export_statement.class", // export default class
],
functionName: [
// function
"function_declaration[name]",
// export default function
"function[name]",
// class method
"method_definition[name]",
// class arrow method
"public_field_definition[name].arrow_function",
// const foo = function() { }
"variable_declarator[name].function",
// const foo = () => { }
"variable_declarator[name].arrow_function",
// foo = function() { }
"assignment_expression[left].function",
// foo = () => { }
"assignment_expression[left].arrow_function",
],
namedFunction: [
// [export] function
"export_statement?.function_declaration",
// export default function
"export_statement.function",
// export default arrow
"export_statement.arrow_function",
// class method
"method_definition",
// class arrow method
"public_field_definition.arrow_function",
// [export] const foo = function() { }
"export_statement?.lexical_declaration.variable_declarator.function",
// [export] const foo = () => { }
"export_statement?.lexical_declaration.variable_declarator.arrow_function",
// foo = function() { }
"assignment_expression.function",
// foo = () => { }
"assignment_expression.arrow_function",
],
type: cascadingMatcher(
// Typed parameters, properties, and functions
matcher(findTypeNode, selectWithLeadingDelimiter),
// Type alias/interface declarations
matcher(
possiblyExportedDeclaration(
"type_alias_declaration",
"interface_declaration"
)
patternMatcher(
"export_statement?.type_alias_declaration",
"export_statement?.interface_declaration"
)
),
argumentOrParameter: matcher(
nodeFinder(
(node) =>
(node.parent?.type === "arguments" &&
(isExpression(node) || node.type === "spread_element")) ||
node.type === "optional_parameter" ||
node.type === "required_parameter"
),
delimitedSelector(
(node) => node.type === "," || node.type === "(" || node.type === ")",
", "
)
),
namedFunction: cascadingMatcher(
// Simple case, eg
// function foo() {}
matcher(
possiblyExportedDeclaration("function_declaration", "method_definition")
),
// Class property defined as field definition with arrow
// eg:
// class Foo {
// bar = () => "hello";
// }
matcher(findClassPropertyArrowFunction),
// eg:
// const foo = () => "hello"
matcher(
findPossiblyWrappedNode(
typedNodeFinder("export_statement"),
findNamedArrowFunction,
(node) => [getDeclarationNode(node)]
)
)
),
comment: matcher(typedNodeFinder("comment")),
argumentOrParameter: argumentMatcher("formal_parameters", "arguments"),
// XML, JSX
xmlAttribute: ["jsx_attribute"],
xmlElement: ["jsx_element", "jsx_self_closing_element"],
xmlBothTags: getTags,
xmlStartTag: getStartTag,
xmlEndTag: getEndTag,
};
export default nodeMatchers;
export default createPatternMatchers(nodeMatchers);

View File

@ -1,4 +1,5 @@
import { SyntaxNode } from "web-tree-sitter";
import { Position, Selection } from "vscode";
import { Point, SyntaxNode } from "web-tree-sitter";
import { NodeFinder } from "./Types";
export const nodeFinder = (
@ -13,6 +14,56 @@ export const typedNodeFinder = (...typeNames: string[]): NodeFinder => {
return nodeFinder((node) => typeNames.includes(node.type));
};
const toPosition = (point: Point) => new Position(point.row, point.column);
export const argumentNodeFinder = (...parentTypes: string[]): NodeFinder => {
const left = ["(", "{", "["];
const right = [")", "}", "]"];
const delimiters = left.concat(right);
const isType = (node: SyntaxNode | null, typeNames: string[]) =>
node != null && typeNames.includes(node.type);
const isOk = (node: SyntaxNode | null) =>
node != null && !isType(node, delimiters);
return (node: SyntaxNode, selection?: Selection) => {
let resultNode: SyntaxNode | null;
const { start, end } = selection!;
// Is already child
if (isType(node.parent, parentTypes)) {
if (isType(node, left)) {
resultNode = node.nextNamedSibling;
} else if (isType(node, right)) {
resultNode = node.previousNamedSibling;
} else if (node.type === ",") {
resultNode = end.isBeforeOrEqual(toPosition(node.startPosition))
? node.previousNamedSibling
: node.nextNamedSibling;
} else {
resultNode = node;
}
return isOk(resultNode) ? resultNode : null;
// Is parent
} else if (isType(node, parentTypes)) {
const children = [...node.children];
const childRight =
children.find(({ startPosition }) =>
toPosition(startPosition).isAfterOrEqual(end)
) ?? null;
if (isOk(childRight)) {
return childRight;
}
children.reverse();
const childLeft =
children.find(({ endPosition }) =>
toPosition(endPosition).isBeforeOrEqual(start)
) ?? null;
if (isOk(childLeft)) {
return childLeft;
}
}
return null;
};
};
/**
* Creates a matcher that can match potentially wrapped nodes. For example
* typescript export statements or python decorators
@ -51,3 +102,139 @@ export function findPossiblyWrappedNode(
return isTargetNode(node) ? node : null;
};
}
export function patternFinder(...patterns: string[]): NodeFinder {
const parsedPatterns = parsePatternStrings(patterns);
return (node: SyntaxNode) => {
for (const pattern of parsedPatterns) {
const match = tryPatternMatch(node, pattern);
if (match != null) {
return match;
}
}
return null;
};
}
function parsePatternStrings(patternStrings: string[]) {
return patternStrings.map((patternString) =>
patternString.split(".").map((pattern) => new Pattern(pattern))
);
}
function tryPatternMatch(
node: SyntaxNode,
patterns: Pattern[]
): SyntaxNode | null {
const firstPattern = patterns[0];
const lastPattern = patterns[patterns.length - 1];
let resultNode: SyntaxNode | null = null;
let resultPattern;
// Only one type try to match current node.
if (patterns.length === 1) {
if (firstPattern.typeEquals(node)) {
resultNode = node;
resultPattern = firstPattern;
}
} else {
// Matched last. Ascending search.
if (lastPattern.typeEquals(node)) {
const result = searchNodeAscending(node, lastPattern, patterns);
if (result != null) {
[resultNode, resultPattern] = result;
}
}
// Matched first. Descending search.
if (resultNode == null && firstPattern.typeEquals(node)) {
const result = searchNodeDescending(node, firstPattern, patterns);
if (result != null) {
[resultNode, resultPattern] = result;
}
}
}
// Use field name child if field name is given
if (
resultNode != null &&
resultPattern != null &&
resultPattern.fields != null
) {
resultPattern.fields.forEach((field) => {
resultNode = resultNode?.childForFieldName(field) ?? null;
});
}
return resultNode;
}
type NodePattern = [SyntaxNode, Pattern] | null;
function searchNodeAscending(
node: SyntaxNode,
lastPattern: Pattern,
patterns: Pattern[]
): NodePattern {
let resultNode = node;
let resultPattern = lastPattern;
let important: NodePattern = lastPattern.isImportant
? [node, lastPattern]
: null;
for (let i = patterns.length - 2; i > -1; --i) {
const pattern = patterns[i];
if (resultNode.parent == null || !pattern.typeEquals(resultNode.parent)) {
if (pattern.isOptional) {
continue;
}
return null;
}
resultNode = resultNode.parent;
resultPattern = pattern;
if (pattern.isImportant) {
important = [resultNode, pattern];
}
}
return important != null ? important : [resultNode, resultPattern];
}
function searchNodeDescending(
node: SyntaxNode,
firstPattern: Pattern,
patterns: Pattern[]
): NodePattern {
let tmpNode = node;
// Even if descending search we return the "top" node by default.
let important: NodePattern = [node, firstPattern];
for (let i = 1; i < patterns.length; ++i) {
const pattern = patterns[i];
const children = tmpNode.namedChildren.filter((node) =>
pattern.typeEquals(node)
);
if (children.length !== 1) {
if (pattern.isOptional) {
continue;
}
return null;
}
tmpNode = children[0];
if (pattern.isImportant) {
important = [tmpNode, pattern];
}
}
return important;
}
class Pattern {
type: string;
fields: string[] | null = null;
isImportant: boolean = false;
isOptional: boolean = false;
constructor(pattern: string) {
this.type = pattern.match(/^[\w*]+/)![0];
this.fields = [...pattern.matchAll(/(?<=\[).+?(?=\])/g)].map((m) => m[0]);
this.isImportant = pattern.indexOf("!") > -1;
this.isOptional = pattern.indexOf("?") > -1;
}
typeEquals(node: SyntaxNode) {
return this.type === node.type || this.type === "*";
}
}

View File

@ -1,16 +1,37 @@
import { SyntaxNode } from "web-tree-sitter";
import { TextEditor } from "vscode";
import { NodeMatcher, NodeFinder, SelectionExtractor } from "./Types";
import { simpleSelectionExtractor } from "./nodeSelectors";
import { typedNodeFinder } from "./nodeFinders";
import {
NodeMatcher,
NodeFinder,
SelectionExtractor,
NodeMatcherAlternative,
ScopeType,
SelectionWithEditor,
} from "./Types";
import {
simpleSelectionExtractor,
argumentSelectionExtractor,
selectWithLeadingDelimiter,
} from "./nodeSelectors";
import {
typedNodeFinder,
patternFinder,
argumentNodeFinder,
} from "./nodeFinders";
export function matcher(
finder: NodeFinder,
selector: SelectionExtractor = simpleSelectionExtractor
): NodeMatcher {
return function (editor: TextEditor, node: SyntaxNode) {
const targetNode = finder(node);
return targetNode ? selector(editor, targetNode) : null;
return function (selection: SelectionWithEditor, node: SyntaxNode) {
const targetNode = finder(node, selection.selection);
return targetNode != null
? [
{
node: targetNode,
selection: selector(selection.editor, targetNode),
},
]
: null;
};
}
@ -18,17 +39,21 @@ export function composedMatcher(
finders: NodeFinder[],
selector: SelectionExtractor = simpleSelectionExtractor
): NodeMatcher {
return function (editor: TextEditor, initialNode: SyntaxNode) {
return function (selection: SelectionWithEditor, initialNode: SyntaxNode) {
let returnNode: SyntaxNode = initialNode;
for (const finder of finders) {
const foundNode = finder(returnNode);
const foundNode = finder(returnNode, selection.selection);
if (foundNode == null) {
return null;
}
returnNode = foundNode;
}
return selector(editor, returnNode);
return [
{
node: returnNode,
selection: selector(selection.editor, returnNode),
},
];
};
}
@ -36,6 +61,21 @@ export function typeMatcher(...typeNames: string[]) {
return matcher(typedNodeFinder(...typeNames));
}
export function patternMatcher(...patterns: string[]): NodeMatcher {
return matcher(patternFinder(...patterns));
}
export function argumentMatcher(...parentTypes: string[]): NodeMatcher {
return matcher(
argumentNodeFinder(...parentTypes),
argumentSelectionExtractor()
);
}
export function valueMatcher(...patterns: string[]): NodeMatcher {
return matcher(patternFinder(...patterns), selectWithLeadingDelimiter);
}
/**
* Create a new matcher that will try the given matchers in sequence until one
* returns non-null
@ -44,9 +84,9 @@ export function typeMatcher(...typeNames: string[]) {
* @returns A NodeMatcher that tries the given matchers in sequence
*/
export function cascadingMatcher(...matchers: NodeMatcher[]): NodeMatcher {
return (editor: TextEditor, node: SyntaxNode) => {
return (selection: SelectionWithEditor, node: SyntaxNode) => {
for (const matcher of matchers) {
const match = matcher(editor, node);
const match = matcher(selection, node);
if (match != null) {
return match;
}
@ -57,8 +97,22 @@ export function cascadingMatcher(...matchers: NodeMatcher[]): NodeMatcher {
}
export const notSupported: NodeMatcher = (
editor: TextEditor,
selection: SelectionWithEditor,
node: SyntaxNode
) => {
throw new Error("Node type not supported");
};
export function createPatternMatchers(
nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>>
): Record<ScopeType, NodeMatcher> {
Object.keys(nodeMatchers).forEach((scopeType: ScopeType) => {
let matcher = nodeMatchers[scopeType];
if (Array.isArray(matcher)) {
nodeMatchers[scopeType] = patternMatcher(...matcher);
} else if (typeof matcher === "string") {
nodeMatchers[scopeType] = patternMatcher(matcher);
}
});
return nodeMatchers as Record<ScopeType, NodeMatcher>;
}

View File

@ -22,6 +22,20 @@ export function simpleSelectionExtractor(
};
}
export function argumentSelectionExtractor(): SelectionExtractor {
return delimitedSelector(
(node) =>
node.type === "," ||
node.type === "(" ||
node.type === ")" ||
node.type === "[" ||
node.type === "]" ||
node.type === "}" ||
node.type === "{",
", "
);
}
export function selectWithLeadingDelimiter(
editor: TextEditor,
node: SyntaxNode
@ -45,7 +59,7 @@ function getNextNonDelimiterNode(
startNode: SyntaxNode,
isDelimiterNode: (node: SyntaxNode) => boolean
): SyntaxNode | null {
var node = startNode.nextSibling;
let node = startNode.nextSibling;
while (node != null) {
if (!isDelimiterNode(node)) {
@ -62,7 +76,7 @@ function getPreviousNonDelimiterNode(
startNode: SyntaxNode,
isDelimiterNode: (node: SyntaxNode) => boolean
): SyntaxNode | null {
var node = startNode.previousSibling;
let node = startNode.previousSibling;
while (node != null) {
if (!isDelimiterNode(node)) {
@ -75,6 +89,10 @@ function getPreviousNonDelimiterNode(
return node;
}
export function delimitersSelector(...delimiters: string[]) {
return delimitedSelector((node) => delimiters.includes(node.type), ", ");
}
export function delimitedSelector(
isDelimiterNode: (node: SyntaxNode) => boolean,
defaultDelimiter: string

View File

@ -1,15 +1,14 @@
import { concat, range, zip } from "lodash";
import update from "immutability-helper";
import { SyntaxNode } from "web-tree-sitter";
import { getNodeMatcher } from "./languages";
import { Selection, Range, Position, Location, TextDocument } from "vscode";
import { nodeMatchers } from "./languages";
import {
Mark,
PrimitiveTarget,
ProcessedTargetsContext,
RangeTarget,
SelectionContext,
SelectionWithContext,
SelectionWithEditor,
Target,
TypedSelection,
@ -18,7 +17,10 @@ import {
} from "./Types";
import { performInsideOutsideAdjustment } from "./performInsideOutsideAdjustment";
import { SUBWORD_MATCHER } from "./constants";
import { selectionWithEditorFromPositions } from "./selectionUtils";
import {
selectionWithEditorFromPositions,
selectionWithEditorFromRange,
} from "./selectionUtils";
export default function processTargets(
context: ProcessedTargetsContext,
@ -236,41 +238,36 @@ function transformSelection(
switch (modifier.type) {
case "identity":
return [{ selection, context: {} }];
case "containingScope":
var node: SyntaxNode | null = context.getNodeAtLocation(
let node: SyntaxNode | null = context.getNodeAtLocation(
new Location(selection.editor.document.uri, selection.selection)
);
const nodeMatcher =
nodeMatchers[selection.editor.document.languageId][modifier.scopeType];
const nodeMatcher = getNodeMatcher(
selection.editor.document.languageId,
modifier.scopeType,
modifier.includeSiblings ?? false
);
while (node != null) {
const matchedSelection = nodeMatcher(selection.editor, node);
if (matchedSelection != null) {
var matchedSelections: SelectionWithContext[];
if (modifier.includeSiblings) {
matchedSelections = node
.parent!.children.map((sibling) =>
nodeMatcher(selection.editor, sibling)
)
.filter(
(selection) => selection != null
) as SelectionWithContext[];
} else {
matchedSelections = [matchedSelection];
}
return matchedSelections.map((matchedSelection) => ({
selection: {
editor: selection.editor,
selection: matchedSelection.selection,
},
context: matchedSelection.context,
}));
const matches = nodeMatcher(selection, node);
if (matches != null) {
return matches
.map((match) => match.selection)
.map((matchedSelection) => ({
selection: selectionWithEditorFromRange(
selection,
matchedSelection.selection
),
context: matchedSelection.context,
}));
}
node = node.parent;
}
throw new Error(`Couldn't find containing ${modifier.scopeType}`);
case "subpiece":
const token = selection.editor.document.getText(selection.selection);
let pieces: { start: number; end: number }[] = [];

View File

@ -0,0 +1,40 @@
spokenForm: take vest tween whale
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: range
start:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: v}
end:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: w}
excludeStart: true
excludeEnd: true
extraArgs: []
marks:
default.v:
start: {line: 1, character: 6}
end: {line: 1, character: 11}
default.w:
start: {line: 1, character: 21}
end: {line: 1, character: 26}
initialState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 26}
active: {line: 1, character: 11}
finalState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 11}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 11}
active: {line: 1, character: 21}
fullTargets: [{type: range, excludeStart: true, excludeEnd: true, start: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}, end: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: w}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}}]

View File

@ -0,0 +1,40 @@
spokenForm: take vest until whale
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: range
start:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: v}
end:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: w}
excludeStart: false
excludeEnd: true
extraArgs: []
marks:
default.v:
start: {line: 1, character: 6}
end: {line: 1, character: 11}
default.w:
start: {line: 1, character: 21}
end: {line: 1, character: 26}
initialState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
finalState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 21}
fullTargets: [{type: range, excludeStart: false, excludeEnd: true, start: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}, end: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: w}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}}]

View File

@ -0,0 +1,40 @@
spokenForm: take whale tween vest
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: range
start:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: w}
end:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: v}
excludeStart: true
excludeEnd: true
extraArgs: []
marks:
default.w:
start: {line: 1, character: 21}
end: {line: 1, character: 26}
default.v:
start: {line: 1, character: 6}
end: {line: 1, character: 11}
initialState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
finalState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 21}
active: {line: 1, character: 11}
thatMark:
- anchor: {line: 1, character: 21}
active: {line: 1, character: 11}
fullTargets: [{type: range, excludeStart: true, excludeEnd: true, start: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: w}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}, end: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}}]

View File

@ -0,0 +1,40 @@
spokenForm: take whale until vest
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: range
start:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: w}
end:
type: primitive
mark: {type: decoratedSymbol, symbolColor: default, character: v}
excludeStart: false
excludeEnd: true
extraArgs: []
marks:
default.w:
start: {line: 1, character: 21}
end: {line: 1, character: 26}
default.v:
start: {line: 1, character: 6}
end: {line: 1, character: 11}
initialState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 21}
finalState:
documentContents: |
const value = "Hello world";
selections:
- anchor: {line: 1, character: 26}
active: {line: 1, character: 11}
thatMark:
- anchor: {line: 1, character: 26}
active: {line: 1, character: 11}
fullTargets: [{type: range, excludeStart: false, excludeEnd: true, start: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: w}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}, end: {type: primitive, mark: {type: decoratedSymbol, symbolColor: default, character: v}, selectionType: token, position: contents, modifier: {type: identity}, insideOutsideType: inside}}]

View File

@ -0,0 +1,35 @@
spokenForm: take arg
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 26}
active: {line: 2, character: 26}
finalState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 31}
thatMark:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 31}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take arg
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 8}
finalState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
thatMark:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take call
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionCall}
extraArgs: []
marks: {}
initialState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 5}
active: {line: 1, character: 5}
finalState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 15}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionCall}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take class
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: class}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
finalState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: class}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take class name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: className}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
finalState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 1, character: 13}
active: {line: 1, character: 20}
thatMark:
- anchor: {line: 1, character: 13}
active: {line: 1, character: 20}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: className}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take comment
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: comment}
extraArgs: []
marks: {}
initialState:
documentContents: |
// Hello world
selections:
- anchor: {line: 1, character: 2}
active: {line: 1, character: 2}
finalState:
documentContents: |
// Hello world
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 14}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 14}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: comment}, insideOutsideType: inside}]

View File

@ -0,0 +1,39 @@
spokenForm: take every arg
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 20}
finalState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 31}
- anchor: {line: 2, character: 33}
active: {line: 2, character: 42}
thatMark:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 31}
- anchor: {line: 2, character: 33}
active: {line: 2, character: 42}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every arg
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 8}
finalState:
documentContents: |
myFunk(1, 2, 3);
selections:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
- anchor: {line: 1, character: 10}
active: {line: 1, character: 11}
- anchor: {line: 1, character: 13}
active: {line: 1, character: 14}
thatMark:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
- anchor: {line: 1, character: 10}
active: {line: 1, character: 11}
- anchor: {line: 1, character: 13}
active: {line: 1, character: 14}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every item
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
int[] values = {1, 2, 3};
selections:
- anchor: {line: 1, character: 17}
active: {line: 1, character: 17}
finalState:
documentContents: |
int[] values = {1, 2, 3};
selections:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 17}
- anchor: {line: 1, character: 19}
active: {line: 1, character: 20}
- anchor: {line: 1, character: 22}
active: {line: 1, character: 23}
thatMark:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 17}
- anchor: {line: 1, character: 19}
active: {line: 1, character: 20}
- anchor: {line: 1, character: 22}
active: {line: 1, character: 23}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take funk
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: namedFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 2, character: 4}
active: {line: 4, character: 5}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 4, character: 5}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: namedFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take funk
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: namedFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
public MyClass () {
}
}
selections:
- anchor: {line: 2, character: 4}
active: {line: 4, character: 5}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 4, character: 5}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: namedFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take funk name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionName}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 15}
thatMark:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionName}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take funk name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionName}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
public MyClass () {
}
}
selections:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 18}
thatMark:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 18}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionName}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take if
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: ifStatement}
extraArgs: []
marks: {}
initialState:
documentContents: |
if () {
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
finalState:
documentContents: |
if () {
}
selections:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: ifStatement}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take item
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\nint[] values = {1, 2, 3};\r\n"
selections:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 16}
finalState:
documentContents: "\r\nint[] values = {1, 2, 3};\r\n"
selections:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 17}
thatMark:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 17}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take list
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: list}
extraArgs: []
marks: {}
initialState:
documentContents: |
int[] values = {1, 2, 3};
selections:
- anchor: {line: 1, character: 17}
active: {line: 1, character: 17}
finalState:
documentContents: |
int[] values = {1, 2, 3};
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 24}
thatMark:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 24}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: list}, insideOutsideType: inside}]

View File

@ -0,0 +1,39 @@
spokenForm: take map
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: dictionary}
extraArgs: []
marks: {}
initialState:
documentContents: |
List<String> value = new ArrayList() {
{
add("a");
add("b");
add("c");
}
};
selections:
- anchor: {line: 3, character: 8}
active: {line: 3, character: 8}
finalState:
documentContents: |
List<String> value = new ArrayList() {
{
add("a");
add("b");
add("c");
}
};
selections:
- anchor: {line: 2, character: 4}
active: {line: 6, character: 5}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 6, character: 5}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: dictionary}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 15}
thatMark:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 26}
active: {line: 2, character: 26}
finalState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 27}
active: {line: 2, character: 31}
thatMark:
- anchor: {line: 2, character: 27}
active: {line: 2, character: 31}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take name
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 15}
finalState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 12}
thatMark:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 12}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take state
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: statement}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
finalState:
documentContents: |
public class MyClass {
}
selections:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 1}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: statement}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take string
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: string}
extraArgs: []
marks: {}
initialState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 22}
active: {line: 1, character: 22}
finalState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 28}
thatMark:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 28}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: string}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take type
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: type}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
finalState:
documentContents: |
public class MyClass {
void myFunk () {
}
}
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 8}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 8}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: type}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take type
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: type}
extraArgs: []
marks: {}
initialState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 27}
active: {line: 2, character: 27}
finalState:
documentContents: |
public class MyClass {
public MyClass (String name, int value) {
}
}
selections:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 26}
thatMark:
- anchor: {line: 2, character: 20}
active: {line: 2, character: 26}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: type}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take type
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: type}
extraArgs: []
marks: {}
initialState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 15}
finalState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 6}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 6}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: type}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take value
languageId: java
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: value}
extraArgs: []
marks: {}
initialState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
finalState:
documentContents: |
String value = "hello world";
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 28}
thatMark:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 28}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: value}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take item
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 9}
finalState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 16}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take item
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": [1, 2, 3]\r\n}\r\n"
selections:
- anchor: {line: 2, character: 13}
active: {line: 2, character: 13}
finalState:
documentContents: "\r\n{\r\n \"foo\": [1, 2, 3]\r\n}\r\n"
selections:
- anchor: {line: 2, character: 12}
active: {line: 2, character: 13}
thatMark:
- anchor: {line: 2, character: 12}
active: {line: 2, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take key
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 10}
active: {line: 2, character: 10}
finalState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 9}
thatMark:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 9}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionKey}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take list
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: list}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": [1, 2, 3]\r\n}\r\n"
selections:
- anchor: {line: 2, character: 19}
active: {line: 2, character: 19}
finalState:
documentContents: "\r\n{\r\n \"foo\": [1, 2, 3]\r\n}\r\n"
selections:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 20}
thatMark:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 20}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: list}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take string
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: string}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 12}
active: {line: 2, character: 12}
finalState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 16}
thatMark:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: string}, insideOutsideType: inside}]

View File

@ -0,0 +1,23 @@
spokenForm: take value
languageId: json
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: value}
extraArgs: []
marks: {}
initialState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 9}
active: {line: 2, character: 9}
finalState:
documentContents: "\r\n{\r\n \"foo\": \"bar\"\r\n}\r\n"
selections:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 16}
thatMark:
- anchor: {line: 2, character: 11}
active: {line: 2, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: value}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take attribute
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlAttribute}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 14}
active: {line: 2, character: 14}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 15}
thatMark:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlAttribute}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take element
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlElement}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 36}
thatMark:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 36}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlElement}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take end tag
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlEndTag}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 30}
active: {line: 2, character: 36}
thatMark:
- anchor: {line: 2, character: 30}
active: {line: 2, character: 36}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlEndTag}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every attribute
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlAttribute, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 15}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 15}
- anchor: {line: 2, character: 16}
active: {line: 2, character: 26}
thatMark:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 15}
- anchor: {line: 2, character: 16}
active: {line: 2, character: 26}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlAttribute, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take key
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 10}
active: {line: 2, character: 10}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 9}
thatMark:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 9}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionKey}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take start tag
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlStartTag}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 27}
thatMark:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 27}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlStartTag}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take tags
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: xmlBothTags}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 15}
active: {line: 2, character: 15}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 27}
- anchor: {line: 2, character: 30}
active: {line: 2, character: 36}
thatMark:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 27}
- anchor: {line: 2, character: 30}
active: {line: 2, character: 36}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: xmlBothTags}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take value
languageId: javascript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: value}
extraArgs: []
marks: {}
initialState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 7}
active: {line: 2, character: 9}
finalState:
documentContents: |
const Foo = (
<div id="bar" name="foo">bar</div>
);
selections:
- anchor: {line: 2, character: 10}
active: {line: 2, character: 15}
thatMark:
- anchor: {line: 2, character: 10}
active: {line: 2, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: value}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take arg
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 21}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take arg
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 8}
finalState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 9}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 9}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take call
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionCall}
extraArgs: []
marks: {}
initialState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
finalState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 16}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionCall}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take class
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: class}
extraArgs: []
marks: {}
initialState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: class}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take class
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: class}
extraArgs: []
marks: {}
initialState:
documentContents: |-
@annotation
class MyClass:
""""""
selections:
- anchor: {line: 3, character: 4}
active: {line: 3, character: 4}
finalState:
documentContents: |-
@annotation
class MyClass:
""""""
selections:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 10}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: class}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take class name
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: className}
extraArgs: []
marks: {}
initialState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: className}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take comment
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: comment}
extraArgs: []
marks: {}
initialState:
documentContents: |
# Hello world
selections:
- anchor: {line: 1, character: 1}
active: {line: 1, character: 1}
finalState:
documentContents: |
# Hello world
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: comment}, insideOutsideType: inside}]

View File

@ -0,0 +1,33 @@
spokenForm: take every arg
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 21}
- anchor: {line: 1, character: 23}
active: {line: 1, character: 28}
thatMark:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 21}
- anchor: {line: 1, character: 23}
active: {line: 1, character: 28}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every arg
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 8}
finalState:
documentContents: |-
my_funk(1, 2, 3)
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 9}
- anchor: {line: 1, character: 11}
active: {line: 1, character: 12}
- anchor: {line: 1, character: 14}
active: {line: 1, character: 15}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 9}
- anchor: {line: 1, character: 11}
active: {line: 1, character: 12}
- anchor: {line: 1, character: 14}
active: {line: 1, character: 15}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 16}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 16}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,35 @@
spokenForm: take every item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 19}
- anchor: {line: 1, character: 21}
active: {line: 1, character: 25}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 13}
- anchor: {line: 1, character: 15}
active: {line: 1, character: 19}
- anchor: {line: 1, character: 21}
active: {line: 1, character: 25}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem, includeSiblings: true}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take funk
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: namedFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: namedFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take funk
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: namedFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |-
@annotation
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 3, character: 4}
active: {line: 3, character: 4}
finalState:
documentContents: |-
@annotation
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 10}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 3, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: namedFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take funk name
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionName}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 11}
thatMark:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 11}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionName}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take if
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: ifStatement}
extraArgs: []
marks: {}
initialState:
documentContents: |-
if True:
return
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |-
if True:
return
selections:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 2, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: ifStatement}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take item
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionItem}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionItem}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take key
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
finalState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
thatMark:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 10}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: collectionKey}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take lambda
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: arrowFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = lambda x: x
selections:
- anchor: {line: 1, character: 14}
active: {line: 1, character: 14}
finalState:
documentContents: |
value = lambda x: x
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 19}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 19}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: arrowFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take list
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: list}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = [1, 2, 3]
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 17}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 17}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: list}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take list
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: list}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {1, 2, 3}
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 17}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 17}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: list}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take map
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: dictionary}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
finalState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 26}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 26}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: dictionary}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take name
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 7}
finalState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 5}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 5}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take name
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 19}
active: {line: 1, character: 19}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 16}
thatMark:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 16}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take name
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: name}
extraArgs: []
marks: {}
initialState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |-
class MyClass:
""""""
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: name}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take state
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: statement}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 6}
finalState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 21}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: statement}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take string
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: string}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 15}
active: {line: 1, character: 15}
finalState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 21}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: string}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take type
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: type}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 33}
active: {line: 1, character: 36}
thatMark:
- anchor: {line: 1, character: 33}
active: {line: 1, character: 36}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: type}, insideOutsideType: inside}]

View File

@ -0,0 +1,29 @@
spokenForm: take type
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: type}
extraArgs: []
marks: {}
initialState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 16}
finalState:
documentContents: |
def my_funk(name: str, value) -> str:
return
selections:
- anchor: {line: 1, character: 18}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 18}
active: {line: 1, character: 21}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: type}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take value
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: value}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 5}
active: {line: 1, character: 5}
finalState:
documentContents: |
value = "hello world"
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 21}
thatMark:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 21}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: value}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take value
languageId: python
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: value}
extraArgs: []
marks: {}
initialState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 10}
active: {line: 1, character: 10}
finalState:
documentContents: |
value = {a: 1, b: 2, c: 3}
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: value}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take arg
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |
function myFunk (name: string) {
}
selections:
- anchor: {line: 1, character: 21}
active: {line: 1, character: 21}
finalState:
documentContents: |
function myFunk (name: string) {
}
selections:
- anchor: {line: 1, character: 17}
active: {line: 1, character: 29}
thatMark:
- anchor: {line: 1, character: 17}
active: {line: 1, character: 29}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take arg
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: argumentOrParameter}
extraArgs: []
marks: {}
initialState:
documentContents: |
myFunk(1, 2, 3)
selections:
- anchor: {line: 1, character: 8}
active: {line: 1, character: 8}
finalState:
documentContents: |
myFunk(1, 2, 3)
selections:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
thatMark:
- anchor: {line: 1, character: 7}
active: {line: 1, character: 8}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: argumentOrParameter}, insideOutsideType: inside}]

View File

@ -0,0 +1,31 @@
spokenForm: take arrow
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: arrowFunction}
extraArgs: []
marks: {}
initialState:
documentContents: |
const value = () => {
}
selections:
- anchor: {line: 2, character: 0}
active: {line: 2, character: 0}
finalState:
documentContents: |
const value = () => {
}
selections:
- anchor: {line: 1, character: 14}
active: {line: 3, character: 1}
thatMark:
- anchor: {line: 1, character: 14}
active: {line: 3, character: 1}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: arrowFunction}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take call
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: functionCall}
extraArgs: []
marks: {}
initialState:
documentContents: |
myFunk()
selections:
- anchor: {line: 1, character: 1}
active: {line: 1, character: 1}
finalState:
documentContents: |
myFunk()
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 8}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 8}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: functionCall}, insideOutsideType: inside}]

View File

@ -0,0 +1,41 @@
spokenForm: take class
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: class}
extraArgs: []
marks: {}
initialState:
documentContents: |
class MyClass {
constructor () {
}
myFunk () {
}
}
selections:
- anchor: {line: 5, character: 4}
active: {line: 5, character: 4}
finalState:
documentContents: |
class MyClass {
constructor () {
}
myFunk () {
}
}
selections:
- anchor: {line: 1, character: 0}
active: {line: 8, character: 1}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 8, character: 1}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: class}, insideOutsideType: inside}]

View File

@ -0,0 +1,41 @@
spokenForm: take class name
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: className}
extraArgs: []
marks: {}
initialState:
documentContents: |
class MyClass {
constructor () {
}
myFunk () {
}
}
selections:
- anchor: {line: 5, character: 4}
active: {line: 5, character: 4}
finalState:
documentContents: |
class MyClass {
constructor () {
}
myFunk () {
}
}
selections:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
thatMark:
- anchor: {line: 1, character: 6}
active: {line: 1, character: 13}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: className}, insideOutsideType: inside}]

View File

@ -0,0 +1,27 @@
spokenForm: take comment
languageId: typescript
command:
actionName: setSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: comment}
extraArgs: []
marks: {}
initialState:
documentContents: |
// const value: string = "Hello world";
selections:
- anchor: {line: 1, character: 32}
active: {line: 1, character: 32}
finalState:
documentContents: |
// const value: string = "Hello world";
selections:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 39}
thatMark:
- anchor: {line: 1, character: 0}
active: {line: 1, character: 39}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, modifier: {type: containingScope, scopeType: comment}, insideOutsideType: inside}]

Some files were not shown because too many files have changed in this diff Show More