mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-22 18:59:59 +08:00
Miscellaneous refactoring (#160)
* Reorganize ContainerBase - Reduce Container overloads using default arguments - Extract member function pointers to virtual functions - Separate classes for Vertical, Horizontal and Tab containers * Collect unpack from NodeDecorator subclasses * Reduce redundant expansion for aliases
This commit is contained in:
parent
210e8c5863
commit
09805e5e86
@ -24,26 +24,19 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
int shift = 0;
|
||||
|
||||
class Graph {
|
||||
public:
|
||||
Graph(int* shift) : shift_(shift) {}
|
||||
std::vector<int> operator()(int width, int height) {
|
||||
std::vector<int> output(width);
|
||||
for (int i = 0; i < width; ++i) {
|
||||
float v = 0;
|
||||
v += 0.1f * sin((i + *shift_) * 0.1f);
|
||||
v += 0.2f * sin((i + *shift_ + 10) * 0.15f);
|
||||
v += 0.1f * sin((i + *shift_) * 0.03f);
|
||||
v *= height;
|
||||
v += 0.5f * height;
|
||||
output[i] = (int)v;
|
||||
}
|
||||
return output;
|
||||
auto my_graph = [&shift](int width, int height) {
|
||||
std::vector<int> output(width);
|
||||
for (int i = 0; i < width; ++i) {
|
||||
float v = 0.5f;
|
||||
v += 0.1f * sin((i + shift) * 0.1f);
|
||||
v += 0.2f * sin((i + shift + 10) * 0.15f);
|
||||
v += 0.1f * sin((i + shift) * 0.03f);
|
||||
v *= height;
|
||||
output[i] = (int)v;
|
||||
}
|
||||
int* shift_;
|
||||
return output;
|
||||
};
|
||||
|
||||
Graph my_graph(&shift);
|
||||
auto htop = Renderer([&] {
|
||||
auto frequency = vbox({
|
||||
text(L"Frequency [Mhz]") | hcenter,
|
||||
@ -53,7 +46,7 @@ int main(int argc, const char* argv[]) {
|
||||
filler(),
|
||||
text(L"1200 "),
|
||||
filler(),
|
||||
text(L"0% "),
|
||||
text(L"0 "),
|
||||
}),
|
||||
graph(std::ref(my_graph)) | flex,
|
||||
}) | flex,
|
||||
|
@ -24,7 +24,6 @@ class ScreenInteractive : public Screen {
|
||||
static ScreenInteractive FitComponent();
|
||||
static ScreenInteractive TerminalOutput();
|
||||
|
||||
~ScreenInteractive();
|
||||
void Loop(Component);
|
||||
std::function<void()> ExitLoopClosure();
|
||||
|
||||
|
@ -36,7 +36,7 @@ class Node {
|
||||
virtual void Render(Screen& screen);
|
||||
|
||||
protected:
|
||||
std::vector<Element> children_;
|
||||
Elements children_;
|
||||
Requirement requirement_;
|
||||
Box box_;
|
||||
};
|
||||
|
@ -13,44 +13,10 @@ namespace ftxui {
|
||||
|
||||
class ContainerBase : public ComponentBase {
|
||||
public:
|
||||
static Component Vertical() { return Vertical({}); }
|
||||
static Component Vertical(Components children) {
|
||||
return Vertical(std::move(children), /*selector=*/nullptr);
|
||||
}
|
||||
static Component Vertical(Components children, int* selector) {
|
||||
auto container = std::make_shared<ContainerBase>();
|
||||
container->event_handler_ = &ContainerBase::VerticalEvent;
|
||||
container->render_handler_ = &ContainerBase::VerticalRender;
|
||||
container->selector_ = selector ? selector : &container->selected_;
|
||||
ContainerBase(Components children, int* selector)
|
||||
: selector_(selector ? selector : &selected_) {
|
||||
for (Component& child : children)
|
||||
container->Add(std::move(child));
|
||||
return container;
|
||||
}
|
||||
|
||||
static Component Horizontal() { return Horizontal({}); }
|
||||
static Component Horizontal(Components children) {
|
||||
return Horizontal(std::move(children), /*selector=*/nullptr);
|
||||
}
|
||||
static Component Horizontal(Components children, int* selector) {
|
||||
auto container = std::make_shared<ContainerBase>();
|
||||
container->event_handler_ = &ContainerBase::HorizontalEvent;
|
||||
container->render_handler_ = &ContainerBase::HorizontalRender;
|
||||
container->selector_ = selector ? selector : &container->selected_;
|
||||
for (Component& child : children)
|
||||
container->Add(std::move(child));
|
||||
return container;
|
||||
}
|
||||
|
||||
static Component Tab(int* selector) { return Tab({}, selector); }
|
||||
static Component Tab(Components children, int* selector) {
|
||||
auto container = std::make_shared<ContainerBase>();
|
||||
container->selector_ = selector ? selector : &container->selected_;
|
||||
container->event_handler_ = &ContainerBase::TabEvent;
|
||||
container->render_handler_ = &ContainerBase::TabRender;
|
||||
container->is_tab_ = true;
|
||||
for (Component& child : children)
|
||||
container->Add(std::move(child));
|
||||
return container;
|
||||
Add(std::move(child));
|
||||
}
|
||||
|
||||
// Component override.
|
||||
@ -64,7 +30,7 @@ class ContainerBase : public ComponentBase {
|
||||
if (ActiveChild() && ActiveChild()->OnEvent(event))
|
||||
return true;
|
||||
|
||||
return (this->*event_handler_)(event);
|
||||
return EventHandler(event);
|
||||
}
|
||||
|
||||
Component ActiveChild() override {
|
||||
@ -83,10 +49,36 @@ class ContainerBase : public ComponentBase {
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
// Handlers
|
||||
virtual bool EventHandler(Event) { return false; }
|
||||
|
||||
bool VerticalEvent(Event event) {
|
||||
virtual bool OnMouseEvent(Event event) {
|
||||
for (Component& child : children_) {
|
||||
if (child->OnEvent(event))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int selected_ = 0;
|
||||
int* selector_ = nullptr;
|
||||
};
|
||||
|
||||
class VerticalContainer : public ContainerBase {
|
||||
public:
|
||||
using ContainerBase::ContainerBase;
|
||||
|
||||
Element Render() override {
|
||||
Elements elements;
|
||||
for (auto& it : children_)
|
||||
elements.push_back(it->Render());
|
||||
if (elements.size() == 0)
|
||||
return text(L"Empty container");
|
||||
return vbox(std::move(elements));
|
||||
}
|
||||
|
||||
bool EventHandler(Event event) override {
|
||||
int old_selected = *selector_;
|
||||
if (event == Event::ArrowUp || event == Event::Character('k'))
|
||||
(*selector_)--;
|
||||
@ -100,8 +92,22 @@ class ContainerBase : public ComponentBase {
|
||||
*selector_ = std::max(0, std::min(int(children_.size()) - 1, *selector_));
|
||||
return old_selected != *selector_;
|
||||
}
|
||||
};
|
||||
|
||||
bool HorizontalEvent(Event event) {
|
||||
class HorizontalContainer : public ContainerBase {
|
||||
public:
|
||||
using ContainerBase::ContainerBase;
|
||||
|
||||
Element Render() override {
|
||||
Elements elements;
|
||||
for (auto& it : children_)
|
||||
elements.push_back(it->Render());
|
||||
if (elements.size() == 0)
|
||||
return text(L"Empty container");
|
||||
return hbox(std::move(elements));
|
||||
}
|
||||
|
||||
bool EventHandler(Event event) override {
|
||||
int old_selected = *selector_;
|
||||
if (event == Event::ArrowLeft || event == Event::Character('h'))
|
||||
(*selector_)--;
|
||||
@ -115,55 +121,22 @@ class ContainerBase : public ComponentBase {
|
||||
*selector_ = std::max(0, std::min(int(children_.size()) - 1, *selector_));
|
||||
return old_selected != *selector_;
|
||||
}
|
||||
};
|
||||
|
||||
bool TabEvent(Event) { return false; }
|
||||
class TabContainer : public ContainerBase {
|
||||
public:
|
||||
using ContainerBase::ContainerBase;
|
||||
|
||||
bool OnMouseEvent(Event event) {
|
||||
if (is_tab_)
|
||||
return ActiveChild()->OnEvent(event);
|
||||
|
||||
for (Component& child : children_) {
|
||||
if (child->OnEvent(event))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
using EventHandler = bool (ContainerBase::*)(Event);
|
||||
using RenderHandler = Element (ContainerBase::*)();
|
||||
|
||||
Element Render() override { return (this->*render_handler_)(); }
|
||||
|
||||
Element VerticalRender() {
|
||||
Elements elements;
|
||||
for (auto& it : children_)
|
||||
elements.push_back(it->Render());
|
||||
if (elements.size() == 0)
|
||||
return text(L"Empty container");
|
||||
return vbox(std::move(elements));
|
||||
}
|
||||
|
||||
Element HorizontalRender() {
|
||||
Elements elements;
|
||||
for (auto& it : children_)
|
||||
elements.push_back(it->Render());
|
||||
if (elements.size() == 0)
|
||||
return text(L"Empty container");
|
||||
return hbox(std::move(elements));
|
||||
}
|
||||
|
||||
Element TabRender() {
|
||||
Element Render() override {
|
||||
Component active_child = ActiveChild();
|
||||
if (active_child)
|
||||
return active_child->Render();
|
||||
return text(L"Empty container");
|
||||
}
|
||||
|
||||
EventHandler event_handler_;
|
||||
RenderHandler render_handler_;
|
||||
int selected_ = 0;
|
||||
int* selector_ = nullptr;
|
||||
bool is_tab_ = false;
|
||||
bool OnMouseEvent(Event event) override {
|
||||
return ActiveChild()->OnEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
namespace Container {
|
||||
@ -185,7 +158,7 @@ namespace Container {
|
||||
/// });
|
||||
/// ```
|
||||
Component Vertical(Components children) {
|
||||
return ContainerBase::Vertical(std::move(children));
|
||||
return Vertical(std::move(children), nullptr);
|
||||
}
|
||||
|
||||
/// @brief A list of components, drawn one by one vertically and navigated
|
||||
@ -207,7 +180,7 @@ Component Vertical(Components children) {
|
||||
/// });
|
||||
/// ```
|
||||
Component Vertical(Components children, int* selector) {
|
||||
return ContainerBase::Vertical(std::move(children), selector);
|
||||
return std::make_shared<VerticalContainer>(std::move(children), selector);
|
||||
}
|
||||
|
||||
/// @brief A list of components, drawn one by one horizontally and navigated
|
||||
@ -228,7 +201,7 @@ Component Vertical(Components children, int* selector) {
|
||||
/// }, &selected_children);
|
||||
/// ```
|
||||
Component Horizontal(Components children) {
|
||||
return ContainerBase::Horizontal(std::move(children));
|
||||
return Horizontal(std::move(children), nullptr);
|
||||
}
|
||||
|
||||
/// @brief A list of components, drawn one by one horizontally and navigated
|
||||
@ -250,14 +223,14 @@ Component Horizontal(Components children) {
|
||||
/// }, selected_children);
|
||||
/// ```
|
||||
Component Horizontal(Components children, int* selector) {
|
||||
return ContainerBase::Horizontal(std::move(children), selector);
|
||||
return std::make_shared<HorizontalContainer>(std::move(children), selector);
|
||||
}
|
||||
|
||||
/// @brief A list of components, where only one is drawn and interacted with at
|
||||
/// a time. The |selector| gives the index of the selected component. This is
|
||||
/// useful to implement tabs.
|
||||
/// @param selector The index of the drawn children.
|
||||
/// @param children The list of components.
|
||||
/// @param selector The index of the drawn children.
|
||||
/// @ingroup component
|
||||
/// @see ContainerBase
|
||||
///
|
||||
@ -273,7 +246,7 @@ Component Horizontal(Components children, int* selector) {
|
||||
/// }, &tab_drawn);
|
||||
/// ```
|
||||
Component Tab(Components children, int* selector) {
|
||||
return ContainerBase::Tab(std::move(children), selector);
|
||||
return std::make_shared<TabContainer>(std::move(children), selector);
|
||||
}
|
||||
|
||||
} // namespace Container
|
||||
|
@ -241,8 +241,6 @@ ScreenInteractive::ScreenInteractive(int dimx,
|
||||
event_sender_ = event_receiver_->MakeSender();
|
||||
}
|
||||
|
||||
ScreenInteractive::~ScreenInteractive() {}
|
||||
|
||||
// static
|
||||
ScreenInteractive ScreenInteractive::FixedSize(int dimx, int dimy) {
|
||||
return ScreenInteractive(dimx, dimy, Dimension::Fixed, false);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, blink
|
||||
#include "ftxui/dom/elements.hpp" // for Element, blink
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -26,7 +26,7 @@ class Blink : public NodeDecorator {
|
||||
/// @brief The text drawn alternates in between visible and hidden.
|
||||
/// @ingroup dom
|
||||
Element blink(Element child) {
|
||||
return std::make_shared<Blink>(unpack(std::move(child)));
|
||||
return std::make_shared<Blink>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, bold
|
||||
#include "ftxui/dom/elements.hpp" // for Element, bold
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -26,7 +26,7 @@ class Bold : public NodeDecorator {
|
||||
/// @brief Use a bold font, for elements with more emphasis.
|
||||
/// @ingroup dom
|
||||
Element bold(Element child) {
|
||||
return std::make_shared<Bold>(unpack(std::move(child)));
|
||||
return std::make_shared<Bold>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, clear_under
|
||||
#include "ftxui/dom/elements.hpp" // for Element, clear_under
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -30,7 +30,7 @@ class ClearUnder : public NodeDecorator {
|
||||
/// @see ftxui::dbox
|
||||
/// @ingroup dom
|
||||
Element clear_under(Element child) {
|
||||
return std::make_shared<ClearUnder>(unpack(std::move(child)));
|
||||
return std::make_shared<ClearUnder>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Decorator, Elements, bgcolor, color
|
||||
#include "ftxui/dom/elements.hpp" // for Element, Decorator, bgcolor, color
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
#include "ftxui/screen/color.hpp" // for Color
|
||||
@ -11,8 +11,8 @@ namespace ftxui {
|
||||
|
||||
class BgColor : public NodeDecorator {
|
||||
public:
|
||||
BgColor(Elements children, Color color)
|
||||
: NodeDecorator(std::move(children)), color_(color) {}
|
||||
BgColor(Element child, Color color)
|
||||
: NodeDecorator(std::move(child)), color_(color) {}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
for (int y = box_.y_min; y <= box_.y_max; ++y) {
|
||||
@ -28,8 +28,8 @@ class BgColor : public NodeDecorator {
|
||||
|
||||
class FgColor : public NodeDecorator {
|
||||
public:
|
||||
FgColor(Elements children, Color color)
|
||||
: NodeDecorator(std::move(children)), color_(color) {}
|
||||
FgColor(Element child, Color color)
|
||||
: NodeDecorator(std::move(child)), color_(color) {}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
for (int y = box_.y_min; y <= box_.y_max; ++y) {
|
||||
@ -55,7 +55,7 @@ class FgColor : public NodeDecorator {
|
||||
/// Element document = color(Color::Green, text(L"Success")),
|
||||
/// ```
|
||||
Element color(Color color, Element child) {
|
||||
return std::make_shared<FgColor>(unpack(std::move(child)), color);
|
||||
return std::make_shared<FgColor>(std::move(child), color);
|
||||
}
|
||||
|
||||
/// @brief Set the background color of an element.
|
||||
@ -70,7 +70,7 @@ Element color(Color color, Element child) {
|
||||
/// Element document = bgcolor(Color::Green, text(L"Success")),
|
||||
/// ```
|
||||
Element bgcolor(Color color, Element child) {
|
||||
return std::make_shared<BgColor>(unpack(std::move(child)), color);
|
||||
return std::make_shared<BgColor>(std::move(child), color);
|
||||
}
|
||||
|
||||
/// @brief Decorate using a foreground color.
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, dim
|
||||
#include "ftxui/dom/elements.hpp" // for Element, dim
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -26,7 +26,7 @@ class Dim : public NodeDecorator {
|
||||
/// @brief Use a light font, for elements with less emphasis.
|
||||
/// @ingroup dom
|
||||
Element dim(Element child) {
|
||||
return std::make_shared<Dim>(unpack(std::move(child)));
|
||||
return std::make_shared<Dim>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -16,8 +16,7 @@ namespace ftxui {
|
||||
|
||||
class Select : public Node {
|
||||
public:
|
||||
Select(std::vector<std::shared_ptr<Node>> children)
|
||||
: Node(std::move(children)) {}
|
||||
Select(Elements children) : Node(std::move(children)) {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
@ -31,7 +30,7 @@ class Select : public Node {
|
||||
};
|
||||
|
||||
void SetBox(Box box) override {
|
||||
box_ = box;
|
||||
Node::SetBox(box);
|
||||
children_[0]->SetBox(box);
|
||||
}
|
||||
};
|
||||
@ -44,7 +43,7 @@ Element select(Element child) {
|
||||
|
||||
class Focus : public Select {
|
||||
public:
|
||||
Focus(std::vector<Element> children) : Select(std::move(children)) {}
|
||||
using Select::Select;
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Select::ComputeRequirement();
|
||||
@ -85,7 +84,7 @@ Element focus(Element child) {
|
||||
|
||||
class Frame : public Node {
|
||||
public:
|
||||
Frame(std::vector<Element> children, bool x_frame, bool y_frame)
|
||||
Frame(Elements children, bool x_frame, bool y_frame)
|
||||
: Node(std::move(children)), x_frame_(x_frame), y_frame_(y_frame) {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, inverted
|
||||
#include "ftxui/dom/elements.hpp" // for Element, inverted
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -27,7 +27,7 @@ class Inverted : public NodeDecorator {
|
||||
/// colors.
|
||||
/// @ingroup dom
|
||||
Element inverted(Element child) {
|
||||
return std::make_shared<Inverted>(unpack(std::move(child)));
|
||||
return std::make_shared<Inverted>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/node.hpp" // for Node, Elements
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
|
||||
namespace ftxui {
|
||||
struct Box;
|
||||
@ -11,7 +12,7 @@ struct Box;
|
||||
// Helper class.
|
||||
class NodeDecorator : public Node {
|
||||
public:
|
||||
NodeDecorator(Elements children) : Node(std::move(children)) {}
|
||||
NodeDecorator(Element child) : Node(unpack(std::move(child))) {}
|
||||
void ComputeRequirement() override;
|
||||
void SetBox(Box box) override;
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <memory> // for make_shared
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, underlined
|
||||
#include "ftxui/dom/elements.hpp" // for Element, underlined
|
||||
#include "ftxui/dom/node.hpp" // for Node
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp" // for Box
|
||||
@ -26,7 +26,7 @@ class Underlined : public NodeDecorator {
|
||||
/// @brief Make the underlined element to be underlined.
|
||||
/// @ingroup dom
|
||||
Element underlined(Element child) {
|
||||
return std::make_shared<Underlined>(unpack(std::move(child)));
|
||||
return std::make_shared<Underlined>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -38,11 +38,6 @@ static const char* MOVE_LEFT = "\r";
|
||||
static const char* MOVE_UP = "\x1B[1A";
|
||||
static const char* CLEAR_LINE = "\x1B[2K";
|
||||
|
||||
bool In(const Box& stencil, int x, int y) {
|
||||
return stencil.x_min <= x && x <= stencil.x_max && //
|
||||
stencil.y_min <= y && y <= stencil.y_max;
|
||||
}
|
||||
|
||||
Pixel dev_null_pixel;
|
||||
|
||||
#if defined(_WIN32)
|
||||
@ -195,7 +190,7 @@ wchar_t& Screen::at(int x, int y) {
|
||||
/// @param x The pixel position along the x-axis.
|
||||
/// @param y The pixel position along the y-axis.
|
||||
Pixel& Screen::PixelAt(int x, int y) {
|
||||
return In(stencil, x, y) ? pixels_[y][x] : dev_null_pixel;
|
||||
return stencil.Contain(x, y) ? pixels_[y][x] : dev_null_pixel;
|
||||
}
|
||||
|
||||
/// @brief Return a string to be printed in order to reset the cursor position
|
||||
|
Loading…
Reference in New Issue
Block a user