From 20a62e0185ed495fffbe371df019013fd776e1f2 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Sat, 18 Jun 2022 03:53:46 +0900 Subject: [PATCH 1/4] convert locale string to utf-8 on Windows --- examples/go.sum | 4 ++++ go.mod | 2 ++ go.sum | 5 +++++ key.go | 10 ++++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/examples/go.sum b/examples/go.sum index e317b767c9..ab7a16eb71 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -33,6 +33,8 @@ github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= @@ -85,6 +87,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.mod b/go.mod index 8da123aa44..628391f77d 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,12 @@ go 1.13 require ( github.com/containerd/console v1.0.3 github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-localereader v0.0.1 github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b github.com/muesli/cancelreader v0.2.2 github.com/muesli/reflow v0.3.0 github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 + golang.org/x/text v0.3.7 // indirect ) diff --git a/go.sum b/go.sum index 7bb6610a7f..270f8f5db1 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -27,3 +29,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/key.go b/key.go index 5c2dac1486..07bc651930 100644 --- a/key.go +++ b/key.go @@ -5,6 +5,8 @@ import ( "fmt" "io" "unicode/utf8" + + "github.com/mattn/go-localereader" ) // KeyMsg contains information about a keypress. KeyMsgs are always sent to @@ -479,10 +481,15 @@ func readInputs(input io.Reader) ([]Msg, error) { if err != nil { return nil, err } + b := buf[:numBytes] + b, err = localereader.UTF8(b) + if err != nil { + return nil, err + } // Check if it's a mouse event. For now we're parsing X10-type mouse events // only. - mouseEvent, err := parseX10MouseEvents(buf[:numBytes]) + mouseEvent, err := parseX10MouseEvents(b) if err == nil { var m []Msg for _, v := range mouseEvent { @@ -493,7 +500,6 @@ func readInputs(input io.Reader) ([]Msg, error) { var runeSets [][]rune var runes []rune - b := buf[:numBytes] // Translate input into runes. In most cases we'll receive exactly one // rune, but there are cases, particularly when an input method editor is From a83e251ecd824d12413ceacf9919ba1b1a6f2653 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Sat, 18 Jun 2022 04:08:09 +0900 Subject: [PATCH 2/4] update go.mod --- tutorials/go.sum | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tutorials/go.sum b/tutorials/go.sum index 7bb6610a7f..270f8f5db1 100644 --- a/tutorials/go.sum +++ b/tutorials/go.sum @@ -5,6 +5,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -27,3 +29,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 0976d0e9e772d6f9f866b72da9b9655aa43725a8 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Sat, 18 Jun 2022 00:45:53 +0000 Subject: [PATCH 3/4] revert go fmt ./... --- commands.go | 118 ++++++++++++++++++++++++++-------------------------- exec.go | 12 +++--- key.go | 67 ++++++++++++++--------------- logging.go | 12 +++--- mouse.go | 2 +- options.go | 13 +++--- tea.go | 7 ++-- 7 files changed, 118 insertions(+), 113 deletions(-) diff --git a/commands.go b/commands.go index 91116388a3..99007b2ce2 100644 --- a/commands.go +++ b/commands.go @@ -19,38 +19,38 @@ import ( // To produce the command, pass a duration and a function which returns // a message containing the time at which the tick occurred. // -// type TickMsg time.Time +// type TickMsg time.Time // -// cmd := Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) +// cmd := Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) // // Beginners' note: Every sends a single message and won't automatically // dispatch messages at an interval. To do that, you'll want to return another // Every command after receiving your tick message. For example: // -// type TickMsg time.Time -// -// // Send a message every second. -// func tickEvery() Cmd { -// return Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return tickEvery() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Every command again to loop. -// return m, tickEvery() -// } -// return m, nil -// } +// type TickMsg time.Time +// +// // Send a message every second. +// func tickEvery() Cmd { +// return Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return tickEvery() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Every command again to loop. +// return m, tickEvery() +// } +// return m, nil +// } // // Every is analogous to Tick in the Elm Architecture. func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { @@ -69,37 +69,38 @@ func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { // To produce the command, pass a duration and a function which returns // a message containing the time at which the tick occurred. // -// type TickMsg time.Time +// type TickMsg time.Time // -// cmd := Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) +// cmd := Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) // // Beginners' note: Tick sends a single message and won't automatically // dispatch messages at an interval. To do that, you'll want to return another // Tick command after receiving your tick message. For example: // -// type TickMsg time.Time -// -// func doTick() Cmd { -// return Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return doTick() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Tick command again to loop. -// return m, doTick() -// } -// return m, nil -// } +// type TickMsg time.Time +// +// func doTick() Cmd { +// return Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return doTick() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Tick command again to loop. +// return m, doTick() +// } +// return m, nil +// } +// func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { return func() Msg { t := time.NewTimer(d) @@ -111,14 +112,15 @@ func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { // commands. // The Msg returned is the first non-nil message returned by a Cmd. // -// func saveStateCmd() Msg { -// if err := save(); err != nil { -// return errMsg{err} -// } -// return nil -// } +// func saveStateCmd() Msg { +// if err := save(); err != nil { +// return errMsg{err} +// } +// return nil +// } +// +// cmd := Sequentially(saveStateCmd, Quit) // -// cmd := Sequentially(saveStateCmd, Quit) func Sequentially(cmds ...Cmd) Cmd { return func() Msg { for _, cmd := range cmds { diff --git a/exec.go b/exec.go index 587d91a8ca..d1d9d69a29 100644 --- a/exec.go +++ b/exec.go @@ -34,17 +34,17 @@ func Exec(c ExecCommand, fn ExecCallback) Cmd { // a message containing the error which may have occurred when running the // ExecCommand. // -// type VimFinishedMsg struct { err error } +// type VimFinishedMsg struct { err error } // -// c := exec.Command("vim", "file.txt") +// c := exec.Command("vim", "file.txt") // -// cmd := ExecProcess(c, func(err error) Msg { -// return VimFinishedMsg{err: error} -// }) +// cmd := ExecProcess(c, func(err error) Msg { +// return VimFinishedMsg{err: error} +// }) // // Or, if you don't care about errors, you could simply: // -// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) +// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) // // For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). func ExecProcess(c *exec.Cmd, fn ExecCallback) Cmd { diff --git a/key.go b/key.go index 07bc651930..12446a2878 100644 --- a/key.go +++ b/key.go @@ -13,30 +13,30 @@ import ( // the program's update function. There are a couple general patterns you could // use to check for keypresses: // -// // Switch on the string representation of the key (shorter) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.String() { -// case "enter": -// fmt.Println("you pressed enter!") -// case "a": -// fmt.Println("you pressed a!") -// } -// } +// // Switch on the string representation of the key (shorter) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.String() { +// case "enter": +// fmt.Println("you pressed enter!") +// case "a": +// fmt.Println("you pressed a!") +// } +// } // -// // Switch on the key type (more foolproof) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.Type { -// case KeyEnter: -// fmt.Println("you pressed enter!") -// case KeyRunes: -// switch string(msg.Runes) { -// case "a": -// fmt.Println("you pressed a!") -// } -// } -// } +// // Switch on the key type (more foolproof) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.Type { +// case KeyEnter: +// fmt.Println("you pressed enter!") +// case KeyRunes: +// switch string(msg.Runes) { +// case "a": +// fmt.Println("you pressed a!") +// } +// } +// } // // Note that Key.Runes will always contain at least one character, so you can // always safely call Key.Runes[0]. In most cases Key.Runes will only contain @@ -60,9 +60,10 @@ type Key struct { // String returns a friendly string representation for a key. It's safe (and // encouraged) for use in key comparison. // -// k := Key{Type: KeyEnter} -// fmt.Println(k) -// // Output: enter +// k := Key{Type: KeyEnter} +// fmt.Println(k) +// // Output: enter +// func (k Key) String() (str string) { if k.Alt { str += "alt+" @@ -81,16 +82,16 @@ func (k Key) String() (str string) { // All other keys will be type KeyRunes. To get the rune value, check the Rune // method on a Key struct, or use the Key.String() method: // -// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} -// if k.Type == KeyRunes { +// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} +// if k.Type == KeyRunes { // -// fmt.Println(k.Runes) -// // Output: a +// fmt.Println(k.Runes) +// // Output: a // -// fmt.Println(k.String()) -// // Output: alt+a +// fmt.Println(k.String()) +// // Output: alt+a // -// } +// } type KeyType int func (k KeyType) String() (str string) { diff --git a/logging.go b/logging.go index 54a4350aca..bca66ca5a2 100644 --- a/logging.go +++ b/logging.go @@ -12,12 +12,12 @@ import ( // // Don't forget to close the file when you're done with it. // -// f, err := LogToFile("debug.log", "debug") -// if err != nil { -// fmt.Println("fatal:", err) -// os.Exit(1) -// } -// defer f.Close() +// f, err := LogToFile("debug.log", "debug") +// if err != nil { +// fmt.Println("fatal:", err) +// os.Exit(1) +// } +// defer f.Close() func LogToFile(path string, prefix string) (*os.File, error) { f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { diff --git a/mouse.go b/mouse.go index 5ff3a2faf0..5fb7427c9c 100644 --- a/mouse.go +++ b/mouse.go @@ -63,7 +63,7 @@ var mouseEventTypes = map[MouseEventType]string{ // // X10 mouse events look like: // -// ESC [M Cb Cx Cy +// ESC [M Cb Cx Cy // // See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking func parseX10MouseEvents(buf []byte) ([]MouseEvent, error) { diff --git a/options.go b/options.go index b60d23c232..09e5ecbd73 100644 --- a/options.go +++ b/options.go @@ -7,7 +7,8 @@ import "io" // // Example usage: // -// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) +// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) +// type ProgramOption func(*Program) // WithOutput sets the output which, by default, is stdout. In most cases you @@ -50,11 +51,11 @@ func WithoutCatchPanics() ProgramOption { // // Example: // -// p := tea.NewProgram(Model{}, tea.WithAltScreen()) -// if err := p.Start(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } +// p := tea.NewProgram(Model{}, tea.WithAltScreen()) +// if err := p.Start(); err != nil { +// fmt.Println("Error running program:", err) +// os.Exit(1) +// } // // To enter the altscreen once the program has already started running use the // EnterAltScreen command. diff --git a/tea.go b/tea.go index 28065a007f..59b48f9354 100644 --- a/tea.go +++ b/tea.go @@ -124,9 +124,10 @@ type Program struct { // // Example: // -// func (m model) Init() Cmd { -// return tea.Batch(someCommand, someOtherCommand) -// } +// func (m model) Init() Cmd { +// return tea.Batch(someCommand, someOtherCommand) +// } +// func Batch(cmds ...Cmd) Cmd { var validCmds []Cmd for _, c := range cmds { From c053dd4bdb6317056c74c5f097c69ca6cb178141 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Fri, 19 Aug 2022 09:23:13 -0700 Subject: [PATCH 4/4] fix(lint): use tabs in GoDoc example code --- commands.go | 118 ++++++++++++++++++++++++++-------------------------- exec.go | 12 +++--- key.go | 67 +++++++++++++++-------------- logging.go | 12 +++--- mouse.go | 2 +- options.go | 13 +++--- tea.go | 7 ++-- 7 files changed, 113 insertions(+), 118 deletions(-) diff --git a/commands.go b/commands.go index 99007b2ce2..91116388a3 100644 --- a/commands.go +++ b/commands.go @@ -19,38 +19,38 @@ import ( // To produce the command, pass a duration and a function which returns // a message containing the time at which the tick occurred. // -// type TickMsg time.Time +// type TickMsg time.Time // -// cmd := Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) +// cmd := Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) // // Beginners' note: Every sends a single message and won't automatically // dispatch messages at an interval. To do that, you'll want to return another // Every command after receiving your tick message. For example: // -// type TickMsg time.Time -// -// // Send a message every second. -// func tickEvery() Cmd { -// return Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return tickEvery() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Every command again to loop. -// return m, tickEvery() -// } -// return m, nil -// } +// type TickMsg time.Time +// +// // Send a message every second. +// func tickEvery() Cmd { +// return Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return tickEvery() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Every command again to loop. +// return m, tickEvery() +// } +// return m, nil +// } // // Every is analogous to Tick in the Elm Architecture. func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { @@ -69,38 +69,37 @@ func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { // To produce the command, pass a duration and a function which returns // a message containing the time at which the tick occurred. // -// type TickMsg time.Time +// type TickMsg time.Time // -// cmd := Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) +// cmd := Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) // // Beginners' note: Tick sends a single message and won't automatically // dispatch messages at an interval. To do that, you'll want to return another // Tick command after receiving your tick message. For example: // -// type TickMsg time.Time -// -// func doTick() Cmd { -// return Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return doTick() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Tick command again to loop. -// return m, doTick() -// } -// return m, nil -// } -// +// type TickMsg time.Time +// +// func doTick() Cmd { +// return Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return doTick() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Tick command again to loop. +// return m, doTick() +// } +// return m, nil +// } func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { return func() Msg { t := time.NewTimer(d) @@ -112,15 +111,14 @@ func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { // commands. // The Msg returned is the first non-nil message returned by a Cmd. // -// func saveStateCmd() Msg { -// if err := save(); err != nil { -// return errMsg{err} -// } -// return nil -// } -// -// cmd := Sequentially(saveStateCmd, Quit) +// func saveStateCmd() Msg { +// if err := save(); err != nil { +// return errMsg{err} +// } +// return nil +// } // +// cmd := Sequentially(saveStateCmd, Quit) func Sequentially(cmds ...Cmd) Cmd { return func() Msg { for _, cmd := range cmds { diff --git a/exec.go b/exec.go index d1d9d69a29..587d91a8ca 100644 --- a/exec.go +++ b/exec.go @@ -34,17 +34,17 @@ func Exec(c ExecCommand, fn ExecCallback) Cmd { // a message containing the error which may have occurred when running the // ExecCommand. // -// type VimFinishedMsg struct { err error } +// type VimFinishedMsg struct { err error } // -// c := exec.Command("vim", "file.txt") +// c := exec.Command("vim", "file.txt") // -// cmd := ExecProcess(c, func(err error) Msg { -// return VimFinishedMsg{err: error} -// }) +// cmd := ExecProcess(c, func(err error) Msg { +// return VimFinishedMsg{err: error} +// }) // // Or, if you don't care about errors, you could simply: // -// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) +// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) // // For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). func ExecProcess(c *exec.Cmd, fn ExecCallback) Cmd { diff --git a/key.go b/key.go index 12446a2878..07bc651930 100644 --- a/key.go +++ b/key.go @@ -13,30 +13,30 @@ import ( // the program's update function. There are a couple general patterns you could // use to check for keypresses: // -// // Switch on the string representation of the key (shorter) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.String() { -// case "enter": -// fmt.Println("you pressed enter!") -// case "a": -// fmt.Println("you pressed a!") -// } -// } +// // Switch on the string representation of the key (shorter) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.String() { +// case "enter": +// fmt.Println("you pressed enter!") +// case "a": +// fmt.Println("you pressed a!") +// } +// } // -// // Switch on the key type (more foolproof) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.Type { -// case KeyEnter: -// fmt.Println("you pressed enter!") -// case KeyRunes: -// switch string(msg.Runes) { -// case "a": -// fmt.Println("you pressed a!") -// } -// } -// } +// // Switch on the key type (more foolproof) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.Type { +// case KeyEnter: +// fmt.Println("you pressed enter!") +// case KeyRunes: +// switch string(msg.Runes) { +// case "a": +// fmt.Println("you pressed a!") +// } +// } +// } // // Note that Key.Runes will always contain at least one character, so you can // always safely call Key.Runes[0]. In most cases Key.Runes will only contain @@ -60,10 +60,9 @@ type Key struct { // String returns a friendly string representation for a key. It's safe (and // encouraged) for use in key comparison. // -// k := Key{Type: KeyEnter} -// fmt.Println(k) -// // Output: enter -// +// k := Key{Type: KeyEnter} +// fmt.Println(k) +// // Output: enter func (k Key) String() (str string) { if k.Alt { str += "alt+" @@ -82,16 +81,16 @@ func (k Key) String() (str string) { // All other keys will be type KeyRunes. To get the rune value, check the Rune // method on a Key struct, or use the Key.String() method: // -// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} -// if k.Type == KeyRunes { +// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} +// if k.Type == KeyRunes { // -// fmt.Println(k.Runes) -// // Output: a +// fmt.Println(k.Runes) +// // Output: a // -// fmt.Println(k.String()) -// // Output: alt+a +// fmt.Println(k.String()) +// // Output: alt+a // -// } +// } type KeyType int func (k KeyType) String() (str string) { diff --git a/logging.go b/logging.go index bca66ca5a2..54a4350aca 100644 --- a/logging.go +++ b/logging.go @@ -12,12 +12,12 @@ import ( // // Don't forget to close the file when you're done with it. // -// f, err := LogToFile("debug.log", "debug") -// if err != nil { -// fmt.Println("fatal:", err) -// os.Exit(1) -// } -// defer f.Close() +// f, err := LogToFile("debug.log", "debug") +// if err != nil { +// fmt.Println("fatal:", err) +// os.Exit(1) +// } +// defer f.Close() func LogToFile(path string, prefix string) (*os.File, error) { f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { diff --git a/mouse.go b/mouse.go index 5fb7427c9c..5ff3a2faf0 100644 --- a/mouse.go +++ b/mouse.go @@ -63,7 +63,7 @@ var mouseEventTypes = map[MouseEventType]string{ // // X10 mouse events look like: // -// ESC [M Cb Cx Cy +// ESC [M Cb Cx Cy // // See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking func parseX10MouseEvents(buf []byte) ([]MouseEvent, error) { diff --git a/options.go b/options.go index 09e5ecbd73..b60d23c232 100644 --- a/options.go +++ b/options.go @@ -7,8 +7,7 @@ import "io" // // Example usage: // -// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) -// +// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) type ProgramOption func(*Program) // WithOutput sets the output which, by default, is stdout. In most cases you @@ -51,11 +50,11 @@ func WithoutCatchPanics() ProgramOption { // // Example: // -// p := tea.NewProgram(Model{}, tea.WithAltScreen()) -// if err := p.Start(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } +// p := tea.NewProgram(Model{}, tea.WithAltScreen()) +// if err := p.Start(); err != nil { +// fmt.Println("Error running program:", err) +// os.Exit(1) +// } // // To enter the altscreen once the program has already started running use the // EnterAltScreen command. diff --git a/tea.go b/tea.go index 59b48f9354..28065a007f 100644 --- a/tea.go +++ b/tea.go @@ -124,10 +124,9 @@ type Program struct { // // Example: // -// func (m model) Init() Cmd { -// return tea.Batch(someCommand, someOtherCommand) -// } -// +// func (m model) Init() Cmd { +// return tea.Batch(someCommand, someOtherCommand) +// } func Batch(cmds ...Cmd) Cmd { var validCmds []Cmd for _, c := range cmds {