-
-
Notifications
You must be signed in to change notification settings - Fork 80
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
Expand cursorless talon command api #492
Comments
Allow custom grammars for reformat action is what I vote! |
Sample use case:
|
Since it often helps to have concrete, real world use cases written down, here is a running list of things I am currently implementing using
|
GitHub failed to backlink this comment, so here it is manually: #1655 (comment) |
update from meet-up: there are a couple approaches Use csvsWe could have custom modifier and action csvs which map from a spoken form to some representation of compound modifiers / actions. Here are a couple possibilities for representing
Benefit of using identifiers rather than spoken form is that they can change spoken form without breaking these, at the expense of being a bit harder to read / write In a csv this would be something like
For custom modifiers, we could have another csv where it's the same syntax but without the leading action. Eg
We could use this syntax in other places, eg
Could have a command to automatically generate this syntax, eg The benefit of this csv approach is that it's compact, and these are super easy to share / find in other people's repos, so even if people struggle a bit to read / write the syntax, power users could come up with cool compound modifiers / actions that others steal Use a set of Talon actionsAnother approach is to expose actions that users can use to build up targets. Eg shave <user.cursorless_target>:
target = user.cursorless_modifier_relative("character", -1, cursorless_target)
user.cursorless_action_remove(target) Note that it's not immediately obvious how to use this approach for custom modifiers, eg The benefit of this approach is that we don't need to have a custom parser, and the user can easily use it in Python, etc. The syntax will also be familiar for users of Talon / Python One disadvantage is that we potentially have less flexibility to change things, because we're locked into this api, whereas with our custom grammar we have more wiggle room. We could add version numbers, eg |
Using the spoken form directly is pretty appealing though. What if it always parsed used the default spoken forms? It’s not too hard to look up the default spoken form, once you understand cursorless well enough to have your own dialect. And they’d be fully transferable from one user to another. And if needed you could use sql-like placeholders to indicate substitution locations (lots of options here). |
Interesting idea to support default spoken form, though that locks us in to a set of default spoken forms, and they also might be surprised when they can't use their own. What if we just supported the exact same grammar as spoken, but using canonical ids, and supported a way to automatically generate from spoken form, as described above? The annoyance here is we'd need to implement our own command parser, rather than relying on Talon's as we do today, and there are likely things they may try to do that wouldn't quite work because they're stopping in the middle of some construct. Eg they might try to map |
Lots of dimensions on which to evaluate these:
yeah. good error messages from the parser could help a lot here, though. |
Use case from #1514:
(Although I may have butchered the grammar, which would itself be a useful data point.) Given |
I like this way of thinking about the problem |
Example from slack
Wanted to be able to do something like: copy next:
user.cursorless_action("take next instance")
user.cursorless_action("copy block") |
ApiCustom actionsAdd a new type of action: interface ParsedActionDescriptor {
name: "parsed";
content: string;
targets?: PartialTargetDescriptor[];
} Here is how we would use it in a Talon file: kill: user.cursorless_custom_command("chuck block")
kill <user.cursorless_target>: user.cursorless_custom_command("chuck block <target>", cursorless_target)
my before <user.cursorless_target>: user.cursorless_custom_command("bring this before <target>", cursorless_target)
my before <user.cursorless_target> and <user.cursorless_target>: user.cursorless_custom_command("bring <target1> before <target2>", cursorless_target_1, cursorless_target_2) Here is the command payloads that would come from the above rules, respectively: {
action: {
name: "parsed",
content: "chuck block",
}
}
{
action: {
name: "parsed",
content: "chuck block <target>",
targets: [{...}],
}
}
{
action: {
name: "parsed",
content: "bring this before <target>",
targets: [{...}],
}
}
{
action: {
name: "parsed",
content: "bring <target1> before <target2>",
targets: [{...}, {...}],
}
} Might also want to have csv version for actions, but let's leave that out for now
Custom modifiersAdd a new type of modifier: interface ParsedModifier {
type: "parsed";
content: string;
} Then add a new csv file talon-side called
Then user could use "duet" as a modifer. The modifier would correspond to: {
type: "parsed",
content: "two tokens",
} The user could say eg Implementation
|
- Private experimental api; one version of #492 - Currently used by [`wax_talon`](https://github.com/pokey/wax_talon); see pokey/wax_talon@4bd7d9b for example usage - Depends on #1880 for Python 3.10 `match` statements ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [-] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [x] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
- Private experimental api; one version of #492 - Currently used by [`wax_talon`](https://github.com/pokey/wax_talon); see pokey/wax_talon@4bd7d9b for example usage - Depends on #1880 for Python 3.10 `match` statements ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [-] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [x] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
- Private experimental api; one version of cursorless-dev#492 - Currently used by [`wax_talon`](https://github.com/pokey/wax_talon); see pokey/wax_talon@4bd7d9b for example usage - Depends on cursorless-dev#1880 for Python 3.10 `match` statements ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [-] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [x] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Initial work towards #492; will be used to parse scope types in #2131 Exposes a function `parseScopeType` that can parse strings like `funk`, `curly` etc into their corresponding scope type payloads Here's a railroad: https://deploy-preview-2295--cursorless.netlify.app/custom-command-railroad ## Checklist - [ ] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [ ] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [ ] I have not broken the cheatsheet
Excited for this to be implemented! My use case is very similar to aforementioned ones. I would like to be able to write a quick+dirty talon command that would accomplish: "post next block this" for purposes of navigating a markdown file. Very random use case but along the lines of the markdown "complete" to check a markdown checkbox. |
Extending custom grammar with actions #492 ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [/] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [/] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com>
Extending custom grammar with actions cursorless-dev/cursorless#492 ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [/] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [/] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com>
Extending custom grammar with actions #492 ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [/] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [/] I have not broken the cheatsheet --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com>
We'd like for users to be able to define more complex custom grammars. To do so, they'll need full access to the types of commands supported by cursorless, whereas today they can just do a single target, with no extra arguments
extraArgs
getText
actionactions.user.cursorless_implicit_target_command
?Proposal
See #492 (comment) below
Old proposal
cursorless_target
that accepts a list of scope ids, followed by an optional target dict. Can accept None as last arg as well and that's equivalent to "this" / omitting mark. If it gets a target it prepends the containing scope modifiers to the target's modifierscursorless_target("every", "collectionItem", "this")
Example
More verbose alternative
Use cases
Checking a box in a markdown checklist
See also #452 and #453
Consider if we want to support extending/overriding other internal cursorless features.
eg support for when focus is not on the text editor. #1717 (comment)
The text was updated successfully, but these errors were encountered: