1// Copyright 2014 The gocui Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8	"fmt"
9	"io"
10	"io/ioutil"
11	"log"
12	"strings"
13
14	"github.com/jroimartin/gocui"
15)
16
17func nextView(g *gocui.Gui, v *gocui.View) error {
18	if v == nil || v.Name() == "side" {
19		return g.SetCurrentView("main")
20	}
21	return g.SetCurrentView("side")
22}
23
24func cursorDown(g *gocui.Gui, v *gocui.View) error {
25	if v != nil {
26		cx, cy := v.Cursor()
27		if err := v.SetCursor(cx, cy+1); err != nil {
28			ox, oy := v.Origin()
29			if err := v.SetOrigin(ox, oy+1); err != nil {
30				return err
31			}
32		}
33	}
34	return nil
35}
36
37func cursorUp(g *gocui.Gui, v *gocui.View) error {
38	if v != nil {
39		ox, oy := v.Origin()
40		cx, cy := v.Cursor()
41		if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
42			if err := v.SetOrigin(ox, oy-1); err != nil {
43				return err
44			}
45		}
46	}
47	return nil
48}
49
50func getLine(g *gocui.Gui, v *gocui.View) error {
51	var l string
52	var err error
53
54	_, cy := v.Cursor()
55	if l, err = v.Line(cy); err != nil {
56		l = ""
57	}
58
59	maxX, maxY := g.Size()
60	if v, err := g.SetView("msg", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2); err != nil {
61		if err != gocui.ErrUnknownView {
62			return err
63		}
64		fmt.Fprintln(v, l)
65		if err := g.SetCurrentView("msg"); err != nil {
66			return err
67		}
68	}
69	return nil
70}
71
72func delMsg(g *gocui.Gui, v *gocui.View) error {
73	if err := g.DeleteView("msg"); err != nil {
74		return err
75	}
76	if err := g.SetCurrentView("side"); err != nil {
77		return err
78	}
79	return nil
80}
81
82func quit(g *gocui.Gui, v *gocui.View) error {
83	return gocui.ErrQuit
84}
85
86func keybindings(g *gocui.Gui) error {
87	if err := g.SetKeybinding("side", gocui.KeyCtrlSpace, gocui.ModNone, nextView); err != nil {
88		return err
89	}
90	if err := g.SetKeybinding("main", gocui.KeyCtrlSpace, gocui.ModNone, nextView); err != nil {
91		return err
92	}
93	if err := g.SetKeybinding("side", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil {
94		return err
95	}
96	if err := g.SetKeybinding("side", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil {
97		return err
98	}
99	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
100		return err
101	}
102	if err := g.SetKeybinding("side", gocui.KeyEnter, gocui.ModNone, getLine); err != nil {
103		return err
104	}
105	if err := g.SetKeybinding("msg", gocui.KeyEnter, gocui.ModNone, delMsg); err != nil {
106		return err
107	}
108
109	if err := g.SetKeybinding("main", gocui.KeyCtrlS, gocui.ModNone, saveMain); err != nil {
110		return err
111	}
112	if err := g.SetKeybinding("main", gocui.KeyCtrlW, gocui.ModNone, saveVisualMain); err != nil {
113		return err
114	}
115	return nil
116}
117
118func saveMain(g *gocui.Gui, v *gocui.View) error {
119	f, err := ioutil.TempFile("", "gocui_demo_")
120	if err != nil {
121		return err
122	}
123	defer f.Close()
124
125	p := make([]byte, 5)
126	v.Rewind()
127	for {
128		n, err := v.Read(p)
129		if n > 0 {
130			if _, err := f.Write(p[:n]); err != nil {
131				return err
132			}
133		}
134		if err == io.EOF {
135			break
136		}
137		if err != nil {
138			return err
139		}
140	}
141	return nil
142}
143
144func saveVisualMain(g *gocui.Gui, v *gocui.View) error {
145	f, err := ioutil.TempFile("", "gocui_demo_")
146	if err != nil {
147		return err
148	}
149	defer f.Close()
150
151	vb := v.ViewBuffer()
152	if _, err := io.Copy(f, strings.NewReader(vb)); err != nil {
153		return err
154	}
155	return nil
156}
157
158func layout(g *gocui.Gui) error {
159	maxX, maxY := g.Size()
160	if v, err := g.SetView("side", -1, -1, 30, maxY); err != nil {
161		if err != gocui.ErrUnknownView {
162			return err
163		}
164		v.Highlight = true
165		fmt.Fprintln(v, "Item 1")
166		fmt.Fprintln(v, "Item 2")
167		fmt.Fprintln(v, "Item 3")
168		fmt.Fprint(v, "\rWill be")
169		fmt.Fprint(v, "deleted\rItem 4\nItem 5")
170	}
171	if v, err := g.SetView("main", 30, -1, maxX, maxY); err != nil {
172		if err != gocui.ErrUnknownView {
173			return err
174		}
175		b, err := ioutil.ReadFile("Mark.Twain-Tom.Sawyer.txt")
176		if err != nil {
177			panic(err)
178		}
179		fmt.Fprintf(v, "%s", b)
180		v.Editable = true
181		v.Wrap = true
182		if err := g.SetCurrentView("main"); err != nil {
183			return err
184		}
185	}
186	return nil
187}
188
189func main() {
190	g := gocui.NewGui()
191	if err := g.Init(); err != nil {
192		log.Panicln(err)
193	}
194	defer g.Close()
195
196	g.SetLayout(layout)
197	if err := keybindings(g); err != nil {
198		log.Panicln(err)
199	}
200	g.SelBgColor = gocui.ColorGreen
201	g.SelFgColor = gocui.ColorBlack
202	g.Cursor = true
203
204	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
205		log.Panicln(err)
206	}
207}
208