Browse Source

Introduce require('tty')

You may need to reconfigure after this commit due to the new library.
v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
a0e9a510b0
  1. 1
      doc/api/_toc.markdown
  2. 40
      doc/api/tty.markdown
  3. 12
      lib/readline.js
  4. 28
      lib/tty.js
  5. 22
      src/node_stdio.cc
  6. 5
      wscript

1
doc/api/_toc.markdown

@ -26,6 +26,7 @@
* [VM](vm.html) * [VM](vm.html)
* [Child Processes](child_processes.html) * [Child Processes](child_processes.html)
* [Assertion Testing](assert.html) * [Assertion Testing](assert.html)
* [TTY](tty.html)
* Appendixes * Appendixes
* [Appendix 1: Recommended Third-party Modules](appendix_1.html) * [Appendix 1: Recommended Third-party Modules](appendix_1.html)
* [Appendix 2: Deprecated API's](appendix_2.html) * [Appendix 2: Deprecated API's](appendix_2.html)

40
doc/api/tty.markdown

@ -0,0 +1,40 @@
## TTY
Use `require('tty')` to access this module.
### tty.open(path, args=[])
Spawns a new process with the executable pointed to by `path` as the session
leader to a new pseudo terminal.
Returns an array `[slaveFD, childProcess]`. `slaveFD` is the file descriptor
of the slave end of the pseudo terminal. `childProcess` is a child process
object.
### tty.isatty(fd)
Returns `true` or `false` depending on if the `fd` is associated with a
terminal.
### tty.setRawMode(mode)
`mode` should be `true` or `false`. This sets the properies of the current
process's stdin fd to act either as a raw device or default.
### tty.getColumns()
Returns the number of columns associated with the current process's TTY.
Note that each time this number is changed the process receives a `SIGWINCH`
signal. So you can keep a cache of it like this:
var columns = tty.getColumns();
process.on('SIGWINCH', function() {
columns = tty.getColumns();
});

12
lib/readline.js

@ -10,7 +10,7 @@ var kBufSize = 10 * 1024;
var util = require('util'); var util = require('util');
var inherits = require('util').inherits; var inherits = require('util').inherits;
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var stdio = process.binding('stdio'); var tty = require('tty');
exports.createInterface = function(output, completer) { exports.createInterface = function(output, completer) {
@ -40,7 +40,7 @@ function Interface(output, completer) {
this.setPrompt('> '); this.setPrompt('> ');
this.enabled = stdio.isatty(output.fd); this.enabled = tty.isatty(output.fd);
if (parseInt(process.env['NODE_NO_READLINE'], 10)) { if (parseInt(process.env['NODE_NO_READLINE'], 10)) {
this.enabled = false; this.enabled = false;
@ -56,7 +56,7 @@ function Interface(output, completer) {
this.line = ''; this.line = '';
// Check process.env.TERM ? // Check process.env.TERM ?
stdio.setRawMode(true); tty.setRawMode(true);
this.enabled = true; this.enabled = true;
// Cursor position on the line. // Cursor position on the line.
@ -65,11 +65,11 @@ function Interface(output, completer) {
this.history = []; this.history = [];
this.historyIndex = -1; this.historyIndex = -1;
exports.columns = process.binding('stdio').getColumns(); exports.columns = tty.getColumns();
if (process.listeners('SIGWINCH').length === 0) { if (process.listeners('SIGWINCH').length === 0) {
process.on('SIGWINCH', function() { process.on('SIGWINCH', function() {
exports.columns = process.binding('stdio').getColumns(); exports.columns = tty.getColumns();
}); });
} }
} }
@ -133,7 +133,7 @@ Interface.prototype._refreshLine = function() {
Interface.prototype.close = function(d) { Interface.prototype.close = function(d) {
if (this.enabled) { if (this.enabled) {
stdio.setRawMode(false); tty.setRawMode(false);
} }
this.emit('close'); this.emit('close');
this._closed = true; this._closed = true;

28
lib/tty.js

@ -0,0 +1,28 @@
var spawn = require('child_process').spawn;
var binding = process.binding('stdio');
exports.isatty = binding.isatty;
exports.setRawMode = binding.setRawMode;
exports.getColumns = binding.getColumns;
exports.open = function(path, args) {
var fds = binding.openpty();
var masterFD = fds[1];
var slaveFD = fds[0];
var env = { TERM: 'vt100' };
for (var k in process.env) {
env[k] = process.env[k];
}
child = spawn(path, args, env, [masterFD, masterFD, masterFD]);
return [slaveFD, child];
};

22
src/node_stdio.cc

@ -5,6 +5,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <pty.h>
#include <termios.h> #include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -189,6 +190,26 @@ static Handle<Value> IsStdoutBlocking(const Arguments& args) {
} }
static Handle<Value> OpenPTY(const Arguments& args) {
HandleScope scope;
int master_fd, slave_fd;
int r = openpty(&master_fd, &slave_fd, NULL, NULL, NULL);
if (r == -1) {
return ThrowException(ErrnoException(errno, "openpty"));
}
Local<Array> a = Array::New(2);
a->Set(0, Integer::New(master_fd));
a->Set(1, Integer::New(slave_fd));
return scope.Close(a);
}
void Stdio::Flush() { void Stdio::Flush() {
if (stdin_flags != -1) { if (stdin_flags != -1) {
fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK); fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK);
@ -232,6 +253,7 @@ void Stdio::Initialize(v8::Handle<v8::Object> target) {
NODE_SET_METHOD(target, "getColumns", GetColumns); NODE_SET_METHOD(target, "getColumns", GetColumns);
NODE_SET_METHOD(target, "getRows", GetRows); NODE_SET_METHOD(target, "getRows", GetRows);
NODE_SET_METHOD(target, "isatty", IsATTY); NODE_SET_METHOD(target, "isatty", IsATTY);
NODE_SET_METHOD(target, "openpty", OpenPTY);
struct sigaction sa; struct sigaction sa;
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));

5
wscript

@ -233,6 +233,9 @@ def configure(conf):
else: else:
Options.options.use_openssl = conf.env["USE_OPENSSL"] = False Options.options.use_openssl = conf.env["USE_OPENSSL"] = False
conf.check(lib='util', libpath=['/usr/lib', '/usr/local/lib'],
uselib_store='UTIL')
# normalize DEST_CPU from --dest-cpu, DEST_CPU or built-in value # normalize DEST_CPU from --dest-cpu, DEST_CPU or built-in value
if Options.options.dest_cpu and Options.options.dest_cpu: if Options.options.dest_cpu and Options.options.dest_cpu:
conf.env['DEST_CPU'] = canonical_cpu_type(Options.options.dest_cpu) conf.env['DEST_CPU'] = canonical_cpu_type(Options.options.dest_cpu)
@ -570,7 +573,7 @@ def build(bld):
node = bld.new_task_gen("cxx", product_type) node = bld.new_task_gen("cxx", product_type)
node.name = "node" node.name = "node"
node.target = "node" node.target = "node"
node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL' node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL UTIL'
node.add_objects = 'eio http_parser' node.add_objects = 'eio http_parser'
if product_type_is_lib: if product_type_is_lib:
node.install_path = '${PREFIX}/lib' node.install_path = '${PREFIX}/lib'

Loading…
Cancel
Save