Skip to content

Commit

Permalink
[Feature] Adding text and separator dom elements (#14)
Browse files Browse the repository at this point in the history
* Bumped up FTXUI to 5.0.0
* Text also supports color formatting
* Separator supports Dashed, Light, Heavy and Double styles

Signed-off-by: Vedant <[email protected]>
  • Loading branch information
vrnimje authored Sep 12, 2023
1 parent 06c8e5a commit 56edf83
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ endif()
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
FetchContent_Declare(ftxui
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
GIT_TAG v4.0.0
GIT_TAG v5.0.0
)

FetchContent_GetProperties(ftxui)
Expand Down
3 changes: 3 additions & 0 deletions examples/Button.qf
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ Vertical{
Animated,
z
}
separator
BlueLight Button{
"chrome",
System("/usr/bin/google-chrome-stable"),
Ascii,
z
}
}
Heavy separator
text("This button exits the TUI")
Button {
"Exit",
"Exit"
Expand Down
21 changes: 21 additions & 0 deletions examples/separator.qf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Vertical{
text("Normal")
Normal separator
text("Light")
Light separator
text("Heavy")
Heavy separator
Horizontal {
text("Double")
Double separator
text("lorem ipsum")
}
separator
text("Dashed")
Dashed separator
Button {
"Exit",
"Exit",
Animated
}
}
15 changes: 15 additions & 0 deletions examples/text.qf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Vertical {
Blue text("The given button opens chrome in Linux")
str a
Red Button {
"chrome",
System("/usr/bin/google-chrome-stable"),
Animated,
a
}
Green text("This text is Green")
Button {
"Exit",
"Exit"
}
}
84 changes: 82 additions & 2 deletions include/quick-ftxui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ std::map<std::string, std::string> strings;
// The AST
///////////////////////////////////////////////////////////////////////////
struct nil {};
struct dom_text;
struct separator;
struct button;
struct expression;
struct input;
Expand All @@ -47,6 +49,7 @@ struct str_variable_decl;
enum block_alignment { VERTICAL, HORIZONTAL };
enum button_option { Ascii, Animated, Simple, NoOpt };
enum input_option { None, Password };
enum sep_style { Normal, Light, Dashed, Double, Heavy };
enum menu_option {
NoMenuOption,
Horizontal,
Expand Down Expand Up @@ -106,7 +109,8 @@ typedef boost::variant<
nil, boost::recursive_wrapper<button>, boost::recursive_wrapper<input>,
boost::recursive_wrapper<slider>, boost::recursive_wrapper<menu>,
boost::recursive_wrapper<toggle>, boost::recursive_wrapper<dropdown>,
boost::recursive_wrapper<expression>,
boost::recursive_wrapper<expression>, boost::recursive_wrapper<dom_text>,
boost::recursive_wrapper<separator>,
boost::recursive_wrapper<int_variable_decl>,
boost::recursive_wrapper<str_variable_decl>>
node;
Expand Down Expand Up @@ -154,6 +158,15 @@ struct dropdown {
std::string selected;
};

struct dom_text {
colours color = colours::Default;
std::string content = "";
};

struct separator {
sep_style style = sep_style::Normal;
};

struct int_variable_decl {
std::string identifier;
int value = 0;
Expand Down Expand Up @@ -252,6 +265,15 @@ BOOST_FUSION_ADAPT_STRUCT(quick_ftxui_ast::dropdown,
(std::string, selected)
)

BOOST_FUSION_ADAPT_STRUCT(quick_ftxui_ast::dom_text,
(quick_ftxui_ast::colours, color)
(std::string, content)
)

BOOST_FUSION_ADAPT_STRUCT(quick_ftxui_ast::separator,
(quick_ftxui_ast::sep_style, style)
)

BOOST_FUSION_ADAPT_STRUCT(quick_ftxui_ast::int_variable_decl,
(std::string, identifier)
(int, value)
Expand Down Expand Up @@ -562,6 +584,48 @@ struct node_printer : boost::static_visitor<> {
// std::cout << "nil: \"" << text << '"' << std::endl;
}

void operator()(quick_ftxui_ast::dom_text const &text) const {
// tab(indent + tabsize);
// std::cout << "nil: \"" << text << '"' << std::endl;
data->components.push_back(ftxui::Renderer([&] {
return (ftxui::text(text.content) |
ftxui::color(quick_ftxui_ast::resolveColour(text.color)));
}));
}

void operator()(quick_ftxui_ast::separator const &text) const {
// tab(indent + tabsize);
// std::cout << "nil: \"" << text << '"' << std::endl;
// clang-format off
switch (text.style) {
case quick_ftxui_ast::sep_style::Normal:
data->components.push_back(
ftxui::Renderer([&] { return ftxui::separator(); }));
break;

case quick_ftxui_ast::sep_style::Light:
data->components.push_back(
ftxui::Renderer([&] { return ftxui::separatorLight(); }));
break;
case quick_ftxui_ast::sep_style::Dashed:
data->components.push_back(
ftxui::Renderer([&] { return ftxui::separatorDashed(); }));
break;
case quick_ftxui_ast::sep_style::Double:
data->components.push_back(
ftxui::Renderer([&] { return ftxui::separatorDouble(); }));
break;
case quick_ftxui_ast::sep_style::Heavy: {
data->components.push_back(
ftxui::Renderer([&] { return ftxui::separatorHeavy(); }));
break;
}
default:
throw std::runtime_error("Should not reach here");
}
// clang-format on
}

void operator()(quick_ftxui_ast::int_variable_decl const &text) const {
// tab(indent + tabsize);

Expand Down Expand Up @@ -683,6 +747,14 @@ struct parser
("Yellow", quick_ftxui_ast::colours::Yellow)
("YellowLight", quick_ftxui_ast::colours::YellowLight)
;
sep_kw
.add
("Normal", quick_ftxui_ast::sep_style::Normal)
("Light", quick_ftxui_ast::sep_style::Light)
("Heavy", quick_ftxui_ast::sep_style::Heavy)
("Double", quick_ftxui_ast::sep_style::Double)
("Dashed", quick_ftxui_ast::sep_style::Dashed)
;
// clang-format on

quoted_string %= qi::lexeme['"' >> +(char_ - '"') >> '"'];
Expand Down Expand Up @@ -718,8 +790,13 @@ struct parser

str_var_decl %= qi::lit("str") >> identifier >> -('=' > quoted_string);

text_comp %= -(color_kw) >> qi::lit("text") >> '(' >> quoted_string >> ')';

sep_comp %= -(sep_kw) >> qi::lit("separator");

node = button_comp | input_comp | slider_comp | menu_comp | toggle_comp |
drpdwn_comp | int_var_decl | str_var_decl | expression;
drpdwn_comp | int_var_decl | str_var_decl | text_comp | sep_comp |
expression;

expression = alignment_kw >> '{' >> *node >> '}';

Expand All @@ -746,11 +823,14 @@ struct parser
int_var_decl;
qi::rule<Iterator, quick_ftxui_ast::str_variable_decl(), ascii::space_type>
str_var_decl;
qi::rule<Iterator, quick_ftxui_ast::dom_text(), ascii::space_type> text_comp;
qi::rule<Iterator, quick_ftxui_ast::separator(), ascii::space_type> sep_comp;
qi::symbols<char, quick_ftxui_ast::block_alignment> alignment_kw;
qi::symbols<char, quick_ftxui_ast::button_option> buttonopt_kw;
qi::symbols<char, quick_ftxui_ast::input_option> inputopt_kw;
qi::symbols<char, quick_ftxui_ast::menu_option> menuopt_kw;
qi::symbols<char, quick_ftxui_ast::colours> color_kw;
qi::symbols<char, quick_ftxui_ast::sep_style> sep_kw;
};

void parse_qf(std::string source_code) {
Expand Down
26 changes: 16 additions & 10 deletions tests/test1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ TEST_CASE("Parse Simple") {
// expect pass
REQUIRE(parse_helper("Vertical{Red Button{\"amool\",\"bmpp\",Ascii}}"));
REQUIRE(parse_helper("Vertical{Button{\"amool\",\"bmpp\",Simple}}"));
REQUIRE(parse_helper("Vertical{YellowLight Button{\"amool\",\"bmpp\",Animated}}"));
REQUIRE(parse_helper(
"Vertical{YellowLight Button{\"amool\",\"bmpp\",Animated}}"));
REQUIRE(parse_helper("Vertical{Button{\"amool\",\"bmpp\"}}"));
REQUIRE(parse_helper("Vertical{str x Blue Button{\"amool\",System(\"ls\"), x}}"));
REQUIRE(
parse_helper("Vertical{str x Blue Button{\"amool\",System(\"ls\"), x}}"));
REQUIRE(parse_helper("Horizontal{Button{\"amool\",\"bmpp\",Ascii}}"));
REQUIRE(parse_helper("Horizontal{Cyan Button{\"amool\",\"bmpp\",Simple}}"));
REQUIRE(parse_helper("Horizontal{Button{\"amool\",\"bmpp\",Animated}}"));
REQUIRE(parse_helper("Horizontal{CyanLight Button{\"amool\",\"bmpp\"}}"));
REQUIRE(parse_helper(
"Horizontal{str y Button{\"amool\",System(\"mkdir dir1\"), y}}"));

REQUIRE(parse_helper("Vertical{int x Black Slider{\"amool\", x, 5, 100, 1}}"));
REQUIRE(
parse_helper("Vertical{int x Black Slider{\"amool\", x, 5, 100, 1}}"));
REQUIRE(parse_helper("Horizontal{int y Slider{\"amool\", y, 5, 100, 1}}"));

REQUIRE(parse_helper(
Expand All @@ -41,15 +44,18 @@ TEST_CASE("Parse Simple") {
parse_helper("Vertical{ Button{ \"amool\" , "
"\"bmpp\" , Simple } }"));

REQUIRE(parse_helper(
"Vertical{int y Magenta Dropdown{[\"Physics\", \"Maths\", \"Chemistry\", "
" \"Biology\",], y}}"));
REQUIRE(parse_helper("Horizontal{int z Default Menu{[\"Physics\", \"Maths\", "
"\"Chemistry\", \"Biology\",], z}}"));
REQUIRE(parse_helper("Vertical{int y Magenta Dropdown{[\"Physics\", "
"\"Maths\", \"Chemistry\", "
" \"Biology\",], y}}"));
REQUIRE(
parse_helper("Horizontal{int z Default Menu{[\"Physics\", \"Maths\", "
"\"Chemistry\", \"Biology\",], z}}"));
REQUIRE(parse_helper("Vertical{int opt Toggle{[\"Opt1\", \"Opt2\",], opt}}"));
REQUIRE(parse_helper("Horizontal{int a MagentaLight Toggle{[\"Opt1\", \"Opt2\",], a}}"));
REQUIRE(parse_helper(
"Horizontal{int a MagentaLight Toggle{[\"Opt1\", \"Opt2\",], a}}"));
REQUIRE(parse_helper("Vertical{int b Toggle{[\"Opt1\", \"Opt2\",], b}}"));
REQUIRE(parse_helper("Horizontal{int x_ GrayDark Toggle{[\"Opt1\", \"Opt2\",], x_}}"));
REQUIRE(parse_helper(
"Horizontal{int x_ GrayDark Toggle{[\"Opt1\", \"Opt2\",], x_}}"));

// expect fail
REQUIRE(!parse_helper("\"amool\"{Button{\"amool\",\"bmpp\",\"cmqq\"}}"));
Expand Down

0 comments on commit 56edf83

Please sign in to comment.