Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ require("flix").setup({
java = "java", -- executable used to launch the jar
jar = "flix.jar", -- relative paths resolve from the project root
root_markers = { "flix.toml" },
terminal = { -- how `flix_cmd` opens its terminal
window = "split", -- "split" (default) or "float" (floating window)
width = 0.60, -- float = fraction of editor, integer = columns
height = 0.5, -- float = fraction of editor, integer = rows
pos_x = "center", -- number or "center" (float = fraction of width)
pos_y = "center", -- number or "center" (float = fraction of height)
close_binding = "q", -- Normal-mode key that closes the floating window
},
features = {
codelens = true, -- refresh code lenses while editing
completion = false, -- native autocompletion (see below)
Expand All @@ -78,6 +86,14 @@ require("flix").setup({
})
```

### Floating terminal

By default `flix_cmd` opens in a `belowright split`. Set `terminal.window = "float"`
to open it in a floating window instead. The remaining `terminal` fields only
apply to the float: `width`/`height` accept a fraction of the editor size (e.g.
`0.5`) or an integer column/row count, `pos_x`/`pos_y` accept a number or
`"center"`, and `close_binding` (default `q`) closes the window from Normal mode.

### Native completion (Neovim 0.11+)

Set `features.completion = true` to get insert-mode autocompletion straight from
Expand Down
63 changes: 60 additions & 3 deletions lua/flix/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,36 @@ local config = require("flix.config")

local M = {}

--- resolve a size spec to an integer number of cells
--- a whole number is used as-is (columns/rows); a fractional value is a fraction of `total`
--- @param spec number
--- @param total integer
--- @return integer
local function resolve_size(spec, total)
if spec % 1 ~= 0 then
return math.max(1, math.floor(spec * total))
end
return spec
end

--- resolve a position spec to an integer cell offset
--- "center" centers a window of `size` cells within `total`;
--- a whole number is used as-is; a fractional value is a fraction of `total`
--- @param spec number|string
--- @param total integer
--- @param size integer
--- @return integer
local function resolve_pos(spec, total, size)
if spec == "center" then
return math.floor((total - size) / 2)
end
if type(spec) == "number" and spec % 1 ~= 0 then
return math.floor(spec * total)
end
---@diagnostic disable-next-line: return-type-mismatch
return spec
end

--- run `java -jar <jar> <cmd>` from the Flix project root in a terminal split
--- works without the LSP being attached: the root is found from `root_markers`
---@param cmd string the Flix CLI subcommand, e.g. "run" or "test"
Expand All @@ -28,9 +58,36 @@ function M.flix_cmd(cmd)
return
end

vim.cmd("belowright split")
local term_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(0, term_buf)
local t = o.terminal

if t.window == "float" then
local term_buf = vim.api.nvim_create_buf(false, true)

local total_cols = vim.o.columns
local total_rows = vim.o.lines

local width = resolve_size(t.width, total_cols)
local height = resolve_size(t.height, total_rows)
local col = resolve_pos(t.pos_x, total_cols, width)
local row = resolve_pos(t.pos_y, total_rows, height)

vim.api.nvim_open_win(term_buf, true, {
relative = "win",
width = width,
height = height,
row = row,
col = col,
title = "Flix Run",
title_pos = "center",
border = "single"
})

vim.keymap.set("n", t.close_binding, "<Cmd>bdelete!<CR>", { buffer = term_buf, silent = true })
else
vim.cmd("belowright split")
local term_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(0, term_buf)
end

vim.fn.jobstart({ o.java, "-jar", jar, cmd }, {
term = true,
Expand Down
26 changes: 26 additions & 0 deletions lua/flix/config.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
local M = {}

---@class flix.TerminalOptions
---@field window "float"|"split" how the terminal is opened
---@field width number integer = columns; float in (0,1) = fraction of editor width
---@field height number integer = rows; float in (0,1) = fraction of editor height
---@field pos_x number|"center" integer = columns from left; float = fraction of editor width; "center" = centered on x
---@field pos_y number|"center" integer = rows from top; float = fraction of editor height; "center" = centered on y
---@field close_binding string Normal-mode key that closes the terminal window

---@class flix.Config
---@field java string path or name of the java executable
---@field jar string path to flix.jar, relative to the project root or absolute
---@field root_markers string[] files used to detect the project root
---@field terminal flix.TerminalOptions options for the floating terminal window
---@field features table feature flags
---@field lsp table options forwarded to `vim.lsp.config("flix", ...)`

-- default configuration
-- override any field via `require("flix").setup({ ... })`
---@type flix.Config
M.defaults = {
java = "java",
jar = "flix.jar",
root_markers = { "flix.toml" },
terminal = {
window = "split",
width = 0.60,
height = 0.5,
pos_x = "center",
pos_y = "center",
close_binding = "q"
},
features = {
codelens = true,
completion = false,
Expand All @@ -14,6 +39,7 @@ M.defaults = {
}

-- active configuration
---@type flix.Config
M.options = vim.deepcopy(M.defaults)

--- merge user options over the defaults
Expand Down