Skip to content
Merged
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
5 changes: 4 additions & 1 deletion docs/codeactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ Behavior:
- actions within each client group keep server response order
- group headers are rendered as plain section rows
- selection index/count is shown in the float border footer (right-aligned)
- keymaps: `j`/`k`, `<Down>`/`<Up>`, `<Tab>`/`<S-Tab>`, `<CR>`/`<Space>`, `<Esc>`/`<C-c>`
- key hints (`Enter:apply q:close`) are rendered as an in-buffer footer row
- the menu opens below the cursor and flips above it when there is not enough
screen space below
- keymaps: `j`/`k`, `<Down>`/`<Up>`, `<Tab>`/`<S-Tab>`, `<CR>`/`<Space>`, `<Esc>`/`<C-c>`/`q`

```lua
require("cosmic-ui").codeactions.open()
Expand Down
13 changes: 13 additions & 0 deletions docs/formatters.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ All methods below:
Opens the formatter toggle UI.
Opts: `OpenOpts`.

Panel keymaps:

- `j`/`k`, `<Down>`/`<Up>`, `<Tab>`/`<S-Tab>`: move the selection
- `<CR>`/`<Space>`: toggle the selected formatter
- `a`: toggle all formatters
- `s`: switch scope (`buffer`/`global`)
- `r`: reset overrides for the current scope
- `f`: close the panel and format the target buffer
- `q`/`<Esc>`: close the panel

When the formatter list is taller than the panel, the selection scrolls the
panel; every row stays reachable.

### `require("cosmic-ui").formatters.toggle(opts?)`

Toggles backend state (`lsp`/`conform`) for selected scope.
Expand Down
6 changes: 3 additions & 3 deletions docs/rename.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Rename input options.
| `default_value` | `string\|nil` | No | current word | Initial value in rename input. |
| `on_submit` | `function\|nil` | No | built-in rename submit | Callback executed when user submits value. |
| `window` | `table\|nil` | No | internal defaults + rename config | Native float window overrides. |
| `window.relative` | `string\|nil` | No | `"cursor"` | Float anchor mode. |
| `window.row` | `integer\|nil` | No | `1` | Float row offset. |
| `window.col` | `integer\|nil` | No | `0` | Float column offset. |
| `window.relative` | `string\|nil` | No | auto (cursor position) | Float anchor mode. When `relative`/`anchor`/`row`/`col` are all omitted, the prompt opens below the cursor and flips above it when there is not enough screen space below. |
| `window.row` | `integer\|nil` | No | auto | Float row offset (disables auto flip placement when set). |
| `window.col` | `integer\|nil` | No | auto | Float column offset (disables auto flip placement when set). |
| `window.width` | `integer\|nil` | No | auto-fit prompt + symbol | Float width. |
| `window.height` | `integer\|nil` | No | auto-fit single prompt line (`1`) | Float height. |
| `window.zindex` | `integer\|nil` | No | `50` | Float z-index. |
Expand Down
22 changes: 17 additions & 5 deletions lua/cosmic-ui/codeactions/ui/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ local function dismiss_current()
end

local function build_panel_model(built)
local footer = { 'q:close' }
if #built.actions > 0 then
footer = { 'Enter:apply', 'q:close' }
end

return panel.prepare({
rows = built.rows,
selected = (#built.actions > 0) and 1 or nil,
footer = footer,
})
end

Expand Down Expand Up @@ -120,6 +126,9 @@ M.open = function(results_lsp, user_opts)
border = border_style,
})

local placement = window.cursor_placement()
local placed = window.cursor_float_config(placement, initial_width, initial_height, { border = border_style })

local buf = window.create_scratch_buf({
filetype = 'cosmicui-codeactions',
modifiable = false,
Expand All @@ -130,11 +139,12 @@ M.open = function(results_lsp, user_opts)
end

local win = window.open_float(buf, {
relative = 'cursor',
row = 1,
col = 0,
width = initial_width,
height = initial_height,
relative = placed.relative,
anchor = placed.anchor,
row = placed.row,
col = placed.col,
width = placed.width,
height = placed.height,
border = border_style,
title = border.title,
title_pos = border.title_align,
Expand All @@ -152,6 +162,8 @@ M.open = function(results_lsp, user_opts)
win = win,
selected = (#built.actions > 0) and 1 or nil,
border = border,
origin_win = origin_win,
placement = placement,
ns = lifecycle.ensure_namespace(),
}
apply_model(ui, built, user_opts, request_state, origin_win)
Expand Down
1 change: 1 addition & 0 deletions lua/cosmic-ui/codeactions/ui/input.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ M.set_keymaps = function(ui, handlers, deps)

map('n', '<Esc>', dismiss)
map('n', '<C-c>', dismiss)
map('n', 'q', dismiss)
end

return M
26 changes: 21 additions & 5 deletions lua/cosmic-ui/codeactions/ui/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,27 @@ M.render = function(ui)
local highlights = prepared.highlights

if ui.win and vim.api.nvim_win_is_valid(ui.win) then
local cfg = vim.api.nvim_win_get_config(ui.win)
cfg.width = width
cfg.height = height
cfg.title = ui.border and ui.border.title or nil
cfg.title_pos = ui.border and ui.border.title_align or nil
local cfg = {
width = width,
height = height,
title = ui.border and ui.border.title or nil,
title_pos = ui.border and ui.border.title_align or nil,
}

if ui.placement then
local border = ui.border and ui.border.style
if border == nil then
border = vim.o.winborder
end

local placed = window.cursor_float_config(ui.placement, width, height, { border = border })
cfg.relative = placed.relative
cfg.anchor = placed.anchor
cfg.row = placed.row
cfg.col = placed.col
cfg.height = placed.height
end

vim.api.nvim_win_set_config(ui.win, cfg)
end

Expand Down
14 changes: 11 additions & 3 deletions lua/cosmic-ui/formatters/ui/input.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local M = {}

M.footer_entries = function()
return {
'Tab:toggle',
'Enter:toggle',
's:scope',
'r:reset',
'a:toggle all',
Expand Down Expand Up @@ -121,15 +121,24 @@ M.set_keymaps = function(ui, handlers, deps)
map('<Down>', function()
move_selection(ui, 1, handlers, deps)
end)
map('<Tab>', function()
move_selection(ui, 1, handlers, deps)
end)

map('k', function()
move_selection(ui, -1, handlers, deps)
end)
map('<Up>', function()
move_selection(ui, -1, handlers, deps)
end)
map('<S-Tab>', function()
move_selection(ui, -1, handlers, deps)
end)

map('<Tab>', function()
map('<CR>', function()
toggle_row(ui, handlers, deps)
end)
map('<Space>', function()
toggle_row(ui, handlers, deps)
end)

Expand All @@ -154,7 +163,6 @@ M.set_keymaps = function(ui, handlers, deps)
handlers.format_async_fn({ scope = scope, bufnr = target_bufnr })
end)

map('<CR>', deps.close_fn)
map('<Esc>', deps.close_fn)
map('q', deps.close_fn)
end
Expand Down
21 changes: 0 additions & 21 deletions lua/cosmic-ui/formatters/ui/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,27 +154,6 @@ M.render = function(ui, handlers, deps)

local size = deps.constants.panel_size
local border = window.resolve_border()
local _, max_height = window.fit_float_size(1, vim.o.lines, {
height_ratio = size.height_ratio,
border = border,
})
if #lines > max_height then
lines = vim.list_slice(lines, 1, max_height)
lines[#lines] = '...'

local visible_rows = {}
for _, row in ipairs(rows) do
if row.lnum < max_height then
table.insert(visible_rows, row)
end
end
rows = visible_rows

if ui.footer_lnum and ui.footer_lnum >= #lines then
ui.footer_lnum = nil
ui.footer_spans = nil
end
end

ui.rows = rows
M.ensure_selection(ui)
Expand Down
29 changes: 23 additions & 6 deletions lua/cosmic-ui/rename/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ local function render(ui, value)
if ui.win and vim.api.nvim_win_is_valid(ui.win) then
local height
width, height = window.fit_float_size(width, ui.fixed_height or #lines, { border = ui.border })
local cfg = vim.api.nvim_win_get_config(ui.win)
cfg.width = width
cfg.height = height
vim.api.nvim_win_set_config(ui.win, cfg)
vim.api.nvim_win_set_config(ui.win, { width = width, height = height })
end

local was_modifiable = vim.bo[ui.buf].modifiable
Expand Down Expand Up @@ -226,7 +223,8 @@ M.open = function(opts)
math.max(1, merged_window_opts.height or 5),
{ border = border.style }
)
local win = window.open_float(buf, {

local float_config = {
relative = merged_window_opts.relative,
row = merged_window_opts.row,
col = merged_window_opts.col,
Expand All @@ -236,7 +234,26 @@ M.open = function(opts)
border = border.style,
title = border.title,
title_pos = border.title_align,
})
}

local position_override = opts.window or {}
if
position_override.relative == nil
and position_override.anchor == nil
and position_override.row == nil
and position_override.col == nil
then
local prompt_height = math.max(1, position_override.height or 1)
local placed =
window.cursor_float_config(window.cursor_placement(), initial_width, prompt_height, { border = border.style })
float_config.relative = placed.relative
float_config.anchor = placed.anchor
float_config.row = placed.row
float_config.col = placed.col
float_config.height = placed.height
end

local win = window.open_float(buf, float_config)
if not win then
window.safe_delete_buf(buf, { force = true })
return
Expand Down
55 changes: 55 additions & 0 deletions lua/cosmic-ui/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,61 @@ M.centered_float_config = function(width, height, opts)
}
end

M.cursor_placement = function()
local win_row, win_col = 0, 0
local ok_pos, pos = pcall(vim.api.nvim_win_get_position, 0)
if ok_pos and type(pos) == 'table' then
win_row = pos[1] or 0
win_col = pos[2] or 0
end

local ok_line, cursor_line = pcall(vim.fn.winline)
local ok_col, cursor_col = pcall(vim.fn.wincol)
if not (ok_line and type(cursor_line) == 'number' and cursor_line >= 1) then
cursor_line = 1
end
if not (ok_col and type(cursor_col) == 'number' and cursor_col >= 1) then
cursor_col = 1
end

local screen_row = win_row + cursor_line
local screen_col = win_col + cursor_col
local usable_height = math.max(1, vim.o.lines - vim.o.cmdheight)

return {
row = screen_row - 1,
col = screen_col - 1,
above = math.max(0, screen_row - 1),
below = math.max(0, usable_height - screen_row),
}
end

M.cursor_float_config = function(placement, width, height, opts)
opts = opts or {}
local border = border_extent(opts.border)
local flip = height + border > placement.below and placement.above > placement.below
local side_height = math.max(1, (flip and placement.above or placement.below) - border)
height = math.max(1, math.min(height, side_height))
local col = math.max(0, math.min(placement.col, vim.o.columns - width - border))

local config = {
relative = 'editor',
width = width,
height = height,
col = col,
}

if flip then
config.anchor = 'SW'
config.row = placement.row
else
config.anchor = 'NW'
config.row = placement.row + 1
end

return config
end

M.resolve_border = function(style)
if style == nil then
style = vim.o.winborder
Expand Down
Loading
Loading