-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhistory.go
167 lines (132 loc) · 3.56 KB
/
history.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
package readline
import (
"strconv"
"strings"
)
// History is an interface to allow you to write your own history logging
// tools. eg sqlite backend instead of a file system.
// By default readline will just use the dummyLineHistory interface which only
// logs the history to memory ([]string to be precise).
type History interface {
// Append takes the line and returns an updated number of lines or an error
Write(string) (int, error)
// GetLine takes the historic line number and returns the line or an error
GetLine(int) (string, error)
// Len returns the number of history lines
Len() int
// Dump returns everything in readline. The return is an any because not all
//LineHistory implementations will want to structure the history in the same
// way. And since Dump() is not actually used by the readline API internally,
// this methods return can be structured in whichever way is most convenient
//for your own applications (or even just create an empty function which
// returns `nil` if you don't require Dump() either)
Dump() any
}
// ExampleHistory is an example of a LineHistory interface:
type ExampleHistory struct {
items []string
}
// Write to history
func (h *ExampleHistory) Write(s string) (int, error) {
h.items = append(h.items, s)
return len(h.items), nil
}
// GetLine returns a line from history
func (h *ExampleHistory) GetLine(i int) (string, error) {
return h.items[i], nil
}
// Len returns the number of lines in history
func (h *ExampleHistory) Len() int {
return len(h.items)
}
// Dump returns the entire history
func (h *ExampleHistory) Dump() any {
return h.items
}
// NullHistory is a null History interface for when you don't want line
// entries remembered eg password input.
type NullHistory struct{}
// Write to history
func (h *NullHistory) Write(s string) (int, error) {
return 0, nil
}
// GetLine returns a line from history
func (h *NullHistory) GetLine(i int) (string, error) {
return "", nil
}
// Len returns the number of lines in history
func (h *NullHistory) Len() int {
return 0
}
// Dump returns the entire history
func (h *NullHistory) Dump() any {
return []string{}
}
// Browse historic lines
func (rl *Instance) walkHistory(i int) {
var (
old, new string
dedup bool
err error
)
switch rl.histPos + i {
case -1, rl.History.Len() + 1:
return
case rl.History.Len():
rl.clearLine()
rl.histPos += i
rl.line = []rune(rl.lineBuf)
default:
dedup = true
old = string(rl.line)
new, err = rl.History.GetLine(rl.histPos + i)
if err != nil {
rl.resetHelpers()
print("\r\n" + err.Error() + "\r\n")
print(rl.prompt)
return
}
if rl.histPos == rl.History.Len() {
rl.lineBuf = string(rl.line)
}
rl.clearLine()
rl.histPos += i
rl.line = []rune(new)
_, y := lineWrapPos(rl.promptLen, len(rl.line), rl.termWidth)
print(strings.Repeat("\r\n", y))
}
rl.pos = len(rl.line)
rl.echo()
rl.updateHelpers()
if dedup && old == new {
rl.walkHistory(i)
}
}
func (rl *Instance) autocompleteHistory() ([]string, map[string]string) {
var (
items []string
descs = make(map[string]string)
line string
num string
err error
)
rl.tcPrefix = string(rl.line)
//for i := 0; i < rl.History.Len(); i++ {
for i := rl.History.Len() - 1; i >= 0; i-- {
line, err = rl.History.GetLine(i)
if err != nil {
continue
}
if !strings.HasPrefix(line, rl.tcPrefix) {
continue
}
line = strings.Replace(line, "\n", ` `, -1)[len(rl.line):]
if descs[line] != "" {
continue
}
items = append(items, line)
num = strconv.Itoa(i)
descs[line] = num
}
return items, descs
}