gob/shell/console/atom/output.go

196 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package atom
import (
"errors"
"fmt"
"strings"
"unicode"
"unicode/utf8"
"gitea.zaclys.com/bvaudour/gob/option"
)
var (
ErrInvalidUnicode = errors.New("Not unicode")
)
// NextUnescape enlève le caractère déchapement en début de chaîne.
func NextUnescape(str string) (result option.Option[string]) {
if !strings.HasPrefix(str, "\033[") {
result = option.Some(str)
} else if i := strings.Index(str, "m"); i >= 0 {
result = option.Some(str[i+1:])
}
return
}
// IsPrintable retourne vrai si le caractère donné est imprimable.
func IsPrintable(r Char) bool {
return r == '\n' || unicode.IsPrint(r)
}
// IsSpace retourne vrai si le caractère donné est un caractère blanc.
func IsSpace(r Char) bool {
return unicode.IsSpace(r)
}
// CheckUnicode vérifie si la chaîne de caractère
// ne contient que des caractères imprimables.
func CheckUnicode(str string) (err option.Option[error]) {
runes := []rune(str)
for i, r := range runes {
if r == Esc {
if i == len(runes)-1 || runes[i+1] != '[' {
return option.Some(ErrInvalidUnicode)
}
} else if unicode.Is(unicode.C, r) {
return option.Some(ErrInvalidUnicode)
}
}
return
}
// VisibleWith indique le nombre de colonnes nécessaires
// pour afficher dune chaîne passée à echo.
func VisibleWidth(str string) int {
w := 0
for len(str) > 0 {
cleaned := NextUnescape(str)
if s, ok := cleaned.Get(); ok {
str = s
} else {
break
}
r, i := utf8.DecodeRuneInString(str)
if IsPrintable(r) {
w++
}
str = str[i:]
}
return w
}
// CursorOffset calcule la position relative du curseur
// par rapport au début de la chaîne, ainsi que le
// le n° de la dernière ligne (en commençant de 0).
func CursorOffset(str string, p, w int) (px, py, l int) {
if len(str) == 0 {
return
}
var (
n, c int
)
for len(str) > 0 {
cleaned := NextUnescape(str)
if s, ok := cleaned.Get(); ok {
str = s
} else {
break
}
r, i := utf8.DecodeRuneInString(str)
str = str[i:]
if IsPrintable(r) {
if p == n {
px, py = c, l
}
n++
if r == '\n' {
c, l = 0, l+1
} else {
c++
if c == w {
c, l = 0, l+1
}
}
}
}
if p >= n {
px, py = c, l
}
return
}
// ClearBeginOfLine efface le début de la ligne, curseur compris
func ClearBeginOfLine() { fmt.Print("\033[1K") }
// ClearEndOfLine efface la fin de la ligne, curseur compris.
func ClearEndOfLine() { fmt.Print("\033[0K") }
// ClearLine efface toute la ligne.
func ClearLine() { fmt.Print("\033[2K") }
// ClearBeginOfScreen efface lécran jusquau curseur, curseur compris.
func ClearBeginOfScreen() { fmt.Print("\033[1J") }
// ClearBeginOfScreen efface lécran à partir du curseur, curseur compris.
func ClearEndOfScreen() { fmt.Print("\033[0J") }
// ClearAllScreen efface tout lécran.
func ClearAllScreen() { fmt.Print("\033[2J") }
// ClearAllScreenAndHistory efface tout lécran, ainsi que lhistorique de laffichage.
func ClearAllScreenAndHistory() { fmt.Print("\033[3J") }
// MoveUp déplace le curseur de c lignes vers le haut.
func MoveUp(c int) { fmt.Printf("\033[%dA", c) }
// MoveDown déplace le curseur de c lignes vers le bas.
func MoveDown(c int) { fmt.Printf("\033[%dB", c) }
// MoveLeft déplace le curseur de c colonnes vers la gauche.
func MoveLeft(c int) { fmt.Printf("\033[%dD", c) }
// MoveRight déplace le curseur de c colonnes vers la droite.
func MoveRight(c int) { fmt.Printf("\033[%dC", c) }
// MoveLineUp se déplace de c lignes vers le haut et revient en début de ligne.
func MoveLineUp(c int) { fmt.Printf("\033[%dF", c) }
// MoveLineDown se déplace de c lignes vers le bas et revient en début de ligne.
func MoveLineDown(c int) { fmt.Printf("\033[%dE", c) }
// MoveToColumn se déplace à la colonne c. La colonne commence à 1.
func MoveToColumn(c int) { fmt.Printf("\033[%dG", c) }
// MoveToScreen se déplace à la ligne l et la colonne c de lécran.
// l et c commencent à 1.
func MoveToScreen(l, c int) { fmt.Print("\033[%d;%dH", l, c) }
// MoveTopLeft se déplace au tout début de lécran
func MoveTopLeft() { MoveToScreen(1, 1) }
// SaveCursorPosition enregistre la position du curseur
// pour pouvoir y revenir plus tard.
func SaveCursorPosition() { fmt.Print("\033[s") }
// RestoreCursorPosition revient à la position précédemment enregistrée.
func RestoreCursorPosition() { fmt.Print("\033[u") }
// Beep émet un beep.
func Beep() { fmt.Print("\a") }
// CarriageReturn revient en début de ligne.
func CarriageReturn() { fmt.Print("\r") }
// NewLines rajoute c lignes.
func NewLines(c int) {
for c > 0 {
fmt.Print("\n")
c--
}
}