From 5b12c64cba06cd74a7d05c46c38dd63cc9fd020d Mon Sep 17 00:00:00 2001 From: myk002 Date: Wed, 23 Jun 2021 13:59:39 -0700 Subject: [PATCH] add new string function: wrap() refactored and improved from the implementation in quickfort's dialog.lua --- library/lua/dfhack.lua | 37 +++++++++++++++++++++++++++++++++++++ test/library/string.lua | 24 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 test/library/string.lua diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index d1e664af7..bca2cc895 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -369,6 +369,43 @@ function string:endswith(suffix) return self:sub(-#suffix) == suffix or #suffix == 0 end +-- Inserts newlines into a string so no individual line exceeds the given width. +-- Lines are split at space-separated word boundaries. Any existing newlines are +-- kept in place. If a single word is longer than width, it is split over +-- multiple lines. +function string:wrap(width) + local wrapped_text = {} + for line in self:gmatch('[^\n]*') do + local line_start_pos = 1 + local wrapped_line = line:gsub( + '%s*()(%S+)()', + function(start_pos, word, end_pos) + -- word fits within the current line + if end_pos - line_start_pos <= width then return end + -- word needs to go on the next line, but is not itself longer + -- than the specified width + if #word <= width then + line_start_pos = start_pos + return '\n' .. word + end + -- word is too long to fit on one line and needs to be split up + local num_chars, str = 0, start_pos == 1 and '' or '\n' + repeat + local word_frag = word:sub(num_chars + 1, num_chars + width) + str = str .. word_frag + num_chars = num_chars + #word_frag + if num_chars < #word then + str = str .. '\n' + end + line_start_pos = start_pos + num_chars + until end_pos - line_start_pos <= width + return str .. word:sub(num_chars + 1) + end) + table.insert(wrapped_text, wrapped_line) + end + return table.concat(wrapped_text, '\n') +end + -- String conversions function dfhack.persistent:__tostring() diff --git a/test/library/string.lua b/test/library/string.lua new file mode 100644 index 000000000..fdb278d40 --- /dev/null +++ b/test/library/string.lua @@ -0,0 +1,24 @@ +-- tests string functions added by dfhack.lua + +function test.startswith() + expect.true_(('abcd'):startswith('')) + expect.true_(('abcd'):startswith('abc')) + expect.false_(('abcd'):startswith('bcd')) +end + +function test.endswith() + expect.true_(('abcd'):endswith('')) + expect.true_(('abcd'):endswith('bcd')) + expect.false_(('abcd'):endswith('abc')) +end + +function test.wrap() + expect.eq('hello world', ('hello world'):wrap(20)) + expect.eq('hello world', ('hello world'):wrap(20)) + expect.eq('hello world\nhow are you?',('hello world how are you?'):wrap(12)) + expect.eq('hello\nworld', ('hello world'):wrap(5)) + expect.eq('hello\nworld', ('hello world'):wrap(5)) + expect.eq('hello\nworld', ('hello world'):wrap(8)) + expect.eq('hel\nlo\nwor\nld', ('hello world'):wrap(3)) + expect.eq('hel\nloo\nwor\nldo', ('helloo worldo'):wrap(3)) +end