간단한 CUI 힌트를 만들어 보도록 하겠습니다.
36183 단어 Goprogrammingtech
이 보도를 본 후, 나는 수중자체 제작 도구가 업데이트되었습니다.에서 이번에 보살핌을 받은 zetamatta/go-readline-ny 포장에 대해 진일보한 발굴과 소개를 진행하였다.
go-readline-ny에는 다음과 같은 특징이 있습니다.
C-w
또는 C-y
등을 사용할 수 있음mattn/go-colorable와 함께 사용
context 표준 패키지 지원
간이 힌트bufio로 표준 포장bufio을 사용했다.Scanner는 유명합니다.입력 흐름을 선택하지 않는 것이 장점이지만 단행 편집, 입력에 대해서는 기본적인 기능, 예를 들어 배공간 등만 제공한다.
또 위"지령선 조개?? 누구나 할 수 있어요."에서 소개mattn/go-tty했는데, 이걸 사용하면 RAW 모드에서 상당히 원시적인 조작이 가능할 것 같은데'간편한 CUI 힌트를 간단하게 조립하고 싶다'는 상황에서 조금 이상하다는 생각이 들었다.go-readline-ny라면
text, err := (&readline.Editor{}).ReadLine(context.Background())
도 정상적으로 작동할 수 있다.너무 좋아요!따라서 go-readline-ny를 사용하여 간단한 CUI 프롬프트를 설정합니다.
우선 다음과 같은 함수를 고려한다.
func Reverse(r []rune) []rune {
if len(r) > 1 {
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
}
return r
}
이것은 간단한 작업으로 런을 반대로 배열하기만 하면 된다.단순 CUI 프롬프트에 입력한 문자열을 함수로 반전[1]합니다.이런 느낌의 코드는 어때요?sample1.go
func main() {
//input
text, err := (&readline.Editor{
Prompt: func() (int, error) { return fmt.Print("> ") },
}).ReadLine(context.Background())
if err != nil {
fmt.Fprintln(os.Stderr, errPrint(err))
return
}
//output
fmt.Println(string(Reverse([]rune(text))))
}
참고로 errprint () 함수는func errPrint(err error) string {
if err == nil {
return ""
}
switch {
case errors.Is(err, readline.CtrlC):
return "処理を中断します"
case errors.Is(err, io.EOF):
return "処理を終了します"
default:
return err.Error()
}
}
는 검사Ctrl+C
와 Ctrl+D
의 함수다.이걸 수행하면...
결과
$ go run sample1.go
> あいうえお
おえういあ
.응, 응.잘 반전하고 있어.다음에 이 알림을 반복해서 실행하기 위해 코드를 변경해 보십시오.더욱 효과적인 간이 역사 기능.
sample2.go
func main() {
history := simplehistory.New()
editor := readline.Editor{
Prompt: func() (int, error) { return fmt.Print("> ") },
History: history,
}
fmt.Println("Input Ctrl+D to stop.")
for {
//input
text, err := editor.ReadLine(context.Background())
if err != nil {
fmt.Fprintln(os.Stderr, errPrint(err))
return
}
//output
fmt.Println(string(Reverse([]rune(text))))
//add history
history.Add(text)
}
return
}
또한 역사 제어용 대상은 zetamatta/go-readline-ny/simplehistory 포장을 사용합니다.이걸 수행하면...$ go run sample2.go
Input Ctrl+D to stop.
> あいうえお
おえういあ
> しんぶんし
しんぶんし
>
処理を終了します
이런 느낌(마지막으로Ctrl+D
으로 끝난다).참고로 위아래 커서는 역사를 표시할 수 있다.버건디!사실readline.Editor 유형은
history.go
type Editor struct {
KeyMap
History IHistory
Writer io.Writer
Out *bufio.Writer
Prompt func() (int, error)
Default string
Cursor int
LineFeed func(Result)
OpenKeyGetter func() (KeyGetter, error)
}
의 IHistory형history.go
type IHistory interface {
Len() int
At(int) string
}
인터페이스형이랑.그러니까 이거readline.IHistory형 구성이 충족되면 자체 제작된 역사형도 사용할 수 있다.저기 있다
sample3.go
const (
max = 50
logfile = "history.log"
)
type History struct {
buffer []string
}
var _ readline.IHistory = (*History)(nil) //compiler hint
func New() (*History, error) {
history := &History{buffer: []string{}}
file, err := os.Open(logfile)
if err != nil {
return history, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
history.Add(scanner.Text())
}
return history, scanner.Err()
}
func (h *History) Len() int {
if h == nil {
return 0
}
return len(h.buffer)
}
func (h *History) At(n int) string {
if h == nil || h.Len() <= n {
return ""
}
return h.buffer[n]
}
func (h *History) Add(s string) {
if h == nil || len(s) == 0 {
return
}
if n := h.Len(); n < 1 {
h.buffer = append(h.buffer, s)
} else if h.buffer[n-1] != s {
h.buffer = append(h.buffer, s)
}
if n := h.Len(); n > max {
h.buffer = h.buffer[n-max:]
}
}
func (h *History) Save() error {
if h == nil {
return nil
}
file, err := os.Create(logfile)
if err != nil {
return err
}
defer file.Close()
for _, s := range h.buffer {
fmt.Fprintln(file, s)
}
return nil
}
유형과 방법[2].이것 괜찮아요?sample3.go
func main() {
history, err := New()
if err != nil {
fmt.Fprintln(os.Stderr, err)
//continue
}
editor := readline.Editor{
Prompt: func() (int, error) { return fmt.Print("> ") },
History: history,
}
fmt.Println("Input Ctrl+D to stop.")
for {
//input
text, err := editor.ReadLine(context.Background())
if err != nil {
fmt.Fprintln(os.Stderr, errPrint(err))
break
}
//output
fmt.Println(string(Reverse([]rune(text))))
//add history
history.Add(text)
}
if err := history.Save(); err != nil {
fmt.Fprintln(os.Stderr, err)
}
return
}
이 경우 최대 50개의 히스토리가 history.log
에 저장됩니다.전sample2.go
의 코드와 비교하기를 바랍니다.이렇게 go-readline-ny의 기본 기능이 제어되겠지.좀 더 놀자.
참고서
각주
엄밀히 말하면, 정렬은 '텍스트' 단위가 아니라 rune (Unicde 코드 점) 단위이다.이체자와 그림문자 등이 여러 코드를 합성할 때가 있는데 이번 코드로 반전시키면 귀찮을 것 같다(웃음)↩︎
사실 권투대 같은 걸 써야 하는데 이번에 게으름을 피웠어요.미안합니다, 컴퓨터.↩︎
Reference
이 문제에 관하여(간단한 CUI 힌트를 만들어 보도록 하겠습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/spiegel/articles/20210104-prompt텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)