Skip to content
Snippets Groups Projects
Commit 49316120 authored by Gleb Kashkin's avatar Gleb Kashkin Committed by Igor Munkin
Browse files

lua-yaml: improve multiline string output

Added tarantool.compat option that allows yaml.encode() to encodes all
strings containing a newline in a more convenient block scalar style.
This is a breaking change, programs that rely on precise lyaml encoding
may fail if the new behavior is selected.

Closes #3012
Requires #7060
Requires #8007

@TarantoolBot document
Title: YAML formatter improvement

Now yaml.encode() can encode strings with a newline in block scalar style,
see https://yaml.org/spec/1.2-old/spec.html#style/block/literal and
https://github.com/tarantool/tarantool/wiki/compat%3Ayaml_pretty_multiline

old:
```
tarantool> compat.yaml_pretty_multiline = 'old'
---
...

tarantool> return "Title: xxx\n- Item 1\n- Item 2\n"
---
- 'Title: xxx

  - Item 1

  - Item 2

  '
...

```

new:
```
tarantool> compat.yaml_pretty_multiline = 'new'
---
...

tarantool> return "Title: xxx\n- Item 1\n- Item 2\n"
---
- |
  Title: xxx
  - Item 1
  - Item 2
...

```
parent 1436601c
No related branches found
No related tags found
No related merge requests found
## feature/yaml
* Lua-yaml readability improvement is introduced as a new compat option:
multiline strings can be encoded in literal-scalar style (gh-3012).
...@@ -37,11 +37,30 @@ lbox_json_escape_forward_slash_toggle(struct lua_State *L) ...@@ -37,11 +37,30 @@ lbox_json_escape_forward_slash_toggle(struct lua_State *L)
return 0; 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[] = { static const struct luaL_Reg internal_compat[] = {
{"msgpuck_escape_forward_slash_toggle", {"msgpuck_escape_forward_slash_toggle",
lbox_msgpuck_escape_forward_slash_toggle}, lbox_msgpuck_escape_forward_slash_toggle},
{"json_escape_forward_slash_toggle", {"json_escape_forward_slash_toggle",
lbox_json_escape_forward_slash_toggle}, lbox_json_escape_forward_slash_toggle},
{"yaml_pretty_multiline_toggle",
yaml_pretty_multiline_toggle},
{NULL, NULL}, {NULL, NULL},
}; };
......
...@@ -23,6 +23,15 @@ don't escape the forward slash, so the new behavior is considered more safe. ...@@ -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 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: -- Contains options descriptions in following format:
-- * default (string) -- * default (string)
-- * brief (string) -- * brief (string)
...@@ -43,6 +52,12 @@ local options = { ...@@ -43,6 +52,12 @@ local options = {
internal.msgpuck_escape_forward_slash_toggle(esc_slash) internal.msgpuck_escape_forward_slash_toggle(esc_slash)
end, 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. -- Array with option names in order of addition.
......
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
...@@ -667,10 +667,11 @@ static int dump_node(struct lua_yaml_dumper *dumper) ...@@ -667,10 +667,11 @@ static int dump_node(struct lua_yaml_dumper *dumper)
if (utf8_check_printable(str, len)) { if (utf8_check_printable(str, len)) {
if (yaml_is_flow_mode(dumper)) { if (yaml_is_flow_mode(dumper)) {
style = YAML_SINGLE_QUOTED_SCALAR_STYLE; 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 * Tarantool-specific: use literal block style for either every
* with empty lines. * multiline string or string containing "\n\n" depending on compat
* setup.
* Useful for tutorial(). * Useful for tutorial().
*/ */
style = YAML_LITERAL_SCALAR_STYLE; style = YAML_LITERAL_SCALAR_STYLE;
......
...@@ -12,6 +12,9 @@ struct luaL_serializer; ...@@ -12,6 +12,9 @@ struct luaL_serializer;
LUALIB_API int LUALIB_API int
luaopen_yaml(lua_State *L); luaopen_yaml(lua_State *L);
/** String with single or double newline char for compat option toggler. */
extern char *FORCE_LITERAL_SUBSTRING;
/** @Sa luaL_newserializer(). */ /** @Sa luaL_newserializer(). */
struct luaL_serializer * struct luaL_serializer *
lua_yaml_new_serializer(lua_State *L); lua_yaml_new_serializer(lua_State *L);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment