Skip to content

Commit

Permalink
fix: textlock (#195)
Browse files Browse the repository at this point in the history
  closes #194

fix: document config and make sure config is required first in init

doc: config

feat: extened blink capabilites

fix: always call the handler for a request response even if the result
  is empty because we are not in an otter context to no stall other
  requests
  • Loading branch information
jmbuhr committed Jan 9, 2025
1 parent e8c662e commit 4f53b89
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 156 deletions.
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ and the latest [Neovim stable version](https://github.com/neovim/neovim/releases
'nvim-treesitter/nvim-treesitter',
},
opts = {},
},
}
```

### Configure otter
Expand All @@ -151,21 +151,32 @@ otter.setup{
}) or vim.fn.getcwd(0)
end,
},
-- options related to the otter buffers
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
-- 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,
},
-- list of characters that should be stripped from the beginning and end of the code chunks
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.
-- remove whitespace from the beginning of the code chunks when writing to the ottter buffers
-- and calculate it back in when handling lsp requests
handle_leading_whitespace = true,
-- mapping of filetypes to extensions for those not already included in otter.tools.extensions
-- e.g. ["bash"] = "sh"
extensions = {
},
-- add event listeners for LSP events for debugging
debug = false,
verbose = { -- set to false to disable all verbose messages
no_code_found = false -- warn if otter.activate is called, but no injected code was found
},
}
```

Expand Down
23 changes: 21 additions & 2 deletions lua/otter/config.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
local M = {}


---@class OtterConfig
local default_config = {
lsp = {
-- `: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" },
-- function to find the root dir where the otter-ls is started
root_dir = function(_, bufnr)
return vim.fs.root(bufnr or 0, {
".git",
Expand All @@ -11,18 +17,31 @@ local default_config = {
}) or vim.fn.getcwd(0)
end,
},
-- options related to the otter buffers
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
-- 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,
},
-- list of characters that should be stripped from the beginning and end of the code chunks
strip_wrapping_quote_characters = { "'", '"', "`" },
-- remove whitespace from the beginning of the code chunks when writing to the ottter buffers
-- and calculate it back in when handling lsp requests
handle_leading_whitespace = true,
-- mapping of filetypes to extensions for those not already included in otter.tools.extensions
-- e.g. ["bash"] = "sh"
extensions = {
},
-- add event listeners for LSP events for debugging
debug = false,
verbose = { -- set to false to disable all verbose messages
no_code_found = true -- warn if otter.activate is called, but no injected code was found
no_code_found = false -- warn if otter.activate is called, but no injected code was found
},
}

Expand Down
5 changes: 3 additions & 2 deletions lua/otter/diagnostics.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ local keeper = require("otter.keeper")

M = {}
M.setup = function(main_nr)
---@type integer[]
local nss = {}
for lang, bufnr in pairs(keeper.rafts[main_nr].buffers) do
local ns = api.nvim_create_namespace("otter-lang-" .. lang)
nss[bufnr] = ns
end
keeper.rafts[main_nr].nss = nss
keeper.rafts[main_nr].diagnostics_namespaces = nss

local sync_diagnostics = function(args)
if vim.tbl_contains(vim.tbl_values(keeper.rafts[main_nr].buffers), args.buf) then
Expand All @@ -31,7 +32,7 @@ M.setup = function(main_nr)
group = group,
callback = sync_diagnostics,
})
keeper.rafts[main_nr].dianostics_group = group
keeper.rafts[main_nr].diagnostics_group = group

