Promptui를 사용하여 Go에서 중첩된 프롬프트

王林
풀어 주다: 2024-07-17 20:22:42
원래의
1147명이 탐색했습니다.

저는 최근 Cobra 도구를 사용하여 Go로 작성된 CLI 도구를 작업하고 있었는데, 명령 중 하나에 대해 중첩된 프롬프트가 필요한 사용 사례가 있었습니다. 프롬프트에 프롬프트 UI를 사용하고 있었는데 이를 수행하는 간단한 방법을 찾을 수 없었습니다. 이 짧은 게시물에서는 프롬프트 UI를 사용하여 중첩된 프롬프트를 만드는 방법을 보여줍니다. 완성된 코드는 여기에서 확인하실 수 있습니다.

먼저 빈 Go 프로젝트를 만들어야 합니다. 이를 중첩 프롬프트라고 부릅니다.

$ mkdir nested-prompt && cd nested-prompt
$ go mod init github.com/Thwani47/nested-prompt 
로그인 후 복사

그런 다음 cobra, cobra-cli 및 프롬프트 UI 패키지를 설치합니다.

$ go get -u github.com/spf13/cobra@latest
$ go install github.com/spf13/cobra-cli@latest 
$ go get -u github.com/manifoldco/promptui
로그인 후 복사

cobra-cli를 사용하여 새 CLI 애플리케이션을 초기화하고 CLI에 명령을 추가할 수 있습니다

$ cobra-cli init            # initializes a new CLI application
$ cobra-cli add config      # adds a new command to the CLI named 'config'
로그인 후 복사

cmd/config.go 파일을 정리하고 모든 주석을 제거할 수 있습니다. 다음과 같아야 합니다:

// cmd/config.go
package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

var configCmd = &cobra.Command{
    Use:   "config",
    Short: "Configure settings for the application",
    Long: `Configure settings for the application`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("config called")
    },
}

func init() {
    rootCmd.AddCommand(configCmd)
}

로그인 후 복사

먼저 프롬프트에 대한 사용자 정의 유형을 만들어야 합니다. 다음과 같이 PromptItem 구조체를 정의하여 이를 수행합니다

type PromptType int

const (
    TextPrompt     PromptType = 0
    PasswordPrompt PromptType = 1
    SelectPrompt   PromptType = 2
)

type promptItem struct {
    ID            string
    Label         string
    Value         string
    SelectOptions []string
    promptType    PromptType
}
로그인 후 복사

PromptType 열거형을 사용하면 프롬프트에서 다양한 유형의 입력을 수집할 수 있습니다. 사용자에게 텍스트 또는 비밀번호나 API 키와 같은 민감한 값을 입력하라는 메시지를 표시하거나 정의된 값 목록에서 사용자에게 선택하라는 메시지를 표시할 수 있습니다.

그런 다음 사용자의 입력을 요청하는 프롬프트Input 함수를 정의합니다. 이 함수는 사용자가 입력한 문자열 값을 반환하거나 프롬프트가 실패할 경우 오류를 반환합니다.

func promptInput(item promptItem) (string, error) {
    prompt := promptui.Prompt{
        Label:       item.Label,
        HideEntered: true,
    }

    if item.promptType == PasswordPrompt {
        prompt.Mask = '*'
    }

    res, err := prompt.Run()

    if err != nil {
        fmt.Printf("Prompt failed %v\n", err)
        return "", err
    }

    return res, nil
}
로그인 후 복사

그런 다음 사용자가 옵션 목록에서 선택할 수 있도록 하는 PromptSelect 함수를 정의합니다. 이 함수는 사용자가 선택한 문자열 값을 반환하거나 프롬프트가 실패할 경우 오류를 반환합니다.

func promptSelect(item selectItem) (string, error) {
    prompt := promptui.Select{
        Label:        item.Label,
        Items:        item.SelectValues,
        HideSelected: true,
    }

    _, result, err := prompt.Run()

    if err != nil {
        fmt.Printf("Prompt failed %v\n", err)
        return "", err
    }

    return result, nil
}
로그인 후 복사

