Giter Club home page Giter Club logo

otter.nvim's Introduction

otter.nvim

Just ask an otter! 🦦

What is otter.nvim?

tldr: Otter.nvim provides lsp features and a code completion source for code embedded in other documents

Demo

demo.mp4

When implementing autocompletion, code diagnostics and the likes for quarto-nvim I realized that a core feature would be useful to other plugins and usecases as well. quarto documents are computational notebooks for scientific communication based on pandocs markdown. One key feature is that these qmd documents can contain exectuable code blocks, with possibly different languages such as R and python mixed in one document.

How do we get all the cool language features we get for a pure e.g. python file -- like code completion, documentation hover windows, diagnostics -- when the code is just embedded as code blocks in a document? Well, if one document can't give us the answer, we ask an otter (another)! otter.nvim creates and synchronizes hidden buffers containing a single language each and directs requests for completion and lsp requests from the main buffer to those other buffers (otter buffers).

Example in a markdown (or quarto markdown) document index.md:

# Some markdown
Hello world

```python
import numpy as np
np.zeros(10)
```

We create a hidden buffer for a file index.md.tmp.py

 
 
 
 
import numpy as np
np.zeros(10)

This contains just the python code and blank lines for all other lines (this keeps line numbers the same, which comes straight from the trick that the quarto dev team uses for the vs code extension as well). Language servers can then attach to this hidden buffer. We can do this for all embedded languages found in a document.

A group of otters is called a raft

Each otter-activated buffer can maintain a set of other buffers synchronized to the main buffer.

In other words, each buffer can have a raft of otters!

otter.nvim contains a completion source for nvim-cmp. When a completion request is made, the whole raft of otters is synchronized and the question is directed to the otters. The accumulated answers are then displayed in the main buffer.

stateDiagram-v2
    Main --> 🦦1
    Main --> 🦦2
    Main --> 🦦3
    🦦1 --> response
    🦦2 --> response
    🦦3 --> response
    response --> Main: filter

How do I use otter.nvim?

The easiest way to get started is try it out in quarto-nvim or look at the usecases there. Specifically, you'll want to look at the lua/plugins/quarto.lua file in the quarto-nvim-kickstarter configuration.

In short:

Configure otter

If you want to use the default config below you don't need to call setup.

local otter = require'otter'
otter.setup{
  lsp = {
    hover = {
      border = { "", "", "", "", "", "", "", "" },
    },
    -- `:h events` that cause the diagnostics to update. Set to:
    -- { "BufWritePost", "InsertLeave", "TextChanged" } for less performant
    -- but more instant diagnostic updates
    diagnostic_update_events = { "BufWritePost" },
  },
  buffers = {
    -- if set to true, the filetype of the otterbuffers will be set.
    -- otherwise only the autocommand of lspconfig that attaches
    -- the language server will be executed without setting the filetype
    set_filetype = false,
    -- write <path>.otter.<embedded language extension> files
    -- to disk on save of main buffer.
    -- usefule for some linters that require actual files
    -- otter files are deleted on quit or main buffer close
    write_to_disk = false,
  },
  strip_wrapping_quote_characters = { "'", '"', "`" },
  -- Otter may not work the way you expect when entire code blocks are indented (eg. in Org files)
  -- When true, otter handles these cases fully. This is a (minor) performance hit
  handle_leading_whitespace = false,
}

Configure autocompletion

Apart from its own functions, otter.nvim comes with a completion source for nvim-cmp for the embedded code. Use it as follows:

local cmp = require'cmp'
cmp.setup({
    -- <rest of your nvim-cmp config>
    sources = {
        { name = "otter" },
        -- <other sources>
    },
})

Activate otter

Activate otter for the current document with

-- table of embedded languages to look for.
-- default = nil, which will activate
-- any embedded languages found
local languages = {'python', 'lua' }

-- enable completion/diagnostics
-- defaults are true
local completion = true
local diagnostics = true
-- treesitter query to look for embedded languages
-- uses injections if nil or not set
local tsquery = nil

otter.activate(languages, completion, diagnostics, tsquery)

Use otter

Assuming otter.nvim is configured and added to nvim-cmp as a completion source, call require'otter'.activate({'python', 'r', <more languages you want to embed> }) on any buffer that has injections (see :h treesitter-language-injections) defined and you will see code completion and diagnostics (on save).

Then use the otter.ask_... functions to e.g. ask for hover documentation, references or the definition.

otter.ask_ functions fall back to regular lsp requests on the main buffer when not in an otter context. Alternatively, you can pass a custom fallback to use instead of the default lsp request. Currently implemented functions are:

otter.ask_definition()
otter.ask_type_definition()
otter.ask_hover()
otter.ask_references()
otter.ask_document_symbols()
otter.ask_rename()
otter.ask_format()

Additional functions:

-- Export the raft of otters as files.
-- Asks for filename for each language.
otter.export()
otter.export_otter_as()

