package format import ( "strings" "unicode/utf8" ) // Tab crée une tabulation d’une longueur donnée. func Tab(size int) string { return strings.Repeat(" ", size) } // TabulateLeft ajoute espaces à gauche. func TabulateLeft(str string, tabSize int) string { return Tab(tabSize) + str } // TabulateRight ajoute espaces à droite. func TabulateRight(str string, tabSize int) string { return str + Tab(tabSize) } // Tabulate ajoute espaces à gauche et espaces à droite. func Tabulate(str string, leftSize, rightSize int) string { return Tab(leftSize) + str + Tab(rightSize) } // AlignmentType représente un type d’alignement. type AlignmentType int const ( LEFT AlignmentType = iota RIGHT CENTER ) // Alignment permet d’aligner des chaînes selon des caractérisques prédéfinies. type Alignment struct { t AlignmentType l int } // NewAlignement retourne un aligneur de type t (gauche, droit ou centré) et de longueur définie. // Ainsi un aligneur gauche défini à 10 caractères transformera une chaîne de la façon suivante : // - si la chaîne fait plus de 10 caractères, elle est tronquée à droite // - sinon, des espaces sont rajoutées à droite de sorte que la chaîne de sortie fasse 10 caractères. // Un aligneur droit procède de la même manière mais de l’autre côté. // Un aligneur centré équilibre de sorte que la chaîne d’entrée reste au milieu. func NewAlignment(t AlignmentType, size int) Alignment { if size <= 0 { panic("Size of alignment must be positive") } return Alignment{ t: t, l: size, } } func size(str string) int { return utf8.RuneCountInString(str) } // Formate aligne la chaîne d’entrée selon les paramètres // prédéfinis de l’aligneur. func (a Alignment) Format(str string) string { l := size(str) if l == a.l { return str } d := a.l - l runes := []rune(str) switch a.t { case RIGHT: if d > 0 { return TabulateLeft(str, d) } return string(runes[-d:]) case CENTER: if d > 0 { left := d >> 1 right := d - left return Tabulate(str, left, right) } left := (-d) >> 1 return string(runes[left : left+a.l]) default: if d > 0 { return TabulateRight(str, d) } return string(runes[:a.l]) } } // Align align la chaîne selon le type d’alignement donné, // de sorte que la chaîne de sortie ait la longueur spécifiée. func Align(str string, align AlignmentType, size int) string { a := NewAlignment(align, size) return a.Format(str) } // Left aligne à gauche. func Left(str string, size int) string { return Align(str, LEFT, size) } // Right aligne à droite. func Right(str string, size int) string { return Align(str, RIGHT, size) } // Center centre la chaîne. func Center(str string, size int) string { return Align(str, CENTER, size) } // ColumnSet permet de formater les entrées d’un tableau. // Chaque entrée correspond à un aligneur de colonne. type ColumnSet []Alignment // NewColumnSet retourne un formateur de tableaux. func NewColumnSet(aligns ...Alignment) ColumnSet { return aligns } // Normalize formate les colonnes spcéfiées en entrées. // Le nombre de colonnes doit être identique au nombre de l’aligneurs // du formateur de colonnes. func (cs ColumnSet) Normalize(columns []string) (out []string) { if len(cs) != len(columns) { panic("Number of columns must be equal to number of column set") } out = make([]string, len(columns)) for i, a := range cs { out[i] = a.Format(columns[i]) } return out } // Line formate une ligne de tableau, avec : // - columns : liste des colonnes de la ligne // - sep : séparateur de colonnes // - prefix : préfixe de ligne // - suffix : suffixe de ligne func (cs ColumnSet) Line(columns []string, sep, prefix, suffix string) string { out := cs.Normalize(columns) if prefix != "" || suffix != "" { for i, c := range out { out[i] = prefix + c + suffix } } return strings.Join(out, sep) }