HOWTO: Dump a string table into formatted columns

Post Reply
phasma
Posts: 191
Joined: Sat Aug 03, 2013 7:00 pm
Discord: phasma#4694

HOWTO: Dump a string table into formatted columns

Post by phasma »

I found myself in a need of a function earlier that will basically accept an array and integer and return a nicely formatted string. While I am sure there may be alternative and better methods of accomplishing this, it is my hope that some people can find this useful.

The function will turn:
Code: [show] | [select all] lua
t = {
   "Go",
   "placidly",
   "amid",
   "the",
   "noise",
   "and",
   "haste",
   "and",
   "remember",
   "what",
   "peace",
   "there",
   "may",
   "be",
   "in",
   "silence"
}
Into:

Code: Select all

Go                       placidly                 amid
the                      noise                    and
haste                    and                      remember
what                     peace                    there
may                      be                       in
silence                  
Further, any integer passed as a second argument will set the padding to that value.
Code: [show] | [select all] lua
function nconc(t, delim, col)
	local delim = delim or 25
	local col = col or "grey"
	local i = 0
	for _, v in ipairs(t) do
		i = i + 1
		local d = ""
		d = d .. v
		if (i - 1)%3 == 0 then
			echo("\n")
		end
		local o = v
		if o:len() < delim and (i - 1)%3 ~= 2 then
			local pad = delim - o:len()
			o = o .. string.rep(" ", pad)
		elseif o:len() > delim then
			o = o:cut(delim)
		end
	cecho("<"..col..">" .. o)
	end
end
Last edited by phasma on Sun Mar 23, 2014 4:54 pm, edited 1 time in total.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: HOWTO: Dump a string table into formatted columns

Post by Jor'Mox »

This should do something similar, but I think it is a bit less complicated, and a bit more flexible.
Code: [show] | [select all] lua
-- this function fills in for just doing unpack(tbl,start,stop) by putting in "" for missing values
-- this is needed to ensure the final row of the table is displayed (as it may be missing values for some columns)
local function get_vals(tbl,start,stop)
	local result = {unpack(tbl,start,stop)}
	for k = 1, stop - start + 1 do
		if not result[k] then result[k] = "" end
	end
	return unpack(result)
end

function make_cols(tbl, cols, width)
	local str
	-- if a width isn't given, finds the width of the largest table entry
	if not width then
		width = 0
		for k,v in ipairs(tbl) do
			str = tostring(v)
			if #str > width then width = #str end
		end
		width = width + 1
	end
	local format = string.rep("%-"..width.."s",cols)
	for k = 1,#tbl,cols do
		str = string.format(format,get_vals(tbl,k,k+cols-1))
		echo(str.."\n")
	end
end

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: HOWTO: Dump a string table into formatted columns

Post by Jor'Mox »

And this version is a bit more complicated, but it allows for custom row formatting and the use of colors.
Code: [show] | [select all] lua
local function get_vals(tbl,start,stop)
	local result = {unpack(tbl,start,stop)}
	for k = 1, stop - start + 1 do
		if not result[k] then result[k] = "" end
	end
	return unpack(result)
end

function make_cols(tbl, cols, width, format)
	local str
	if not width then
		width = 0
		for k,v in ipairs(tbl) do
			str = tostring(v)
			if #str > width then width = #str end
		end
		width = width + 1
	end
	-- write a format string if one isn't given
	if not format then
		format = string.rep("%-"..width.."s",cols)
	else
	-- sub in width used in format string
		format = rex.gsub(format,"\%(\-?)s","%%%1"..tostring(width).."s")
	end
	-- match column count to number of %s values in format string
	local count = 0
	for w in string.gmatch(format, "%%%-?%d+s") do
		count = count + 1
	end
	cols = count
	
	for k = 1,#tbl,cols do
		str = string.format(format,get_vals(tbl,k,k+cols-1))
		cecho(str.."\n")
	end
end

phasma
Posts: 191
Joined: Sat Aug 03, 2013 7:00 pm
Discord: phasma#4694

Re: HOWTO: Dump a string table into formatted columns

Post by phasma »

Oooh, that's a pretty cute way to do it.

Edited mine to allow for colours. The possibilities for improvements are decent. Maybe I'll keep adding things!

User avatar
Belgarath
Posts: 232
Joined: Fri Jul 26, 2013 7:19 am
Discord: macjabeth#7149

Re: HOWTO: Dump a string table into formatted columns

Post by Belgarath »

Hehe. I made it a little project myself and tried to replicate this to the same effect. This was my outcome, though a bit longer and involving a few more functions.
Code: [show] | [select all] lua
function table.getMaxStr(t)
  local k,v = "",0
  for i = 1, #t do
    if #t[i] > v then
      k,v = t[i],#t[i]
    end
  end
  return k,v
end

function table.members(t)
  local c = 0
  for k,v in pairs(t) do
    c = c + 1
  end
  return c
end

function getRandomColour()
  local choice = math.random(table.members(color_table))
  local i = 1
  for k,v in pairs(color_table) do
    if i == choice then
      return string.format("<%s>", k)
    end
    i = i + 1
  end
end

function table.printify(t, columns, colours)
  if type(t) ~= "table" then
    cecho("\n<red>Error: table.printify: table expected, got " .. type(t))
    return
  end
  
  local max_str, max_num = table.getMaxStr(t)
  columns = columns or 3
  max_num = max_num + 5
  
  for i = 1, #t do
    local colour = colours and getRandomColour() or ""
    if i % columns ~= 0 then
      echo(string.format(colour .. "%-" .. max_num .. "s", t[i]))
    else
      echo(string.format(colour .. "%s\n", t[i]))
    end
  end
end
Image
Last edited by Belgarath on Fri Mar 28, 2014 6:23 am, edited 1 time in total.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: HOWTO: Dump a string table into formatted columns

Post by Jor'Mox »

A more efficient way to get your random colors would be like this:
Code: [show] | [select all] lua
local color_names = {}
for k,v in pairs(color_table) do
   table.insert(color_names,k)
end

function getRandomColour()
  return string.format("<%s>",color_names[math.random(1, #color_names)])
end
Then you only have to iterate through the color_table once to get a list of names, rather than doing it twice each time to count the items in the table and select the random name you picked.

Post Reply