Skip to content

Commit

Permalink
Implement Tty (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
creationix committed Jun 8, 2016
1 parent 62add5e commit 4e6dfb8
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 37 deletions.
48 changes: 46 additions & 2 deletions api/uv.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,53 @@ Used to receive handles over IPC pipes.
First - call `pipe.pendingCount()`, if it’s > 0 then initialize a handle of
the given type, returned by `pipe.pendingType()` and call `pipe.accept(handle)`.

## `uv_tty_t`
## `uv_tty_t` - Tty handle

*TODO: document this module*
TTY handles represent a stream for the console.

### `new uv.Tty(fd, readable) → tty`

Initialize a new TTY stream with the given file descriptor. Usually the file
descriptor will be:

- 0 = stdin
- 1 = stdout
- 2 = stderr

*readable*, specifies if you plan on calling `tty.readStart()` with this stream.
stdin is readable, stdout is not.

On Unix this function will determine the path of the fd of the terminal using
ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY.
This lets libuv put the tty in non-blocking mode without affecting other
processes that share the tty.

This function is not thread safe on systems that don’t support ioctl TIOCGPTN or
TIOCPTYGNAME, for instance OpenBSD and Solaris.

*Note: If reopening the TTY fails, libuv falls back to blocking writes for
non-readable TTY streams.*

### `tty.setMode(mode)`

Set the TTY using the specified terminal mode.

- 0 = UV_TTY_MODE_NORMAL - Initial/normal terminal mode
- 1 = UV_TTY_MODE_RAW - Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also
enabled)
- 2 = UV_TTY_MODE_IO - Binary-safe I/O mode for IPC (Unix-only)

### `uv.ttyResetMode()`

To be called when the program exits. Resets TTY settings to default values for
the next process to take over.

This function is async signal-safe on Unix platforms but can fail with error
code UV_EBUSY if you call it when execution is inside `tty.setMode()`

### `tty.getWinsize() → [width, height]`

Gets the current Window size.

## `uv_udp_t`

Expand Down
40 changes: 32 additions & 8 deletions app/test-uv.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ p(Object.getPrototypeOf(streamProto));
print("\nPipe.prototype");
p(uv.Pipe.prototype);
print("Stream.prototype (via Pipe.prototype)");
var streamProto = Object.getPrototypeOf(uv.Pipe.prototype);
p(streamProto);
p(Object.getPrototypeOf(uv.Pipe.prototype));

print("\nTty.prototype");
p(uv.Tty.prototype);
print("Stream.prototype (via Tty.prototype)");
p(Object.getPrototypeOf(uv.Tty.prototype));

var prepare = new uv.Prepare();
prepare.start(function () {
Expand Down Expand Up @@ -171,11 +175,6 @@ client.connect("127.0.0.1", 8080, function (err) {
});
uv.run();

prepare.close();
check.close();
idle.close();
uv.run();


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


print("before");
nextTick(function () {
print("tick");
});
print("after");
uv.run();


print("Testing stdio with default mode");
var stdin = new uv.Tty(0, true);
var stdout = new uv.Tty(1, false);
p(stdin, stdout, stdin.getWinsize());
print("Type test, hit enter to send");
print("Press Control-D to stop test");
stdin.readStart(function (err, chunk) {
if (err) throw err;
p("stdin", chunk);
if (chunk) {
stdout.write(chunk);
}
else {
stdin.readStop();
}
});
uv.run();
stdin.close();
stdout.close();

ticker.close();
prepare.close();
check.close();
idle.close();
uv.run();
49 changes: 22 additions & 27 deletions implementations/duktape/duv/duv.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "stream.h"
#include "tcp.h"
#include "pipe.h"
#include "tty.h"

static const duk_function_list_entry duv_handle_methods[] = {
{"inspect", duv_tostring, 0},
Expand Down Expand Up @@ -92,6 +93,12 @@ static const duk_function_list_entry duv_pipe_methods[] = {
{0,0,0}
};

static const duk_function_list_entry duv_tty_methods[] = {
{"setMode", duv_tty_set_mode, 1},
{"getWinsize", duv_tty_get_winsize, 0},
{0,0,0}
};

static const duk_function_list_entry duv_funcs[] = {
// loop.c
{"run", duv_run, 0},
Expand All @@ -105,23 +112,10 @@ static const duk_function_list_entry duv_funcs[] = {
{"Async", duv_new_async, 1},
{"Tcp", duv_new_tcp, 0},
{"Pipe", duv_new_pipe, 1},
{"Tty", duv_new_tty, 2},

{"ttyResetMode", duv_tty_reset_mode, 0},

// // pipe.c
// {"new_pipe", duv_new_pipe, 1},
// {"pipe_open", duv_pipe_open, 2},
// {"pipe_bind", duv_pipe_bind, 2},
// {"pipe_connect", duv_pipe_connect, 3},
// {"pipe_getsockname", duv_pipe_getsockname, 1},
// {"pipe_pending_instances", duv_pipe_pending_instances, 2},
// {"pipe_pending_count", duv_pipe_pending_count, 1},
// {"pipe_pending_type", duv_pipe_pending_type, 1},
//
// // tty.c
// {"new_tty", duv_new_tty, 2},
// {"tty_set_mode", duv_tty_set_mode, 2},
// {"tty_reset_mode", duv_tty_reset_mode, 0},
// {"tty_get_winsize", duv_tty_get_winsize, 1},
//
// // fs.c
// {"fs_close", duv_fs_close, 2},
// {"fs_open", duv_fs_open, 4},
Expand Down Expand Up @@ -262,32 +256,33 @@ duk_ret_t duv_push_module(duk_context *ctx) {

// uv.Tcp.prototype
duk_get_prop_string(ctx, -3, "Tcp");
// stack: nucleus uv Handle.prototype Stream.prototype Tcp
duk_push_object(ctx);
duk_put_function_list(ctx, -1, duv_tcp_methods);
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype
duk_dup(ctx, -3);
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype Stream.prototype
duk_set_prototype(ctx, -2);
// stack: nucleus uv Handle.prototype Stream.prototype Tcp Tcp.prototype
duk_put_prop_string(ctx, -2, "prototype");
// stack: nucleus uv Handle.prototype Stream.prototype Tcp
duk_pop(ctx);

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

// uv.Pipe.prototype
duk_get_prop_string(ctx, -3, "Pipe");
// stack: nucleus uv Handle.prototype Stream.prototype Pipe
duk_push_object(ctx);
duk_put_function_list(ctx, -1, duv_tcp_methods);
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype
duk_put_function_list(ctx, -1, duv_pipe_methods);
duk_dup(ctx, -3);
duk_set_prototype(ctx, -2);
duk_put_prop_string(ctx, -2, "prototype");
duk_pop(ctx);

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

// uv.Tty.prototype
duk_get_prop_string(ctx, -3, "Tty");
duk_push_object(ctx);
duk_put_function_list(ctx, -1, duv_tty_methods);
duk_dup(ctx, -3);
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype Stream.prototype
duk_set_prototype(ctx, -2);
// stack: nucleus uv Handle.prototype Stream.prototype Pipe Pipe.prototype
duk_put_prop_string(ctx, -2, "prototype");
// stack: nucleus uv Handle.prototype Stream.prototype Pipe
duk_pop(ctx);

// stack: nucleus uv Handle.prototype Stream.prototype
Expand Down
44 changes: 44 additions & 0 deletions implementations/duktape/duv/tty.c
Original file line number Diff line number Diff line change
@@ -1 +1,45 @@
#include "tty.h"

duk_ret_t duv_new_tty(duk_context *ctx) {
dschema_check(ctx, (const duv_schema_entry[]) {
{"fd", duk_is_number},
{"readable", duk_is_boolean},
{0,0}
});
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
duv_check(ctx, uv_tty_init(duv_loop(ctx), tty,
duk_get_int(ctx, 0),
duk_get_int(ctx, 1)
));
duv_setup_handle(ctx, (uv_handle_t*)tty, DUV_TTY);
return 1;
}

duk_ret_t duv_tty_set_mode(duk_context *ctx) {
dschema_check(ctx, (const duv_schema_entry[]) {
{"mode", duk_is_number},
{0,0}
});
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
duv_check(ctx, uv_tty_set_mode(tty,
duk_get_int(ctx, 1)
));
return 0;
}

duk_ret_t duv_tty_get_winsize(duk_context *ctx) {
uv_tty_t *tty = duk_push_fixed_buffer(ctx, sizeof(uv_tty_t));
int width, height;
duv_check(ctx, uv_tty_get_winsize(tty, &width, &height));
duk_push_array(ctx);
duk_push_int(ctx, width);
duk_put_prop_index(ctx, -2, 0);
duk_push_int(ctx, height);
duk_put_prop_index(ctx, -2, 1);
return 1;
}

duk_ret_t duv_tty_reset_mode(duk_context *ctx) {
duv_check(ctx, uv_tty_reset_mode());
return 0;
}
5 changes: 5 additions & 0 deletions implementations/duktape/duv/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@

#include "duv.h"

duk_ret_t duv_new_tty(duk_context *ctx);
duk_ret_t duv_tty_set_mode(duk_context *ctx);
duk_ret_t duv_tty_get_winsize(duk_context *ctx);
duk_ret_t duv_tty_reset_mode(duk_context *ctx);

#endif

0 comments on commit 4e6dfb8

Please sign in to comment.