diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index 234a8e81c83c60c679f787fa5ab324fb1e0c3284..d53506ba35d40a5321561f1664fb7071f07ad65a 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -52,6 +52,7 @@ lua_source(lua_sources lua/config/source/env.lua config_source_env_lua) lua_source(lua_sources lua/config/source/file.lua config_source_file_lua) lua_source(lua_sources lua/config/utils/log.lua config_utils_log_lua) lua_source(lua_sources lua/config/utils/schema.lua config_utils_schema_lua) +lua_source(lua_sources lua/config/utils/tabulate.lua config_utils_tabulate_lua) if (ENABLE_CONFIG_EXTRAS) lua_source(lua_sources ${CONFIG_EXTRAS_DIR}/source/etcd.lua config_source_etcd_lua) diff --git a/src/box/lua/config/utils/tabulate.lua b/src/box/lua/config/utils/tabulate.lua new file mode 100644 index 0000000000000000000000000000000000000000..05c52e6c7232da2971cc661a46b01b0145773274 --- /dev/null +++ b/src/box/lua/config/utils/tabulate.lua @@ -0,0 +1,68 @@ +-- Very simple pretty-printer of tabular data. +-- +-- Example: +-- +-- tabulate.encode({ +-- {'a', 'b', 'c'}, +-- tabulate.SPACER, +-- {'d', 'e', 'f'}, +-- {'g', 'h', 'i'}, +-- }) +-- +-- -> +-- +-- | a | b | c | +-- | - | - | - | +-- | d | e | f | +-- | g | h | i | + +local SPACER = {} + +-- Format data as a table. +-- +-- Accepts an array of rows. Each row in an array of values. Each +-- value is a string. +local function encode(rows) + -- Calculate column widths and columns amount. + local column_widths = {} + for _i, row in ipairs(rows) do + for j, v in ipairs(row) do + assert(type(v) == 'string') + column_widths[j] = math.max(column_widths[j] or 0, #v) + end + end + local column_count = #column_widths + + -- Use a table as a string buffer. + local acc = {} + + -- Add all the values into the accumulator with proper spacing + -- around and appropriate separators. + for _i, row in ipairs(rows) do + if row == SPACER then + for j = 1, column_count do + local width = column_widths[j] + table.insert(acc, '| ') + table.insert(acc, ('-'):rep(width)) + table.insert(acc, ' ') + end + table.insert(acc, '|\n') + else + for j = 1, column_count do + assert(row[j] ~= nil) + local width = column_widths[j] + table.insert(acc, '| ') + table.insert(acc, row[j]:ljust(width)) + table.insert(acc, ' ') + end + table.insert(acc, '|\n') + end + end + + return table.concat(acc) +end + +return { + SPACER = SPACER, + encode = encode, +} diff --git a/src/box/lua/init.c b/src/box/lua/init.c index b0a3b49c4326ce2fa7ab5c5245efac3434bc7d72..9be8ae05e97be0e44903f4f4876fed9687c10e6e 100644 --- a/src/box/lua/init.c +++ b/src/box/lua/init.c @@ -150,7 +150,8 @@ extern char session_lua[], config_source_env_lua[], config_source_file_lua[], config_utils_log_lua[], - config_utils_schema_lua[] + config_utils_schema_lua[], + config_utils_tabulate_lua[] #if ENABLE_CONFIG_EXTRAS , config_source_etcd_lua[], @@ -322,6 +323,10 @@ static const char *lua_sources[] = { "internal.config.utils.schema", config_utils_schema_lua, + "config/utils/tabulate", + "internal.config.utils.tabulate", + config_utils_tabulate_lua, + "config/instance_config", "internal.config.instance_config", config_instance_config_lua, diff --git a/test/config-luatest/tabulate_test.lua b/test/config-luatest/tabulate_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..7121f24c319e73aea48052b10ed9b4d166a05961 --- /dev/null +++ b/test/config-luatest/tabulate_test.lua @@ -0,0 +1,44 @@ +local tabulate = require('internal.config.utils.tabulate') +local t = require('luatest') + +local g = t.group() + +g.test_basic = function() + local header = { + 'Destination', + 'Gateway', + 'Genmask', + 'Flags', + 'Metric', + 'Ref', + 'Use', + 'Iface', + } + local route_1 = { + '0.0.0.0', -- Destination + '10.0.0.1', -- Gateway + '0.0.0.0', -- Genmask + 'UG', -- Flags + '3005', -- Metric + '0', -- Ref + '0', -- Use + 'wlan0', -- Iface + } + local route_2 = { + '10.0.0.0', -- Destination + '0.0.0.0', -- Gateway + '255.255.255.0', -- Genmask + 'U', -- Flags + '3005', -- Metric + '0', -- Ref + '0', -- Use + 'wlan0', -- Iface + } + local res = tabulate.encode({header, tabulate.SPACER, route_1, route_2}) + t.assert_equals(res, ([[ +| Destination | Gateway | Genmask | Flags | Metric | Ref | Use | Iface | +| ----------- | -------- | ------------- | ----- | ------ | --- | --- | ----- | +| 0.0.0.0 | 10.0.0.1 | 0.0.0.0 | UG | 3005 | 0 | 0 | wlan0 | +| 10.0.0.0 | 0.0.0.0 | 255.255.255.0 | U | 3005 | 0 | 0 | wlan0 | +]]):lstrip()) +end