중첩된 프롬프트를 시뮬레이션하기 위해 사용자에게 값을 묻는 메시지를 표시하고 사용자가 "완료"를 선택할 때까지 프롬프트가 활성 상태로 유지되는 프롬프트Nested 함수를 만듭니다. 이 함수는 프롬프트가 성공했음을 나타내는 부울 값을 반환합니다.

함수의 주석은 각 주요 코드 블록이 담당하는 역할을 설명합니다

func promptNested(promptLabel string, startingIndex int, items []*promptItem) bool {

    // Add a "Done" option to the prompt if it does not exist
    doneID := "Done"
    if len(items) > 0 && items[0].ID != doneID {
        items = append([]*promptItem{{ID: doneID, Label: "Done"}}, items...)
    }

    templates := &promptui.SelectTemplates{
        Label:    "{{ . }}?",
        Active:   "\U0001F336 {{ .Label | cyan }}",
        Inactive: "{{ .Label | cyan }}",
        Selected: "\U0001F336 {{ .Label | red  | cyan }}",
    }

    prompt := promptui.Select{
        Label:        promptLabel,
        Items:        items,
        Templates:    templates,
        Size:         3,
        HideSelected: true,
        CursorPos:    startingIndex, // Set the cursor to the last selected item
    }

    idx, _, err := prompt.Run()

    if err != nil {
        fmt.Printf("Error occurred when running prompt: %v\n", err)
        return false
    }

    selectedItem := items[idx]

    // if the user selects "Done", return true and exit from the function
    if selectedItem.ID == doneID {
        return true
    }

    var promptResponse string

    // if the prompt type is Text or Password, prompt the user for input
    if selectedItem.promptType == TextPrompt || selectedItem.promptType == PasswordPrompt {
        promptResponse, err = promptInput(*selectedItem)

        if err != nil {
            fmt.Printf("Error occurred when running prompt: %v\n", err)
            return false
        }

        items[idx].Value = promptResponse

    }

    // if the prompt type is Select, prompt the user to select from a list of options
    if selectedItem.promptType == SelectPrompt {
        promptResponse, err = promptSelect(*selectedItem)

        if err != nil {
            fmt.Printf("Error occurred when running prompt: %v\n", err)
            return false
        }
        items[idx].Value = promptResponse
    }

    if err != nil {
        fmt.Printf("Error occurred when running prompt: %v\n", err)
        return false
    }

    // recursively call the promptNested function to allow the user to select another option
    return promptNested(idx, items)
}
로그인 후 복사

이제 필요한 모든 방법이 준비되었으며 테스트해 봐야 합니다. configCmd 명령의 Run 함수 내에서 PromptItem 목록을 생성하고 PromptNested 함수를 호출하여 사용자에게 입력하라는 메시지를 표시합니다. Run 함수는 다음과 같습니다.

// create a list of prompt items
items := []*promptItem{
    {
        ID:         "APIKey",
        Label:      "API Key",
        promptType: PasswordPrompt,
    },
    {
        ID:            "Theme",
        Label:         "Theme",
        promptType:    SelectPrompt,
        SelectOptions: []string{"Dark", "Light"},
    },
    {
        ID:            "Language",
        Label:         "Preferred Language",
        promptType:    SelectPrompt,
        SelectOptions: []string{"English", "Spanish", "French", "German", "Chinese", "Japanese"},
    },
}

// set the starting index to 0 to start at the first item in the list
promptNested("Configuration Items", 0, items)

for _, v := range items {
    fmt.Printf("Saving configuration (%s) with value (%s)...\n", v.ID, v.Value)
}
로그인 후 복사

다음과 같이 애플리케이션을 빌드하고 테스트합니다

$ go build . 
$ ./nested-prompt config
로그인 후 복사

결과는 다음과 같습니다
Nested Prompts in Go using promptui

위 내용은 Promptui를 사용하여 Go에서 중첩된 프롬프트의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!