github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/cli/histutil/hybrid_store.go (about)

     1  package histutil
     2  
     3  import "github.com/markusbkk/elvish/pkg/store/storedefs"
     4  
     5  // NewHybridStore returns a store that provides a view of all the commands that
     6  // exists in the database, plus a in-memory session history.
     7  func NewHybridStore(db DB) (Store, error) {
     8  	if db == nil {
     9  		return NewMemStore(), nil
    10  	}
    11  	dbStore, err := NewDBStore(db)
    12  	if err != nil {
    13  		return NewMemStore(), err
    14  	}
    15  	return hybridStore{dbStore, NewMemStore()}, nil
    16  }
    17  
    18  type hybridStore struct {
    19  	shared, session Store
    20  }
    21  
    22  func (s hybridStore) AddCmd(cmd storedefs.Cmd) (int, error) {
    23  	seq, err := s.shared.AddCmd(cmd)
    24  	s.session.AddCmd(storedefs.Cmd{Text: cmd.Text, Seq: seq})
    25  	return seq, err
    26  }
    27  
    28  func (s hybridStore) AllCmds() ([]storedefs.Cmd, error) {
    29  	shared, err := s.shared.AllCmds()
    30  	session, err2 := s.session.AllCmds()
    31  	if err == nil {
    32  		err = err2
    33  	}
    34  	if len(shared) == 0 {
    35  		return session, err
    36  	}
    37  	return append(shared, session...), err
    38  }
    39  
    40  func (s hybridStore) Cursor(prefix string) Cursor {
    41  	return &hybridStoreCursor{
    42  		s.shared.Cursor(prefix), s.session.Cursor(prefix), false}
    43  }
    44  
    45  type hybridStoreCursor struct {
    46  	shared    Cursor
    47  	session   Cursor
    48  	useShared bool
    49  }
    50  
    51  func (c *hybridStoreCursor) Prev() {
    52  	if c.useShared {
    53  		c.shared.Prev()
    54  		return
    55  	}
    56  	c.session.Prev()
    57  	if _, err := c.session.Get(); err == ErrEndOfHistory {
    58  		c.useShared = true
    59  		c.shared.Prev()
    60  	}
    61  }
    62  
    63  func (c *hybridStoreCursor) Next() {
    64  	if !c.useShared {
    65  		c.session.Next()
    66  		return
    67  	}
    68  	c.shared.Next()
    69  	if _, err := c.shared.Get(); err == ErrEndOfHistory {
    70  		c.useShared = false
    71  		c.session.Next()
    72  	}
    73  }
    74  
    75  func (c *hybridStoreCursor) Get() (storedefs.Cmd, error) {
    76  	if c.useShared {
    77  		return c.shared.Get()
    78  	}
    79  	return c.session.Get()
    80  }