mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-12-16 01:48:56 +08:00
Compare commits
3 Commits
3d5146a5fb
...
1b4248db4f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b4248db4f | ||
|
|
b78b97056b | ||
|
|
baa5973128 |
@@ -1,9 +1,64 @@
|
|||||||
#include "ftxui/component/component.hpp"
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
|
// the LICENSE file.
|
||||||
|
#include <memory> // for shared_ptr, __shared_ptr_access
|
||||||
|
#include <string> // for operator+, to_string
|
||||||
|
|
||||||
int main(){
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
auto screen = ftxui::ScreenInteractive::Fullscreen();
|
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
|
||||||
auto testComponent = ftxui::Renderer([](){return ftxui::text("test Component");});
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
screen.Loop(testComponent);
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
return 0;
|
#include "ftxui/dom/elements.hpp" // for separator, gauge, text, Element, operator|, vbox, border
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
// This is a helper function to create a button with a custom style.
|
||||||
|
// The style is defined by a lambda function that takes an EntryState and
|
||||||
|
// returns an Element.
|
||||||
|
// We are using `center` to center the text inside the button, then `border` to
|
||||||
|
// add a border around the button, and finally `flex` to make the button fill
|
||||||
|
// the available space.
|
||||||
|
ButtonOption Style() {
|
||||||
|
auto option = ButtonOption::Animated();
|
||||||
|
option.transform = [](const EntryState& s) {
|
||||||
|
auto element = text(s.label);
|
||||||
|
if (s.focused) {
|
||||||
|
element |= bold;
|
||||||
|
}
|
||||||
|
return element | center | borderEmpty | flex;
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int value = 50;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
auto btn_dec_01 = Button("-1", [&] { value += 1; }, Style());
|
||||||
|
auto btn_inc_01 = Button("+1", [&] { value -= 1; }, Style());
|
||||||
|
auto btn_dec_10 = Button("-10", [&] { value -= 10; }, Style());
|
||||||
|
auto btn_inc_10 = Button("+10", [&] { value += 10; }, Style());
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// The tree of components. This defines how to navigate using the keyboard.
|
||||||
|
// The selected `row` is shared to get a grid layout.
|
||||||
|
int row = 0;
|
||||||
|
auto buttons = Container::Vertical({
|
||||||
|
Container::Horizontal({btn_dec_01, btn_inc_01}, &row) | flex,
|
||||||
|
Container::Horizontal({btn_dec_10, btn_inc_10}, &row) | flex,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modify the way to render them on screen:
|
||||||
|
auto component = Renderer(buttons, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("value = " + std::to_string(value)),
|
||||||
|
separator(),
|
||||||
|
buttons->Render() | flex,
|
||||||
|
}) |
|
||||||
|
flex | border;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
|
screen.Loop(component);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace ftxui {
|
|||||||
/// - 2x4 braille characters (1x1 pixel)
|
/// - 2x4 braille characters (1x1 pixel)
|
||||||
/// - 2x2 block characters (2x2 pixels)
|
/// - 2x2 block characters (2x2 pixels)
|
||||||
/// - 2x4 normal characters (2x4 pixels)
|
/// - 2x4 normal characters (2x4 pixels)
|
||||||
///
|
///
|
||||||
/// You need to multiply the x coordinate by 2 and the y coordinate by 4 to
|
/// You need to multiply the x coordinate by 2 and the y coordinate by 4 to
|
||||||
/// get the correct position in the terminal.
|
/// get the correct position in the terminal.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
|
||||||
/// @brief FlexboxConfig is a configuration structure that defines the layout
|
/// @brief FlexboxConfig is a configuration structure that defines the layout
|
||||||
/// properties for a flexbox container.
|
/// properties for a flexbox container.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace ftxui {
|
|||||||
/// It is defined by its minimum and maximum coordinates along the x and y axes.
|
/// It is defined by its minimum and maximum coordinates along the x and y axes.
|
||||||
/// Note that the coordinates are inclusive, meaning that the box includes both
|
/// Note that the coordinates are inclusive, meaning that the box includes both
|
||||||
/// the minimum and maximum values.
|
/// the minimum and maximum values.
|
||||||
///
|
///
|
||||||
/// @ingroup screen
|
/// @ingroup screen
|
||||||
struct Box {
|
struct Box {
|
||||||
int x_min = 0;
|
int x_min = 0;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <ftxui/component/event.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp"
|
||||||
#include "ftxui/component/terminal_input_parser.hpp"
|
#include "ftxui/component/terminal_input_parser.hpp"
|
||||||
@@ -212,16 +213,17 @@ extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
|
|||||||
auto screen =
|
auto screen =
|
||||||
Screen::Create(Dimension::Fixed(width), Dimension::Fixed(height));
|
Screen::Create(Dimension::Fixed(width), Dimension::Fixed(height));
|
||||||
|
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
// Generate some events.
|
||||||
{
|
std::vector<Event> events;
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
auto parser =
|
||||||
for (size_t i = 0; i < size; ++i)
|
TerminalInputParser([&](const Event& event) { events.push_back(event); });
|
||||||
parser.Add(data[i]);
|
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
parser.Add(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task event;
|
for (const auto& event : events) {
|
||||||
while (event_receiver->Receive(&event)) {
|
component->OnEvent(event);
|
||||||
component->OnEvent(std::get<Event>(event));
|
|
||||||
auto document = component->Render();
|
auto document = component->Render();
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ constexpr int timeout_milliseconds = 20;
|
|||||||
|
|
||||||
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
||||||
auto console = GetStdHandle(STD_INPUT_HANDLE);
|
auto console = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
auto parser = TerminalInputParser(out->Clone());
|
auto parser =
|
||||||
|
TerminalInputParser([&](Event event) { out->Send(std::move(event)); });
|
||||||
while (!*quit) {
|
while (!*quit) {
|
||||||
// Throttle ReadConsoleInput by waiting 250ms, this wait function will
|
// Throttle ReadConsoleInput by waiting 250ms, this wait function will
|
||||||
// return if there is input in the console.
|
// return if there is input in the console.
|
||||||
@@ -137,7 +138,8 @@ void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
|||||||
|
|
||||||
// Read char from the terminal.
|
// Read char from the terminal.
|
||||||
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
||||||
auto parser = TerminalInputParser(std::move(out));
|
auto parser =
|
||||||
|
TerminalInputParser([&](Event event) { out->Send(std::move(event)); });
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
while (!*quit) {
|
while (!*quit) {
|
||||||
@@ -173,7 +175,8 @@ int CheckStdinReady(int usec_timeout) {
|
|||||||
|
|
||||||
// Read char from the terminal.
|
// Read char from the terminal.
|
||||||
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
|
||||||
auto parser = TerminalInputParser(std::move(out));
|
auto parser =
|
||||||
|
TerminalInputParser([&](Event event) { out->Send(std::move(event)); });
|
||||||
|
|
||||||
while (!*quit) {
|
while (!*quit) {
|
||||||
if (!CheckStdinReady(timeout_microseconds)) {
|
if (!CheckStdinReady(timeout_microseconds)) {
|
||||||
@@ -381,10 +384,10 @@ ScreenInteractive ScreenInteractive::Fullscreen() {
|
|||||||
ScreenInteractive ScreenInteractive::FullscreenPrimaryScreen() {
|
ScreenInteractive ScreenInteractive::FullscreenPrimaryScreen() {
|
||||||
auto terminal = Terminal::Size();
|
auto terminal = Terminal::Size();
|
||||||
return {
|
return {
|
||||||
Dimension::Fullscreen,
|
Dimension::Fullscreen,
|
||||||
terminal.dimx,
|
terminal.dimx,
|
||||||
terminal.dimy,
|
terminal.dimy,
|
||||||
/*use_alternative_screen=*/false,
|
/*use_alternative_screen=*/false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +412,7 @@ ScreenInteractive ScreenInteractive::TerminalOutput() {
|
|||||||
return {
|
return {
|
||||||
Dimension::TerminalOutput,
|
Dimension::TerminalOutput,
|
||||||
terminal.dimx,
|
terminal.dimx,
|
||||||
terminal.dimy, // Best guess.
|
terminal.dimy, // Best guess.
|
||||||
/*use_alternative_screen=*/false,
|
/*use_alternative_screen=*/false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -421,8 +424,8 @@ ScreenInteractive ScreenInteractive::FitComponent() {
|
|||||||
auto terminal = Terminal::Size();
|
auto terminal = Terminal::Size();
|
||||||
return {
|
return {
|
||||||
Dimension::FitComponent,
|
Dimension::FitComponent,
|
||||||
terminal.dimx, // Best guess.
|
terminal.dimx, // Best guess.
|
||||||
terminal.dimy, // Best guess.
|
terminal.dimy, // Best guess.
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace {
|
|||||||
// Capture the standard output (stdout) to a string.
|
// Capture the standard output (stdout) to a string.
|
||||||
class StdCapture {
|
class StdCapture {
|
||||||
public:
|
public:
|
||||||
explicit StdCapture(std::string* captured)
|
explicit StdCapture(std::string* captured) : captured_(captured) {
|
||||||
: captured_(captured) {
|
if (pipe(pipefd_) != 0)
|
||||||
if (pipe(pipefd_) != 0) return;
|
return;
|
||||||
old_stdout_ = dup(fileno(stdout));
|
old_stdout_ = dup(fileno(stdout));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
dup2(pipefd_[1], fileno(stdout));
|
dup2(pipefd_[1], fileno(stdout));
|
||||||
@@ -188,9 +188,7 @@ TEST(ScreenInteractive, FixedSizeInitialFrame) {
|
|||||||
auto capture = StdCapture(&output);
|
auto capture = StdCapture(&output);
|
||||||
|
|
||||||
auto screen = ScreenInteractive::FixedSize(2, 2);
|
auto screen = ScreenInteractive::FixedSize(2, 2);
|
||||||
auto component = Renderer([&] {
|
auto component = Renderer([&] { return text("AB"); });
|
||||||
return text("AB");
|
|
||||||
});
|
|
||||||
|
|
||||||
Loop loop(&screen, component);
|
Loop loop(&screen, component);
|
||||||
loop.RunOnce();
|
loop.RunOnce();
|
||||||
@@ -241,7 +239,6 @@ TEST(ScreenInteractive, FixedSizeInitialFrame) {
|
|||||||
"\r\n"sv;
|
"\r\n"sv;
|
||||||
ASSERT_EQ(expected, output);
|
ASSERT_EQ(expected, output);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <cstdint> // for uint32_t
|
#include <cstdint> // for uint32_t
|
||||||
#include <ftxui/component/mouse.hpp> // for Mouse, Mouse::Button, Mouse::Motion
|
#include <ftxui/component/mouse.hpp> // for Mouse, Mouse::Button, Mouse::Motion
|
||||||
#include <ftxui/component/receiver.hpp> // for SenderImpl, Sender
|
#include <functional> // for std::function
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory> // for unique_ptr, allocator
|
#include <memory> // for unique_ptr, allocator
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
@@ -90,7 +90,7 @@ const std::map<std::string, std::string> g_uniformize = {
|
|||||||
{"\x1B[X", "\x1B[24~"}, // F12
|
{"\x1B[X", "\x1B[24~"}, // F12
|
||||||
};
|
};
|
||||||
|
|
||||||
TerminalInputParser::TerminalInputParser(Sender<Task> out)
|
TerminalInputParser::TerminalInputParser(std::function<void(Event)> out)
|
||||||
: out_(std::move(out)) {}
|
: out_(std::move(out)) {}
|
||||||
|
|
||||||
void TerminalInputParser::Timeout(int time) {
|
void TerminalInputParser::Timeout(int time) {
|
||||||
@@ -131,7 +131,7 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case CHARACTER:
|
case CHARACTER:
|
||||||
out_->Send(Event::Character(std::move(pending_)));
|
out_(Event::Character(std::move(pending_)));
|
||||||
pending_.clear();
|
pending_.clear();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -140,25 +140,25 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) {
|
|||||||
if (it != g_uniformize.end()) {
|
if (it != g_uniformize.end()) {
|
||||||
pending_ = it->second;
|
pending_ = it->second;
|
||||||
}
|
}
|
||||||
out_->Send(Event::Special(std::move(pending_)));
|
out_(Event::Special(std::move(pending_)));
|
||||||
pending_.clear();
|
pending_.clear();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MOUSE:
|
case MOUSE:
|
||||||
out_->Send(Event::Mouse(std::move(pending_), output.mouse)); // NOLINT
|
out_(Event::Mouse(std::move(pending_), output.mouse)); // NOLINT
|
||||||
pending_.clear();
|
pending_.clear();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CURSOR_POSITION:
|
case CURSOR_POSITION:
|
||||||
out_->Send(Event::CursorPosition(std::move(pending_), // NOLINT
|
out_(Event::CursorPosition(std::move(pending_), // NOLINT
|
||||||
output.cursor.x, // NOLINT
|
output.cursor.x, // NOLINT
|
||||||
output.cursor.y)); // NOLINT
|
output.cursor.y)); // NOLINT
|
||||||
pending_.clear();
|
pending_.clear();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CURSOR_SHAPE:
|
case CURSOR_SHAPE:
|
||||||
out_->Send(Event::CursorShape(std::move(pending_), output.cursor_shape));
|
out_(Event::CursorShape(std::move(pending_), output.cursor_shape));
|
||||||
pending_.clear();
|
pending_.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
#ifndef FTXUI_COMPONENT_TERMINAL_INPUT_PARSER
|
#ifndef FTXUI_COMPONENT_TERMINAL_INPUT_PARSER
|
||||||
#define FTXUI_COMPONENT_TERMINAL_INPUT_PARSER
|
#define FTXUI_COMPONENT_TERMINAL_INPUT_PARSER
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string> // for string
|
#include <string> // for string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse
|
#include "ftxui/component/mouse.hpp" // for Mouse
|
||||||
#include "ftxui/component/receiver.hpp" // for Sender
|
|
||||||
#include "ftxui/component/task.hpp" // for Task
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
@@ -17,7 +16,7 @@ struct Event;
|
|||||||
// Parse a sequence of |char| accross |time|. Produces |Event|.
|
// Parse a sequence of |char| accross |time|. Produces |Event|.
|
||||||
class TerminalInputParser {
|
class TerminalInputParser {
|
||||||
public:
|
public:
|
||||||
explicit TerminalInputParser(Sender<Task> out);
|
explicit TerminalInputParser(std::function<void(Event)> out);
|
||||||
void Timeout(int time);
|
void Timeout(int time);
|
||||||
void Add(char c);
|
void Add(char c);
|
||||||
|
|
||||||
@@ -62,7 +61,7 @@ class TerminalInputParser {
|
|||||||
Output ParseMouse(bool altered, bool pressed, std::vector<int> arguments);
|
Output ParseMouse(bool altered, bool pressed, std::vector<int> arguments);
|
||||||
Output ParseCursorPosition(std::vector<int> arguments);
|
Output ParseCursorPosition(std::vector<int> arguments);
|
||||||
|
|
||||||
Sender<Task> out_;
|
std::function<void(Event)> out_;
|
||||||
int position_ = -1;
|
int position_ = -1;
|
||||||
int timeout_ = 0;
|
int timeout_ = 0;
|
||||||
std::string pending_;
|
std::string pending_;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
#include <ftxui/component/mouse.hpp> // for Mouse, Mouse::Left, Mouse::Middle, Mouse::Pressed, Mouse::Released, Mouse::Right
|
#include <ftxui/component/mouse.hpp> // for Mouse, Mouse::Left, Mouse::Middle, Mouse::Pressed, Mouse::Released, Mouse::Right
|
||||||
#include <ftxui/component/task.hpp> // for Task
|
#include <functional> // for function
|
||||||
#include <initializer_list> // for initializer_list
|
#include <initializer_list> // for initializer_list
|
||||||
#include <memory> // for allocator, unique_ptr
|
#include <memory> // for allocator, unique_ptr
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp, Event::Backspace, Event::End, Event::Home, Event::Custom, Event::Delete, Event::F1, Event::F10, Event::F11, Event::F12, Event::F2, Event::F3, Event::F4, Event::F5, Event::F6, Event::F7, Event::F8, Event::F9, Event::PageDown, Event::PageUp, Event::Tab, Event::TabReverse, Event::Escape
|
#include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp, Event::Backspace, Event::End, Event::Home, Event::Custom, Event::Delete, Event::F1, Event::F10, Event::F11, Event::F12, Event::F2, Event::F3, Event::F4, Event::F5, Event::F6, Event::F7, Event::F8, Event::F9, Event::PageDown, Event::PageUp, Event::Tab, Event::TabReverse, Event::Escape
|
||||||
#include "ftxui/component/receiver.hpp" // for MakeReceiver, ReceiverImpl
|
|
||||||
#include "ftxui/component/terminal_input_parser.hpp"
|
#include "ftxui/component/terminal_input_parser.hpp"
|
||||||
#include "gtest/gtest.h" // for AssertionResult, Test, Message, TestPartResult, EXPECT_EQ, EXPECT_TRUE, TEST, EXPECT_FALSE
|
#include "gtest/gtest.h" // for AssertionResult, Test, Message, TestPartResult, EXPECT_EQ, EXPECT_TRUE, TEST, EXPECT_FALSE
|
||||||
|
|
||||||
@@ -22,228 +22,197 @@ TEST(Event, Character) {
|
|||||||
for (char c = 'A'; c <= 'Z'; ++c)
|
for (char c = 'A'; c <= 'Z'; ++c)
|
||||||
basic_char.push_back(c);
|
basic_char.push_back(c);
|
||||||
|
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
for (char c : basic_char)
|
for (char c : basic_char)
|
||||||
parser.Add(c);
|
parser.Add(c);
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
for (size_t i = 0; i < basic_char.size(); ++i) {
|
||||||
for (char c : basic_char) {
|
EXPECT_TRUE(received_events[i].is_character());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(basic_char[i], received_events[i].character()[0]);
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_character());
|
|
||||||
EXPECT_EQ(c, std::get<Event>(received).character()[0]);
|
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
EXPECT_EQ(received_events.size(), basic_char.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, EscapeKeyWithoutWaiting) {
|
TEST(Event, EscapeKeyWithoutWaiting) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_TRUE(received_events.empty());
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, EscapeKeyNotEnoughWait) {
|
TEST(Event, EscapeKeyNotEnoughWait) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Timeout(49);
|
parser.Timeout(49);
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_TRUE(received_events.empty());
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, EscapeKeyEnoughWait) {
|
TEST(Event, EscapeKeyEnoughWait) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Timeout(50);
|
parser.Timeout(50);
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(received_events[0], Event::Escape);
|
||||||
EXPECT_EQ(std::get<Event>(received), Event::Escape);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, EscapeFast) {
|
TEST(Event, EscapeFast) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('a');
|
parser.Add('a');
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('b');
|
parser.Add('b');
|
||||||
parser.Timeout(49);
|
parser.Timeout(49);
|
||||||
}
|
|
||||||
Task received;
|
EXPECT_EQ(2, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(received_events[0], Event::AltA);
|
||||||
EXPECT_EQ(std::get<Event>(received), Event::AltA);
|
EXPECT_EQ(received_events[1], Event::AltB);
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
||||||
EXPECT_EQ(std::get<Event>(received), Event::AltB);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseLeftClickPressed) {
|
TEST(Event, MouseLeftClickPressed) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('0');
|
parser.Add('0');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('M');
|
parser.Add('M');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_mouse());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
EXPECT_EQ(Mouse::Left, received_events[0].mouse().button);
|
||||||
EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
|
EXPECT_EQ(12, received_events[0].mouse().x);
|
||||||
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
EXPECT_EQ(42, received_events[0].mouse().y);
|
||||||
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
EXPECT_EQ(received_events[0].mouse().motion, Mouse::Pressed);
|
||||||
EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Pressed);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseLeftMoved) {
|
TEST(Event, MouseLeftMoved) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('3');
|
parser.Add('3');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('M');
|
parser.Add('M');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_mouse());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
EXPECT_EQ(Mouse::Left, received_events[0].mouse().button);
|
||||||
EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
|
EXPECT_EQ(12, received_events[0].mouse().x);
|
||||||
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
EXPECT_EQ(42, received_events[0].mouse().y);
|
||||||
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
EXPECT_EQ(received_events[0].mouse().motion, Mouse::Moved);
|
||||||
EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Moved);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseLeftClickReleased) {
|
TEST(Event, MouseLeftClickReleased) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('0');
|
parser.Add('0');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('m');
|
parser.Add('m');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_mouse());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
EXPECT_EQ(Mouse::Left, received_events[0].mouse().button);
|
||||||
EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
|
EXPECT_EQ(12, received_events[0].mouse().x);
|
||||||
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
EXPECT_EQ(42, received_events[0].mouse().y);
|
||||||
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
EXPECT_EQ(received_events[0].mouse().motion, Mouse::Released);
|
||||||
EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Released);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseReporting) {
|
TEST(Event, MouseReporting) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('R');
|
parser.Add('R');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_cursor_position());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_cursor_position());
|
EXPECT_EQ(42, received_events[0].cursor_x());
|
||||||
EXPECT_EQ(42, std::get<Event>(received).cursor_x());
|
EXPECT_EQ(12, received_events[0].cursor_y());
|
||||||
EXPECT_EQ(12, std::get<Event>(received).cursor_y());
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseMiddleClick) {
|
TEST(Event, MouseMiddleClick) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('3');
|
parser.Add('3');
|
||||||
parser.Add('3');
|
parser.Add('3');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('M');
|
parser.Add('M');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_mouse());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
EXPECT_EQ(Mouse::Middle, received_events[0].mouse().button);
|
||||||
EXPECT_EQ(Mouse::Middle, std::get<Event>(received).mouse().button);
|
EXPECT_EQ(12, received_events[0].mouse().x);
|
||||||
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
EXPECT_EQ(42, received_events[0].mouse().y);
|
||||||
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, MouseRightClick) {
|
TEST(Event, MouseRightClick) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add('\x1B');
|
parser.Add('');
|
||||||
parser.Add('[');
|
parser.Add('[');
|
||||||
parser.Add('3');
|
parser.Add('3');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('1');
|
parser.Add('1');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add(';');
|
parser.Add(';');
|
||||||
parser.Add('4');
|
parser.Add('4');
|
||||||
parser.Add('2');
|
parser.Add('2');
|
||||||
parser.Add('M');
|
parser.Add('M');
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_mouse());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
EXPECT_EQ(Mouse::Right, received_events[0].mouse().button);
|
||||||
EXPECT_EQ(Mouse::Right, std::get<Event>(received).mouse().button);
|
EXPECT_EQ(12, received_events[0].mouse().x);
|
||||||
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
EXPECT_EQ(42, received_events[0].mouse().y);
|
||||||
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, UTF8) {
|
TEST(Event, UTF8) {
|
||||||
@@ -313,31 +282,29 @@ TEST(Event, UTF8) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
for (auto test : kTestCase) {
|
for (auto test : kTestCase) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
for (auto input : test.input)
|
for (auto input : test.input)
|
||||||
parser.Add(input);
|
parser.Add(input);
|
||||||
}
|
|
||||||
Task received;
|
|
||||||
if (test.valid) {
|
if (test.valid) {
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_character());
|
EXPECT_TRUE(received_events[0].is_character());
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(received_events.empty());
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, NewLine) {
|
TEST(Event, NewLine) {
|
||||||
for (char newline : {'\r', '\n'}) {
|
for (char newline : {'\r', '\n'}) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add(newline);
|
parser.Add(newline);
|
||||||
}
|
EXPECT_EQ(1, received_events.size());
|
||||||
Task received;
|
EXPECT_TRUE(received_events[0] == Event::Return);
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
||||||
EXPECT_TRUE(std::get<Event>(received) == Event::Return);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,17 +324,16 @@ TEST(Event, Control) {
|
|||||||
cases.push_back({char(127), false});
|
cases.push_back({char(127), false});
|
||||||
|
|
||||||
for (auto test : cases) {
|
for (auto test : cases) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add(test.input);
|
parser.Add(test.input);
|
||||||
}
|
|
||||||
Task received;
|
|
||||||
if (test.cancel) {
|
if (test.cancel) {
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events.empty());
|
||||||
} else {
|
} else {
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_EQ(std::get<Event>(received), Event::Special({test.input}));
|
EXPECT_EQ(received_events[0], Event::Special({test.input}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,10 +351,9 @@ TEST(Event, Special) {
|
|||||||
Event expected;
|
Event expected;
|
||||||
} kTestCase[] = {
|
} kTestCase[] = {
|
||||||
// Arrow (default cursor mode)
|
// Arrow (default cursor mode)
|
||||||
{str("\x1B[A"), Event::ArrowUp}, {str("\x1B[B"), Event::ArrowDown},
|
{str("[A"), Event::ArrowUp}, {str("[B"), Event::ArrowDown},
|
||||||
{str("\x1B[C"), Event::ArrowRight}, {str("\x1B[D"), Event::ArrowLeft},
|
{str("[C"), Event::ArrowRight}, {str("[D"), Event::ArrowLeft},
|
||||||
{str("\x1B[H"), Event::Home}, {str("\x1B[F"), Event::End},
|
{str("[H"), Event::Home}, {str("[F"), Event::End},
|
||||||
/*
|
|
||||||
|
|
||||||
// Arrow (application cursor mode)
|
// Arrow (application cursor mode)
|
||||||
{str("\x1BOA"), Event::ArrowUp},
|
{str("\x1BOA"), Event::ArrowUp},
|
||||||
@@ -469,45 +434,38 @@ TEST(Event, Special) {
|
|||||||
|
|
||||||
// Custom:
|
// Custom:
|
||||||
{{0}, Event::Custom},
|
{{0}, Event::Custom},
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto test : kTestCase) {
|
for (auto test : kTestCase) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
for (auto input : test.input) {
|
for (auto input : test.input) {
|
||||||
parser.Add(input);
|
parser.Add(input);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_EQ(received_events[0], test.expected);
|
||||||
EXPECT_EQ(std::get<Event>(received), test.expected);
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, DeviceControlString) {
|
TEST(Event, DeviceControlString) {
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
std::vector<Event> received_events;
|
||||||
{
|
auto parser = TerminalInputParser(
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
[&](Event event) { received_events.push_back(std::move(event)); });
|
||||||
parser.Add(27); // ESC
|
parser.Add(27); // ESC
|
||||||
parser.Add(80); // P
|
parser.Add(80); // P
|
||||||
parser.Add(49); // 1
|
parser.Add(49); // 1
|
||||||
parser.Add(36); // $
|
parser.Add(36); // $
|
||||||
parser.Add(114); // r
|
parser.Add(114); // r
|
||||||
parser.Add(49); // 1
|
parser.Add(49); // 1
|
||||||
parser.Add(32); // SP
|
parser.Add(32); // SP
|
||||||
parser.Add(113); // q
|
parser.Add(113); // q
|
||||||
parser.Add(27); // ESC
|
parser.Add(27); // ESC
|
||||||
parser.Add(92); // (backslash)
|
parser.Add(92); // (backslash)
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
EXPECT_EQ(1, received_events.size());
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
EXPECT_TRUE(received_events[0].is_cursor_shape());
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_cursor_shape());
|
EXPECT_EQ(1, received_events[0].cursor_shape());
|
||||||
EXPECT_EQ(1, std::get<Event>(received).cursor_shape());
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
|
#include <cstddef>
|
||||||
|
#include <ftxui/component/event.hpp>
|
||||||
#include "ftxui/component/terminal_input_parser.hpp"
|
#include "ftxui/component/terminal_input_parser.hpp"
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
auto parser = TerminalInputParser([&](Event) {});
|
||||||
{
|
for (size_t i = 0; i < size; ++i) {
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
parser.Add(data[i]);
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
parser.Add(data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task received;
|
|
||||||
while (event_receiver->Receive(&received)) {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
return 0; // Non-zero return values are reserved for future use.
|
return 0; // Non-zero return values are reserved for future use.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,25 +48,38 @@ Dimensions& FallbackSize() {
|
|||||||
return g_fallback_size;
|
return g_fallback_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* Safe(const char* c) {
|
|
||||||
return (c != nullptr) ? c : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Contains(const std::string& s, const char* key) {
|
bool Contains(const std::string& s, const char* key) {
|
||||||
return s.find(key) != std::string::npos;
|
return s.find(key) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/gabime/spdlog/blob/885b5473e291833b148eeac3b7ce227e582cd88b/include/spdlog/details/os-inl.h#L566
|
||||||
|
std::string getenv_safe(const char *field) {
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#if defined(__cplusplus_winrt)
|
||||||
|
return std::string{}; // not supported under uwp
|
||||||
|
#else
|
||||||
|
size_t len = 0;
|
||||||
|
char buf[1024];
|
||||||
|
bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0;
|
||||||
|
return ok ? buf : std::string{};
|
||||||
|
#endif
|
||||||
|
#else // revert to getenv
|
||||||
|
char *buf = ::getenv(field); // NOLINT(*-mt-unsafe)
|
||||||
|
return buf ? buf : std::string{};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Terminal::Color ComputeColorSupport() {
|
Terminal::Color ComputeColorSupport() {
|
||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
return Terminal::Color::TrueColor;
|
return Terminal::Color::TrueColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string COLORTERM = Safe(std::getenv("COLORTERM")); // NOLINT
|
std::string COLORTERM = getenv_safe("COLORTERM");
|
||||||
if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor")) {
|
if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor")) {
|
||||||
return Terminal::Color::TrueColor;
|
return Terminal::Color::TrueColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TERM = Safe(std::getenv("TERM")); // NOLINT
|
std::string TERM = getenv_safe("TERM");
|
||||||
if (Contains(COLORTERM, "256") || Contains(TERM, "256")) {
|
if (Contains(COLORTERM, "256") || Contains(TERM, "256")) {
|
||||||
return Terminal::Color::Palette256;
|
return Terminal::Color::Palette256;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user