Dependencies

otter.nvim requires the following plugins:

{
  'hrsh7th/nvim-cmp', -- optional, for completion
  'neovim/nvim-lspconfig',
  'nvim-treesitter/nvim-treesitter'
}

An otter eagerly awaiting your lsp requests.

otter.nvim's People

Contributors

0fflineuser avatar atusy avatar benlubas avatar faldor20 avatar georgeguimaraes avatar github-actions[bot] avatar jmbuhr avatar mesa123123 avatar rational-curiosity avatar rollincuberawhide avatar yongrenjie avatar zyriab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

otter.nvim's Issues

would it be possible to edit the 'otter'-buffer with the excellent nvim-R- package, so that interactive changes could be saved back to the code chunks

Hi so this is above my skill level to implement my self, but what I really mis about Sublime Text is that I had a plugin that could just send lines of codes to tmux. This meant that I would interatively edit code chunks in a quarto document, because it didn't what type of file it was.

Now I'm using nvim-R for my R scripts, which is completely amazing. But it does not work in code chunks in a quarto document, so I have to copy back and forth when polising something.

So I was thinking if it is possible to edit the hidden buffer, which I guess is an R file type, so that I would edit that with nvim-R and a terminal, and then changes saved would go back to the code chunks?

As you can hear, I do not have much knowledge about what's going on under the hood. But I'm hoping it would be possible?

Add a deactivate method?

There's otter.activate. sometimes I just want to turn otter off for the current buffer.

Is there a way to deactivate it for the current buffer? This should also remove diagnostics.

Happy to contribute this of course.

`get_language_lines_in_visual_selection` off by one

if I have a code block like this:

```{python}
print("Hello")
x = 10
...

and call otterkeeper.get_language_lines_in_visual_selection(true) with the first line visually selected (visual or visual line mode) I get nil.

So I think there is an off by one somewhere

FR: expose API for diagnostics refreshing / Bug: Diagnostics not update via `vim.cmd.write` etc

The FR part:
Right now, the diagnostics only update on write. As far as I can tell, via the BufWritePost autocmd. When you are not in the habit of constantly saving, it is somewhat annoying often only show up much later.


The bug (?) part:
I tried to fix that via this autocmd, which for some reason saves the file but does not trigger the refreshing of diagnostics. Only manually typing :w seems to work 🤔

vim.api.nvim_create_autocmd("FileType", {
	pattern = "markdown",
	callback = function(ctx)
		vim.api.nvim_create_autocmd("InsertLeave", {
			buffer = ctx.buf,
			callback = function() vim.cmd.write() end,
		})
	end,
})

[bug] ask_format() eats a line

When formatting code in a markdown cell with the Lua language server like:

```lua
print( "this should be formatted")
```

The result is:

```lua
print("this should be formatted")

I also see this in norg files where the @end that delimits the end of a code cell is removed.

Completion does not work, even on a minimal configuration

First, thanks for the awesome plugin - both otter.nvim and quarto-nvim! Really love the idea and how it works, but I'm having issues with getting the completion to work. I've spent more time troubleshooting now than I care to admit, and I cannot for the life of me get it to work. Completion in other filetypes (e.g. R, Python, R Markdown) works just fine, it's just Quarto that doesn't work.

Both plugins (quarto-nvim and otter.nvim) load just fine, I get syntax highlighting from Treesitter and I can correctly see active but not attached LSP clients when I look at LspInfo. I can move to the otter-buffers, within which completion works just fine - the sources are just the normal ones, though, and not otter sources (which I assume is correct in these buffers). There's just no connection between Otter and nvim.cmp, even though I've checked that I'm using all the correct configurations for all the related plugins (following your documentation). LSP-related things like goto-definition still works inside Quarto files, though.

Thinking that it was probably something weird I have in my config I setup a minimal configuration with just nvim.cmp, nvim.lspconfig, nvim-treesitter, quarto-nvim and otter.nvim, but it still doesn't work. The config is here: https://github.com/fasterius/nvim-otter-minimal.

I'm probably missing something stupid, but I can't for the life of me figure out what. Any ideas?

Diagnostics don't show up right away

When calling otter.activate(...) with something like this:

```python
print("hi
```

Will not immediately show diagnostics. You first have to write the file.

attempt to call method '_rawquery' (a nil value)

When I open a markdown file, whether or not it has fenced blocks, I'm getting an exception:

Error detected while processing BufEnter Autocommands for "*.md":                                                                                                                                                           
Error executing lua callback: .../lazy/otter.nvim/lua/otter/tools/treesitter_iterator.lua:8: attempt to call method '_rawquery' (a nil value)                                                                               
stack traceback:                                                                                                                                                                                                            
        .../lazy/otter.nvim/lua/otter/tools/treesitter_iterator.lua:8: in function 'iter_captures'                                                                                                                          
        ...b/.local/share/nvim/lazy/otter.nvim/lua/otter/keeper.lua:54: in function 'extract_code_chunks'                                                                                                                   
        ...lib/.local/share/nvim/lazy/otter.nvim/lua/otter/init.lua:69: in function 'activate'                                                                                                                              
        /Users/llimllib/.config/nvim/lua/config_otter.lua:19: in function </Users/llimllib/.config/nvim/lua/config_otter.lua:18> 

I recently updated to neovim 0.10.0, which I'm not sure is relevant or not. I ran :TSUpdate to update all my treesitter grammars when I did.

line 19 of my config is otter.activate in this block:

vim.api.nvim_create_autocmd({ "BufEnter" }, {
	pattern = { "*.md" },
	callback = function()
		otter.activate({ "javascript", "typescript", "js", "ts" }, true, true)
		vim.api.nvim_buf_set_keymap(0, "n", "gd", ":lua require'otter'.ask_definition()<cr>", { silent = true })
		vim.api.nvim_buf_set_keymap(0, "n", "K", ":lua require'otter'.ask_hover()<cr>", { silent = true })
	end,
})

line 54 of keeper.lua is the last line of this block:

M.extract_code_chunks = function(main_nr, lang, exclude_eval_false, row_from, row_to)
  local query = M._otters_attached[main_nr].query
  local parser = M._otters_attached[main_nr].parser
  local tree = parser:parse()
  local root = tree[1]:root()

  local code_chunks = {}
  local lang_capture = nil
  for id, node, metadata in treesitter_iterator.iter_captures(root, main_nr, query) do

the first 8 lines of treesitter_iterator.lua are:

M = {}

M.iter_captures = function (node, source, query)
  if type(source) == "number" and source == 0 then
    source = vim.api.nvim_get_current_buf()
  end

  local raw_iter = node:_rawquery(query.query, true, 0, -1)

Here's my full :healthcheck output:

:healthcheck

==============================================================================
lazy: require("lazy.health").check()

lazy.nvim ~
- OK Git installed
- OK no existing packages found by other package managers
- OK packer_compiled.lua not found

==============================================================================
null-ls: require("null-ls.health").check()

- ERROR black: the command "black" is not executable.
- OK clang_format: the command "clang-format" is executable.
- OK goimports: the command "goimports" is executable.
- OK gofumpt: the command "gofumpt" is executable.
- OK prettier: the command "prettier" is executable.
- OK stylua: the command "stylua" is executable.
- ERROR terraform_fmt: the command "terraform" is not executable.

==============================================================================
nvim: require("nvim.health").check()

Configuration ~
- OK no issues found

Runtime ~
- OK $VIMRUNTIME: /opt/homebrew/Cellar/neovim/0.10.0/share/nvim/runtime

Performance ~
- OK Build type: Release

Remote Plugins ~
- OK Up to date

terminal ~
- key_backspace (kbs) terminfo entry: `key_backspace=\177`
- key_dc (kdch1) terminfo entry: `key_dc=\E[3~`
- $COLORTERM="truecolor"

External Tools ~
- OK ripgrep 14.1.0 (/opt/homebrew/bin/rg)

==============================================================================
nvim-treesitter: require("nvim-treesitter.health").check()

Installation ~
- OK `tree-sitter` found 0.22.6 (parser generator, only needed for :TSInstallFromGrammar)
- OK `node` found v20.11.1 (only needed for :TSInstallFromGrammar)
- OK `git` executable found.
- OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
  Version: Apple clang version 15.0.0 (clang-1500.3.9.4)
- OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.

OS Info:
{
  machine = "arm64",
  release = "23.4.0",
  sysname = "Darwin",
  version = "Darwin Kernel Version 23.4.0: Fri Mar 15 00:12:49 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T6020"
} ~

