package atom import ( "bufio" "fmt" "io" "unicode/utf8" "gitea.zaclys.com/bvaudour/gob/option" ) // History stocke l’historique des saisies. type History struct { Cycler } // Append ajoute une entrée dans l’historique. func (h *History) Append(data string) { h.Cycler.Append(data) h.cursor = h.Len() } // Clear efface l’historique. func (h *History) Clear() { h.Cycler.Clear() h.cursor = 0 } // SetCursor positionne le pointeur de l’historique. func (h *History) SetCursor(n int) (ok bool) { l := h.Len() if ok = n >= -1 && n <= l; ok { h.cursor = n } return } // Next incrémente le pointeur de l’historique // et retourne vrai si le pointeur pointe vers un élément. func (h *History) Next() (ok bool) { if ok = h.SetCursor(h.cursor + 1); ok { ok = isCursorValid(h.cursor, h.Len()) } else if h.cycled { ok = h.SetCursor(0) } return } // Prev décrémente le pointeur de l’historique // et retourne vrai si le pointeur pointe vers un élément. func (h *History) Prev() (ok bool) { if ok = h.SetCursor(h.cursor - 1); ok { ok = isCursorValid(h.cursor, h.Len()) } else if l := h.Len(); h.cycled && l > 0 { ok = h.SetCursor(l - 1) } return } // Read charge l’historique à partir d’un fichier // et retourne le nombre d’entrées ajoutées. func (h *History) Read(r io.Reader) option.Result[int] { var n int buf := bufio.NewReader(r) for { line, part, err := buf.ReadLine() if err == nil { if part { err = fmt.Errorf("line %d is too long", n+1) } else if !utf8.Valid(line) { err = fmt.Errorf("invalid string at line %d", n+1) } else { h.Append(string(line)) n++ } } if err != nil { if err == io.EOF { break } return option.Err[int](err) } } return option.Ok(n) } // Write persiste l’historique dans un fichier // et retourne le nombre d’entrées ajoutées. func (h *History) Write(w io.Writer) option.Result[int] { var n int for _, item := range h.data { _, err := fmt.Fprintln(w, item) if err != nil { return option.Err[int](err) } n++ } return option.Ok(n) } // NewHistory retourne un nouvel historique. // Si cycled est faux l’historique ne peut être parcouru en boucle. func NewHistory(cycled bool) *History { var h History h.cycled = cycled return &h }