Add suffixedMatcher; use for keys (#260)

* Add suffixedMatcher; use for keys

* Fix whitespace

* Fix tests
This commit is contained in:
Pokey Rule 2021-09-06 17:58:53 +01:00 committed by GitHub
parent 4a5b5501bf
commit 8488e917d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 181 additions and 19 deletions

View File

@ -1,7 +1,7 @@
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
prefixedMatcher,
} from "../util/nodeMatchers";
import { NodeMatcherAlternative, ScopeType } from "../typings/Types";
@ -95,7 +95,7 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
"function_definition[declarator][declarator]", // void funcName() {}
"declaration.function_declarator![declarator]", // void funcName();
],
value: valueMatcher(
value: prefixedMatcher(
"*[declarator][value]",
"*[value]",
"assignment_expression[right]",

View File

@ -1,7 +1,7 @@
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
prefixedMatcher,
} from "../util/nodeMatchers";
import { NodeMatcherAlternative, ScopeType } from "../typings/Types";
@ -62,7 +62,7 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
"method_declaration.identifier!",
"constructor_declaration.identifier!",
],
value: valueMatcher("*[declarator][value]", "*[value]"),
value: prefixedMatcher("*[declarator][value]", "*[value]"),
collectionItem: argumentMatcher("array_initializer"),
argumentOrParameter: argumentMatcher("formal_parameters", "argument_list"),
};

View File

@ -1,7 +1,8 @@
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
prefixedMatcher,
suffixedMatcher,
} from "../util/nodeMatchers";
import { ScopeType, NodeMatcherAlternative } from "../typings/Types";
@ -10,8 +11,8 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
list: "array",
string: "string",
comment: "comment",
collectionKey: "pair[key]",
value: valueMatcher("*[value]"),
collectionKey: suffixedMatcher("pair[key]"),
value: prefixedMatcher("*[value]"),
collectionItem: argumentMatcher("object", "array"),
};

View File

@ -2,7 +2,8 @@ import { SyntaxNode } from "web-tree-sitter";
import {
createPatternMatchers,
argumentMatcher,
valueMatcher,
prefixedMatcher,
suffixedMatcher,
} from "../util/nodeMatchers";
import { NodeMatcherAlternative, ScopeType } from "../typings/Types";
@ -46,7 +47,7 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
list: listTypes,
statement: STATEMENT_TYPES,
string: "string",
collectionKey: "pair[key]",
collectionKey: suffixedMatcher("pair[key]"),
ifStatement: "if_statement",
anonymousFunction: "lambda",
functionCall: "call",
@ -55,7 +56,7 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
className: "class_definition[name]",
namedFunction: "decorated_definition?.function_definition",
functionName: "function_definition[name]",
type: valueMatcher("function_definition[return_type]", "*[type]"),
type: prefixedMatcher("function_definition[return_type]", "*[type]"),
name: [
"assignment[left]",
"typed_parameter.identifier!",
@ -63,7 +64,7 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
"*[name]",
],
collectionItem: argumentMatcher(...dictionaryTypes, ...listTypes),
value: valueMatcher("assignment[right]", "~subscript[value]"),
value: prefixedMatcher("assignment[right]", "~subscript[value]"),
argumentOrParameter: argumentMatcher("parameters", "argument_list"),
};

View File

@ -5,6 +5,7 @@ import {
patternMatcher,
createPatternMatchers,
argumentMatcher,
suffixedMatcher,
} from "../util/nodeMatchers";
import {
NodeMatcherAlternative,
@ -86,7 +87,10 @@ const nodeMatchers: Partial<Record<ScopeType, NodeMatcherAlternative>> = {
map: mapTypes,
list: listTypes,
string: ["string", "template_string"],
collectionKey: ["pair[key]", "jsx_attribute.property_identifier!"],
collectionKey: suffixedMatcher(
"pair[key]",
"jsx_attribute.property_identifier!"
),
collectionItem: argumentMatcher(...mapTypes, ...listTypes),
value: valueMatcher(),
ifStatement: "if_statement",

View File

@ -0,0 +1,31 @@
spokenForm: chuck key
languageId: python
command:
actionName: remove
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}
extraArgs: []
marks: {}
initialState:
documentContents: |-
{
"foo": "bar",
"baz": "bongo",
}
selections:
- anchor: {line: 1, character: 5}
active: {line: 1, character: 5}
finalState:
documentContents: |-
{
"bar",
"baz": "bongo",
}
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
thatMark:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}]

