mirror of
https://github.com/jroimartin/gocui.git
synced 2025-04-24 13:48:51 +08:00
Editor refactoring. Add doc. Simplify _examples.
This commit is contained in:
parent
f42f45fad3
commit
4aed924ceb
@ -21,8 +21,6 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -37,8 +35,7 @@ func main() {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
@ -187,8 +187,6 @@ func layout(g *gocui.Gui) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -203,8 +201,7 @@ func main() {
|
||||
g.SelFgColor = gocui.ColorBlack
|
||||
g.Cursor = true
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
@ -79,20 +79,18 @@ func counter(g *gocui.Gui) {
|
||||
case <-done:
|
||||
return
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
mu.Lock()
|
||||
n := ctr
|
||||
ctr++
|
||||
mu.Unlock()
|
||||
|
||||
g.Execute(func(g *gocui.Gui) error {
|
||||
v, err := g.View("ctr")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
n := ctr
|
||||
ctr++
|
||||
mu.Unlock()
|
||||
|
||||
v.Clear()
|
||||
fmt.Fprintln(v, n)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -32,8 +32,6 @@ func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -46,8 +44,7 @@ func main() {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -29,8 +27,7 @@ func main() {
|
||||
g.Cursor = true
|
||||
g.Mouse = true
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,6 @@ func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -69,8 +67,7 @@ func main() {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ func main() {
|
||||
}
|
||||
g.Cursor = true
|
||||
|
||||
err := g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,6 @@ func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
@ -45,8 +43,7 @@ func main() {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
|
118
doc.go
118
doc.go
@ -5,36 +5,106 @@
|
||||
/*
|
||||
Package gocui allows to create console user interfaces.
|
||||
|
||||
Example:
|
||||
Create a new GUI:
|
||||
|
||||
func layout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
if v, err := g.SetView("center", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(v, "This is an example")
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
// handle error
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
// Set layout and key bindings
|
||||
// ...
|
||||
|
||||
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
|
||||
// handle error
|
||||
}
|
||||
|
||||
Set the layout function:
|
||||
|
||||
g.SetLayout(fcn)
|
||||
|
||||
On each iteration of the GUI's main loop, the "layout function" will be
|
||||
executed. These layout functions can be used to set-up and update the main
|
||||
application views, being possible to freely switch between them. Also, it is
|
||||
important to mention that a main loop iteration is executed on each reported
|
||||
event (key-press, mouse event, window resize, etc).
|
||||
|
||||
GUIs are composed by Views, you can think of it as free text buffers. Views
|
||||
implement the io.ReadWriter interface, so you can just write to them if you
|
||||
want to modify their content and the same is valid for reading.
|
||||
|
||||
Create and intialize a view with absolute coordinates:
|
||||
|
||||
if v, err := g.SetView("viewname", 2, 2, 22, 7); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
// handle error
|
||||
}
|
||||
fmt.Fprintln(v, "This is a new view")
|
||||
// ...
|
||||
}
|
||||
|
||||
Views can also being created using relative coordinates:
|
||||
|
||||
maxX, maxY := g.Size()
|
||||
if v, err := g.SetView("viewname", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2); err != nil {
|
||||
// ...
|
||||
}
|
||||
|
||||
IMPORTANT: Views can only be created, destroyed or updated in two ways: from a
|
||||
layout funcion or via *Gui.Execute(). The reason for this is that it allows
|
||||
gocui to be conccurent-safe. So, if you want to update your GUI from a
|
||||
goroutine, you must use *Gui.Execute(). For example:
|
||||
|
||||
g.Execute(func(g *gocui.Gui) error {
|
||||
v, err := g.View("viewname")
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
v.Clear()
|
||||
fmt.Fprintln(v, "Writing from different goroutines")
|
||||
return nil
|
||||
})
|
||||
|
||||
Configure keybindings:
|
||||
|
||||
if err := g.SetKeybinding("viewname", gocui.KeyEnter, gocui.ModNone, fcn); err != nil {
|
||||
// handle error
|
||||
}
|
||||
func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
|
||||
gocui implements full mouse support than can be enabled with:
|
||||
|
||||
g.Mouse = true
|
||||
|
||||
Mouse events are handled like any other keybinding:
|
||||
|
||||
if err := g.SetKeybinding("viewname", gocui.MouseLeft, gocui.ModNone, fcn); err != nil {
|
||||
// handle error
|
||||
}
|
||||
func main() {
|
||||
var err error
|
||||
g := gocui.NewGui()
|
||||
if err := g.Init(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
defer g.Close()
|
||||
g.SetLayout(layout)
|
||||
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
err = g.MainLoop()
|
||||
if err != nil && err != gocui.ErrQuit {
|
||||
log.Panicln(err)
|
||||
|
||||
By default, gocui provides a basic edition mode. This mode can be extended
|
||||
and customized creating a new Editor and asigning it to *Gui.Editor:
|
||||
|
||||
type Editor interface {
|
||||
Edit(v *View, key Key, ch rune, mod Modifier)
|
||||
}
|
||||
|
||||
DefaultEditor can be taken as example to create your own custom Editor:
|
||||
|
||||
var DefaultEditor = EditorFunc(simpleEditor)
|
||||
|
||||
func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
|
||||
switch {
|
||||
case ch != 0 && mod == 0:
|
||||
v.EditWrite(ch)
|
||||
case key == KeySpace:
|
||||
v.EditWrite(' ')
|
||||
case key == KeyBackspace || key == KeyBackspace2:
|
||||
v.EditDelete(true)
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
For more information, see the examples in folder "_examples/".
|
||||
*/
|
||||
package gocui
|
||||
|
12
edit.go
12
edit.go
@ -6,11 +6,6 @@ package gocui
|
||||
|
||||
const maxInt = int(^uint(0) >> 1)
|
||||
|
||||
// Edit allows to define the editor that manages the edition mode,
|
||||
// including keybindings or cursor behaviour. DefaultEditor is used by
|
||||
// default.
|
||||
var Edit = EditorFunc(DefaultEditor)
|
||||
|
||||
// Editor interface must be satisfied by gocui editors.
|
||||
type Editor interface {
|
||||
Edit(v *View, key Key, ch rune, mod Modifier)
|
||||
@ -26,8 +21,11 @@ func (f EditorFunc) Edit(v *View, key Key, ch rune, mod Modifier) {
|
||||
f(v, key, ch, mod)
|
||||
}
|
||||
|
||||
// DefaultEditor is used as the default gocui editor.
|
||||
func DefaultEditor(v *View, key Key, ch rune, mod Modifier) {
|
||||
// DefaultEditor is the default editor.
|
||||
var DefaultEditor Editor = EditorFunc(simpleEditor)
|
||||
|
||||
// simpleEditor is used as the default gocui editor.
|
||||
func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
|
||||
switch {
|
||||
case ch != 0 && mod == 0:
|
||||
v.EditWrite(ch)
|
||||
|
14
gui.go
14
gui.go
@ -19,7 +19,7 @@ type userEvent struct {
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrQuit is used to decide if the MainLoop finished succesfully.
|
||||
// ErrQuit is used to decide if the MainLoop finished successfully.
|
||||
ErrQuit = errors.New("quit")
|
||||
|
||||
// ErrUnknownView allows to assert if a View must be initialized.
|
||||
@ -50,6 +50,11 @@ type Gui struct {
|
||||
|
||||
// If Mouse is true then mouse events will be enabled.
|
||||
Mouse bool
|
||||
|
||||
// Editor allows to define the editor that manages the edition mode,
|
||||
// including keybindings or cursor behaviour. DefaultEditor is used by
|
||||
// default.
|
||||
Editor Editor
|
||||
}
|
||||
|
||||
// NewGui returns a new Gui object.
|
||||
@ -68,6 +73,7 @@ func (g *Gui) Init() error {
|
||||
g.maxX, g.maxY = termbox.Size()
|
||||
g.BgColor = ColorBlack
|
||||
g.FgColor = ColorWhite
|
||||
g.Editor = DefaultEditor
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -220,7 +226,7 @@ func (g *Gui) Execute(h Handler) {
|
||||
}
|
||||
|
||||
// SetLayout sets the current layout. A layout is a function that
|
||||
// will be called everytime the gui is re-drawed, it must contain
|
||||
// will be called every time the gui is redrawn, it must contain
|
||||
// the base views and its initializations.
|
||||
func (g *Gui) SetLayout(layout Handler) {
|
||||
g.layout = layout
|
||||
@ -493,8 +499,8 @@ func (g *Gui) onKey(ev *termbox.Event) error {
|
||||
|
||||
switch ev.Type {
|
||||
case termbox.EventKey:
|
||||
if g.currentView != nil && g.currentView.Editable && Edit != nil {
|
||||
Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod))
|
||||
if g.currentView != nil && g.currentView.Editable && g.Editor != nil {
|
||||
g.Editor.Edit(g.currentView, Key(ev.Key), ev.Ch, Modifier(ev.Mod))
|
||||
}
|
||||
curView = g.currentView
|
||||
case termbox.EventMouse:
|
||||
|
4
view.go
4
view.go
@ -419,7 +419,7 @@ func (v *View) breakLine(x, y int) error {
|
||||
}
|
||||
|
||||
// Buffer returns a string with the contents of the view's internal
|
||||
// buffer
|
||||
// buffer.
|
||||
func (v *View) Buffer() string {
|
||||
str := ""
|
||||
for _, l := range v.lines {
|
||||
@ -429,7 +429,7 @@ func (v *View) Buffer() string {
|
||||
}
|
||||
|
||||
// ViewBuffer returns a string with the contents of the view's buffer that is
|
||||
// showed to the user
|
||||
// shown to the user.
|
||||
func (v *View) ViewBuffer() string {
|
||||
str := ""
|
||||
for _, l := range v.viewLines {
|
||||
|
Loading…
x
Reference in New Issue
Block a user