mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
line -> cmd; visited_dir -> dir
This commit is contained in:
parent
fb32536e3b
commit
b5bf7f2dba
|
@ -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
56
store/cmd_hist.go
Normal 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
68
store/cmd_hist_test.go
Normal 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
68
store/dir_hist.go
Normal 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
26
store/dir_hist_test.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user