diff --git a/changelogs/unreleased/gh-3012-yaml-prettier-multiline-output b/changelogs/unreleased/gh-3012-yaml-prettier-multiline-output new file mode 100644 index 0000000000000000000000000000000000000000..cf9e863d4257e72f63a295458ae8f47e89ebc3e2 --- /dev/null +++ b/changelogs/unreleased/gh-3012-yaml-prettier-multiline-output @@ -0,0 +1,4 @@ +## feature/yaml + +* Lua-yaml readability improvement is introduced as a new compat option: + multiline strings can be encoded in literal-scalar style (gh-3012). diff --git a/src/lua/compat.c b/src/lua/compat.c index 3605cf9c9fe95d53fd7bf0ccd9afd31f8a67f632..0fa354a8f6a0b36175d335cc47d5453b62d2479d 100644 --- a/src/lua/compat.c +++ b/src/lua/compat.c @@ -37,11 +37,30 @@ lbox_json_escape_forward_slash_toggle(struct lua_State *L) return 0; } +static const char double_newline[] = "\n\n"; +static const char single_newline[] = "\n"; + +const char *FORCE_LITERAL_SUBSTRING = double_newline; + +/* Toggler for lyaml multiline string encoding change. */ +static int +yaml_pretty_multiline_toggle(struct lua_State *L) +{ + assert(lua_isboolean(L, -1)); + bool is_new = lua_toboolean(L, -1); + + FORCE_LITERAL_SUBSTRING = is_new ? single_newline : double_newline; + + return 0; +} + static const struct luaL_Reg internal_compat[] = { {"msgpuck_escape_forward_slash_toggle", lbox_msgpuck_escape_forward_slash_toggle}, {"json_escape_forward_slash_toggle", lbox_json_escape_forward_slash_toggle}, + {"yaml_pretty_multiline_toggle", + yaml_pretty_multiline_toggle}, {NULL, NULL}, }; diff --git a/src/lua/compat.lua b/src/lua/compat.lua index 1af3c2c5178121207a52dd60e42064e5a7ccdb4a..2dd8ac5bf0764620d3df3fb59f87e1a91cb41f62 100644 --- a/src/lua/compat.lua +++ b/src/lua/compat.lua @@ -23,6 +23,15 @@ don't escape the forward slash, so the new behavior is considered more safe. https://github.com/tarantool/tarantool/wiki/compat%3Ajson_escape_forward_slash ]] +local YAML_PRETTY_MULTILINE_BRIEF = [[ +Whether to encode in block scalar style all multiline strings or ones +containing "\n\n" substring. The new behavior makes all multiline string output +as single text block which is handier for the reader, but may be incompatible +with some existing applications that rely on the old style. + +https://github.com/tarantool/tarantool/wiki/compat%3Ayaml_pretty_multiline +]] + -- Contains options descriptions in following format: -- * default (string) -- * brief (string) @@ -43,6 +52,12 @@ local options = { internal.msgpuck_escape_forward_slash_toggle(esc_slash) end, }, + yaml_pretty_multiline = { + default = 'old', + obsolete = nil, + brief = YAML_PRETTY_MULTILINE_BRIEF, + action = internal.yaml_pretty_multiline_toggle, + }, } -- Array with option names in order of addition. diff --git a/test/app-luatest/gh_3012_yaml_prettier_multiline_output_test.lua b/test/app-luatest/gh_3012_yaml_prettier_multiline_output_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..b22226f454b05cd8a1c4bacc5c3903f60a7eaf8e --- /dev/null +++ b/test/app-luatest/gh_3012_yaml_prettier_multiline_output_test.lua @@ -0,0 +1,17 @@ +local compat = require('tarantool').compat +local yaml = require('yaml') +local t = require('luatest') +local g = t.group() + +g.test_encode = function() + local str = 'Title: xxx\n - Item 1\n - Item 2\n' + local old_res = '--- "Title: xxx\\n - Item 1\\n - Item 2\\n"\n...\n' + local new_res = '--- |\n Title: xxx\n - Item 1\n - Item 2\n...\n' + + t.assert_equals(yaml.encode(str), old_res) + compat.yaml_pretty_multiline = 'new' + t.assert_equals(yaml.encode(str), new_res) + compat.yaml_pretty_multiline = 'old' + t.assert_equals(yaml.encode(str), old_res) + compat.yaml_pretty_multiline = 'default' +end diff --git a/third_party/lua-yaml/lyaml.cc b/third_party/lua-yaml/lyaml.cc index d3ad2fe32dc1315c493d1260de2993f053751e79..33eecd803ec258da3cf2b4ef584c849bc33125b1 100644 --- a/third_party/lua-yaml/lyaml.cc +++ b/third_party/lua-yaml/lyaml.cc @@ -667,10 +667,11 @@ static int dump_node(struct lua_yaml_dumper *dumper) if (utf8_check_printable(str, len)) { if (yaml_is_flow_mode(dumper)) { style = YAML_SINGLE_QUOTED_SCALAR_STYLE; - } else if (strstr(str, "\n\n") != 0) { + } else if (strstr(str, FORCE_LITERAL_SUBSTRING) != NULL) { /* - * Tarantool-specific: use literal style for string - * with empty lines. + * Tarantool-specific: use literal block style for either every + * multiline string or string containing "\n\n" depending on compat + * setup. * Useful for tutorial(). */ style = YAML_LITERAL_SCALAR_STYLE; diff --git a/third_party/lua-yaml/lyaml.h b/third_party/lua-yaml/lyaml.h index 335792d245150eb5375819a8c6c92d6ce9cbdbb3..52575f9a60821b5a6c760ec7bf7fcfd4b79a58e8 100644 --- a/third_party/lua-yaml/lyaml.h +++ b/third_party/lua-yaml/lyaml.h @@ -12,6 +12,9 @@ struct luaL_serializer; LUALIB_API int luaopen_yaml(lua_State *L); +/** String with single or double newline char for compat option toggler. */ +extern char *FORCE_LITERAL_SUBSTRING; + /** @Sa luaL_newserializer(). */ struct luaL_serializer * lua_yaml_new_serializer(lua_State *L);