- NodeJs的介绍及使用
- Node.js核心模块概览
- NodeJs-Assertion Testing
- NodeJs-Asynchronous Context Tracking
- NodeJs-async_hooks
- NodeJs-Buffer
- Node.js- C++ Addons
- Node.js-C++ Addons Node-API
- NodeJs-C++ Embedder API
- Node.js-Child Process
- NodeJs-Cluster
- Node.js-命令行选项
- Node.js-Console
- Node.js-Corepack
- Node.js-Crypto
- NodeJs-Debugger
- NodeJs-Diagnostics Channel
- NodeJs-DNS
- NodeJs-Domain
- NodeJs-Errors
- NodeJs-Events
- NodeJs-File system(一)
- NodeJs-File system(二)
- NodeJs-File system(三)
- NodeJs-Globals
- NodeJs-HTTP
- NodeJs-HTTP/2
- NodeJs-HTTPS
- NodeJs-Inspector
- NodeJs-Internationalization
- NodeJs-Modules CommonJS modules、ECMAScript modules、node:module、Packages、TypeScript
- NodeJs-Net
- NodeJs-OS
- NodeJs-path
- NodeJs-Performance Hooks
- NodeJs-Permissions
- NodeJs-process
- NodeJs-punycode
- Node.js-querystring
- NodeJs-Readline
- NodeJs-REPL
- NodeJs-Report
- NodeJs-Single Executable Applications
- NodeJs-SQLite
- NodeJs-Stream
- NodeJs-String Decoder
- NodeJs-Test runner
- NodeJs-Timers
- NodeJs-TLS/SSL
- NodeJs-Trace events
- NodeJs-TTY
- NodeJs-UDP/datagram
- NodeJs-URL
- NodeJs-Utilities
- NodeJs-V8
- NodeJs-VM
- NodeJs-WASI
- NodeJs-Web Crypto API
- NodeJs Web Streams API
- NodeJs Worker threads
- NodeJs-Zlib
- NodeJs-Single Executable Applications
NodeJs-TTY
class TTYTTY
模块是 Node.js 提供的一个与终端(终端设备,Terminal)交互的模块。TTY
是 Teletypewriter 的缩写,最初是指一种远程交互系统。如今,tty
模块允许我们访问和处理命令行输入、输出流,通常与 process.stdin
和 process.stdout
一起使用,处理交互式命令行应用中的输入输出行为。
1. 引入 tty
模块
在使用 tty
模块之前,需要将其引入到项目中:
const tty = require('tty');
2. 基本概念
- 终端(TTY):终端设备或终端仿真器(例如,shell、命令提示符),提供文本输入输出功能。
- 标准输入(stdin) 和 标准输出(stdout):分别表示输入设备(通常是键盘)和输出设备(通常是屏幕)。
tty
流:Node.js 中的process.stdin
和process.stdout
是流对象,它们也可以是TTY
对象。tty
模块可以检测这些流是否连接到 TTY。
3. 检测 TTY
可以使用 process.stdin.isTTY
和 process.stdout.isTTY
来检查当前进程的标准输入和输出是否连接到 TTY 设备。
示例:
if (process.stdout.isTTY) {
console.log('This is running in a terminal');
} else {
console.log('Not running in a terminal');
}
4. tty.isatty(fd)
方法
tty.isatty(fd)
用于检查给定的文件描述符(fd
)是否关联到 TTY 设备。
参数:
fd
:文件描述符,通常是process.stdin.fd
或process.stdout.fd
。
返回值:
- 返回
true
或false
,表示文件描述符是否指向 TTY。
示例:
const tty = require('tty');
console.log(tty.isatty(process.stdin.fd)); // 输出: true (如果连接到终端)
console.log(tty.isatty(1)); // 输出: true (stdout)
5. Class: tty.ReadStream
tty.ReadStream
是继承自 net.Socket
的类,表示一个读取 TTY 输入的流。process.stdin
是 tty.ReadStream
类的实例,默认情况下它是标准输入的流。
属性:
readStream.isRaw
:布尔值,指示是否启用了原始模式。readStream.setRawMode(mode)
:将readStream
切换到原始模式或关闭原始模式。
原始模式:
- 在原始模式下,输入不会被解释为特殊字符(例如 Ctrl+C 退出)。
- 启用原始模式适用于需要逐字节读取输入(如键盘输入)时。
示例:
const stdin = process.stdin;
stdin.setRawMode(true); // 启用原始模式
stdin.resume(); // 启用数据流
stdin.setEncoding('utf8');
stdin.on('data', (key) => {
if (key === '\u0003') { // Ctrl+C 退出
process.exit();
}
console.log(`You pressed: ${key}`);
});
在这个例子中,原始模式下每个按键的输入都会被读取并立即处理,而不会等待用户按下 Enter
。
6. Class: tty.WriteStream
tty.WriteStream
是继承自 net.Socket
的类,表示一个输出到 TTY 的流。process.stdout
和 process.stderr
都是 tty.WriteStream
类的实例。
属性:
writeStream.columns
:当前终端的列数(宽度)。如果流没有连接到 TTY,返回undefined
。writeStream.rows
:当前终端的行数(高度)。如果流没有连接到 TTY,返回undefined
。writeStream.isTTY
:指示流是否连接到 TTY 设备。
动态调整终端大小:
当终端大小发生变化时,resize
事件会触发。
示例:
if (process.stdout.isTTY) {
console.log(`Terminal size: ${process.stdout.columns}x${process.stdout.rows}`);
}
process.stdout.on('resize', () => {
console.log(`Resized to: ${process.stdout.columns}x${process.stdout.rows}`);
});
在这个例子中,resize
事件会在终端大小发生变化时触发,输出新的终端宽度和高度。
7. tty
模块的事件和交互
tty.ReadStream
和 tty.WriteStream
类都继承自 net.Socket
,因此支持标准的 stream
和 socket
事件,如 data
、end
、error
、close
。
data
事件:当输入流收到数据时触发。end
事件:当输入流结束时触发。resize
事件:当终端大小发生变化时触发(仅适用于tty.WriteStream
)。
示例:监听输入的 data
事件
const stdin = process.stdin;
stdin.setRawMode(true); // 启用原始模式
stdin.resume(); // 启用数据流
stdin.setEncoding('utf8');
stdin.on('data', (key) => {
if (key === '\u0003') { // Ctrl+C 退出
process.exit();
}
console.log(`You pressed: ${key}`);
});
在此例中,我们监听 data
事件,捕获用户输入并输出。
8. 终端控制字符
终端的控制字符(例如,Ctrl+C)通常会发送特定的字符代码。你可以通过启用原始模式来拦截这些字符,并自定义它们的行为。
- Ctrl+C (
\u0003
):通常用于终止进程。 - Ctrl+D (
\u0004
):发送 EOF(End of File)信号,表示输入结束。 - Ctrl+Z (
\u001A
):通常用于将进程挂起。
通过 setRawMode(true)
,可以捕获并处理这些控制字符,而不是让它们执行默认的行为。
9. Node.js 中的 tty
用途
tty
模块常用于构建命令行工具和交互式终端应用。使用 tty
模块,你可以:
- 检查进程是否在终端中运行。
- 处理和管理终端大小变化。
- 读取用户输入并处理特殊字符。
- 创建复杂的命令行交互(如进度条、菜单等)。
示例:构建一个简单的交互式命令行应用
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('What is your name? ', (answer) => {
console.log(`Hello, ${answer}!`);
rl.close();
});
在这个例子中,我们使用 readline
模块来读取用户输入,但底层依赖的是 tty
流。
总结
TTY
模块提供了处理命令行输入输出的底层机制。通过 tty
模块,你可以检测进程是否在终端中运行,管理终端大小变化,启用原始模式捕获和处理输入,以及构建复杂的交互式命令行应用。结合 Node.js 的流和事件模型,tty
模块是构建强大 CLI 应用程序的关键工具。