diff --git a/.emmyrc.json b/.emmyrc.json
index ce1f079..61f28f7 100644
--- a/.emmyrc.json
+++ b/.emmyrc.json
@@ -2,7 +2,8 @@
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
"diagnostics": {
"disable": [
- "unnecessary-if"
+ "unnecessary-if",
+ "unnecessary-assert"
]
},
"runtime": {
@@ -15,20 +16,20 @@
"workspace": {
"ignoreDir": [
"deps",
- ".venv"
+ ".venv"
],
"ignoreGlobs": [
"*.log"
],
"library": [
- "$VIMRUNTIME",
+ "$VIMRUNTIME/lua",
"./deps",
"$HOME/.local/share/nvim/lazy/image.nvim/",
"$HOME/.local/share/nvim/lazy/snacks.nvim/",
"$HOME/.local/share/nvim/lazy/lualine.nvim/"
],
- "workspaceRoots": [
- "./lua"
- ]
+ "workspaceRoots": [
+ "./lua"
+ ]
}
}
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 9d34407..be6e660 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -110,7 +110,7 @@ jobs:
- name: Run emmylua_check
run: |
export VIMRUNTIME=$(nvim --clean --headless +'lua io.write(vim.env.VIMRUNTIME)' +qa)
- emmylua_check . --warnings-as-errors --output-format github
+ emmylua_check . --warnings-as-errors
# Ark needs a real R at runtime. Install it out-of-band; the script only
# downloads the ark binary and writes the kernelspec.
diff --git a/README.md b/README.md
index a670d9a..ba9bcee 100644
--- a/README.md
+++ b/README.md
@@ -438,10 +438,9 @@ Architecture differences aside, a high-level feature comparison is as follows:
## FAQ
-Was jet.nvim vibe coded?
+Is jet.nvim vibe coded?
-> No. I did use AI quite a bit to develop Jet proper, i.e. the Rust backend. I
-> wrote this README with a keyboard using my own two mucky paws.
+> No. Some AI was used to develop Jet proper, jet.nvim's Rust backend.
diff --git a/doc/jet-nvim.txt b/doc/jet-nvim.txt
index c71f2c4..9fa0e44 100644
--- a/doc/jet-nvim.txt
+++ b/doc/jet-nvim.txt
@@ -162,6 +162,8 @@ The full set of configuration options is as follows:
After a kernel becomes or stops
becoming the 'current' kernel for its
filetype.
+ • {on_win_open} (`table`)
+ After a window is opened
------------------------------------------------------------------------------
Extensions *jet-extensions*
@@ -438,7 +440,7 @@ THE API MODULE *jet-jet.api*
api.next_expr_boundary({opts}, {p}) *jet-api.next_expr_boundary()*
Parameters: ~
- • {opts} (`jet.send.next_expr_boundary.Opts?`)
+ • {opts} (`jet.send.next_expr_boundary.Opts?`) Fields:
• direction (`(1|-1)?`)
• boundary (`("start"|"end"|"any")?`)
• current_ok (`boolean?`)
@@ -577,8 +579,6 @@ THE KERNEL CLASS *jet-the-kernel-class*
connection to the kernel.
• {lsp} (`jet.Lsp`) Information about the kernel's Jet
LSP process.
- • {term} (`jet.Kernel.Term?`) Repl buffer data
- • {img} (`jet.Kernel.Img?`) Image buffer data
• {owned} (`boolean`) `true` if the kernel session was
started by this nvim session; `false` otherwise.
• {filetype} (`string?`) The kernel's filetype. jet.nvim will
@@ -607,12 +607,24 @@ THE KERNEL CLASS *jet-the-kernel-class*
• {hooks} (`jet.Hooks`) Kernel-specific hooks. Basically
for convenience on top of the 'global' hooks you
can set in |jet.Config|
- • {metadata} (`table`) Arbitrary extra data,
- e.g. for use by extensions
• {priority} (`integer`) Defaults to 100. `api.get_kernel()`
will try to use this field to select a single
kernel. Typically you would set the priority
using the kernel's init hook (see |jet.Hooks|).
+ • {wins} (`jet.Kernel.Windows`) Windows used to show
+ kernel UI. Kernels use 2 windows by default (one
+ for the repl, one for all other stuff). This
+ field is extensible!
+ Fields:
+ • primary (`jet.Win`)
+ • secondary (`jet.Win`)
+ • {bufs} (`jet.Kernel.Buffers`) Buffers used to show
+ kernel UI. By default includes the repl and a
+ plots buffer.
+ Fields:
+ • term (`jet.Kernel.Term?`)
+ • img (`jet.Kernel.Img?`)
+ • {subclass} (`string?`)
Kernel.init_owned({opts}) *jet-Kernel.init_owned()*
@@ -620,7 +632,7 @@ Kernel.init_owned({opts}) *jet-Kernel.init_owned()*
process.
Parameters: ~
- • {opts} (`jet.kernel.init_owned.Opts`)
+ • {opts} (`jet.kernel.init_owned.Opts`) Fields:
• spec_path (`string`)
• session_name (`string?`)
• spec
@@ -636,7 +648,7 @@ Kernel.init_external({opts}) *jet-Kernel.init_external()*
session
Parameters: ~
- • {opts} (`jet.kernel.init_external.Opts`)
+ • {opts} (`jet.kernel.init_external.Opts`) Fields:
• session_id (`string`)
• priority (`integer?`)
@@ -748,6 +760,18 @@ Kernel:stop({callback}) *jet-Kernel:stop()*
See: ~
• |Kernel:close()|
+Kernel:get_comm({name}, {pattern}) *jet-Kernel:get_comm()*
+
+ Convenience; find a comm id (from `Kernel.open_comms`) using the comm name
+
+ Parameters: ~
+ • {name} (`string`)
+ • {pattern} (`boolean?`)
+
+ Return: ~
+ (`string?`)
+ (`table?`)
+
Kernel:comm_open({name}, {data}, {opts}) *jet-Kernel:comm_open()*
Open a comm channel to the kernel
@@ -761,7 +785,7 @@ Kernel:comm_open({name}, {data}, {opts}) *jet-Kernel:comm_open()*
Parameters: ~
• {name} (`string`)
• {data} (`table?`)
- • {opts} (`jet.kernel.comm_open.Opts?`)
+ • {opts} (`jet.kernel.comm_open.Opts?`) Fields:
• listener (`(fun(res: jupyter.Msg))?`)
• listener_interval (`integer?`): In milliseconds,
default 50ms
@@ -850,7 +874,7 @@ jet.nvim uses the following highlight groups, which can be overridden:
• {JetIdle} (`{ link = "DiagnosticOk" }`)
• {JetItalic} (`{ italic = true }`)
• {JetLabel} (`{ link = "@label" }`)
- • {JetRepl} (`{ link = "NormalFloat" }`)
+ • {JetNormal} (`{ link = "NormalFloat" }`)
• {JetSpecial} (`{ link = "@punctuation.special" }`)
• {JetSuccess} (`{ link = "DiagnosticOk" }`)
• {JetUrl} (`{ link = "@markup.link" }`)
@@ -916,4 +940,45 @@ tree-sitter node: >lua
jet.filetype.python = { get_expr = get_python_expr }
<
+CUSTOM UI COMPONENTS *jet-custom-ui-components*
+
+Extensions may want to add custom UI for a particular kernel. `Kernel` objects
+manage UI via two fields:
+
+• `Kernel.wins`: a table with the following fields:
+ • `wins.primary` (|jet.Win|)
+ • `wins.secondary` (|jet.Win|)
+• `Kernel.bufs` a table with the following fields
+ • `bufs.term`: (|jet.Kernel.Term|, inherits from |jet.Buf|) targets the
+ `primary` window
+ • `bufs.img`: (|jet.Kernel.Img|, inherits from |jet.Buf|) targets the
+ `secondary` window
+
+You can add more fields to `Kernel.wins` or `Kernel.bufs` to define custom UI,
+or modify existing fields to control behaviour. For example, to open the
+secondary window in a float: >lua
+ local hooks = require("jet").hooks
+
+ -- Patch the secondary window's `open_opts` to open a float
+ ---@param k jet.Kernel
+ table.insert(hooks.on_kernel_init, function(k)
+ ---@type vim.api.keyset.win_config
+ k.wins.secondary.open_opts = {
+ relative = "editor",
+ col = math.floor(vim.o.columns * 0.1),
+ width = math.floor(vim.o.columns * 0.8),
+ row = math.floor(vim.o.lines * 0.1),
+ height = math.floor(vim.o.lines * 0.8),
+ }
+ end)
+
+ -- Focus the window when it opens and add a keymap to close
+ table.insert(k.hooks.on_win_open, function(_, win, buf)
+ if win:name() == "secondary" then
+ vim.keymap.set("n", "q", "q", { buf = buf })
+ vim.api.nvim_set_current_win(assert(win:winnr()))
+ end
+ end)
+<
+
vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/doc/jet-recipes.txt b/doc/jet-recipes.txt
index 8584643..328a2e0 100644
--- a/doc/jet-recipes.txt
+++ b/doc/jet-recipes.txt
@@ -49,7 +49,7 @@ visible. >lua
local code = input and input.code
local text = result and result.data and result.data["text/plain"]
- local term_is_open = k.term and k.term:win()
+ local term_is_open = k.buf.term and k.buf.term:win()
if code and text and not term_is_open then
vim.notify(string.format("Ran `%s`:\nResult: %s", code, text))
@@ -137,4 +137,7 @@ alternative approach, e.g. for R, would be to override the `print` method for
console. jet.nvim could then pick up the `execute_reply` message and continue
to call visidata as above.
+------------------------------------------------------------------------------
+Floating plots window *jet-recipes-floating-plots-window*
+
vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/doc/jet-types.txt b/doc/jet-types.txt
index 01b7664..533b076 100644
--- a/doc/jet-types.txt
+++ b/doc/jet-types.txt
@@ -126,7 +126,7 @@ Range:code({opts}) *jet-types-Range:code()*
Also returns the local filetype at the range start.
Parameters: ~
- • {opts} (`jet.send.range_code.Opts?`)
+ • {opts} (`jet.send.range_code.Opts?`) Fields:
• comments (`boolean?`): Set to `true` to include
comments in the returned code.
@@ -161,9 +161,8 @@ Repl and image buffers *jet-types-repl-and-image-buffers*
Term.init({opts}) *jet-types-Term.init()*
Parameters: ~
- • {opts} (`jet.Kernel.Term.init.Opts`)
+ • {opts} (`jet.Kernel.Term.init.Opts`) Fields:
• kernel (`jet.Kernel`)
- • ns (`integer`)
Return: ~
(`jet.Kernel.Term`)
@@ -185,9 +184,8 @@ Term:send({code}, {tabstop}) *jet-types-Term:send()*
Img.init({opts}) *jet-types-Img.init()*
Parameters: ~
- • {opts} (`jet.Kernel.Img.init.Opts`)
+ • {opts} (`jet.Kernel.Img.init.Opts`) Fields:
• kernel (`jet.Kernel`)
- • ns (`integer`)
Return: ~
(`jet.Kernel.Img`)
@@ -212,42 +210,43 @@ Img:display({which}) *jet-types-Img:display()*
Parameters: ~
• {which} (`(string|integer)?`)
+------------------------------------------------------------------------------
+Buffer/window abstractions *jet-types-bufferwindow-abstractions*
+
*jet.Buf*
Fields: ~
- • {buf} (`integer`)
- • {name} (`string`)
- • {augroup} (`integer`)
- • {ns} (`integer`)
- • {kernel} (`jet.Kernel`)
- • {open_opts} (`(vim.api.keyset.win_config|fun() -> vim.api.keyset.win_config)`)
+ • {buf} (`integer`)
+ • {win_name} (`string`)
+ • {name} (`string`)
+ • {augroup} (`integer`)
+ • {ns} (`integer`)
+ • {kernel} (`jet.Kernel`)
Buf.init({class}, {opts}) *jet-types-Buf.init()*
Parameters: ~
• {class} (`T?`)
- • {opts} (`jet.Buf.init.Opts`)
+ • {opts} (`jet.Buf.init.Opts`) Fields:
• name (`string`)
- • ns (`integer`)
+ • win_name (`(string|keyof jet.Kernel.Windows)`)
• kernel (`jet.Kernel`)
- • open_opts
- (`(vim.api.keyset.win_config|fun() -> vim.api.keyset.win_config)`)
Return: ~
(`T`)
Buf:win() *jet-types-Buf:win()*
- Get a window displaying the buffer, if there is one
+ Get the kernel window associated with the buffer
Return: ~
- (`integer?`)
+ (`jet.Win`)
-Buf:open({focus}, {opts}) *jet-types-Buf:open()*
+Buf:open({opts}, {focus}) *jet-types-Buf:open()*
Parameters: ~
- • {focus} (`boolean?`)
• {opts} (`vim.api.keyset.win_config?`)
+ • {focus} (`boolean?`)
Return: ~
(`integer`) The opened window
@@ -262,4 +261,79 @@ Buf:create_autocmd({event}, {callback}) *jet-types-Buf:create_autocmd()*
• {event} (`(vim.api.keyset.events|vim.api.keyset.events[])`)
• {callback} (`(string|fun(args: vim.api.keyset.create_autocmd.callback_args) -> boolean?)`)
+*jet.Win*
+
+ Fields: ~
+ • {ns} (`integer`)
+ • {focus} (`boolean`) If `true` then `Win:open()` will focus an
+ already open window, otherwise it's a no-op.
+ • {kernel} (`jet.Kernel`)
+ • {open_opts} (`(vim.api.keyset.win_config|fun(k: jet.Kernel) -> vim.api.keyset.win_config)?`)
+ • {__index} (`jet.Win`)
+
+Win.init({opts}) *jet-types-Win.init()*
+
+ Parameters: ~
+ • {opts} (`jet.Win.init.Opts`) Fields:
+ • kernel (`jet.Win["kernel"]`)
+ • open_opts (`jet.Win["open_opts"]`)
+ • focus (`jet.Win["focus"]`)
+
+ Return: ~
+ (`jet.Win`)
+
+Win:name() *jet-types-Win:name()*
+
+ Return: ~
+ (`string`)
+
+Win:open({buf}, {opts}, {focus}) *jet-types-Win:open()*
+
+ Opens with the following algorithm
+
+ • If the window is not open, opens with `buf`
+ • If the window is open with `buf`, focus the window (if `Win.focus`)
+ • Otherwise, if the window is open with another buffer:
+ • Does the buffer have `vim.b.jet` set? If so, show `buf` in the window
+ • Otherwise, open a fresh window, resetting `self.win`.
+
+ Parameters: ~
+ • {buf} (`integer`)
+ • {opts} (`vim.api.keyset.win_config?`)
+ • {focus} (`boolean?`)
+
+ Return: ~
+ (`integer`)
+
+Win:close({buf}) *jet-types-Win:close()*
+
+ Parameters: ~
+ • {buf} (`integer?`)
+
+Win:toggle({buf}) *jet-types-Win:toggle()*
+
+ Parameters: ~
+ • {buf} (`integer`)
+
+Win:get_curr_jet_buf({buf}) *jet-types-Win:get_curr_jet_buf()*
+
+ Parameters: ~
+ • {buf} (`integer?`)
+
+ Return: ~
+ (`integer?`)
+
+Win:winnr({buf}) *jet-types-Win:winnr()*
+
+ Parameters: ~
+ • {buf} (`integer?`)
+
+ Return: ~
+ (`integer?`)
+
+Win:get_buf() *jet-types-Win:get_buf()*
+
+ Return: ~
+ (`integer?`)
+
vim:tw=78:sw=4:ts=4:ft=help:norl:et:
diff --git a/docs/jet-nvim.md b/docs/jet-nvim.md
index e642a06..2a7d6ea 100644
--- a/docs/jet-nvim.md
+++ b/docs/jet-nvim.md
@@ -322,7 +322,7 @@ python3 scripts/emmylua-to-md.py --type jet.api.Filters
### The Kernel Class
```{.sh include=true}
-python3 scripts/emmylua-to-md.py --type jet.Kernel
+python3 scripts/emmylua-to-md.py --type jet.Kernel --inline jet.Kernel.Buffers,jet.Kernel.Windows
```
### Highlights
@@ -392,3 +392,48 @@ end
local jet = require("jet")
jet.filetype.python = { get_expr = get_python_expr }
```
+
+### Custom UI components
+
+Extensions may want to add custom UI for a particular kernel. `Kernel` objects
+manage UI via two fields:
+
+* `Kernel.wins`: a table with the following fields:
+ * `wins.primary` (|jet.Win|)
+ * `wins.secondary` (|jet.Win|)
+
+* `Kernel.bufs` a table with the following fields
+ * `bufs.term`: (|jet.Kernel.Term|, inherits from |jet.Buf|) targets the
+ `primary` window
+ * `bufs.img`: (|jet.Kernel.Img|, inherits from |jet.Buf|) targets the
+ `secondary` window
+
+You can add more fields to `Kernel.wins` or `Kernel.bufs` to define custom UI,
+or modify existing fields to control behaviour. For example, to open the
+secondary window in a float:
+
+``` lua
+local hooks = require("jet").hooks
+
+-- Patch the secondary window's `open_opts` to open a float
+---@param k jet.Kernel
+table.insert(hooks.on_kernel_init, function(k)
+ ---@type vim.api.keyset.win_config
+ k.wins.secondary.open_opts = {
+ relative = "editor",
+ col = math.floor(vim.o.columns * 0.1),
+ width = math.floor(vim.o.columns * 0.8),
+ row = math.floor(vim.o.lines * 0.1),
+ height = math.floor(vim.o.lines * 0.8),
+ }
+end)
+
+-- Focus the window when it opens and add a keymap to close
+table.insert(k.hooks.on_win_open, function(_, win, buf)
+ if win:name() == "secondary" then
+ vim.keymap.set("n", "q", "q", { buf = buf })
+ vim.api.nvim_set_current_win(assert(win:winnr()))
+ end
+end)
+```
+
diff --git a/docs/jet-recipes.md b/docs/jet-recipes.md
index 7960c2b..5d947c9 100644
--- a/docs/jet-recipes.md
+++ b/docs/jet-recipes.md
@@ -48,7 +48,7 @@ hooks.on_message_received.notify = function(k, msg)
local code = input and input.code
local text = result and result.data and result.data["text/plain"]
- local term_is_open = k.term and k.term:win()
+ local term_is_open = k.buf.term and k.buf.term:win()
if code and text and not term_is_open then
vim.notify(string.format("Ran `%s`:\nResult: %s", code, text))
@@ -142,3 +142,8 @@ alternative approach, e.g. for R, would be to override the `print` method for
`data.frame`s to write the tempfile, then simply print the file path to the
console. jet.nvim could then pick up the `execute_reply` message and continue
to call visidata as above.
+
+## Floating plots window
+
+
+
diff --git a/docs/jet-types.md b/docs/jet-types.md
index 7c2627d..23746c1 100644
--- a/docs/jet-types.md
+++ b/docs/jet-types.md
@@ -26,6 +26,12 @@ python3 scripts/emmylua-to-md.py --type jet.Kernel.Term
python3 scripts/emmylua-to-md.py --type jet.Kernel.Img
```
+## Buffer/window abstractions
+
```{.sh include=true}
python3 scripts/emmylua-to-md.py --type jet.Buf
```
+
+```{.sh include=true}
+python3 scripts/emmylua-to-md.py --type jet.Win
+```
diff --git a/lua/jet/core/config.lua b/lua/jet/core/config.lua
index e8b97a1..0f7233a 100644
--- a/lua/jet/core/config.lua
+++ b/lua/jet/core/config.lua
@@ -90,7 +90,7 @@ M.defaults = {
hooks = require("jet.core.hooks").init_hooks(),
}
-M.jet_nvim_version = "0.1.0"
+M.jet_nvim_version = "0.2.0"
---@class jet.Config.Data
M.data = {
diff --git a/lua/jet/core/hooks.lua b/lua/jet/core/hooks.lua
index b150ee3..a7b902f 100644
--- a/lua/jet/core/hooks.lua
+++ b/lua/jet/core/hooks.lua
@@ -61,6 +61,10 @@ M.init_hooks = function()
---its filetype.
---@type table
on_currentness_changed = {},
+
+ ---After a window is opened
+ ---@type table
+ on_win_open = {},
}
return hooks
@@ -110,6 +114,7 @@ M.do_send_pre = make_caller(h.on_send_pre)
M.do_status_changed = make_caller(h.on_status_changed)
M.do_image_display_pre = make_caller(h.on_image_display_pre)
M.do_currentness_changed = make_caller(h.on_currentness_changed)
+M.do_win_open = make_caller(h.on_win_open)
-- stylua: ignore end
return M
diff --git a/lua/jet/core/kernel/buf.lua b/lua/jet/core/kernel/buf.lua
index 1065285..e1d8ada 100644
--- a/lua/jet/core/kernel/buf.lua
+++ b/lua/jet/core/kernel/buf.lua
@@ -1,20 +1,17 @@
-local utils = require("jet.core.utils")
-
---@class jet.Buf
---@field buf integer
+---@field win_name string
---@field name string
---@field augroup integer
---@field ns integer
---@field kernel jet.Kernel
----@field open_opts vim.api.keyset.win_config | fun(): vim.api.keyset.win_config
local Buf = {}
Buf.__index = Buf ---@private
---@class jet.Buf.init.Opts
---@field name string
----@field ns integer
+---@field win_name string | keyof jet.Kernel.Windows
---@field kernel jet.Kernel
----@field open_opts vim.api.keyset.win_config | fun(): vim.api.keyset.win_config
---@generic T
---@param class? T
@@ -23,9 +20,9 @@ Buf.__index = Buf ---@private
function Buf.init(class, opts)
local out = setmetatable({
kernel = opts.kernel,
- ns = opts.ns,
+ ns = vim.api.nvim_create_namespace("jet_highlights"),
name = opts.name,
- open_opts = opts.open_opts,
+ win_name = opts.win_name,
augroup = vim.api.nvim_create_augroup(opts.name, { clear = true }),
buf = vim.api.nvim_create_buf(false, true),
}, class or Buf)
@@ -36,55 +33,27 @@ function Buf.init(class, opts)
return out
end
----Get a window displaying the buffer, if there is one
----@return integer?
-function Buf:win() return utils.buf_get_win(self.buf) end
+---Get the kernel window associated with the buffer
+---@return jet.Win
+function Buf:win()
+ local out = self.kernel.wins[self.win_name]
+ assert(
+ out,
+ string.format(
+ "Kernel window '%s' not found. Kernel has windows %s",
+ self.win_name,
+ vim.inspect(vim.tbl_keys(self.kernel.wins))
+ )
+ )
+ return out
+end
+---@param opts vim.api.keyset.win_config?
---@param focus? boolean
----@param opts? vim.api.keyset.win_config
---@return integer # The opened window
-function Buf:open(focus, opts)
- local win = self:win()
-
- if win then
- if focus then
- vim.api.nvim_set_current_win(win)
- if vim.bo[self.buf].buftype == "terminal" then
- vim.cmd.startinsert()
- end
- end
- return win
- end
-
- local open_opts = opts
- or type(self.open_opts) == "function" and self.open_opts()
- or type(self.open_opts) == "table" and self.open_opts
- or {}
+function Buf:open(opts, focus) return self:win():open(self.buf, opts, focus) end
- ---@type integer
- win = vim.api.nvim_open_win(self.buf, false, open_opts)
- vim.api.nvim_win_set_hl_ns(win, self.ns)
-
- if vim.bo[self.buf].buftype == "terminal" then
- -- When the cursor is at the bottom of the REPL you get auto-scroll
- -- when new lines appear. This is a good state to start in.
- vim.api.nvim_win_set_cursor(win, { vim.api.nvim_buf_line_count(self.buf), 0 })
- end
-
- vim.wo[win].number = false
- vim.wo[win].relativenumber = false
-
- return win
-end
-
-function Buf:toggle()
- local win = self:win()
- if win then
- vim.api.nvim_win_close(win, true)
- else
- self:open()
- end
-end
+function Buf:toggle() self:win():toggle(self.buf) end
function Buf:delete()
vim.schedule(function()
diff --git a/lua/jet/core/kernel/img.lua b/lua/jet/core/kernel/img.lua
index 6f61f82..153b6de 100644
--- a/lua/jet/core/kernel/img.lua
+++ b/lua/jet/core/kernel/img.lua
@@ -9,7 +9,6 @@ Img.__index = Img ---@private
---@class jet.Kernel.Img.init.Opts
---@field kernel jet.Kernel
----@field ns integer
---@param opts jet.Kernel.Img.init.Opts
---@return jet.Kernel.Img
@@ -18,20 +17,12 @@ function Img.init(opts)
local out = buf.init(Img, {
name = opts.kernel:friendly_name() .. " - Images",
- ns = opts.ns,
kernel = opts.kernel,
- open_opts = function()
- local term_win = opts.kernel.term and opts.kernel.term:win()
- return {
- split = term_win and "above" or "right",
- win = term_win or -1,
- style = "minimal",
- }
- end,
+ win_name = "secondary",
})
out.kernel = opts.kernel
- vim.bo[out.buf].filetype = "jetimg" -- Note: Snacks.image overrides to "image"
+ vim.bo[out.buf].filetype = "jetimg"
out:create_autocmd("BufWinEnter", function() out:display() end)
@@ -45,7 +36,7 @@ end
---@param which? string | integer
---@return integer # Win number
function Img:open(focus, which)
- local win = buf.open(self, focus)
+ local win = buf.open(self, nil, focus)
self:display(which)
-- For folks who want to display image stuff in the winbar/statusline
vim.api.nvim__redraw({ win = win, winbar = true, statusline = true })
@@ -92,9 +83,7 @@ function Img:display(which)
return
end
- local win = self:win()
-
- if not win then
+ if not self:win():get_curr_jet_buf(self.buf) then
return
end
@@ -132,7 +121,6 @@ function Img:display(which)
if ok and image_api then
local img = image_api.from_file(src, {
buffer = self.buf,
- window = win,
})
if img then
img:render()
diff --git a/lua/jet/core/kernel/init.lua b/lua/jet/core/kernel/init.lua
index 4f8ed60..493c86c 100644
--- a/lua/jet/core/kernel/init.lua
+++ b/lua/jet/core/kernel/init.lua
@@ -1,8 +1,9 @@
local manager = require("jet.core.manager")
-local cfg = require("jet.core.config").options
local utils = require("jet.core.utils")
-local lsp = require("jet.core.kernel.lsp")
local hooks = require("jet.core.hooks")
+local win = require("jet.core.kernel.win")
+local lsp = require("jet.core.kernel.lsp")
+local cfg = require("jet.core.config").options
local STARTING_KERNEL_SENTINEL = ""
@@ -10,6 +11,23 @@ local STARTING_KERNEL_SENTINEL = ""
---@alias jet.Kernel.PartialSpec { display_name: string, language: string }
---@alias jet.Kernel.execution_state "busy" | "idle" | "starting"
+---Buffers used by the kernel
+---
+---Can be extended to implement custom UI.
+---
+---@class (partial) jet.Kernel.Buffers
+---@field term? jet.Kernel.Term
+---@field img? jet.Kernel.Img
+
+---Windows 'owned' by the kernel
+---
+---Note, you can extend this to add additional windows, or modify the default
+---windows directly.
+---
+---@class (partial) jet.Kernel.Windows
+---@field primary jet.Win
+---@field secondary jet.Win
+
---The `Kernel` class is jet.nvim's central abstraction for working with
---Jupyter kernels. You can create a new instance using two methods:
---
@@ -43,10 +61,6 @@ local STARTING_KERNEL_SENTINEL = ""
---@field client_id? string
---Information about the kernel's Jet LSP process.
---@field lsp jet.Lsp
----Repl buffer data
----@field term? jet.Kernel.Term
----Image buffer data
----@field img? jet.Kernel.Img
---`true` if the kernel session was started by this nvim session; `false`
---otherwise.
---@field owned boolean
@@ -73,12 +87,17 @@ local STARTING_KERNEL_SENTINEL = ""
---Kernel-specific hooks. Basically for convenience on top of the 'global'
---hooks you can set in |jet.Config|
---@field hooks jet.Hooks
----Arbitrary extra data, e.g. for use by extensions
----@field metadata table
---Defaults to 100. `api.get_kernel()` will try to use this field to select a
---single kernel. Typically you would set the priority using the kernel's init
---hook (see |jet.Hooks|).
---@field priority integer
+---Windows used to show kernel UI. Kernels use 2 windows by default (one for
+---the repl, one for all other stuff). This field is extensible!
+---@field wins jet.Kernel.Windows
+---Buffers used to show kernel UI. By default includes the repl and a plots
+---buffer.
+---@field bufs jet.Kernel.Buffers
+---@field subclass string?
---@field private stream jet.callback
---@field private ui_expand boolean
---@field private on_started table
@@ -97,9 +116,9 @@ local init_defaults = function()
incomplete_line = "",
},
on_started = {},
- metadata = {},
priority = 100,
hooks = hooks.init_hooks(),
+ bufs = {},
}
end
@@ -120,6 +139,7 @@ function Kernel.init_owned(opts)
local base = vim.tbl_extend("keep", opts, init_defaults(), { owned = true })
local out = setmetatable(base, Kernel)
+ out:initialise_wins()
out:try_resolve_filetype()
out:do_kernel_init()
@@ -150,6 +170,8 @@ function Kernel.init_external(opts)
Kernel
)
+ out:initialise_wins()
+
manager:insert(out)
Kernel.try_resolve_filetype(out)
@@ -158,6 +180,38 @@ function Kernel.init_external(opts)
return out
end
+---@private
+function Kernel:initialise_wins()
+ self.wins = {
+ primary = win.init({
+ kernel = self,
+ focus = true,
+ ---@param kernel jet.Kernel
+ open_opts = function(kernel)
+ local secondary_win = kernel.wins.secondary:winnr()
+ return {
+ split = secondary_win and "below" or "right",
+ win = secondary_win or -1,
+ }
+ end,
+ }),
+
+ secondary = win.init({
+ kernel = self,
+ focus = true,
+ ---@param kernel jet.Kernel
+ open_opts = function(kernel)
+ local primary_win = kernel.wins.primary:winnr()
+ return {
+ split = primary_win and "above" or "right",
+ win = primary_win or -1,
+ }
+ end,
+ }),
+ }
+end
+
+
-- stylua: ignore start
Kernel.do_execution_state_changed = hooks.do_execution_state_changed ---@private
Kernel.do_kernel_close = hooks.do_kernel_close ---@private
@@ -167,32 +221,30 @@ Kernel.do_message_received = hooks.do_message_received ---@private
Kernel.do_send_pre = hooks.do_send_pre ---@private
Kernel.do_status_changed = hooks.do_status_changed ---@private
Kernel.do_image_display_pre = hooks.do_image_display_pre ---@private
-Kernel.do_currentness_changed = hooks.do_currentness_changed ---@private
+Kernel.do_currentness_changed = hooks.do_currentness_changed ---@private
+Kernel.do_win_open = hooks.do_win_open ---@private
-- stylua: ignore end
---Toggle the terminal window for the kernel.
---If no terminal is active, one will be created and opened.
function Kernel:term_toggle()
- if self.term then
- self.term:toggle()
+ if self.bufs.term then
+ self.bufs.term:toggle()
else
self:term_open()
end
end
-local jet_hl_ns = vim.api.nvim_create_namespace("jet_highlights")
-vim.api.nvim_set_hl(jet_hl_ns, "Normal", { link = "JetRepl" })
-
---Open a terminal window for the kernel.
---If no terminal is active, one will be created and opened
---@param callback? fun(t: jet.Kernel.Term)
---@param focus? boolean
function Kernel:term_open(callback, focus)
self:term_create(function()
- assert(self.term, "kernel.term is nil")
- self.term:open(focus)
+ assert(self.bufs.term, "kernel.buf.term is nil")
+ self.bufs.term:open(nil, focus)
if callback then
- callback(self.term)
+ callback(self.bufs.term)
end
end)
end
@@ -207,12 +259,12 @@ function Kernel:set_current() manager:set_current(self) end
---@param callback? fun(k: jet.Kernel)
function Kernel:term_create(callback)
self:start_lua_client(function()
- if not self.term then
+ if not self.bufs.term then
assert(self.session_id, "Kernel has no session id")
- self.term = require("jet.core.kernel.term").init({ kernel = self, ns = jet_hl_ns })
- self.term:create_autocmd("TermEnter", function() self:set_current() end)
+ self.bufs.term = require("jet.core.kernel.term").init({ kernel = self })
+ self.bufs.term:create_autocmd("TermEnter", function() self:set_current() end)
if cfg.stop_on_buf_wipeout then
- self.term:create_autocmd("BufWipeout", function() self:close("BufWipeout") end)
+ self.bufs.term:create_autocmd("BufWipeout", function() self:close("BufWipeout") end)
end
end
if callback then
@@ -389,8 +441,8 @@ function Kernel:update_execution_state(msg)
self.last_execution.end_time = os.time()
end
- if self.term and self.term.buf and vim.api.nvim_buf_is_valid(self.term.buf) then
- vim.api.nvim__redraw({ statusline = true, buf = self.term.buf })
+ if self.bufs.term and self.bufs.term.buf and vim.api.nvim_buf_is_valid(self.bufs.term.buf) then
+ vim.api.nvim__redraw({ statusline = true, buf = self.bufs.term.buf })
end
self:do_execution_state_changed(new_state)
@@ -406,8 +458,8 @@ end
---Toggle the image display
function Kernel:img_toggle()
- if self.img then
- self.img:toggle()
+ if self.bufs.img then
+ self.bufs.img:toggle()
else
self:img_open()
end
@@ -417,11 +469,11 @@ end
---@param which? string | integer
---@return integer # Win number
function Kernel:img_open(which)
- if not self.img then
+ if not self.bufs.img then
assert(self.session_id, "Kernel has no session id")
- self.img = require("jet.core.kernel.img").init({ kernel = self, ns = jet_hl_ns })
+ self.bufs.img = require("jet.core.kernel.img").init({ kernel = self })
end
- return self.img:open(false, which)
+ return self.bufs.img:open(false, which)
end
---Get a unique, human-readable name for the kernel
@@ -754,8 +806,8 @@ function Kernel:close(reason)
if self.augroup then
pcall(vim.api.nvim_del_augroup_by_id, self.augroup)
end
- if self.term then
- self.term:delete()
+ if self.bufs.term then
+ self.bufs.term:delete()
end
if self.owned then
@@ -806,6 +858,19 @@ end
---@field listener_interval? integer In milliseconds, default 50ms
---@field callback? fun(msg: jupyter.Msg)
+---Convenience; find a comm id (from `Kernel.open_comms`) using the comm name
+---@param name string
+---@param pattern boolean?
+---@return string?, table?
+function Kernel:get_comm(name, pattern)
+ for comm_id, comm in pairs(self.open_comms) do
+ local is_match = pattern and comm.name:match(name) or comm.name == name
+ if is_match then
+ return comm_id, comm.data
+ end
+ end
+end
+
---Open a comm channel to the kernel
---
---Kernels may implement custom messages using comm channels. This function
@@ -880,7 +945,7 @@ end
---@param code string | string[] Code to be sent
---@param tabstop? integer Optional; number of spaces to use for tab characters
function Kernel:send_repl(code, tabstop)
- self:term_open(function(t) t:send(code, tabstop) end)
+ self:term_open(function(t) t:send(code, tabstop) end, false)
end
---Send code to the kernel via the Lua client
diff --git a/lua/jet/core/kernel/term.lua b/lua/jet/core/kernel/term.lua
index ad2c79e..fd45859 100644
--- a/lua/jet/core/kernel/term.lua
+++ b/lua/jet/core/kernel/term.lua
@@ -9,7 +9,6 @@ Term.__index = Term ---@private
---@class jet.Kernel.Term.init.Opts
---@field kernel jet.Kernel
----@field ns integer
---@param opts jet.Kernel.Term.init.Opts
---@return jet.Kernel.Term
@@ -18,16 +17,8 @@ function Term.init(opts)
local out = buf.init(Term, {
name = opts.kernel:friendly_name(),
- ns = opts.ns,
kernel = opts.kernel,
- open_opts = function()
- local img_win = opts.kernel.img and opts.kernel.img:win()
- return {
- split = img_win and "below" or "right",
- win = img_win or -1,
- style = "minimal",
- }
- end,
+ win_name = "primary",
})
out.kernel = opts.kernel
@@ -68,7 +59,7 @@ end
function Term:send(code, tabstop)
tabstop = tabstop or vim.bo.tabstop or 4
if type(code) == "string" then
- code = vim.split(code, "[\n\r]", { plain = false })
+ code = vim.split(code, "[\n\r]", { plain = false }) --[[@as string[] ]]
end
-- Remove trailing empty lines
diff --git a/lua/jet/core/kernel/win.lua b/lua/jet/core/kernel/win.lua
new file mode 100644
index 0000000..9543312
--- /dev/null
+++ b/lua/jet/core/kernel/win.lua
@@ -0,0 +1,155 @@
+---@class jet.Win
+---@field private win integer
+---@field ns integer
+---If `true` then `Win:open()` will focus an already open window, otherwise
+---it's a no-op.
+---@field focus boolean
+---@field kernel jet.Kernel
+---@field open_opts? vim.api.keyset.win_config | fun(k: jet.Kernel): vim.api.keyset.win_config
+local Win = {}
+Win.__index = Win
+
+---@param buf integer | jet.Buf
+local to_bufnr = function(buf) return type(buf) == "number" and buf or buf.buf end
+
+---@class jet.Win.init.Opts
+---@field kernel jet.Win["kernel"]
+---@field open_opts jet.Win["open_opts"]
+---@field focus jet.Win["focus"]
+
+---@param opts jet.Win.init.Opts
+Win.init = function(opts)
+ if opts.focus == nil then
+ opts.focus = false
+ end
+ local ns = vim.api.nvim_create_namespace("jet_highlights")
+ return setmetatable(vim.tbl_extend("force", opts, { win = -99, ns = ns }), Win)
+end
+
+---@return string
+function Win:name()
+ for name, w in pairs(self.kernel.wins) do
+ if w == self then
+ return name
+ end
+ end
+ error("Could not determine the window name")
+end
+
+---Opens with the following algorithm
+---
+---* If the window is not open, opens with `buf`
+---* If the window is open with `buf`, focus the window (if `Win.focus`)
+---* Otherwise, if the window is open with another buffer:
+--- * Does the buffer have `vim.b.jet` set? If so, show `buf` in the window
+--- * Otherwise, open a fresh window, resetting `self.win`.
+---
+---@param buf integer
+---@param opts vim.api.keyset.win_config?
+---@param focus? boolean
+---@return integer
+function Win:open(buf, opts, focus)
+ if focus == nil then
+ focus = self.focus
+ end
+
+ local curr_jet_buf = self:get_curr_jet_buf()
+
+ if curr_jet_buf == buf then
+ if focus then
+ vim.api.nvim_set_current_win(self.win)
+ if vim.bo[buf].buftype == "terminal" then
+ vim.cmd.startinsert()
+ end
+ end
+ return self.win
+ end
+
+ local bufnr = to_bufnr(buf)
+
+ if curr_jet_buf and vim.api.nvim_win_is_valid(self.win) then
+ vim.api.nvim_win_set_buf(self.win, bufnr)
+ else
+ self.win = vim.api.nvim_open_win(bufnr, false, opts or self:make_open_opts())
+ require("jet.core.hooks").do_win_open(self.kernel, self, buf)
+ end
+
+ vim.api.nvim_win_set_hl_ns(self.win, self.ns)
+
+ if vim.bo[bufnr].buftype == "terminal" then
+ -- When the cursor is at the bottom of the REPL you get auto-scroll
+ -- when new lines appear. This is a good state to start in.
+ vim.api.nvim_win_set_cursor(self.win, { vim.api.nvim_buf_line_count(bufnr), 0 })
+ end
+
+ return self.win
+end
+
+---@private
+---@return vim.api.keyset.win_config
+function Win:make_open_opts()
+ if type(self.open_opts) == "function" then
+ local out = self.open_opts(self.kernel)
+ out.style = "minimal"
+ return out
+ elseif type(self.open_opts) == "table" then
+ local out = self.open_opts
+ out.style = "minimal"
+ return out
+ else
+ return {
+ style = "minimal",
+ split = "right",
+ win = -1,
+ }
+ end
+end
+
+---@param buf? integer
+function Win:close(buf)
+ if self:get_curr_jet_buf(buf) and vim.api.nvim_win_is_valid(self.win) then
+ vim.api.nvim_win_close(self.win, true)
+ end
+end
+
+---@param buf integer
+function Win:toggle(buf)
+ if self:get_curr_jet_buf(buf) then
+ self:close(buf)
+ else
+ self:open(buf)
+ end
+end
+
+---@param buf? integer
+---@return integer?
+function Win:get_curr_jet_buf(buf)
+ local curr_buf = self:get_buf()
+ if not curr_buf then
+ return nil
+ end
+ if buf and buf ~= curr_buf then
+ return nil
+ end
+ for _, k_buf in pairs(self.kernel.bufs) do
+ if k_buf.buf == curr_buf and k_buf.win_name == self:name() then
+ return curr_buf
+ end
+ end
+end
+
+---@param buf? integer
+function Win:winnr(buf)
+ if self:get_curr_jet_buf(buf) then
+ return self.win
+ end
+end
+
+---@return integer?
+function Win:get_buf()
+ if vim.api.nvim_win_is_valid(self.win) then
+ return vim.api.nvim_win_get_buf(self.win)
+ end
+end
+
+return Win
diff --git a/lua/jet/core/manager.lua b/lua/jet/core/manager.lua
index d78c276..23acb16 100644
--- a/lua/jet/core/manager.lua
+++ b/lua/jet/core/manager.lua
@@ -97,7 +97,7 @@ Manager.filter_kernels = function(kernels, filters)
return false
end
- if filters.spec_path and k.spec_path ~= filters.spec_path then
+ if filters.spec_path and utils.path_normalise(k.spec_path) ~= utils.path_normalise(filters.spec_path) then
return false
end
diff --git a/lua/jet/core/ui/colours.lua b/lua/jet/core/ui/colours.lua
index 104f92b..42fff90 100644
--- a/lua/jet/core/ui/colours.lua
+++ b/lua/jet/core/ui/colours.lua
@@ -17,7 +17,7 @@ M.colours = {
JetIdle = { link = "DiagnosticOk" },
JetItalic = { italic = true },
JetLabel = { link = "@label" },
- JetRepl = { link = "NormalFloat" },
+ JetNormal = { link = "NormalFloat" },
JetSpecial = { link = "@punctuation.special" },
JetSuccess = { link = "DiagnosticOk" },
JetUrl = { link = "@markup.link" },
@@ -39,6 +39,9 @@ M.setup = function()
return
end
+ local jet_hl_ns = vim.api.nvim_create_namespace("jet_highlights")
+ vim.api.nvim_set_hl(jet_hl_ns, "Normal", { link = "JetNormal" })
+
M.did_setup = true
M.set_highlights()
diff --git a/lua/jet/core/ui/init.lua b/lua/jet/core/ui/init.lua
index d4ef01a..34857fc 100644
--- a/lua/jet/core/ui/init.lua
+++ b/lua/jet/core/ui/init.lua
@@ -477,7 +477,7 @@ M.show = function()
if l and l.data and l.data.kernel then
---@type jet.Kernel
local k = l.data.kernel
- local should_focus = k.term and k.term:win()
+ local should_focus = k.bufs.term and k.bufs.term:win():winnr()
k:term_open(function()
if should_focus then
ui:close()
diff --git a/lua/jet/core/ui/line.lua b/lua/jet/core/ui/line.lua
index 8c3e7a9..c84057d 100644
--- a/lua/jet/core/ui/line.lua
+++ b/lua/jet/core/ui/line.lua
@@ -52,7 +52,7 @@ function Line:resolve()
---@return vim.api.keyset.set_extmark[]
local to_extmarks = function(x)
x = type(x) == "table" and vim.isarray(x) and x or { x } ---@type string[] | vim.api.keyset.set_extmark[]
- return vim.tbl_map(function(xi) return type(xi) == "string" and { hl_group = xi } or xi end, x)
+ return vim.tbl_map(function(xi) return type(xi) == "string" and { hl_group = xi } or xi end, x) --[[@as vim.api.keyset.set_extmark[] ]]
end
for _, part in ipairs(self.parts) do
diff --git a/lua/lualine/extensions/jet.lua b/lua/lualine/extensions/jet.lua
index 2c62979..1c2712d 100644
--- a/lua/lualine/extensions/jet.lua
+++ b/lua/lualine/extensions/jet.lua
@@ -41,11 +41,11 @@ end
---@param k jet.Kernel
local jet_img = function(k)
- if not k.img then
+ if not k.bufs.img then
return ""
end
- local files, curr_file_index = k.img:list_files()
+ local files, curr_file_index = k.bufs.img:list_files()
if not curr_file_index then
return ""
diff --git a/scripts/emmylua-to-md.py b/scripts/emmylua-to-md.py
index c65d9e7..55ddba5 100644
--- a/scripts/emmylua-to-md.py
+++ b/scripts/emmylua-to-md.py
@@ -254,7 +254,7 @@ def _render_tags(tags: list[Tag] | None) -> list[str]:
return [line for block in tag_blocks for line in block]
-def _render_fn(doc: Doc, x: Fn, parent=None):
+def _render_fn(doc: Doc, x: Fn, parent=None, always_inline: list[str] | None = None):
sep = ":" if x.is_meth else "."
name = x.name if parent is None else f"{parent}{sep}{x.name}"
params = ", ".join([f"{{{param.name}}}" for param in x.params])
@@ -271,7 +271,7 @@ def _render_fn(doc: Doc, x: Fn, parent=None):
f"{{{param.name}}}",
f": (`{param.typ or 'any'}`)",
*([] if param.desc is None else [param.desc]),
- *_render_opts_fields(doc, param.typ),
+ *_inline_type(doc, param.typ, always_inline),
"",
]
for param in x.params
@@ -303,11 +303,15 @@ def _render_fn(doc: Doc, x: Fn, parent=None):
)
-def _render_opts_fields(doc: Doc, which: str | None, indent=2) -> list[str]:
+def _inline_type(
+ doc: Doc, which: str | None, force: list[str] | None = None, indent=2
+) -> list[str]:
if which is not None and which.endswith("?"):
which = which[0:-1]
- if which is None or not which.endswith("Opts") or indent > 8:
+ force = force or []
+
+ if which is None or indent > 8 or not (which in force or which.endswith("Opts")):
return []
x = _get_type(doc, which)
@@ -321,7 +325,7 @@ def render_one(item: Field | Fn) -> list[str]:
return [
f"{ind}* {item.name} (`{item.typ}`)"
+ ("" if item.description is None else f": {item.description}"),
- *_render_opts_fields(doc, item.typ, indent + 2),
+ *_inline_type(doc, item.typ, force, indent + 2),
]
elif type(item) is Fn:
return [f"{ind}* {item.name} (function): {item.description}"]
@@ -329,10 +333,10 @@ def render_one(item: Field | Fn) -> list[str]:
raise ValueError("Value is not a Field or Fn")
fields = [line for f in x.members for line in render_one(f)]
- return ["", *fields]
+ return [f"{ind}Fields:", *fields]
-def _render_class(x: Class | Module, doc: Doc):
+def _render_class(x: Class | Module, doc: Doc, always_inline: list[str] | None = None):
fields = [
[
f"{{{field.name}}}",
@@ -342,7 +346,7 @@ def _render_class(x: Class | Module, doc: Doc):
if field.description is None or field.description == ""
else [" " + line for line in field.description.split("\n")] + [""]
),
- *_render_opts_fields(doc, field.typ),
+ *_inline_type(doc, field.typ, always_inline),
"",
]
for field in x.members
@@ -387,6 +391,7 @@ def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--type", help="Type to render", required=False)
parser.add_argument("--mod", help="Module to render", required=False)
+ parser.add_argument("--inline", help="Elements to expand 'inline'", required=False)
args = parser.parse_args()
with open("emmylua_doc_cli/doc.json") as f:
@@ -394,16 +399,21 @@ def main() -> int:
doc = parse(raw)
+ inline = args.inline
+
+ if args.inline is not None:
+ inline = inline.split(",")
+
if args.type:
emmylua_type = _get_type(doc, args.type)
if emmylua_type is not None:
- print("\n".join(_render_class(emmylua_type, doc)))
+ print("\n".join(_render_class(emmylua_type, doc, inline)))
return 0
if args.mod:
emmylua_mod = _get_mod(doc, args.mod)
if emmylua_mod is not None:
- print("\n".join(_render_class(emmylua_mod, doc)))
+ print("\n".join(_render_class(emmylua_mod, doc, inline)))
return 0
print("No emmylua docs found")
diff --git a/tests/test_image.lua b/tests/test_image.lua
index 5751314..0677cc2 100644
--- a/tests/test_image.lua
+++ b/tests/test_image.lua
@@ -11,11 +11,10 @@ local T = new_set({
require("jet.core.config").options.hooks.on_image_display_pre.test = function(k, src)
_G.rendered_image = src
- _G.image_buf = k.img.buf
+ _G.image_buf = k.bufs.img.buf
end
_G.k:start_lua_client(function(k)
- _G.bla = 123
k:send_lua("hist(iris$Sepal.Width)")
end)
]])
@@ -25,7 +24,7 @@ local T = new_set({
})
T["Image files are produced"] = function()
- vim.wait(5000, function() return child.lua_get("_G.rendered_image") ~= vim.NIL end)
+ vim.wait(10000, function() return child.lua_get("_G.rendered_image") ~= vim.NIL end)
local file = child.lua_get("_G.rendered_image")
file = file ~= vim.NIL and file or nil
assert(file, "No image was produced by the kernel")
diff --git a/tests/test_send_repl.lua b/tests/test_send_repl.lua
index 719e4e2..14f8d73 100644
--- a/tests/test_send_repl.lua
+++ b/tests/test_send_repl.lua
@@ -22,8 +22,8 @@ local run_send = function()
]])
local TERM_TEXT = [[
- _G.kernel and _G.kernel.term
- and table.concat(vim.api.nvim_buf_get_lines(_G.kernel.term.buf, 0, -1, false), "\n")
+ _G.kernel and _G.kernel.bufs.term
+ and table.concat(vim.api.nvim_buf_get_lines(_G.kernel.bufs.term.buf, 0, -1, false), "\n")
or ""
]]