View File

@ -0,0 +1,31 @@
spokenForm: chuck key
languageId: python
command:
actionName: remove
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}
extraArgs: []
marks: {}
initialState:
documentContents: |-
{
"foo": "bar",
"baz": "bongo",
}
selections:
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
finalState:
documentContents: |-
{
"bar",
"baz": "bongo",
}
selections:
- anchor: {line: 1, character: 5}
active: {line: 1, character: 5}
thatMark:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}]

View File

@ -13,11 +13,11 @@ initialState:
- anchor: {line: 0, character: 2}
active: {line: 0, character: 2}
finalState:
documentContents: "foo: str "
documentContents: "foo: str"
selections:
- anchor: {line: 0, character: 2}
active: {line: 0, character: 2}
thatMark:
- anchor: {line: 0, character: 9}
active: {line: 0, character: 9}
- anchor: {line: 0, character: 8}
active: {line: 0, character: 8}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: value, includeSiblings: false}}]

View File

@ -0,0 +1,29 @@
spokenForm: chuck key
languageId: typescript
command:
actionName: remove
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}
extraArgs: []
marks: {}
initialState:
documentContents: |-
{
foo: "bar"
}
selections:
- anchor: {line: 1, character: 5}
active: {line: 1, character: 5}
finalState:
documentContents: |-
{
"bar"
}
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
thatMark:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: outside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}]

View File

@ -0,0 +1,29 @@
spokenForm: clear key
languageId: typescript
command:
actionName: clearAndSetSelection
partialTargets:
- type: primitive
modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}
extraArgs: []
marks: {}
initialState:
documentContents: |-
{
foo: "bar"
}
selections:
- anchor: {line: 1, character: 10}
active: {line: 1, character: 10}
finalState:
documentContents: |-
{
: "bar"
}
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
thatMark:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
fullTargets: [{type: primitive, mark: {type: cursor}, selectionType: token, position: contents, insideOutsideType: inside, modifier: {type: containingScope, scopeType: collectionKey, includeSiblings: false}}]

View File

@ -11,6 +11,7 @@ import {
simpleSelectionExtractor,
argumentSelectionExtractor,
selectWithLeadingDelimiter,
selectWithTrailingDelimiter,
} from "./nodeSelectors";
import {
typedNodeFinder,
@ -72,10 +73,26 @@ export function argumentMatcher(...parentTypes: string[]): NodeMatcher {
);
}
export function valueMatcher(...patterns: string[]): NodeMatcher {
/**
* Given `patterns`, creates a node matcher that will add leading delimiter to
* removal range.
* @param patterns Patterns for pattern finder
* @returns A node matcher
*/
export function prefixedMatcher(...patterns: string[]): NodeMatcher {
return matcher(patternFinder(...patterns), selectWithLeadingDelimiter);
}
/**
* Given `patterns`, creates a node matcher that will add trailing delimiter to
* removal range.
* @param patterns Patterns for pattern finder
* @returns A node matcher
*/
export function suffixedMatcher(...patterns: string[]): NodeMatcher {
return matcher(patternFinder(...patterns), selectWithTrailingDelimiter);
}
/**
* Create a new matcher that will try the given matchers in sequence until one
* returns non-null

View File

@ -40,11 +40,11 @@ export function selectWithLeadingDelimiter(
editor: TextEditor,
node: SyntaxNode
): SelectionWithContext {
const leadingDelimiterToken = node.previousSibling;
const leadingNonDelimiterToken = node.previousSibling?.previousSibling;
const leadingDelimiterRange =
leadingDelimiterToken != null
? makeRange(leadingDelimiterToken.startPosition, node.startPosition)
leadingNonDelimiterToken != null
? makeRange(leadingNonDelimiterToken.endPosition, node.startPosition)
: null;
return {
@ -55,6 +55,25 @@ export function selectWithLeadingDelimiter(
};
}
export function selectWithTrailingDelimiter(
editor: TextEditor,
node: SyntaxNode
): SelectionWithContext {
const trailingNonDelimiterToken = node.nextSibling?.nextSibling;
const trailingDelimiterRange =
trailingNonDelimiterToken != null
? makeRange(node.endPosition, trailingNonDelimiterToken.startPosition)
: null;
return {
...simpleSelectionExtractor(editor, node),
context: {
trailingDelimiterRange,
},
};
}
function getNextNonDelimiterNode(
startNode: SyntaxNode,
isDelimiterNode: (node: SyntaxNode) => boolean