parent
11376e2ff4
commit
ddb43b82e5
@ -0,0 +1,59 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type HiddenWriter struct {
|
||||
path string
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func NewHiddenWriter(path string) *HiddenWriter {
|
||||
return &HiddenWriter{
|
||||
path: "." + path,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HiddenWriter) Open() error {
|
||||
var err error
|
||||
h.file, err = os.OpenFile(h.path, os.O_CREATE|os.O_WRONLY, 0644)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *HiddenWriter) Write(p []byte) (n int, err error) {
|
||||
return h.file.Write(p)
|
||||
}
|
||||
|
||||
func (h *HiddenWriter) Close() error {
|
||||
return h.file.Close()
|
||||
}
|
||||
|
||||
func Reader() io.ReadCloser {
|
||||
file := os.Getenv("RQLITE_HISTFILE")
|
||||
if file == "" {
|
||||
file = "rqlite_history"
|
||||
}
|
||||
|
||||
// Call OS-specific function actually
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func Writer() io.WriteCloser {
|
||||
file := os.Getenv("RQLITE_HISTFILE")
|
||||
if file == "" {
|
||||
file = "rqlite_history"
|
||||
}
|
||||
|
||||
// Call OS-specific function actually
|
||||
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0755)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return f
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const MaxHistSize = 100
|
||||
|
||||
func Dedupe(s []string) []string {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
o := make([]string, 0, len(s))
|
||||
for si := 0; si < len(s); si++ {
|
||||
if si == 0 || s[si] != o[len(o)-1] {
|
||||
o = append(o, s[si])
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func FileSize() int {
|
||||
maxSize := MaxHistSize
|
||||
maxSizeStr := os.Getenv("RQLITE_HISTFILESIZE")
|
||||
if maxSizeStr != "" {
|
||||
sz, err := strconv.Atoi(maxSizeStr)
|
||||
if err == nil && maxSize > 0 {
|
||||
maxSize = sz
|
||||
}
|
||||
}
|
||||
return maxSize
|
||||
}
|
||||
|
||||
func Read(r io.Reader) ([]string, error) {
|
||||
if r == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var cmds []string
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
cmds = append(cmds, scanner.Text())
|
||||
}
|
||||
|
||||
return cmds, scanner.Err()
|
||||
}
|
||||
|
||||
func Write(j []string, maxSz int, w io.Writer) error {
|
||||
if len(j) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cut start off slice is bigger, but before or after dupes?
|
||||
if len(j) > maxSz {
|
||||
j = j[len(j)-maxSz:]
|
||||
}
|
||||
|
||||
i := 0
|
||||
var k []string
|
||||
for {
|
||||
k = append(k, j[i])
|
||||
|
||||
for {
|
||||
if i < len(j)-1 && j[i] == j[i+1] {
|
||||
i++
|
||||
continue
|
||||
} else if i == len(j) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(k)-1; i++ {
|
||||
if _, err := w.Write([]byte(k[i] + "\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := w.Write([]byte(k[len(k)-1]))
|
||||
return err
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package history
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Dedupe(t *testing.T) {
|
||||
for i, tt := range []struct {
|
||||
orig []string
|
||||
exp []string
|
||||
}{
|
||||
{
|
||||
orig: nil,
|
||||
exp: nil,
|
||||
},
|
||||
{
|
||||
orig: []string{"foo"},
|
||||
exp: []string{"foo"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "bar"},
|
||||
exp: []string{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "bar", "foo"},
|
||||
exp: []string{"foo", "bar", "foo"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "foo", "foo"},
|
||||
exp: []string{"foo"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "bar", "foo", "foo"},
|
||||
exp: []string{"foo", "bar", "foo"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "foo", "bar", "foo", "foo"},
|
||||
exp: []string{"foo", "bar", "foo"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "foo", "bar", "foo", "foo", "qux"},
|
||||
exp: []string{"foo", "bar", "foo", "qux"},
|
||||
},
|
||||
{
|
||||
orig: []string{"foo", "foo", "bar", "bar", "foo", "foo", "qux"},
|
||||
exp: []string{"foo", "bar", "foo", "qux"},
|
||||
},
|
||||
} {
|
||||
got := Dedupe(tt.orig)
|
||||
if !reflect.DeepEqual(tt.exp, got) {
|
||||
t.Fatalf("test %d failed, exp %s, got %s", i, tt.exp, got)
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue