From 88fa144c9ea93670c5f70f445d96243240336825 Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Sat, 18 Nov 2017 13:23:43 +0100 Subject: [PATCH] Fixed alignment issue for certain tables. --- .gitignore | 1 + common.lua | 36 +++++++++++++++++++++-- function.lua | 17 ++++------- pretty.lua | 68 ++++++++++++++++++++++++------------------- test/test_pretty.lua | 55 ++++------------------------------ test/test_sorting.lua | 31 ++++++++++---------- 6 files changed, 98 insertions(+), 110 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a01ee28 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/common.lua b/common.lua index 830b0b2..15571de 100644 --- a/common.lua +++ b/common.lua @@ -1,7 +1,4 @@ --- TODO: I don't like to have such tiny modules. Either merge into another --- module or provide the functionality with another approach. - -------------------------------------------------------------------------------- -- Enum @@ -42,10 +39,43 @@ local function utf8_string_length (str) return len end +-------------------------------------------------------------------------------- +-- L utility + +local function width_of_strings_in_l (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(stop_i) == 'number') + + -- Do stuff + local width = 0 + for i = start_i, stop_i do + local item_width = 0 + if type(l[i]) == 'string' then + item_width = utf8_string_length(l[i]) + elseif l[i].est_width then + item_width = l[i].est_width + end + width = width + item_width + end + + -- Return + return width +end + + + -------------------------------------------------------------------------------- return { TABLE_TYPE = enum { 'EMPTY', 'SEQUENCE', 'STRING_MAP', 'PURE_MAP', 'MIXED', 'SET' }, DISPLAY = { HIDE = 1, SMALL = 2, INLINE = 3, EXPAND = 4 }, + utf8_string_length = utf8_string_length, + width_of_strings_in_l = width_of_strings_in_l, } + diff --git a/function.lua b/function.lua index c5b3449..c796aea 100644 --- a/function.lua +++ b/function.lua @@ -61,6 +61,7 @@ simplest, and move towards abstraction. local LIBRARY = require((... and select('1', ...):match('.+%.') or '')..'library') or {} local DISPLAY = assert(require((... and select('1', ...):match('.+%.') or '')..'common'), '[pretty]: Could not load vital library: common') . DISPLAY local utf8_string_length = assert(require((... and select('1', ...):match('.+%.') or '')..'common'), '[pretty]: Could not load vital library: common') . utf8_string_length +local width_of_strings_in_l = assert(require((... and select('1', ...):match('.+%.') or '')..'common'), '[pretty]: Could not load vital library: common') . width_of_strings_in_l -- Constants @@ -108,10 +109,10 @@ local function get_function_info (f) end end - if info.source:sub(1,1) == '=' then info.defined_how = 'C' - elseif info.source:sub(1,1) == '@' then info.defined_how = 'file' + if info.source:sub(1,1) == '=' then info.defined_how = 'C' + elseif info.source:sub(1,1) == '@' then info.defined_how = 'file' elseif info.source:find(LUA_FILE_PATTERN) then info.defined_how = 'file' -- Fix for when someone has misunderstood the source format is for. - else info.defined_how = 'string' + else info.defined_how = 'string' end if info.builtin and LIBRARY[f] then @@ -235,15 +236,6 @@ end -------------------------------------------------------------------------------- -- Text handling -local function width_of_strings_in_l (l, start_i, end_i) - -- FIXME: Copy of the one in pretty.lua - local width = 0 - for i = start_i or 1, (end_i or #l) do - width = width + utf8_string_length(l[i]) - end - return width -end - local function add_indent_to_string (str, indent) -- Indents `str` by `indent`. @@ -380,3 +372,4 @@ return function (value, display, l, format_value) end l[#l+1] = '\nend' end + diff --git a/pretty.lua b/pretty.lua index 96ee85f..7b45b3a 100644 --- a/pretty.lua +++ b/pretty.lua @@ -101,6 +101,8 @@ local VALUE_TYPE_SORT_ORDER = { ['function'] = 7, } +local COLUMN_SEPERATION = 1 + -------------------------------------------------------------------------------- -- Key-value-pair Util @@ -202,24 +204,7 @@ end -- Formatting Util local length_of_utf8_string = import 'common' . utf8_string_length - -local function width_of_strings_in_l (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') - - -- Do stuff - local width = 0 - for i = start_i, stop_i do - width = width + ((type(l[i]) ~= 'string') and 1 or length_of_utf8_string(l[i])) - end - return width -end +local width_of_strings_in_l = import 'common' . width_of_strings_in_l local function ignore_alignment_info (l, start_i, stop_i) @@ -229,7 +214,7 @@ local function ignore_alignment_info (l, start_i, stop_i) local start_i, stop_i = start_i or 1, stop_i or #l assert(type(start_i) == 'number') - assert(type(start_i) == 'number') + assert(type(stop_i) == 'number') -- Do stuff for i = start_i, stop_i do @@ -239,15 +224,14 @@ local function ignore_alignment_info (l, start_i, stop_i) end end -local function fix_alignment (l, start_i, stop_i) - +local function insert_alignment_estimations (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') + assert(type(stop_i) == 'number') -- Find maximums local max = {} @@ -260,7 +244,28 @@ local function fix_alignment (l, start_i, stop_i) -- Insert the proper whitespace for i = start_i, stop_i do if type(l[i]) == 'table' and l[i][1] == 'align' then - l[i] = string.rep(' ', max[ l[i][2] ] - l[i][3]) + l[i].est_width = max[ l[i][2] ] - l[i][3] + end + end +end + +local function fix_alignment (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(stop_i) == 'number') + + -- Find whitespace to insert + insert_alignment_estimations(l, start_i, stop_i) + + -- Insert whitespace + for i = start_i, stop_i do + if type(l[i]) == 'table' and l[i][1] == 'align' then + l[i] = string.rep(' ', l[i].est_width) end end end @@ -268,7 +273,7 @@ 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(stop_i) == 'number') assert(type(nr_items_pr_row) == 'number') local column = {} @@ -301,6 +306,8 @@ local function align_into_columns (l, start_i, stop_i) assert(type(start_i) == 'number') assert(type(stop_i) == 'number') + insert_alignment_estimations(l, start_i, stop_i) + -- Find columns local columns = nil for nr_items_pr_row = 10, 1, -1 do -- TODO: Do this more intelligently. @@ -336,7 +343,7 @@ local function align_into_columns (l, start_i, stop_i) 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) + l[i] = l[i][2] .. (' '):rep(COLUMN_SEPERATION+columns[column_i]-width_of_item) end end start_of_item_i, item_nr = i + 1, item_nr + 1 @@ -345,16 +352,16 @@ local function align_into_columns (l, start_i, stop_i) end local function align_into_tabular_style (l, start_i, stop_i) - -- Adds alignment after seperators, to create nicely aligned tabular-format. + -- Adds alignment after separators, to create nicely aligned tabular-format. -- Argument fixing and Error Checking local start_i, stop_i = start_i or 1, stop_i or #l - assert(type(l) == 'table') - assert(type(start_i) == 'number') - assert(type(stop_i) == 'number') + assert(type(l) == 'table') + assert(type(start_i) == 'number') + assert(type(stop_i) == 'number') assert(type(l[start_i]) == 'table' and l[start_i][1] == 'indent') - assert(type(l[stop_i]) == 'table' and l[stop_i][1] == 'unindent') + assert(type(l[stop_i]) == 'table' and l[stop_i][1] == 'unindent') -- Calculate where to insert new alignment. local indent, key_nr, index_of_last_meta, insert_later = 0, 0, 1, {} @@ -639,3 +646,4 @@ local function pretty_format (value, options) end return pretty_format + diff --git a/test/test_pretty.lua b/test/test_pretty.lua index c9e187b..be40791 100644 --- a/test/test_pretty.lua +++ b/test/test_pretty.lua @@ -266,10 +266,11 @@ format_test { format_test { name = 'Tabular style with strings left aligned', input = { - { a = 'hello', b = 'hi' }, - { a = 'hi', b = 'hello' } + { a = 'hello', b = 'hi' }, + { a = 'hi', b = 'hello' }, + { a = 'hi', b = 'hi' }, }, - expect = '{\n { a = \'hello\', b = \'hi\' },\n { a = \'hi\', b = \'hello\' }\n}', + expect = '{\n { a = \'hello\', b = \'hi\' },\n { a = \'hi\', b = \'hello\' },\n { a = \'hi\', b = \'hi\' }\n}', } format_test { @@ -398,53 +399,6 @@ end) local BIG_EXAMPLE_TABLE = [[ return { [0] = 21082, [1] = 696, - [2] = 463, [3] = 235, - [4] = 315, [5] = 312, - [6] = 204, [7] = 124, - [8] = 692, [9] = 84, - [10] = 248, [11] = 148, - [12] = 108, [13] = 109, - [14] = 1019, [15] = 1211, - [16] = 470, [17] = 73, - [18] = 121, [19] = 36, - [20] = 149, [21] = 514, - [22] = 38, [23] = 45, - [24] = 353, [25] = 27, - [26] = 27, [27] = 51, - [28] = 84, [29] = 61, - [30] = 29, [31] = 448, - [32] = 2064, [33] = 65, - [34] = 34, [35] = 20, - [36] = 859, [37] = 239, - [38] = 24, [39] = 41, - [40] = 297, [41] = 95, - [42] = 43, [43] = 30, - [44] = 202, [45] = 123, - [46] = 243, [47] = 98, - [48] = 207, [49] = 484, - [50] = 31, [51] = 59, - [52] = 51, [53] = 118, - [54] = 27, [55] = 22, - [56] = 227, [57] = 168, - [58] = 55, [59] = 38, - [60] = 74, [61] = 106, - [62] = 62, [63] = 40, - [64] = 170, [65] = 857, - [66] = 412, [67] = 136, - [68] = 737, [69] = 238, - [70] = 64, [71] = 119, - [72] = 2567, [73] = 481, - [74] = 50, [75] = 55, - [76] = 714, [77] = 189, - [78] = 61, [79] = 55, - [80] = 114, [81] = 26, - [82] = 69, [83] = 150, - [84] = 238, [85] = 172, - [86] = 65, [87] = 81, - [88] = 102, [89] = 39, - [90] = 30, [91] = 154, - [92] = 155, [93] = 191, - [94] = 75, [95] = 185, [96] = 62, [97] = 334, [98] = 119, [99] = 217, [100] = 261 @@ -458,3 +412,4 @@ end) -------------------------------------------------------------------------------- return SUITE + diff --git a/test/test_sorting.lua b/test/test_sorting.lua index 6292087..094ef31 100644 --- a/test/test_sorting.lua +++ b/test/test_sorting.lua @@ -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, adam = 6, Dave = 1,\n dave = 2, Mary = 4, mary = 3\n}', + expect = '{\n Adam = 5, adam = 6, Dave = 1,\n dave = 2, Mary = 4, mary = 3\n}', } format_test { @@ -82,13 +82,13 @@ format_test { format_test { name = 'Proper sorting of number keys', input = { [-1/0] = 'a', [-100] = 'b', [-1] = 'c', [0] = 'd', [1] = 'e', [100] = 'f', [1/0] = 'g' }, - expect = '{\n [-1/0] = \'a\', [-100] = \'b\',\n [-1] = \'c\', [0] = \'d\',\n [1] = \'e\', [100] = \'f\',\n [1/0] = \'g\'\n}', + expect = '{\n [-1/0] = \'a\', [-100] = \'b\',\n [-1] = \'c\', [0] = \'d\',\n [1] = \'e\', [100] = \'f\',\n [1/0] = \'g\'\n}', } format_test { name = 'Proper sorting of number strings keys', input = { ['-10'] = 'a', ['-0.5'] = 'b', ['0'] = 'c', ['1'] = 'd', ['10.1'] = 'e' }, - expect = '{\n [\'-10\'] = \'a\', [\'-0.5\'] = \'b\',\n [\'0\'] = \'c\', [\'1\'] = \'d\',\n [\'10.1\'] = \'e\'\n}', + expect = '{\n [\'-10\'] = \'a\', [\'-0.5\'] = \'b\',\n [\'0\'] = \'c\', [\'1\'] = \'d\',\n [\'10.1\'] = \'e\'\n}', } @@ -131,17 +131,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', ' ') @@ -240,10 +240,11 @@ 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, ['z2.'] = 1,\n ['z2.z'] = 1, ['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) -------------------------------------------------------------------------------- return SUITE +