Files
LeonOS/data/computercraft/lua/rom/modules/main/cc/strings.lua

134 lines
2.9 KiB
Lua
Raw Normal View History

-- cc.strings
local term = require("term")
local expectlib = require("cc.expect")
local expect = expectlib.expect
local field = expectlib.field
local strings = {}
local function count(...)
local tab = table.pack(...)
local n = 0
for i=1, tab.n, 1 do
if tab[i] then n = n + 1 end
end
return n
end
function strings.splitElements(text, limit)
expect(1, text, "string")
expect(2, limit, "number", "nil")
local tokens = {}
while #text > 0 do
local ws = text:match("^[ \t]+")
local nl = text:match("^\n+")
local sep = text:match("^[%-%+%*]")
local word = text:match("^[^ \t\n%-%+%*]+")
if count(ws, nl, sep, word) > 1 then
error(("Edge case: %q, %q, %q, %q"):format(ws, nl, sep, word), 0)
end
local token = ws or nl or sep or word
text = text:sub(#token + 1)
while #token > 0 do
local ttext = token:sub(1, limit or 65535)
token = token:sub(#ttext + 1)
tokens[#tokens+1] = { text = ttext, type = ws and "ws" or nl and "nl"
or sep and "word" or word and "word" }
end
end
return tokens
end
function strings.wrappedWriteElements(elements, width, doHalves, handler)
expect(1, elements, "table")
expect(2, width, "number")
expect(3, doHalves, "boolean", "nil")
expect(4, handler, "table")
field(handler, "newline", "function")
field(handler, "append", "function")
field(handler, "getX", "function")
for i=1, #elements, 1 do
local e = elements[i]
if e.type == "nl" then
for _=1, #e.text do handler.newline() end
elseif e.type == "ws" then
local x = handler.getX()
if x + #e.text > width + 1 then
handler.newline()
else
handler.append(e.text)
end
elseif e.type == "word" then
local x = handler.getX()
local half = math.ceil(#e.text / 2)
if x + #e.text > width + 1 then
if doHalves and x + half < width and #e.text > width/2 then
local halfText = e.text:sub(1, math.floor(#e.text / 2)) .. "-"
e.text = e.text:sub(#halfText)
handler.append(halfText)
handler.newline()
elseif x > 1 then
handler.newline()
end
end
handler.append(e.text)
end
end
end
function strings.wrap(text, width, doHalves)
expect(1, text, "string")
expect(2, width, "number", "nil")
expect(3, doHalves, "boolean", "nil")
width = width or term.getSize()
local lines = { "" }
local elements = strings.splitElements(text, width)
strings.wrappedWriteElements(elements, width, doHalves, {
newline = function()
lines[#lines+1] = ""
end,
append = function(newText)
lines[#lines] = lines[#lines] .. newText
end,
getX = function()
return #lines[#lines]
end
})
return lines
end
function strings.ensure_width(line, width)
expect(1, line, "string")
expect(2, width, "number", "nil")
width = width or term.getSize()
return (line .. (" "):rep(width - #line)):sub(1, width)
end
return strings