This repository has been archived by the owner on Apr 7, 2018. It is now read-only.
/
history.go
206 lines (188 loc) · 6.01 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
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
203
204
205
206
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package readline
/*
#include <stdlib.h>
#include "goreadline.h"
*/
import "C"
import (
"fmt"
// "os"
"strings"
"syscall"
"unicode"
"unsafe"
)
// UsingHistory begins a session in which the history functions might be used. This initializes the interactive variables.
// (See using_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX2)
func UsingHistory() {
C.using_history()
}
// AddHistory places string at the end of the history list.
// Blank lines are discarded.
// (See add_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX5)
func AddHistory(line string) {
if len(line) == 0 || len(strings.TrimSpace(line)) == 0 {
return
}
if unicode.IsSpace(rune(line[0])) { // ignorespace
return
}
if prev, err := GetHistory(-1); err == nil && prev == line { // ignore consecutive dups
return
}
cline := C.CString(line)
C.add_history(cline)
C.free(unsafe.Pointer(cline))
}
// ReadHistory adds the content of filename to the history list, a line at a time.
// If filename is "", then read from '~/.history'.
// (See read_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX27)
func ReadHistory(filename string) (bool, error) {
var cfilename *C.char
if len(filename) != 0 {
cfilename = C.CString(filename)
}
err := C.read_history(cfilename)
if cfilename != nil {
C.free(unsafe.Pointer(cfilename))
}
if err != 0 {
e := syscall.Errno(err)
if e == syscall.ENOENT { // ignored when the file doesn't exist.
return false, nil
}
return false, e
}
return true, nil
}
// WriteHistory writes the current history to filename, overwriting filename if necessary.
// If filename is "", then write the history list to `~/.history'.
// (See write_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX29)
func WriteHistory(filename string) error {
if HistoryLength() <= 0 {
return nil
}
var cfilename *C.char
if len(filename) != 0 {
cfilename = C.CString(filename)
}
err := C.write_history(cfilename)
if cfilename != nil {
C.free(unsafe.Pointer(cfilename))
}
if err != 0 {
return syscall.Errno(err)
}
return nil
}
// AppendHistory appends the last nelements of the history list to filename.
// If filename is "", then append to `~/.history'.
// (See append_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX30)
/* not supported by editline
func AppendHistory(nelements int, filename string) error {
if HistoryLength() == 0 {
return nil
}
// Checks if the file exists. If not, creates it.
f, err := os.Open(filename)
if os.IsNotExist(err) {
f, err = os.Create(filename)
}
if err != nil {
return err
}
if err = f.Close(); err != nil {
return err
}
var cfilename *C.char
if len(filename) != 0 {
cfilename = C.CString(filename)
}
cerr := C.append_history(C.int(nelements), cfilename)
if cfilename != nil {
C.free(unsafe.Pointer(cfilename))
}
if cerr != 0 {
return syscall.Errno(cerr)
}
return nil
}
*/
// TruncateHistoryFile truncates the history file filename, leaving only the last nlines lines.
// If filename is "", then `~/.history' is truncated.
// (See history_truncate_file http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX31)
func TruncateHistoryFile(filename string, nlines int32) error {
var cfilename *C.char
if len(filename) != 0 {
cfilename = C.CString(filename)
}
err := C.history_truncate_file(cfilename, C.int(nlines))
if cfilename != nil {
C.free(unsafe.Pointer(cfilename))
}
if err != 0 {
return syscall.Errno(err)
}
return nil
}
// ClearHistory clears the history list by deleting all the entries.
// (See clear_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX10)
func ClearHistory() {
C.clear_history()
}
// StifleHistory cuts off the history list, remembering only the last max entries.
// (See stifle_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX11)
func StifleHistory(max int32) {
C.stifle_history(C.int(max))
}
// UnstifleHistory stops stifling the history.
// This returns the previously-set maximum number of history entries (as set by StifleHistory()).
// The value is positive if the history was stifled, negative if it wasn't.
// (See unstifle_history http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX12)
func UnstifleHistory() int32 {
return int32(C.unstifle_history())
}
// IsHistoryStifled says if the history is stifled.
// (See history_is_stifled http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX13)
func IsHistoryStifled() bool {
return C.history_is_stifled() != 0
}
// HistoryLength returns the number of entries currently stored in the history list.
// (See history_length http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX37)
func HistoryLength() int32 {
return int32(C.history_length)
}
// HistoryBase returns the logical offset of the first entry in the history list.
// (See history_base http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX36)
func HistoryBase() int32 {
return int32(C.history_base)
}
/*
// Return a nil terminated array of HIST_ENTRY * which is the current input history.
// Element 0 of this list is the beginning of time. If there is no history, return nil.
// (See history_list http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX17)
func HistoryList(offset int) string {
C.history_list()
}
*/
// GetHistory returns the history entry at position index, starting from 0.
// If there is no entry there, or if index is greater than the history length, return an error.
// (See history_get http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX17)
func GetHistory(index int32) (string, error) {
length := HistoryLength()
if index < 0 {
index += length
}
if index < 0 || index >= length {
return "", fmt.Errorf("invalid index %d", index)
}
index += HistoryBase() // TODO
entry := C.history_get(C.int(index))
if entry == nil {
return "", fmt.Errorf("invalid index %d", index)
}
return C.GoString(entry.line), nil
}