Parser/Features         H L F I J
  - bash                ✓ ✓ ✓ . ✓
  - c                   ✓ ✓ ✓ ✓ ✓
  - c_sharp             ✓ ✓ ✓ . ✓
  - comment             ✓ . . . .
  - cpp                 ✓ ✓ ✓ ✓ ✓
  - css                 ✓ . ✓ ✓ ✓
  - csv                 ✓ . . . .
  - diff                ✓ . . . .
  - dockerfile          ✓ . . . ✓
  - elixir              ✓ ✓ ✓ ✓ ✓
  - erlang              ✓ . ✓ . .
  - git_config          ✓ . ✓ . ✓
  - git_rebase          ✓ . . . ✓
  - gitcommit           ✓ . . . ✓
  - gitignore           ✓ . . . .
  - glsl                ✓ ✓ ✓ ✓ ✓
  - go                  ✓ ✓ ✓ ✓ ✓
  - gomod               ✓ . . . ✓
  - gosum               ✓ . . . .
  - gowork              ✓ . . . ✓
  - html                ✓ ✓ ✓ ✓ ✓
  - htmldjango          ✓ . ✓ ✓ ✓
  - ini                 ✓ . ✓ . .
  - java                ✓ ✓ ✓ ✓ ✓
  - javascript          ✓ ✓ ✓ ✓ ✓
  - json                ✓ ✓ ✓ ✓ .
  - json5               ✓ . . . ✓
  - jsonc               ✓ ✓ ✓ ✓ ✓
  - julia               ✓ ✓ ✓ ✓ ✓
  - latex               ✓ . ✓ . ✓
  - lua                 ✓ ✓ ✓ ✓ ✓
  - make                ✓ . ✓ . ✓
  - markdown            ✓ . ✓ ✓ ✓
  - markdown_inline     ✓ . . . ✓
  - prisma              ✓ . ✓ . .
  - python              ✓ ✓ ✓ ✓ ✓
  - query               ✓ ✓ ✓ ✓ ✓
  - ruby                ✓ ✓ ✓ ✓ ✓
  - rust                ✓ ✓ ✓ ✓ ✓
  - scss                ✓ . ✓ ✓ .
  - sql                 ✓ . . ✓ ✓
  - starlark            ✓ ✓ ✓ ✓ ✓
  - swift               ✓ ✓ . ✓ .
  - terraform           ✓ . ✓ ✓ ✓
  - toml                ✓ ✓ ✓ ✓ ✓
  - tsx                 ✓ ✓ ✓ ✓ ✓
  - typescript          ✓ ✓ ✓ ✓ ✓
  - vim                 ✓ ✓ ✓ . ✓
  - vimdoc              ✓ . . . ✓
  - xml                 ✓ ✓ ✓ ✓ ✓
  - yaml                ✓ ✓ ✓ ✓ ✓
  - zig                 ✓ ✓ ✓ ✓ ✓

  Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
         +) multiple parsers found, only one will be used
         x) errors found in the query, try to run :TSUpdate {lang} ~

==============================================================================
provider.clipboard: require("provider.clipboard.health").check()

Clipboard (optional) ~
- OK Clipboard tool found: pbcopy

==============================================================================
provider.node: require("provider.node.health").check()

Node.js provider (optional) ~
- Node.js: v20.11.1
  
- WARNING Missing "neovim" npm (or yarn, pnpm) package.
  - ADVICE:
    - Run in shell: npm install -g neovim
    - Run in shell (if you use yarn): yarn global add neovim
    - Run in shell (if you use pnpm): pnpm install -g neovim
    - You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim

==============================================================================
provider.perl: require("provider.perl.health").check()

Perl provider (optional) ~
- WARNING "Neovim::Ext" cpan module is not installed
  - ADVICE:
    - See :help |provider-perl| for more information.
    - You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim
- WARNING No usable perl executable found

==============================================================================
provider.python: require("provider.python.health").check()

Python 3 provider (optional) ~
- WARNING No Python executable found that can `import neovim`. Using the first available executable for diagnostics.
- WARNING Could not load Python :
  /Users/llimllib/.local/share/mise/installs/python/3.12/bin/python3 does not have the "neovim" module.
  /Users/llimllib/.local/share/mise/installs/python/3.12/bin/python3.12 does not have the "neovim" module.
  /opt/homebrew/bin/python3.11 does not have the "neovim" module.
  python3.10 not found in search path or not executable.
  python3.9 not found in search path or not executable.
  python3.8 not found in search path or not executable.
  python3.7 not found in search path or not executable.
  /Users/llimllib/.local/share/mise/installs/python/3.12/bin/python does not have the "neovim" module.
  - ADVICE:
    - See :help |provider-python| for more information.
    - You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim
- Executable: Not found

Python virtualenv ~
- OK no $VIRTUAL_ENV

==============================================================================
provider.ruby: require("provider.ruby.health").check()

Ruby provider (optional) ~
- Ruby: ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin23]
- WARNING `neovim-ruby-host` not found.
  - ADVICE:
    - Run `gem install neovim` to ensure the neovim RubyGem is installed.
    - Run `gem environment` to ensure the gem bin directory is in $PATH.
    - If you are using rvm/rbenv/chruby, try "rehashing".
    - See :help |g:ruby_host_prog| for non-standard gem installations.
    - You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim

==============================================================================
telescope: require("telescope.health").check()

Checking for required plugins ~
- OK plenary installed.
- OK nvim-treesitter installed.

Checking external dependencies ~
- OK rg: found ripgrep 14.1.0
- OK fd: found fd 8.7.0

===== Installed extensions ===== ~

Telescope Extension: `fzf` ~
- OK lib working as expected
- OK file_sorter correctly configured
- OK generic_sorter correctly configured

==============================================================================
vim.lsp: require("vim.lsp.health").check()

- LSP log level : WARN
- Log path: /Users/llimllib/.local/state/nvim/lsp.log
- Log size: 9823 KB

