Finally implemented column alignment
It's currently a bit limited in scope, but looks great when active.
This commit is contained in:
parent
0b0c2330ec
commit
93beb4bd1e
|
@ -101,8 +101,6 @@ printers specified below.
|
|||
|
||||
I'm looking into implementing following features:
|
||||
|
||||
- Improve display of medium-long lists with short elements. One option is
|
||||
something analog to the default results of `ls` on Linux.
|
||||
- Add support for `setmetatable`, and exploring the values accessible through
|
||||
it.
|
||||
- Provide nice formatting for `cdata` datatype in LuaJIT.
|
||||
|
|
|
@ -36,10 +36,11 @@ local RESERVED_LUA_WORDS = {
|
|||
['goto'] = true,
|
||||
}
|
||||
|
||||
local SIMPLE_VALUE_TYPES = {
|
||||
local LEAF_VALUE_TYPES = {
|
||||
['nil'] = true,
|
||||
['boolean'] = true,
|
||||
['number'] = true,
|
||||
['string'] = true,
|
||||
['boolean'] = true,
|
||||
}
|
||||
|
||||
local SHORT_STRING_MAX_LEN = 7
|
||||
|
@ -186,6 +187,20 @@ local function has_uniform_structure (t)
|
|||
return true
|
||||
end
|
||||
|
||||
local function is_leaf_node (t)
|
||||
-- Predicate: Returns true if table only contains elements of type nil,
|
||||
-- number, string or boolean
|
||||
|
||||
assert(type(t) == 'table')
|
||||
|
||||
for k,v in pairs(t) do
|
||||
if not LEAF_VALUE_TYPES[type(k)] or not LEAF_VALUE_TYPES[type(v)] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function get_table_info (t)
|
||||
|
@ -201,6 +216,7 @@ local function get_table_info (t)
|
|||
info.is_set = is_set(t) and info.nr_elems >= MINIMUM_NUMBER_OF_SET_ELEMENTS
|
||||
info.is_tabular = is_tabular(t)
|
||||
info.is_uniform = has_uniform_structure(t)
|
||||
info.is_leaf_node = is_leaf_node(t)
|
||||
|
||||
-- Determine type of table
|
||||
if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY
|
||||
|
|
87
pretty.lua
87
pretty.lua
|
@ -30,7 +30,7 @@ a table, we have a better idea, but then the output would be cluttered.
|
|||
continue to represent it as `{}`, but `{...}` would be more "honest".
|
||||
4. Single-line: TODO
|
||||
5. Multi-line: TODO
|
||||
6. ls style: TODO
|
||||
6. Format into columns: (like ls) TODO
|
||||
7. Tabular: TODO
|
||||
8. Special cases: (Array-tree, Table-Tree, Linked-List) TODO
|
||||
|
||||
|
@ -268,7 +268,6 @@ local function fix_alignment (l, start_i, stop_i)
|
|||
|
||||
assert(type(start_i) == 'number')
|
||||
assert(type(start_i) == 'number')
|
||||
-- Do stuff
|
||||
|
||||
-- Find maximums
|
||||
local max = {}
|
||||
|
@ -286,6 +285,85 @@ local function fix_alignment (l, start_i, stop_i)
|
|||
end
|
||||
end
|
||||
|
||||
local function attempt_to_align_into_columns (l, start_i, stop_i, nr_items_pr_row)
|
||||
assert(type(l) == 'table')
|
||||
assert(type(start_i) == 'number')
|
||||
assert(type(stop_i) == 'number')
|
||||
assert(type(nr_items_pr_row) == 'number')
|
||||
|
||||
local column = {}
|
||||
---
|
||||
local start_of_item_i, item_nr = nil, 0
|
||||
for i = start_i, stop_i do
|
||||
if type(l[i]) == 'table' and (l[i][1] == 'indent' or l[i][1] == 'seperator' or l[i][1] == 'unindent') then
|
||||
if start_of_item_i then
|
||||
local width_of_item = width_of_strings_in_l(l, start_of_item_i, i-1)
|
||||
local column_i = (item_nr-1)%nr_items_pr_row+1
|
||||
column[column_i] = math.max(column[column_i] or 0, width_of_item)
|
||||
end
|
||||
start_of_item_i, item_nr = i + 1, item_nr + 1
|
||||
end
|
||||
end
|
||||
---
|
||||
local width = nr_items_pr_row * 2 - 1 -- FIXME: Magic numbers: 2 = #', ', 1 = #' '
|
||||
for i = 1, #column do width = width + column[i] end
|
||||
--
|
||||
return width, column
|
||||
end
|
||||
|
||||
local function align_into_columns (l, start_i, stop_i)
|
||||
|
||||
-- Argument fixing and Error Checking
|
||||
assert(type(l) == 'table')
|
||||
|
||||
local start_i, stop_i = start_i or 1, stop_i or #l
|
||||
|
||||
assert(type(start_i) == 'number')
|
||||
assert(type(start_i) == 'number')
|
||||
|
||||
-- Find columns
|
||||
local columns = nil
|
||||
for nr_items_pr_row = 10, 1, -1 do -- TODO: Do this more intelligently.
|
||||
local column_width
|
||||
column_width, columns = attempt_to_align_into_columns(l, start_i, stop_i, nr_items_pr_row)
|
||||
if column_width <= MAX_WIDTH_FOR_SINGLE_LINE_TABLE then break end
|
||||
end
|
||||
|
||||
-- Change alignment of columns
|
||||
local start_of_item_i, item_nr = nil, 0
|
||||
for i = start_i, stop_i do
|
||||
if type(l[i]) == 'table' and l[i][1] == 'align' then
|
||||
local column_i = (item_nr-1)%#columns+1
|
||||
l[i][2] = l[i][2] .. '_column_'..column_i
|
||||
elseif (l[i][1] == 'indent' or l[i][1] == 'seperator' or l[i][1] == 'unindent') then
|
||||
start_of_item_i, item_nr = i + 1, item_nr + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Fix newly changed alignment
|
||||
fix_alignment(l, start_i, stop_i)
|
||||
|
||||
-- Quick-exit on only a single column
|
||||
if #columns == 1 then return end
|
||||
|
||||
-- Fit into columns.
|
||||
local start_of_item_i, item_nr = nil, 0
|
||||
for i = start_i, stop_i do
|
||||
if type(l[i]) ~= 'table' then
|
||||
-- Do nothing
|
||||
elseif (l[i][1] == 'indent' or l[i][1] == 'seperator' or l[i][1] == 'unindent') then
|
||||
if start_of_item_i and l[i][1] == 'seperator' then
|
||||
local column_i = (item_nr-1)%#columns+1
|
||||
if column_i ~= #columns then
|
||||
local width_of_item = width_of_strings_in_l(l, start_of_item_i, i-1)
|
||||
l[i] = l[i][2] .. ' ' .. (' '):rep(columns[column_i]-width_of_item)
|
||||
end
|
||||
end
|
||||
start_of_item_i, item_nr = i + 1, item_nr + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function fix_seperator_info (l, indent_char, max_depth)
|
||||
|
||||
-- Error Checking
|
||||
|
@ -404,6 +482,11 @@ local function format_table (t, depth, l)
|
|||
-- Is short table: Ignore the "width of key"-shit
|
||||
l[start_of_table_i][3] = 'inline'
|
||||
ignore_alignment_info(l, start_of_table_i)
|
||||
elseif table_info.is_leaf_node then
|
||||
-- Is leaf node: Can format into columns.
|
||||
-- NOTE: Currently we only allow leaf-nodes to format into columns, due
|
||||
-- to issues with table alignment.
|
||||
align_into_columns(l, start_of_table_i)
|
||||
else
|
||||
-- Is long table: Fix whitespace alignment
|
||||
fix_alignment(l, start_of_table_i)
|
||||
|
|
|
@ -316,6 +316,18 @@ format_test {
|
|||
expect = '{\n djævle = \'dyr?\',\n europa = \'måne\',\n øå = \'en å på en ø?\'\n}',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'Format table into columns, if leaf node',
|
||||
input = {
|
||||
'hello', 'world', 'how',
|
||||
'is', 'it', 'going?',
|
||||
'Im', 'doing great', 'thanks',
|
||||
'that', 'was', 'what',
|
||||
'I', 'were', 'expecting'
|
||||
},
|
||||
expect = '{\n \'hello\', \'world\', \'how\',\n \'is\', \'it\', \'going?\',\n \'Im\', \'doing great\', \'thanks\',\n \'that\', \'was\', \'what\',\n \'I\', \'were\', \'expecting\'\n}',
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Table recursion
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ format_test {
|
|||
format_test {
|
||||
name = 'Keys should be sorted such that uppercase and lowercase lies near each other',
|
||||
input = { Dave = 1, dave = 2, mary = 3, Mary = 4, Adam = 5, adam = 6 },
|
||||
expect = '{\n Adam = 5,\n adam = 6,\n Dave = 1,\n dave = 2,\n Mary = 4,\n mary = 3\n}',
|
||||
expect = '{\n Adam = 5, adam = 6, Dave = 1,\n dave = 2, Mary = 4, mary = 3\n}',
|
||||
}
|
||||
|
||||
format_test {
|
||||
|
@ -118,28 +118,17 @@ local EXAMPLE_1_INPUT = {
|
|||
}
|
||||
|
||||
local EXAMPLE_1_OUTPUT = ([[{
|
||||
['z1.doc'] = 1,
|
||||
['z2.doc'] = 1,
|
||||
['z3.doc'] = 1,
|
||||
['z4.doc'] = 1,
|
||||
['z5.doc'] = 1,
|
||||
['z6.doc'] = 1,
|
||||
['z7.doc'] = 1,
|
||||
['z8.doc'] = 1,
|
||||
['z9.doc'] = 1,
|
||||
['z10.doc'] = 1,
|
||||
['z11.doc'] = 1,
|
||||
['z12.doc'] = 1,
|
||||
['z13.doc'] = 1,
|
||||
['z14.doc'] = 1,
|
||||
['z15.doc'] = 1,
|
||||
['z16.doc'] = 1,
|
||||
['z17.doc'] = 1,
|
||||
['z18.doc'] = 1,
|
||||
['z19.doc'] = 1,
|
||||
['z20.doc'] = 1,
|
||||
['z100.doc'] = 1,
|
||||
['z101.doc'] = 1,
|
||||
['z1.doc'] = 1, ['z2.doc'] = 1,
|
||||
['z3.doc'] = 1, ['z4.doc'] = 1,
|
||||
['z5.doc'] = 1, ['z6.doc'] = 1,
|
||||
['z7.doc'] = 1, ['z8.doc'] = 1,
|
||||
['z9.doc'] = 1, ['z10.doc'] = 1,
|
||||
['z11.doc'] = 1, ['z12.doc'] = 1,
|
||||
['z13.doc'] = 1, ['z14.doc'] = 1,
|
||||
['z15.doc'] = 1, ['z16.doc'] = 1,
|
||||
['z17.doc'] = 1, ['z18.doc'] = 1,
|
||||
['z19.doc'] = 1, ['z20.doc'] = 1,
|
||||
['z100.doc'] = 1, ['z101.doc'] = 1,
|
||||
['z102.doc'] = 1
|
||||
}]]):gsub('\t', ' ')
|
||||
|
||||
|
@ -238,7 +227,7 @@ end)
|
|||
|
||||
SUITE:addTest('alphanum algorithm extension 1', function ()
|
||||
-- This is a test-case taken from http://www.davekoelle.com/alphanum.html
|
||||
local OUTPUT = "{\n ['z2'] = 1,\n ['z2.'] = 1,\n ['z2.z'] = 1,\n ['z2.0'] = 1\n}"
|
||||
local OUTPUT = "{\n ['z2'] = 1, ['z2.'] = 1,\n ['z2.z'] = 1, ['z2.0'] = 1\n}"
|
||||
assert_equal(OUTPUT, pretty { ['z2.z'] = 1, ['z2.0'] = 1, ['z2.'] = 1, ['z2'] = 1 })
|
||||
end)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user