Skip to content

Commit 4e6dfb8

Browse files
committed
Implement Tty (#5)
1 parent 62add5e commit 4e6dfb8

File tree

5 files changed

+149
-37
lines changed

5 files changed

+149
-37
lines changed

api/uv.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,53 @@ Used to receive handles over IPC pipes.
421421
First - call `pipe.pendingCount()`, if it’s > 0 then initialize a handle of
422422
the given type, returned by `pipe.pendingType()` and call `pipe.accept(handle)`.
423423

424-
## `uv_tty_t`
424+
## `uv_tty_t` - Tty handle
425425

426-
*TODO: document this module*
426+
TTY handles represent a stream for the console.
427+
428+
### `new uv.Tty(fd, readable) → tty`
429+
430+
Initialize a new TTY stream with the given file descriptor. Usually the file
431+
descriptor will be:
432+
433+
- 0 = stdin
434+
- 1 = stdout
435+
- 2 = stderr
436+
437+
*readable*, specifies if you plan on calling `tty.readStart()` with this stream.
438+
stdin is readable, stdout is not.
439+
440+
On Unix this function will determine the path of the fd of the terminal using
441+
ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY.
442+
This lets libuv put the tty in non-blocking mode without affecting other
443+
processes that share the tty.
444+
445+
This function is not thread safe on systems that don’t support ioctl TIOCGPTN or
446+
TIOCPTYGNAME, for instance OpenBSD and Solaris.
447+
448+
*Note: If reopening the TTY fails, libuv falls back to blocking writes for
449+
non-readable TTY streams.*
450+
451+
### `tty.setMode(mode)`
452+
453+
Set the TTY using the specified terminal mode.
454+
455+
- 0 = UV_TTY_MODE_NORMAL - Initial/normal terminal mode
456+
- 1 = UV_TTY_MODE_RAW - Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also
457+
enabled)
458+
- 2 = UV_TTY_MODE_IO - Binary-safe I/O mode for IPC (Unix-only)
459+
460+
### `uv.ttyResetMode()`
461+
462+
To be called when the program exits. Resets TTY settings to default values for
463+
the next process to take over.
464+
465+
This function is async signal-safe on Unix platforms but can fail with error
466+
code UV_EBUSY if you call it when execution is inside `tty.setMode()`
467+
468+
### `tty.getWinsize() → [width, height]`
469+
470+
Gets the current Window size.
427471

428472
## `uv_udp_t`
429473

app/test-uv.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ p(Object.getPrototypeOf(streamProto));
3737
print("\nPipe.prototype");
3838
p(uv.Pipe.prototype);
3939
print("Stream.prototype (via Pipe.prototype)");
40-
var streamProto = Object.getPrototypeOf(uv.Pipe.prototype);
41-
p(streamProto);
40+
p(Object.getPrototypeOf(uv.Pipe.prototype));
41+
42+
print("\nTty.prototype");
43+
p(uv.Tty.prototype);
44+
print("Stream.prototype (via Tty.prototype)");
45+
p(Object.getPrototypeOf(uv.Tty.prototype));
4246