api.nvim_create_autocmd(config.cfg.lsp.diagnostic_update_events, {
buffer = main_nr,
Expand Down
82 changes: 52 additions & 30 deletions lua/otter/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@ local M = {}

local api = vim.api
local ts = vim.treesitter

local config = require("otter.config")
local extensions = require("otter.tools.extensions")
local keeper = require("otter.keeper")
local otterls = require("otter.lsp")

local path_to_otterpath = require("otter.tools.functions").path_to_otterpath
local config = require("otter.config")

M.setup = function(opts)
if M.did_setup then
return vim.notify("[otter] otter.nvim is already setup", vim.log.levels.ERROR)
end
M.did_setup = true

if vim.fn.has("nvim-0.10.0") ~= 1 then
return vim.notify("[otter] otter.nvim requires Neovim >= 0.10.0", vim.log.levels.ERROR)
end

config.cfg = vim.tbl_deep_extend("force", config.cfg, opts or {})

extensions = vim.tbl_deep_extend("force", extensions, config.cfg.extensions or {})
end

-- expose some functions from the otter keeper directly
Expand All @@ -19,10 +32,10 @@ M.export_otter_as = keeper.export_otter_as

--- Activate the current buffer by adding and synchronizing
--- otter buffers.
---@param languages table|nil List of languages to activate. If nil, all available languages will be activated.
---@param completion boolean|nil Enable completion for otter buffers. Default: true
---@param diagnostics boolean|nil Enable diagnostics for otter buffers. Default: true
---@param tsquery string|nil Explicitly provide a treesitter query. If nil, the injections query for the current filetyepe will be used. See :h treesitter-language-injections.
---@param languages string[]? List of languages to activate. If nil, all available languages will be activated.
---@param completion boolean? Enable completion for otter buffers. Default: true
---@param diagnostics boolean? Enable diagnostics for otter buffers. Default: true
---@param tsquery string? Explicitly provide a treesitter query. If nil, the injections query for the current filetyepe will be used. See :h treesitter-language-injections.
M.activate = function(languages, completion, diagnostics, tsquery)
languages = languages or vim.tbl_keys(require("otter.tools.extensions"))
completion = completion ~= false
Expand All @@ -49,19 +62,31 @@ M.activate = function(languages, completion, diagnostics, tsquery)
)
return
end
keeper.rafts[main_nr] = {}
keeper.rafts[main_nr].languages = {}
keeper.rafts[main_nr].buffers = {}
keeper.rafts[main_nr].paths = {}
keeper.rafts[main_nr].otter_nr_to_lang = {}
keeper.rafts[main_nr].tsquery = tsquery
keeper.rafts[main_nr].query = query
keeper.rafts[main_nr].parser = ts.get_parser(main_nr, parsername)
keeper.rafts[main_nr].code_chunks = nil
keeper.rafts[main_nr].last_changetick = nil
keeper.rafts[main_nr].otterls = {}
local parser = ts.get_parser(main_nr, parsername)
if parser == nil then
vim.notify_once("[otter] No parser found for current buffer. Can't activate.", vim.log.levels.WARN, {})
return
end
keeper.rafts[main_nr] = {
languages = {},
buffers = {},
paths = {},
otter_nr_to_lang = {},
tsquery = tsquery,
query = query,
parser = parser,
code_chunks = {},
last_changetick = nil,
otterls = {
client_id = nil,
},
diagnostics_namespaces = {},
diagnostics_group = nil,
}

local all_code_chunks = keeper.extract_code_chunks(main_nr)

---@type string[]
local found_languages = {}
for _, lang in ipairs(languages) do
if all_code_chunks[lang] ~= nil and lang ~= main_lang then
Expand All @@ -70,11 +95,9 @@ M.activate = function(languages, completion, diagnostics, tsquery)
end
languages = found_languages
if #languages == 0 then
-- just return quietly until
-- TODO: config handling is more robust
-- if config.cfg.verbose and config.cfg.verbose.no_code_found then
-- vim.notify_once("[otter] No code chunks found. Not activating. You can activate after having added code chunks with require'otter'.activate(). You can turn of this message by setting the option verbose.no_code_found to false", vim.log.levels.INFO, {})
-- end
if config.cfg.verbose and config.cfg.verbose.no_code_found then
vim.notify_once("[otter] No code chunks found. Not activating. You can activate after having added code chunks with require'otter'.activate(). You can turn of this message by setting the option verbose.no_code_found to false", vim.log.levels.INFO, {})
end
return
end

Expand Down Expand Up @@ -151,6 +174,7 @@ M.activate = function(languages, completion, diagnostics, tsquery)
end)
end

-- or if requested set the filetype
if config.cfg.buffers.set_filetype then
api.nvim_set_option_value("filetype", lang, { buf = otter_nr })
else
Expand Down Expand Up @@ -192,21 +216,19 @@ M.activate = function(languages, completion, diagnostics, tsquery)
-- remove the need to use keybindings for otter ask_ functions
-- by being our own lsp server-client combo
local otterclient_id = otterls.start(main_nr, completion)
if otterclient_id == nil then
if otterclient_id ~= nil then
keeper.rafts[main_nr].otterls.client_id = otterclient_id
else
vim.notify_once("[otter] activation of otter-ls failed", vim.log.levels.WARN, {})
end

keeper.rafts[main_nr].otterls.client_id = otterclient_id

-- debugging
if config.cfg.debug == true then
-- listen to lsp requests and notifications
vim.api.nvim_create_autocmd("LspNotify", {
callback = function(args)
local bufnr = args.buf
local client_id = args.data.client_id
local method = args.data.method
local params = args.data.params
---@param _ {buf: number, data: {client_id: number, method: string, params: any}}
callback = function(_)
end,
})

Expand Down Expand Up @@ -237,11 +259,11 @@ M.deactivate = function(completion, diagnostics)
end

if diagnostics then
for _, ns in pairs(keeper.rafts[main_nr].nss) do
for _, ns in pairs(keeper.rafts[main_nr].diagnostics_namespaces) do
vim.diagnostic.reset(ns, main_nr)
end
-- remove diagnostics autocommands
local id = keeper.rafts[main_nr].dianostics_group
local id = keeper.rafts[main_nr].diagnostics_group
if id ~= nil then
vim.api.nvim_del_augroup_by_id(id)
end
Expand Down
Loading

0 comments on commit 4f53b89

Please sign in to comment.