ttx 0.1.0
Loading...
Searching...
No Matches
pane.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/container/queue/queue.h"
4#include "di/container/string/string_view.h"
5#include "di/container/tree/tree_map.h"
6#include "di/container/vector/vector.h"
7#include "di/function/container/function.h"
8#include "di/sync/atomic.h"
9#include "di/sync/synchronized.h"
10#include "di/vocab/error/result.h"
11#include "di/vocab/pointer/box.h"
12#include "dius/condition_variable.h"
13#include "dius/sync_file.h"
14#include "dius/system/process.h"
15#include "dius/thread.h"
16#include "ttx/direction.h"
17#include "ttx/key_event.h"
18#include "ttx/mouse.h"
20#include "ttx/paste_event.h"
21#include "ttx/renderer.h"
22#include "ttx/size.h"
23#include "ttx/terminal.h"
29
30namespace ttx {
31class Pane;
32
33struct PaneHooks {
35 di::Function<void(Pane&, di::Optional<dius::system::ProcessResult>)> did_exit;
36
38 di::Function<void(Pane&)> did_update;
39
41 di::Function<void(terminal::OSC52, bool)> did_selection;
42
45
47 di::Function<void(di::StringView)> apc_passthrough;
48
50 di::Function<void(di::StringView)> did_finish_output;
51
53 di::Function<void(di::StringView)> did_get_extra_output;
54
56 di::Function<void()> did_update_cwd;
57};
58
60 auto clone() const -> CreatePaneArgs {
61 // NOTE: the hooks aren't cloned.
62 return { command.clone(),
64 replay_path.clone(),
65 save_state_path.clone(),
66 pipe_input.clone(),
67 cwd.clone(),
68 terminfo_dir.clone(),
69 term.clone(),
75 mock,
76 {} };
77 }
78
79 auto with_cwd(di::Optional<di::Path> cwd) const& -> CreatePaneArgs {
80 auto result = clone();
81 result.cwd = di::move(cwd);
82 return result;
83 }
84
85 di::Vector<di::TransparentString> command {};
86 di::Optional<di::Path> capture_command_output_path {};
87 di::Optional<di::Path> replay_path {};
88 di::Optional<di::Path> save_state_path {};
89 di::Optional<di::String> pipe_input {};
90 di::Optional<di::Path> cwd {};
91 di::Optional<di::Path> terminfo_dir {};
92 di::TransparentString term { "xterm-ttx"_ts };
96 bool pipe_output { false };
97 bool pipe_extra_output { false };
98 bool mock { false };
100};
101
102class Pane {
103public:
104 static auto create_from_replay(u64 id, di::Optional<di::Path> cwd, di::PathView replay_path,
105 di::Optional<di::Path> save_state_path, Size const& size, PaneHooks hooks)
106 -> di::Result<di::Box<Pane>>;
107 static auto create(u64 id, CreatePaneArgs args, Size const& size) -> di::Result<di::Box<Pane>>;
108
109 // For testing, create a mock pane. This doesn't actually create a psuedo terminal or a subprocess.
110 static auto create_mock(u64 id = 0, di::Optional<di::Path> cwd = {}) -> di::Box<Pane>;
111
112 explicit Pane(u64 id, di::Optional<di::Path> cwd, dius::SyncFile pty_controller, Size const& size,
113 dius::system::ProcessHandle process, terminal::Palette const& global_palette,
114 terminal::Palette const& local_palette, terminal::ThemeMode theme_mode, PaneHooks hooks)
115 : m_id(id)
116 , m_pty_controller(di::move(pty_controller))
117 , m_terminal(di::in_place, id, size, global_palette, local_palette, theme_mode)
118 , m_process(process)
119 , m_cwd(di::move(cwd))
120 , m_hooks(di::move(hooks)) {}
121 ~Pane();
122
123 auto id() const { return m_id; }
124 auto draw(Renderer& renderer) -> di::Tuple<RenderedCursor, terminal::Color>;
125
126 auto event(KeyEvent const& event) -> bool;
127 auto event(MouseEvent const& event) -> bool;
128 auto event(FocusEvent const& event) -> bool;
129 auto event(PasteEvent const& event) -> bool;
130
136 auto accepts_scrolling() -> bool;
137
138 void invalidate_all();
139 void resize(Size const& size);
140 void scroll(Direction direction, i32 amount_in_cells);
141 void scroll_page_up();
142 void scroll_page_down();
143 void scroll_to_top();
144 void scroll_to_bottom();
145 void scroll_prev_command();
146 void scroll_next_command();
147 void copy_last_command(bool include_command);
148 auto save_state(di::PathView path) -> di::Result<>;
149 void send_clipboard(terminal::SelectionType selection_type, di::Vector<byte> data);
150 void stop_capture();
151 void soft_reset();
152 void exit();
153
154 auto seamless_navigate(terminal::OSC8671&& osc_8671) -> bool;
155
161 auto current_working_directory() -> di::Optional<di::Path>;
162
164 auto window_title() -> di::Optional<di::String>;
165
166 void update_local_palette(di::FunctionRef<void(terminal::Palette&)> update);
167
168 void set_global_palette(terminal::Palette const& palette);
169 void set_theme_mode(terminal::ThemeMode theme_mode);
170
171private:
172 void handle_terminal_event(TerminalEvent&& event);
173 void write_pty_string(di::StringView data);
174 void write_pty_string(di::TransparentStringView data);
175 void update_selection_after_scrolling();
176
177 void update_cwd(terminal::OSC7&& path_with_hostname);
178 void update_window_title(terminal::OSC2&& window_title);
179 void reset_viewport_scroll();
180
181 u64 m_id { 0 };
182 di::Atomic<bool> m_done { false };
183 di::Atomic<bool> m_capture { true };
184 di::Optional<MousePosition> m_last_mouse_position;
185 di::Optional<terminal::AbsolutePosition> m_pending_selection_start;
186 MouseClickTracker m_mouse_click_tracker { 3 };
187 dius::SyncFile m_pty_controller;
188 di::Function<void()> m_restore_termios;
189 di::Synchronized<Terminal> m_terminal;
190 di::Optional<Size> m_desired_visible_size;
191 dius::system::ProcessHandle m_process;
192
193 u32 m_vertical_scroll_offset { 0 };
194 u32 m_horizontal_scroll_offset { 0 };
195
196 di::Synchronized<di::Optional<di::Path>> m_cwd;
197 di::Synchronized<di::Optional<di::String>> m_window_title;
198 PaneHooks m_hooks;
199 di::Synchronized<di::Queue<di::Vector<byte>>> m_output_queue;
200 dius::ConditionVariable m_output_condition;
201
202 // These are declared last, for when dius::Thread calls join() in the destructor.
203 dius::Thread m_process_thread;
204 dius::Thread m_output_thread;
205 dius::Thread m_reader_thread;
206 dius::Thread m_pipe_writer_thread;
207 dius::Thread m_pipe_reader_thread;
208 dius::Thread m_pipe_extra_reader_thread;
209};
210}
Definition focus_event.h:7
Definition key_event.h:24
Definition mouse_event.h:23
Definition pane.h:102
auto accepts_scrolling() -> bool
Query if it is valid to try to scroll the pane.
Definition pane.cpp:913
void resize(Size const &size)
Definition pane.cpp:643
void update_local_palette(di::FunctionRef< void(terminal::Palette &)> update)
Definition pane.cpp:935
void exit()
Definition pane.cpp:901
void soft_reset()
Definition pane.cpp:801
void scroll_page_up()
Definition pane.cpp:721
void send_clipboard(terminal::SelectionType selection_type, di::Vector< byte > data)
Definition pane.cpp:788
Pane(u64 id, di::Optional< di::Path > cwd, dius::SyncFile pty_controller, Size const &size, dius::system::ProcessHandle process, terminal::Palette const &global_palette, terminal::Palette const &local_palette, terminal::ThemeMode theme_mode, PaneHooks hooks)
Definition pane.h:112
void stop_capture()
Definition pane.cpp:797
auto save_state(di::PathView path) -> di::Result<>
Definition pane.cpp:780
void set_global_palette(terminal::Palette const &palette)
Definition pane.cpp:948
static auto create_from_replay(u64 id, di::Optional< di::Path > cwd, di::PathView replay_path, di::Optional< di::Path > save_state_path, Size const &size, PaneHooks hooks) -> di::Result< di::Box< Pane > >
Definition pane.cpp:77
void invalidate_all()
Definition pane.cpp:637
~Pane()
Definition pane.cpp:350
void set_theme_mode(terminal::ThemeMode theme_mode)
Definition pane.cpp:959
static auto create(u64 id, CreatePaneArgs args, Size const &size) -> di::Result< di::Box< Pane > >
Definition pane.cpp:130
auto seamless_navigate(terminal::OSC8671 &&osc_8671) -> bool
Definition pane.cpp:919
static auto create_mock(u64 id=0, di::Optional< di::Path > cwd={}) -> di::Box< Pane >
Definition pane.cpp:343
void scroll_to_top()
Definition pane.cpp:731
auto id() const
Definition pane.h:123
void scroll(Direction direction, i32 amount_in_cells)
Definition pane.cpp:656
void scroll_next_command()
Definition pane.cpp:757
void scroll_page_down()
Definition pane.cpp:726
void scroll_prev_command()
Definition pane.cpp:749
auto window_title() -> di::Optional< di::String >
Get the pane's window title.
Definition pane.cpp:849
void scroll_to_bottom()
Definition pane.cpp:739
auto event(KeyEvent const &event) -> bool
Definition pane.cpp:487
auto draw(Renderer &renderer) -> di::Tuple< RenderedCursor, terminal::Color >
Definition pane.cpp:362
auto current_working_directory() -> di::Optional< di::Path >
Get the pane's current working directory.
Definition pane.cpp:845
void copy_last_command(bool include_command)
Definition pane.cpp:765
Definition paste_event.h:8
Definition renderer.h:28
Definition palette.h:69
SelectionType
Represents the type of selection being modifed by an OSC 52 sequence.
Definition osc_52.h:8
ThemeMode
Theme mode (light or dark).
Definition palette.h:10
@ Dark
Definition palette.h:12
Definition clipboard.h:10
di::Variant< APC, terminal::OSC2, terminal::OSC7, terminal::OSC52, terminal::OSC8671, Size, WritePtyString > TerminalEvent
Definition terminal.h:33
Direction
Definition direction.h:7
Definition pane.h:59
bool pipe_output
Definition pane.h:96
di::Optional< di::Path > cwd
Definition pane.h:90
di::Optional< di::Path > capture_command_output_path
Definition pane.h:86
di::Optional< di::Path > replay_path
Definition pane.h:87
PaneHooks hooks
Definition pane.h:99
di::Vector< di::TransparentString > command
Definition pane.h:85
bool mock
Definition pane.h:98
terminal::ThemeMode theme_mode
Definition pane.h:95
auto with_cwd(di::Optional< di::Path > cwd) const &-> CreatePaneArgs
Definition pane.h:79
di::Optional< di::String > pipe_input
Definition pane.h:89
di::Optional< di::Path > terminfo_dir
Definition pane.h:91
di::TransparentString term
Definition pane.h:92
terminal::Palette local_palette
Definition pane.h:94
di::Optional< di::Path > save_state_path
Definition pane.h:88
bool pipe_extra_output
Create a pipe on fd 3 and read from it.
Definition pane.h:97
terminal::Palette global_palette
Definition pane.h:93
auto clone() const -> CreatePaneArgs
Definition pane.h:60
Definition pane.h:33
di::Function< void(terminal::OSC8671)> did_receive_seamless_navigation
Callback when a seamless navigation message is seen.
Definition pane.h:44
di::Function< void(di::StringView)> did_finish_output
Callback with the results on reading from the output pipe.
Definition pane.h:50
di::Function< void(terminal::OSC52, bool)> did_selection
Application controlled callback when a clipboard set/request is invoked.
Definition pane.h:41
di::Function< void(di::StringView)> did_get_extra_output
Callback when a line of "extra output" is read.
Definition pane.h:53
di::Function< void()> did_update_cwd
Callback when the pane's current working directory changes.
Definition pane.h:56
di::Function< void(Pane &, di::Optional< dius::system::ProcessResult >)> did_exit
Application controlled callback when the internal process exits.
Definition pane.h:35
di::Function< void(di::StringView)> apc_passthrough
Application controlled callback when APC command is set.
Definition pane.h:47
di::Function< void(Pane &)> did_update
controlled callback when the terminal buffer has updated.
Definition pane.h:38
Definition size.h:7
Represents a request to set the current window title.
Definition osc_2.h:11
Represents an OSC 52 sequence, which allows for modifying or querying the clipboard.
Definition osc_52.h:51
Represents a application current working directory report.
Definition osc_7.h:14
Represents a seamless pane navigation request.
Definition osc_8671.h:26