Skip to content

Commit

Permalink
tty: Deno.setRaw(rid, mode) to turn on/off raw mode (denoland#3958)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinkassimo authored Feb 26, 2020
1 parent e53064c commit 5946808
Show file tree
Hide file tree
Showing 19 changed files with 429 additions and 49 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ nix = "0.14.1"

[dev-dependencies]
os_pipe = "0.9.1"

[target.'cfg(unix)'.dev-dependencies]
pty = "0.2"
2 changes: 1 addition & 1 deletion cli/js/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export {
dir,
env,
exit,
isTTY,
execPath,
hostname,
loadavg,
Expand Down Expand Up @@ -124,6 +123,7 @@ export { statSync, lstatSync, stat, lstat } from "./stat.ts";
export { symlinkSync, symlink } from "./symlink.ts";
export { connectTLS, listenTLS } from "./tls.ts";
export { truncateSync, truncate } from "./truncate.ts";
export { isatty, setRaw } from "./tty.ts";
export { utimeSync, utime } from "./utime.ts";
export { version } from "./version.ts";
export { writeFileSync, writeFile, WriteFileOptions } from "./write_file.ts";
Expand Down
25 changes: 15 additions & 10 deletions cli/js/lib.deno.ns.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,6 @@ declare namespace Deno {

export function runTests(opts?: RunTestsOptions): Promise<void>;

/** Check if running in terminal.
*
* console.log(Deno.isTTY().stdout);
*/
export function isTTY(): {
stdin: boolean;
stdout: boolean;
stderr: boolean;
};

/** Get the loadavg. Requires the `--allow-env` flag.
*
* console.log(Deno.loadavg());
Expand Down Expand Up @@ -492,6 +482,7 @@ declare namespace Deno {
seekSync(offset: number, whence: SeekMode): void;
close(): void;
}

/** An instance of `File` for stdin. */
export const stdin: File;
/** An instance of `File` for stdout. */
Expand Down Expand Up @@ -555,6 +546,20 @@ declare namespace Deno {
/** Read-write. Behaves like `x` and allows to read from file. */
| "x+";

// @url js/tty.d.ts

/** UNSTABLE: newly added API
*
* Check if a given resource is TTY
*/
export function isatty(rid: number): boolean;

/** UNSTABLE: newly added API
*
* Set TTY to be under raw mode or not.
*/
export function setRaw(rid: number, mode: boolean): void;

// @url js/buffer.d.ts

/** A Buffer is a variable-sized buffer of bytes with read() and write()
Expand Down
7 changes: 0 additions & 7 deletions cli/js/os.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@ import { sendSync } from "./dispatch_json.ts";
import { errors } from "./errors.ts";
import * as util from "./util.ts";

/** Check if running in terminal.
*
* console.log(Deno.isTTY().stdout);
*/
export function isTTY(): { stdin: boolean; stdout: boolean; stderr: boolean } {
return sendSync("op_is_tty");
}
/** Get the loadavg.
* Requires the `--allow-env` flag.
*
Expand Down
4 changes: 0 additions & 4 deletions cli/js/os_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ test(function osPid(): void {
assert(Deno.pid > 0);
});

test(function osIsTTYSmoke(): void {
console.log(Deno.isTTY());
});

testPerm({ env: true }, function getDir(): void {
type supportOS = "mac" | "win" | "linux";

Expand Down
14 changes: 14 additions & 0 deletions cli/js/tty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { sendSync } from "./dispatch_json.ts";

/** Check if a given resource is TTY. */
export function isatty(rid: number): boolean {
return sendSync("op_isatty", { rid });
}

/** Set TTY to be under raw mode or not. */
export function setRaw(rid: number, mode: boolean): void {
sendSync("op_set_raw", {
rid,
mode
});
}
22 changes: 22 additions & 0 deletions cli/js/tty_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert } from "./test_util.ts";

// Note tests for Deno.setRaw is in integration tests.

testPerm({ read: true }, function isatty(): void {
// CI not under TTY, so cannot test stdin/stdout/stderr.
const f = Deno.openSync("cli/tests/hello.txt");
assert(!Deno.isatty(f.rid));
});

test(function isattyError(): void {
let caught = false;
try {
// Absurdly large rid.
Deno.isatty(0x7fffffff);
} catch (e) {
caught = true;
assert(e instanceof Deno.errors.BadResource);
}
assert(caught);
});
1 change: 1 addition & 0 deletions cli/js/unit_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import "./text_encoding_test.ts";
import "./timers_test.ts";
import "./tls_test.ts";
import "./truncate_test.ts";
import "./tty_test.ts";
import "./url_test.ts";
import "./url_search_params_test.ts";
import "./utime_test.ts";
Expand Down
11 changes: 6 additions & 5 deletions cli/ops/files.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, JsonOp, Value};
use super::io::StreamResource;
use super::io::{FileMetadata, StreamResource};
use crate::fs as deno_fs;
use crate::op_error::OpError;
use crate::state::State;
Expand Down Expand Up @@ -125,9 +125,10 @@ fn op_open(
let fut = async move {
let fs_file = open_options.open(filename).await?;
let mut state = state_.borrow_mut();
let rid = state
.resource_table
.add("fsFile", Box::new(StreamResource::FsFile(fs_file)));
let rid = state.resource_table.add(
"fsFile",
Box::new(StreamResource::FsFile(fs_file, FileMetadata::default())),
);
Ok(json!(rid))
};

Expand Down Expand Up @@ -197,7 +198,7 @@ fn op_seek(
.ok_or_else(OpError::bad_resource)?;

let tokio_file = match resource {
StreamResource::FsFile(ref file) => file,
StreamResource::FsFile(ref file, _) => file,
_ => return Err(OpError::bad_resource()),
};
let mut file = futures::executor::block_on(tokio_file.try_clone())?;
Expand Down
28 changes: 21 additions & 7 deletions cli/ops/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub fn init(i: &mut Isolate, s: &State) {
}

pub fn get_stdio() -> (StreamResource, StreamResource, StreamResource) {
let stdin = StreamResource::Stdin(tokio::io::stdin());
let stdin = StreamResource::Stdin(tokio::io::stdin(), TTYMetadata::default());
let stdout = StreamResource::Stdout({
let stdout = STDOUT_HANDLE
.try_clone()
Expand All @@ -69,11 +69,25 @@ pub fn get_stdio() -> (StreamResource, StreamResource, StreamResource) {
(stdin, stdout, stderr)
}

#[cfg(unix)]
use nix::sys::termios;

#[derive(Default)]
pub struct TTYMetadata {
#[cfg(unix)]
pub mode: Option<termios::Termios>,
}

#[derive(Default)]
pub struct FileMetadata {
pub tty: TTYMetadata,
}

pub enum StreamResource {
Stdin(tokio::io::Stdin),
Stdin(tokio::io::Stdin, TTYMetadata),
Stdout(tokio::fs::File),
Stderr(tokio::io::Stderr),
FsFile(tokio::fs::File),
FsFile(tokio::fs::File, FileMetadata),
TcpStream(tokio::net::TcpStream),
ServerTlsStream(Box<ServerTlsStream<TcpStream>>),
ClientTlsStream(Box<ClientTlsStream<TcpStream>>),
Expand Down Expand Up @@ -101,8 +115,8 @@ impl DenoAsyncRead for StreamResource {
) -> Poll<Result<usize, OpError>> {
use StreamResource::*;
let mut f: Pin<Box<dyn AsyncRead>> = match self {
FsFile(f) => Box::pin(f),
Stdin(f) => Box::pin(f),
FsFile(f, _) => Box::pin(f),
Stdin(f, _) => Box::pin(f),
TcpStream(f) => Box::pin(f),
ClientTlsStream(f) => Box::pin(f),
ServerTlsStream(f) => Box::pin(f),
Expand Down Expand Up @@ -203,7 +217,7 @@ impl DenoAsyncWrite for StreamResource {
) -> Poll<Result<usize, OpError>> {
use StreamResource::*;
let mut f: Pin<Box<dyn AsyncWrite>> = match self {
FsFile(f) => Box::pin(f),
FsFile(f, _) => Box::pin(f),
Stdout(f) => Box::pin(f),
Stderr(f) => Box::pin(f),
TcpStream(f) => Box::pin(f),
Expand All @@ -220,7 +234,7 @@ impl DenoAsyncWrite for StreamResource {
fn poll_flush(&mut self, cx: &mut Context) -> Poll<Result<(), OpError>> {
use StreamResource::*;
let mut f: Pin<Box<dyn AsyncWrite>> = match self {
FsFile(f) => Box::pin(f),
FsFile(f, _) => Box::pin(f),
Stdout(f) => Box::pin(f),
Stderr(f) => Box::pin(f),
TcpStream(f) => Box::pin(f),
Expand Down
1 change: 1 addition & 0 deletions cli/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ pub mod runtime_compiler;
pub mod signal;
pub mod timers;
pub mod tls;
pub mod tty;
pub mod web_worker;
pub mod worker_host;
14 changes: 0 additions & 14 deletions cli/ops/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::op_error::OpError;
use crate::state::State;
use atty;
use deno_core::*;
use std::collections::HashMap;
use std::env;
Expand All @@ -12,7 +11,6 @@ use url::Url;

pub fn init(i: &mut Isolate, s: &State) {
i.register_op("op_exit", s.stateful_json_op(op_exit));
i.register_op("op_is_tty", s.stateful_json_op(op_is_tty));
i.register_op("op_env", s.stateful_json_op(op_env));
i.register_op("op_exec_path", s.stateful_json_op(op_exec_path));
i.register_op("op_set_env", s.stateful_json_op(op_set_env));
Expand Down Expand Up @@ -151,18 +149,6 @@ fn op_exit(
std::process::exit(args.code)
}

fn op_is_tty(
_s: &State,
_args: Value,
_zero_copy: Option<ZeroCopyBuf>,
) -> Result<JsonOp, OpError> {
Ok(JsonOp::Sync(json!({
"stdin": atty::is(atty::Stream::Stdin),
"stdout": atty::is(atty::Stream::Stdout),
"stderr": atty::is(atty::Stream::Stderr),
})))
}

fn op_loadavg(
state: &State,
_args: Value,
Expand Down
2 changes: 1 addition & 1 deletion cli/ops/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn clone_file(rid: u32, state: &State) -> Result<std::fs::File, OpError> {
.get_mut::<StreamResource>(rid)
.ok_or_else(OpError::bad_resource)?;
let file = match repr {
StreamResource::FsFile(ref mut file) => file,
StreamResource::FsFile(ref mut file, _) => file,
_ => return Err(OpError::bad_resource()),
};
let tokio_file = futures::executor::block_on(file.try_clone())?;
Expand Down
Loading

0 comments on commit 5946808

Please sign in to comment.