diff --git a/doc/settings.md b/doc/settings.md index f350cb0f76..734a83a769 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -65,6 +65,8 @@ The file list is built in the following order from the following sources: - `name=2000` and `name="2000"` have the same meaning. - There is no distinction between XML-attribute and XML-subobject, i.e. any attributes are sub-objects: - `` and ` ` have the same meaning. + - No spaces are allowed between the opening angle bracket and the name when declaring an XML-subobject. + - `... < name ...`, `... <= ...`, `... << ...` are treated as parts of Lua script code. - In addition to a set of sub-objects each object can contain its own text value: - E.g. `` - subobject `name` has text value `names_value`. - Each object can be defined in any way, either using an XML-attribute or an XML-subobject syntax: diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index d3acf48c54..2421d3a101 100644 --- a/src/netxs/desktopio/application.hpp +++ b/src/netxs/desktopio/application.hpp @@ -22,7 +22,7 @@ namespace netxs::app namespace netxs::app::shared { - static const auto version = "v2025.05.21"; + static const auto version = "v2025.05.21a"; static const auto repository = "https://github.com/directvt/vtm"; static const auto usr_config = "~/.config/vtm/settings.xml"s; static const auto sys_config = "/etc/vtm/settings.xml"s; diff --git a/src/netxs/desktopio/utf.hpp b/src/netxs/desktopio/utf.hpp index 73bb31f94b..c79382230d 100644 --- a/src/netxs/desktopio/utf.hpp +++ b/src/netxs/desktopio/utf.hpp @@ -1709,8 +1709,17 @@ namespace netxs::utf debase437(utf8, buff); return buff; } - // utf: Find char position ignoring backslashed. + // utf: Find char position. auto _find_char(auto head, auto tail, auto hittest) + { + while (head != tail && !hittest(head)) + { + ++head; + } + return head; + } + // utf: Find char position ignoring backslashed. + auto _find_char_except_escaped(auto head, auto tail, auto hittest) { while (head != tail) { @@ -1723,20 +1732,60 @@ namespace netxs::utf template auto find_char(Iter head, Iter tail, view delims) { - return _find_char(head, tail, [&](auto iter){ return delims.find(*iter) != view::npos; }); + return _find_char_except_escaped(head, tail, [&](auto iter){ return delims.find(*iter) != view::npos; }); + } + // utf: Check if utf8 start with test string. + bool _starts_with(auto& iter, view utf8, view test) + { + auto found = utf8.starts_with(test); + if (found) + { + iter += test.size(); + } + return found; + } + // utf: Check if utf8 starts with something using test proc (the test proc must do increment of iter if skips). + bool _starts_with(auto& iter, view utf8, auto test) + { + return test(iter, utf8); + } + // utf: Find char position ignoring skips. + template + auto find_char_except_skips(view utf8, char c, Args&&... skips) + { + auto head = utf8.begin(); + auto tail = utf8.end(); + auto found_iter = _find_char(head, tail, [&](auto& iter) + { + if (*iter == c) + { + auto substr = view{ iter, tail }; + auto found = (utf::_starts_with(iter, substr, skips) || ...); + if (found) + { + return iter == tail; // faux if not end + } + else + { + return true; + } + } + return faux; + }); + return found_iter; } // utf: Find substring position ignoring backslashed. auto find_substring(view& utf8, auto... delims) { auto head = utf8.begin(); auto tail = utf8.end(); - return _find_char(head, tail, [&](auto iter){ return (view{ iter, tail }.starts_with(delims) || ...); }); + return _find_char_except_escaped(head, tail, [&](auto iter){ return (view{ iter, tail }.starts_with(delims) || ...); }); } // utf: Find char position ignoring backslashed. template auto find_char(Iter head, Iter tail, char delim) { - return _find_char(head, tail, [&](auto iter){ return *iter == delim; }); + return _find_char_except_escaped(head, tail, [&](auto iter){ return *iter == delim; }); } auto check_any(view shadow, view delims) { diff --git a/src/netxs/desktopio/xml.hpp b/src/netxs/desktopio/xml.hpp index 3bdad897da..93da36578c 100644 --- a/src/netxs/desktopio/xml.hpp +++ b/src/netxs/desktopio/xml.hpp @@ -239,7 +239,10 @@ namespace netxs::xml close_inline, // '>' ex: ... > empty_tag, // '/>' ex: ... /> equal, // '=' ex: name=value - defaults, // '*' ex: name* + defaults, //todo deprecate '*' ex: name* + lua_op_shl, // '<<' ex: Lua's shift left operator + lua_op_less, // '< ' ex: Lua's less than operator + lua_op_less_eq,// '<=' ex: Lua's less than or equal operator compact, // '/[^>]' ex: compact syntax: include, // ':' ex: localpath, // ex: @@ -651,19 +654,22 @@ namespace netxs::xml } }; - static constexpr auto find_start = "<"sv; - static constexpr auto rawtext_delims = std::tuple{ " "sv, "/>"sv, ">"sv, "<"sv, "\n"sv, "\r"sv, "\t"sv }; - static constexpr auto token_delims = " \t\n\r=*/><"sv; - static constexpr auto view_comment_begin = ""sv; - static constexpr auto view_close_tag = ""sv; - static constexpr auto view_slash = "/"sv; - static constexpr auto view_close_inline = ">"sv; - static constexpr auto view_quoted_text = "\""sv; - static constexpr auto view_equal = "="sv; - static constexpr auto view_defaults = "*"sv; + static constexpr auto find_start = "<"sv; + static constexpr auto rawtext_delims = std::tuple{ " "sv, "/>"sv, ">"sv, "<"sv, "\n"sv, "\r"sv, "\t"sv }; + static constexpr auto token_delims = " \t\n\r=*/><"sv; + static constexpr auto view_comment_begin = ""sv; + static constexpr auto view_close_tag = ""sv; + static constexpr auto view_slash = "/"sv; + static constexpr auto view_close_inline = ">"sv; + static constexpr auto view_quoted_text = "\""sv; + static constexpr auto view_equal = "="sv; + static constexpr auto view_defaults = "*"sv; + static constexpr auto view_lua_op_shl = "<<"sv; + static constexpr auto view_lua_op_less = "< "sv; + static constexpr auto view_lua_op_less_eq = "<="sv; suit page; sptr root; @@ -856,22 +862,25 @@ namespace netxs::xml { switch (what) { - case type::na: return view{ "{START}" } ; - case type::eof: return view{ "{EOF}" } ; - case type::eol: return view{ "{EOL}" } ; - case type::token: return view{ "{token}" } ; - case type::raw_text: return view{ "{raw text}" }; - case type::compact: return view{ "{compact}" } ; - case type::quoted_text: return view_quoted_text ; - case type::begin_tag: return view_begin_tag ; - case type::close_tag: return view_close_tag ; - case type::comment_begin: return view_comment_begin ; - case type::comment_close: return view_comment_close ; - case type::close_inline: return view_close_inline ; - case type::empty_tag: return view_empty_tag ; - case type::equal: return view_equal ; - case type::defaults: return view_defaults ; - default: return view{ "{unknown}" } ; + case type::na: return view{ "{START}" } ; + case type::eof: return view{ "{EOF}" } ; + case type::eol: return view{ "{EOL}" } ; + case type::token: return view{ "{token}" } ; + case type::raw_text: return view{ "{raw text}" } ; + case type::compact: return view{ "{compact}" } ; + case type::quoted_text: return view_quoted_text ; + case type::begin_tag: return view_begin_tag ; + case type::close_tag: return view_close_tag ; + case type::comment_begin: return view_comment_begin ; + case type::comment_close: return view_comment_close ; + case type::close_inline: return view_close_inline ; + case type::empty_tag: return view_empty_tag ; + case type::equal: return view_equal ; + case type::defaults: return view_defaults ; + case type::lua_op_shl: return view_lua_op_shl ; + case type::lua_op_less: return view_lua_op_less ; + case type::lua_op_less_eq: return view_lua_op_less_eq ; + default: return view{ "{unknown}" } ; }; }; fail(ansi::add("Unexpected '", str(what), "' after '", str(last), "'")); @@ -1088,8 +1097,8 @@ namespace netxs::xml } else if (what == type::raw_text) { - auto size = data.find('<'); - if (size == view::npos) + auto iter = utf::find_char_except_skips(data, '<', view_lua_op_shl, view_lua_op_less, view_lua_op_less_eq); + if (iter == data.end()) { item->body.push_back(page.append(type::unknown, data)); data = {}; @@ -1097,6 +1106,7 @@ namespace netxs::xml what = type::eof; break; } + auto size = iter - data.begin(); item->body.push_back(page.append(type::raw_text, data.substr(0, size))); data.remove_prefix(size); temp = data; diff --git a/src/vtm.xml b/src/vtm.xml index bfb43de897..f65317ca49 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -418,9 +418,9 @@ R"==( + -->