Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Perl support and some tests #1301

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5f35c86
Initial Perl support and some tests
Leeft Mar 12, 2023
cbc72ff
Initial review notes: improve tests, few new tests
Leeft Mar 13, 2023
580f55d
Remove all unused variables
Leeft Mar 13, 2023
3175e6b
Fix item in hash not selecting both key and value
Leeft Mar 14, 2023
c4c6afa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 22, 2023
2abccee
Initial review notes: improve tests, few new tests
Leeft Mar 13, 2023
b406a48
Fix item in hash not selecting both key and value
Leeft Mar 14, 2023
2a70959
Move perl tests to match pnpm updates
Leeft Mar 23, 2023
fa494ec
Better regular expression handling and more tests
Leeft Mar 23, 2023
fe039a6
Fix "class name"
Leeft Mar 26, 2023
8de6370
Remove TODO comment
Leeft Mar 26, 2023
e8ed2bc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 26, 2023
726cab0
Fix `arg` and more tests
Leeft Mar 26, 2023
f7a0fcf
Fix hash key matching, add more tests
Leeft Mar 26, 2023
3596f1f
Simplify string processing; make chuck round work
Leeft Mar 26, 2023
65d7a59
Merge branch 'perl-support' of github.com:Leeft/cursorless into perl-…
Leeft Mar 26, 2023
37aa1b4
Merge branch 'main' into perl-support
Leeft Mar 27, 2023
521f2e0
Implement `callee`
Leeft Mar 27, 2023
a052de0
Merge remote-tracking branch 'origin/main' into perl-support
Leeft Apr 3, 2023
12a1a22
Add class support
Leeft Apr 3, 2023
d287a38
Improve arg behaviour
Leeft Apr 8, 2023
c6cb621
Add test for change class name in lexical package
Leeft Apr 8, 2023
b40ff3d
Suggested "item" tests for array assignment
Leeft Apr 8, 2023
70bed59
Improved condition scope with for loop support
Leeft Apr 8, 2023
c0187b2
Fix scope condition for C-style for loops
Leeft Apr 8, 2023
a0bb761
Add if and unless support for condition scope
Leeft Apr 8, 2023
64a9894
Initial name scope support
Leeft Apr 8, 2023
dd0d992
Initial value scope support
Leeft Apr 8, 2023
3846418
Partial branch scope support; ternary not yet done
Leeft Apr 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/cursorless-engine/src/languages/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const supportedLanguageIds = [
"jsonc",
"latex",
"markdown",
"perl",
"php",
"python",
"ruby",
Expand Down
2 changes: 2 additions & 0 deletions packages/cursorless-engine/src/languages/getNodeMatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import java from "./java";
import { patternMatchers as json } from "./json";
import latex from "./latex";
import markdown from "./markdown";
import { patternMatchers as perl } from "./perl";
import php from "./php";
import python from "./python";
import { patternMatchers as ruby } from "./ruby";
Expand Down Expand Up @@ -68,6 +69,7 @@ const languageMatchers: Record<
jsonc: json,
latex,
markdown,
perl,
php,
python,
ruby,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ const textFragmentExtractors: Record<
),
latex: fullDocumentTextFragmentExtractor,
markdown: fullDocumentTextFragmentExtractor,
perl: constructDefaultTextFragmentExtractor("perl"),
php: constructDefaultTextFragmentExtractor(
"php",
phpStringTextFragmentExtractor,
Expand Down
83 changes: 83 additions & 0 deletions packages/cursorless-engine/src/languages/perl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
argumentMatcher,
cascadingMatcher,
createPatternMatchers,
matcher,
patternMatcher,
} from "../util/nodeMatchers";
import { NodeMatcherAlternative } from "../typings/Types";
import { SimpleScopeTypeType } from "@cursorless/common";
import {
childRangeSelector,
unwrapSelectionExtractor,
} from "../util/nodeSelectors";
import { patternFinder } from "../util/nodeFinders";
import { branchMatcher } from "./branchMatcher";

const nodeMatchers: Partial<
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing "state" (statement)

Record<SimpleScopeTypeType, NodeMatcherAlternative>
> = {
map: "hash",
list: "array",
condition: matcher(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing ternaries. prob not a showstopper to ship without it; depending how common ternaries are in Perl

patternFinder(
"while_statement[condition]",
"for_statement_1[condition]",
"for_statement_2.binary_expression!",
"for_statement_2.array_variable!",
"for_simple_statement.binary_expression!",
"for_simple_statement.array_variable!",
"if_statement[condition]",
"unless_statement[condition]",
),
unwrapSelectionExtractor,
),
string: [
"string_single_quoted",
"string_double_quoted",
"string_q_quoted",
"string_qq_quoted",
],
ifStatement: "if_statement",
functionCall: [
"call_expression",
"call_expression_with_just_name",
"method_invocation",
],
functionCallee: cascadingMatcher(
patternMatcher("call_expression_with_just_name"),
matcher(
patternFinder("call_expression", "method_invocation"),
childRangeSelector(
["arguments", "argument", "empty_parenthesized_argument"],
[],
),
),
),
comment: "comments",
namedFunction: ["function_definition"],
anonymousFunction: "anonymous_function",
regularExpression: [
"patter_matcher_m", // Mistype (?) but that is the name in tree-sitter-perl; it must come before pattern_matcher
"pattern_matcher",
"regex_pattern_qr",
"substitution_pattern_s",
],
collectionKey: "key_value_pair[key]",
collectionItem: "hash[variable]",
argumentOrParameter: argumentMatcher("arguments"),
class: [
"package_statement!.block[body]",
"source_file!.package_statement",
"package_statement",
"source_file",
],
className: "package_statement.package_name!",
name: ["function_definition[name]", "*[key]"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • should include the matchers from className here as well
  • "name" should match variable name in assignment statement

value: ["*[value]"],
branch: cascadingMatcher(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing ternaries. prob not a showstopper to ship without it; depending how common ternaries are in Perl

branchMatcher("if_statement", ["else_clause", "elsif_clause"]),
),
};

export const patternMatchers = createPatternMatchers(nodeMatchers);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
languageId: perl
command:
version: 4
spokenForm: change arg
action: { name: clearAndSetSelection }
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: { type: argumentOrParameter }
usePrePhraseSnapshot: true
initialState:
documentContents: some_funky_func( "and", "three", "args" )
selections:
- anchor: { line: 0, character: 36 }
active: { line: 0, character: 36 }
marks: {}
finalState:
documentContents: some_funky_func( "and", "three", )
selections:
- anchor: { line: 0, character: 33 }
active: { line: 0, character: 33 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
languageId: perl
command:
version: 4
spokenForm: change arg
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: argumentOrParameter}
usePrePhraseSnapshot: true
initialState:
documentContents: some_funky_func( "and", "three", "args" )
selections:
- anchor: {line: 0, character: 29}
active: {line: 0, character: 29}
marks: {}
finalState:
documentContents: some_funky_func( "and", , "args" )
selections:
- anchor: {line: 0, character: 24}
active: {line: 0, character: 24}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
languageId: perl
command:
version: 4
spokenForm: change arg
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: argumentOrParameter}
usePrePhraseSnapshot: true
initialState:
documentContents: some_funky_func( "and", "three", "args" )
selections:
- anchor: {line: 0, character: 21}
active: {line: 0, character: 21}
marks: {}
finalState:
documentContents: some_funky_func( , "three", "args" )
selections:
- anchor: {line: 0, character: 17}
active: {line: 0, character: 17}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
languageId: perl
command:
version: 5
spokenForm: change arg
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: argumentOrParameter}
usePrePhraseSnapshot: true
initialState:
documentContents: some_funky_func( "and", "three", "args" )
selections:
- anchor: {line: 0, character: 16}
active: {line: 0, character: 16}
marks: {}
thrownError: {name: NoContainingScopeError}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mixed feelings about adding a test for behaviour that we don't actually want to preserve. any thoughts @AndreasArvidsson? some schools of thought support it; I believe it's called "characterization testing" in the literature

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
languageId: perl
command:
version: 5
spokenForm: change branch
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: branch}
usePrePhraseSnapshot: true
initialState:
documentContents: |
if ( 1 ) {
2;
} elsif ( 3 ) {
4;
} else {
5;
}
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
marks: {}
finalState:
documentContents: |2
elsif ( 3 ) {
4;
} else {
5;
}
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
languageId: perl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

command:
version: 5
spokenForm: change branch
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: branch}
usePrePhraseSnapshot: true
initialState:
documentContents: |
if ( 1 ) {
2;
} elsif ( 3 ) {
4;
} else {
5;
}
selections:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 2}
marks: {}
finalState:
documentContents: |
if ( 1 ) {
2;
} else {
5;
}
selections:
- anchor: {line: 2, character: 2}
active: {line: 2, character: 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
languageId: perl
command:
version: 5
spokenForm: change branch
action: {name: clearAndSetSelection}
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: {type: branch}
usePrePhraseSnapshot: true
initialState:
documentContents: |
if ( 1 ) {
2;
} elsif ( 3 ) {
4;
} else {
5;
}
selections:
- anchor: {line: 4, character: 2}
active: {line: 4, character: 2}
marks: {}
finalState:
documentContents: |
if ( 1 ) {
2;
} elsif ( 3 ) {
4;
}
selections:
- anchor: {line: 4, character: 2}
active: {line: 4, character: 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
languageId: perl
command:
version: 4
spokenForm: change call
action: { name: clearAndSetSelection }
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: { type: functionCall }
usePrePhraseSnapshot: true
initialState:
documentContents: |-
my $var = 1;
$var = func();
$var = 2;
selections:
- anchor: { line: 1, character: 12 }
active: { line: 1, character: 12 }
marks: {}
finalState:
documentContents: |-
my $var = 1;
$var = ;
$var = 2;
selections:
- anchor: { line: 1, character: 7 }
active: { line: 1, character: 7 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
languageId: perl
command:
version: 4
spokenForm: change call
action: { name: clearAndSetSelection }
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: { type: functionCall }
usePrePhraseSnapshot: true
initialState:
documentContents: |-
my $var = 1;
$var = func_with_params( $var );
$var = 2;
selections:
- anchor: { line: 1, character: 27 }
active: { line: 1, character: 27 }
marks: {}
finalState:
documentContents: |-
my $var = 1;
$var = ;
$var = 2;
selections:
- anchor: { line: 1, character: 7 }
active: { line: 1, character: 7 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
languageId: perl
command:
version: 4
spokenForm: change call
action: { name: clearAndSetSelection }
targets:
- type: primitive
modifiers:
- type: containingScope
scopeType: { type: functionCall }
usePrePhraseSnapshot: true
initialState:
documentContents: |-
my $var = 1;
$var = $object->method( );
$var = 2;
selections:
- anchor: { line: 1, character: 24 }
active: { line: 1, character: 24 }
marks: {}
finalState:
documentContents: |-
my $var = 1;
$var = ;
$var = 2;
selections:
- anchor: { line: 1, character: 7 }
active: { line: 1, character: 7 }
Loading