From 5b2461c713889b9832f5b99c85abf87e5d494242 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 11 Sep 2017 16:25:20 +0200 Subject: [PATCH] Fix core.wrap_text and make its behaviour consistent with the docs Code based on initial implementation by @dsohler. --- builtin/common/misc_helpers.lua | 66 ++++++++------------------------- builtin/mainmenu/common.lua | 2 +- builtin/mainmenu/tab_mods.lua | 2 +- doc/lua_api.txt | 6 ++- 4 files changed, 22 insertions(+), 54 deletions(-) diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 0bdd4b02a..4840dcbaa 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -308,59 +308,25 @@ function core.formspec_escape(text) end -function core.wrap_text(text, charlimit) - local retval = {} - - local current_idx = 1 - - local start,stop = string_find(text, " ", current_idx) - local nl_start,nl_stop = string_find(text, "\n", current_idx) - local gotnewline = false - if nl_start ~= nil and (start == nil or nl_start < start) then - start = nl_start - stop = nl_stop - gotnewline = true - end - local last_line = "" - while start ~= nil do - if string.len(last_line) + (stop-start) > charlimit then - retval[#retval + 1] = last_line - last_line = "" +function core.wrap_text(text, max_length, as_table) + local result = {} + local line = {} + if #text <= max_length then + return as_table and {text} or text + end + + for word in text:gmatch('%S+') do + local cur_length = #table.concat(line, ' ') + if cur_length > 0 and cur_length + #word + 1 >= max_length then + -- word wouldn't fit on current line, move to next line + table.insert(result, table.concat(line, ' ')) + line = {} end - - if last_line ~= "" then - last_line = last_line .. " " - end - - last_line = last_line .. string_sub(text, current_idx, stop - 1) - - if gotnewline then - retval[#retval + 1] = last_line - last_line = "" - gotnewline = false - end - current_idx = stop+1 - - start,stop = string_find(text, " ", current_idx) - nl_start,nl_stop = string_find(text, "\n", current_idx) - - if nl_start ~= nil and (start == nil or nl_start < start) then - start = nl_start - stop = nl_stop - gotnewline = true - end - end - - --add last part of text - if string.len(last_line) + (string.len(text) - current_idx) > charlimit then - retval[#retval + 1] = last_line - retval[#retval + 1] = string_sub(text, current_idx) - else - last_line = last_line .. " " .. string_sub(text, current_idx) - retval[#retval + 1] = last_line + table.insert(line, word) end - return retval + table.insert(result, table.concat(line, ' ')) + return as_table and result or table.concat(result, '\n') end -------------------------------------------------------------------------------- diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index fa7ae583b..7eb941775 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -250,7 +250,7 @@ end -------------------------------------------------------------------------------- function text2textlist(xpos, ypos, width, height, tl_name, textlen, text, transparency) - local textlines = core.wrap_text(text, textlen) + local textlines = core.wrap_text(text, textlen, true) local retval = "textlist[" .. xpos .. "," .. ypos .. ";" .. width .. "," .. height .. ";" .. tl_name .. ";" diff --git a/builtin/mainmenu/tab_mods.lua b/builtin/mainmenu/tab_mods.lua index 9510a9e18..7f95355a9 100644 --- a/builtin/mainmenu/tab_mods.lua +++ b/builtin/mainmenu/tab_mods.lua @@ -75,7 +75,7 @@ local function get_formspec(tabview, name, tabdata) if error == nil then local descriptiontext = descriptionfile:read("*all") - descriptionlines = core.wrap_text(descriptiontext, 42) + descriptionlines = core.wrap_text(descriptiontext, 42, true) descriptionfile:close() else descriptionlines = {} diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 03c825689..f0e6931db 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2128,9 +2128,11 @@ Helper functions * e.g. `string:split("a,b", ",") == {"a","b"}` * `string:trim()` * e.g. `string.trim("\n \t\tfoo bar\t ") == "foo bar"` -* `minetest.wrap_text(str, limit)`: returns a string - * Adds new lines to the string to keep it within the specified character limit +* `minetest.wrap_text(str, limit, [as_table])`: returns a string or table + * Adds newlines to the string to keep it within the specified character limit + Note that returned lines may be longer than the limit since it only splits at word borders. * limit: Maximal amount of characters in one line + * as_table: optional, if true return table of lines instead of string * `minetest.pos_to_string({x=X,y=Y,z=Z}, decimal_places))`: returns string `"(X,Y,Z)"` * Convert position to a printable string Optional: 'decimal_places' will round the x, y and z of the pos to the given decimal place. -- 2.25.1