Skip to content

Instantly share code, notes, and snippets.

@metaspatial
Created March 26, 2010 12:37
Show Gist options
  • Save metaspatial/344838 to your computer and use it in GitHub Desktop.
Save metaspatial/344838 to your computer and use it in GitHub Desktop.
function string.wrap(text,cols)
-- takes one or more lines of text and wraps them at punctuation, whilst preserving the (tab or space) indentation
cols = cols or tonumber(string.match(io.popen("stty size"):read()," (%d*)")) -- sh doesn't seem to export $COLUMNS
local output = {} -- more memory efficient than constantly concatenating
local offset,char,indent,indents,wrapped
local function IndexString (text) local temp = {} for i=1,#text do temp[string.sub(text,i,i)]=true end return temp end -- this just makes it easier to write the values as a string on the next line
local punctuation = IndexString [[ ,.;:!?"[]{}()]]
-- iterate over each line
for line in string.gmatch(text.."\n","(.-)\n") do
-- determine indentation
indent = ""
indents = 0
for char,position in string.gmatch(line,"(%s)()") do
if position > (#indent + 2) then break end
indent = indent .. char
if char == "\t" then indents = indents + 8 -- assuming the terminal displays tabs as 8 spaces
else indents = indents + 1 end
end
-- check each line
if #line + indents - #indent < cols then
-- doesn't need to be wrapped, so output unchanged
table.insert(output,line)
else
-- does need to be wrapped
-- work backwards from the wrap point to find punctuation
offset = cols - indents
while offset > 0 do
char = string.sub(line,offset,offset)
if punctuation[char] then break end
offset = offset - 1
end
-- output the trimmed line
table.insert(output,string.sub(line,1,offset))
table.insert(output,"\n")
-- determine if the wrapped line also needs wrapping
wrapped = indent..string.sub(line,offset+1)
if #wrapped + indents - #indent > cols then
-- does need wrapping as well, so call self with new value
table.insert(output,string.wrap(wrapped,cols))
else
-- output the wrapped line
table.insert(output,wrapped)
end
end
table.insert(output,"\n")
end
table.remove(output,#output) -- removes the final linebreak we added initially
return table.concat(output)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment