Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
- `<name param=value />` and `<name> <param=value /> </name>` 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. `<name=names_value param=params_value />` - 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:
Expand Down
2 changes: 1 addition & 1 deletion src/netxs/desktopio/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
57 changes: 53 additions & 4 deletions src/netxs/desktopio/utf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -1723,20 +1732,60 @@ namespace netxs::utf
template<class Iter>
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<class ...Args>
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<class Iter>
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)
{
Expand Down
74 changes: 42 additions & 32 deletions src/netxs/desktopio/xml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: <name/nested_block1/nested_block2=value param=value />
include, // ':' ex: <name:...=value param=value />
localpath, // ex: <name:/path/path=value param=value />
Expand Down Expand Up @@ -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_comment_close = "-->"sv;
static constexpr auto view_close_tag = "</"sv;
static constexpr auto view_begin_tag = "<"sv;
static constexpr auto view_empty_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_comment_close = "-->"sv;
static constexpr auto view_close_tag = "</"sv;
static constexpr auto view_begin_tag = "<"sv;
static constexpr auto view_empty_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;
Expand Down Expand Up @@ -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), "'"));
Expand Down Expand Up @@ -1088,15 +1097,16 @@ 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 = {};
last = what;
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;
Expand Down
4 changes: 2 additions & 2 deletions src/vtm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ R"==(
<autohide=menu/autohide/>
<slim=menu/slim/>
<!-- //todo implement "linked nodes" (ala operator '|' ):
<LeftClick on="LeftClick"/>
<OnLeftClick on="LeftClick"/>
<AlwaysOnTopApplet="vtm.applet.ZOrder(vtm.applet.ZOrder()==1 and 0 or 1);"/>
<item label=" script="vtm.gear.SetHandled();"|AlwaysOnTopApplet|LeftClick tooltip=" AlwaysOnTop "/> -->
<item label=" AlwaysOnTop " script="vtm.gear.SetHandled();"|AlwaysOnTopApplet|OnLeftClick tooltip=" AlwaysOnTop "/> -->
<item label=" " tooltip=" AlwaysOnTop off ">
<script=AlwaysOnTopApplet on="LeftClick"/> <!-- The default event source is the parent object, i.e. source="item" (aka vtm.item). -->
<script> <!-- A binding to update the menu item label at runtime. -->
Expand Down