Skip to content

Commit c22f4d5

Browse files
author
Cedric Halbronn
committed
Cursorless neovim support
1 parent 1abf38d commit c22f4d5

File tree

86 files changed

+5144
-575
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+5144
-575
lines changed

.github/workflows/deploy.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,41 @@ jobs:
4040
registryUrl: https://marketplace.visualstudio.com
4141
extensionFile: ${{ steps.publishToOpenVSX.outputs.vsixPath }}
4242

43+
publish-neovim-extension:
44+
runs-on: ubuntu-latest
45+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
46+
environment: production
47+
env:
48+
CURSORLESS_REPO_ROOT: ${{ github.workspace }}
49+
steps:
50+
- uses: actions/checkout@v4
51+
with:
52+
fetch-depth: 0
53+
token: ${{ secrets.CURSORLESS_BOT_TOKEN }}
54+
- run: corepack enable
55+
- uses: actions/setup-node@v4
56+
with:
57+
node-version-file: .nvmrc
58+
cache: pnpm
59+
- run: pnpm --color install
60+
- run: pnpm --color compile
61+
- run: pnpm --color --filter '!cursorless-org' --filter '!cursorless-org-*' build
62+
env:
63+
CURSORLESS_DEPLOY: true
64+
- name: Configure GPG Key
65+
run: |
66+
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import
67+
env:
68+
GPG_SIGNING_KEY: ${{ secrets.CURSORLESS_BOT_GPG_SIGNING_KEY }}
69+
- name: git config
70+
run: |
71+
git config user.name cursorless-bot
72+
git config user.email [email protected]
73+
git config user.signingkey A9387720AFC62221
74+
git config commit.gpgsign true
75+
- name: Push compiled files to cursorless.nvim plugin repo
76+
run: bash -x scripts/deploy-cursorless-nvim.sh
77+
4378
push-cursorless-talon:
4479
name: Push cursorless-talon subrepo
4580
runs-on: ubuntu-latest

.github/workflows/pre-commit.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ jobs:
2424
node-version-file: .nvmrc
2525
cache: pnpm
2626
- run: pnpm --color install
27+
- uses: leafo/gh-actions-lua@v9
28+
- uses: leafo/gh-actions-luarocks@v4
2729
- uses: pre-commit/[email protected]
2830
- uses: pre-commit-ci/[email protected]
2931
if: always()

.github/workflows/test.yml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,25 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
os: [macos-latest, ubuntu-latest, windows-latest]
19-
vscode_version: [stable]
19+
app_version: [stable]
2020
include:
2121
- os: ubuntu-latest
22-
vscode_version: legacy
22+
app_version: legacy
2323
runs-on: ${{ matrix.os }}
2424
env:
25-
VSCODE_VERSION: ${{ matrix.vscode_version }}
25+
APP_VERSION: ${{ matrix.app_version }}
2626
VSCODE_CRASH_DIR: ${{ github.workspace }}/artifacts/dumps
2727
VSCODE_LOGS_DIR: ${{ github.workspace }}/artifacts/logs
2828
CURSORLESS_REPO_ROOT: ${{ github.workspace }}
29+
TEMP_DIR: ${{ github.workspace }}/temp
2930
steps:
3031
- uses: actions/checkout@v4
3132
- run: corepack enable
3233
- uses: actions/setup-node@v4
3334
with:
3435
node-version-file: .nvmrc
3536
cache: pnpm
36-
- run: mkdir -p "${{ env.VSCODE_CRASH_DIR }}" "${{ env.VSCODE_LOGS_DIR }}"
37+
- run: mkdir -p "${{ env.VSCODE_CRASH_DIR }}" "${{ env.VSCODE_LOGS_DIR }}" "${{ env.TEMP_DIR }}"
3738
shell: bash
3839
- run: pnpm --color install
3940
- run: pnpm --color compile
@@ -42,9 +43,21 @@ jobs:
4243
if: runner.os == 'Linux'
4344
- run: pnpm --color test
4445
if: runner.os != 'Linux'
46+
- run: bash -x scripts/install-neovim-dependencies.sh
47+
- uses: rhysd/action-setup-vim@v1
48+
if: matrix.app_version != 'legacy'
49+
id: vim
50+
with:
51+
version: ${{ matrix.app_version }}
52+
neovim: true
53+
- name: Run neovim unit tests using test-harness
54+
run: xvfb-run -a pnpm -F @cursorless/test-harness testNeovim
55+
if: runner.os == 'Linux' && matrix.app_version == 'stable'
56+
env:
57+
NEOVIM_PATH: ${{ steps.vim.outputs.executable }}
4558
- name: Create vscode dist that can be installed locally
4659
run: pnpm -F @cursorless/cursorless-vscode populate-dist --local-install
47-
if: runner.os == 'Linux' && matrix.vscode_version == 'stable'
60+
if: runner.os == 'Linux' && matrix.app_version == 'stable'
4861
- name: Test create vsix
4962
id: createVsix
5063
uses: HaaLeo/publish-vscode-extension@v1
@@ -53,10 +66,10 @@ jobs:
5366
packagePath: packages/cursorless-vscode/dist
5467
dryRun: true
5568
- run: mv ${{ steps.createVsix.outputs.vsixPath }} cursorless-development.vsix
56-
if: runner.os == 'Linux' && matrix.vscode_version == 'stable'
69+
if: runner.os == 'Linux' && matrix.app_version == 'stable'
5770
- name: Upload vsix
5871
uses: actions/upload-artifact@v4
59-
if: runner.os == 'Linux' && matrix.vscode_version == 'stable'
72+
if: runner.os == 'Linux' && matrix.app_version == 'stable'
6073
with:
6174
name: vsix
6275
path: cursorless-development.vsix

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ node_modules
55
*.vsix
66
/package-lock.json
77
*.DS_Store
8+
.luacheckcache
89

