118 lines
2.3 KiB
Go
118 lines
2.3 KiB
Go
|
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
|
|||
|
}
|