range: add extmark utilities
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m22s
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m22s
This commit is contained in:
parent
6f86bfaa42
commit
859187585b
@ -1,6 +1,13 @@
|
|||||||
local Pos = require 'u.pos'
|
local Pos = require 'u.pos'
|
||||||
|
|
||||||
local ESC = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
local ESC = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
||||||
|
local NS = vim.api.nvim_create_namespace 'u.range'
|
||||||
|
|
||||||
|
---@class u.ExtmarkRange
|
||||||
|
---@field bufnr number
|
||||||
|
---@field id number
|
||||||
|
local ExtmarkRange = {}
|
||||||
|
ExtmarkRange.__index = ExtmarkRange
|
||||||
|
|
||||||
--- @class u.Range
|
--- @class u.Range
|
||||||
--- @field start u.Pos
|
--- @field start u.Pos
|
||||||
@ -83,6 +90,27 @@ function Range.from_marks(lpos, rpos)
|
|||||||
return Range.new(start, stop, mode)
|
return Range.new(start, stop, mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param bufnr number
|
||||||
|
--- @param id number
|
||||||
|
function Range.from_extmark(bufnr, id)
|
||||||
|
---@type integer, integer, vim.api.keyset.extmark_details | nil
|
||||||
|
local start_row0, start_col0, details =
|
||||||
|
unpack(vim.api.nvim_buf_get_extmark_by_id(bufnr, NS, id, { details = true }))
|
||||||
|
|
||||||
|
local start = Pos.new(bufnr, start_row0 + 1, start_col0 + 1)
|
||||||
|
local stop = details and Pos.new(bufnr, details.end_row + 1, details.end_col)
|
||||||
|
|
||||||
|
local max_line_num = vim.api.nvim_buf_line_count(bufnr)
|
||||||
|
if stop and stop.lnum > max_line_num then
|
||||||
|
stop.lnum = max_line_num
|
||||||
|
stop.col = Pos.MAX_COL
|
||||||
|
stop = stop:as_real()
|
||||||
|
end
|
||||||
|
if stop and stop.col == 0 then stop = stop:must_next(-1) end
|
||||||
|
|
||||||
|
return Range.new(start, stop, 'v')
|
||||||
|
end
|
||||||
|
|
||||||
--- @param bufnr? number
|
--- @param bufnr? number
|
||||||
function Range.from_buf_text(bufnr)
|
function Range.from_buf_text(bufnr)
|
||||||
if bufnr == nil or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
if bufnr == nil or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||||
@ -272,6 +300,13 @@ function Range:to_linewise()
|
|||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Range:to_charwise()
|
||||||
|
local r = self:clone()
|
||||||
|
r.mode = 'v'
|
||||||
|
if r.stop:is_col_max() then r.stop = r.stop:as_real() end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
|
||||||
--- @param x u.Pos | u.Range
|
--- @param x u.Pos | u.Range
|
||||||
function Range:contains(x)
|
function Range:contains(x)
|
||||||
if getmetatable(x) == Pos then
|
if getmetatable(x) == Pos then
|
||||||
@ -334,6 +369,15 @@ function Range:save_to_marks(left, right)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Range:save_to_extmark()
|
||||||
|
local r = self:to_charwise()
|
||||||
|
local id = vim.api.nvim_buf_set_extmark(r.start.bufnr, NS, r.start.lnum - 1, r.start.col - 1, {
|
||||||
|
end_row = r.stop.lnum - 1,
|
||||||
|
end_col = r.stop.col,
|
||||||
|
})
|
||||||
|
return ExtmarkRange.new(r.start.bufnr, id)
|
||||||
|
end
|
||||||
|
|
||||||
function Range:set_visual_selection()
|
function Range:set_visual_selection()
|
||||||
if self:is_empty() then return end
|
if self:is_empty() then return end
|
||||||
if vim.api.nvim_get_current_buf() ~= self.start.bufnr then
|
if vim.api.nvim_get_current_buf() ~= self.start.bufnr then
|
||||||
@ -596,4 +640,10 @@ function Range:highlight(group, opts)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ExtmarkRange.new(bufnr, id) return setmetatable({ bufnr = bufnr, id = id }, ExtmarkRange) end
|
||||||
|
|
||||||
|
function ExtmarkRange:range() return Range.from_extmark(self.bufnr, self.id) end
|
||||||
|
|
||||||
|
function ExtmarkRange:delete() vim.api.nvim_buf_del_extmark(self.bufnr, NS, self.id) end
|
||||||
|
|
||||||
return Range
|
return Range
|
||||||
|
@ -7,6 +7,8 @@ local M = {}
|
|||||||
--- @alias QfItem { col: number, filename: string, kind: string, lnum: number, text: string }
|
--- @alias QfItem { col: number, filename: string, kind: string, lnum: number, text: string }
|
||||||
--- @alias KeyMaps table<string, fun(): any | string> }
|
--- @alias KeyMaps table<string, fun(): any | string> }
|
||||||
-- luacheck: ignore
|
-- luacheck: ignore
|
||||||
|
--- @alias RawCmdArgs { args: string; bang: boolean; count: number; fargs: string[]; line1: number; line2: number; mods: string; name: string; range: 0|1|2; reg: string; smods: any }
|
||||||
|
-- luacheck: ignore
|
||||||
--- @alias CmdArgs { args: string; bang: boolean; count: number; fargs: string[]; line1: number; line2: number; mods: string; name: string; range: 0|1|2; reg: string; smods: any; info: u.Range|nil }
|
--- @alias CmdArgs { args: string; bang: boolean; count: number; fargs: string[]; line1: number; line2: number; mods: string; name: string; range: 0|1|2; reg: string; smods: any; info: u.Range|nil }
|
||||||
|
|
||||||
--- @generic T
|
--- @generic T
|
||||||
@ -51,6 +53,17 @@ function M.ucmd(name, cmd, opts)
|
|||||||
vim.api.nvim_create_user_command(name, cmd2, opts or {})
|
vim.api.nvim_create_user_command(name, cmd2, opts or {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param current_args RawCmdArgs
|
||||||
|
function M.create_forward_cmd_args(current_args)
|
||||||
|
local args = { args = current_args.fargs }
|
||||||
|
if current_args.range == 1 then
|
||||||
|
args.range = { current_args.line1 }
|
||||||
|
elseif current_args.range == 2 then
|
||||||
|
args.range = { current_args.line1, current_args.line2 }
|
||||||
|
end
|
||||||
|
return args
|
||||||
|
end
|
||||||
|
|
||||||
function M.get_editor_dimensions() return { width = vim.go.columns, height = vim.go.lines } end
|
function M.get_editor_dimensions() return { width = vim.go.columns, height = vim.go.lines } end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
@ -617,4 +617,29 @@ describe('Range', function()
|
|||||||
}, vim.api.nvim_buf_get_lines(b, 0, -1, false))
|
}, vim.api.nvim_buf_get_lines(b, 0, -1, false))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can save to extmark', function()
|
||||||
|
withbuf({
|
||||||
|
'The quick brown',
|
||||||
|
'fox',
|
||||||
|
'jumps',
|
||||||
|
'over',
|
||||||
|
'the lazy dog',
|
||||||
|
}, function()
|
||||||
|
-- Construct a range over 'fox jumps'
|
||||||
|
local r = Range.new(Pos.new(nil, 2, 1), Pos.new(nil, 3, Pos.MAX_COL), 'V')
|
||||||
|
local extrange = r:save_to_extmark()
|
||||||
|
assert.are.same({ 'fox', 'jumps' }, extrange:range():lines())
|
||||||
|
-- change 'jumps' to 'leaps':
|
||||||
|
vim.api.nvim_buf_set_text(extrange.bufnr, 2, 0, 2, 4, { 'leap' })
|
||||||
|
assert.are.same({
|
||||||
|
'The quick brown',
|
||||||
|
'fox',
|
||||||
|
'leaps',
|
||||||
|
'over',
|
||||||
|
'the lazy dog',
|
||||||
|
}, vim.api.nvim_buf_get_lines(extrange.bufnr, 0, -1, false))
|
||||||
|
assert.are.same({ 'fox', 'leaps' }, extrange:range():lines())
|
||||||
|
end)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user