Skip to content

Commit

Permalink
add already packaged cursorless.nvim to speed up things in CI for now
Browse files Browse the repository at this point in the history
  • Loading branch information
Cedric Halbronn committed May 16, 2024
1 parent f0e4128 commit e28d2f2
Show file tree
Hide file tree
Showing 14 changed files with 78,884 additions and 0 deletions.
91 changes: 91 additions & 0 deletions dist/cursorless.nvim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!-- vim-markdown-toc GFM -->

- [cursorless.nvim](#cursorlessnvim)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Lazy installation](#lazy-installation)
- [Manual installation](#manual-installation)
- [Configuration](#configuration)
- [neovim configuration](#neovim-configuration)
- [Talon configuration](#talon-configuration)
- [Frequently asked questions](#frequently-asked-questions)
- [nvim does not support Lazy?](#nvim-does-not-support-lazy)
- [nvim does not find the `neovim` globally installed package?](#nvim-does-not-find-the-neovim-globally-installed-package)
- [Contributors](#contributors)

<!-- vim-markdown-toc -->

# cursorless.nvim

Neovim plugin to support Cursorless

## Prerequisites

- neovim: https://neovim.io/
- Talon voice: https://talonvoice.com/
- neovim-talon: https://github.com/hands-free-vim/neovim-talon
- node/npm: https://nodejs.org/en
- neovim node package: https://github.com/neovim/node-client (globally installed with `npm`)
- talon.nvim: https://github.com/hands-free-vim/talon.nvim (optional but recommended)

## Installation

Ideally, you want to use a neovim plugin manager like [lazy.nvim](https://github.com/folke/lazy.nvim).

### Lazy installation

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`.

```lua
require('lazy').setup({
'hands-free-vim/cursorless.nvim',
})
```

### Manual installation

This method is not recommended but you can try directly cloning the plugin into your nvim data folder:

```
git clone https://github.com/hands-free-vim/cursorless.nvim
```

## Configuration

### neovim configuration

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):

```lua
require("cursorless").setup()
```

### Talon configuration

Add a `.talon` file like the following anywhere in your Talon user directory (e.g. named `cursorless_neovim.talon`):

```talon
app: neovim
-
tag(): user.cursorless
```

## Frequently asked questions

### nvim does not support Lazy?

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.

### nvim does not find the `neovim` globally installed package?

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).

## Contributors

You will need to add the `vim-scripts/BufOnly.vim` neovim plugin if you want to be able to run the tests. For instance, with lazy:

```lua
require('lazy').setup({
'vim-scripts/BufOnly.vim'
})
```
Empty file.
140 changes: 140 additions & 0 deletions dist/cursorless.nvim/lua/cursorless/cursorless.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
local M = {}

-- Get the first and last visible line of the current window/buffer
-- @see https://vi.stackexchange.com/questions/28471/get-first-and-last-visible-line-from-other-buffer-than-current
-- w0/w$ are indexed from 1, similarly to what is shown in neovim
-- e.g. :lua print(dump_table(require('talon.cursorless').window_get_visible_lines()))"
-- window_get_visible_lines
-- { [1] = 28, [2] = 74 }
function M.window_get_visible_lines()
-- print('window_get_visible_lines()')
return { vim.fn.line('w0'), vim.fn.line('w$') }
end

-- https://www.reddit.com/r/neovim/comments/p4u4zy/how_to_pass_visual_selection_range_to_lua_function/
-- https://neovim.io/doc/user/api.html#nvim_win_get_cursor()
--
-- luacheck:ignore 631
-- e.g. run in command mode :vmap <c-a> <Cmd>lua print(vim.inspect(require('talon.cursorless').buffer_get_selection()))<Cr>
-- then go in visual mode with "v" and select "hello" on the first line and continue selection with "air"
-- on the second line.
-- Then hit ctrl+b and it will show the selection
-- cline=2, ccol=2, vline=1, vcol=1
-- sline=1, scol=1, eline=2, ecol=3, reverse=false
-- { 1, 1, 2, 3, false }
--
-- if instead you select from the end of the "air" word on the second line
-- and select up to the beginning of "hello" on the first line
-- cline=1, ccol=0, vline=3, vcol=3
-- sline=1, scol=1, eline=2, ecol=3, reverse=true
-- { 1, 1, 2, 3, true }
--
-- if you want to directly see how it is parsed in the node extension, you can use the below:
-- e.g. run in command mode :vmap <c-a> <Cmd>:call CursorlessLoadExtension()<Cr>
-- and again use ctrl+a after selecting the text
function M.buffer_get_selection()
-- print('buffer_get_selection()')
local modeInfo = vim.api.nvim_get_mode()
local mode = modeInfo.mode

local cursor = vim.api.nvim_win_get_cursor(0)
local cline, ccol = cursor[1], cursor[2]
local vline, vcol = vim.fn.line('v'), vim.fn.col('v')
-- print(('cline=%d, ccol=%d, vline=%d, vcol=%d'):format(cline, ccol, vcol, vcol))

local sline, scol
local eline, ecol
local reverse
if cline == vline then
-- if ccol <= vcol then
if ccol < vcol then
sline, scol = cline, ccol
eline, ecol = vline, vcol
scol = scol + 1
reverse = true
else
sline, scol = vline, vcol
eline, ecol = cline, ccol
ecol = ecol + 1
reverse = false
end
elseif cline < vline then
sline, scol = cline, ccol
eline, ecol = vline, vcol
scol = scol + 1
reverse = true
else
sline, scol = vline, vcol
eline, ecol = cline, ccol
ecol = ecol + 1
reverse = false
end

if mode == 'V' or mode == 'CTRL-V' or mode == '\22' then
scol = 1
ecol = nil
end

-- print(
-- ('sline=%d, scol=%d, eline=%d, ecol=%d, reverse=%s'):format(
-- sline,
-- scol,
-- eline,
-- ecol,
-- tostring(reverse)
-- )
-- )
return { sline, scol, eline, ecol, reverse }
end

-- https://www.reddit.com/r/neovim/comments/p4u4zy/how_to_pass_visual_selection_range_to_lua_function/
-- luacheck:ignore 631
-- e.g. run in command mode :vmap <c-b> <Cmd>lua print(vim.inspect(require('talon.cursorless').buffer_get_selection_text()))<Cr>
-- then go in visual mode with "v" and select "hello" on the first line and continue selection with "air"
-- on the second line.
-- Then hit ctrl+b and it will show the selection
-- { "hello", "air" }
function M.buffer_get_selection_text()
-- print('buffer_get_selection_text()')
local sline, scol, eline, ecol, _ = unpack(require('talon.cursorless').buffer_get_selection())

local lines = vim.api.nvim_buf_get_lines(0, sline - 1, eline, 0)
if #lines == 0 then
return
end

local startText, endText
if #lines == 1 then
startText = string.sub(lines[1], scol, ecol)
else
startText = string.sub(lines[1], scol)
endText = string.sub(lines[#lines], 1, ecol)
end

local selection = { startText }
if #lines > 2 then
vim.list_extend(selection, vim.list_slice(lines, 2, #lines - 1))
end
table.insert(selection, endText)

return selection
end

-- https://github.com/nvim-treesitter/nvim-treesitter/blob/master/lua/nvim-treesitter/ts_utils.lua#L278
-- luacheck:ignore 631
-- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/blob/master/lua/nvim-treesitter/textobjects/select.lua#L114
-- as an example if you put that in a vim buffer and do the following you can do a selection:
-- :w c:\work\tmp\test.lua
-- :so %
-- :lua select_range(5, 12, 5, 30)
-- for example it will highlight the last function name (nvim_win_set_cursor).
-- another example is :tmap <c-b> <Cmd>lua require("talon.cursorless").select_range(4, 0, 4, 38)<Cr>
-- NOTE: works for any mode (n,i,v,nt) except in t mode
function M.select_range(start_x, start_y, end_x, end_y)
vim.cmd([[normal! :noh]])
vim.api.nvim_win_set_cursor(0, { start_x, start_y })
vim.cmd([[normal v]])
vim.api.nvim_win_set_cursor(0, { end_x, end_y })
end

return M
85 changes: 85 additions & 0 deletions dist/cursorless.nvim/lua/cursorless/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
local function register_functions()
local path = require('cursorless.utils').cursorless_nvim_path()
-- revert to using forward slashes as works when passed to remote#host#RegisterPlugin()
if require('cursorless.utils').is_win() then
path = path:gsub('\\', '/')
end
vim.api.nvim_call_function('RegisterFunctions', { path })
end

-- this triggers loading the node process as well as calling one function
-- in the cursorless-neovim, command-server and neovim-registry extensions
-- in order to initialize them
local function load_extensions()
vim.api.nvim_call_function('CursorlessLoadExtension', {})
vim.api.nvim_call_function('CommandServerLoadExtension', {})

-- if os.getenv('CURSORLESS_MODE') == 'test' then
-- -- make sure cursorless is loaded before starting the tests
-- -- see https://neovim.io/doc/user/various.html#%3Asleep
-- vim.cmd([[sleep 1]])
-- vim.api.nvim_call_function('TestHarnessRun', {})
-- end
end

-- Cursorless command-server shortcut: CTRL+q
-- https://stackoverflow.com/questions/40504408/can-i-map-a-key-binding-to-a-function-in-vimrc
-- https://stackoverflow.com/questions/7642746/is-there-any-way-to-view-the-currently-mapped-keys-in-vim
-- luacheck:ignore 631
-- https://stackoverflow.com/questions/3776117/what-is-the-difference-between-the-remap-noremap-nnoremap-and-vnoremap-mapping
local function configure_command_server_shortcut()
-- these mappings don't change the current mode
-- https://neovim.io/doc/user/api.html#nvim_set_keymap()
-- https://www.reddit.com/r/neovim/comments/pt92qn/mapping_cd_in_terminal_mode/
vim.api.nvim_set_keymap(
'i',
'<C-S-F12>',
'<cmd>lua vim.fn.CommandServerRunCommand()<CR>',
{ noremap = true }
)
vim.api.nvim_set_keymap(
'n',
'<C-S-F12>',
'<cmd>lua vim.fn.CommandServerRunCommand()<CR>',
{ noremap = true }
)
vim.api.nvim_set_keymap(
'c',
'<C-S-F12>',
'<cmd>lua vim.fn.CommandServerRunCommand()<CR>',
{ noremap = true }
)
vim.api.nvim_set_keymap(
'v',
'<C-S-F12>',
'<cmd>lua vim.fn.CommandServerRunCommand()<CR>',
{ noremap = true }
)
vim.api.nvim_set_keymap(
't',
'<C-S-F12>',
'<cmd>lua vim.fn.CommandServerRunCommand()<CR>',
{ noremap = true }
)
end

local function setup()
vim.cmd('source ' .. require('cursorless.utils').cursorless_nvim_path() .. '/vim/cursorless.vim')
register_functions()
load_extensions()
configure_command_server_shortcut()

-- if os.getenv('CURSORLESS_MODE') == 'test' then
-- -- make sure cursorless is loaded before starting the tests
-- -- see https://neovim.io/doc/user/various.html#%3Asleep
-- vim.cmd([[sleep 1]])
-- vim.api.nvim_call_function('TestHarnessRun', {})
-- end
-- print("TestHarnessRun() done")
end

local M = {
setup = setup,
}

return M
64 changes: 64 additions & 0 deletions dist/cursorless.nvim/lua/cursorless/utils.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
local M = {}

-- :lua print(require('cursorless.utils').is_win())
function M.is_win()
return package.config:sub(1, 1) == '\\'
end

-- :lua print(require('cursorless.utils').get_path_separator())
function M.get_path_separator()
if require('cursorless.utils').is_win() then
return '\\'
end
return '/'
end

-- https://www.reddit.com/r/neovim/comments/tk1hby/get_the_path_to_the_current_lua_script_in_neovim/
-- https://pgl.yoyo.org/luai/i/debug.getinfo
-- https://www.gammon.com.au/scripts/doc.php?lua=debug.getinfo
-- e.g. :lua print(require('cursorless.utils').cursorless_nvim_path())
-- outputs: C:\Users\User\AppData\Local\nvim-data\lazy\talon.nvim
-- NOTE: Development cursorless-neovim is installed in: C:\Users\User\AppData\Local\nvim\rplugin\node\cursorless-neovim
function M.cursorless_nvim_path()
--source_file=@C:/Users/User/AppData/Local/nvim-data/lazy/talon.nvim/lua/talon/utils.lua
local str = debug.getinfo(1, 'S').source
-- print(('source_file=%s'):format(str))
-- skip as the file name is prefixed by "@"
str = str:sub(2)
-- print(('source_file2=%s'):format(str))
if require('cursorless.utils').is_win() then
str = str:gsub('/', '\\')
-- print('is_win')
end
-- print(('source_file3=%s'):format(str))
-- remove where our current file is located to get talon.nvim base path
str = str:sub(0, -1 - #'lua/cursorless/utils.lua')
-- print(('talon.nvim=%s'):format(str))
return str
end

-- assumes we are in terminal mode and switch to normal terminal mode
-- https://www.reddit.com/r/neovim/comments/uk3xmq/change_mode_in_lua/
-- https://neovim.io/doc/user/api.html#nvim_feedkeys()
-- https://neovim.io/doc/user/builtin.html#feedkeys()
-- https://neovim.io/doc/user/api.html#nvim_replace_termcodes()
-- e.g. run in command mode :tmap <c-a> <Cmd>lua mode_switch_nt()<Cr>
function M.mode_switch_nt()
local key = vim.api.nvim_replace_termcodes('<c-\\><c-n>', true, false, true)
vim.api.nvim_feedkeys(key, 'n', false)
end

-- assumes we are in normal terminal mode and switch to terminal mode
-- e.g. run in command mode :nmap <c-b> <Cmd>lua mode_switch_t()<Cr>
function M.mode_switch_t()
vim.api.nvim_feedkeys('i', 'n', true)
end

-- paste what is in the clipboard
-- https://www.baeldung.com/linux/vim-paste-text
-- e.g. run in command mode :imap <c-b> <Cmd>lua require('cursorless.utils').paste()<Cr>
function M.paste()
vim.cmd([[normal! "+p]])
end

return M
Loading

0 comments on commit e28d2f2

Please sign in to comment.