mirror of
https://github.com/neovim/neovim.git
synced 2026-05-26 23:08:36 +00:00
refactor(pos,range): add missing validators and improve the docs
Problem: Our documentation is incomplete or inconsistent in several ways: - Some public APIs lack corresponding validators. - Some public APIs lack usage examples. - The meaning of some return values or parameters is not clearly explained. Solution: Add the missing validators, examples, and clarifications.
This commit is contained in:
@@ -4510,18 +4510,33 @@ by |vim.Pos| objects.
|
||||
cursor({buf}, {pos}) *vim.pos.cursor()*
|
||||
Creates a new |vim.Pos| from cursor position (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
local cursor_pos = vim.api.nvim_win_get_cursor(0)
|
||||
local pos = vim.pos.lsp(0, cursor_pos)
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {buf} (`integer`)
|
||||
• {pos} (`[integer, integer]`)
|
||||
• {pos} (`[integer, integer]`) (lnum, col) tuple
|
||||
|
||||
Return: ~
|
||||
(`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
extmark({buf}, {row}, {col}) *vim.pos.extmark()*
|
||||
Creates a new |vim.Pos| from extmark position (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
local pos = vim.pos.extmark(0, 3, 5)
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {buf} (`integer`)
|
||||
• {row} (`integer`)
|
||||
• {col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
lsp({buf}, {pos}, {position_encoding}) *vim.pos.lsp()*
|
||||
Creates a new |vim.Pos| from `lsp.Position`.
|
||||
|
||||
@@ -4539,16 +4554,38 @@ lsp({buf}, {pos}, {position_encoding}) *vim.pos.lsp()*
|
||||
• {pos} (`lsp.Position`)
|
||||
• {position_encoding} (`lsp.PositionEncodingKind`)
|
||||
|
||||
mark({buf}, {row}, {col}) *vim.pos.mark()*
|
||||
Return: ~
|
||||
(`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
mark({buf}, {lnum}, {col}) *vim.pos.mark()*
|
||||
Creates a new |vim.Pos| from mark position (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
local mark_info = vim.api.nvim_get_mark('M', {})
|
||||
local lnum, col, buf, name = unpack(mark_info)
|
||||
|
||||
if lnum == 0 and col == 0 and buf == 0 then
|
||||
return -- mark 'M' is not set.
|
||||
end
|
||||
|
||||
local pos = vim.pos.mark(buf, lnum, col)
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {buf} (`integer`)
|
||||
• {row} (`integer`)
|
||||
• {col} (`integer`)
|
||||
• {buf} (`integer`)
|
||||
• {lnum} (`integer`)
|
||||
• {col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
offset({buf}, {offset}) *vim.pos.offset()*
|
||||
Creates a new |vim.Pos| from buffer offset.
|
||||
Creates a new |vim.Pos| from buffer (bytes) offset.
|
||||
|
||||
Example: >lua
|
||||
local offset = vim.api.nvim_buf_get_offset(0, vim.api.nvim_buf_line_count(0))
|
||||
local pos = vim.pos.offset(0, offset)
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {buf} (`integer`)
|
||||
@@ -4572,18 +4609,25 @@ to_cursor({pos}) *vim.pos.to_cursor()*
|
||||
• {pos} (`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`) lnum
|
||||
(`integer`) col
|
||||
|
||||
to_extmark({pos}) *vim.pos.to_extmark()*
|
||||
Converts |vim.Pos| to extmark position (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
local pos = vim.pos(0, 3, 5)
|
||||
|
||||
-- Convert to extmark position, you can call it in a method style.
|
||||
local extmark_pos = pos:to_extmark()
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {pos} (`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`) row
|
||||
(`integer`) col
|
||||
|
||||
to_lsp({pos}, {position_encoding}) *vim.pos.to_lsp()*
|
||||
Converts |vim.Pos| to `lsp.Position`.
|
||||
@@ -4599,18 +4643,40 @@ to_lsp({pos}, {position_encoding}) *vim.pos.to_lsp()*
|
||||
• {pos} (`vim.Pos`) See |vim.Pos|.
|
||||
• {position_encoding} (`lsp.PositionEncodingKind`)
|
||||
|
||||
Return: ~
|
||||
(`lsp.Position`)
|
||||
|
||||
to_mark({pos}) *vim.pos.to_mark()*
|
||||
Converts |vim.Pos| to mark position (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
local pos = vim.pos(0, 3, 5)
|
||||
|
||||
-- Convert to mark position, you can call it in a method style.
|
||||
local lnum, col = pos:to_mark()
|
||||
vim.api.nvim_buf_set_mark(0, 'M', lnum, col, {})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {pos} (`vim.Pos`) See |vim.Pos|.
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`) lnum
|
||||
(`integer`) col
|
||||
|
||||
to_offset({pos}) *vim.pos.to_offset()*
|
||||
Converts |vim.Pos| to buffer offset.
|
||||
Converts |vim.Pos| to buffer (bytes) offset.
|
||||
|
||||
Example: >lua
|
||||
local p1 = vim.pos(0, 3, 5)
|
||||
local p2 = vim.pos(0, 4, 0)
|
||||
|
||||
-- Convert to buffer offset, you can call it in a method style.
|
||||
local offset1 = p1:to_offset()
|
||||
local offset2 = p2:to_offset()
|
||||
-- Can be used to calculate the distance between two locations.
|
||||
local distance = offset2 - offset1
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {pos} (`vim.Pos`) See |vim.Pos|.
|
||||
@@ -4681,6 +4747,9 @@ extmark({buf}, {start_row}, {start_col}, {end_row}, {end_col})
|
||||
• {end_row} (`integer`)
|
||||
• {end_col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.Range`) See |vim.Range|.
|
||||
|
||||
has({outer}, {inner}) *vim.range.has()*
|
||||
Checks whether {outer} range contains {inner} range or position.
|
||||
|
||||
@@ -4729,25 +4798,31 @@ lsp({buf}, {range}, {position_encoding}) *vim.range.lsp()*
|
||||
• {range} (`lsp.Range`)
|
||||
• {position_encoding} (`lsp.PositionEncodingKind`)
|
||||
|
||||
Return: ~
|
||||
(`vim.Range`) See |vim.Range|.
|
||||
|
||||
*vim.range.mark()*
|
||||
mark({buf}, {start_row}, {start_col}, {end_row}, {end_col})
|
||||
mark({buf}, {start_lnum}, {start_col}, {end_lnum}, {end_col})
|
||||
Creates a new |vim.Range| from "mark-indexed" range (see |api-indexing|).
|
||||
|
||||
Example: >lua
|
||||
-- A range represented by marks may be end-inclusive (decided by 'selection' option).
|
||||
local start_row, start_col = unpack(api.nvim_buf_get_mark(bufnr, '<'))
|
||||
local end_row, end_col = unpack(api.nvim_buf_get_mark(bufnr, '>'))
|
||||
local start_lnum, start_col = unpack(api.nvim_buf_get_mark(bufnr, '<'))
|
||||
local end_lnum, end_col = unpack(api.nvim_buf_get_mark(bufnr, '>'))
|
||||
|
||||
-- Create an end-exclusive range.
|
||||
local range = vim.range.mark(0, start_row, start_col, end_row, end_col)
|
||||
local range = vim.range.mark(0, start_lnum, start_col, end_lnum, end_col)
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {buf} (`integer`)
|
||||
• {start_row} (`integer`)
|
||||
• {start_col} (`integer`)
|
||||
• {end_row} (`integer`)
|
||||
• {end_col} (`integer`)
|
||||
• {buf} (`integer`)
|
||||
• {start_lnum} (`integer`)
|
||||
• {start_col} (`integer`)
|
||||
• {end_lnum} (`integer`)
|
||||
• {end_col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.Range`) See |vim.Range|.
|
||||
|
||||
to_extmark({range}) *vim.range.to_extmark()*
|
||||
Converts |vim.Range| to extmark range (see |api-indexing|).
|
||||
@@ -4762,6 +4837,12 @@ to_extmark({range}) *vim.range.to_extmark()*
|
||||
Parameters: ~
|
||||
• {range} (`vim.Range`) See |vim.Range|.
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`) start_row
|
||||
(`integer`) start_col
|
||||
(`integer`) end_row
|
||||
(`integer`) end_col
|
||||
|
||||
to_lsp({range}, {position_encoding}) *vim.range.to_lsp()*
|
||||
Converts |vim.Range| to `lsp.Range`.
|
||||
|
||||
@@ -4786,17 +4867,17 @@ to_mark({range}) *vim.range.to_mark()*
|
||||
local range = vim.range(0, 3, 5, 4, 0)
|
||||
|
||||
-- Convert to mark range, you can call it in a method style.
|
||||
local start_row, start_col, end_row, end_col = range:to_mark()
|
||||
local start_lnum, start_col, end_lnum, end_col = range:to_mark()
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {range} (`vim.Range`) See |vim.Range|.
|
||||
|
||||
Return (multiple): ~
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`)
|
||||
(`integer`) start_lnum
|
||||
(`integer`) start_col
|
||||
(`integer`) end_lnum
|
||||
(`integer`) end_col
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
@@ -112,6 +112,7 @@ end
|
||||
--- ```
|
||||
---@param pos vim.Pos
|
||||
---@param position_encoding lsp.PositionEncodingKind
|
||||
---@return lsp.Position
|
||||
function M.to_lsp(pos, position_encoding)
|
||||
validate('pos', pos, 'table')
|
||||
validate('position_encoding', position_encoding, 'string')
|
||||
@@ -133,6 +134,7 @@ end
|
||||
---@param buf integer
|
||||
---@param pos lsp.Position
|
||||
---@param position_encoding lsp.PositionEncodingKind
|
||||
---@return vim.Pos
|
||||
function M.lsp(buf, pos, position_encoding)
|
||||
validate('buf', buf, 'number')
|
||||
validate('pos', pos, 'table')
|
||||
@@ -157,49 +159,110 @@ end
|
||||
--- vim.api.nvim_win_set_cursor(0, cursor_pos)
|
||||
--- ```
|
||||
---@param pos vim.Pos
|
||||
---@return integer, integer
|
||||
---@return integer lnum, integer col
|
||||
function M.to_cursor(pos)
|
||||
validate('pos', pos, 'table')
|
||||
return util.to_mark(pos[1], pos[2])
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from cursor position (see |api-indexing|).
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local cursor_pos = vim.api.nvim_win_get_cursor(0)
|
||||
--- local pos = vim.pos.lsp(0, cursor_pos)
|
||||
--- ```
|
||||
---@param buf integer
|
||||
---@param pos [integer, integer]
|
||||
---@param pos [integer, integer] (lnum, col) tuple
|
||||
---@return vim.Pos
|
||||
function M.cursor(buf, pos)
|
||||
return M.new(buf, util.from_mark(pos[1], pos[2]))
|
||||
end
|
||||
validate('buf', buf, 'number')
|
||||
validate('pos', pos, 'table')
|
||||
|
||||
--- Converts |vim.Pos| to mark position (see |api-indexing|).
|
||||
---@param pos vim.Pos
|
||||
---@return integer, integer
|
||||
function M.to_mark(pos)
|
||||
return util.to_mark(pos[1], pos[2])
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from mark position (see |api-indexing|).
|
||||
---@param buf integer
|
||||
---@param row integer
|
||||
---@param col integer
|
||||
function M.mark(buf, row, col)
|
||||
if buf == 0 then
|
||||
buf = api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
return M.new(buf, util.from_mark(row, col))
|
||||
return M.new(buf, util.from_mark(pos[1], pos[2]))
|
||||
end
|
||||
|
||||
--- Converts |vim.Pos| to mark position (see |api-indexing|).
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local pos = vim.pos(0, 3, 5)
|
||||
---
|
||||
--- -- Convert to mark position, you can call it in a method style.
|
||||
--- local lnum, col = pos:to_mark()
|
||||
--- vim.api.nvim_buf_set_mark(0, 'M', lnum, col, {})
|
||||
--- ```
|
||||
---@param pos vim.Pos
|
||||
---@return integer lnum, integer col
|
||||
function M.to_mark(pos)
|
||||
validate('pos', pos, 'table')
|
||||
return util.to_mark(pos[1], pos[2])
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from mark position (see |api-indexing|).
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local mark_info = vim.api.nvim_get_mark('M', {})
|
||||
--- local lnum, col, buf, name = unpack(mark_info)
|
||||
---
|
||||
--- if lnum == 0 and col == 0 and buf == 0 then
|
||||
--- return -- mark 'M' is not set.
|
||||
--- end
|
||||
---
|
||||
--- local pos = vim.pos.mark(buf, lnum, col)
|
||||
--- ```
|
||||
---@param buf integer
|
||||
---@param lnum integer
|
||||
---@param col integer
|
||||
---@return vim.Pos
|
||||
function M.mark(buf, lnum, col)
|
||||
validate('buf', buf, 'number')
|
||||
validate('lnum', lnum, 'number')
|
||||
validate('col', col, 'number')
|
||||
|
||||
if buf == 0 then
|
||||
buf = api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
return M.new(buf, util.from_mark(lnum, col))
|
||||
end
|
||||
|
||||
--- Converts |vim.Pos| to extmark position (see |api-indexing|).
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local pos = vim.pos(0, 3, 5)
|
||||
---
|
||||
--- -- Convert to extmark position, you can call it in a method style.
|
||||
--- local extmark_pos = pos:to_extmark()
|
||||
--- ```
|
||||
---@param pos vim.Pos
|
||||
---@return integer, integer
|
||||
---@return integer row, integer col
|
||||
function M.to_extmark(pos)
|
||||
validate('pos', pos, 'table')
|
||||
return pos[1], pos[2]
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from extmark position (see |api-indexing|).
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local pos = vim.pos.extmark(0, 3, 5)
|
||||
--- ```
|
||||
---@param buf integer
|
||||
---@param row integer
|
||||
---@param col integer
|
||||
---@return vim.Pos
|
||||
function M.extmark(buf, row, col)
|
||||
validate('buf', buf, 'number')
|
||||
validate('row', row, 'number')
|
||||
validate('col', col, 'number')
|
||||
|
||||
if buf == 0 then
|
||||
buf = api.nvim_get_current_buf()
|
||||
end
|
||||
@@ -207,18 +270,40 @@ function M.extmark(buf, row, col)
|
||||
return M.new(buf, row, col)
|
||||
end
|
||||
|
||||
--- Converts |vim.Pos| to buffer offset.
|
||||
--- Converts |vim.Pos| to buffer (bytes) offset.
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local p1 = vim.pos(0, 3, 5)
|
||||
--- local p2 = vim.pos(0, 4, 0)
|
||||
---
|
||||
--- -- Convert to buffer offset, you can call it in a method style.
|
||||
--- local offset1 = p1:to_offset()
|
||||
--- local offset2 = p2:to_offset()
|
||||
--- -- Can be used to calculate the distance between two locations.
|
||||
--- local distance = offset2 - offset1
|
||||
--- ```
|
||||
---@param pos vim.Pos
|
||||
---@return integer
|
||||
function M.to_offset(pos)
|
||||
validate('pos', pos, 'table')
|
||||
return api.nvim_buf_get_offset(pos.buf, pos[1]) + pos[2]
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from buffer offset.
|
||||
--- Creates a new |vim.Pos| from buffer (bytes) offset.
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local offset = vim.api.nvim_buf_get_offset(0, vim.api.nvim_buf_line_count(0))
|
||||
--- local pos = vim.pos.offset(0, offset)
|
||||
--- ```
|
||||
---@param buf integer
|
||||
---@param offset integer
|
||||
---@return vim.Pos
|
||||
function M.offset(buf, offset)
|
||||
validate('buf', buf, 'number')
|
||||
validate('offset', offset, 'number')
|
||||
|
||||
local lnum = vim.list.bisect(
|
||||
setmetatable({}, {
|
||||
__index = function(_, lnum)
|
||||
|
||||
@@ -183,6 +183,7 @@ end
|
||||
---@param range vim.Range
|
||||
---@return boolean `true` if the given range is empty.
|
||||
function M.is_empty(range)
|
||||
validate('range', range, 'table')
|
||||
return util.cmp_pos.ge(range[1], range[2], range[3], range[4])
|
||||
end
|
||||
|
||||
@@ -192,6 +193,9 @@ end
|
||||
---@param inner vim.Range|vim.Pos
|
||||
---@return boolean `true` if {outer} range fully contains {inner} range or position.
|
||||
function M.has(outer, inner)
|
||||
validate('outer', outer, 'table')
|
||||
validate('inner', inner, 'table')
|
||||
|
||||
if getmetatable(inner) == vim.pos then
|
||||
---@cast inner -vim.Range
|
||||
return util.cmp_pos.le(outer[1], outer[2], inner[1], inner[2])
|
||||
@@ -225,6 +229,9 @@ end
|
||||
---@return vim.Range? range that is present inside both `r1` and `r2`.
|
||||
--- `nil` if such range does not exist.
|
||||
function M.intersect(r1, r2)
|
||||
validate('r1', r1, 'table')
|
||||
validate('r2', r2, 'table')
|
||||
|
||||
if r1.buf ~= r2.buf then
|
||||
return nil
|
||||
end
|
||||
@@ -285,6 +292,7 @@ end
|
||||
---@param buf integer
|
||||
---@param range lsp.Range
|
||||
---@param position_encoding lsp.PositionEncodingKind
|
||||
---@return vim.Range
|
||||
function M.lsp(buf, range, position_encoding)
|
||||
validate('buf', buf, 'number')
|
||||
validate('range', range, 'table')
|
||||
@@ -306,10 +314,10 @@ end
|
||||
--- local range = vim.range(0, 3, 5, 4, 0)
|
||||
---
|
||||
--- -- Convert to mark range, you can call it in a method style.
|
||||
--- local start_row, start_col, end_row, end_col = range:to_mark()
|
||||
--- local start_lnum, start_col, end_lnum, end_col = range:to_mark()
|
||||
--- ```
|
||||
---@param range vim.Range
|
||||
---@return integer, integer, integer, integer
|
||||
---@return integer start_lnum, integer start_col, integer end_lnum, integer end_col
|
||||
function M.to_mark(range)
|
||||
validate('range', range, 'table')
|
||||
|
||||
@@ -329,35 +337,36 @@ end
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- -- A range represented by marks may be end-inclusive (decided by 'selection' option).
|
||||
--- local start_row, start_col = unpack(api.nvim_buf_get_mark(bufnr, '<'))
|
||||
--- local end_row, end_col = unpack(api.nvim_buf_get_mark(bufnr, '>'))
|
||||
--- local start_lnum, start_col = unpack(api.nvim_buf_get_mark(bufnr, '<'))
|
||||
--- local end_lnum, end_col = unpack(api.nvim_buf_get_mark(bufnr, '>'))
|
||||
---
|
||||
--- -- Create an end-exclusive range.
|
||||
--- local range = vim.range.mark(0, start_row, start_col, end_row, end_col)
|
||||
--- local range = vim.range.mark(0, start_lnum, start_col, end_lnum, end_col)
|
||||
--- ```
|
||||
---@param buf integer
|
||||
---@param start_row integer
|
||||
---@param start_lnum integer
|
||||
---@param start_col integer
|
||||
---@param end_row integer
|
||||
---@param end_lnum integer
|
||||
---@param end_col integer
|
||||
function M.mark(buf, start_row, start_col, end_row, end_col)
|
||||
---@return vim.Range
|
||||
function M.mark(buf, start_lnum, start_col, end_lnum, end_col)
|
||||
validate('buf', buf, 'number')
|
||||
validate('start_row', start_row, 'number')
|
||||
validate('start_lnum', start_lnum, 'number')
|
||||
validate('start_col', start_col, 'number')
|
||||
validate('end_row', end_row, 'number')
|
||||
validate('end_lnum', end_lnum, 'number')
|
||||
validate('end_col', end_col, 'number')
|
||||
|
||||
if buf == 0 then
|
||||
buf = api.nvim_get_current_buf()
|
||||
end
|
||||
|
||||
start_row, start_col = util.from_mark(start_row, start_col)
|
||||
end_row, end_col = util.from_mark(end_row, end_col)
|
||||
start_lnum, start_col = util.from_mark(start_lnum, start_col)
|
||||
end_lnum, end_col = util.from_mark(end_lnum, end_col)
|
||||
|
||||
if vim.o.selection ~= 'exclusive' then
|
||||
end_row, end_col = to_exclusive_pos(buf, end_row, end_col)
|
||||
end_lnum, end_col = to_exclusive_pos(buf, end_lnum, end_col)
|
||||
end
|
||||
return M.new(buf, start_row, start_col, end_row, end_col)
|
||||
return M.new(buf, start_lnum, start_col, end_lnum, end_col)
|
||||
end
|
||||
|
||||
--- Converts |vim.Range| to extmark range (see |api-indexing|).
|
||||
@@ -370,6 +379,7 @@ end
|
||||
--- local extmark_range = range:to_extmark()
|
||||
--- ```
|
||||
---@param range vim.Range
|
||||
---@return integer start_row, integer start_col, integer end_row, integer end_col
|
||||
function M.to_extmark(range)
|
||||
validate('range', range, 'table')
|
||||
|
||||
@@ -406,6 +416,7 @@ end
|
||||
---@param start_col integer
|
||||
---@param end_row integer
|
||||
---@param end_col integer
|
||||
---@return vim.Range
|
||||
function M.extmark(buf, start_row, start_col, end_row, end_col)
|
||||
validate('buf', buf, 'number')
|
||||
validate('start_row', start_row, 'number')
|
||||
|
||||
Reference in New Issue
Block a user