4347
var prepare = new uv.Prepare();
4448
prepare.start(function () {
@@ -171,11 +175,6 @@ client.connect("127.0.0.1", 8080, function (err) {
171175
});
172176
uv.run();
173177

174-
prepare.close();
175-
check.close();
176-
idle.close();
177-
uv.run();
178-
179178

180179
// Use uv.Async to implement nextTick
181180
var ticks = [];
@@ -196,11 +195,36 @@ function nextTick(callback) {
196195
ticker.send();
197196
}
198197

199-
200198
print("before");
201199
nextTick(function () {
202200
print("tick");
203201
});
204202
print("after");
205203
uv.run();
204+
205+
206+
print("Testing stdio with default mode");
207+
var stdin = new uv.Tty(0, true);
208+
var stdout = new uv.Tty(1, false);
209+
p(stdin, stdout, stdin.getWinsize());
210+
print("Type test, hit enter to send");
211+
print("Press Control-D to stop test");
212+
stdin.readStart(function (err, chunk) {
213+
if (err) throw err;
214+
p("stdin", chunk);
215+
if (chunk) {
216+
stdout.write(chunk);
217+
}
218+
else {
219+
stdin.readStop();
220+
}
221+
});
222+
uv.run();
223+
stdin.close();
224+
stdout.close();
225+
206226
ticker.close();
227+
prepare.close();
228+
check.close();
229+
idle.close();
230+
uv.run();

implementations/duktape/duv/duv.c

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "stream.h"
1111
#include "tcp.h"
1212
#include "pipe.h"
13+
#include "tty.h"
1314

1415
static const duk_function_list_entry duv_handle_methods[] = {
1516
{"inspect", duv_tostring, 0},
@@ -92,6 +93,12 @@ static const duk_function_list_entry duv_pipe_methods[] = {
9293
{0,0,0}
9394
};
9495

96+
static const duk_function_list_entry duv_tty_methods[] = {
97+
{"setMode", duv_tty_set_mode, 1},
98+
{"getWinsize", duv_tty_get_winsize, 0},
99+
{0,0,0}
100+
};
101+
95102
static const duk_function_list_entry duv_funcs[] = {
96103
// loop.c
97104
{"run", duv_run, 0},
@@ -105,23 +112,10 @@ static const duk_function_list_entry duv_funcs[] = {
105112
{"Async", duv_new_async, 1},
106113
{"Tcp", duv_new_tcp, 0},
107114
{"Pipe", duv_new_pipe, 1},
115+
{"Tty", duv_new_tty, 2},
116+
117+
{"ttyResetMode", duv_tty_reset_mode, 0},
108118

109-
// // pipe.c
110-
// {"new_pipe", duv_new_pipe, 1},
111-
// {"pipe_open", duv_pipe_open, 2},
112-
// {"pipe_bind", duv_pipe_bind, 2},
113-
// {"pipe_connect", duv_pipe_connect, 3},
114-
// {"pipe_getsockname", duv_pipe_getsockname, 1},
115-
// {"pipe_pending_instances", duv_pipe_pending_instances, 2},
116-
// {"pipe_pending_count", duv_pipe_pending_count, 1},
117-
// {"pipe_pending_type", duv_pipe_pending_type, 1},
118-
//
119-
// // tty.c
120-
// {"new_tty", duv_new_tty, 2},
121-
// {"tty_set_mode", duv_tty_set_mode, 2},
122-
// {"tty_reset_mode", duv_tty_reset_mode, 0},
123-
// {"tty_get_winsize", duv_tty_get_winsize, 1},
124-
//
125119
// // fs.c
126120
// {"fs_close", duv_fs_close, 2},
127121
// {"fs_open", duv_fs_open, 4},
@@ -262,32 +256,33 @@ duk_ret_t duv_push_module(duk_context *ctx) {
262256

263257
// uv.Tcp.prototype
264258
duk_get_prop_string(ctx, -3, "Tcp");
265-
// stack: nucleus uv Handle.prototype Stream.prototype Tcp
266259
duk_push_object(ctx);
267260
duk_put_function_list(ctx, -1, duv_tcp_methods);
268-
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype
269261
duk_dup(ctx, -3);
270-
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype Stream.prototype
271262
duk_set_prototype(ctx, -2);
272-
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype
273263
duk_put_prop_string(ctx, -2, "prototype");
274-
// stack: nucleus uv Handle.prototype Stream.prototype Tcp
275264
duk_pop(ctx);
276265

277266
// stack: nucleus uv Handle.prototype Stream.prototype
278267

279268
// uv.Pipe.prototype
280269
duk_get_prop_string(ctx, -3, "Pipe");
281-
// stack: nucleus uv Handle.prototype Stream.prototype Pipe
282270
duk_push_object(ctx);
283-
duk_put_function_list(ctx, -1, duv_tcp_methods);
284-
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype
271+
duk_put_function_list(ctx, -1, duv_pipe_methods);
272+
duk_dup(ctx, -3);
273+
duk_set_prototype(ctx, -2);
274+
duk_put_prop_string(ctx, -2, "prototype");
275+
duk_pop(ctx);
276+
277+
// stack: nucleus uv Handle.prototype Stream.prototype
278+
279+
// uv.Tty.prototype
280+
duk_get_prop_string(ctx, -3, "Tty");
281+
duk_push_object(ctx);
282+
duk_put_function_list(ctx, -1, duv_tty_methods);
285283
duk_dup(ctx, -3);
286-
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype Stream.prototype
287284
duk_set_prototype(ctx, -2);
288-
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype
289285
duk_put_prop_string(ctx, -2, "prototype");
290-
// stack: nucleus uv Handle.prototype Stream.prototype Pipe
291286
duk_pop(ctx);
292287

293288
// stack: nucleus uv Handle.prototype Stream.prototype

implementations/duktape/duv/tty.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,45 @@
11
#include "tty.h"
2+
3+
duk_ret_t duv_new_tty(duk_context *ctx) {
4+
dschema_check(ctx, (const duv_schema_entry[]) {
5+
{"fd", duk_is_number},
6+
{"readable", duk_is_boolean},
7+
{0,0}
8+
});
9+
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
10+
duv_check(ctx, uv_tty_init(duv_loop(ctx), tty,
11+
duk_get_int(ctx, 0),
12+
duk_get_int(ctx, 1)
13+
));
14+
duv_setup_handle(ctx, (uv_handle_t*)tty, DUV_TTY);
15+
return 1;
16+
}
17+
18+
duk_ret_t duv_tty_set_mode(duk_context *ctx) {
19+
dschema_check(ctx, (const duv_schema_entry[]) {
20+
{"mode", duk_is_number},
21+
{0,0}
22+
});
23+
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
24+
duv_check(ctx, uv_tty_set_mode(tty,
25+
duk_get_int(ctx, 1)
26+
));
27+
return 0;
28+
}
29+
30+
duk_ret_t duv_tty_get_winsize(duk_context *ctx) {
31+
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
32+
int width, height;
33+
duv_check(ctx, uv_tty_get_winsize(tty, &width, &height));
34+
duk_push_array(ctx);
35+
duk_push_int(ctx, width);
36+
duk_put_prop_index(ctx, -2, 0);
37+
duk_push_int(ctx, height);
38+
duk_put_prop_index(ctx, -2, 1);
39+
return 1;
40+
}
41+
42+
duk_ret_t duv_tty_reset_mode(duk_context *ctx) {
43+
duv_check(ctx, uv_tty_reset_mode());
44+
return 0;
45+
}

implementations/duktape/duv/tty.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@
33

44
#include "duv.h"
55

6+
duk_ret_t duv_new_tty(duk_context *ctx);
7+
duk_ret_t duv_tty_set_mode(duk_context *ctx);
8+
duk_ret_t duv_tty_get_winsize(duk_context *ctx);
9+
duk_ret_t duv_tty_reset_mode(duk_context *ctx);
10+
611
#endif

0 commit comments

Comments
 (0)