feat(view): position cursor at name column on new empty lines
Problem: pressing `o`/`O` in a canola buffer placed the cursor at column 0, requiring manual navigation past concealed ID prefixes and column text (icons, permissions) to reach the name column. Solution: add `show_insert_guide()` which temporarily sets `virtualedit=all` on empty lines and positions the cursor at the name column. Computes the correct virtual column by measuring the visible column prefix width via `nvim_strwidth`, adjusting for `conceallevel` (0=full ID width, 1=replacement char, 2/3=hidden). Restores `virtualedit` on `TextChangedI` or `InsertLeave`.
This commit is contained in:
parent
c3de0004d1
commit
022e92c4b4
1 changed files with 92 additions and 1 deletions
|
|
@ -340,6 +340,84 @@ local function constrain_cursor(bufnr, mode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param bufnr integer
|
||||||
|
local function show_insert_guide(bufnr)
|
||||||
|
if not config.constrain_cursor then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if bufnr ~= vim.api.nvim_get_current_buf() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local adapter = util.get_adapter(bufnr, true)
|
||||||
|
if not adapter then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local cur = vim.api.nvim_win_get_cursor(0)
|
||||||
|
local current_line = vim.api.nvim_buf_get_lines(bufnr, cur[1] - 1, cur[1], true)[1]
|
||||||
|
if current_line ~= '' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local all_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
|
||||||
|
local ref_line
|
||||||
|
if cur[1] > 1 and all_lines[cur[1] - 1] ~= '' then
|
||||||
|
ref_line = all_lines[cur[1] - 1]
|
||||||
|
elseif cur[1] < #all_lines and all_lines[cur[1] + 1] ~= '' then
|
||||||
|
ref_line = all_lines[cur[1] + 1]
|
||||||
|
else
|
||||||
|
for i, line in ipairs(all_lines) do
|
||||||
|
if line ~= '' and i ~= cur[1] then
|
||||||
|
ref_line = line
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not ref_line then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local parser = require('canola.mutator.parser')
|
||||||
|
local column_defs = columns.get_supported_columns(adapter)
|
||||||
|
local result = parser.parse_line(adapter, ref_line, column_defs)
|
||||||
|
if not result or not result.ranges then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local id_end = result.ranges.id[2] + 1
|
||||||
|
local col_prefix = ref_line:sub(id_end + 1, result.ranges.name[1])
|
||||||
|
local col_width = vim.api.nvim_strwidth(col_prefix)
|
||||||
|
local id_width
|
||||||
|
local cole = vim.wo.conceallevel
|
||||||
|
if cole >= 2 then
|
||||||
|
id_width = 0
|
||||||
|
elseif cole == 1 then
|
||||||
|
id_width = 1
|
||||||
|
else
|
||||||
|
id_width = vim.api.nvim_strwidth(ref_line:sub(1, id_end))
|
||||||
|
end
|
||||||
|
local virtual_col = id_width + col_width
|
||||||
|
if virtual_col <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.w.canola_saved_ve = vim.wo.virtualedit
|
||||||
|
vim.wo.virtualedit = 'all'
|
||||||
|
vim.api.nvim_win_set_cursor(0, { cur[1], virtual_col })
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd('TextChangedI', {
|
||||||
|
group = 'Canola',
|
||||||
|
buffer = bufnr,
|
||||||
|
once = true,
|
||||||
|
callback = function()
|
||||||
|
if vim.w.canola_saved_ve ~= nil then
|
||||||
|
vim.wo.virtualedit = vim.w.canola_saved_ve
|
||||||
|
vim.w.canola_saved_ve = nil
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
---Redraw original path virtual text for trash buffer
|
---Redraw original path virtual text for trash buffer
|
||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
local function redraw_trash_virtual_text(bufnr)
|
local function redraw_trash_virtual_text(bufnr)
|
||||||
|
|
@ -458,7 +536,20 @@ M.initialize = function(bufnr)
|
||||||
callback = function()
|
callback = function()
|
||||||
-- For some reason the cursor bounces back to its original position,
|
-- For some reason the cursor bounces back to its original position,
|
||||||
-- so we have to defer the call
|
-- so we have to defer the call
|
||||||
vim.schedule_wrap(constrain_cursor)(bufnr, config.constrain_cursor)
|
vim.schedule(function()
|
||||||
|
constrain_cursor(bufnr, config.constrain_cursor)
|
||||||
|
show_insert_guide(bufnr)
|
||||||
|
end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
vim.api.nvim_create_autocmd('InsertLeave', {
|
||||||
|
group = 'Canola',
|
||||||
|
buffer = bufnr,
|
||||||
|
callback = function()
|
||||||
|
if vim.w.canola_saved_ve ~= nil then
|
||||||
|
vim.wo.virtualedit = vim.w.canola_saved_ve
|
||||||
|
vim.w.canola_saved_ve = nil
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
vim.api.nvim_create_autocmd({ 'CursorMoved', 'ModeChanged' }, {
|
vim.api.nvim_create_autocmd({ 'CursorMoved', 'ModeChanged' }, {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue