line -> cmd; visited_dir -> dir

This commit is contained in:
Cheer Xiao 2015-02-25 16:40:48 +01:00
parent fb32536e3b
commit b5bf7f2dba
9 changed files with 222 additions and 222 deletions

View File

@ -225,7 +225,7 @@ func cd(ec *evalCtx, args []Value) exitus {
pwd, err := os.Getwd()
// XXX(xiaq): ignores error
if err == nil {
ec.store.AddVisitedDir(pwd)
ec.store.AddDir(pwd)
}
}
return success
@ -237,7 +237,7 @@ func visistedDirs(ec *evalCtx, args []Value) exitus {
if ec.store == nil {
return storeNotConnected
}
dirs, err := ec.store.ListVisitedDirs()
dirs, err := ec.store.ListDirs()
if err != nil {
return newFailure("store error: " + err.Error())
}
@ -260,7 +260,7 @@ func jumpDir(ec *evalCtx, args []Value) exitus {
if ec.store == nil {
return storeNotConnected
}
dirs, err := ec.store.FindVisitedDirs(toString(args[0]))
dirs, err := ec.store.FindDirs(toString(args[0]))
if err != nil {
return newFailure("store error: " + err.Error())
}
@ -273,7 +273,7 @@ func jumpDir(ec *evalCtx, args []Value) exitus {
if err != nil {
return newFailure(err.Error())
}
ec.store.AddVisitedDir(dir)
ec.store.AddDir(dir)
return success
}

56
store/cmd_hist.go Normal file
View File

@ -0,0 +1,56 @@
package store
import (
"database/sql"
"errors"
)
func init() {
createTable["cmd"] = `create table if not exists cmd (content text)`
}
func (s *Store) GetNextCmdSeq() (int, error) {
row := s.db.QueryRow(`select ifnull(max(rowid), 0) + 1 from cmd`)
var seq int
err := row.Scan(&seq)
return seq, err
}
func (s *Store) AddCmd(cmd string) error {
_, err := s.db.Exec(`insert into cmd (content) values(?)`, cmd)
return err
}
func (s *Store) GetCmd(seq int) (string, error) {
row := s.db.QueryRow(`select content from cmd where rowid = ?`, seq)
var cmd string
err := row.Scan(&cmd)
return cmd, err
}
var ErrNoMatchingCmd = errors.New("no matching command line")
func convertCmd(row *sql.Row) (int, string, error) {
var (
seq int
cmd string
)
err := row.Scan(&seq, &cmd)
if err != nil {
if err == sql.ErrNoRows {
err = ErrNoMatchingCmd
}
return 0, "", err
}
return seq, cmd, nil
}
func (s *Store) GetLastCmdWithPrefix(upto int, prefix string) (int, string, error) {
row := s.db.QueryRow(`select rowid, content from cmd where rowid < ? and substr(content, 1, ?) = ? order by rowid desc limit 1`, upto, len(prefix), prefix)
return convertCmd(row)
}
func (s *Store) GetFirstCmdWithPrefix(from int, prefix string) (int, string, error) {
row := s.db.QueryRow(`select rowid, content from cmd where rowid >= ? and substr(content, 1, ?) = ? order by rowid asc limit 1`, from, len(prefix), prefix)
return convertCmd(row)
}

68
store/cmd_hist_test.go Normal file
View File

@ -0,0 +1,68 @@
package store
import "testing"
var (
cmds = []string{"echo foo", "put bar", "put lorem", "echo bar"}
searches = []struct {
first bool
seq int
prefix string
wantedSeq int
wantedCmd string
wantedErr error
}{
{false, 5, "echo", 4, "echo bar", nil},
{false, 5, "put", 3, "put lorem", nil},
{false, 4, "echo", 1, "echo foo", nil},
{false, 3, "f", 0, "", ErrNoMatchingCmd},
{true, 1, "echo", 1, "echo foo", nil},
{true, 1, "put", 2, "put bar", nil},
{true, 2, "echo", 4, "echo bar", nil},
{true, 4, "put", 0, "", ErrNoMatchingCmd},
}
)
func TestCmd(t *testing.T) {
startSeq, err := tStore.GetNextCmdSeq()
if startSeq != 1 || err != nil {
t.Errorf("tStore.GetNextCmdSeq() => (%v, %v), want (1, nil)",
startSeq, err)
}
for _, cmd := range cmds {
err := tStore.AddCmd(cmd)
if err != nil {
t.Errorf("tStore.AddCmd(%v) => %v, want nil", cmd, err)
}
}
endSeq, err := tStore.GetNextCmdSeq()
wantedEndSeq := startSeq + len(cmds)
if endSeq != wantedEndSeq || err != nil {
t.Errorf("tStore.GetNextCmdSeq() => (%v, %v), want (%v, nil)",
endSeq, err, wantedEndSeq)
}
for i, wantedCmd := range cmds {
seq := i + startSeq
cmd, err := tStore.GetCmd(seq)
if cmd != wantedCmd || err != nil {
t.Errorf("tStore.GetCmd(%v) => (%v, %v), want (%v, nil)",
seq, cmd, err, wantedCmd)
}
}
for _, tt := range searches {
f := tStore.GetLastCmdWithPrefix
fname := "tStore.GetLastCmdWithPrefix"
if tt.first {
f = tStore.GetFirstCmdWithPrefix
fname = "tStore.GetFirstCmdWithPrefix"
}
seq, cmd, err := f(tt.seq, tt.prefix)
if seq != tt.wantedSeq || cmd != tt.wantedCmd || err != tt.wantedErr {
t.Errorf("%s(%v, %v) => (%v, %v, %v), want (%v, %v, %v)",
fname, tt.seq, tt.prefix,
seq, cmd, err,
tt.wantedSeq, tt.wantedCmd, tt.wantedErr)
}
}
}

68
store/dir_hist.go Normal file
View File

@ -0,0 +1,68 @@
package store
import "database/sql"
type Dir struct {
Path string
Score float64
}
const (
ScoreIncrement = 10
)
func init() {
createTable["dir"] = `create table if not exists dir (path text unique primary key, score real default 0)`
}
func (s *Store) AddDir(d string) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Commit()
// Insert when the path does not already exist
_, err = tx.Exec("insert or ignore into dir (path) values(?)", d)
if err != nil {
return err
}
// Increment score
_, err = tx.Exec("update dir set score = score + ? where path = ?", ScoreIncrement, d)
return err
}
func convertDirs(rows *sql.Rows) ([]Dir, error) {
var (
dir Dir
dirs []Dir
)
for rows.Next() {
rows.Scan(&dir.Path, &dir.Score)
dirs = append(dirs, dir)
}
if err := rows.Err(); err != nil {
return nil, err
}
return dirs, nil
}
func (s *Store) FindDirs(p string) ([]Dir, error) {
rows, err := s.db.Query(
"select path, score from dir where instr(path, ?) > 0 order by score desc", p)
if err != nil {
return nil, err
}
return convertDirs(rows)
}
func (s *Store) ListDirs() ([]Dir, error) {
rows, err := s.db.Query(
"select path, score from dir order by score desc")
if err != nil {
return nil, err
}
return convertDirs(rows)
}

26
store/dir_hist_test.go Normal file
View File

@ -0,0 +1,26 @@
package store
import (
"reflect"
"testing"
)
var (
dirsToAdd = []string{"/usr", "/usr/bin", "/usr"}
wantedDirs = []Dir{Dir{"/usr", 20}, Dir{"/usr/bin", 10}}
)
func TestDir(t *testing.T) {
for _, path := range dirsToAdd {
err := tStore.AddDir(path)
if err != nil {
t.Errorf("tStore.AddDir(%q) => %v, want <nil>", path, err)
}
}
dirs, err := tStore.FindDirs("usr")
if err != nil || !reflect.DeepEqual(dirs, wantedDirs) {
t.Errorf(`tStore.FindDirs("usr") => (%v, %v), want (%v, <nil>)`,
dirs, err, wantedDirs)
}
}

View File

@ -1,56 +0,0 @@
package store
import (
"database/sql"
"errors"
)
func init() {
createTable["line"] = `create table if not exists line (content text)`
}
func (s *Store) GetNextLineSeq() (int, error) {
row := s.db.QueryRow(`select ifnull(max(rowid), 0) + 1 from line`)
var seq int
err := row.Scan(&seq)
return seq, err
}
func (s *Store) AddLine(line string) error {
_, err := s.db.Exec(`insert into line (content) values(?)`, line)
return err
}
func (s *Store) GetLine(seq int) (string, error) {
row := s.db.QueryRow(`select content from line where rowid = ?`, seq)
var line string
err := row.Scan(&line)
return line, err
}
var ErrNoMatchingLine = errors.New("no matching line")
func convertLine(row *sql.Row) (int, string, error) {
var (
seq int
line string
)
err := row.Scan(&seq, &line)
if err != nil {
if err == sql.ErrNoRows {
err = ErrNoMatchingLine
}
return 0, "", err
}
return seq, line, nil
}
func (s *Store) GetLastLineWithPrefix(upto int, prefix string) (int, string, error) {
row := s.db.QueryRow(`select rowid, content from line where rowid < ? and substr(content, 1, ?) = ? order by rowid desc limit 1`, upto, len(prefix), prefix)
return convertLine(row)
}
func (s *Store) GetFirstLineWithPrefix(from int, prefix string) (int, string, error) {
row := s.db.QueryRow(`select rowid, content from line where rowid >= ? and substr(content, 1, ?) = ? order by rowid asc limit 1`, from, len(prefix), prefix)
return convertLine(row)
}

View File

@ -1,68 +0,0 @@
package store
import "testing"
var (
lines = []string{"echo foo", "put bar", "put lorem", "echo bar"}
searches = []struct {
first bool
seq int
prefix string
wantedSeq int
wantedLine string
wantedErr error
}{
{false, 5, "echo", 4, "echo bar", nil},
{false, 5, "put", 3, "put lorem", nil},
{false, 4, "echo", 1, "echo foo", nil},
{false, 3, "f", 0, "", ErrNoMatchingLine},
{true, 1, "echo", 1, "echo foo", nil},
{true, 1, "put", 2, "put bar", nil},
{true, 2, "echo", 4, "echo bar", nil},
{true, 4, "put", 0, "", ErrNoMatchingLine},
}
)
func TestLine(t *testing.T) {
startSeq, err := tStore.GetNextLineSeq()
if startSeq != 1 || err != nil {
t.Errorf("tStore.GetNextLineSeq() => (%v, %v), want (1, nil)",
startSeq, err)
}
for _, line := range lines {
err := tStore.AddLine(line)
if err != nil {
t.Errorf("tStore.AddLine(%v) => %v, want nil", line, err)
}
}
endSeq, err := tStore.GetNextLineSeq()
wantedEndSeq := startSeq + len(lines)
if endSeq != wantedEndSeq || err != nil {
t.Errorf("tStore.GetLastLineSeq() => (%v, %v), want (%v, nil)",
endSeq, err, wantedEndSeq)
}
for i, wantedLine := range lines {
seq := i + startSeq
line, err := tStore.GetLine(seq)
if line != wantedLine || err != nil {
t.Errorf("tStore.GetLine(%v) => (%v, %v), want (%v, nil)",
seq, line, err, wantedLine)
}
}
for _, tt := range searches {
f := tStore.GetLastLineWithPrefix
fname := "tStore.GetLastLineWithPrefix"
if tt.first {
f = tStore.GetFirstLineWithPrefix
fname = "tStore.GetFirstLineWithPrefix"
}
seq, line, err := f(tt.seq, tt.prefix)
if seq != tt.wantedSeq || line != tt.wantedLine || err != tt.wantedErr {
t.Errorf("%s(%v, %v) => (%v, %v, %v), want (%v, %v, %v)",
fname, tt.seq, tt.prefix,
seq, line, err,
tt.wantedSeq, tt.wantedLine, tt.wantedErr)
}
}
}

View File

@ -1,68 +0,0 @@
package store
import "database/sql"
type VisitedDir struct {
Path string
Score float64
}
const (
ScoreIncrement = 10
)
func init() {
createTable["visited_dir"] = `create table if not exists visited_dir (path text unique primary key, score real default 0)`
}
func (s *Store) AddVisitedDir(d string) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
defer tx.Commit()
// Insert when the path does not already exist
_, err = tx.Exec("insert or ignore into visited_dir (path) values(?)", d)
if err != nil {
return err
}
// Increment score
_, err = tx.Exec("update visited_dir set score = score + ? where path = ?", ScoreIncrement, d)
return err
}
func convertVisitedDirs(rows *sql.Rows) ([]VisitedDir, error) {
var (
dir VisitedDir
dirs []VisitedDir
)
for rows.Next() {
rows.Scan(&dir.Path, &dir.Score)
dirs = append(dirs, dir)
}
if err := rows.Err(); err != nil {
return nil, err
}
return dirs, nil
}
func (s *Store) FindVisitedDirs(p string) ([]VisitedDir, error) {
rows, err := s.db.Query(
"select path, score from visited_dir where instr(path, ?) > 0 order by score desc", p)
if err != nil {
return nil, err
}
return convertVisitedDirs(rows)
}
func (s *Store) ListVisitedDirs() ([]VisitedDir, error) {
rows, err := s.db.Query(
"select path, score from visited_dir order by score desc")
if err != nil {
return nil, err
}
return convertVisitedDirs(rows)
}

View File

@ -1,26 +0,0 @@
package store
import (
"reflect"
"testing"
)
var (
dirsToAdd = []string{"/usr", "/usr/bin", "/usr"}
wantedDirs = []VisitedDir{VisitedDir{"/usr", 20}, VisitedDir{"/usr/bin", 10}}
)
func TestDir(t *testing.T) {
for _, path := range dirsToAdd {
err := tStore.AddVisitedDir(path)
if err != nil {
t.Errorf("tStore.AddVisitedDir(%q) => %v, want <nil>", path, err)
}
}
dirs, err := tStore.FindVisitedDirs("usr")
if err != nil || !reflect.DeepEqual(dirs, wantedDirs) {
t.Errorf(`tStore.FindVisitedDirs("usr") => (%v, %v), want (%v, <nil>)`,
dirs, err, wantedDirs)
}
}