Skip to content

Inquirer 中文文档

常用的交互式的命令行用户界面

alt text

在你的终端中自己尝试一下!

sh
npx @inquirer/demo@latest

安装

shell
npm install @inquirer/prompts
shell
yarn add @inquirer/prompts

提示

Inquirer 最近进行了彻底的重写,减少了包体积并提升了性能。之前的版本虽然没有再积极开发了,但还在维护。之前版本中提供的数百个来自社区的 prompt 可能尚未迁移至最新的 API。如果你正在找这些包,可以在这里查看之前的包

使用

js
import { input } from '@inquirer/prompts';

const answer = await input({ message: '请输入名字' });

输入方式

输入 Input

alt text

js
import { input } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

单选 Select

alt text

js
import { select } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

多选 Checkbox

alt text

js
import { checkbox } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

确认 Confirm

alt text

js
import { confirm } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

alt text

js
import { search } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

密码 Password

alt text

js
import { password } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

折叠 Expand

alt text

alt text

js
import { expand } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

编辑器 Editor

在一个临时文件上启动一个编辑器实例。当用户关闭编辑器,临时文件中的内容将会被读入回答中。使用哪个编辑器取决于环境变量 $VISUAL$EDITOR。如果二者都没有指定值,将会使用系统默认编辑器,即记事本(Windows)和 Vim(Max/Linux)。

js
import { editor } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

数字 Number

输入 十分相似,只是添加了内置的数字验证器。

js
import { number } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

原始列表 Raw List

alt text

js
import { rawlist } from '@inquirer/prompts';

文档 中查看使用示例和其它可选内容。

创建你的输入提示

这里 查看 API 文档,这里 则是我们提供的测试工具。


高级用法

所有的 inquirer 输入提示都是包含 2 个参数的函数。第一个参数是提示配置(每个输入提示都是独一无二的)。第二个参数是提供上下文或运行时配置。

上下文选项:

属性类型必填描述
inputNodeJS.ReadableStream输入流 (默认是 process.stdin)
outputNodeJS.WritableStream输出流 (默认是 process.stdout)
clearPromptOnDoneboolean如果为真,我们会在输入得到回答后清除屏幕
signalAbortSignal一个中止信号,以异步地进行取消

示例:

js
import { confirm } from '@inquirer/prompts';

const allowEmail = await confirm(
  { message: '是否允许我们给你发送电子邮件?' },
  {
    output: new Stream.Writable({
      write(chunk, _encoding, next) {
        // 其它业务逻辑
        next();
      },
    }),
    clearPromptOnDone: true,
  },
);

取消提示

可以通过 AbortControllerAbortSignal 来实现。

js
// 示例 1:使用内置的中止信号
import { confirm } from '@inquirer/prompts';

const answer = await confirm({ ... }, { signal: AbortSignal.timeout(5000) });
js
// 示例 2:使用 AbortController 来实现一个自定义的中止
import { confirm } from '@inquirer/prompts';

const controller = new AbortController();
setTimeout(() => {
  controller.abort(); // 这将 reject 掉当前的 Promise
}, 5000);

const answer = await confirm({ ... }, { signal: controller.signal });

具体应用

更好地处理 Ctrl + C

当用户按下 Ctrl + C,Inquirer 会 reject 当前提示的 Promise。这是预期中的行为,以便允许你的程序打扫运行后的环境。当使用了 async/await,被 reject 的 Promise 会抛出错误。当没有捕获错误时,它们的错误信息和堆栈信息将会打印到用户的终端上。