vim.lsp: Active Clients ~
- null-ls (id=1, root_dir=~/readme/mdx-renderer, attached_to=[1,4])

vim.lsp: File watcher ~
- file watching "(workspace/didChangeWatchedFiles)" disabled on all clients

==============================================================================
vim.treesitter: require("vim.treesitter.health").check()

- Nvim runtime ABI version: 14
- OK Parser: bash                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/bash.so
- OK Parser: c                    ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/c.so
- OK Parser: comment              ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/comment.so
- OK Parser: cpp                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/cpp.so
- OK Parser: css                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/css.so
- OK Parser: csv                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/csv.so
- OK Parser: c_sharp              ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/c_sharp.so
- OK Parser: diff                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/diff.so
- OK Parser: dockerfile           ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/dockerfile.so
- OK Parser: elixir               ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/elixir.so
- OK Parser: erlang               ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/erlang.so
- OK Parser: gitcommit            ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/gitcommit.so
- OK Parser: gitignore            ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/gitignore.so
- OK Parser: git_config           ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/git_config.so
- OK Parser: git_rebase           ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/git_rebase.so
- OK Parser: glsl                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/glsl.so
- OK Parser: go                   ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/go.so
- OK Parser: gomod                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/gomod.so
- OK Parser: gosum                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/gosum.so
- OK Parser: gowork               ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/gowork.so
- OK Parser: html                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/html.so
- OK Parser: htmldjango           ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/htmldjango.so
- OK Parser: ini                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/ini.so
- OK Parser: java                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/java.so
- OK Parser: javascript           ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/javascript.so
- OK Parser: json                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/json.so
- OK Parser: json5                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/json5.so
- OK Parser: jsonc                ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/jsonc.so
- OK Parser: julia                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/julia.so
- OK Parser: latex                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/latex.so
- OK Parser: lua                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/lua.so
- OK Parser: make                 ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/make.so
- OK Parser: markdown             ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/markdown.so
- OK Parser: markdown_inline      ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/markdown_inline.so
- OK Parser: prisma               ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/prisma.so
- OK Parser: python               ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/python.so
- OK Parser: query                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/query.so
- OK Parser: ruby                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/ruby.so
- OK Parser: rust                 ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/rust.so
- OK Parser: scss                 ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/scss.so
- OK Parser: sql                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/sql.so
- OK Parser: starlark             ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/starlark.so
- OK Parser: swift                ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/swift.so
- OK Parser: terraform            ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/terraform.so
- OK Parser: toml                 ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/toml.so
- OK Parser: tsx                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/tsx.so
- OK Parser: typescript           ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/typescript.so
- OK Parser: vim                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/vim.so
- OK Parser: vimdoc               ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/vimdoc.so
- OK Parser: xml                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/xml.so
- OK Parser: yaml                 ABI: 13, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/yaml.so
- OK Parser: zig                  ABI: 14, path: /Users/llimllib/.local/share/nvim/lazy/nvim-treesitter/parser/zig.so
- OK Parser: bash                 ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/bash.so
- OK Parser: c                    ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/c.so
- OK Parser: lua                  ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/lua.so
- OK Parser: markdown             ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/markdown.so
- OK Parser: markdown_inline      ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/markdown_inline.so
- OK Parser: python               ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/python.so
- OK Parser: query                ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/query.so
- OK Parser: vim                  ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/vim.so
- OK Parser: vimdoc               ABI: 14, path: /opt/homebrew/Cellar/neovim/0.10.0/lib/nvim/parser/vimdoc.so

Diagnostic Line Numbers are offset by one in certain situations

With file after/ftplugin/markdown.lua having the contents of

require("otter").activate({ "python" }, true, true, nil)

If I open nvim . and navigate to notebooks/notebook.ipynb to open it, otter will activate, and have the diagnostics offset by 1 line.

If I directly open nvim notebooks/notebook.ipynb, the code in after/ftplugin/markdown.lua will not trigger (not sure why), but calling require("otter").activate({ "python" }, true, true, nil) manually will cause diagnostics to appear on the correct line.

Similarly, if I don't have the after/ftplugin/markdown.lua, and manually activate otter, no matter how I open it, the offset issue does not exist.

Originally thought this was a molten issue, but after discussing in benlubas/molten-nvim#178 I've discovered it's more likely something in otter.nvim

How to use this with eruby?

When writing *.html.erb, i would like to have <% %> blocks use solargraph LSP.
Is it possible with this plugin? If so, how?

Feature request: support coq_nvim (or: be autocompletion-engine-agnostic)

Hi,

I love the plugin, but recently I switched away from nvim-cmp to coq_nvim due to performance reasons and unfortunately it seems that otter lacks support for coq.

Could support for coq please be added?

Alternatively, why not register a new LSP directly in neovim (in lua) which will simply redirect to other relevant LSPs, instead of having this implementation as a separate autocompletion plugin? I haven't looked into neovim APIs in great detail, but it seems that something along those lines should be possible.

