Saya sedang mengusahakan alat CLI yang ditulis dalam Go, menggunakan alat Cobra baru-baru ini, dan saya mempunyai kes penggunaan di mana saya memerlukan gesaan bersarang untuk salah satu arahan. Saya menggunakan promptui untuk gesaan dan saya tidak dapat mencari cara yang mudah untuk melakukan ini. Catatan pendek ini akan menunjukkan cara membuat gesaan bersarang menggunakan promptui. Kod yang lengkap boleh didapati di sini.
Kita perlu membuat projek Go kosong dahulu. Kami akan memanggilnya nested-prompt:
$ mkdir nested-prompt && cd nested-prompt $ go mod init github.com/Thwani47/nested-prompt
Kami kemudian akan memasang pakej cobra, cobra-cli dan promptui:
$ go get -u github.com/spf13/cobra@latest $ go install github.com/spf13/cobra-cli@latest $ go get -u github.com/manifoldco/promptui
Kami boleh memulakan aplikasi CLI baharu menggunakan cobra-cli dan menambah arahan pada CLI kami
$ cobra-cli init # initializes a new CLI application $ cobra-cli add config # adds a new command to the CLI named 'config'
Kami boleh membersihkan fail cmd/config.go dan mengalih keluar semua komen. Sepatutnya begini:
// 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) }
Kami perlu membuat jenis tersuai terlebih dahulu untuk gesaan kami. Kami melakukannya dengan mentakrifkan struct promptItem seperti berikut
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 }
Enum PromptType membolehkan kami mengumpul pelbagai jenis input daripada gesaan kami, kami boleh menggesa pengguna untuk teks, atau nilai sensitif seperti kata laluan atau Kunci API, atau menggesa pengguna untuk memilih daripada senarai nilai yang ditentukan
Kami kemudiannya mentakrifkan fungsi promptInput yang akan meminta input daripada pengguna. Fungsi mengembalikan nilai rentetan yang dimasukkan oleh pengguna atau ralat jika gesaan gagal.
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 }
Kami kemudiannya mentakrifkan fungsi promptSelect yang membolehkan pengguna memilih daripada senarai pilihan. Fungsi mengembalikan nilai rentetan yang dipilih oleh pengguna atau ralat jika gesaan gagal.
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 }
Untuk mensimulasikan gesaan bersarang, kami akan mencipta fungsi promptNested yang akan membolehkan kami menggesa pengguna untuk nilai dan gesaan akan kekal aktif sehingga pengguna memilih "Selesai". Fungsi ini mengembalikan nilai boolean yang menunjukkan bahawa gesaan itu berjaya.
Komen dalam fungsi menerangkan perkara yang menjadi tanggungjawab setiap blok kod utama
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) }
Kini kami mempunyai semua kaedah yang kami perlukan dan kami perlu mengujinya. Di dalam fungsi Run perintah configCmd, kami akan membuat senarai promptItem dan memanggil fungsi promptNested untuk menggesa pengguna untuk input. Fungsi Run sepatutnya kelihatan seperti ini:
// 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) }
Bina dan uji aplikasi seperti berikut
$ go build . $ ./nested-prompt config
Hasilnya adalah seperti berikut
Atas ialah kandungan terperinci Gesaan Bersarang dalam Go menggunakan promptui. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!