ExitPromptError: User force closed the prompt with 0 null
  at file://example/packages/core/dist/esm/lib/create-prompt.js:55:20
  at Emitter.emit (file://example/node_modules/signal-exit/dist/mjs/index.js:67:19)
  at #processEmit (file://example/node_modules/signal-exit/dist/mjs/index.js:236:27)
  at #process.emit (file://example/node_modules/signal-exit/dist/mjs/index.js:187:37)
  at process.callbackTrampoline (node:internal/async_hooks:130:17)

这并不是很好的用户体验,所以我们十分建议你能更好地捕获错误。

第一个办法是使用 try/catch 包裹你的脚本,就像 我们在示例程序中做的那样。或者是在你的命令行程序框架中对其进行捕获,例如 Clipanioncatch 方法

最后,你应该可以使用一个事件监听器来全局捕获错误并让它闭嘴了。

ts
process.on('uncaughtException', (error) => {
  if (error instanceof Error && error.name === 'ExitPromptError') {
    console.log('👋 下次见!');
  } else {
    // 重新抛出未知的错误
    throw error;
  }
});

获取对象中的回答

当提问了很多问题时,你一定不想每个答案都是一个单一的值。这时你可以将答案放在一个对象中。

js
import { input, confirm } from '@inquirer/prompts';

const answers = {
  firstName: await input({ message: "你姓什么?" }),
  allowEmail: await confirm({ message: '是否允许我们给你发送电子邮件?' }),
};

console.log(answers.firstName);

根据条件提问

有时一些问题是否出现取决于其它问题的回答。

js
import { input, confirm } from '@inquirer/prompts';

const allowEmail = await confirm({ message: '是否允许我们给你发送电子邮件?' });

let email;
if (allowEmail) {
  email = await input({ message: '你的电子邮件地址是什么?' });
}

超时后获取默认值

js
import { input } from '@inquirer/prompts';

const answer = await input(
  { message: '输入一个值 (5秒后超时)' },
  { signal: AbortSignal.timeout(5000) },
).catch((error) => {
  if (error.name === 'AbortPromptError') {
    return '默认值';
  }

  throw error;
});

在预提交/git 钩子或脚本中使用

默认情况下,一些工具中(比如 huskylint-staged)运行的脚本可能无法在交互式 shell 中运行。但是在非交互式的 shell 中,Inquirer 无法运行,用户无法向该进程发送按键事件。

为了使其可以在这些工具中使用,你必须启动一个 tty(或者是一个交互式输入流)。

如果那些脚本被配置在你的 package.json 中,你可以像这样定义一个流:

json
  "precommit": "my-script < /dev/tty"

或者是在脚本文件中定义的,你可以像这样:(在 Windows 中可能这是你唯一的选择)

sh
#!/bin/sh
exec < /dev/tty

node my-script.js

与 nodemon 一起使用

当 Inquirer 输入提示和 nodemon 一起使用时,你需要在任何命令中加上 --no-stdin 标志来让一切如预期运行。

sh
npx nodemon ./packages/demo/demos/password.mjs --no-stdin

需要注意的是,对于大多数情况来说,你可以使用 Node 内置的全新的 watch-mode 模式。此模式可以与 Inquire 直接配合使用。

sh
# 取决于你的具体需求
node --watch script.js
node --watch-path=packages/ packages/demo/

等待配置

可能一些问题的配置需要等待一个异步结果。

js
import { confirm } from '@inquirer/prompts';

const answer = await confirm({ message: await getMessage() });

与在 bash 脚本中使用的 npx 一起使用

你可以通过 npx 在 shell 中直接使用 Inquirer 输入提示,这对一些快速脚本或者是 package.json 中的命令特别有用。

@inquirer-cli 是一个公共库,为每一个输入提示都暴露了一个独立的命令行接口。

例如,提示用户进行输入:

bash
name=$(npx -y @inquirer-cli/input -r "你的名字是?")
echo "你好, $name!"

或者是创建一个可交互的版本查询工具:

bash
$ npm version $(npx -y @inquirer-cli/select -c patch -c minor -c major 'Select Version')

查看更多: @inquirer-cli

社区提供的更多输入提示

如果你创建了一个很酷的输入提示,给我们提交一个 PR 来将它添加到下面的列表中!

交互式的列表提示

通过方向键+回车键或是通过快捷键来进行选择。

? 选择一项:
>   运行命令 (D)
    退出 (Q)

动作选择提示

在列表中选择其中一项,并通过按键来选择一个动作。

? 选择一个文件以 打开 <O> 编辑 <E> 删除 <X>
❯ image.png
  audio.mp3
  code.py

基于表格的多选

通过表格视图选择多个答案。

sh
进行你的选择? (按下 <> 选中/取消选中, <上下箭> 移动光标,
<左右箭头> 在列之间移动)

┌──────────┬───────┬───────┐
 选项 是? 否?   |
├──────────┼───────┼───────┤
 选项 1 [  ]   |
├──────────┼───────┼───────┤
 选项 2   |
└──────────┴───────┴───────┘

切换选项

使用一个切换器进行确认。使用方向键+回车来选择一个选项。

? 是否继续? 否 / 是

可排序的多选输入提示

和内置的多选提示相同,但是允许使用 Ctrl + 上下箭头来给选项重新排序。

? 哪些 PR 要按照什么顺序进行合并? (<空格> 选中/取消, <a> 全选, <i> 反选, <ctrl+上> 向上移动, <ctrl+下> 向下移动, <enter> 继续)
❯ ◯ PR 1
  ◯ PR 2
  ◯ PR 3

多选提示

支持多选和过滤、搜索的输入提示。

? 选择你的操作系统, IDE, PL等。 (<tab> 选择/取消选择, <退格键> 取消所有已选, <回车> 确定)
>>  vue
>[ ] vue
 [ ] vuejs
 [ ] fuelphp
 [ ] venv
 [ ] vercel
 (使用方向键移动来显示更多选项)

文件选择器

一个文件选择器,你可以在目录间自由导航,可以指定显示任何文件类型,并且是完全可定制的。

sh
? 选择一个文件:
/main/path/
├── folder1/
├── folder2/
├── folder3/
├── file1.txt
├── file2.pdf
└── file3.jpg (禁止选择)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
使用 ↑↓ 在列表间导航
 <esc> 跳转到上一级
 <> 以选择文件或进入目录

许可

Copyright (c) 2023 Simon Boudrias (twitter: @vaxilart)
Licensed under the MIT license.

最后更新于: