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 and AskOne . 주요 차이점은 단일 정보 수집에 관심이 있는지 또는 단일 구조물로 답변을 수집 해야하는 질문 목록이 있는지 여부입니다. 대부분의 기본 usecases의 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 가지 옵션을 표시하는 것으로 제한되며 그보다 더 긴 옵션 목록을 페이지를 paginated합니다. 이것은 여러 가지 방법으로 변경 될 수 있습니다.
// 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 또는 $ 편집기 환경 변수에 의해 정의 됨)를 시작합니다. 사용자가 편집기를 종료하면 임시 파일의 내용을 결과적으로 읽습니다. 그 중 어느 것도 존재하지 않으면 메모장 (Windows) 또는 VIM (Linux 또는 Mac)이 사용됩니다.
임시 파일의 이름에 대한 패턴을 지정할 수도 있습니다. 이는 구문 강조 표시가 Usecase와 일치하도록하는 데 유용 할 수 있습니다.
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 일반적인 상황에 맞는 몇몇 유효성 검사기와 함께 전 포장됩니다. 현재 이러한 유효성 검사기에는 다음이 포함됩니다.
| 이름 | 유효한 유형 | 설명 | 메모 |
|---|---|---|---|
| 필수의 | 어느 | 응답 유형의 0 값을 거부합니다 | 0 값 (False)이 유효한 응답이기 때문에 부울 값은 곧바로 통과합니다. |
| 미네 길이 (n) | 끈 | 응답이 적어도 주어진 길이임을 시행합니다. | |
| MaxLength (N) | 끈 | 응답이 주어진 길이보다 더 이상 없음을 시행합니다. | |
| maxitems (n) | [] 선택 사항 | 응답에 표시된 선택이 더 이상 없음을 시행합니다. | |
| 미니 템 (n) | [] 선택 사항 | 응답이 표시된 선택의 선택이 없음을 시행합니다. |
모든 프롬프트에는 사용자에게 더 많은 정보를 제공하기 위해 정의 할 수있는 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"
}))아이콘과 기본 텍스트 및 형식은 다음과 같습니다.
| 이름 | 텍스트 | 체재 | 설명 |
|---|---|---|---|
| 오류 | 엑스 | 빨간색 | 오류 전에 |
| 돕다 | 나 | 시안 | 도움말 텍스트 전에 |
| 질문 | ? | 녹색+HB | 프롬프트의 메시지 전에 |
| SelectFocus | > | 녹색 | Select 및 MultiSelect 프롬프트에서 현재 초점을 표시합니다 |
| uncedoption | [] | 기본+HB | MultiSelect 프롬프트에서 선택되지 않은 옵션을 표시합니다 |
| 표시 | [엑스] | 시안+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-Expect를 사용하여 프로그램의 대화식 프롬프트를 테스트 할 수 있습니다. 라이브러리는 stdout에서 일치하고 Stdin에서 응답하는 데 사용될 수 있습니다. go test 프로세스에서 os.Stdout TTY가 아니기 때문에 커서를 조작하거나 survey 사용하는 경우 CursorLocation 와 같은 것들에 대해 터미널 / ANSI 탈출 시퀀스를 해석하는 방법이 필요합니다. vt10x.NewVT10XConsole memory 내 가상 터미널에 stdio를 멀티 플렉스하는 go-expect 콘솔을 만듭니다.
몇 가지 예에서는이 리포지토리에서 테스트를 볼 수 있습니다.
survey 통해 어떤 종류의 IO가 지원됩니까?설문 조사는 대부분의 터미널 에뮬레이터를 지원하는 것을 목표로합니다. ANSI 탈출 시퀀스에 대한 지원을 기대합니다. 이는 파이프가있는 stdin 또는 쓰기에서 Piped Stdout에 대한 읽기가 지원되지 않으며 이러한 상황에서 응용 프로그램을 중단 할 가능성이 있음을 의미합니다. #337을 참조하십시오
일반적으로 Ctrl-C를 입력하면 터미널은 이것을 quit 버튼으로 인식하고 Sigint 신호를 프로세스에 전달하여 종료합니다. 그러나 설문 조사를 통해 터미널을 일시적으로 구성하여 제어 코드를 일반 입력 바이트로 전달합니다. 설문 조사에서 A ^C Byte (ASCII x03, "End of Text")를 읽으면 현재 설문 조사를 중단하고 github.com/AlecAivazis/survey/v2/terminal.InterruptErr 을 Ask 또는 AskOne 에서 반환합니다. 프로세스를 중지하려면 코드에서 반환 된 오류를 처리합니다.
err := survey . AskOne ( prompt , & myVar )
if err != nil {
if err == terminal. InterruptErr {
log . Fatal ( "interrupted" )
}
...
}