910
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
1011

.luacheckrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
std = luajit
2+
cache = true
3+
codes = true
4+
ignore = { "432" }
5+
6+
globals = {
7+
"vim",
8+
}

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,13 @@ repos:
8181
- id: ruff
8282
args: [--fix, --exit-non-zero-on-fix]
8383
- id: ruff-format
84+
- repo: https://github.com/lunarmodules/luacheck
85+
rev: v1.2.0
86+
hooks:
87+
- id: luacheck
88+
exclude: ^data/playground/lua/.*\.lua$
89+
- repo: https://github.com/JohnnyMorganz/StyLua
90+
rev: v0.20.0
91+
hooks:
92+
- id: stylua
93+
exclude: ^data/playground/lua/.*\.lua$

.vscode/extensions.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"dbaeumer.vscode-eslint",
88
"esbenp.prettier-vscode",
99
"jrieken.vscode-tree-sitter-query",
10-
"wenkokke.tree-sitter-talon",
11-
"usernamehw.commands"
10+
"wenkokke.talonfmt-vscode",
11+
"usernamehw.commands",
12+
"sumneko.lua",
13+
"JohnnyMorganz.stylua"
1214
]
1315
}

.vscode/launch.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
{
66
"version": "0.2.0",
77
"configurations": [
8+
{
9+
"name": "Run neovim extension",
10+
"request": "attach",
11+
"continueOnAttach": true,
12+
"skipFiles": ["<node_internals>/**"],
13+
"preLaunchTask": "Build neovim extension",
14+
"type": "node"
15+
},
16+
{
17+
"name": "Neovim extension tests",
18+
"request": "attach",
19+
"continueOnAttach": true,
20+
"skipFiles": ["<node_internals>/**"],
21+
"preLaunchTask": "Build neovim extension tests",
22+
"type": "node"
23+
},
824
{
925
"name": "Run extension",
1026
"type": "extensionHost",

.vscode/settings.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"editor.defaultFormatter": "AndreasArvidsson.andreas-talon"
88
},
99
"[talon]": {
10-
"editor.defaultFormatter": "wenkokke.tree-sitter-talon"
10+
"editor.defaultFormatter": "wenkokke.talonfmt-vscode"
1111
},
1212
"editor.defaultFormatter": "esbenp.prettier-vscode",
1313
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
@@ -25,5 +25,10 @@
2525
"files.eol": "\n",
2626
"typescript.enablePromptUseWorkspaceTsdk": true,
2727
"typescript.tsdk": "node_modules/typescript/lib",
28-
"eslint.workingDirectories": [{ "pattern": "packages/*/" }]
28+
"eslint.workingDirectories": [{ "pattern": "packages/*/" }],
29+
"Lua.runtime.version": "Lua 5.1",
30+
"Lua.diagnostics.globals": ["vim", "talon"],
31+
"[lua]": {
32+
"editor.defaultFormatter": "JohnnyMorganz.stylua"
33+
}
2934
}

.vscode/tasks.json

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,86 @@
1616
"isDefault": true
1717
}
1818
},
19+
{
20+
"label": "Build neovim extension",
21+
"dependsOn": ["neovim start", "ESBuild-cursorless-neovim"],
22+
"group": "build"
23+
},
24+
{
25+
"label": "Build neovim extension tests",
26+
"dependsOn": [
27+
"neovim test start",
28+
"ESBuild-cursorless-neovim",
29+
"TSBuild",
30+
"Build test harness"
31+
],
32+
"group": "build"
33+
},
34+
{
35+
"label": "ESBuild-cursorless-neovim",
36+
"type": "npm",
37+
"script": "compile",
38+
"path": "packages/cursorless-neovim",
39+
"dependsOn": [],
40+
"presentation": {
41+
"reveal": "silent"
42+
},
43+
"group": "build"
44+
},
45+
{
46+
"label": "neovim start",
47+
"type": "process",
48+
"windows": {
49+
"command": "powershell",
50+
"args": [
51+
"(New-Object -ComObject WScript.Shell).Run(\"\"\"nvim\"\"\", 1, $false)"
52+
]
53+
},
54+
"osx": {
55+
"command": "osascript",
56+
"args": [
57+
"-e",
58+
"tell app \"Terminal\" to do script \"${workspaceFolder}/packages/cursorless-neovim/scripts/debug-neovim.sh ${workspaceFolder} development\""
59+
]
60+
},
61+
"group": "build",
62+
"options": {
63+
"env": {
64+
"CURSORLESS_REPO_ROOT": "${workspaceFolder}",
65+
"NVIM_NODE_HOST_DEBUG": "1",
66+
"NVIM_NODE_LOG_FILE": "${workspaceFolder}/packages/cursorless-neovim/out/nvim_node.log",
67+
"NVIM_NODE_LOG_LEVEL": "info",
68+
"CURSORLESS_MODE": "development"
69+
}
70+
}
71+
},
72+
{
73+
"label": "neovim test start",
74+
"type": "process",
75+
"windows": {
76+
"command": "powershell",
77+
"args": [
78+
"(New-Object -ComObject WScript.Shell).Run(\"\"\"nvim\"\"\", 1, $false)"
79+
]
80+
},
81+
"osx": {
82+
"command": "osascript",
83+
"args": [
84+
"-e",
85+
"tell app \"Terminal\" to do script \"${workspaceFolder}/packages/cursorless-neovim/scripts/debug-neovim.sh ${workspaceFolder} test\""
86+
]
87+
},
88+
"group": "build",
89+
"options": {
90+
"env": {
91+
"CURSORLESS_REPO_ROOT": "${workspaceFolder}",
92+
"NVIM_NODE_HOST_DEBUG": "1",
93+
"NVIM_NODE_LOG_FILE": "${workspaceFolder}/packages/cursorless-neovim/out/nvim_node.log",
94+
"NVIM_NODE_LOG_LEVEL": "info",
95+
"CURSORLESS_MODE": "test"
96+
}
97+
}
98+
},
1999
{
20100
"label": "Build extension only",
21101
"dependsOn": ["Populate dist", "ESBuild"],

cursorless.nvim/README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<!-- vim-markdown-toc GFM -->
2+
3+
- [cursorless.nvim](#cursorlessnvim)
4+
- [Prerequisites](#prerequisites)
5+
- [Installation](#installation)
6+
- [Configuration](#configuration)
7+
- [Frequently asked questions](#frequently-asked-questions)
8+
- [Contributors](#contributors)
9+
10+
<!-- vim-markdown-toc -->
11+
12+
# cursorless.nvim
13+
14+
Neovim plugin to support Cursorless
15+
16+
## Prerequisites
17+
18+
- [neovim](https://neovim.io/.) Tested with neovim version `v0.10.0` and above, but it may work with earlier versions.
19+
- [Talon voice](https://talonvoice.com/)
20+
- [neovim-talon](https://github.com/hands-free-vim/neovim-talon)
21+
- [node/npm](https://nodejs.org/en)
22+
- [neovim node package](https://github.com/neovim/node-client) (>= 5.1.0 installed globally)
23+
- [talon.nvim](https://github.com/hands-free-vim/talon.nvim) (likely required, unless standalone neovim
24+
GUI (nvim-qt.exe, neovide, etc)
25+
26+
## Installation
27+
28+
### 1. Install Cursorless neovim plugin
29+
30+
Ideally, you want to use a neovim plugin manager like [lazy.nvim](https://github.com/folke/lazy.nvim).
31+
32+
#### Option A: Lazy installation
33+
34+
After the typical [lazy setup](https://github.com/folke/lazy.nvim?tab=readme-ov-file#-installation), you'll have to add the `cursorless.nvim` plugin to your `init.lua`.
35+
36+
```lua
37+
require('lazy').setup({
38+
'hands-free-vim/cursorless.nvim',
39+
})
40+
```
41+
42+
#### Option B: Manual installation
43+
44+
This method is not recommended but you can try directly cloning the plugin into your nvim data folder:
45+
46+
```
47+
git clone https://github.com/hands-free-vim/cursorless.nvim
48+
```
49+
50+
### 2. Tell neovim to run the plugin
51+
52+
If you aren't using a plugin manager that automatically calls setup for you (e.g. it is needed for lazy), you will need this somewhere in your neovim config, e.g. in [init.lua](https://neovim.io/doc/user/lua-guide.html#lua-guide-config):
53+
54+
```lua
55+
require("cursorless").setup()
56+
```
57+
58+
### 3. Activate Cursorless commands in Talon
59+
60+
Add a `.talon` file like the following anywhere in your Talon user directory (e.g. named `cursorless_neovim.talon`):
61+
62+
```talon
63+
app: neovim
64+
-
65+
tag(): user.cursorless
66+
```
67+
68+
## Configuration
69+
70+
### Keyboard shortcut
71+
72+
By default the keyboard shortcut used to communicate with cursorless is `<C-S-f12>`, but this might not work for
73+
everybody and is configurable. You can change it by passing a different value in the configuration options passed to
74+
`setup()`:
75+
76+
```lua
77+
require("cursorless").setup({ shortcut = `<C-Q>`})
78+
```
79+
80+
_IMPORTANT_: If you change this shortcut, be sure to set the corresponding neovim-talon setting. This can be done by
81+
having a `.talon` file somewhere in your talon user directory that contains the following:
82+
83+
```talon
84+
settings():
85+
user.neovim_command_server_shortcut = "ctrl-q"
86+
```
87+
88+
### Absolute row numbers
89+
90+
You MUST currently use absolute row numbers in order to target rows using cursorless. The `talon.nvim` plugin will
91+
configure this automatically, but your own config may be overriding it. Be sure to disable relative numbers.
92+
93+
## Frequently asked questions
94+
95+
### nvim does not support Lazy?
96+
97+
Some Linux package managers ship with a version of `nvim` too old for Lazy. If this is the case, [install nvim](https://github.com/neovim/neovim/blob/master/INSTALL.md) via another method.
98+
99+
### nvim does not find the `neovim` globally installed package?
100+
101+
If you are on Linux, avoid using the snap package for `npm` as it may not be able to globally expose the neovim npm package due to sandboxing. If this is the case, install node via another method (nvm, brew, etc).
102+
103+
## Contributors
104+
105+
Welcome! So glad you've decided to help make Cursorless in Neovim better. You'll want to start by getting [set up](https://github.com/saidelike/cursorless/blob/nvim-talon/docs/contributing/cursorless-in-neovim.md). You may also find the [Neovim API docs](https://neovim.io/doc/user/api.html) helpful to learn about Neovim extension development.

0 commit comments

Comments
 (0)