-
-
Notifications
You must be signed in to change notification settings - Fork 267
util: Add types & docs for str utils, cleanup old functions #1419
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
c51c1d8
9642899
a0fc0ba
fa4a5ea
bb1c84d
6deeec4
803915f
60025d3
92f82d2
509776d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,15 @@ | ||
| -- Some string processing utility functions | ||
| local M = {} | ||
|
|
||
| ---In-place dedents strings in lines. | ||
| ---@param lines string[]. | ||
| --- In-place dedents strings in lines. | ||
| ---@param lines string[] | ||
| local function dedent(lines) | ||
| if #lines > 0 then | ||
| local ind_size = math.huge | ||
| for i, _ in ipairs(lines) do | ||
| local i1, i2 = lines[i]:find("^%s*[^%s]") | ||
| if i1 and i2 < ind_size then | ||
| ---@cast i2 -nil | ||
| ind_size = i2 | ||
| end | ||
| end | ||
|
|
@@ -18,7 +19,7 @@ local function dedent(lines) | |
| end | ||
| end | ||
|
|
||
| ---Convert string `from` to unit indent | ||
| --- In-place convert string `from` to unit indent in lines. | ||
| ---@param lines string[] | ||
| ---@param from string | ||
| ---@param unit_indent string | ||
|
|
@@ -51,15 +52,17 @@ local function convert_indent(lines, from, unit_indent) | |
| end | ||
| end | ||
|
|
||
| ---Applies opts to lines. | ||
| ---lines is modified in-place. | ||
| ---@param lines string[]. | ||
| ---@param options table, required, can have values: | ||
| --- - trim_empty: removes empty first and last lines. | ||
| --- - dedent: removes indent common to all lines. | ||
| --- - indent_string: an unit indent at beginning of each line after applying `dedent`, default empty string (disabled) | ||
| function M.process_multiline(lines, options) | ||
| if options.trim_empty then | ||
| ---@class LuaSnip.Opts.Str.MultilineProcess | ||
| ---@field trim_empty? boolean Whether to remove whitespace-only first/last lines | ||
| ---@field dedent? boolean Whether to remove all common indent in `str`. | ||
| ---@field indent_string? string When set, will convert `indent_string` at | ||
| --- beginning of each line to unit indent ('\t') after applying `dedent`. | ||
|
|
||
| --- In-place process lines with given opts. | ||
| ---@param lines string[] | ||
| ---@param opts LuaSnip.Opts.Str.MultilineProcess | ||
| function M.process_multiline(lines, opts) | ||
| if opts.trim_empty then | ||
| if lines[1]:match("^%s*$") then | ||
| table.remove(lines, 1) | ||
| end | ||
|
|
@@ -68,21 +71,28 @@ function M.process_multiline(lines, options) | |
| end | ||
| end | ||
|
|
||
| if options.dedent then | ||
| if opts.dedent then | ||
| dedent(lines) | ||
| end | ||
|
|
||
| if options.indent_string and #options.indent_string > 0 then | ||
| convert_indent(lines, options.indent_string, "\t") | ||
| if opts.indent_string and #opts.indent_string > 0 then | ||
| convert_indent(lines, opts.indent_string, "\t") | ||
| end | ||
| end | ||
|
|
||
| --- Remove common indentation from the given string. | ||
| ---@param s string | ||
| ---@return string | ||
| function M.dedent(s) | ||
| local lst = vim.split(s, "\n") | ||
| dedent(lst) | ||
| return table.concat(lst, "\n") | ||
| end | ||
|
|
||
| --- Convert string `indent_string` to unit indent (\t) in given string. | ||
| ---@param s string | ||
| ---@param indent_string string | ||
| ---@return string | ||
| function M.convert_indent(s, indent_string) | ||
| local lst = vim.split(s, "\n") | ||
| convert_indent(lst, indent_string, "\t") | ||
|
|
@@ -101,11 +111,12 @@ local function is_escaped(s, indx) | |
| return count % 2 == 1 | ||
| end | ||
|
|
||
| --- return position of next (relative to `start`) unescaped occurence of | ||
| --- Return position of next (relative to `start`) unescaped occurence of | ||
| --- `target` in `s`. | ||
| ---@param s string | ||
| ---@param target string | ||
| ---@param start number | ||
| ---@param start integer | ||
| ---@return integer? | ||
| local function find_next_unescaped(s, target, start) | ||
| while true do | ||
| local from = s:find(target, start, true) | ||
|
|
@@ -125,7 +136,7 @@ end | |
| ---@param s string | ||
| ---@param left string | ||
| ---@param right string | ||
| ---@return function: iterator, returns pairs from,to. | ||
| ---@return fun(): (integer?, integer?) An iterator returning pairs from,to. | ||
| function M.unescaped_pairs(s, left, right) | ||
| local search_from = 1 | ||
|
|
||
|
|
@@ -144,6 +155,7 @@ function M.unescaped_pairs(s, left, right) | |
| end | ||
| end | ||
|
|
||
| -- FIXME(@L3MON4D3): not used anywhere? | ||
| function M.aupatescape(s) | ||
| if vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 then | ||
| -- windows: replace \ with / for au-pattern. | ||
|
|
@@ -153,20 +165,26 @@ function M.aupatescape(s) | |
| return vim.fn.fnameescape(escaped) | ||
| end | ||
|
|
||
| --- Sanitize the given string (e.g. \r) | ||
| ---@param str string | ||
| ---@return string | ||
| function M.sanitize(str) | ||
| return str:gsub("%\r", "") | ||
| local ret = str:gsub("%\r", "") | ||
| return ret -- note: local var required for correct typing | ||
| end | ||
|
|
||
| -- requires that from and to are within the region of str. | ||
| -- str is treated as a 0,0-indexed, and the character at `to` is excluded from | ||
| -- the result. | ||
| -- `from` may not be before `to`. | ||
| function M.multiline_substr(str, from, to) | ||
| --- Extract a rectangular block of lines in a multiline string area. | ||
| ---@param lines string[] | ||
| ---@param from LuaSnip.Pos00 From this position, MUST be within `lines`. | ||
| ---@param to LuaSnip.Pos00 To this position (excluded), MUST be within `lines` | ||
|
bew marked this conversation as resolved.
Outdated
|
||
| --- and before `from`. | ||
| ---@return string[] | ||
| function M.multiline_substr(lines, from, to) | ||
| local res = {} | ||
|
|
||
| -- include all rows | ||
| for i = from[1], to[1] do | ||
| table.insert(res, str[i + 1]) | ||
| table.insert(res, lines[i + 1]) | ||
| end | ||
|
|
||
| -- trim text before from and after to. | ||
|
|
@@ -179,35 +197,42 @@ function M.multiline_substr(str, from, to) | |
| return res | ||
| end | ||
|
|
||
| function M.multiline_upper(str) | ||
| for i, s in ipairs(str) do | ||
| str[i] = s:upper() | ||
| --- In-place uppercase all text in `lines` | ||
| ---@param lines string[] | ||
| function M.multiline_upper(lines) | ||
| for i, s in ipairs(lines) do | ||
| lines[i] = s:upper() | ||
| end | ||
| end | ||
| function M.multiline_lower(str) | ||
| for i, s in ipairs(str) do | ||
| str[i] = s:lower() | ||
|
|
||
| --- In-place lowercase all text in `lines` | ||
| ---@param lines string[] | ||
| function M.multiline_lower(lines) | ||
| for i, s in ipairs(lines) do | ||
| lines[i] = s:lower() | ||
| end | ||
| end | ||
|
|
||
| -- modifies strmod | ||
| -- FIXME(@L3MON4D3): not used anywhere? | ||
|
bew marked this conversation as resolved.
Outdated
|
||
| function M.multiline_append(strmod, strappend) | ||
| strmod[#strmod] = strmod[#strmod] .. strappend[1] | ||
| for i = 2, #strappend do | ||
| table.insert(strmod, strappend[i]) | ||
| end | ||
| end | ||
|
|
||
| -- turn a row+col-offset for a multiline-string (string[]) (where the column is | ||
| -- given in bytes and 0-based) into an offset (in bytes, 1-based) for | ||
| -- the \n-concatenated version of that string. | ||
| --- Turns a row+col-offset for a multiline-string (string[]) (where the column is | ||
| --- given in bytes and 0-based) into an offset (in bytes, 1-based) for | ||
| --- the \n-concatenated version of that string. | ||
| --- | ||
| ---@param str string[], a multiline string | ||
| ---@param pos LuaSnip.ApiPosition, an api-position relative to the start of str. | ||
| function M.multiline_to_byte_offset(str, pos) | ||
| if pos[1] < 0 or pos[1] + 1 > #str or pos[2] < 0 then | ||
| ---@param lines string[] a multiline string | ||
| ---@param pos LuaSnip.ApiPosition an api-position relative to the start of str. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| ---@return integer? | ||
| function M.multiline_to_byte_offset(lines, pos) | ||
| if pos[1] < 0 or pos[1] + 1 > #lines or pos[2] < 0 then | ||
| -- pos is trivially (row negative or beyond str, or col negative) | ||
| -- outside of str, can't represent position in str. | ||
| -- outside of lines, can't represent position in lines. | ||
| -- col-wise outside will be determined later, but we want this | ||
| -- precondition for following code. | ||
| return nil | ||
|
|
@@ -216,12 +241,12 @@ function M.multiline_to_byte_offset(str, pos) | |
| local byte_pos = 0 | ||
| for i = 1, pos[1] do | ||
| -- increase index by full lines, don't forget +1 for \n. | ||
| byte_pos = byte_pos + #str[i] + 1 | ||
| byte_pos = byte_pos + #lines[i] + 1 | ||
| end | ||
|
|
||
| -- allow positions one beyond the last character for all lines (even the | ||
| -- last line). | ||
| if pos[2] >= #str[pos[1] + 1] + 1 then | ||
| if pos[2] >= #lines[pos[1] + 1] + 1 then | ||
| -- in this case, pos is outside of the multiline-region. | ||
| return nil | ||
| end | ||
|
|
@@ -233,16 +258,18 @@ function M.multiline_to_byte_offset(str, pos) | |
| return byte_pos + 1 | ||
| end | ||
|
|
||
| -- inverse of multiline_to_byte_offset, 1-based byte to 0,0-based row,column. | ||
| ---@param str string[], the multiline string | ||
| ---@param byte_pos number, a 1-based index into the \n-concatenated `str`. | ||
| function M.byte_to_multiline_offset(str, byte_pos) | ||
| --- Convert a 1-based byte index in a multiline string to 0,0-based row,column. | ||
| --- (It is functionally the inverse of multiline_to_byte_offset) | ||
| ---@param lines string[] the multiline string | ||
| ---@param byte_pos number 1-based index into the \n-concatenated `lines`. | ||
| ---@return LuaSnip.Pos00? | ||
| function M.byte_to_multiline_offset(lines, byte_pos) | ||
| if byte_pos < 0 then | ||
| return nil | ||
| end | ||
|
|
||
| local byte_pos_so_far = 0 | ||
| for i, line in ipairs(str) do | ||
| for i, line in ipairs(lines) do | ||
| -- line-length + \n. | ||
| local line_i_end = byte_pos_so_far + #line + 1 | ||
| if byte_pos <= line_i_end then | ||
|
|
@@ -256,27 +283,36 @@ end | |
| -- string-operations implemented according to | ||
| -- https://github.com/microsoft/vscode/blob/71c221c532996c9976405f62bb888283c0cf6545/src/vs/editor/contrib/snippet/browser/snippetParser.ts#L372-L415 | ||
| -- such that they can be used for snippet-transformations in vscode-snippets. | ||
| ---@param str string | ||
| ---@return string | ||
| local function capitalize(str) | ||
| -- uppercase first character. | ||
| return str:gsub("^.", string.upper) | ||
| local ret = str:gsub("^.", string.upper) | ||
| return ret -- note: local var required for correct typing | ||
| end | ||
| ---@param str string | ||
| ---@return string | ||
| local function pascalcase(str) | ||
| local pascalcased = "" | ||
| for match in str:gmatch("[a-zA-Z0-9]+") do | ||
| pascalcased = pascalcased .. capitalize(match) | ||
| end | ||
| return pascalcased | ||
| end | ||
| ---@param str string | ||
| ---@return string | ||
| local function camelcase(str) | ||
| -- same as pascalcase, but first character lowercased. | ||
| local ret = pascalcase(str):gsub("^.", string.lower) | ||
| return ret -- note: local var required for correct typing | ||
| end | ||
|
|
||
| M.vscode_string_modifiers = { | ||
| upcase = string.upper, | ||
| downcase = string.lower, | ||
| capitalize = capitalize, | ||
| pascalcase = pascalcase, | ||
| camelcase = function(str) | ||
| -- same as pascalcase, but first character lowercased. | ||
| return pascalcase(str):gsub("^.", string.lower) | ||
| end, | ||
| camelcase = camelcase, | ||
| } | ||
|
|
||
| return M | ||
Uh oh!
There was an error while loading. Please reload this page.