Skip to content

Improve support for custom user grammars #494

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

Open
1 of 9 tasks
pokey opened this issue Jan 18, 2022 · 0 comments
Open
1 of 9 tasks

Improve support for custom user grammars #494

pokey opened this issue Jan 18, 2022 · 0 comments
Labels
enhancement New feature or request
Milestone

Comments

@pokey
Copy link
Member

pokey commented Jan 18, 2022

The problem

We have started to add support for user-defined commands that reference cursorless targets, but today they have some limitations, and we have only just started to explore the idea of users defining their own cursorless-powered custom grammars. We'd like to use this issue to explore specific use cases to drive development in this direction, and create a place to track the various cursorless efforts that need to be completed to handle these use cases.

The examples

Example 1: "else"

The goal

"else" would find the closest "if" and insert an else clause
- @sterlind

I'll do my best to elaborate on @sterlind's use case, (but please correct me if I've gotten this wrong @sterlind 😅). In the following example:

if (foo) {
    const bar = "whatever"|
}

with the user's cursor at the |, @sterlind would like to be able to say eg "else call baz" and have the following output:

if (foo) {
  const bar = "whatever";
} else {
  baz();
}
The solution

Note: we assume that the user has defined a call <user.whatever> command themselves

Then the user will be able to define a talon command as follows:

else: user.insert_else()

And then in python define the following:

@mod.action_class
class Actions:
    def insert_else():
        """Insert an else snippet after the current if statement"""
        cursorless_target = {
            "type": "primitive",
            "mark": {"type": "cursor"},
            "position": "after",
        }

        actions.user.cursorless_command(
            "insertSnippet", cursorless_target, ["elseStatement"]
        )
  • To get this setup to work in Python, we'll need to properly handle indentation. In particular, once we have Switch targets to object-oriented #210, a python if statement will have an insertAfter function that will create a new line and dedent it. This function will be used by insertSnippet
Questions
  • Should there be a cursorless version eg "at air else" or "after air else"?

Example 2: "arg foo of int"

The goal

"arg foo of int" would automatically append "foo: int" to the closest arg-capable scope (enclosing function)
- @sterlind

As above, I'll do my best to elaborate on @sterlind's use case. In the following example:

function helloWorld() {
    const bar = "baz";|
}

with the user's cursor at the |, @sterlind would like to be able to say eg "arg foo of int" and have the following output:

function helloWorld(foo: int) {
  const bar = "baz";
}
The solution
Option 1: Restricted argument grammar

In this version, the user will have a specific <user.argument> capture that restricts what can come after "arg", and will return a string. Cursorless will need the following to make this setup work:

Then the user will be able to define a talon command as follows:

arg <user.argument>: user.append_argument(argument)

And then in python define the following:

@mod.action_class
class Actions:
    def append_argument(argument: str):
        """Append an arguement to the argument list of the current function"""
        cursorless_target = {
            "type": "primitive",
            "modifier": {
                "type": "containingScope",
                "scopeType": "parameterList",
                "includeSiblings": False,
            },
            "mark": {"type": "cursor"},
            "position": "after",
        }

        actions.user.cursorless_command("replace", cursorless_target, [[argument]])
Option 2: Unrestricted argument grammar

In this version, the user will be able to say anything after "arg", but the cursor will move. Cursorless will need the following in order to support this option:

Then the user will be able to define a talon command as follows:

arg: user.append_argument()

And then in python define the following:

@mod.action_class
class Actions:
    def append_argument():
        """Append an arguement to the argument list of the current function"""
        cursorless_target = {
            "type": "primitive",
            "modifier": {
                "type": "containingScope",
                "scopeType": "parameterList",
                "includeSiblings": False,
            },
            "mark": {"type": "cursor"},
        }

        actions.user.cursorless_command("editNewLineAfter", cursorless_target)
Questions
  • Should there be a cursorless version eg "at air arg foo of int"?

Example 3: "returns string"

TODO

Example 4: "pass bar to call rose drum"

TODO

@pokey pokey added the enhancement New feature or request label Jan 18, 2022
@pokey pokey added this to the On deck milestone Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant