diff --git a/DOC.md b/DOC.md index b05aa5619..6621c91f4 100644 --- a/DOC.md +++ b/DOC.md @@ -4040,7 +4040,7 @@ Expand a snippet in the current buffer. * `opts?: LuaSnip.Opts.SnipExpand?` Optional additional arguments. Valid keys are: - * `clear_region?: LuaSnip.BufferRegion?` A region of text to clear after populating env-variables, + * `clear_region?: LuaSnip.RawRegion00?` A region of text to clear after populating env-variables, but before jumping into `snip`. If `nil`, no clearing is performed. Being able to remove text at this point is useful as clearing before calling this function would populate `TM_CURRENT_LINE` and `TM_CURRENT_WORD` with wrong values (they would miss the snippet trigger). The actual values @@ -4066,8 +4066,8 @@ Expand a snippet in the current buffer. * `captures?: string[]?` Set as the expanded snippets' captures (Defaults to `{}`). * `env_override?: { [string]: string }?` Set or override environment variables of the expanded snippet (Defaults to `{}`). - * `pos?: (integer,integer)?` Position at which the snippet should be inserted. Pass as - `(row,col)`, both 0-based, the `col` given in bytes. + * `pos?: LuaSnip.RawPos00?` Position at which the snippet should be inserted. Pass as `(row,col)`, + both 0-based, the `col` given in bytes. * `indent?: boolean?` Whether to prepend the current lines' indent to all lines of the snippet. (Defaults to `true`) Turning this off is a good idea when a LSP server already takes indents into consideration. In such cases, LuaSnip should not add additional indents. If you are using @@ -4295,8 +4295,7 @@ Lookup a node by position and activate (ie. jump into) it. * `strict?: boolean?` Only activate nodes one could usually jump to. (Defaults to false) * `select?: boolean?` Whether to select the entire node, or leave the cursor at the position it is currently at. (Defaults to true) - * `pos?: LuaSnip.BytecolBufferPosition?` Where to look for the node. (Defaults to the position of - the cursor) + * `pos?: LuaSnip.RawPos00?` Where to look for the node. (Defaults to the position of the cursor) Not covered in this section are the various node-constructors exposed by the module, their usage is shown either previously in this file or in diff --git a/doc/luasnip.txt b/doc/luasnip.txt index b9a8376e8..7397359fc 100644 --- a/doc/luasnip.txt +++ b/doc/luasnip.txt @@ -1,4 +1,4 @@ -*luasnip.txt* For NeoVim 0.7-0.11 Last change: 2026 January 19 +*luasnip.txt* For NeoVim 0.7-0.11 Last change: 2026 January 23 ============================================================================== Table of Contents *luasnip-table-of-contents* @@ -3966,7 +3966,7 @@ Expand a snippet in the current buffer. - `snippet: LuaSnip.Snippet` The snippet. - `opts?: LuaSnip.Opts.SnipExpand?` Optional additional arguments. Valid keys are: - - `clear_region?: LuaSnip.BufferRegion?` A region of text to clear after + - `clear_region?: LuaSnip.RawRegion00?` A region of text to clear after populating env-variables, but before jumping into `snip`. If `nil`, no clearing is performed. Being able to remove text at this point is useful as clearing before calling this function would populate `TM_CURRENT_LINE` and @@ -3993,7 +3993,7 @@ Expand a snippet in the current buffer. `{}`). - `env_override?: { [string]: string }?` Set or override environment variables of the expanded snippet (Defaults to `{}`). - - `pos?: (integer,integer)?` Position at which the snippet should be inserted. + - `pos?: LuaSnip.RawPos00?` Position at which the snippet should be inserted. Pass as `(row,col)`, both 0-based, the `col` given in bytes. - `indent?: boolean?` Whether to prepend the current lines’ indent to all lines of the snippet. (Defaults to `true`) Turning this off is a good idea when a LSP @@ -4261,8 +4261,8 @@ Lookup a node by position and activate (ie. jump into) it. to false) - `select?: boolean?` Whether to select the entire node, or leave the cursor at the position it is currently at. (Defaults to true) - - `pos?: LuaSnip.BytecolBufferPosition?` Where to look for the node. (Defaults - to the position of the cursor) + - `pos?: LuaSnip.RawPos00?` Where to look for the node. (Defaults to the + position of the cursor) Not covered in this section are the various node-constructors exposed by the module, their usage is shown either previously in this file or in diff --git a/lua/luasnip/_types.lua b/lua/luasnip/_types.lua index e179c8257..b6888db0f 100644 --- a/lua/luasnip/_types.lua +++ b/lua/luasnip/_types.lua @@ -1,18 +1,23 @@ +---@class LuaSnip.Pos00 A [row, col] position (e.g. in a buffer), (0,0)-indexed. +---@field [1] integer +---@field [2] integer + ---@alias LuaSnip.Cursor {[1]: number, [2]: number} ----@class LuaSnip.MatchRegion 0-based region within a single line +---@class LuaSnip.Region00InLine 0-based region within a single line ---@field row integer 0-based row ---@field col_range { [1]: integer, [2]: integer } 0-based column range, from-in, to-exclusive +--- A raw (byte) [row, col] position in a buffer, (0,0)-indexed. --- Specifies a position in a buffer, or some other collection of lines. (0,0) is --- the first line, first character, and the column-position is specified in --- bytes, not visual columns (there are characters that are visually one column, --- but occupy several bytes). ----@class LuaSnip.BytecolBufferPosition +---@class LuaSnip.RawPos00 ---@field [1] integer ---@field [2] integer ---- 0-based region in a buffer. ----@class LuaSnip.BufferRegion ----@field from LuaSnip.BytecolBufferPosition Starting position, included. ----@field to LuaSnip.BytecolBufferPosition Ending position, excluded. +--- 0-based region (end column excluded) in a buffer. +---@class LuaSnip.RawRegion00 +---@field from LuaSnip.RawPos00 Starting position, included. +---@field to LuaSnip.RawPos00 Ending position, excluded. diff --git a/lua/luasnip/extras/_treesitter.lua b/lua/luasnip/extras/_treesitter.lua index bd22a6cd8..8fcf51b56 100644 --- a/lua/luasnip/extras/_treesitter.lua +++ b/lua/luasnip/extras/_treesitter.lua @@ -28,7 +28,7 @@ local function inspect_node(node) end ---@param bufnr number ----@param region LuaSnip.MatchRegion +---@param region LuaSnip.Region00InLine ---@return vim.treesitter.LanguageTree, string local function reparse_buffer_after_removing_match(bufnr, region) local lang = get_lang(bufnr) @@ -56,11 +56,11 @@ end ---@class LuaSnip.extra.FixBufferContext ---@field ori_bufnr number ---@field ori_text string ----@field region LuaSnip.MatchRegion +---@field region LuaSnip.Region00InLine local FixBufferContext = {} ---@param ori_bufnr number ----@param region LuaSnip.MatchRegion +---@param region LuaSnip.Region00InLine ---@return LuaSnip.extra.FixBufferContext function FixBufferContext.new(ori_bufnr, region, region_content) local o = { @@ -291,10 +291,10 @@ function TSParser.new(bufnr, parser, source) return o end ----@param pos { [1]: number, [2]: number }? +---@param pos LuaSnip.RawPos00 ---@return TSNode? function TSParser:get_node_at_pos(pos) - pos = vim.F.if_nil(pos, util.get_cursor_0ind()) + local pos = pos or util.get_cursor_0ind() local row, col = pos[1], pos[2] assert( row >= 0 and col >= 0, @@ -308,7 +308,7 @@ function TSParser:get_node_at_pos(pos) end ---Get the root for the smallest tree containing `pos`. ----@param pos { [1]: number, [2]: number } +---@param pos LuaSnip.RawPos00 ---@return TSNode? function TSParser:root_at(pos) local tree = self.parser:tree_for_range( @@ -323,7 +323,7 @@ function TSParser:root_at(pos) end ---@param match_opts LuaSnip.extra.EffectiveMatchTSNodeOpts ----@param pos { [1]: number, [2]: number } +---@param pos LuaSnip.RawPos00 ---@return LuaSnip.extra.NamedTSMatch?, TSNode? function TSParser:match_at(match_opts, pos) -- Since we want to find a match to the left of pos, and if we accept there diff --git a/lua/luasnip/extras/treesitter_postfix.lua b/lua/luasnip/extras/treesitter_postfix.lua index 3dcaaeabe..9e343acd9 100644 --- a/lua/luasnip/extras/treesitter_postfix.lua +++ b/lua/luasnip/extras/treesitter_postfix.lua @@ -43,7 +43,7 @@ local function generate_match_tsnode_func(opts) end ---@param parser LuaSnip.extra.TSParser - ---@param pos { [1]: number, [2]: number } + ---@param pos LuaSnip.RawPos00 return function(parser, pos) return parser:match_at( match_opts, --[[@as LuaSnip.extra.MatchTSNodeOpts]] @@ -140,7 +140,7 @@ local function generate_resolve_expand_param(match_tsnode, user_resolver) ---@param parser vim.treesitter.LanguageTree ---@param source number|string ---@param bufnr number - ---@param pos { [1]: number, [2]: number } + ---@param pos LuaSnip.RawPos00 return function( snippet, line_to_cursor, @@ -227,7 +227,7 @@ local function generate_simple_parent_lookup_function(lookup_fun) return function(types) local type_checker = tbl.list_to_set(types) ---@param parser LuaSnip.extra.TSParser - ---@param pos { [1]: number, [2]: number } + ---@param pos LuaSnip.RawPos00 return function(parser, pos) -- check node just before the position. local root = parser:get_node_at_pos({ pos[1], pos[2] - 1 }) @@ -260,7 +260,7 @@ end ---@param n number local function find_nth_parent(n) ---@param parser LuaSnip.extra.TSParser - ---@param pos { [1]: number, [2]: number } + ---@param pos LuaSnip.RawPos00 return function(parser, pos) local inner_node = parser:get_node_at_pos({ pos[1], pos[2] - 1 }) diff --git a/lua/luasnip/init.lua b/lua/luasnip/init.lua index 734c84b51..7ae80c151 100644 --- a/lua/luasnip/init.lua +++ b/lua/luasnip/init.lua @@ -542,7 +542,7 @@ end --This can also use `jump_into_func`. ---@class LuaSnip.Opts.SnipExpand: LuaSnip.Opts.Expand --- ----@field clear_region? LuaSnip.BufferRegion A region of text to clear after +---@field clear_region? LuaSnip.RawRegion00 A region of text to clear after --- populating env-variables, but before jumping into `snip`. If `nil`, no --- clearing is performed. --- Being able to remove text at this point is useful as clearing before calling @@ -566,7 +566,7 @@ end --- }) --- ``` --- ----@field pos? [integer, integer] Position at which the snippet should be +---@field pos? LuaSnip.RawPos00 Position at which the snippet should be --- inserted. Pass as `(row,col)`, both 0-based, the `col` given in bytes. --- ---@field indent? boolean Whether to prepend the current lines' indent to all @@ -1301,7 +1301,7 @@ end --- (Defaults to false) ---@field select? boolean Whether to select the entire node, or leave the --- cursor at the position it is currently at. (Defaults to true) ----@field pos? LuaSnip.BytecolBufferPosition Where to look for the node. +---@field pos? LuaSnip.RawPos00 Where to look for the node. --- (Defaults to the position of the cursor) --- Lookup a node by position and activate (ie. jump into) it. diff --git a/lua/luasnip/nodes/choiceNode.lua b/lua/luasnip/nodes/choiceNode.lua index 1331e644c..64e400ba8 100644 --- a/lua/luasnip/nodes/choiceNode.lua +++ b/lua/luasnip/nodes/choiceNode.lua @@ -145,6 +145,7 @@ function ChoiceNode:make_args_absolute() self.absolute_insert_position[last_indx] = last end +---@param pos LuaSnip.RawPos00 function ChoiceNode:put_initial(pos) local old_pos = vim.deepcopy(pos) diff --git a/lua/luasnip/nodes/dynamicNode.lua b/lua/luasnip/nodes/dynamicNode.lua index 23c77f4be..8315ffad1 100644 --- a/lua/luasnip/nodes/dynamicNode.lua +++ b/lua/luasnip/nodes/dynamicNode.lua @@ -80,6 +80,7 @@ function DynamicNode:get_docstring() end -- DynamicNode's don't have static text, only set as visible. +---@param pos LuaSnip.RawPos00 function DynamicNode:put_initial(pos) -- if we generated a snippet before, insert it into the buffer now. This -- can happen if this dynamicNode was removed (eg. because of a diff --git a/lua/luasnip/nodes/insertNode.lua b/lua/luasnip/nodes/insertNode.lua index a379e4ba3..ddeaa6761 100644 --- a/lua/luasnip/nodes/insertNode.lua +++ b/lua/luasnip/nodes/insertNode.lua @@ -442,6 +442,7 @@ function InsertNode:argnode_text() return self.static_text end +---@param pos LuaSnip.RawPos00 function InsertNode:put_initial(pos) self.static_text:put(pos) self.visible = true diff --git a/lua/luasnip/nodes/node.lua b/lua/luasnip/nodes/node.lua index 40010ba50..2b9d4d4cf 100644 --- a/lua/luasnip/nodes/node.lua +++ b/lua/luasnip/nodes/node.lua @@ -73,6 +73,7 @@ function Node:get_docstring() return self.static_text end +---@param pos LuaSnip.RawPos00 function Node:put_initial(pos) -- access static text directly, get_static_text() won't work due to -- static_visible not being set. diff --git a/lua/luasnip/nodes/restoreNode.lua b/lua/luasnip/nodes/restoreNode.lua index 530b82a40..5653adee5 100644 --- a/lua/luasnip/nodes/restoreNode.lua +++ b/lua/luasnip/nodes/restoreNode.lua @@ -86,6 +86,7 @@ function RestoreNode:expand_tabs(_) end -- will be called when before expansion but after snip.parent was initialized. -- Get the actual snippetNode here. +---@param pos LuaSnip.RawPos00 function RestoreNode:put_initial(pos) local tmp = self.parent.snippet.stored[self.key] diff --git a/lua/luasnip/nodes/snippet.lua b/lua/luasnip/nodes/snippet.lua index 933556dd7..bcbd11c14 100644 --- a/lua/luasnip/nodes/snippet.lua +++ b/lua/luasnip/nodes/snippet.lua @@ -909,6 +909,7 @@ function Snippet:dump() end end +---@param pos LuaSnip.RawPos00 function Snippet:put_initial(pos) for _, node in ipairs(self.nodes) do -- save pos to compare to later. @@ -1603,6 +1604,7 @@ function Snippet:subtree_leave_entered() end end +---@param pos LuaSnip.RawPos00 function Snippet:put(pos) --- Put text-content of snippet into buffer and set marks. local old_pos = vim.deepcopy(pos) diff --git a/lua/luasnip/nodes/util.lua b/lua/luasnip/nodes/util.lua index cb27d9ffd..a9a66831d 100644 --- a/lua/luasnip/nodes/util.lua +++ b/lua/luasnip/nodes/util.lua @@ -868,12 +868,11 @@ end ---of more than one restore data, and the correct ones can be identified via ---store_id. ---@field node LuaSnip.Node The node the cursor will be stored relative to. ----@field cursor_start_relative LuaSnip.BytecolBufferPosition The position of ----the cursor, or beginning of selected area, relative to the beginning of ----`node`. ----@field selection_end_start_relative LuaSnip.BytecolBufferPosition The ----position of the cursor, or end of selected area, relative to the beginning of ----`node`. The column is one beyond the byte where the selection ends. +---@field cursor_start_relative LuaSnip.RawPos00 The position of the cursor, +---or beginning of selected area, relative to the beginning of `node`. +---@field selection_end_start_relative LuaSnip.RawPos00 The position of the +---cursor, or end of selected area, relative to the beginning of `node`. The +---column is one beyond the byte where the selection ends. ---@field mode string The first character (see `vim.fn.mode()`) of the mode at ---the time of `store`. @@ -1016,6 +1015,8 @@ local function store_cursor_node_relative(node, opts) return data end +---@param node LuaSnip.Node +---@param data LuaSnip.SnippetCursorRestoreData local function restore_cursor_pos_relative(node, data) local cursor_pos = data.cursor_start_relative local cursor_pos_v = data.selection_end_start_relative diff --git a/lua/luasnip/util/feedkeys.lua b/lua/luasnip/util/feedkeys.lua index 0b5a362d0..f997958d5 100644 --- a/lua/luasnip/util/feedkeys.lua +++ b/lua/luasnip/util/feedkeys.lua @@ -75,7 +75,8 @@ function M.feedkeys_insert(keys) end, next_id()) end --- pos: (0,0)-indexed. +---@param pos LuaSnip.RawPos00 +---@param before? boolean local function cursor_set_keys(pos, before) if before then if pos[2] == 0 then @@ -119,6 +120,9 @@ local function cursor_set_keys(pos, before) .. ":silent! foldopen!" end +--- Visual select between the given begin/end positions +---@param b LuaSnip.RawPos00 Starting position +---@param e LuaSnip.RawPos00 Ending position (inclusive) function M.select_range(b, e) local id = next_id() enqueued_cursor_state = @@ -152,7 +156,8 @@ function M.select_range(b, e) end, id) end --- move the cursor to a position and enter insert-mode (or stay in it). +--- Move the cursor to a position and enter insert-mode (or stay in it). +---@param pos LuaSnip.RawPos00 function M.insert_at(pos) local id = next_id() enqueued_cursor_state = { pos = pos, mode = "i", id = id } @@ -205,12 +210,12 @@ function M.confirm(id) end ---@class LuaSnip.Feedkeys.LastState ----@field pos LuaSnip.BytecolBufferPosition Position of the cursor or beginning of visual ----area. ----@field pos_v LuaSnip.BytecolBufferPosition Position of the cursor or end of visual ----area. ----@field mode string Represents the current mode. Only the first character of ----`vim.fn.mode()`, so not completely exact. +---@field pos LuaSnip.RawPos00 Position of the cursor or beginning of visual +--- area. +---@field pos_v LuaSnip.RawPos00 Position of the cursor or end of visual +--- area. +---@field mode string Represents the current mode. +--- Only the first character of `vim.fn.mode()`, so not completely exact. ---if there are some operations that move the cursor enqueued, retrieve their ---target-state, otherwise return the current cursor state. diff --git a/lua/luasnip/util/mark.lua b/lua/luasnip/util/mark.lua index ab4e539f7..015520e06 100644 --- a/lua/luasnip/util/mark.lua +++ b/lua/luasnip/util/mark.lua @@ -1,17 +1,27 @@ local session = require("luasnip.session") local util = require("luasnip.util.util") ----@class LuaSnip.Mark +---@alias LuaSnip.Mark.WhichSide +---| -1 # left side +---| 1 # right side + +---@class LuaSnip.Mark Represents an extmark in a buffer. +---@field id? integer Extmark ID +---@field opts vim.api.keyset.set_extmark Extmark options local Mark = {} +---@return LuaSnip.Mark function Mark:new(o) - o = o or {} + o = o or { id = nil, opts = {} } setmetatable(o, self) self.__index = self return o end --- opts just like in nvim_buf_set_extmark. +---@param pos_begin LuaSnip.RawPos00 +---@param pos_end LuaSnip.RawPos00 +---@param opts vim.api.keyset.set_extmark +---@return LuaSnip.Mark local function mark(pos_begin, pos_end, opts) return Mark:new({ id = vim.api.nvim_buf_set_extmark( @@ -31,12 +41,17 @@ local function mark(pos_begin, pos_end, opts) }) end +---@param pos LuaSnip.RawPos00 +---@return LuaSnip.Pos00 local function bytecol_to_utfcol(pos) local line = vim.api.nvim_buf_get_lines(0, pos[1], pos[1] + 1, false) -- line[1]: get_lines returns table. return { pos[1], util.str_utf32index(line[1] or "", pos[2]) } end +--- Returns the (utf-32) begin/end positions of the mark. +---@return LuaSnip.Pos00 begin Begin position, (0,0)-indexed +---@return LuaSnip.Pos00 end End position, (0,0)-indexed function Mark:pos_begin_end() local mark_info = vim.api.nvim_buf_get_extmark_by_id( 0, @@ -49,6 +64,8 @@ function Mark:pos_begin_end() bytecol_to_utfcol({ mark_info[3].end_row, mark_info[3].end_col }) end +--- Returns the (utf-32) begin position of the mark +---@return LuaSnip.Pos00 function Mark:pos_begin() local mark_info = vim.api.nvim_buf_get_extmark_by_id( 0, @@ -60,6 +77,8 @@ function Mark:pos_begin() return bytecol_to_utfcol({ mark_info[1], mark_info[2] }) end +--- Returns the (utf-32) end position of the mark +---@return LuaSnip.Pos00 function Mark:pos_end() local mark_info = vim.api.nvim_buf_get_extmark_by_id( 0, @@ -71,6 +90,9 @@ function Mark:pos_end() return bytecol_to_utfcol({ mark_info[3].end_row, mark_info[3].end_col }) end +--- Returns the raw (byte) begin/end positions of the mark. +---@return LuaSnip.RawPos00 begin Begin position, (0,0)-indexed +---@return LuaSnip.RawPos00 end End position, (0,0)-indexed function Mark:pos_begin_end_raw() local mark_info = vim.api.nvim_buf_get_extmark_by_id( 0, @@ -84,6 +106,8 @@ function Mark:pos_begin_end_raw() } end +--- Returns the raw (byte) begin position of the mark +---@return LuaSnip.RawPos00 function Mark:pos_begin_raw() local mark_info = vim.api.nvim_buf_get_extmark_by_id( 0, @@ -94,6 +118,8 @@ function Mark:pos_begin_raw() return { mark_info[1], mark_info[2] } end +---@param opts vim.api.keyset.set_extmark +---@return LuaSnip.Mark function Mark:copy_pos_gravs(opts) local pos_beg, pos_end = self:pos_begin_end_raw() opts.right_gravity = self.opts.right_gravity @@ -101,31 +127,7 @@ function Mark:copy_pos_gravs(opts) return mark(pos_beg, pos_end, opts) end --- opts just like in nvim_buf_set_extmark. --- opts as first arg bcs. pos are pretty likely to stay the same. -function Mark:update(opts, pos_begin, pos_end) - -- if one is changed, the other is likely as well. - if not pos_begin then - pos_begin = old_pos_begin - if not pos_end then - pos_end = old_pos_end - end - end - -- override with new. - self.opts = vim.tbl_extend("force", self.opts, opts) - vim.api.nvim_buf_set_extmark( - 0, - session.ns_id, - pos_begin[1], - pos_begin[2], - vim.tbl_extend( - "force", - self.opts, - { id = self.id, end_line = pos_end[1], end_col = pos_end[2] } - ) - ) -end - +---@param opts vim.api.keyset.set_extmark function Mark:set_opts(opts) local pos_begin, pos_end = self:pos_begin_end_raw() vim.api.nvim_buf_del_extmark(0, session.ns_id, self.id) @@ -146,6 +148,9 @@ function Mark:set_opts(opts) ) end +--- Set right-gravity for left & right sides +---@param rgrav_left boolean +---@param rgrav_right boolean function Mark:set_rgravs(rgrav_left, rgrav_right) -- don't update if nothing would change. if @@ -158,16 +163,22 @@ function Mark:set_rgravs(rgrav_left, rgrav_right) end end -function Mark:get_rgrav(which) - if which == -1 then +--- Returns right-gravity for left or right side +---@param which_side LuaSnip.Mark.WhichSide +---@return boolean? +function Mark:get_rgrav(which_side) + if which_side == -1 then return self.opts.right_gravity else return self.opts.end_right_gravity end end -function Mark:set_rgrav(which, rgrav) - if which == -1 then +--- Set right-gravity for left or right side +---@param which_side LuaSnip.Mark.WhichSide +---@param rgrav boolean +function Mark:set_rgrav(which_side, rgrav) + if which_side == -1 then if self.opts.right_gravity == rgrav then return end @@ -181,17 +192,21 @@ function Mark:set_rgrav(which, rgrav) self:set_opts(self.opts) end -function Mark:get_endpoint(which) +--- Returns the raw (byte) position of the wanted side +---@param which_side LuaSnip.Mark.WhichSide +---@return LuaSnip.RawPos00 +function Mark:get_endpoint(which_side) -- simpler for now, look into perf here later. local l, r = self:pos_begin_end_raw() - if which == -1 then + if which_side == -1 then return l else return r end end --- change all opts except rgravs. +--- Update all opts except right-gravities +---@param opts vim.api.keyset.set_extmark function Mark:update_opts(opts) local opts_cp = vim.deepcopy(opts) opts_cp.right_gravity = self.opts.right_gravity @@ -199,14 +214,16 @@ function Mark:update_opts(opts) self:set_opts(opts_cp) end --- invalidate this mark object only, leave the underlying extmark alone. +--- Invalidate this mark object only, leave the underlying extmark alone. function Mark:invalidate() self.id = nil end +--- Delete the underlying extmark if any. function Mark:clear() if self.id then vim.api.nvim_buf_del_extmark(0, session.ns_id, self.id) + self.id = nil end end diff --git a/lua/luasnip/util/util.lua b/lua/luasnip/util/util.lua index 144dc71d2..bf4a3cef4 100644 --- a/lua/luasnip/util/util.lua +++ b/lua/luasnip/util/util.lua @@ -1,6 +1,7 @@ local session = require("luasnip.session") local vimversion = require("luasnip.util.vimversion") +---@return LuaSnip.RawPos00 local function get_cursor_0ind() local c = vim.api.nvim_win_get_cursor(0) c[1] = c[1] - 1 @@ -8,12 +9,13 @@ local function get_cursor_0ind() end -- don't use utf-indexed column, win_set_cursor ignores these. +---@param c LuaSnip.RawPos00 local function set_cursor_0ind(c) c[1] = c[1] + 1 vim.api.nvim_win_set_cursor(0, c) end --- pos: (0,0)-indexed. +---@param pos LuaSnip.RawPos00 local function line_chars_before(pos) -- cur-rows are 1-indexed, api-rows 0. local line = vim.api.nvim_buf_get_lines(0, pos[1], pos[1] + 1, false) @@ -117,6 +119,7 @@ local function move_to_mark(id) id, { details = false } ) + ---@cast new_cur_pos LuaSnip.RawPos00 set_cursor_0ind(new_cur_pos) end @@ -163,12 +166,14 @@ local function word_under_cursor(cur, line) end -- Put text and update cursor(pos) where cursor is byte-indexed. -local function put(text, pos) - vim.api.nvim_buf_set_text(0, pos[1], pos[2], pos[1], pos[2], text) +---@param lines string[] +---@param pos LuaSnip.RawPos00 +local function put(lines, pos) + vim.api.nvim_buf_set_text(0, pos[1], pos[2], pos[1], pos[2], lines) -- add rows - pos[1] = pos[1] + #text - 1 + pos[1] = pos[1] + #lines - 1 -- add columns, start at 0 if no rows were added, else at old col-value. - pos[2] = (#text > 1 and 0 or pos[2]) + #text[#text] + pos[2] = (#lines > 1 and 0 or pos[2]) + #lines[#lines] end --[[ Wraps the value in a table if it's not one, makes @@ -199,6 +204,13 @@ local function wrap_nodes(nodes) end end +--- Returns whether the given positions are equal +--- +---@param p1 LuaSnip.RawPos00|LuaSnip.Pos00 +---@param p2 LuaSnip.RawPos00|LuaSnip.Pos00 +---@return boolean +-- +-- FIXME(@bew): I don't know how to enforce the use of the same type of pos.. local function pos_equal(p1, p2) return p1[1] == p2[1] and p1[2] == p2[2] end @@ -305,13 +317,6 @@ local function get_snippet_filetypes() return deduplicate(redirect_filetypes(fts)) end -local function pos_add(p1, p2) - return { p1[1] + p2[1], p1[2] + p2[2] } -end -local function pos_sub(p1, p2) - return { p1[1] - p2[1], p1[2] - p2[2] } -end - local function pop_front(list) local front = list[1] for i = 2, #list do @@ -397,7 +402,17 @@ local function cmp(i1, i2) return 0 end --- compare two positions, <0 => pos1 pos1=pos2, >0 => pos1 > pos2. +--- Compare two positions +--- +--- Returns <0 when pos1 < pos2 +--- Returns 0 when pos1 == pos2 +--- Returns >0 when pos1 > pos2 +--- +---@param pos1 LuaSnip.RawPos00|LuaSnip.Pos00 +---@param pos2 LuaSnip.RawPos00|LuaSnip.Pos00 +---@return integer +-- +-- FIXME(@bew): I don't know how to enforce the use of the same type of pos.. local function pos_cmp(pos1, pos2) -- if row is different it determines result, otherwise the column does. return 2 * cmp(pos1[1], pos2[1]) + cmp(pos1[2], pos2[2]) @@ -413,19 +428,32 @@ local function default_tbl_get(default, t, ...) return default end --- compute offset of `pos` into multiline string starting at `base_pos`. --- This is different from pos_sub because here the column-offset starts at zero --- when `pos` is on a line different from `base_pos`. --- Assumption: `pos` occurs after `base_pos`. +--- Compute offset of `pos` into multiline string starting at `base_pos`. +--- +--- This is different from pos_sub because here the column-offset starts at zero +--- when `pos` is on a line different from `base_pos`. +--- +--- Assumption: `pos` occurs after `base_pos`. +--- +---@param base_pos LuaSnip.RawPos00 +---@param pos LuaSnip.RawPos00 +---@return LuaSnip.RawPos00 local function pos_offset(base_pos, pos) local row_offset = pos[1] - base_pos[1] - return { row_offset, row_offset == 0 and pos[2] - base_pos[2] or pos[2] } + return { + row_offset, + row_offset == 0 and pos[2] - base_pos[2] or pos[2], + } end --- compute offset of `pos` into multiline string starting at `base_pos`. --- This is different from pos_sub because here the column-offset starts at zero --- when `pos` is on a line different from `base_pos`. --- Assumption: `pos` occurs after `base_pos`. +--- Given an offset computed via `pos_offset`, compute its position when +--- applied to `base_pos`. +--- +--- Assumption: `offset` occurs after `base_pos`. +--- +---@param base_pos LuaSnip.RawPos00 +---@param offset LuaSnip.RawPos00 +---@return LuaSnip.RawPos00 local function pos_from_offset(base_pos, offset) return { base_pos[1] + offset[1], @@ -470,8 +498,6 @@ return { get_snippet_filetypes = get_snippet_filetypes, json_decode = vim.json.decode, json_encode = vim.json.encode, - pos_sub = pos_sub, - pos_add = pos_add, deduplicate = deduplicate, pop_front = pop_front, key_sorted_pairs = key_sorted_pairs,