Thanks again for the plugin and your time.

[Question] How to turn off diagnostic

Sometimes the code snippets inside a code block do not necessarily have to use a complete and correct syntax, but I do not want to have diagnostic hints for these blocks. For example, the following error is pretty annoying:

image

Thanks in advance!

cmp source active for other buffers that are not activated

leads to

Error detected while processing TextChangedI Autocommands for "*":                            
Error executing lua callback: /usr/share/nvim/runtime/lua/vim/treesitter/query.lua:219: string
 expected                                                                                     
stack traceback:                                                                              
        [C]: in function '_ts_parse_query'                                                    
        /usr/share/nvim/runtime/lua/vim/treesitter/query.lua:219: in function 'parse_query'   
        /home/jannik/projects/otter.nvim/lua/otter/keeper.lua:23: in function 'extract_code_ch
unks'                                                                                         
        /home/jannik/projects/otter.nvim/lua/otter/keeper.lua:54: in function 'sync_raft'     
        /home/jannik/projects/otter.nvim/lua/otter/keeper.lua:86: in function 'updater'       
        ...nnik/projects/otter.nvim/lua/otter/completion/source.lua:65: in function 'complete'
                                                                                              
        ...annik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/source.lua:296: in function 'complete
'                                                                                             
        .../jannik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:286: in function 'complete
'                                                                                             
        .../jannik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:168: in function 'callback
'                                                                                             
        .../jannik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:218: in function 'autoinde
nt'                                                                                           
        .../jannik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:160: in function 'on_chang
e'                                                                                            
        .../jannik/.local/share/nvim/lazy/nvim-cmp/lua/cmp/init.lua:301: in function 'callback
'                                                                                             
        ...local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/autocmd.lua:49: in function 'emit'    
        ...local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/autocmd.lua:23: in function <...local/
share/nvim/lazy/nvim-cmp/lua/cmp/utils/autocmd.lua:22>                                        

Otter not loading unless save and quit neovim and reopen buffer

As the title says.

If I make a new quarto document and create code chunks (without saving) otter doesn't show cmp suggestions.

If I save multiple times similarly otter still doesn't show code completions. Only after I quit neovim and load the same quarto document does cmp work for all code chunks.

However, if I created say an .r or .sh or .py file I get full suggestions without having to quit nvim first.

I understand in otters use case that saving the buffer first would trigger the cmp right? But I am not entirely sure why I have to quit nvim and reopen the file? Perhaps soemone can help. For example, it almost seems like otters hidden buffers are only being created after saving and then quitting neovim, is there a way to debug which hidden buffers are created and when? Thanks in advance!

Deprecated `vim.lsp.get_active_clients`

Editing a block displays:

 | Messages: 2024-05-23T15:56:37 Warning  WARN  | Warning: vim.lsp.get_active_clients() is deprecated, use vim.lsp.get_clients() instead. :help deprecated
Feature will be removed in Nvim 0.12
2024-05-23T15:56:37 Warning  WARN  | Warning: stack traceback:
	/usr/local/share/nvim/runtime/lua/vim/lsp.lua:793: in function 'get_active_clients'
	...share/nvim/lazy/otter.nvim/lua/otter/completion/init.lua:37: in function 'cmp_on_insert_enter'
	...share/nvim/lazy/otter.nvim/lua/otter/completion/init.lua:14: in function <...share/nvim/lazy/otter.nvim/lua/otter/completion/init.lua:13>

feat: pass in a custom request to use instead of default LSP's

Same kind of request as for the fallback, I'd like Otter to use my usual function for type_definition (for example) instead of the default LSP.
Would default to the current behavior (using the LSP's builtin function).

I looked into the code to do it myself but I don't understand where it is done, I'd be happy to open a PR if you can give me some directions. :)

My idea is to add a second parameter callback of type function|nil to all ask_* functions.

Treesitter error in markdown files

When opening a markdown file, I get the following error:

Error executing vim.schedule lua callback: /usr/share/nvim/runtime/lua/vim/treesitter/query.lua:741: attempt to get length of local 'v' (a number value)
stack traceback:
        /usr/share/nvim/runtime/lua/vim/treesitter/query.lua:741: in function 'handler'
        /usr/share/nvim/runtime/lua/vim/treesitter/query.lua:823: in function 'apply_directives'
        ...kages/otter.nvim/lua/otter/tools/treesitter_iterator.lua:23: in function '(for generator)'
        ...ocal/share/nvim/packages/otter.nvim/lua/otter/keeper.lua:54: in function 'extract_code_chunks'
        ....local/share/nvim/packages/otter.nvim/lua/otter/init.lua:69: in function 'activate'
        /home/zeng/.config/nvim/lua/configs/otter.lua:35: in function </home/zeng/.config/nvim/lua/configs/otter.lua:15>

Here is my config:

local ot = require('otter')

ot.setup({
  buffers = {
    set_filetype = true,
  },
})

vim.api.nvim_create_autocmd('FileType', {
  desc = 'Activate otter for filetypes with injections.',
  group = vim.api.nvim_create_augroup('OtterActivate', {}),
  pattern = { 'markdown', 'norg', 'org' },
  callback = function(info)
    vim.schedule(function()
      local buf = info.buf
      if
        not vim.api.nvim_buf_is_valid(buf)
        or not vim.bo[buf].ma
      then
        return
      end
      -- Enable completion only, disable diagnostics
      ot.activate({ 'python', 'bash', 'lua' }, true, false)
    end)
  end,
})

This error only occurs on NVIM v0.10.0-dev-2483+g6ab0876f51 but not NVIM v0.10.0-dev-2363+gb76a01055f, so it could be a neovim bug.

Specify custom fallback instead of default LSP

Hello!
Thanks for this great plugin, it's really helpful!

I use telescope.nvim to do a few things instead of the default LSP functions and would like to keep them as fallback, is this possible? I've looked at the PR introducing the fallbacks but it did not seem doable (or have I missed something?)

For example, to go to a definition, I have the following keymap:

vim.keymap.set("n", "gd", require('telescope.builtin").lsp_definitions, { desc = "[G]oto [D]efinition" })

Any way I could keep that?

Something nice would be to pass the fallback function as an argument to ask_definition, for example, and if nothing is passed, it'll default to the default LSP function.

Cheers

[feature request] trim common leading whitespace

problem

Some filetypes (notably org and norg) have code blocks that are potentially indented.

In a norg file, you might have something like this for example:

* Heading
  @code python
  print('hi there')
  @end

The otter buffer then looks like:

  print('hi there')

and then pyright complains about unexpected indentation.

proposed solution

Automatically trim white space (or add an option to enable this) when an injected chunk of code all has common leading white space. We'd then have to track the whitespace offset for each chunk and account for it when adding diagnostics or suggesting completions.


What are your thoughts on this? I'm happy to take a stab at implementing it.

Can I use this the otter way around?

Hi, wanted to attach markdown LSPs (markdownlint and vale) into markdown that is embedded into Elixir files, like this:

defmodule Foo do
  
  @doc """
  Greets someone

  ## Examples

      iex> Foo.hello("George)"
      Hello, George

  """
  def hello(name) do
    IO.puts "Hello, #{name}"
  end
end

Markdown inside Elixir is already injected through https://github.com/nvim-treesitter/nvim-treesitter/blob/4199be485cd85662d8ff1dc8c4cc78d819fad6cd/queries/elixir/injections.scm#L5-L14

Is this possible? Tried it and it didn't work.

fix breaking change of nvim-treesitter and nvim 0.9: `no parser for 'quarto' language, see :help treesitter`

When use the nvim 0.9 (the latest release), the latest commit of nvim treesitter 584ccea brings a lot of breaking change,

this includes:

https://github.com/nvim-treesitter/nvim-treesitter/blob/584ccea56e2d37b31ba292da2b539e1a4bb411ca/lua/nvim-treesitter/parsers.lua#L25

this means if you are using nvim 0.9, then filetype_to_parsername will return nil, and thus parsername will always be the filetype itself since parsers.filetype_to_parsername[ft] will always return nil and we cannot get the correct parsername we want to use.

Here is a traceback for quarto filetype

Error executing vim.schedule lua callback: ...0.9.0/share/nvim/runtime/lua/vim/treesitter/language.lua:94: no parser for 'quarto' language, see :help treesitter
-parsers
stack traceback:
        [C]: in function 'error'
        ...0.9.0/share/nvim/runtime/lua/vim/treesitter/language.lua:94: in function 'add'
        ...0/share/nvim/runtime/lua/vim/treesitter/languagetree.lua:88: in function 'new'
        ...r/neovim/0.9.0/share/nvim/runtime/lua/vim/treesitter.lua:61: in function '_create_parser'
        ...r/neovim/0.9.0/share/nvim/runtime/lua/vim/treesitter.lua:131: in function 'get_parser'
        ...vim/site/pack/packer/opt/otter.nvim/lua/otter/keeper.lua:26: in function 'extract_code_chunks'
        ...vim/site/pack/packer/opt/otter.nvim/lua/otter/keeper.lua:65: in function 'sync_raft'
        ...vim/site/pack/packer/opt/otter.nvim/lua/otter/keeper.lua:124: in function 'activate'
        /Users/northyear/.config/nvim/lua/conf/langs.lua:455: in function ''
        vim/_editor.lua: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>

A brute force way for the fixing is to maintain a local filetype_to_parsername table by our own rather than using the nvim-treesitter one.

Other than this bug, there are also deprecations: vim.treesitter.parse_query(), vim.treesitter.query.parse_query, vim.treesitter.query.get_node_text is also deprecated. We should use the new nvim api depending on the context (whether has('nvim-0.9') or not.

Readme improvements

It would be greatly appreciated if the README was a bit more detailed . With some added installation instructions and how to use .

For example:

Assuming otter.nvim is configured and added to nvim-cmp as a completion source

These are never mentioned and the only docs is the README

require'otter'.activate({'python', 'r', })

Should this be called like .setup() or should this be called on file enter with all the languages the file is potentially going to have ?

and a few other stuff.

Thanks for your hard work!

keymaps that activate only in otter context

To allow keeping other mappins when outside of a code chunk, e.g. go to definition in quarto / markdown would be using the marksman lsp go-to-definition for a headding but otter when inside of a code context.

write more lsp request filters

Requests

user-facing

  • textDocument/completion
  • textDocument/definition
  • textDocument/hover
  • textDocument/references
  • textDocument/rename
  • textDocument/codeAction
  • textDocument/declaration*
  • textDocument/documentHighlight
  • textDocument/documentSymbol
  • textDocument/formatting
  • textDocument/implementation*
  • textDocument/publishDiagnostics
  • textDocument/rangeFormatting
  • textDocument/signatureHelp
  • textDocument/typeDefinition*
  • workspace/symbol

Other

  • callHierarchy/incomingCalls
  • callHierarchy/outgoingCalls
  • window/logMessage
  • window/showDocument
  • window/showMessage
  • window/showMessageRequest
  • workspace/applyEdit

References

Rename action is not working

First thanks for creating such an awesome plugin)

I found that lsp rename action not work properly with Otter, but works wonderfully elsewhere. I am not sure why this happens. I use Lazyvim and it uses just vim.lsp.buf.rename. I took the autoseggestion script from Bekaboo nvim configuration

CleanShot.2024-03-06.at.11.11.07.mp4

I have similar issues with hover, references and type_definitions

Why do you think it can happen? Maybe where the issue can be

Configuration for add lsp feature to html! macro in Yew (rust)

hi, i try to config this plugin for add support for add lsp features to the html macro, i try to follow the config i found in quarto-nvim but it didn't work, this is the config:
{ "jmbuhr/otter.nvim", opts = function(_, opts) local rsquery = [[ (macro_invocation name: (indentifier) @name (#eq? @name "html") (token_tree (ERROR) @html_macro ) ) ]] local otter = require("otter") otter.activate( { "html" }, { true }, { true }, rsquery ) end },

Hidden buffers sometimes include extra characters from source buffer

When injecting code like this in a TypeScript or JavaScript file:

const vert = glsl`
  void main() {
    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
  }
`;

const foo = html`
  <div>
    <p>hello</p>
  </div>
`;

const bar = css`
  .foo {
    color: rgb(0, 0, 0);
  }
`;

const lua = lua`
  local foo = "bar"
  print(foo)
`;

I would not expect the backticks to be included, but they are:

2023-12-01_18-46-05_region

This causes incorrect diagnostic errors with some LSPs, like luals.

Handle buffers without active raft more gracefully or provide a way to check whether a raft is registered

When I for example run otter.ask_hover() in a buffer where otter.activate() wasn't run, I get the following error:

E5108: Error executing lua: ...u/.local/share/nvim/lazy/otter.nvim/lua/otter/keeper.lua:381: attempt to index a nil value
stack traceback:
        ...u/.local/share/nvim/lazy/otter.nvim/lua/otter/keeper.lua:381: in function 'send_request'
        ...cau/.local/share/nvim/lazy/otter.nvim/lua/otter/init.lua:326: in function 'ask_hover'

I can fix this with an xpcall for now, but it would be nice, if I could check whether otter was activated in the current buffer in my keymap instead.

Turn keymaps off

Hello!

I saw some key mappings on dev_setup function in init.lua file.
How can I turn these off without modifying otter's sources?

Thx.

perf: python issues

Two problems:

  • pyright startup in the background still freezes ui when main document is opened
  • having a python chunk leads to small random stutters (at injection language boundaries?) when scrolling or holding j or k.

[bug]ask format eat some additional lines

thanks for with great plugin, which makes working with notebooks in nvim so much better.

I happen to notice some lines is eaten when using the ask_format, I'm using otter with pyright and ruff-lsp server. Having tried with a minimal config on the astronvim pack, but it still remains.

original

```python
print("first line")



print("2nd line")
```

## Header1

```python
print("3rd line.")



print("4th line.")
```

```python
print("5th line.")
```

after ask format in the first code cell

It seems the '```' and 'header' is gone

```python
print("first line")


print("2nd line")

```python
print("3rd line.")



print("4th line.")
```

```python
print("5th line.")
```

after ask format in the 2nd code cell

the '```' is gone.

```python
print("first line")



print("2nd line")
```

## Header1

```python
print("3rd line.")


print("4th line.")

```python
print("5th line.")
```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.