mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-12-16 01:48:56 +08:00
Coding style + fix tests
This commit is contained in:
@@ -25,6 +25,8 @@ class Loop;
|
|||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
using Component = std::shared_ptr<ComponentBase>;
|
using Component = std::shared_ptr<ComponentBase>;
|
||||||
|
using TerminalIDUpdateCallback = std::function<void (const TerminalID &)>;
|
||||||
|
|
||||||
class ScreenInteractivePrivate;
|
class ScreenInteractivePrivate;
|
||||||
|
|
||||||
/// @brief ScreenInteractive is a `Screen` that can handle events, run a main
|
/// @brief ScreenInteractive is a `Screen` that can handle events, run a main
|
||||||
@@ -75,10 +77,7 @@ class ScreenInteractive : public Screen {
|
|||||||
|
|
||||||
TerminalID TerminalId() const;
|
TerminalID TerminalId() const;
|
||||||
|
|
||||||
typedef std::function<void(TerminalID const& terminal_id)> TerminalIDUpdateCallback;
|
void OnTerminalIDUpdate(const TerminalIDUpdateCallback& callback);
|
||||||
|
|
||||||
void OnTerminalIDUpdate(
|
|
||||||
TerminalIDUpdateCallback const& callback);
|
|
||||||
|
|
||||||
// Selection API.
|
// Selection API.
|
||||||
std::string GetSelection();
|
std::string GetSelection();
|
||||||
@@ -164,10 +163,10 @@ class ScreenInteractive : public Screen {
|
|||||||
std::unique_ptr<Selection> selection_;
|
std::unique_ptr<Selection> selection_;
|
||||||
std::function<void()> selection_on_change_;
|
std::function<void()> selection_on_change_;
|
||||||
|
|
||||||
TerminalID m_terminal_id;
|
TerminalID m_terminal_id = TerminalID::Unknown;
|
||||||
|
|
||||||
typedef std::list<TerminalIDUpdateCallback> TerminalIDUpdateCallbackContainer;
|
using TerminalIDUpdateCallbackContainer = std::list<TerminalIDUpdateCallback>;
|
||||||
TerminalIDUpdateCallbackContainer m_terminal_id_update_callbacks;
|
TerminalIDUpdateCallbackContainer terminal_id_callback_;
|
||||||
|
|
||||||
friend class Loop;
|
friend class Loop;
|
||||||
|
|
||||||
|
|||||||
@@ -10,20 +10,20 @@
|
|||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
std::string const TERMINAL_ID_REQUEST("\x1b[0c");
|
/// @brief The TerminalID enum class represents different types of terminal
|
||||||
|
/// emulators that FTXUI can detect. It is used to identify the terminal
|
||||||
/// @brief A mouse event. It contains the coordinate of the mouse, the button
|
/// emulator in use, which can affect how FTXUI renders its output and handles
|
||||||
/// pressed and the modifier (shift, ctrl, meta).
|
/// input events.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
|
enum class TerminalID {
|
||||||
|
Unknown,
|
||||||
|
// --
|
||||||
|
|
||||||
enum class TerminalID
|
Konsole,
|
||||||
{
|
LinuxVC,
|
||||||
UNKNOWN,
|
Urxvt,
|
||||||
XTERM,
|
Vte,
|
||||||
KONSOLE,
|
Xterm,
|
||||||
URXVT,
|
|
||||||
VTE,
|
|
||||||
LINUXVC
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(
|
std::ostream& operator<<(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "ftxui/component/loop.hpp"
|
#include "ftxui/component/loop.hpp"
|
||||||
#include "ftxui/component/terminal_id.hpp"
|
|
||||||
|
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
|
|
||||||
@@ -49,9 +48,6 @@ void Loop::RunOnceBlocking() {
|
|||||||
/// Execute the loop, blocking the current thread, up until the loop has
|
/// Execute the loop, blocking the current thread, up until the loop has
|
||||||
/// quitted.
|
/// quitted.
|
||||||
void Loop::Run() {
|
void Loop::Run() {
|
||||||
// Ensure we perform a single terminal id request before we are starting the loop itself.
|
|
||||||
std::cout << TERMINAL_ID_REQUEST;
|
|
||||||
|
|
||||||
while (!HasQuitted()) {
|
while (!HasQuitted()) {
|
||||||
RunOnceBlocking();
|
RunOnceBlocking();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,6 +321,8 @@ std::string DeviceStatusReport(DSRMode ps) {
|
|||||||
return CSI + std::to_string(int(ps)) + "n";
|
return CSI + std::to_string(int(ps)) + "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string TerminalIdReport = "\x1b[0c";
|
||||||
|
|
||||||
class CapturedMouseImpl : public CapturedMouseInterface {
|
class CapturedMouseImpl : public CapturedMouseInterface {
|
||||||
public:
|
public:
|
||||||
explicit CapturedMouseImpl(std::function<void(void)> callback)
|
explicit CapturedMouseImpl(std::function<void(void)> callback)
|
||||||
@@ -352,8 +354,7 @@ ScreenInteractive::ScreenInteractive(Dimension dimension,
|
|||||||
bool use_alternative_screen)
|
bool use_alternative_screen)
|
||||||
: Screen(dimx, dimy),
|
: Screen(dimx, dimy),
|
||||||
dimension_(dimension),
|
dimension_(dimension),
|
||||||
use_alternative_screen_(use_alternative_screen),
|
use_alternative_screen_(use_alternative_screen) {
|
||||||
m_terminal_id(TerminalID::UNKNOWN) {
|
|
||||||
task_receiver_ = MakeReceiver<Task>();
|
task_receiver_ = MakeReceiver<Task>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,10 +383,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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +411,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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -422,8 +423,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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -725,6 +726,9 @@ void ScreenInteractive::Install() {
|
|||||||
enable({DECMode::kMouseSgrExtMode});
|
enable({DECMode::kMouseSgrExtMode});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Report the Terminal ID.
|
||||||
|
std::cout << TerminalIdReport;
|
||||||
|
|
||||||
// After installing the new configuration, flush it to the terminal to
|
// After installing the new configuration, flush it to the terminal to
|
||||||
// ensure it is fully applied:
|
// ensure it is fully applied:
|
||||||
Flush();
|
Flush();
|
||||||
@@ -795,34 +799,22 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg.is_terminal_id()) {
|
||||||
|
m_terminal_id = arg.terminal_id();
|
||||||
|
|
||||||
|
for(auto & callback : terminal_id_callback_) {
|
||||||
|
if (callback) {
|
||||||
|
callback(m_terminal_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (arg.is_mouse()) {
|
if (arg.is_mouse()) {
|
||||||
arg.mouse().x -= cursor_x_;
|
arg.mouse().x -= cursor_x_;
|
||||||
arg.mouse().y -= cursor_y_;
|
arg.mouse().y -= cursor_y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.is_terminal_id())
|
|
||||||
{
|
|
||||||
m_terminal_id =
|
|
||||||
arg.terminal_id();
|
|
||||||
|
|
||||||
for (auto itr = m_terminal_id_update_callbacks.begin(),
|
|
||||||
end_itr = m_terminal_id_update_callbacks.end();
|
|
||||||
(itr != end_itr);
|
|
||||||
++itr)
|
|
||||||
{
|
|
||||||
if (*itr)
|
|
||||||
{
|
|
||||||
(*itr)(m_terminal_id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The callback function is invalid and will be removed
|
|
||||||
m_terminal_id_update_callbacks.erase(
|
|
||||||
itr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arg.screen_ = this;
|
arg.screen_ = this;
|
||||||
|
|
||||||
bool handled = component->OnEvent(arg);
|
bool handled = component->OnEvent(arg);
|
||||||
@@ -1108,16 +1100,13 @@ bool ScreenInteractive::SelectionData::operator!=(
|
|||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalID ScreenInteractive::TerminalId() const
|
TerminalID ScreenInteractive::TerminalId() const {
|
||||||
{
|
return m_terminal_id;
|
||||||
return m_terminal_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenInteractive::OnTerminalIDUpdate(
|
void ScreenInteractive::OnTerminalIDUpdate(
|
||||||
TerminalIDUpdateCallback const& callback)
|
const TerminalIDUpdateCallback& callback) {
|
||||||
{
|
terminal_id_callback_.push_back(callback);
|
||||||
m_terminal_id_update_callbacks.push_back(
|
|
||||||
callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ftxui.
|
} // namespace ftxui.
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ TEST(ScreenInteractive, FixedSizeInitialFrame) {
|
|||||||
"\x1B[?1003h" // Enable mouse motion tracking.
|
"\x1B[?1003h" // Enable mouse motion tracking.
|
||||||
"\x1B[?1015h" // Enable mouse wheel tracking.
|
"\x1B[?1015h" // Enable mouse wheel tracking.
|
||||||
"\x1B[?1006h" // Enable SGR mouse tracking.
|
"\x1B[?1006h" // Enable SGR mouse tracking.
|
||||||
|
"\x1B[0c" // Query terminal ID.
|
||||||
"\0" // Flush stdout.
|
"\0" // Flush stdout.
|
||||||
|
|
||||||
// Reset the screen.
|
// Reset the screen.
|
||||||
|
|||||||
@@ -7,45 +7,35 @@
|
|||||||
namespace ftxui
|
namespace ftxui
|
||||||
{
|
{
|
||||||
|
|
||||||
std::ostream& operator<<(
|
std::ostream& operator<<(std::ostream& os, TerminalID terminal_id) {
|
||||||
std::ostream& os,
|
switch (terminal_id) {
|
||||||
TerminalID terminal_id)
|
case TerminalID::Unknown: {
|
||||||
{
|
os << "Unknown";
|
||||||
switch(terminal_id)
|
break;
|
||||||
{
|
}
|
||||||
case TerminalID::UNKNOWN:
|
case TerminalID::Urxvt: {
|
||||||
{
|
os << "Urxvt";
|
||||||
os << "UNKNOWN";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TerminalID::XTERM:
|
case TerminalID::LinuxVC: {
|
||||||
{
|
os << "LinuxVC";
|
||||||
os << "XTERM";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TerminalID::KONSOLE:
|
case TerminalID::Konsole: {
|
||||||
{
|
os << "Konsole";
|
||||||
os << "KONSOLE";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TerminalID::URXVT:
|
case TerminalID::Vte: {
|
||||||
{
|
os << "Vte";
|
||||||
os << "URXVT";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TerminalID::VTE:
|
case TerminalID::Xterm: {
|
||||||
{
|
os << "Xterm";
|
||||||
os << "VTE";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TerminalID::LINUXVC:
|
}
|
||||||
{
|
|
||||||
os << "LINUXVC";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|||||||
@@ -469,52 +469,21 @@ TerminalInputParser::Output TerminalInputParser::ParseCursorPosition(
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminalInputParser::Output TerminalInputParser::ParseTerminalID(
|
TerminalInputParser::Output TerminalInputParser::ParseTerminalID(
|
||||||
std::vector<int> arguments)
|
std::vector<int> arguments) {
|
||||||
{
|
if (arguments.empty()) {
|
||||||
Output output(TERMINAL_ID);
|
return TerminalID::Unknown;
|
||||||
|
|
||||||
if (!arguments.empty())
|
|
||||||
{
|
|
||||||
switch(arguments[0])
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
output.terminal_id =
|
|
||||||
TerminalID::URXVT;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
output.terminal_id =
|
|
||||||
TerminalID::LINUXVC;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 62:
|
|
||||||
{
|
|
||||||
output.terminal_id =
|
|
||||||
TerminalID::KONSOLE;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
output.terminal_id =
|
|
||||||
TerminalID::UNKNOWN;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
output.terminal_id =
|
|
||||||
TerminalID::UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
switch (arguments[0]) {
|
||||||
|
case 1:
|
||||||
|
return TerminalID::Xterm;
|
||||||
|
case 6:
|
||||||
|
return TerminalID::LinuxVC;
|
||||||
|
case 62:
|
||||||
|
return TerminalID::Konsole;
|
||||||
|
default:
|
||||||
|
return TerminalID::Unknown;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ class TerminalInputParser {
|
|||||||
|
|
||||||
Output(Type t) // NOLINT
|
Output(Type t) // NOLINT
|
||||||
: type(t) {}
|
: type(t) {}
|
||||||
|
|
||||||
|
Output(TerminalID terminal_id) // NOLINT
|
||||||
|
: type(TERMINAL_ID), terminal_id(terminal_id) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Send(Output output);
|
void Send(Output output);
|
||||||
|
|||||||
@@ -511,26 +511,25 @@ TEST(Event, DeviceControlString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(Event, TerminalID) {
|
TEST(Event, TerminalID) {
|
||||||
|
// Test terminal id for KDE konsole
|
||||||
|
auto event_receiver = MakeReceiver<Task>();
|
||||||
|
{
|
||||||
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
||||||
|
parser.Add('\x1B');
|
||||||
|
parser.Add('[');
|
||||||
|
parser.Add('?');
|
||||||
|
parser.Add('6');
|
||||||
|
parser.Add('2');
|
||||||
|
parser.Add(';');
|
||||||
|
parser.Add('2');
|
||||||
|
parser.Add('c');
|
||||||
|
}
|
||||||
|
|
||||||
// Test terminal id for KDE konsole
|
Task received;
|
||||||
auto event_receiver = MakeReceiver<Task>();
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
||||||
{
|
EXPECT_TRUE(std::get<Event>(received).is_terminal_id());
|
||||||
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
EXPECT_EQ(TerminalID::Konsole, std::get<Event>(received).terminal_id());
|
||||||
parser.Add('\x1B');
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
||||||
parser.Add('[');
|
|
||||||
parser.Add('?');
|
|
||||||
parser.Add('6');
|
|
||||||
parser.Add('2');
|
|
||||||
parser.Add(';');
|
|
||||||
parser.Add('2');
|
|
||||||
parser.Add('c');
|
|
||||||
}
|
|
||||||
|
|
||||||
Task received;
|
|
||||||
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
||||||
EXPECT_TRUE(std::get<Event>(received).is_terminal_id());
|
|
||||||
EXPECT_EQ(TerminalID::KONSOLE, std::get<Event>(received).terminal_id());
|
|
||||||
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|||||||
Reference in New Issue
Block a user