-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathciv.go
202 lines (176 loc) · 4.17 KB
/
civ.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package civ
import (
"fmt"
termbox "github.com/nsf/termbox-go"
"os"
)
const (
SCROLL_SIZE = 1
)
type Civ struct {
ql *QueryLine
terminal *Terminal
table *Table
mode int
terminate bool
}
const promptDefault string = "Search> "
func NewCiv(data [][]string, dummyHeader bool) *Civ {
c := &Civ{
ql: NewQueryLine(),
terminal: NewTerminal(),
table: NewTable(data, dummyHeader),
}
return c
}
// Key event used by view mode
func (c *Civ) keyEventView(event termbox.Event) {
switch event.Key {
case 0:
if !c.maybeChangeMode(event.Ch) {
_, maxY := GetMaxXY()
windowMoveSize := maxY / 2
switch event.Ch {
case 'b':
c.table.MoveUp(windowMoveSize)
case 'F':
c.table.MoveDown(windowMoveSize)
case 'f':
c.table.MoveDown(windowMoveSize)
case 'e':
c.table.MoveDown(SCROLL_SIZE)
case 'y':
c.table.MoveUp(SCROLL_SIZE)
case 'd':
c.table.MoveDown(windowMoveSize / 2)
case 'u':
c.table.MoveUp(windowMoveSize / 2)
case 'g':
c.table.SetOffsetRow(0)
case 'G':
h := c.table.computeHeight()
moveTo := 0
if h > maxY {
moveTo = h - maxY
}
c.table.SetOffsetRow(moveTo)
}
}
case termbox.KeyArrowRight:
c.table.MoveRight(SCROLL_SIZE)
case termbox.KeyArrowLeft:
c.table.MoveLeft(SCROLL_SIZE)
case termbox.KeyArrowDown:
c.table.MoveDown(SCROLL_SIZE)
case termbox.KeyArrowUp:
c.table.MoveUp(SCROLL_SIZE)
case termbox.KeySpace:
_, maxY := GetMaxXY()
windowMoveSize := maxY / 2
c.table.MoveDown(windowMoveSize)
case termbox.KeyEnter:
c.table.MoveDown(SCROLL_SIZE)
}
}
// Key event used by command mode and search mode
func (c *Civ) keyEventInput(event termbox.Event) {
// When press enter key, execute the command and clear query
// line string while keeping mode and state of each cell (matches,
// visibility). Also we return immediately after cleared query line
// so that we can leave the current state.
if event.Key == termbox.KeyEnter {
c.ExecuteCommand()
c.ql.ClearQuery()
return
}
switch event.Key {
case 0:
if !c.maybeChangeMode(event.Ch) {
// mode is not changed, input char
c.ql.InputChar(event.Ch)
}
case termbox.KeySpace:
c.ql.InputChar(' ')
case termbox.KeyBackspace, termbox.KeyBackspace2:
c.ql.BackwardChar()
case termbox.KeyCtrlD:
c.ql.DeleteChar()
case termbox.KeyCtrlK:
c.ql.TruncateChars()
case termbox.KeyArrowRight, termbox.KeyCtrlF:
c.ql.MoveForward()
case termbox.KeyArrowLeft, termbox.KeyCtrlB:
c.ql.MoveBackward()
case termbox.KeyHome, termbox.KeyCtrlA:
c.ql.MoveToTop()
case termbox.KeyEnd, termbox.KeyCtrlE:
c.ql.MoveToEnd()
default:
// Don't execute increment search/filter when get invalid
// key.
return
}
// Do incremental search and filter
if c.ql.mode == MODE_SEARCH {
c.executeSearchCommand()
} else if c.ql.mode == MODE_FILTER {
c.executeFilterCommand()
}
}
func (c *Civ) handleKeyEvent(event termbox.Event) {
if c.ql.mode == MODE_VIEW {
c.keyEventView(event)
} else {
// MODE_COMMAND, MODE_SEARCH
c.keyEventInput(event)
}
}
func (c *Civ) maybeChangeMode(key rune) bool {
// If this is not first character, it's not mode change
if ql := c.ql.QueryLen(); ql != 0 {
return false
}
if key == '/' && c.ql.mode != MODE_SEARCH {
c.ql.mode = MODE_SEARCH
return true
} else if key == '@' && c.ql.mode != MODE_COMMAND {
c.ql.mode = MODE_COMMAND
return true
} else if key == '^' && c.ql.mode != MODE_FILTER {
c.ql.mode = MODE_FILTER
return true
} else if key == ':' && c.ql.mode != MODE_VIEW {
c.ql.mode = MODE_VIEW
return true
}
return false
}
func (c *Civ) Draw() {
c.terminal.Draw(c.ql, c.table)
}
func (c *Civ) Run() bool {
for {
// Terminate if commanded
if c.terminate {
return true
}
c.terminal.Draw(c.ql, c.table)
switch ev := termbox.PollEvent(); ev.Type {
case termbox.EventKey:
if ev.Key == termbox.KeyCtrlC {
// Ctrl-c is always used to terminate
return false
} else if ev.Key == termbox.KeyCtrlG {
c.ql.ClearAll()
}
// Dispatch key input even to the current mode
c.handleKeyEvent(ev)
case termbox.EventError:
fmt.Printf("detected an error event from termbox\n")
os.Exit(1)
break
default:
}
}
return false
}