This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
viluon's profile picture

Word wrap

Started by viluon, 24 April 2014 - 04:03 PM
viluon #1
Posted 24 April 2014 - 06:03 PM
Hello, community! I'd need to separate given text by a given maximal amount of characters per line and fill up the line with spaces if the next word can't fit in. I googled for a simple function to do this as I thought that it can already have some answer, but there are so many Lua modifications that I simply couldn't find anything that would work for me. (Hope that my goal is understandable, sorry for my bad English.) So, I'm asking you as a noob in pattern matching, does anyone know how to solve this problem? Thanks for any feedback!
masterdisasterHD #2
Posted 24 April 2014 - 06:14 PM
http://computercraft.info/wiki/Textutils.pagedPrint
CometWolf #3
Posted 24 April 2014 - 06:39 PM
I fail to see how pagedPrint is related to his quesiton…
Here's a an excerpt from one of my own codes. This will split strings into lines.

  local tLine = {}
  local lineLength = 25 --idk how long you want them to be
  while #text > 0 do  --splits text into a table containing each line
	local line = text:sub(1,lineLength)
	local newLine = string.find(line.."","\n") --check for new line character
	if newLine then
	  line = line:sub(1,newLine-1)
	  text = text:sub(#line+2,#text)
	elseif #line == lineLength then
	  local endSpace = line:find"%s$" or line:find"%s%S-$" or lineLength
	  line = line:sub(1,endSpace)
	  text = text:sub(#line+1,#text)
	else
	  text = ""
	end
	tLine[#tLine+1] = line
  end
I suppose what you're lookig for would be something like this

local line = text:sub(1,lineLength) --extract the max length of each line from the string
local endSpace = line:find"%s$" or line:find"%s%S-$" or lineLength --look for a space at the end, or the space closest to the end, or just return the max line length
line = line:sub(1,endSpace) --extract the new string
line = line..string.rep(" ",endSpace-lineLength) --fill in the blank spaces with well... spaces
Edited on 24 April 2014 - 04:40 PM
viluon #4
Posted 25 April 2014 - 03:10 PM
-snip-
First of all, THANKS! But… Have you tried executing the code? I am getting vm exception negative array size :/ its on that line
line = line..string.rep(" ",endSpace-lineLength) --fill in the blank spaces with well... spaces
Shouldn't it be lineLenght-endSpace ? I added your code, fixed that line with if endSpace-lineLenght>0 then … end but it's weirdly adding the spaces (in fact, it's not adding them till the eol, only about 1 space is added). On the other hand, the output from (I added this to a wrap(str,limit) function) wrap("this is some text asdasdasdasd",5) is something like
this
me
xt
sdasd
...
(simply cutting off first 2 symbols if line!=1)… Weird isn't it? I'm using CC 1.63, it might be because of that, I debugged your code at first with my Android device and SigmaScript while at school, and it worked (well, dunno if the spaces were added properly, SigmaScript doesn't offer better output than a console-no colors, etc.). by the way here is your code when put into a function that should work
Spoiler
--this doesn't work, as it doesn't fill in the missing spaces, can't figure out why after 2 hours of programming without a break :D/>   '
function wrap(str, limit)
  local tLine = {}
  while #str > 0 do  --splits text into a table containing each line
	--print(#str) debug
	  local line = str:sub(1,limit)
	  local newLine = string.find(line.."","\n") --check for new line character
	  if newLine then
		line = line:sub(1,newLine-1)
		str = str:sub(#line+2,#str)
	  elseif #line == limit then
		local endSpace = line:find"%s$" or line:find"%s%S-$" or limit
		line = line:sub(1,endSpace)
  if endSpace-limit>0 then
		line = line..string.rep(" ",endSpace-limit) end --fill in the blank spaces with well... spaces
		str = str:sub(#line+1,#str)
	  else
		str = ""
	  end
	  tLine[#tLine+1] = line
  end
  local out=""
  for i,v in ipairs(tLine) do --put the for loop into the draw function and instead of writing newline
   out=out.."\n"..tostring(v) --set new cursor position with term.setCursorPos(x,y+i) (and of course, here return tLine)
  end
  return out
end
that last comment is for a modified version that actually wrap the text on screen, here:
...
--end of that function is changed
return tLine
end
--and later used in my code to wrap text on-screen as follows:
if string.len(this.text)>this.width then
   term.setCursorPos(x,y)
   local space=this.width*this.height --this is not used now, will be as soon as I finally figure out the damned text wrapping!!!
   for i,v in ipairs(wrap(this.text,this.width)) do
	term.setCursorPos(x,y+i)
	term.write(tostring(v))
   end
  else
   term.setCursorPos(x,y)
   term.write(wrap(this.text))
  end
Hope I'm not too stupid and it's not obvious…. (but as usual, it is isn't it? Im just sooo tired… )
And hope that you will be able to help me, thanks for any feedback! :)/>
Edited on 25 April 2014 - 01:12 PM
CometWolf #5
Posted 25 April 2014 - 04:21 PM
You are indeed correct about the endSpace thing. The original code is part of what i use to render message windows in Turtle Architect so i know it works, it dosen't require the appended strings though. string.rep is annoying like that, you'll have to resort to using math.max(value,0) to avoid any negatives.
viluon #6
Posted 26 April 2014 - 08:08 PM
Sorry for the long delay, I've edited it a bit and guess what, IT WORKS!!! Huge thanks to you, CometWolf! :)/>