99 lines
1.8 KiB
Go
99 lines
1.8 KiB
Go
|
package atom
|
|||
|
|
|||
|
import (
|
|||
|
"gitea.zaclys.com/bvaudour/gob/option"
|
|||
|
)
|
|||
|
|
|||
|
// Cycler stocke les données possibles de l’autocomplétion
|
|||
|
type Cycler struct {
|
|||
|
data []string
|
|||
|
cursor int
|
|||
|
cycled bool
|
|||
|
}
|
|||
|
|
|||
|
func isCursorValid(c, l int) bool {
|
|||
|
return c >= 0 && c < l
|
|||
|
}
|
|||
|
|
|||
|
// Len retourne le nombre de propositions du cycler.
|
|||
|
func (c *Cycler) Len() int {
|
|||
|
return len(c.data)
|
|||
|
}
|
|||
|
|
|||
|
// Cursor retourne la position de l’élément pointé.
|
|||
|
func (c *Cycler) Cursor() int {
|
|||
|
return c.cursor
|
|||
|
}
|
|||
|
|
|||
|
// Index retourne l’élément selon son index.
|
|||
|
func (c *Cycler) Index(i int) (value option.Option[string]) {
|
|||
|
l := c.Len()
|
|||
|
if i < 0 {
|
|||
|
i += l
|
|||
|
}
|
|||
|
|
|||
|
if isCursorValid(i, l) {
|
|||
|
value = option.Some(c.data[i])
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// SetCursor positionne le pointeur à l’index donné.
|
|||
|
func (c *Cycler) SetCursor(n int) (ok bool) {
|
|||
|
l := c.Len()
|
|||
|
if n < 0 {
|
|||
|
n += l
|
|||
|
}
|
|||
|
|
|||
|
if ok = isCursorValid(n, l); ok {
|
|||
|
c.cursor = n
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Append ajoute une proposition au cycler.
|
|||
|
func (c *Cycler) Append(data string) {
|
|||
|
c.data = append(c.data, data)
|
|||
|
}
|
|||
|
|
|||
|
// Clear efface le cycler.
|
|||
|
func (c *Cycler) Clear() {
|
|||
|
c.data = c.data[:0]
|
|||
|
c.cursor = -1
|
|||
|
}
|
|||
|
|
|||
|
// Next incrémente le pointeur et retourne vrai
|
|||
|
// si le pointeur pointe sur un élément.
|
|||
|
func (c *Cycler) Next() (ok bool) {
|
|||
|
n := c.cursor + 1
|
|||
|
if ok = c.SetCursor(n); !ok && c.cycled {
|
|||
|
ok = c.SetCursor(0)
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Prev décrémente le pointeur et retourne vrai
|
|||
|
// si le pointeur pointe sur un élément.
|
|||
|
func (c *Cycler) Prev() (ok bool) {
|
|||
|
n := c.cursor - 1
|
|||
|
if ok = n >= 0 && c.SetCursor(n); !ok && c.cycled {
|
|||
|
ok = c.SetCursor(-1)
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// NewCycler crée un nouveau cycler avec les données fournies.
|
|||
|
// Si cycled est vrai, le cycler revient au début s’il a atteint la
|
|||
|
// fin et inversement.
|
|||
|
func NewCycler(cycled bool, data ...string) *Cycler {
|
|||
|
return &Cycler{
|
|||
|
data: data,
|
|||
|
cycled: cycled,
|
|||
|
cursor: -1,
|
|||
|
}
|
|||
|
}
|