Documentation for core.common (#1510)
* docs(core.common): add and improve documentation * refactor(core.common): remove unused variable to get_height() * docs(core.common): remove messy newlines * docs(core.common): fix wording * docs(core.common): use integer instead of number Co-authored-by: Guldoman <giulio.lettieri@gmail.com> * docs(core.common): update docs the docs now follow the style in docs/ directory. some of the changes suggested are also implemented. * docs(core.common): fix typo Co-authored-by: Guldoman <giulio.lettieri@gmail.com> * docs(core.common): restyle annoatations Extra whitespaces are removed and @overload is used whenever possible. * docs(core.common): fix various documentation errors * docs(core.common): simplify unicode description * docs(core.common): fix return value Co-authored-by: Guldoman <giulio.lettieri@gmail.com> * docs(core.common): clarify common.bench for not being a benchmark * docs(common): add disclaimer for numbers in common.serialize --------- Co-authored-by: Guldoman <giulio.lettieri@gmail.com>
This commit is contained in:
parent
82fa9bc363
commit
7b330ae81b
|
@ -1,22 +1,41 @@
|
|||
local common = {}
|
||||
|
||||
|
||||
---Checks if the byte at offset is a UTF-8 continuation byte.
|
||||
---
|
||||
---UTF-8 encodes code points in 1 to 4 bytes.
|
||||
---For a multi-byte sequence, each byte following the start byte is a continuation byte.
|
||||
---@param s string
|
||||
---@param offset? integer The offset of the string to start searching. Defaults to 1.
|
||||
---@return boolean
|
||||
function common.is_utf8_cont(s, offset)
|
||||
local byte = s:byte(offset or 1)
|
||||
return byte >= 0x80 and byte < 0xc0
|
||||
end
|
||||
|
||||
|
||||
---Returns an iterator that yields a UTF-8 character on each iteration.
|
||||
---@param text string
|
||||
---@return fun(): string
|
||||
function common.utf8_chars(text)
|
||||
return text:gmatch("[\0-\x7f\xc2-\xf4][\x80-\xbf]*")
|
||||
end
|
||||
|
||||
|
||||
---Clamps the number n between lo and hi.
|
||||
---@param n number
|
||||
---@param lo number
|
||||
---@param hi number
|
||||
---@return number
|
||||
function common.clamp(n, lo, hi)
|
||||
return math.max(math.min(n, hi), lo)
|
||||
end
|
||||
|
||||
|
||||
---Returns a new table containing the contents of b merged into a.
|
||||
---@param a table|nil
|
||||
---@param b table?
|
||||
---@return table
|
||||
function common.merge(a, b)
|
||||
a = type(a) == "table" and a or {}
|
||||
local t = {}
|
||||
|
@ -32,11 +51,19 @@ function common.merge(a, b)
|
|||
end
|
||||
|
||||
|
||||
---Returns the value of a number rounded to the nearest integer.
|
||||
---@param n number
|
||||
---@return number
|
||||
function common.round(n)
|
||||
return n >= 0 and math.floor(n + 0.5) or math.ceil(n - 0.5)
|
||||
end
|
||||
|
||||
|
||||
---Returns the first index where a subtable in tbl has prop set.
|
||||
---If none is found, nil is returned.
|
||||
---@param tbl table
|
||||
---@param prop any
|
||||
---@return number|nil
|
||||
function common.find_index(tbl, prop)
|
||||
for i, o in ipairs(tbl) do
|
||||
if o[prop] then return i end
|
||||
|
@ -44,6 +71,16 @@ function common.find_index(tbl, prop)
|
|||
end
|
||||
|
||||
|
||||
---Returns a value between a and b on a linear scale, based on the
|
||||
---interpolation point t.
|
||||
---
|
||||
---If a and b are tables, a table containing the result for all the
|
||||
---elements in a and b is returned.
|
||||
---@param a number
|
||||
---@param b number
|
||||
---@param t number
|
||||
---@return number
|
||||
---@overload fun(a: table, b: table, t: number): table
|
||||
function common.lerp(a, b, t)
|
||||
if type(a) ~= "table" then
|
||||
return a + (b - a) * t
|
||||
|
@ -56,11 +93,29 @@ function common.lerp(a, b, t)
|
|||
end
|
||||
|
||||
|
||||
---Returns the euclidean distance between two points.
|
||||
---@param x1 number
|
||||
---@param y1 number
|
||||
---@param x2 number
|
||||
---@param y2 number
|
||||
---@return number
|
||||
function common.distance(x1, y1, x2, y2)
|
||||
return math.sqrt(((x2-x1) ^ 2)+((y2-y1) ^ 2))
|
||||
end
|
||||
|
||||
|
||||
---Parses a CSS color string.
|
||||
---
|
||||
---Only these formats are supported:
|
||||
---* `rgb(r, g, b)`
|
||||
---* `rgba(r, g, b, a)`
|
||||
---* `#rrggbbaa`
|
||||
---* `#rrggbb`
|
||||
---@param str string
|
||||
---@return number r
|
||||
---@return number g
|
||||
---@return number b
|
||||
---@return number a
|
||||
function common.color(str)
|
||||
local r, g, b, a = str:match("^#(%x%x)(%x%x)(%x%x)(%x?%x?)$")
|
||||
if r then
|
||||
|
@ -81,6 +136,12 @@ function common.color(str)
|
|||
end
|
||||
|
||||
|
||||
---Splices a numerically indexed table.
|
||||
---This function mutates the original table.
|
||||
---@param t any[]
|
||||
---@param at number Index at which to start splicing.
|
||||
---@param remove number Number of elements to remove.
|
||||
---@param insert? any[] A table containing elements to insert after splicing.
|
||||
function common.splice(t, at, remove, insert)
|
||||
assert(remove >= 0, "bad argument #3 to 'splice' (non-negative value expected)")
|
||||
insert = insert or {}
|
||||
|
@ -110,6 +171,16 @@ local function fuzzy_match_items(items, needle, files)
|
|||
end
|
||||
|
||||
|
||||
---Performs fuzzy matching.
|
||||
---
|
||||
---If the haystack is a string, a score ranging from 0 to 1 is returned. </br>
|
||||
---If the haystack is a table, a table containing the haystack sorted in ascending
|
||||
---order of similarity is returned.
|
||||
---@param haystack string
|
||||
---@param needle string
|
||||
---@param files boolean If true, the matching process will be performed in reverse to better match paths.
|
||||
---@return number
|
||||
---@overload fun(haystack: string[], needle: string, files: boolean): string[]
|
||||
function common.fuzzy_match(haystack, needle, files)
|
||||
if type(haystack) == "table" then
|
||||
return fuzzy_match_items(haystack, needle, files)
|
||||
|
@ -118,6 +189,14 @@ function common.fuzzy_match(haystack, needle, files)
|
|||
end
|
||||
|
||||
|
||||
---Performs fuzzy matching and returns recently used strings if needed.
|
||||
---
|
||||
---If the needle is empty, then a list of recently used strings
|
||||
---are added to the result, followed by strings from the haystack.
|
||||
---@param haystack string[]
|
||||
---@param recents string[]
|
||||
---@param needle string
|
||||
---@return string[]
|
||||
function common.fuzzy_match_with_recents(haystack, recents, needle)
|
||||
if needle == "" then
|
||||
local recents_ext = {}
|
||||
|
@ -136,6 +215,13 @@ function common.fuzzy_match_with_recents(haystack, recents, needle)
|
|||
end
|
||||
|
||||
|
||||
---Returns a list of paths that are relative to the input path.
|
||||
---
|
||||
---If a root directory is specified, the function returns paths
|
||||
---that are relative to the root directory.
|
||||
---@param text string The input path.
|
||||
---@param root? string The root directory.
|
||||
---@return string[]
|
||||
function common.path_suggest(text, root)
|
||||
if root and root:sub(-1) ~= PATHSEP then
|
||||
root = root .. PATHSEP
|
||||
|
@ -189,6 +275,9 @@ function common.path_suggest(text, root)
|
|||
end
|
||||
|
||||
|
||||
---Returns a list of directories that are related to a path.
|
||||
---@param text string The input path.
|
||||
---@return string[]
|
||||
function common.dir_path_suggest(text)
|
||||
local path, name = text:match("^(.-)([^/\\]*)$")
|
||||
local files = system.list_dir(path == "" and "." or path) or {}
|
||||
|
@ -204,6 +293,10 @@ function common.dir_path_suggest(text)
|
|||
end
|
||||
|
||||
|
||||
---Filters a list of paths to find those that are related to the input path.
|
||||
---@param text string The input path.
|
||||
---@param dir_list string[] A list of paths to filter.
|
||||
---@return string[]
|
||||
function common.dir_list_suggest(text, dir_list)
|
||||
local path, name = text:match("^(.-)([^/\\]*)$")
|
||||
local res = {}
|
||||
|
@ -216,6 +309,15 @@ function common.dir_list_suggest(text, dir_list)
|
|||
end
|
||||
|
||||
|
||||
---Matches a string against a list of patterns.
|
||||
---
|
||||
---If a match was found, its start and end index is returned.
|
||||
---Otherwise, false is returned.
|
||||
---@param text string
|
||||
---@param pattern string|string[]
|
||||
---@param ... any Other options for string.find().
|
||||
---@return number|boolean start_index
|
||||
---@return number|nil end_index
|
||||
function common.match_pattern(text, pattern, ...)
|
||||
if type(pattern) == "string" then
|
||||
return text:find(pattern, ...)
|
||||
|
@ -228,8 +330,24 @@ function common.match_pattern(text, pattern, ...)
|
|||
end
|
||||
|
||||
|
||||
---Draws text onto the window.
|
||||
---The function returns the X and Y coordinates of the bottom-right
|
||||
---corner of the text.
|
||||
---@param font renderer.font
|
||||
---@param color renderer.color
|
||||
---@param text string
|
||||
---@param align string
|
||||
---| '"left"' # Align text to the left of the bounding box
|
||||
---| '"right"' # Align text to the right of the bounding box
|
||||
---| '"center"' # Center text in the bounding box
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
---@param h number
|
||||
---@return number x_advance
|
||||
---@return number y_advance
|
||||
function common.draw_text(font, color, text, align, x,y,w,h)
|
||||
local tw, th = font:get_width(text), font:get_height(text)
|
||||
local tw, th = font:get_width(text), font:get_height()
|
||||
if align == "center" then
|
||||
x = x + (w - tw) / 2
|
||||
elseif align == "right" then
|
||||
|
@ -240,6 +358,16 @@ function common.draw_text(font, color, text, align, x,y,w,h)
|
|||
end
|
||||
|
||||
|
||||
---Prints the execution time of a function.
|
||||
---
|
||||
---The execution time and percentage of frame time
|
||||
---for the function is printed to standard output. </br>
|
||||
---The frame rate is always assumed to be 60 FPS, thus
|
||||
---a value of 100% would mean that the benchmark took
|
||||
---1/60 of a second to execute.
|
||||
---@param name string
|
||||
---@param fn fun(...: any): any
|
||||
---@return any # The result returned by the function
|
||||
function common.bench(name, fn, ...)
|
||||
local start = system.get_time()
|
||||
local res = fn(...)
|
||||
|
@ -285,14 +413,28 @@ local function serialize(val, pretty, indent_str, escape, sort, limit, level)
|
|||
return tostring(val)
|
||||
end
|
||||
|
||||
-- Serialize `val` into a parsable string.
|
||||
-- Available options
|
||||
-- * pretty: enable pretty printing
|
||||
-- * indent_str: indent to use (" " by default)
|
||||
-- * escape: use normal escape characters instead of the ones used by string.format("%q", ...)
|
||||
-- * sort: sort the keys inside tables
|
||||
-- * limit: limit how deep to serialize
|
||||
-- * initial_indent: the initial indentation level
|
||||
|
||||
---@class common.serializeoptions
|
||||
---@field pretty boolean Enables pretty printing.
|
||||
---@field indent_str string The indentation character to use. Defaults to `" "`.
|
||||
---@field escape boolean Uses normal escape characters ("\n") instead of decimal escape sequences ("\10").
|
||||
---@field limit number Limits the depth when serializing nested tables. Defaults to `math.huge`.
|
||||
---@field sort boolean Sorts the output if it is a sortable table.
|
||||
---@field initial_indent number The initial indentation level. Defaults to 0.
|
||||
|
||||
---Serializes a value into a Lua string that is loadable with load().
|
||||
---
|
||||
---Only these basic types are supported:
|
||||
---* nil
|
||||
---* boolean
|
||||
---* number (except very large numbers and special constants, e.g. `math.huge`, `inf` and `nan`)
|
||||
---* integer
|
||||
---* string
|
||||
---* table
|
||||
---
|
||||
---@param val any
|
||||
---@param opts? common.serializeoptions
|
||||
---@return string
|
||||
function common.serialize(val, opts)
|
||||
opts = opts or {}
|
||||
local indent_str = opts.indent_str or " "
|
||||
|
@ -304,6 +446,9 @@ function common.serialize(val, opts)
|
|||
end
|
||||
|
||||
|
||||
---Returns the last portion of a path.
|
||||
---@param path string
|
||||
---@return string
|
||||
function common.basename(path)
|
||||
-- a path should never end by / or \ except if it is '/' (unix root) or
|
||||
-- 'X:\' (windows drive)
|
||||
|
@ -311,12 +456,18 @@ function common.basename(path)
|
|||
end
|
||||
|
||||
|
||||
-- can return nil if there is no directory part in the path
|
||||
---Returns the directory name of a path.
|
||||
---If the path doesn't have a directory, this function may return nil.
|
||||
---@param path string
|
||||
---@return string|nil
|
||||
function common.dirname(path)
|
||||
return path:match("(.+)[\\/][^\\/]+$")
|
||||
end
|
||||
|
||||
|
||||
---Returns a path where the user's home directory is replaced by `"~"`.
|
||||
---@param text string
|
||||
---@return string
|
||||
function common.home_encode(text)
|
||||
if HOME and string.find(text, HOME, 1, true) == 1 then
|
||||
local dir_pos = #HOME + 1
|
||||
|
@ -330,6 +481,9 @@ function common.home_encode(text)
|
|||
end
|
||||
|
||||
|
||||
---Returns a list of paths where the user's home directory is replaced by `"~"`.
|
||||
---@param paths string[] A list of paths to encode
|
||||
---@return string[]
|
||||
function common.home_encode_list(paths)
|
||||
local t = {}
|
||||
for i = 1, #paths do
|
||||
|
@ -339,6 +493,10 @@ function common.home_encode_list(paths)
|
|||
end
|
||||
|
||||
|
||||
---Expands the `"~"` prefix in a path into the user's home directory.
|
||||
---This function is not guaranteed to return an absolute path.
|
||||
---@param text string
|
||||
---@return string
|
||||
function common.home_expand(text)
|
||||
return HOME and text:gsub("^~", HOME) or text
|
||||
end
|
||||
|
@ -356,12 +514,13 @@ local function split_on_slash(s, sep_pattern)
|
|||
end
|
||||
|
||||
|
||||
-- The filename argument given to the function is supposed to
|
||||
-- come from system.absolute_path and as such should be an
|
||||
-- absolute path without . or .. elements.
|
||||
-- This function exists because on Windows the drive letter returned
|
||||
-- by system.absolute_path is sometimes with a lower case and sometimes
|
||||
-- with an upper case so we normalize to upper case.
|
||||
---Normalizes the drive letter in a Windows path to uppercase.
|
||||
---This function expects an absolute path, e.g. a path from `system.absolute_path`.
|
||||
---
|
||||
---This function is needed because the path returned by `system.absolute_path`
|
||||
---may contain drive letters in upper or lowercase.
|
||||
---@param filename string|nil The input path.
|
||||
---@return string|nil
|
||||
function common.normalize_volume(filename)
|
||||
if not filename then return end
|
||||
if PATHSEP == '\\' then
|
||||
|
@ -374,6 +533,13 @@ function common.normalize_volume(filename)
|
|||
end
|
||||
|
||||
|
||||
---Normalizes a path into the same format across platforms.
|
||||
---
|
||||
---On Windows, all drive letters are converted to uppercase.
|
||||
---UNC paths with drive letters are converted back to ordinary Windows paths.
|
||||
---All path separators (`"/"`, `"\\"`) are converted to platform-specific ones.
|
||||
---@param filename string|nil
|
||||
---@return string|nil
|
||||
function common.normalize_path(filename)
|
||||
if not filename then return end
|
||||
local volume
|
||||
|
@ -414,16 +580,27 @@ function common.normalize_path(filename)
|
|||
end
|
||||
|
||||
|
||||
---Checks whether a path is absolute or relative.
|
||||
---@param path string
|
||||
---@return boolean
|
||||
function common.is_absolute_path(path)
|
||||
return path:sub(1, 1) == PATHSEP or path:match("^(%a):\\")
|
||||
end
|
||||
|
||||
|
||||
---Checks whether a path belongs to a parent directory.
|
||||
---@param filename string The path to check.
|
||||
---@param path string The parent path.
|
||||
---@return boolean
|
||||
function common.path_belongs_to(filename, path)
|
||||
return string.find(filename, path .. PATHSEP, 1, true) == 1
|
||||
end
|
||||
|
||||
|
||||
---Checks whether a path is relative to another path.
|
||||
---@param ref_dir string The path to check against.
|
||||
---@param dir string The input path.
|
||||
---@return boolean
|
||||
function common.relative_path(ref_dir, dir)
|
||||
local drive_pattern = "^(%a):\\"
|
||||
local drive, ref_drive = dir:match(drive_pattern), ref_dir:match(drive_pattern)
|
||||
|
@ -449,6 +626,11 @@ function common.relative_path(ref_dir, dir)
|
|||
end
|
||||
|
||||
|
||||
---Creates a directory recursively if necessary.
|
||||
---@param path string
|
||||
---@return boolean success
|
||||
---@return string|nil error
|
||||
---@return string|nil path The path where an error occured.
|
||||
function common.mkdirp(path)
|
||||
local stat = system.get_file_info(path)
|
||||
if stat and stat.type then
|
||||
|
@ -471,6 +653,13 @@ function common.mkdirp(path)
|
|||
return true
|
||||
end
|
||||
|
||||
|
||||
---Removes a path.
|
||||
---@param path string
|
||||
---@param recursively boolean If true, the function will attempt to remove everything in the specified path.
|
||||
---@return boolean success
|
||||
---@return string|nil error
|
||||
---@return string|nil path The path where the error occured.
|
||||
function common.rm(path, recursively)
|
||||
local stat = system.get_file_info(path)
|
||||
if not stat or (stat.type ~= "file" and stat.type ~= "dir") then
|
||||
|
|
Loading…
Reference in New Issue