reflex-terminal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.doc/ext/reflex-terminal/native.cpp +19 -0
- data/.doc/ext/reflex-terminal/renderer.cpp +110 -0
- data/.doc/ext/reflex-terminal/terminal.cpp +530 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/.github/workflows/release-gem.yml +60 -0
- data/.github/workflows/tag.yml +35 -0
- data/.github/workflows/test.yml +46 -0
- data/.github/workflows/utils.rb +127 -0
- data/CONTRIBUTING.md +7 -0
- data/ChangeLog.md +6 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +100 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/examples/terminal.rb +101 -0
- data/ext/reflex-terminal/defs.h +17 -0
- data/ext/reflex-terminal/extconf.rb +29 -0
- data/ext/reflex-terminal/native.cpp +19 -0
- data/ext/reflex-terminal/renderer.cpp +118 -0
- data/ext/reflex-terminal/terminal.cpp +572 -0
- data/include/reflex/terminal.h +233 -0
- data/include/reflex-terminal/defs.h +36 -0
- data/include/reflex-terminal/renderer.h +57 -0
- data/include/reflex-terminal/ruby/renderer.h +41 -0
- data/include/reflex-terminal/ruby/terminal.h +43 -0
- data/include/reflex-terminal/ruby.h +11 -0
- data/include/reflex-terminal.h +13 -0
- data/lib/reflex/bell_event.rb +15 -0
- data/lib/reflex/terminal.rb +168 -0
- data/lib/reflex/terminal_view.rb +268 -0
- data/lib/reflex-terminal/ext.rb +2 -0
- data/lib/reflex-terminal/extension.rb +41 -0
- data/lib/reflex-terminal.rb +7 -0
- data/reflex-terminal.gemspec +39 -0
- data/src/pty.cpp +236 -0
- data/src/renderer.cpp +365 -0
- data/src/terminal.cpp +1547 -0
- data/src/terminal.h +66 -0
- data/src/win32/pty.cpp +387 -0
- data/test/helper.rb +11 -0
- data/test/test_renderer.rb +113 -0
- data/test/test_terminal.rb +683 -0
- data/test/test_terminal_view.rb +182 -0
- metadata +152 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d7279668d5fe73e778c224a568ae79b829c138117f4d1458d73278451847a7f5
|
|
4
|
+
data.tar.gz: 157ebc265844d375f75b258f87890ce561e93a5c2225b64800e6063f02d53d1e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f3ebfbc2b62e3b3d2d2194d9c278518a2bb2966b34e6f6e8a8bf48ae44f862a520e75742746107db912847989bf09355c805c4799836c73f87739d0f19c99471
|
|
7
|
+
data.tar.gz: a402b3b23959dc21c314a2d39ddda704363f0740a9603ed1ee5cfeb8e590ae6ce77ec9c44cf4edc4e0f7033d4ab428cb67a3b5fef3f1719f20edc2348b5757b7
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#include "defs.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
void Init_reflex_terminal ();
|
|
5
|
+
void Init_reflex_terminal_renderer ();
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
extern "C" void
|
|
9
|
+
Init_reflex_terminal_ext ()
|
|
10
|
+
{
|
|
11
|
+
RUCY_TRY
|
|
12
|
+
|
|
13
|
+
Rucy::init();
|
|
14
|
+
|
|
15
|
+
Init_reflex_terminal();
|
|
16
|
+
Init_reflex_terminal_renderer();
|
|
17
|
+
|
|
18
|
+
RUCY_CATCH
|
|
19
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#include "reflex-terminal/ruby/renderer.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <rays/ruby/bounds.h>
|
|
5
|
+
#include <rays/ruby/font.h>
|
|
6
|
+
#include <rays/ruby/painter.h>
|
|
7
|
+
#include <reflex-terminal/ruby/terminal.h>
|
|
8
|
+
#include "defs.h"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
RUCY_DEFINE_VALUE_FROM_TO(REFLEX_TERMINAL_EXPORT, ReflexTerminal::Renderer)
|
|
12
|
+
|
|
13
|
+
#define THIS to<ReflexTerminal::Renderer*>(self)
|
|
14
|
+
|
|
15
|
+
#define CHECK RUCY_CHECK_OBJ(ReflexTerminal::Renderer, self)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
static
|
|
19
|
+
VALUE alloc(VALUE klass)
|
|
20
|
+
{
|
|
21
|
+
return new_type<ReflexTerminal::Renderer>(klass);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static
|
|
25
|
+
VALUE set_font(VALUE self, VALUE font)
|
|
26
|
+
{
|
|
27
|
+
CHECK;
|
|
28
|
+
THIS->set_font(to<Rays::Font&>(font));
|
|
29
|
+
return font;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static
|
|
33
|
+
VALUE get_font(VALUE self)
|
|
34
|
+
{
|
|
35
|
+
CHECK;
|
|
36
|
+
return value(THIS->font());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static
|
|
40
|
+
VALUE get_cell_width(VALUE self)
|
|
41
|
+
{
|
|
42
|
+
CHECK;
|
|
43
|
+
return value(THIS->cell_width());
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static
|
|
47
|
+
VALUE get_cell_height(VALUE self)
|
|
48
|
+
{
|
|
49
|
+
CHECK;
|
|
50
|
+
return value(THIS->cell_height());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static
|
|
54
|
+
VALUE bake_glyphs(VALUE self, VALUE terminal)
|
|
55
|
+
{
|
|
56
|
+
CHECK;
|
|
57
|
+
THIS->bake_glyphs(to<Reflex::Terminal&>(terminal));
|
|
58
|
+
return self;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static
|
|
62
|
+
VALUE get_glyph_count(VALUE self)
|
|
63
|
+
{
|
|
64
|
+
CHECK;
|
|
65
|
+
return value(THIS->glyph_count());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static
|
|
69
|
+
VALUE draw(VALUE self, VALUE painter, VALUE terminal, VALUE bounds)
|
|
70
|
+
{
|
|
71
|
+
CHECK;
|
|
72
|
+
THIS->draw(
|
|
73
|
+
to<Rays::Painter*>(painter),
|
|
74
|
+
to<Reflex::Terminal&>(terminal),
|
|
75
|
+
to<Rays::Bounds>(bounds));
|
|
76
|
+
return self;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
static Class cRenderer;
|
|
81
|
+
|
|
82
|
+
void
|
|
83
|
+
Init_reflex_terminal_renderer ()
|
|
84
|
+
{
|
|
85
|
+
Module mReflexTerminal = rb_define_module("ReflexTerminal");
|
|
86
|
+
|
|
87
|
+
cRenderer = rb_define_class_under(mReflexTerminal, "Renderer", rb_cObject);
|
|
88
|
+
rb_define_alloc_func(cRenderer, alloc);
|
|
89
|
+
rb_define_method(cRenderer, "font=", RUBY_METHOD_FUNC(set_font), 1);
|
|
90
|
+
rb_define_method(cRenderer, "font", RUBY_METHOD_FUNC(get_font), 0);
|
|
91
|
+
rb_define_method(cRenderer, "cell_width", RUBY_METHOD_FUNC(get_cell_width), 0);
|
|
92
|
+
rb_define_method(cRenderer, "cell_height", RUBY_METHOD_FUNC(get_cell_height), 0);
|
|
93
|
+
rb_define_method(cRenderer, "bake_glyphs", RUBY_METHOD_FUNC(bake_glyphs), 1);
|
|
94
|
+
rb_define_method(cRenderer, "glyph_count", RUBY_METHOD_FUNC(get_glyph_count), 0);
|
|
95
|
+
rb_define_method(cRenderer, "draw", RUBY_METHOD_FUNC(draw), 3);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
namespace ReflexTerminal
|
|
100
|
+
{
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
Class
|
|
104
|
+
renderer_class ()
|
|
105
|
+
{
|
|
106
|
+
return cRenderer;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
}// ReflexTerminal
|
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
#include "reflex-terminal/ruby/terminal.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <xot/exception.h>
|
|
5
|
+
#include <rays/ruby/color.h>
|
|
6
|
+
#include <reflex/ruby/event.h>
|
|
7
|
+
#include "defs.h"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
RUCY_DEFINE_VALUE_FROM_TO(REFLEX_TERMINAL_EXPORT, Reflex::Terminal)
|
|
11
|
+
|
|
12
|
+
RUCY_DEFINE_CONVERT_TO(REFLEX_TERMINAL_EXPORT, Reflex::Terminal::OptionAsAlt)
|
|
13
|
+
|
|
14
|
+
#define THIS to<Reflex::Terminal*>(self)
|
|
15
|
+
|
|
16
|
+
#define CHECK RUCY_CHECK_OBJECT(Reflex::Terminal, self)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
static
|
|
20
|
+
VALUE alloc(VALUE klass)
|
|
21
|
+
{
|
|
22
|
+
return new_type<Reflex::Terminal>(klass);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static
|
|
26
|
+
VALUE initialize(VALUE self, VALUE columns, VALUE rows, VALUE scrollback)
|
|
27
|
+
{
|
|
28
|
+
RUCY_CHECK_OBJ(Reflex::Terminal, self);
|
|
29
|
+
|
|
30
|
+
*THIS = Reflex::Terminal(to<int>(columns), to<int>(rows), to<size_t>(scrollback));
|
|
31
|
+
return self;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static
|
|
35
|
+
VALUE initialize_copy(VALUE self, VALUE obj)
|
|
36
|
+
{
|
|
37
|
+
Xot::invalid_state_error(__FILE__, __LINE__, "can not duplicate Terminal");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static
|
|
41
|
+
VALUE update(VALUE self)
|
|
42
|
+
{
|
|
43
|
+
CHECK;
|
|
44
|
+
return value(THIS->update());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static
|
|
48
|
+
VALUE reset(VALUE self)
|
|
49
|
+
{
|
|
50
|
+
CHECK;
|
|
51
|
+
THIS->reset();
|
|
52
|
+
return self;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static
|
|
56
|
+
VALUE resize(VALUE self, VALUE columns, VALUE rows, VALUE cell_width, VALUE cell_height, VALUE screen_width, VALUE screen_height)
|
|
57
|
+
{
|
|
58
|
+
CHECK;
|
|
59
|
+
THIS->resize(
|
|
60
|
+
to<int>(columns), to<int>(rows),
|
|
61
|
+
to<int>(cell_width), to<int>(cell_height),
|
|
62
|
+
to<int>(screen_width), to<int>(screen_height));
|
|
63
|
+
return self;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static
|
|
67
|
+
VALUE feed(VALUE self, VALUE bytes)
|
|
68
|
+
{
|
|
69
|
+
CHECK;
|
|
70
|
+
if (!bytes.is_s())
|
|
71
|
+
Rucy::type_error(__FILE__, __LINE__, "bytes must be a String");
|
|
72
|
+
|
|
73
|
+
// feed() takes a raw byte stream, so avoid to<const char*>/c_str()
|
|
74
|
+
// (StringValueCStr rejects NUL bytes) and Value#size (character
|
|
75
|
+
// count, not the byte length)
|
|
76
|
+
RubyValue str = bytes.value();
|
|
77
|
+
THIS->feed(RSTRING_PTR(str), RSTRING_LEN(str));
|
|
78
|
+
return self;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static
|
|
82
|
+
VALUE read_pending_input(VALUE self)
|
|
83
|
+
{
|
|
84
|
+
CHECK;
|
|
85
|
+
// a raw byte stream for the child process
|
|
86
|
+
Reflex::String input = THIS->read_pending_input();
|
|
87
|
+
return value(input.data(), input.size(), rb_ascii8bit_encoding());
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static
|
|
91
|
+
VALUE spawn(VALUE self, VALUE args, VALUE envs)
|
|
92
|
+
{
|
|
93
|
+
CHECK;
|
|
94
|
+
|
|
95
|
+
Reflex::StringList list;
|
|
96
|
+
for (size_t i = 0, size = args.size(); i < size; ++i)
|
|
97
|
+
list.emplace_back(args[i].c_str());
|
|
98
|
+
|
|
99
|
+
Reflex::Terminal::EnvMap map;
|
|
100
|
+
Value names = envs.call("keys");
|
|
101
|
+
for (size_t i = 0, size = names.size(); i < size; ++i)
|
|
102
|
+
{
|
|
103
|
+
Value name = names[i];
|
|
104
|
+
Value value = envs.get(name);
|
|
105
|
+
if (value)
|
|
106
|
+
map[name.c_str()] = value.c_str();
|
|
107
|
+
else
|
|
108
|
+
map[name.c_str()] = std::nullopt;// nil removes the variable
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
THIS->spawn(list, map);
|
|
112
|
+
return self;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static
|
|
116
|
+
VALUE close(VALUE self)
|
|
117
|
+
{
|
|
118
|
+
CHECK;
|
|
119
|
+
THIS->close();
|
|
120
|
+
return self;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static
|
|
124
|
+
VALUE write(VALUE self, VALUE bytes)
|
|
125
|
+
{
|
|
126
|
+
CHECK;
|
|
127
|
+
if (!bytes.is_s())
|
|
128
|
+
Rucy::type_error(__FILE__, __LINE__, "bytes must be a String");
|
|
129
|
+
|
|
130
|
+
// write() takes a raw byte stream (see feed)
|
|
131
|
+
RubyValue str = bytes.value();
|
|
132
|
+
THIS->write(RSTRING_PTR(str), RSTRING_LEN(str));
|
|
133
|
+
return self;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static
|
|
137
|
+
VALUE write_key(VALUE self, VALUE event)
|
|
138
|
+
{
|
|
139
|
+
CHECK;
|
|
140
|
+
THIS->write_key(to<Reflex::KeyEvent&>(event));
|
|
141
|
+
return self;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static
|
|
145
|
+
VALUE write_pointer(VALUE self, VALUE event)
|
|
146
|
+
{
|
|
147
|
+
CHECK;
|
|
148
|
+
THIS->write_pointer(to<Reflex::PointerEvent&>(event));
|
|
149
|
+
return self;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static
|
|
153
|
+
VALUE write_wheel(VALUE self, VALUE event)
|
|
154
|
+
{
|
|
155
|
+
CHECK;
|
|
156
|
+
THIS->write_wheel(to<Reflex::WheelEvent&>(event));
|
|
157
|
+
return self;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static
|
|
161
|
+
VALUE paste(VALUE self, VALUE text)
|
|
162
|
+
{
|
|
163
|
+
CHECK;
|
|
164
|
+
if (!text.is_s())
|
|
165
|
+
Rucy::type_error(__FILE__, __LINE__, "text must be a String");
|
|
166
|
+
|
|
167
|
+
RubyValue str = text.value();
|
|
168
|
+
THIS->paste(RSTRING_PTR(str), RSTRING_LEN(str));
|
|
169
|
+
return self;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static
|
|
173
|
+
VALUE is_alive(VALUE self)
|
|
174
|
+
{
|
|
175
|
+
CHECK;
|
|
176
|
+
return value(THIS->is_alive());
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static
|
|
180
|
+
VALUE is_mouse_tracking(VALUE self)
|
|
181
|
+
{
|
|
182
|
+
CHECK;
|
|
183
|
+
return value(THIS->is_mouse_tracking());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static
|
|
187
|
+
VALUE select(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
|
|
188
|
+
{
|
|
189
|
+
CHECK;
|
|
190
|
+
THIS->select(to<int>(x1), to<int>(y1), to<int>(x2), to<int>(y2));
|
|
191
|
+
return self;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static
|
|
195
|
+
VALUE select_rect(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
|
|
196
|
+
{
|
|
197
|
+
CHECK;
|
|
198
|
+
THIS->select_rect(to<int>(x1), to<int>(y1), to<int>(x2), to<int>(y2));
|
|
199
|
+
return self;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static
|
|
203
|
+
VALUE select_word(VALUE self, VALUE x, VALUE y)
|
|
204
|
+
{
|
|
205
|
+
CHECK;
|
|
206
|
+
THIS->select_word(to<int>(x), to<int>(y));
|
|
207
|
+
return self;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
static
|
|
211
|
+
VALUE select_line(VALUE self, VALUE y)
|
|
212
|
+
{
|
|
213
|
+
CHECK;
|
|
214
|
+
THIS->select_line(to<int>(y));
|
|
215
|
+
return self;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static
|
|
219
|
+
VALUE deselect(VALUE self)
|
|
220
|
+
{
|
|
221
|
+
CHECK;
|
|
222
|
+
THIS->deselect();
|
|
223
|
+
return self;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
static
|
|
227
|
+
VALUE has_selection(VALUE self)
|
|
228
|
+
{
|
|
229
|
+
CHECK;
|
|
230
|
+
return value(THIS->has_selection());
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static
|
|
234
|
+
VALUE get_selected_text(VALUE self)
|
|
235
|
+
{
|
|
236
|
+
CHECK;
|
|
237
|
+
Reflex::String text = THIS->selected_text();
|
|
238
|
+
return value(text.c_str(), text.size(), rb_utf8_encoding());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static
|
|
242
|
+
VALUE scroll_to(VALUE self, VALUE row)
|
|
243
|
+
{
|
|
244
|
+
CHECK;
|
|
245
|
+
THIS->scroll_to(to<int>(row));
|
|
246
|
+
return self;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
static
|
|
250
|
+
VALUE scroll_by(VALUE self, VALUE rows)
|
|
251
|
+
{
|
|
252
|
+
CHECK;
|
|
253
|
+
THIS->scroll_by(to<int>(rows));
|
|
254
|
+
return self;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static
|
|
258
|
+
VALUE get_scroll(VALUE self)
|
|
259
|
+
{
|
|
260
|
+
CHECK;
|
|
261
|
+
return value(THIS->scroll());
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
static
|
|
265
|
+
VALUE each_line(VALUE self)
|
|
266
|
+
{
|
|
267
|
+
CHECK;
|
|
268
|
+
|
|
269
|
+
for (const auto& line : THIS->lines())
|
|
270
|
+
yield(value(line.c_str(), line.size(), rb_utf8_encoding()));
|
|
271
|
+
return self;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static
|
|
275
|
+
VALUE each_span(VALUE self)
|
|
276
|
+
{
|
|
277
|
+
CHECK;
|
|
278
|
+
|
|
279
|
+
const auto& rows = THIS->spans();
|
|
280
|
+
for (size_t y = 0; y < rows.size(); ++y)
|
|
281
|
+
{
|
|
282
|
+
for (const auto& span : rows[y])
|
|
283
|
+
{
|
|
284
|
+
yield(
|
|
285
|
+
value(span.x), value((int) y), value(span.width),
|
|
286
|
+
value(span.text.c_str(), span.text.size(), rb_utf8_encoding()),
|
|
287
|
+
span.fg == Reflex::Terminal::Span::COLOR_NONE ? nil() : value(span.fg),
|
|
288
|
+
span.bg == Reflex::Terminal::Span::COLOR_NONE ? nil() : value(span.bg),
|
|
289
|
+
value(span.attribs));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return self;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static
|
|
296
|
+
VALUE set_option_as_alt(VALUE self, VALUE state)
|
|
297
|
+
{
|
|
298
|
+
CHECK;
|
|
299
|
+
THIS->set_option_as_alt(to<Reflex::Terminal::OptionAsAlt>(state));
|
|
300
|
+
return state;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
static
|
|
304
|
+
VALUE get_option_as_alt(VALUE self)
|
|
305
|
+
{
|
|
306
|
+
CHECK;
|
|
307
|
+
return value((int) THIS->option_as_alt());
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
static
|
|
311
|
+
VALUE get_columns(VALUE self)
|
|
312
|
+
{
|
|
313
|
+
CHECK;
|
|
314
|
+
return value(THIS->columns());
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
static
|
|
318
|
+
VALUE get_rows(VALUE self)
|
|
319
|
+
{
|
|
320
|
+
CHECK;
|
|
321
|
+
return value(THIS->rows());
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
static
|
|
325
|
+
VALUE get_cursor(VALUE self)
|
|
326
|
+
{
|
|
327
|
+
CHECK;
|
|
328
|
+
|
|
329
|
+
Reflex::Terminal::Cursor cursor = THIS->cursor();
|
|
330
|
+
Value values[] = {
|
|
331
|
+
value(cursor.x),
|
|
332
|
+
value(cursor.y),
|
|
333
|
+
value((int) cursor.style),
|
|
334
|
+
value(cursor.visible)
|
|
335
|
+
};
|
|
336
|
+
return array(values, 4);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
static Reflex::Terminal::ColorIndex
|
|
340
|
+
to_color_index (Value index)
|
|
341
|
+
{
|
|
342
|
+
int i = to<int>(index);
|
|
343
|
+
if (i < Reflex::Terminal::COLOR_FOREGROUND || Reflex::Terminal::COLOR_PALETTE_LAST < i)
|
|
344
|
+
Rucy::argument_error(__FILE__, __LINE__, "invalid color index: %d", i);
|
|
345
|
+
|
|
346
|
+
return (Reflex::Terminal::ColorIndex) i;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static
|
|
350
|
+
VALUE set_default_color(VALUE self, VALUE index, VALUE color)
|
|
351
|
+
{
|
|
352
|
+
CHECK;
|
|
353
|
+
THIS->set_default_color(to_color_index(index), to<Rays::Color>(color));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
static
|
|
357
|
+
VALUE clear_default_color(VALUE self, VALUE index)
|
|
358
|
+
{
|
|
359
|
+
CHECK;
|
|
360
|
+
THIS->clear_default_color(to_color_index(index));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
static
|
|
364
|
+
VALUE get_default_color(VALUE self, VALUE index)
|
|
365
|
+
{
|
|
366
|
+
CHECK;
|
|
367
|
+
|
|
368
|
+
Rays::Color color;
|
|
369
|
+
if (THIS->get_default_color(to_color_index(index), &color))
|
|
370
|
+
return value(color);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
static
|
|
374
|
+
VALUE get_color(VALUE self, VALUE index)
|
|
375
|
+
{
|
|
376
|
+
CHECK;
|
|
377
|
+
|
|
378
|
+
Rays::Color color;
|
|
379
|
+
if (THIS->get_color(to_color_index(index), &color))
|
|
380
|
+
return value(color);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
static
|
|
384
|
+
VALUE get_title(VALUE self)
|
|
385
|
+
{
|
|
386
|
+
CHECK;
|
|
387
|
+
return value(THIS->title(), rb_utf8_encoding());
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
static
|
|
391
|
+
VALUE get_history_rows(VALUE self)
|
|
392
|
+
{
|
|
393
|
+
CHECK;
|
|
394
|
+
return value(THIS->history_rows());
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
static
|
|
398
|
+
VALUE get_history_lines(VALUE self, VALUE offset, VALUE size)
|
|
399
|
+
{
|
|
400
|
+
CHECK;
|
|
401
|
+
|
|
402
|
+
Value result = array(NULL, 0);// a std::vector<Value> would be invisible to the gc
|
|
403
|
+
for (const auto& line : THIS->get_history_lines(to<int>(offset), to<int>(size)))
|
|
404
|
+
result.push(value(line.c_str(), line.size(), rb_utf8_encoding()));
|
|
405
|
+
return result;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
static
|
|
409
|
+
VALUE get_bells(VALUE self)
|
|
410
|
+
{
|
|
411
|
+
CHECK;
|
|
412
|
+
return value(THIS->bells());
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
static Class cTerminal;
|
|
417
|
+
|
|
418
|
+
void
|
|
419
|
+
Init_reflex_terminal ()
|
|
420
|
+
{
|
|
421
|
+
Module mReflex = rb_define_module("Reflex");
|
|
422
|
+
|
|
423
|
+
cTerminal = rb_define_class_under(mReflex, "Terminal", rb_cObject);
|
|
424
|
+
rb_define_alloc_func(cTerminal, alloc);
|
|
425
|
+
cTerminal.define_private_method("initialize!", initialize);
|
|
426
|
+
rb_define_private_method(cTerminal, "initialize_copy", RUBY_METHOD_FUNC(initialize_copy), 1);
|
|
427
|
+
rb_define_method(cTerminal, "update", RUBY_METHOD_FUNC(update), 0);
|
|
428
|
+
rb_define_method(cTerminal, "reset", RUBY_METHOD_FUNC(reset), 0);
|
|
429
|
+
cTerminal.define_method("resize!", resize);
|
|
430
|
+
rb_define_method(cTerminal, "feed", RUBY_METHOD_FUNC(feed), 1);
|
|
431
|
+
rb_define_method(cTerminal, "read_pending_input", RUBY_METHOD_FUNC(read_pending_input), 0);
|
|
432
|
+
cTerminal.define_method("spawn!", spawn);
|
|
433
|
+
rb_define_method(cTerminal, "close", RUBY_METHOD_FUNC(close), 0);
|
|
434
|
+
rb_define_method(cTerminal, "write", RUBY_METHOD_FUNC(write), 1);
|
|
435
|
+
rb_define_method(cTerminal, "write_key", RUBY_METHOD_FUNC(write_key), 1);
|
|
436
|
+
rb_define_method(cTerminal, "write_pointer", RUBY_METHOD_FUNC(write_pointer), 1);
|
|
437
|
+
rb_define_method(cTerminal, "write_wheel", RUBY_METHOD_FUNC(write_wheel), 1);
|
|
438
|
+
rb_define_method(cTerminal, "paste", RUBY_METHOD_FUNC(paste), 1);
|
|
439
|
+
cTerminal.define_method("alive?", is_alive);
|
|
440
|
+
cTerminal.define_method("mouse_tracking?", is_mouse_tracking);
|
|
441
|
+
rb_define_method(cTerminal, "select", RUBY_METHOD_FUNC(select), 4);
|
|
442
|
+
rb_define_method(cTerminal, "select_rect", RUBY_METHOD_FUNC(select_rect), 4);
|
|
443
|
+
rb_define_method(cTerminal, "select_word", RUBY_METHOD_FUNC(select_word), 2);
|
|
444
|
+
rb_define_method(cTerminal, "select_line", RUBY_METHOD_FUNC(select_line), 1);
|
|
445
|
+
rb_define_method(cTerminal, "deselect", RUBY_METHOD_FUNC(deselect), 0);
|
|
446
|
+
cTerminal.define_method( "selection?", has_selection);
|
|
447
|
+
rb_define_method(cTerminal, "selected_text", RUBY_METHOD_FUNC(get_selected_text), 0);
|
|
448
|
+
rb_define_method(cTerminal, "scroll_to", RUBY_METHOD_FUNC(scroll_to), 1);
|
|
449
|
+
rb_define_method(cTerminal, "scroll_by", RUBY_METHOD_FUNC(scroll_by), 1);
|
|
450
|
+
rb_define_method(cTerminal, "scroll", RUBY_METHOD_FUNC(get_scroll), 0);
|
|
451
|
+
cTerminal.define_private_method("each_line!", each_line);
|
|
452
|
+
cTerminal.define_private_method("each_span!", each_span);
|
|
453
|
+
rb_define_method(cTerminal, "option_as_alt=", RUBY_METHOD_FUNC(set_option_as_alt), 1);
|
|
454
|
+
rb_define_method(cTerminal, "option_as_alt", RUBY_METHOD_FUNC(get_option_as_alt), 0);
|
|
455
|
+
rb_define_method(cTerminal, "columns", RUBY_METHOD_FUNC(get_columns), 0);
|
|
456
|
+
rb_define_method(cTerminal, "rows", RUBY_METHOD_FUNC(get_rows), 0);
|
|
457
|
+
rb_define_method(cTerminal, "cursor", RUBY_METHOD_FUNC(get_cursor), 0);
|
|
458
|
+
cTerminal.define_private_method( "set_default_color!", set_default_color);
|
|
459
|
+
cTerminal.define_private_method("clear_default_color!", clear_default_color);
|
|
460
|
+
cTerminal.define_private_method( "get_default_color!", get_default_color);
|
|
461
|
+
cTerminal.define_private_method( "get_color!", get_color);
|
|
462
|
+
rb_define_method(cTerminal, "title", RUBY_METHOD_FUNC(get_title), 0);
|
|
463
|
+
rb_define_method(cTerminal, "history_rows", RUBY_METHOD_FUNC(get_history_rows), 0);
|
|
464
|
+
cTerminal.define_private_method("get_history_lines!", get_history_lines);
|
|
465
|
+
rb_define_method(cTerminal, "bells", RUBY_METHOD_FUNC(get_bells), 0);
|
|
466
|
+
|
|
467
|
+
cTerminal.define_const("BOLD", Reflex::Terminal::Span::BOLD);
|
|
468
|
+
cTerminal.define_const("ITALIC", Reflex::Terminal::Span::ITALIC);
|
|
469
|
+
cTerminal.define_const("FAINT", Reflex::Terminal::Span::FAINT);
|
|
470
|
+
cTerminal.define_const("BLINK", Reflex::Terminal::Span::BLINK);
|
|
471
|
+
cTerminal.define_const("INVISIBLE", Reflex::Terminal::Span::INVISIBLE);
|
|
472
|
+
cTerminal.define_const("STRIKETHROUGH", Reflex::Terminal::Span::STRIKETHROUGH);
|
|
473
|
+
cTerminal.define_const("OVERLINE", Reflex::Terminal::Span::OVERLINE);
|
|
474
|
+
cTerminal.define_const("INVERSE", Reflex::Terminal::Span::INVERSE);
|
|
475
|
+
cTerminal.define_const("SELECTED", Reflex::Terminal::Span::SELECTED);
|
|
476
|
+
cTerminal.define_const("UNDERLINE_SHIFT", Reflex::Terminal::Span::UNDERLINE_SHIFT);
|
|
477
|
+
cTerminal.define_const("UNDERLINE_MASK", Reflex::Terminal::Span::UNDERLINE_MASK);
|
|
478
|
+
|
|
479
|
+
cTerminal.define_const("CURSOR_BAR", Reflex::Terminal::Cursor::BAR);
|
|
480
|
+
cTerminal.define_const("CURSOR_BLOCK", Reflex::Terminal::Cursor::BLOCK);
|
|
481
|
+
cTerminal.define_const("CURSOR_UNDERLINE", Reflex::Terminal::Cursor::UNDERLINE);
|
|
482
|
+
cTerminal.define_const("CURSOR_BLOCK_HOLLOW", Reflex::Terminal::Cursor::BLOCK_HOLLOW);
|
|
483
|
+
|
|
484
|
+
cTerminal.define_const("COLOR_FOREGROUND", Reflex::Terminal::COLOR_FOREGROUND);
|
|
485
|
+
cTerminal.define_const("COLOR_BACKGROUND", Reflex::Terminal::COLOR_BACKGROUND);
|
|
486
|
+
cTerminal.define_const("COLOR_CURSOR", Reflex::Terminal::COLOR_CURSOR);
|
|
487
|
+
cTerminal.define_const("COLOR_PALETTE_FIRST", Reflex::Terminal::COLOR_PALETTE_FIRST);
|
|
488
|
+
cTerminal.define_const("COLOR_PALETTE_LAST", Reflex::Terminal::COLOR_PALETTE_LAST);
|
|
489
|
+
|
|
490
|
+
cTerminal.define_const("OPTION_AS_ALT_OFF", Reflex::Terminal::OPTION_AS_ALT_OFF);
|
|
491
|
+
cTerminal.define_const("OPTION_AS_ALT_ON", Reflex::Terminal::OPTION_AS_ALT_ON);
|
|
492
|
+
cTerminal.define_const("OPTION_AS_ALT_LEFT", Reflex::Terminal::OPTION_AS_ALT_LEFT);
|
|
493
|
+
cTerminal.define_const("OPTION_AS_ALT_RIGHT", Reflex::Terminal::OPTION_AS_ALT_RIGHT);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
namespace Rucy
|
|
498
|
+
{
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
template <> REFLEX_TERMINAL_EXPORT Reflex::Terminal::OptionAsAlt
|
|
502
|
+
value_to<Reflex::Terminal::OptionAsAlt> (
|
|
503
|
+
int argc, const Value* argv, bool convert)
|
|
504
|
+
{
|
|
505
|
+
if (argc <= 0 || !argv)
|
|
506
|
+
argument_error(__FILE__, __LINE__);
|
|
507
|
+
|
|
508
|
+
int state = value_to<int>(*argv, convert);
|
|
509
|
+
if (state < 0 || Reflex::Terminal::OPTION_AS_ALT_MAX <= state)
|
|
510
|
+
argument_error(__FILE__, __LINE__, "invalid option_as_alt state");
|
|
511
|
+
|
|
512
|
+
return (Reflex::Terminal::OptionAsAlt) state;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
}// Rucy
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
namespace Reflex
|
|
520
|
+
{
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
Class
|
|
524
|
+
terminal_class ()
|
|
525
|
+
{
|
|
526
|
+
return cTerminal;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
}// Reflex
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Pull Requests Not Accepted 🚫
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
However, this repository does not accept pull requests directly.
|
|
5
|
+
|
|
6
|
+
### Where to Contribute?
|
|
7
|
+
|
|
8
|
+
Please submit your changes to the [xord/all](https://github.com/xord/all) monorepo, which serves as the primary repository for all our main libraries.
|
|
9
|
+
|
|
10
|
+
For more details, please refer to our [contribution guidelines](../CONTRIBUTING.md).
|
|
11
|
+
|
|
12
|
+
Thanks for your understanding! 🙌
|