用於在支持ANSI逃生序列的終端上構建交互式和可訪問提示的庫。
嘿,大家!我終於想到了一個事實,即我再也無法花費足夠的時間來保持這個圖書館的活力。這個項目超過了我最瘋狂的期望,這是一個很棒的經歷。如果其他人想接管維護,請伸出援手
package main
import (
"fmt"
"github.com/AlecAivazis/survey/v2"
)
// the questions to ask
var qs = [] * survey. Question {
{
Name : "name" ,
Prompt : & survey. Input { Message : "What is your name?" },
Validate : survey . Required ,
Transform : survey . Title ,
},
{
Name : "color" ,
Prompt : & survey. Select {
Message : "Choose a color:" ,
Options : [] string { "red" , "blue" , "green" },
Default : "red" ,
},
},
{
Name : "age" ,
Prompt : & survey. Input { Message : "How old are you?" },
},
}
func main () {
// the answers will be written to this struct
answers := struct {
Name string // survey will match the question and field names
FavoriteColor string `survey:"color"` // or you can tag fields to match a specific name
Age int // if the types don't match, survey will convert it
}{}
// perform the questions
err := survey . Ask ( qs , & answers )
if err != nil {
fmt . Println ( err . Error ())
return
}
fmt . Printf ( "%s chose %s." , answers . Name , answers . FavoriteColor )
}示例可以在examples/目錄中找到。運行它們以查看基本行為:
go run examples/simple.go
go run examples/validation.go執行提示並開始向用戶收集信息的主要方法有兩種: Ask和AskOne 。主要區別是您是否有興趣收集一條信息,還是您有一個問題列表要詢問應將答案收集到單個結構中。對於大多數基本的用途, Ask應該就足夠了。但是,對於具有復雜分支邏輯的調查,我們建議您將問題分解為對這兩個功能的多個調用,以滿足您的需求。
大多數提示通過您實例化的結構上的字段進行細粒的配置。也可以通過通過AskOpts進行Ask或AskOne來更改調查的默認行為。本文檔中的示例既可以互換:
prompt := & Select {
Message : "Choose a color:" ,
Options : [] string { "red" , "blue" , "green" },
// can pass a validator directly
Validate : survey . Required ,
}
// or define a default for the single call to `AskOne`
// the answer will get written to the color variable
survey . AskOne ( prompt , & color , survey . WithValidator ( survey . Required ))
// or define a default for every entry in a list of questions
// the answer will get copied into the matching field of the struct as shown above
survey . Ask ( questions , & answers , survey . WithValidator ( survey . Required )) name := ""
prompt := & survey. Input {
Message : "ping" ,
}
survey . AskOne ( prompt , & name ) file := ""
prompt := & survey. Input {
Message : "inform a file to save:" ,
Suggest : func ( toComplete string ) [] string {
files , _ := filepath . Glob ( toComplete + "*" )
return files
},
}
}
survey . AskOne ( prompt , & file ) text := ""
prompt := & survey. Multiline {
Message : "ping" ,
}
survey . AskOne ( prompt , & text ) password := ""
prompt := & survey. Password {
Message : "Please type your password" ,
}
survey . AskOne ( prompt , & password ) name := false
prompt := & survey. Confirm {
Message : "Do you like pie?" ,
}
survey . AskOne ( prompt , & name ) color := ""
prompt := & survey. Select {
Message : "Choose a color:" ,
Options : [] string { "red" , "blue" , "green" },
}
survey . AskOne ( prompt , & color )來自Select提示的字段和值可能是兩種不同的事物之一。如果通過一個int則該字段將具有所選索引的值。如果您傳遞字符串,則選擇的字符串值將寫入字段。
用戶還可以按esc使用J和K鍵分別向下進行操作,以切換能力週期。
默認情況下,選擇提示只能一次顯示7個選項,並且會將選項的列表分頁率更長。這可以改變多種方式:
// as a field on a single select
prompt := & survey. MultiSelect { ... , PageSize : 10 }
// or as an option to Ask or AskOne
survey . AskOne ( prompt , & days , survey . WithPageSize ( 10 ))可選的說明文本可用於為選擇提示中列出的每個選項添加額外信息:
color := ""
prompt := & survey. Select {
Message : "Choose a color:" ,
Options : [] string { "red" , "blue" , "green" },
Description : func ( value string , index int ) string {
if value == "red" {
return "My favorite color"
}
return ""
},
}
survey . AskOne ( prompt , & color )
// Assuming that the user chose "red - My favorite color":
fmt . Println ( color ) //=> "red"
days := [] string {}
prompt := & survey. MultiSelect {
Message : "What days do you prefer:" ,
Options : [] string { "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" },
}
survey . AskOne ( prompt , & days )來自MultiSelect提示的字段和值可能是兩種不同的事情之一。如果通過一個int則該字段將具有所選索引的切片。相反,如果您傳遞字符串,則選擇的字符串值的切片將寫入字段。
用戶還可以按esc使用J和K鍵分別向下進行操作,以切換能力週期。
默認情況下,多電選擇提示只能一次顯示7個選項,並且會將選項的列表分頁率更長。這可以改變多種方式:
// as a field on a single select
prompt := & survey. MultiSelect { ... , PageSize : 10 }
// or as an option to Ask or AskOne
survey . AskOne ( prompt , & days , survey . WithPageSize ( 10 ))在臨時文件上啟動用戶的首選編輯器(由$ Visual或$ Editor環境變量定義)。用戶退出其編輯器後,結果將讀取臨時文件的內容。如果兩個都不存在,則使用記事本(在Windows上)或VIM(Linux或Mac)。
您還可以為臨時文件的名稱指定模式。這對於確保語法突出顯示與您的用例匹配可能很有用。
prompt := & survey. Editor {
Message : "Shell code snippet" ,
FileName : "*.sh" ,
}
survey . AskOne ( prompt , & content )默認情況下,用戶可以通過在提示處活動時鍵入SELECT和MultiSelect中的選項過濾。這將濾除所有不包含其名稱中任何位置的鍵入字符串的選項,忽略案例。
還可以提供自定義過濾功能以改變此行為:
func myFilter ( filterValue string , optValue string , optIndex int ) bool {
// only include the option if it includes the filter and has length greater than 5
return strings . Contains ( optValue , filterValue ) && len ( optValue ) >= 5
}
// configure it for a specific prompt
& Select {
Message : "Choose a color:" ,
Options : [] string { "red" , "blue" , "green" },
Filter : myFilter ,
}
// or define a default for all of the questions
survey . AskOne ( prompt , & color , survey . WithFilter ( myFilter ))默認情況下,如果用戶選擇過濾後的元素之一,則過濾器將消失。用戶選擇一個元素後,過濾器設置已消失。
但是,用戶可以防止這種情況發生,並使濾波器在多選中的多個選擇中保持活躍:
// configure it for a specific prompt
& Select {
Message : "Choose a color:" ,
Options : [] string { "light-green" , "green" , "dark-green" , "red" },
KeepFilter : true ,
}
// or define a default for all of the questions
survey . AskOne ( prompt , & color , survey . WithKeepFilter ( true ))可以通過在survey.Question中定義Validate字段來驗證對特定問題的響應。此功能採用interface{}類型並返回錯誤以顯示給用戶,並提示他們進行其他響應。像往常一樣,可以直接向提示或survey.WithValidator提供驗證器。
q := & survey. Question {
Prompt : & survey. Input { Message : "Hello world validation" },
Validate : func ( val interface {}) error {
// since we are validating an Input, the assertion will always succeed
if str , ok := val .( string ) ; ! ok || len ( str ) > 10 {
return errors . New ( "This response cannot be longer than 10 characters." )
}
return nil
},
}
color := ""
prompt := & survey. Input { Message : "Whats your name?" }
// you can pass multiple validators here and survey will make sure each one passes
survey . AskOne ( prompt , & color , survey . WithValidator ( survey . Required ))survey與一些驗證器預先包裝以適應常見情況。當前這些驗證器包括:
| 姓名 | 有效類型 | 描述 | 筆記 |
|---|---|---|---|
| 必需的 | 任何 | 拒絕響應類型的零值 | 布爾值直接通過,因為零值(false)是有效的響應 |
| 最小長度(n) | 細繩 | 強制執行響應至少是給定的長度 | |
| 最大長度(n) | 細繩 | 強制執行響應不超過給定的長度 | |
| 最大值(n) | [] optionanswer | 強制執行響應不再選擇指示的 | |
| Minitems(n) | [] optionanswer | 強制執行響應對所指示的選擇不少 |
所有提示都有一個Help字段,可以定義為您的用戶提供更多信息:
& survey. Input {
Message : "What is your phone number:" ,
Help : "Phone number should include the area code" ,
}默認情況下,用戶可以使用正確的箭頭鍵選擇所有多選項。為了防止用戶能夠執行此操作(並從提示符中刪除<right> to all消息),請使用WithRemoveSelectAll選項:
import (
"github.com/AlecAivazis/survey/v2"
)
number := ""
prompt := & survey. Input {
Message : "This question has the select all option removed" ,
}
survey . AskOne ( prompt , & number , survey . WithRemoveSelectAll ())同樣,默認情況下,用戶可以使用左箭頭鍵來取消所有選項。為了防止用戶能夠執行此操作(並從提示符中刪除<left> to none消息),請使用WithRemoveSelectNone選項:
import (
"github.com/AlecAivazis/survey/v2"
)
number := ""
prompt := & survey. Input {
Message : "This question has the select all option removed" ,
}
survey . AskOne ( prompt , & number , survey . WithRemoveSelectNone ())在某些情況下?是一個完全有效的響應。為了處理這一點,您可以使用WithHelpInput更改調查的符文:
import (
"github.com/AlecAivazis/survey/v2"
)
number := ""
prompt := & survey. Input {
Message : "If you have this need, please give me a reasonable message." ,
Help : "I couldn't come up with one." ,
}
survey . AskOne ( prompt , & number , survey . WithHelpInput ( '^' ))更改圖標及其顏色/格式可以通過WithIcons選項來完成。格式遵循此處概述的模式。例如:
import (
"github.com/AlecAivazis/survey/v2"
)
number := ""
prompt := & survey. Input {
Message : "If you have this need, please give me a reasonable message." ,
Help : "I couldn't come up with one." ,
}
survey . AskOne ( prompt , & number , survey . WithIcons ( func ( icons * survey. IconSet ) {
// you can set any icons
icons . Question . Text = "⁇"
// for more information on formatting the icons, see here: https://github.com/mgutz/ansi#style-format
icons . Question . Format = "yellow+hb"
}))圖標及其默認文本和格式如下:
| 姓名 | 文字 | 格式 | 描述 |
|---|---|---|---|
| 錯誤 | x | 紅色的 | 錯誤之前 |
| 幫助 | 我 | 青色 | 在幫助文本之前 |
| 問題 | ? | 綠色+HB | 提示之前 |
| SelectFocus | > | 綠色的 | 標記當前的Select和MultiSelect提示中的重點 |
| 未標記 | [] | 默認+HB | 在MultiSelect提示中標記未選擇的選項 |
| 標記 | [x] | 青色+b | 在MultiSelect提示中標記選擇的選擇 |
調查將對您的自定義類型的及時答案分配此接口:
type Settable interface {
WriteAnswer ( field string , value interface {}) error
}這是一個如何使用它們的示例:
type MyValue struct {
value string
}
func ( my * MyValue ) WriteAnswer ( name string , value interface {}) error {
my . value = value .( string )
}
myval := MyValue {}
survey . AskOne (
& survey. Input {
Message : "Enter something:" ,
},
& myval
)您可以使用Go-evect測試程序的交互提示。該庫可用於期望在Stdout上進行匹配並在STDIN上做出響應。由於os.Stdout在go test過程中不是TTY,因此,如果您正在操縱光標或使用survey ,則需要一種解釋CursorLocation之類的終端 / ANSI逃生序列的方法。 vt10x.NewVT10XConsole將創建一個go-expect Console,該控制台還將STDIO多重到內存虛擬終端。
對於一些示例,您可以在此存儲庫中看到任何測試。
survey支持哪些IO?調查旨在支持大多數終端模擬器;它預計支持ANSI逃生序列。這意味著不支持從管道的stdin或寫作到管道的Stdout的閱讀,並且在這些情況下可能會破壞您的應用程序。參見#337
通常,當您鍵入CTRL-C時,終端將其識別為退出按鈕,並將Sigint信號傳遞到該過程,從而終止它。但是,調查會臨時配置終端以將控制代碼作為普通輸入字節傳遞。當調查讀取A ^c字節(ASCII X03,“文本的結尾”)時,它會中斷當前的調查並返回github.com/AlecAivazis/survey/v2/terminal.InterruptErr from Ask或AskOne 。如果要停止該過程,請處理代碼中返回的錯誤:
err := survey . AskOne ( prompt , & myVar )
if err != nil {
if err == terminal. InterruptErr {
log . Fatal ( "interrupted" )
}
...
}