commit 54b1008
Hubert Hirtz
·
2020-08-10 08:35:22 +0000 UTC
parent 7ce0747
editor: Handle UP and DOWN keys
3 files changed,
+68,
-16
M
app.go
+4,
-0
1@@ -232,6 +232,10 @@ func (app *App) handleUIEvent(ev tcell.Event) {
2 } else {
3 app.win.InputLeft()
4 }
5+ case tcell.KeyUp:
6+ app.win.InputUp()
7+ case tcell.KeyDown:
8+ app.win.InputDown()
9 case tcell.KeyHome:
10 app.win.InputHome()
11 case tcell.KeyEnd:
+54,
-16
1@@ -7,7 +7,9 @@ import (
2 // editor is the text field where the user writes messages and commands.
3 type editor struct {
4 // text contains the written runes. An empty slice means no text is written.
5- text []rune
6+ text [][]rune
7+
8+ lineIdx int
9
10 // textWidth[i] contains the width of string(text[:i]). Therefore
11 // len(textWidth) is always strictly greater than 0 and textWidth[0] is
12@@ -28,7 +30,7 @@ type editor struct {
13
14 func newEditor(width int) editor {
15 return editor{
16- text: []rune{},
17+ text: [][]rune{{}},
18 textWidth: []int{0},
19 width: width,
20 }
21@@ -43,17 +45,17 @@ func (e *editor) Resize(width int) {
22 }
23
24 func (e *editor) IsCommand() bool {
25- return len(e.text) != 0 && e.text[0] == '/'
26+ return len(e.text[e.lineIdx]) != 0 && e.text[e.lineIdx][0] == '/'
27 }
28
29 func (e *editor) TextLen() int {
30- return len(e.text)
31+ return len(e.text[e.lineIdx])
32 }
33
34 func (e *editor) PutRune(r rune) {
35- e.text = append(e.text, ' ')
36- copy(e.text[e.cursorIdx+1:], e.text[e.cursorIdx:])
37- e.text[e.cursorIdx] = r
38+ e.text[e.lineIdx] = append(e.text[e.lineIdx], ' ')
39+ copy(e.text[e.lineIdx][e.cursorIdx+1:], e.text[e.lineIdx][e.cursorIdx:])
40+ e.text[e.lineIdx][e.cursorIdx] = r
41
42 rw := runeWidth(r)
43 tw := e.textWidth[len(e.textWidth)-1]
44@@ -93,13 +95,14 @@ func (e *editor) remRuneAt(idx int) {
45 copy(e.textWidth[idx+1:], e.textWidth[idx+2:])
46 e.textWidth = e.textWidth[:len(e.textWidth)-1]
47
48- copy(e.text[idx:], e.text[idx+1:])
49- e.text = e.text[:len(e.text)-1]
50+ copy(e.text[e.lineIdx][idx:], e.text[e.lineIdx][idx+1:])
51+ e.text[e.lineIdx] = e.text[e.lineIdx][:len(e.text[e.lineIdx])-1]
52 }
53
54 func (e *editor) Flush() (content string) {
55- content = string(e.text)
56- e.text = e.text[:0]
57+ content = string(e.text[e.lineIdx])
58+ e.lineIdx = len(e.text)
59+ e.text = append(e.text, []rune{})
60 e.textWidth = e.textWidth[:1]
61 e.cursorIdx = 0
62 e.offsetIdx = 0
63@@ -107,13 +110,13 @@ func (e *editor) Flush() (content string) {
64 }
65
66 func (e *editor) Right() {
67- if e.cursorIdx == len(e.text) {
68+ if e.cursorIdx == len(e.text[e.lineIdx]) {
69 return
70 }
71 e.cursorIdx++
72 if e.width <= e.textWidth[e.cursorIdx]-e.textWidth[e.offsetIdx] {
73 e.offsetIdx += 16
74- max := len(e.text) - 1
75+ max := len(e.text[e.lineIdx]) - 1
76 if max < e.offsetIdx {
77 e.offsetIdx = max
78 }
79@@ -139,20 +142,55 @@ func (e *editor) Home() {
80 }
81
82 func (e *editor) End() {
83- e.cursorIdx = len(e.text)
84+ e.cursorIdx = len(e.text[e.lineIdx])
85 for e.width < e.textWidth[e.cursorIdx]-e.textWidth[e.offsetIdx]+16 {
86 e.offsetIdx++
87 }
88 }
89
90+func (e *editor) Up() {
91+ if e.lineIdx == 0 {
92+ return
93+ }
94+ e.lineIdx--
95+ e.computeTextWidth()
96+ e.cursorIdx = 0
97+ e.offsetIdx = 0
98+ e.End()
99+}
100+
101+func (e *editor) Down() {
102+ if e.lineIdx == len(e.text)-1 {
103+ if len(e.text[e.lineIdx]) == 0 {
104+ return
105+ }
106+ e.Flush()
107+ return
108+ }
109+ e.lineIdx++
110+ e.computeTextWidth()
111+ e.cursorIdx = 0
112+ e.offsetIdx = 0
113+ e.End()
114+}
115+
116+func (e *editor) computeTextWidth() {
117+ e.textWidth = e.textWidth[:1]
118+ rw := 0
119+ for _, r := range e.text[e.lineIdx] {
120+ rw += runeWidth(r)
121+ e.textWidth = append(e.textWidth, rw)
122+ }
123+}
124+
125 func (e *editor) Draw(screen tcell.Screen, y int) {
126 st := tcell.StyleDefault
127
128 x := 0
129 i := e.offsetIdx
130
131- for i < len(e.text) && x < e.width {
132- r := e.text[i]
133+ for i < len(e.text[e.lineIdx]) && x < e.width {
134+ r := e.text[e.lineIdx][i]
135 screen.SetContent(x, y, r, nil, st)
136 x += runeWidth(r)
137 i++
M
ui/ui.go
+10,
-0
1@@ -166,6 +166,16 @@ func (ui *UI) InputEnd() {
2 ui.draw()
3 }
4
5+func (ui *UI) InputUp() {
6+ ui.e.Up()
7+ ui.draw()
8+}
9+
10+func (ui *UI) InputDown() {
11+ ui.e.Down()
12+ ui.draw()
13+}
14+
15 func (ui *UI) InputBackspace() (ok bool) {
16 ok = ui.e.RemRune()
17 if ok {