prompts: Node.js 命令行问答交互程序

prompts: Node.js 命令行问答交互程序

prompts 是一个 Node.js npm 包,用来实现命令行问答程序,通常被一些 CLI 程序使用,比如 create-vite[1] 就是使用 prompts 让用户选择哪种模板创建程序的。

初始化项目

本地创建 prompts-demos/ 目录,开始我们学习之旅。

$ mkdir prompts-demos
cd .prompts-demos
# 使用 VS Code 中打开当前目录
$ code .

初始化项目,安装依赖:

$ pnpm init
# 使用 ES Module 组织模块 
$ npm pkg set type="module"
# 安装 prompts
$ pnpm install prompts @types/prompts

TIP:prompts 没有内置声明文件,我们通过下载类型包 @types/prompts 支持。

练习

每条 Prompt 都是 PromptObject 类型对象,包含一个 type 属性,用来决定提问类型。

下面是 type 属性类型定义 PromptType 的具体取值范围。

type PromptType = "text" | "password" | "invisible" | "number" | "confirm" | "list" | "toggle" | "select" | "multiselect" | "autocomplete" | "date" | "autocompleteMultiselect";

以下我们举一些常用 type 的例子,练习 prompts 的使用。

import prompts from 'prompts'

// 练习代码

text:文本提问

console.log(
  await prompts([
    {
      type'text',
      name: 'projectName',
      message: 'Project Name:',
      initial: 'vite-project'
    }
  ])
)

字段含义:

  • name:指定当前提问在返回对象中的属性名
  • message:显示给用户看的提问内容
  • initial:用户在不输入情况下,采用的默认值

执行看下效果:

prompts: Node.js 命令行问答交互程序

第一次我们使用默认值 vite-project,第二次我们输入了自定义项目名 hello-world

confirm:确认提问

const defaultTargetDir = 'vite-project'
let targetDir = defaultTargetDir

console.log(
  await prompts([
    {
      type'text',
      name: 'projectName',
      message: 'Project Name:',
      initial: defaultTargetDir,
      onState: (state) => {
        console.log(state)
        targetDir = state.value
      }
    },
    {
      type'confirm',
      name: 'overwrite',
      message: `Target directory "${targetDir}" is not empty. Remove existing files and continue?`,
      initial: true
    }
  ])
)

这个例子稍微复杂一丢丢。我们先进行了一次文本提问,用这一步输入的内容拼接第二个确认问题的问题。注意,为了能够在中间过程获得提问内容,我们用了 onState   钩子函数。

字段含义:

  • name:指定当前提问在返回对象中的属性名
  • message:显示给用户看的提问内容
  • initial:用户在不输入情况下,采用的默认值。confirm 默认值是 false(对应 N/No),我们改为 true(对应 Y/Yes)

执行看下效果:

prompts: Node.js 命令行问答交互程序

text 不同的是,confirm 的返回值是个布尔值。

select:选择项

const FRAMEWORKS = [
  {
    name: 'vanilla',
    display: 'Vanilla'
  },
  {
    name: 'vue',
    display: 'Vue'
  },
  {
    name: 'react',
    display: 'React'
  },
  {
    name: 'preact',
    display: 'Preact'
  }
]


console.log(
  await prompts([
    {
      type'select',
      name: 'framework',
      message: 'Select a framework:',
      choices: FRAMEWORKS.map(framework => {
        return {
          title: framework.display,
          value: framework
        }
      })
    }
  ])
)

字段含义:

  • name:指定当前提问在返回对象中的属性名
  • message:显示给用户看的提问内容
  • choices:选项列表,是一个数组。成员类型 { title: string, value:any }——title 是选择时展示的文本,value 表示返回值。

执行看下效果:

选择

prompts: Node.js 命令行问答交互程序

选中

prompts: Node.js 命令行问答交互程序

配合 kolorist 一起使用

目前选择框架时候,高亮文字都是一样的颜色。为了便于区分,我们可以为不通框架文字展示时显示不通颜色,这里需要借助 kolorist 工具包。

安装依赖:

$ pnpm install kolorist

修改 select 案例代码:

import prompts from 'prompts';
import {
  cyan,
  green,
  magenta,
  yellow,
from 'kolorist'

const FRAMEWORKS = [
  {
    name: 'vanilla',
    display: 'Vanilla',
    color: yellow
  },
  {
    name: 'vue',
    display: 'Vue',
    color: green
  },
  {
    name: 'react',
    display: 'React',
    color: cyan
  },
  {
    name: 'preact',
    display: 'Preact',
    color: magenta
  }
]


console.log(
  await prompts([
    {
      type'select',
      name: 'framework',
      message: 'Select a framework:',
      choices: FRAMEWORKS.map(framework => {
        return {
          title: framework.color(framework.display),
          value: framework
        }
      })
    }
  ])
)

执行看下效果:

prompts: Node.js 命令行问答交互程序

忽略此步:type: null

type: null 是一个特殊类型,prompts 会直接掠过这条 Prompt,通常用来根据输入做条件展示的场景。

import fs from 'node:fs'
import prompts from 'prompts'

const defaultTargetDir = 'vite-project'
let targetDir = defaultTargetDir

console.log(
  await prompts(
    [
      {
        type'text',
        name: 'projectName',
        message: 'Project name:',
        initial: defaultTargetDir,
        onState: (state) => {
          targetDir = state.value || defaultTargetDir
        },
      },
      {
        type() =>
          !fs.existsSync(targetDir) ? null : 'confirm',
        name: 'overwrite',
        message: () =>
          (targetDir === '.'
            ? 'Current directory'
            : `Target directory "${targetDir}"`) +
          ` is not empty. Remove existing files and continue?`,
      },
    ]
  )
)

执行看下效果:

prompts: Node.js 命令行问答交互程序

可以看见:

  • 在开始 vite-project 目录不存在的情况下,第二条由于是 type: null,直接略过了
  • 然后,我们创建 vite-project 目录,就触发了是否覆写的第二条提问显示了

总结

以上就是关于 prompts 这个命令行问答程序的基础介绍啦,更多详情的使用方式可以参考官方的案例[2],或者查看 create-vite 的代码[3]进行学习。

参考链接


  • https://github.com/vitejs/vite/blob/main/packages/create-vite/src/index.ts
  • https://www.npmjs.com/package/prompts
  • https://www.npmjs.com/package/kolorist

References

[1]

create-vite: https://github.com/vitejs/vite/blob/main/packages/create-vite/src/index.ts

[2]

官方的案例: https://github.com/terkelg/prompts#-examples

[3]

create-vite 的代码: https://github.com/vitejs/vite/blob/main/packages/create-vite/src/index.ts


原文始发于微信公众号(写代码的宝哥):prompts: Node.js 命令行问答交互程序

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/243864.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!