github.com/ladydascalie/elvish@v0.0.0-20170703214355-2964dd3ece7f/store/dir.go (about)

     1  package store
     2  
     3  import (
     4  	"database/sql"
     5  
     6  	"github.com/elves/elvish/store/storedefs"
     7  )
     8  
     9  const (
    10  	scoreDecay     = 0.986 // roughly 0.5^(1/50)
    11  	scoreIncrement = 10
    12  )
    13  
    14  func init() {
    15  	initDB["initialize directory history table"] = func(db *sql.DB) error {
    16  		_, err := db.Exec(`create table if not exists dir (path text unique primary key, score real default 0)`)
    17  		return err
    18  	}
    19  }
    20  
    21  // AddDir adds a directory to the directory history.
    22  func (s *Store) AddDir(d string, incFactor float64) error {
    23  	return transaction(s.db, func(tx *sql.Tx) error {
    24  		// Insert when the path does not already exist
    25  		_, err := tx.Exec("insert or ignore into dir (path) values(?)", d)
    26  		if err != nil {
    27  			return err
    28  		}
    29  
    30  		// Decay scores
    31  		_, err = tx.Exec("update dir set score = score * ?", scoreDecay)
    32  		if err != nil {
    33  			return err
    34  		}
    35  
    36  		// Increment score
    37  		_, err = tx.Exec("update dir set score = score + ? where path = ?", scoreIncrement*incFactor, d)
    38  		return err
    39  	})
    40  }
    41  
    42  // GetDirs lists all directories in the directory history whose names are not
    43  // in the blacklist. The results are ordered by scores in descending order.
    44  func (s *Store) GetDirs(blacklist map[string]struct{}) ([]storedefs.Dir, error) {
    45  	rows, err := s.db.Query(
    46  		"select path, score from dir order by score desc")
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	return convertDirs(rows, blacklist)
    51  }
    52  
    53  func convertDirs(rows *sql.Rows, blacklist map[string]struct{}) ([]storedefs.Dir, error) {
    54  	var (
    55  		dir  storedefs.Dir
    56  		dirs []storedefs.Dir
    57  	)
    58  
    59  	for rows.Next() {
    60  		rows.Scan(&dir.Path, &dir.Score)
    61  		if _, black := blacklist[dir.Path]; !black {
    62  			dirs = append(dirs, dir)
    63  		}
    64  	}
    65  	if err := rows.Err(); err != nil {
    66  		return nil, err
    67  	}
    68  	return dirs, nil
    69  }