2017-03-12 00:57:32 +01:00
|
|
|
---------------------------------------------------------------------------
|
2021-12-21 06:54:15 +01:00
|
|
|
--- Various string manipulation and introspection fuctions.
|
2017-03-12 00:57:32 +01:00
|
|
|
--
|
2019-06-06 09:40:17 +02:00
|
|
|
-- @utillib gears.string
|
2017-03-12 00:57:32 +01:00
|
|
|
---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
local gstring = {}
|
|
|
|
|
|
|
|
local xml_entity_names = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" };
|
2019-06-08 01:08:05 +02:00
|
|
|
|
2017-03-12 00:57:32 +01:00
|
|
|
--- Escape a string from XML char.
|
|
|
|
-- Useful to set raw text in textbox.
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam string text Text to escape.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @treturn string Escaped text.
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.xml_escape
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.xml_escape(text)
|
|
|
|
return text and text:gsub("['&<>\"]", xml_entity_names) or nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local xml_entity_chars = { lt = "<", gt = ">", nbsp = " ", quot = "\"", apos = "'", ndash = "-", mdash = "-",
|
2019-06-08 01:08:05 +02:00
|
|
|
amp = "&" };
|
|
|
|
|
2017-03-12 00:57:32 +01:00
|
|
|
--- Unescape a string from entities.
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam string text Text to unescape.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @treturn string Unescaped text.
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.xml_unescape
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.xml_unescape(text)
|
|
|
|
return text and text:gsub("&(%a+);", xml_entity_chars) or nil
|
|
|
|
end
|
|
|
|
|
2019-12-13 21:19:38 +01:00
|
|
|
--- Count number of lines in a string.
|
|
|
|
-- @DOC_text_gears_string_linecount_EXAMPLE@
|
2017-03-12 00:57:32 +01:00
|
|
|
-- @tparam string text Input string.
|
|
|
|
-- @treturn int Number of lines.
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.linecount
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.linecount(text)
|
|
|
|
return select(2, text:gsub('\n', '\n')) + 1
|
|
|
|
end
|
|
|
|
|
2019-06-08 01:08:05 +02:00
|
|
|
--- Split a string into multiple lines.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @DOC_text_gears_string_linewrap_EXAMPLE@
|
|
|
|
-- @tparam string text String to wrap.
|
|
|
|
-- @tparam number width Maximum length of each line. Default: 72.
|
|
|
|
-- @tparam number indent Number of spaces added before each wrapped line. Default: 0.
|
|
|
|
-- @treturn string The string with lines wrapped to width.
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.linewrap
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.linewrap(text, width, indent)
|
|
|
|
text = text or ""
|
|
|
|
width = width or 72
|
|
|
|
indent = indent or 0
|
|
|
|
|
|
|
|
local pos = 1
|
|
|
|
return text:gsub("(%s+)()(%S+)()",
|
|
|
|
function(_, st, word, fi)
|
|
|
|
if fi - pos > width then
|
|
|
|
pos = st
|
|
|
|
return "\n" .. string.rep(" ", indent) .. word
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Escape all special pattern-matching characters so that lua interprets them
|
|
|
|
-- literally instead of as a character class.
|
|
|
|
-- Source: http://stackoverflow.com/a/20778724/15690
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @DOC_text_gears_string_quote_pattern_EXAMPLE@
|
|
|
|
-- @tparam string s String to generate pattern for
|
|
|
|
-- @treturn string string with escaped characters
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.quote_pattern
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.quote_pattern(s)
|
|
|
|
-- All special characters escaped in a string: %%, %^, %$, ...
|
|
|
|
local patternchars = '['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..']'
|
|
|
|
return string.gsub(s, patternchars, "%%%1")
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Generate a pattern matching expression that ignores case.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @tparam string q Original pattern matching expression.
|
2022-07-05 10:37:14 +02:00
|
|
|
-- @treturn string The pattern.
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.query_to_pattern
|
2017-03-12 00:57:32 +01:00
|
|
|
function gstring.query_to_pattern(q)
|
|
|
|
local s = gstring.quote_pattern(q)
|
|
|
|
-- Poor man's case-insensitive character matching.
|
|
|
|
s = string.gsub(s, "%a",
|
|
|
|
function (c)
|
|
|
|
return string.format("[%s%s]", string.lower(c),
|
|
|
|
string.upper(c))
|
|
|
|
end)
|
|
|
|
return s
|
|
|
|
end
|
2017-03-18 01:13:11 +01:00
|
|
|
|
2023-11-19 02:14:35 +01:00
|
|
|
|
2017-03-18 01:13:11 +01:00
|
|
|
--- Split separates a string containing a delimiter into the list of
|
|
|
|
-- substrings between that delimiter.
|
|
|
|
-- @tparam string str String to be splitted
|
|
|
|
-- @tparam string delimiter Character where the string will be splitted
|
|
|
|
-- @treturn table list of the substrings
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.split
|
2017-03-18 01:13:11 +01:00
|
|
|
function gstring.split(str, delimiter)
|
2020-01-20 01:04:28 +01:00
|
|
|
delimiter = delimiter or "\n"
|
2017-03-18 01:13:11 +01:00
|
|
|
local result = {}
|
2020-01-20 01:04:28 +01:00
|
|
|
if gstring.startswith(str, delimiter) then
|
|
|
|
result[#result+1] = ""
|
|
|
|
end
|
|
|
|
local pattern = string.format("([^%s]+)", delimiter)
|
|
|
|
str:gsub(pattern, function(c) result[#result+1] = c end)
|
|
|
|
if gstring.endswith(str, delimiter) then
|
|
|
|
result[#result+1] = ""
|
|
|
|
end
|
|
|
|
if #result == 0 then
|
|
|
|
result[#result+1] = str
|
2017-03-18 01:13:11 +01:00
|
|
|
end
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
2023-11-19 02:14:35 +01:00
|
|
|
|
|
|
|
--- Pattern split separates a string by a pattern to the table of substrings.
|
|
|
|
-- @tparam string str String to be splitted
|
|
|
|
-- @tparam string[opt="\n"] pattern Pattern the target string will
|
|
|
|
-- be splitted by.
|
|
|
|
-- @treturn table A list of substrings.
|
|
|
|
-- @staticfct gears.string.split
|
|
|
|
function gstring.psplit(str, pattern)
|
|
|
|
pattern = pattern or "\n"
|
|
|
|
local result = {}
|
|
|
|
if #pattern == 0 then
|
|
|
|
for index = 1, #str do
|
|
|
|
result[#result+1] = str:sub(index, index)
|
|
|
|
end
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
local pos = 1
|
|
|
|
for match in str:gmatch(pattern) do
|
|
|
|
local start_pos, end_pos = str:find(match, pos, true)
|
|
|
|
result[#result+1] = str:sub(pos, start_pos-1)
|
|
|
|
pos = end_pos+1
|
|
|
|
end
|
|
|
|
result[#result+1] = str:sub(pos, #str)
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2019-06-08 01:08:05 +02:00
|
|
|
--- Check if a string starts with another string.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @DOC_text_gears_string_startswith_EXAMPLE@
|
2017-08-14 17:48:12 +02:00
|
|
|
-- @tparam string str String to search
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @treturn boolean `true` if string starts with specified string
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @tparam string sub String to check for.
|
|
|
|
-- @staticfct gears.string.startswith
|
2017-08-14 17:48:12 +02:00
|
|
|
function gstring.startswith(str, sub)
|
2021-01-26 17:58:25 +01:00
|
|
|
return str and (string.sub(str, 1, string.len(sub)) == sub) or false
|
2017-08-14 17:48:12 +02:00
|
|
|
end
|
|
|
|
|
2019-06-08 01:08:05 +02:00
|
|
|
--- Check if a string ends with another string.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @DOC_text_gears_string_endswith_EXAMPLE@
|
2017-08-14 17:48:12 +02:00
|
|
|
-- @tparam string str String to search
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @tparam string sub String to check for.
|
2019-12-13 21:19:38 +01:00
|
|
|
-- @treturn boolean `true` if string ends with specified string
|
2019-06-08 01:08:05 +02:00
|
|
|
-- @staticfct gears.string.endswith
|
2017-08-14 17:48:12 +02:00
|
|
|
function gstring.endswith(str, sub)
|
2021-01-26 17:58:25 +01:00
|
|
|
return str and (sub == "" or string.sub(str,-string.len(sub)) == sub) or false
|
2017-08-14 17:48:12 +02:00
|
|
|
end
|
|
|
|
|
2017-03-12 00:57:32 +01:00
|
|
|
return gstring
|