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

Add docs for adding a new language #187

Merged
merged 6 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ yarn run test

See [test-case-recorder.md](docs/test-case-recorder.md).

### Adding new programming languages / syntactic scopes
### Adding a new programming language

See [docs](docs/adding-a-new-language.md).

### Adding syntactic scope types to an existing language

See [parse-tree-patterns.md](docs/parse-tree-patterns.md).

Expand Down
34 changes: 34 additions & 0 deletions docs/adding-a-new-language.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Adding a new programming language

So you want cursorless to support a new language? Great! Here's how to do it:

## 1. Add support to the [vscode-parse-tree](https://github.com/pokey/vscode-parse-tree) extension

Cursorless relies on the vscode-parse-tree extension to access the parse tree
of a document. See the
[docs](https://github.com/pokey/vscode-parse-tree/#adding-a-new-language) there
for how to add support for a new parser

## 2. Define parse tree patterns in Cursorless

The parse trees exposed by tree-sitter are often pretty close to what we're
looking for, but we often need to look for specific patterns within the parse
tree to get the scopes that the user expects. Fortunately, we have a
domain-specific language that makes these definitions fairly compact.

- Check out the [docs](parse-tree-patterns.md) for the syntax tree pattern
matcher
- You may also find it helpful to look at an existing language, such as
[java](../src/languages/java.ts).
- If you look in the debug console, you'll see debug output every time you move
your cursor, which might be helpful.
- You will likely want to look at `node-types.json` for your language, (eg [java](https://github.com/tree-sitter/tree-sitter-java/blob/master/src/node-types.json)). This file is generated from `grammar.js`, which might also be helpful to look at (eg [java](https://github.com/tree-sitter/tree-sitter-java/blob/master/grammar.js)).

## 3. Write tests

Test cases can be automatically recorded, which should speed things up a lot.
See the [docs](test-case-recorder.md) for the test case recorder. It will also
likely be helpful to look at the existing recorded test cases (eg
[java](../src/test/suite/fixtures/recorded/languages/java)) to see how
they
should end up looking when they're recorded.
51 changes: 36 additions & 15 deletions docs/test-case-recorder.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
# Test case recorder

## Record new tests
1. Add voice command
- `cursorless record: user.vscode("cursorless.recordTestCase")`
- We don't want to commit this so add it to your own repository.
We use an automated test case recorder to generate test cases. To use it, you
set up a file the way you'd like (usually a minimal file containing something
like `hello world`), positioning your cursor where you want, tell cursorless to
start recording, and then issue one or more cursorless commands. It works by
recording the initial state of the file including cursor position(s), the
command run, and the final state, all in the form of a yaml document. See
[existing test cases](../src/test/suite/fixtures/recorded) for example outputs.

## Initial setup

1. Add a voice command for recording to your personal talon files:
- `cursorless record: user.vscode("cursorless.recordTestCase")`
- We don't want to commit this so add it to your own repository.

## Recording new tests

1. Start debugging (F5)
1. `"cursorless record"`
- List of target directories is shown
1. Create a minimal file to use for recording tests. And position your cursor
where you'd like. Check out the `initialState.documentContents` field of
[existing test cases](../src/test/suite/fixtures/recorded) for examples.
1. Issue the `"cursorless record"` command
- List of target directories is shown. All test cases will be put into the
given subdirectory of `src/test/suite/fixtures/recorded`
1. Select existing directory or create new one
- Select `Create new folder`
- Use `/` to create subdirectories.
- Select `Create new folder`
- If the new directory name contains any `/`, it will create nested
subdirectories.
1. `Recording test cases for following commands` is shown
1. Issue any cursorless voice command
- `"take air"`
- `"take air"`
1. `Cursorless test case saved` is shown
- File created on disk using spoken words as file name
1. Repeat as many voice commands as you want recorded
1. `"cursorless record"`
- `Stopped recording test cases` is shown
- You can also just stop the debugger or close the debug window
- File created on disk using spoken words as file name
1. Repeat as many cursorless voice commands as you want recorded. Each command
you
issue will generate a test case in the form of a yaml file.
1. Issue `"cursorless record"` command again to stop recording
- `Stopped recording test cases` is shown
- You can also just stop the debugger or close the debug window

## Run recorded tests
Recorded tests are run with the normal test and can be run in vscode or via yarn in terminal.

Recorded tests will automatically be picked up and run with the normal tests,
and can be run in vscode or via yarn in terminal.