github.com/elves/elvish@v0.15.0/pkg/cli/histutil/db.go (about) 1 package histutil 2 3 import ( 4 "strings" 5 6 "github.com/elves/elvish/pkg/store" 7 ) 8 9 // DB is the interface of the storage database. 10 type DB interface { 11 NextCmdSeq() (int, error) 12 AddCmd(cmd string) (int, error) 13 CmdsWithSeq(from, upto int) ([]store.Cmd, error) 14 PrevCmd(upto int, prefix string) (store.Cmd, error) 15 NextCmd(from int, prefix string) (store.Cmd, error) 16 } 17 18 // FaultyInMemoryDB is an in-memory DB implementation that can be injected 19 // one-off errors. It is useful in tests. 20 type FaultyInMemoryDB interface { 21 DB 22 // SetOneOffError causes the next operation on the database to return the 23 // given error. 24 SetOneOffError(err error) 25 } 26 27 // NewFaultyInMemoryDB creates a new FaultyInMemoryDB with the given commands. 28 func NewFaultyInMemoryDB(cmds ...string) FaultyInMemoryDB { 29 return &testDB{cmds: cmds} 30 } 31 32 // Implementation of FaultyInMemoryDB. 33 type testDB struct { 34 cmds []string 35 oneOffError error 36 } 37 38 func (s *testDB) SetOneOffError(err error) { 39 s.oneOffError = err 40 } 41 42 func (s *testDB) error() error { 43 err := s.oneOffError 44 s.oneOffError = nil 45 return err 46 } 47 48 func (s *testDB) NextCmdSeq() (int, error) { 49 return len(s.cmds), s.error() 50 } 51 52 func (s *testDB) AddCmd(cmd string) (int, error) { 53 if s.oneOffError != nil { 54 return -1, s.error() 55 } 56 s.cmds = append(s.cmds, cmd) 57 return len(s.cmds) - 1, nil 58 } 59 60 func (s *testDB) CmdsWithSeq(from, upto int) ([]store.Cmd, error) { 61 if err := s.error(); err != nil { 62 return nil, err 63 } 64 if from < 0 { 65 from = 0 66 } 67 if upto < 0 || upto > len(s.cmds) { 68 upto = len(s.cmds) 69 } 70 var cmds []store.Cmd 71 for i := from; i < upto; i++ { 72 cmds = append(cmds, store.Cmd{Text: s.cmds[i], Seq: i}) 73 } 74 return cmds, nil 75 } 76 77 func (s *testDB) PrevCmd(upto int, prefix string) (store.Cmd, error) { 78 if s.oneOffError != nil { 79 return store.Cmd{}, s.error() 80 } 81 if upto < 0 || upto > len(s.cmds) { 82 upto = len(s.cmds) 83 } 84 for i := upto - 1; i >= 0; i-- { 85 if strings.HasPrefix(s.cmds[i], prefix) { 86 return store.Cmd{Text: s.cmds[i], Seq: i}, nil 87 } 88 } 89 return store.Cmd{}, store.ErrNoMatchingCmd 90 } 91 92 func (s *testDB) NextCmd(from int, prefix string) (store.Cmd, error) { 93 if s.oneOffError != nil { 94 return store.Cmd{}, s.error() 95 } 96 if from < 0 { 97 from = 0 98 } 99 for i := from; i < len(s.cmds); i++ { 100 if strings.HasPrefix(s.cmds[i], prefix) { 101 return store.Cmd{Text: s.cmds[i], Seq: i}, nil 102 } 103 } 104 return store.Cmd{}, store.ErrNoMatchingCmd 105 }