Skip to content

Commit 2715503

Browse files
committed
First version of supporting extraction of the terminal id.
1 parent 68fc9b1 commit 2715503

13 files changed

Lines changed: 281 additions & 6 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ add_library(component
144144
src/ftxui/component/resizable_split.cpp
145145
src/ftxui/component/screen_interactive.cpp
146146
src/ftxui/component/slider.cpp
147+
src/ftxui/component/terminal_id.cpp
147148
src/ftxui/component/terminal_input_parser.cpp
148149
src/ftxui/component/terminal_input_parser.hpp
149150
src/ftxui/component/util.cpp

examples/component/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ example(slider_direction)
4646
example(slider_rgb)
4747
example(tab_horizontal)
4848
example(tab_vertical)
49+
example(terminal_id)
4950
example(textarea)
5051
example(toggle)
5152
example(window)

examples/component/terminal_id.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2025 Arthur Sonzogni. All rights reserved.
2+
// Use of this source code is governed by the MIT license that can be found in
3+
// the LICENSE file.
4+
5+
#include "ftxui/component/component.hpp" // for Renderer
6+
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
7+
#include "ftxui/dom/elements.hpp" // for text, hbox, separator, Element, operator|, vbox, border
8+
9+
int main() {
10+
using namespace ftxui;
11+
12+
std::string terminal_id = "UNKNOWN";
13+
14+
auto screen =
15+
ScreenInteractive::TerminalOutput();
16+
17+
screen.OnTerminalIDUpdate([&terminal_id] (
18+
TerminalID const& terminal_id_update)
19+
{
20+
std::stringstream stream;
21+
stream << terminal_id_update;
22+
terminal_id = stream.str();
23+
});
24+
25+
auto renderer = Renderer([&]
26+
{
27+
return vbox({
28+
text("Terminal id " + terminal_id),
29+
}) | border;
30+
});
31+
32+
screen.Loop(renderer);
33+
}

include/ftxui/component/event.hpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
#ifndef FTXUI_COMPONENT_EVENT_HPP
55
#define FTXUI_COMPONENT_EVENT_HPP
66

7-
#include <ftxui/component/mouse.hpp> // for Mouse
8-
#include <string> // for string, operator==
7+
#include <ftxui/component/mouse.hpp> // for Mouse
8+
#include <ftxui/component/terminal_id.hpp> // for TerminalID
9+
#include <string> // for string, operator==
910

1011
namespace ftxui {
1112

@@ -35,6 +36,7 @@ struct Event {
3536
static Event Mouse(std::string, Mouse mouse);
3637
static Event CursorPosition(std::string, int x, int y); // Internal
3738
static Event CursorShape(std::string, int shape); // Internal
39+
static Event TerminalID(std::string input, enum TerminalID terminal_id); // Internal
3840

3941
// --- Arrow ---
4042
static const Event ArrowLeft;
@@ -117,6 +119,9 @@ struct Event {
117119
bool is_cursor_shape() const { return type_ == Type::CursorShape; }
118120
int cursor_shape() const { return data_.cursor_shape; }
119121

122+
bool is_terminal_id() const { return type_ == Type::TerminalID; }
123+
enum TerminalID terminal_id() const { return data_.terminal_id; }
124+
120125
// Debug
121126
std::string DebugString() const;
122127

@@ -132,6 +137,7 @@ struct Event {
132137
Mouse,
133138
CursorPosition,
134139
CursorShape,
140+
TerminalID
135141
};
136142
Type type_ = Type::Unknown;
137143

@@ -144,6 +150,7 @@ struct Event {
144150
struct Mouse mouse;
145151
struct Cursor cursor;
146152
int cursor_shape;
153+
enum TerminalID terminal_id;
147154
} data_ = {};
148155

149156
std::string input_;

include/ftxui/component/screen_interactive.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <memory> // for shared_ptr
1111
#include <string> // for string
1212
#include <thread> // for thread
13+
#include <list>
1314

1415
#include "ftxui/component/animation.hpp" // for TimePoint
1516
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
@@ -72,6 +73,13 @@ class ScreenInteractive : public Screen {
7273
void ForceHandleCtrlC(bool force);
7374
void ForceHandleCtrlZ(bool force);
7475

76+
TerminalID TerminalId() const;
77+
78+
typedef std::function<void(TerminalID const& terminal_id)> TerminalIDUpdateCallback;
79+
80+
void OnTerminalIDUpdate(
81+
TerminalIDUpdateCallback const& callback);
82+
7583
// Selection API.
7684
std::string GetSelection();
7785
void SelectionChange(std::function<void()> callback);
@@ -156,6 +164,11 @@ class ScreenInteractive : public Screen {
156164
std::unique_ptr<Selection> selection_;
157165
std::function<void()> selection_on_change_;
158166

167+
TerminalID m_terminal_id;
168+
169+
typedef std::list<TerminalIDUpdateCallback> TerminalIDUpdateCallbackContainer;
170+
TerminalIDUpdateCallbackContainer m_terminal_id_update_callbacks;
171+
159172
friend class Loop;
160173

161174
public:
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2025 Arthur Sonzogni. All rights reserved.
2+
// Use of this source code is governed by the MIT license that can be found in
3+
// the LICENSE file.
4+
5+
#ifndef FTXUI_COMPONENT_TERMINAL_ID_HPP
6+
#define FTXUI_COMPONENT_TERMINAL_ID_HPP
7+
8+
#include <ostream>
9+
#include <string>
10+
11+
namespace ftxui {
12+
13+
std::string const TERMINAL_ID_REQUEST("\x1b[0c");
14+
15+
/// @brief A mouse event. It contains the coordinate of the mouse, the button
16+
/// pressed and the modifier (shift, ctrl, meta).
17+
/// @ingroup component
18+
19+
enum class TerminalID
20+
{
21+
UNKNOWN,
22+
XTERM,
23+
KONSOLE,
24+
URXVT,
25+
VTE,
26+
LINUXVC
27+
};
28+
29+
std::ostream& operator<<(
30+
std::ostream& os,
31+
TerminalID terminal_id);
32+
33+
} // namespace ftxui
34+
35+
#endif /* end of include guard: FTXUI_COMPONENT_TERMINAL_ID_HPP */

src/ftxui/component/event.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ Event Event::CursorPosition(std::string input, int x, int y) {
8787
return event;
8888
}
8989

90+
/// @internal
91+
// static
92+
Event Event::TerminalID(std::string input, enum TerminalID terminal_id) {
93+
Event event;
94+
event.input_ = std::move(input);
95+
event.type_ = Type::TerminalID;
96+
event.data_.terminal_id = terminal_id;
97+
return event;
98+
}
99+
90100
/// @brief Return a string representation of the event.
91101
std::string Event::DebugString() const {
92102
static std::map<Event, const char*> event_to_string = {

src/ftxui/component/loop.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright 2022 Arthur Sonzogni. All rights reserved.
22
// Use of this source code is governed by the MIT license that can be found in
33
// the LICENSE file.
4+
#include <iostream>
45
#include "ftxui/component/loop.hpp"
6+
#include "ftxui/component/terminal_id.hpp"
57

68
#include <utility> // for move
79

@@ -47,6 +49,9 @@ void Loop::RunOnceBlocking() {
4749
/// Execute the loop, blocking the current thread, up until the loop has
4850
/// quitted.
4951
void Loop::Run() {
52+
// Ensure we perform a single terminal id request before we are starting the loop itself.
53+
std::cout << TERMINAL_ID_REQUEST;
54+
5055
while (!HasQuitted()) {
5156
RunOnceBlocking();
5257
}

src/ftxui/component/screen_interactive.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,8 @@ ScreenInteractive::ScreenInteractive(Dimension dimension,
352352
bool use_alternative_screen)
353353
: Screen(dimx, dimy),
354354
dimension_(dimension),
355-
use_alternative_screen_(use_alternative_screen) {
355+
use_alternative_screen_(use_alternative_screen),
356+
m_terminal_id(TerminalID::UNKNOWN) {
356357
task_receiver_ = MakeReceiver<Task>();
357358
}
358359

@@ -799,6 +800,29 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
799800
arg.mouse().y -= cursor_y_;
800801
}
801802

803+
if (arg.is_terminal_id())
804+
{
805+
m_terminal_id =
806+
arg.terminal_id();
807+
808+
for (auto itr = m_terminal_id_update_callbacks.begin(),
809+
end_itr = m_terminal_id_update_callbacks.end();
810+
(itr != end_itr);
811+
++itr)
812+
{
813+
if (*itr)
814+
{
815+
(*itr)(m_terminal_id);
816+
}
817+
else
818+
{
819+
// The callback function is invalid and will be removed
820+
m_terminal_id_update_callbacks.erase(
821+
itr);
822+
}
823+
}
824+
}
825+
802826
arg.screen_ = this;
803827

804828
bool handled = component->OnEvent(arg);
@@ -1084,4 +1108,16 @@ bool ScreenInteractive::SelectionData::operator!=(
10841108
return !(*this == other);
10851109
}
10861110

1111+
TerminalID ScreenInteractive::TerminalId() const
1112+
{
1113+
return m_terminal_id;
1114+
}
1115+
1116+
void ScreenInteractive::OnTerminalIDUpdate(
1117+
TerminalIDUpdateCallback const& callback)
1118+
{
1119+
m_terminal_id_update_callbacks.push_back(
1120+
callback);
1121+
}
1122+
10871123
} // namespace ftxui.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2025 Arthur Sonzogni. All rights reserved.
2+
// Use of this source code is governed by the MIT license that can be found in
3+
// the LICENSE file.
4+
5+
#include "ftxui/component/terminal_id.hpp"
6+
7+
namespace ftxui
8+
{
9+
10+
std::ostream& operator<<(
11+
std::ostream& os,
12+
TerminalID terminal_id)
13+
{
14+
switch(terminal_id)
15+
{
16+
case TerminalID::UNKNOWN:
17+
{
18+
os << "UNKNOWN";
19+
break;
20+
}
21+
case TerminalID::XTERM:
22+
{
23+
os << "XTERM";
24+
break;
25+
}
26+
case TerminalID::KONSOLE:
27+
{
28+
os << "KONSOLE";
29+
break;
30+
}
31+
case TerminalID::URXVT:
32+
{
33+
os << "URXVT";
34+
break;
35+
}
36+
case TerminalID::VTE:
37+
{
38+
os << "VTE";
39+
break;
40+
}
41+
case TerminalID::LINUXVC:
42+
{
43+
os << "LINUXVC";
44+
break;
45+
}
46+
}
47+
48+
return os;
49+
}
50+
51+
} // namespace ftxui

0 commit comments

Comments
 (0)