Sign in

    promptx

    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    3 months ago
    Downloads
    91

    #MoonBit Inquirer

    一个用于MoonBit的命令行交互式问答库,受到npm的Inquirer.js的启发。

    #功能特性

    MoonBit Inquirer提供优雅的方式来创建交互式命令行界面,支持以下问题类型:

    • Input: 文本输入
    • Confirm: 确认(是/否)
    • List: 列表选择
    • RawList: 带数字的列表选择
    • Expand: 展开式选择
    • Checkbox: 多选框
    • Password: 密码输入
    • Editor: 多行文本输入

    #安装

    将此库添加到您的MoonBit项目:

    moon add wangmingfa/promptx

    #快速开始

    import { "wangmingfa/promptx" }
    import { "moonbitlang/async" }

    async fn main {
    // 创建问题数组
    let questions : Array[Question] = [
    input(
    question_name="username",
    question_message="What is your name?",
    question_default=Some(AnswerValue::StringValue("Guest"))
    ),
    confirm(
    question_name="subscribe",
    question_message="Do you want to subscribe?"
    ),
    list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue"]
    ),
    ]

    // 执行提示并获取答案
    let answers = prompt(questions)

    // 处理答案
    match answers["username"] {
    AnswerValue::StringValue(name) => println("Hello, \{name}!")
    _ => println("Hello, Guest!")
    }
    }

    #API说明

    #核心函数

    #prompt

    处理问题数组并返回用户答案。

    pub async fn prompt(questions : Array[Question]) -> Answer

    参数:
    • questions : Array[Question] - 问题数组

    返回值: 返回 Answer 类型(Map[String, AnswerValue]),包含每个问题的答案。

    #问题构造函数

    #input

    创建文本输入问题。

    pub fn input(
    question_name~ : String,
    question_message~ : String,
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称,用于在答案中获取结果
    • question_message~ : String - 显示给用户的问题文本
    • question_default? : AnswerValue? - 可选的默认值

    示例:
    ///|
    let q = input(
    question_name="username",
    question_message="What is your username?",
    question_default=Some(AnswerValue::StringValue("admin")),
    )

    #confirm

    创建确认问题(是/否)。

    pub fn confirm(
    question_name~ : String,
    question_message~ : String,
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_default? : AnswerValue? - 可选的默认值

    返回值: 用户输入 Y/y/yes/true/1 返回 BoolValue(true),输入 N/n/no/false/0 返回 BoolValue(false)。

    示例:
    ///|
    let q = confirm(
    question_name="agree",
    question_message="Do you agree to the terms?",
    question_default=Some(AnswerValue::BoolValue(true)),
    )

    #list

    创建列表选择问题。

    pub fn list(
    question_name~ : String,
    question_message~ : String,
    question_choices~ : Array[String],
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_choices~ : Array[String] - 选项数组
    • question_default? : AnswerValue? - 可选的默认选项索引

    返回值: 返回用户选择的选项值:AnswerValue::StringValue("selected_option")

    示例:
    ///|
    let q = list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue", "Yellow"],
    question_default=Some(AnswerValue::IntValue(0)),
    )

    #rawlist

    创建带数字前缀的列表选择问题。

    pub fn rawlist(
    question_name~ : String,
    question_message~ : String,
    question_choices~ : Array[String],
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_choices~ : Array[String] - 选项数组
    • question_default? : AnswerValue? - 可选的默认选项索引

    返回值: 返回用户选择的选项值:AnswerValue::StringValue("selected_option")

    示例:
    ///|
    let q = rawlist(question_name="action", question_message="Select an action:", question_choices=[
    "Run", "Debug", "Build", "Test",
    ])

    #expand

    创建展开式选择问题(按字母选择)。

    pub fn expand(
    question_name~ : String,
    question_message~ : String,
    question_choices~ : Array[String],
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_choices~ : Array[String] - 选项数组
    • question_default? : AnswerValue? - 可选的默认选项索引

    返回值: 返回用户选择的选项值:AnswerValue::StringValue("selected_option")

    示例:
    ///|
    let q = expand(
    question_name="format",
    question_message="Select output format:",
    question_choices=["JSON", "XML", "YAML"],
    )

    #checkbox

    创建多选框问题(可选择多个选项)。

    pub fn checkbox(
    question_name~ : String,
    question_message~ : String,
    question_choices~ : Array[String],
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_choices~ : Array[String] - 选项数组
    • question_default? : AnswerValue? - 可选的默认选项

    返回值: 返回用户选择的选项数组:AnswerValue::ArrayValue(["option1", "option2"])

    示例:
    ///|
    let q = checkbox(
    question_name="hobbies",
    question_message="Select your hobbies:",
    question_choices=["Reading", "Gaming", "Sports", "Music"],
    )

    #password

    创建密码输入问题(输入不可见)。

    pub fn password(
    question_name~ : String,
    question_message~ : String,
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_default? : AnswerValue? - 可选的默认值

    返回值: 返回输入的密码:AnswerValue::StringValue("password")

    示例:
    ///|
    let q = password(question_name="pwd", question_message="Enter your password:")

    #editor

    创建多行文本输入问题。

    pub fn editor(
    question_name~ : String,
    question_message~ : String,
    question_default? : AnswerValue? = None
    ) -> Question

    参数:
    • question_name~ : String - 问题名称
    • question_message~ : String - 问题文本
    • question_default? : AnswerValue? - 可选的默认值

    返回值: 返回输入的文本:AnswerValue::StringValue("multiline text")

    示例:
    ///|
    let q = editor(
    question_name="bio",
    question_message="Write your bio:",
    question_default=Some(AnswerValue::StringValue("No bio provided")),
    )

    #数据类型

    #QuestionType

    问题的类型枚举。

    ///|
    pub enum QuestionType {
    Input // 文本输入
    Confirm // 确认(是/否)
    List // 列表选择
    RawList // 带数字的列表选择
    Expand // 展开式选择
    Checkbox // 多选框
    Password // 密码输入
    Editor // 多行文本输入
    }

    #AnswerValue

    问题答案的值类型枚举。

    ///|
    pub enum AnswerValue {
    StringValue(String) // 字符串值(Input、List、Password、Editor)
    BoolValue(Bool) // 布尔值(Confirm)
    ArrayValue(Array[String]) // 数组值(Checkbox)
    IntValue(Int) // 整数值(用于指定默认选项索引)
    }

    #Answer

    答案映射类型。

    ///|
    pub type Answer = Map[String, AnswerValue]

    用于存储问题名称到答案值的映射。

    #Question

    问题结构体定义。

    ///|
    pub struct Question {
    question_type : QuestionType // 问题类型
    question_name : String // 问题名称(用于获取答案)
    question_message : String // 问题文本
    question_default : AnswerValue? // 可选的默认值
    question_choices : Array[String]? // 可选的选项列表
    }

    #工具函数

    #parse_int

    将字符串解析为整数。

    pub fn parse_int(s : String) -> Int?

    参数:
    • s : String - 要解析的字符串

    返回值:
    • Some(Int) - 解析成功
    • None - 解析失败

    示例:
    match parse_int("123") {
    Some(n) => println("Number: \{n}")
    None => println("Not a number")
    }

    #完整示例

    import { "wangmingfa/promptx" }
    import { "moonbitlang/async" }

    async fn main {
    println("=== MoonBit Inquirer Demo ===\n")

    let questions : Array[Question] = [
    // 文本输入
    input(
    question_name="username",
    question_message="What is your name?"
    ),

    // 确认问题
    confirm(
    question_name="subscribe",
    question_message="Do you want to subscribe to our newsletter?",
    question_default=Some(AnswerValue::BoolValue(true))
    ),

    // 列表选择
    list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue", "Yellow", "Purple"],
    question_default=Some(AnswerValue::IntValue(0))
    ),

    // 多选框
    checkbox(
    question_name="hobbies",
    question_message="Select your hobbies:",
    question_choices=["Reading", "Gaming", "Sports", "Music", "Cooking"]
    ),

    // 密码输入
    password(
    question_name="password",
    question_message="Enter a password (optional)"
    ),

    // 多行文本
    editor(
    question_name="bio",
    question_message="Write a short bio (optional)"
    ),
    ]

    // 执行提示
    let answers = prompt(questions)

    // 显示结果
    println("\n=== Your Answers ===\n")

    match answers["username"] {
    AnswerValue::StringValue(name) =>
    if name.length() == 0 {
    println("Username: (empty)")
    } else {
    println("Username: \{name}")
    }
    _ => println("Username: (not provided)")
    }

    match answers["subscribe"] {
    AnswerValue::BoolValue(subscribed) =>
    if subscribed {
    println("Newsletter subscription: Yes")
    } else {
    println("Newsletter subscription: No")
    }
    _ => println("Newsletter subscription: (not provided)")
    }

    match answers["color"] {
    AnswerValue::StringValue(color) => println("Favorite color: \{color}")
    _ => println("Favorite color: (not selected)")
    }

    match answers["hobbies"] {
    AnswerValue::ArrayValue(hobbies) =>
    if hobbies.length() > 0 {
    println("Hobbies: \{hobbies.join(", ")}")
    } else {
    println("Hobbies: (none selected)")
    }
    _ => println("Hobbies: (none selected)")
    }

    match answers["password"] {
    AnswerValue::StringValue(pwd) =>
    if pwd.length() > 0 {
    println("Password: [hidden, length: \{pwd.length()} characters]")
    } else {
    println("Password: (empty)")
    }
    _ => println("Password: (not provided)")
    }

    match answers["bio"] {
    AnswerValue::StringValue(bio) =>
    if bio.length() == 0 {
    println("Bio: (empty)")
    } else {
    println("Bio: \{bio}")
    }
    _ => println("Bio: (not provided)")
    }

    println("\n=== Demo Complete ===")
    }

    #测试

    运行测试:

    moon test

    当前测试覆盖了:
    • ✅ 所有问题类型的创建
    • ✅ 答案值的类型匹配
    • ✅ parse_int函数
    • ✅ 辅助函数

    #开发状态

    • ✅ 核心类型定义
    • ✅ API设计
    • ✅ 单元测试
    • ✅ 交互式输入
    • ⏳ 验证和过滤功能
    • ⏳ 交互式选择界面(方向键、空格选择)

    #关于灵感来源

    MoonBit Inquirer 受到npm的Inquirer.js的启发。

    Inquirer.js 是一个非常优秀的Node.js交互式命令行界面库,为JavaScript开发者提供了优雅的方式来创建命令行问答界面。

    本项目旨在将Inquirer.js的核心概念和API设计引入MoonBit生态系统,让MoonBit开发者也能享受同样优雅的交互式命令行开发体验。

    致敬Inquirer.js团队的出色工作!

    #许可证

    Apache-2.0

    #贡献

    欢迎贡献代码!请提交Pull Request。

    Answer

    Mutable linked hash map that maintains the order of insertion, not thread safe.

    Example

    test {
    let map = { 3: "three", 8: "eight", 1: "one" }
    @test.assert_eq(map.get(2), None)
    @test.assert_eq(map.get(3), Some("three"))
    map.set(3, "updated")
    @test.assert_eq(map.get(3), Some("updated"))
    }

    AnswerValue

    MoonBit Inquirer

    一个用于MoonBit的命令行交互式问答库,灵感来自npm的Inquirer.js。

    功能特性

    MoonBit Inquirer提供优雅的方式来创建交互式命令行界面,支持以下问题类型:

    • Input: 文本输入
    • Confirm: 确认(是/否)
    • List: 列表选择
    • RawList: 带数字的列表选择
    • Expand: 展开式选择
    • Checkbox: 多选框
    • Password: 密码输入
    • Editor: 多行文本输入

    快速开始

    import { "wangmingfa/promptx" }
    import { "moonbitlang/async" }

    async fn main {
    // 创建问题数组
    let questions : Array[Question] = [
    input(
    question_name="username",
    question_message="What is your name?",
    question_default=Some(AnswerValue::StringValue("Guest"))
    ),
    confirm(
    question_name="subscribe",
    question_message="Do you want to subscribe?"
    ),
    list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue"]
    ),
    ]

    // 执行提示并获取答案
    let answers = prompt(questions)

    // 处理答案
    match answers["username"] {
    AnswerValue::StringValue(name) => println("Hello, \{name}!")
    _ => println("Hello, Guest!")
    }
    }

    Question

    MoonBit Inquirer

    一个用于MoonBit的命令行交互式问答库,灵感来自npm的Inquirer.js。

    功能特性

    MoonBit Inquirer提供优雅的方式来创建交互式命令行界面,支持以下问题类型:

    • Input: 文本输入
    • Confirm: 确认(是/否)
    • List: 列表选择
    • RawList: 带数字的列表选择
    • Expand: 展开式选择
    • Checkbox: 多选框
    • Password: 密码输入
    • Editor: 多行文本输入

    快速开始

    import { "wangmingfa/promptx" }
    import { "moonbitlang/async" }

    async fn main {
    // 创建问题数组
    let questions : Array[Question] = [
    input(
    question_name="username",
    question_message="What is your name?",
    question_default=Some(AnswerValue::StringValue("Guest"))
    ),
    confirm(
    question_name="subscribe",
    question_message="Do you want to subscribe?"
    ),
    list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue"]
    ),
    ]

    // 执行提示并获取答案
    let answers = prompt(questions)

    // 处理答案
    match answers["username"] {
    AnswerValue::StringValue(name) => println("Hello, \{name}!")
    _ => println("Hello, Guest!")
    }
    }

    QuestionType

    MoonBit Inquirer

    一个用于MoonBit的命令行交互式问答库,灵感来自npm的Inquirer.js。

    功能特性

    MoonBit Inquirer提供优雅的方式来创建交互式命令行界面,支持以下问题类型:

    • Input: 文本输入
    • Confirm: 确认(是/否)
    • List: 列表选择
    • RawList: 带数字的列表选择
    • Expand: 展开式选择
    • Checkbox: 多选框
    • Password: 密码输入
    • Editor: 多行文本输入

    快速开始

    import { "wangmingfa/promptx" }
    import { "moonbitlang/async" }

    async fn main {
    // 创建问题数组
    let questions : Array[Question] = [
    input(
    question_name="username",
    question_message="What is your name?",
    question_default=Some(AnswerValue::StringValue("Guest"))
    ),
    confirm(
    question_name="subscribe",
    question_message="Do you want to subscribe?"
    ),
    list(
    question_name="color",
    question_message="Choose your favorite color:",
    question_choices=["Red", "Green", "Blue"]
    ),
    ]

    // 执行提示并获取答案
    let answers = prompt(questions)

    // 处理答案
    match answers["username"] {
    AnswerValue::StringValue(name) => println("Hello, \{name}!")
    _ => println("Hello, Guest!")
    }
    }

    checkbox

    fn checkbox(question_name~ : String, question_message~ : String, question_choices~ : Array[String], question_default? :
    AnswerValue
    ?) ->
    Question

    confirm

    fn confirm(question_name~ : String, question_message~ : String, question_default? :
    AnswerValue
    ?) ->
    Question

    editor

    fn editor(question_name~ : String, question_message~ : String, question_default? :
    AnswerValue
    ?) ->
    Question

    expand

    fn expand(question_name~ : String, question_message~ : String, question_choices~ : Array[String], question_default? :
    AnswerValue
    ?) ->
    Question

    input

    fn input(question_name~ : String, question_message~ : String, question_default? :
    AnswerValue
    ?) ->
    Question

    list

    fn list(question_name~ : String, question_message~ : String, question_choices~ : Array[String], question_default? :
    AnswerValue
    ?) ->
    Question

    parse_int

    fn parse_int(s : String) -> Int?

    Alias for backwards compatibility

    password

    fn password(question_name~ : String, question_message~ : String, question_default? :
    AnswerValue
    ?) ->
    Question

    prompt

    Interactive prompt implementation using async I/O.

    This module provides the core prompt function and helper utilities. Note: In MoonBit, async functions are called like regular functions - they automatically wait for completion when called from another async function.

    rawlist

    fn rawlist(question_name~ : String, question_message~ : String, question_choices~ : Array[String], question_default? :
    AnswerValue
    ?) ->
    Question

    Source Files