Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tty: Deno.setRaw(rid, mode) to turn on/off raw mode #3958

Merged
merged 22 commits into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -73,3 +73,6 @@ nix = "0.14.1"

[dev-dependencies]
os_pipe = "0.9.1"

[target.'cfg(unix)'.dev-dependencies]
pty = "0.2"
3 changes: 2 additions & 1 deletion cli/js/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export {
ShutdownMode,
shutdown
} from "./net.ts";
export { dir, env, exit, isTTY, execPath, hostname, loadavg } from "./os.ts";
export { dir, env, exit, execPath, hostname, loadavg } from "./os.ts";
export {
permissions,
PermissionName,
Expand Down Expand Up @@ -114,6 +114,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, isTTY, 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
3 changes: 2 additions & 1 deletion cli/js/dispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { AsyncHandler } from "./plugins.ts";
export let OP_READ: number;
export let OP_WRITE: number;
export let OP_EXIT: number;
export let OP_IS_TTY: number;
export let OP_ENV: number;
export let OP_EXEC_PATH: number;
export let OP_UTIME: number;
Expand Down Expand Up @@ -81,6 +80,8 @@ export let OP_SIGNAL_BIND: number;
export let OP_SIGNAL_UNBIND: number;
export let OP_SIGNAL_POLL: number;
export let OP_LOADAVG: number;
export let OP_SET_RAW: number;
export let OP_ISATTY: number;

const PLUGIN_ASYNC_HANDLER_MAP: Map<number, AsyncHandler> = new Map();

Expand Down
35 changes: 25 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 @@ -486,6 +476,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 @@ -549,6 +540,30 @@ 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;

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

// @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 @@ -4,13 +4,6 @@ import { sendSync } from "./dispatch_json.ts";
import { Err } 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(dispatch.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
27 changes: 27 additions & 0 deletions cli/js/tty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { sendSync } from "./dispatch_json.ts";
import * as dispatch from "./dispatch.ts";

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

/** Set TTY to be under raw mode or not. */
export function setRaw(rid: number, mode: boolean): void {
sendSync(dispatch.OP_SET_RAW, {
rid,
mode
});
}

/** Check if running in terminal.
*
* console.log(Deno.isTTY().stdout);
*/
export function isTTY(): { stdin: boolean; stdout: boolean; stderr: boolean } {
return {
stdin: isatty(0),
stdout: isatty(1),
stderr: isatty(2)
};
}
ry marked this conversation as resolved.
Show resolved Hide resolved
27 changes: 27 additions & 0 deletions cli/js/tty_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert } from "./test_util.ts";

// setRaw test is in integration tests.

// Smoke test to ensure no error.
test(function isTTYSmoke(): void {
console.log(Deno.isTTY());
});

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.Err.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 @@ -53,6 +53,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::ops::json_op;
Expand Down Expand Up @@ -126,9 +126,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 @@ -198,7 +199,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 @@ -216,7 +230,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 @@ -233,7 +247,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 @@ -3,7 +3,6 @@ use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::op_error::OpError;
use crate::ops::json_op;
use crate::state::State;
use atty;
use deno_core::*;
use std::collections::HashMap;
use std::env;
Expand All @@ -13,7 +12,6 @@ use url::Url;

pub fn init(i: &mut Isolate, s: &State) {
i.register_op("exit", s.core_op(json_op(s.stateful_op(op_exit))));
i.register_op("is_tty", s.core_op(json_op(s.stateful_op(op_is_tty))));
i.register_op("env", s.core_op(json_op(s.stateful_op(op_env))));
i.register_op("exec_path", s.core_op(json_op(s.stateful_op(op_exec_path))));
i.register_op("set_env", s.core_op(json_op(s.stateful_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),
})))
}
ry marked this conversation as resolved.
Show resolved Hide resolved

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 @@ -37,7 +37,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