# Readline
~~~
穩定度: 2 - 不穩定
~~~
要使用此模塊,需要`require('readline')`.Readline程序允許逐行讀取一個流內容(例如`process.stdin`).
需要注意的是你一旦調用了這個模塊,你的node程序將不會終止直到你關閉此接口。下面是如何讓你的程序正常退出的方法:
~~~
rl.close();
});
~~~
### readline.createInterface(options)
創建一個readline的接口實例. 接受一個Object類型參數,可傳遞以下幾個值:
- `input` - 要監聽的可讀流 (必需).
- `output` - 要寫入 readline 的可寫流 (必須).
- `completer` - 用于 Tab 自動補全的可選函數。見下面使用的例子。
- `terminal` - 如果希望 `input` 和 `output` 流像 TTY 一樣對待,那么傳遞參數 `true` ,并且經由 ANSI/VT100 轉碼。 默認情況下檢查 `isTTY` 是否在 `output` 流上實例化。
通過用戶 `completer` 函數給定了一個當前行入口,并且期望返回一個包含兩個條目的數組:
1. 一個匹配當前輸入補全的字符串數組.
1. 一個用于匹配的子字符串。
最終像這種形式: `[[substr1, substr2, ...], originalsubstring]`.
實例:
~~~
function completer(line) {
var completions = '.help .error .exit .quit .q'.split(' ')
var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })
// show all completions if none found
return [hits.length ? hits : completions, line]
}
~~~
`completer` 也可以運行在異步模式下,此時接受兩個參數:
~~~
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
}
~~~
為了接受用戶的輸入,`createInterface` 通常跟 `process.stdin` 和 `process.stdout` 一塊使用:
~~~
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
~~~
一旦你有一個 readline 實例,你通常會監聽 "line" 事件。
如果這個實例中`terminal`為`true`,而且`output`流定義了一個`output.columns`屬性,那么`output`流將獲得最好的兼容性,并且,當columns變化時(當它是TTY時,`process.stdout`會自動這樣做),會在`output`上觸發一個 `"resize"`事件。
### 類: 接口
代表一個有輸入輸出流的 readline 接口的類。
### rl.setPrompt(prompt)
設置提示符,例如當你在命令行運行 `node` 時,你會看到 `>` ,這就是 node 的提示符。
### rl.prompt([preserveCursor])
為用戶輸入準備好readline,將現有的`setPrompt`選項放到新的一行,讓用戶有一個新的地方開始輸入。將`preserveCursor`設為`true`來防止光標位置被重新設定成`0`。
如果暫停,也會使用 `createInterface` 重置 `input` 流。
### rl.question(query, callback)
預先提示指定的query,然后用戶應答后觸發指定的callback。 顯示指定的query給用戶后,當用戶的應答被輸入后,就觸發了指定的callback
如果暫停,也會使用 `createInterface` 重置 `input` 流。
使用示例:
~~~
interface.question('What is your favorite food?', function(answer) {
console.log('Oh, so your favorite food is ' + answer);
});
~~~
### rl.pause()
暫停 readline 的輸入流 (`input` stream), 如果有需要稍后還可以恢復。
### rl.resume()
恢復 readline 的輸入流 (`input` stream).
### rl.close()
關閉接口實例 (`Interface` instance), 放棄控制輸入輸出流。"close" 事件會被觸發。
### rl.write(data, [key])
將 `data` 寫入到 `output` 流。`key` 是一個代表鍵序列的對象;當終端是一個 TTY 時可用。
如果暫停,也會重置 `input` 流。
實例:
~~~
rl.write('Delete me!');
// 模仿 ctrl+u快捷鍵,刪除之前所寫行
rl.write(null, {ctrl: true, name: 'u'});
~~~
### Events
### Event: 'line'
`function (line) {}`
在 `input` 流接受了一個 `\n` 時觸發,通常在用戶敲擊回車或者返回時接收。 這是一個監聽用戶輸入的利器。
監聽 `line` 事件的示例:
~~~
rl.on('line', function (cmd) {
console.log('You just typed: '+cmd);
});
~~~
### 事件: 'pause'
`function () {}`
不論何時,只要輸入流被暫停就會觸發。
同樣當輸入流未被暫停,但收到 `SIGCONT` 也會觸發。 (詳見 `SIGTSTP` 和 `SIGCONT` 事件)
監聽 `pause` 事件的示例:
~~~
rl.on('pause', function() {
console.log('Readline 輸入暫停.');
});
~~~
### 事件: 'resume'
`function () {}`
不論何時,只要輸入流重新啟用就會觸發。
監聽 `resume` 事件的示例:
~~~
rl.on('resume', function() {
console.log('Readline 恢復.');
});
~~~
### 事件: 'close'
`function () {}`
當 `close()` 被調用時觸發。
當 `input`流接收到"結束"事件時也會被觸發. 一旦觸發,應當認為`Interface`實例 "結束" . 例如, 當`input`流接收到`^D`時, 分別被認為`EOT`.
當 `input` 流接收到一個 `^C` 時,即使沒有 `SIGINT` 監聽器,也會觸發這個事件,分別被稱為 `SIGINT` 。
### Event: 'SIGINT'
`function () {}`
只要 `input`流 接收到`^C`就會被觸發, 分別被認為`SIGINT`.當`input`流接收到`SIGINT`時, 如果沒有 `SIGINT` 事件監聽器,`pause` 將會被觸發.
監聽 `SIGINT` 信號的示例:
~~~
rl.on('SIGINT', function() {
rl.question('Are you sure you want to exit?', function(answer) {
if (answer.match(/^y(es)?$/i)) rl.pause();
});
});
~~~
### Event: 'SIGTSTP'
`function () {}`
**該功能不支持 windows 操作系統**
只要`input`流接收到`^Z`時就被觸發, 分別被認為`SIGTSTP`. 當`input`流接收到 `SIGTSTP`時,如果沒有`SIGTSTP` 事件監聽器 ,程序會被發送到后臺 .
當程序使用參數 `fg` 重啟,`pause` 和 `SIGCONT` 事件將會被觸發。 你可以使用兩者中任一事件來恢復流。
在程序被發送到后臺之前,如果流暫停,`pause` 和 `SIGCONT` 事件將不會被觸發。
監聽 `SIGTSTP` 的示例:
~~~
rl.on('SIGTSTP', function() {
// 這將重載 SIGTSTP并防止程序轉到
// 后臺.
console.log('Caught SIGTSTP.');
});
~~~
### Event: 'SIGCONT'
`function () {}`
**該功能不支持 windows 操作系統**
一旦 `input`流中含有 `^Z`并被發送到后臺就會觸發,分別被認為 `SIGTSTP`, 然后繼續執行`fg(1)`. 這一事件只有在流被發送后臺之前沒有暫停才會觸發.
監聽 `SIGCONT` 的示例:
~~~
rl.on('SIGCONT', function() {
// `prompt` 將會自動恢復流
rl.prompt();
});
~~~
### 示例: Tiny CLI
這里有一個使用所有方法精心設計的小命令行程序:
~~~
rl.on('line', function(line) {
switch(line.trim()) {
case 'hello':
console.log('world!');
break;
default:
console.log('Say what? I might have heard `' + line.trim() + '`');
break;
}
rl.prompt();
}).on('close', function() {
console.log('Have a great day!');
process.exit(0);
});
~~~