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
|
||
}
|