Définitions de style pour de belles dispositions de terminaux. Construit en pensant aux TUI.
Lip Gloss adopte une approche expressive et déclarative du rendu du terminal. Les utilisateurs familiers avec CSS se sentiront à l’aise avec Lip Gloss.
import "github.com/charmbracelet/lipgloss"
var style = lipgloss . NewStyle ().
Bold ( true ).
Foreground ( lipgloss . Color ( "#FAFAFA" )).
Background ( lipgloss . Color ( "#7D56F4" )).
PaddingTop ( 2 ).
PaddingLeft ( 4 ).
Width ( 22 )
fmt . Println ( style . Render ( "Hello, kitty" ))
Lip Gloss prend en charge les profils de couleurs suivants :
lipgloss . Color ( "5" ) // magenta
lipgloss . Color ( "9" ) // red
lipgloss . Color ( "12" ) // light blue
lipgloss . Color ( "86" ) // aqua
lipgloss . Color ( "201" ) // hot pink
lipgloss . Color ( "202" ) // orange
lipgloss . Color ( "#0000FF" ) // good ol' 100% blue
lipgloss . Color ( "#04B575" ) // a green
lipgloss . Color ( "#3C3C3C" ) // a dark gray
...ainsi qu'un profil ASCII 1 bit, uniquement en noir et blanc.
Le profil de couleur du terminal sera automatiquement détecté et les couleurs en dehors de la gamme de la palette actuelle seront automatiquement contraintes à leur valeur disponible la plus proche.
Vous pouvez également spécifier des options de couleur pour les arrière-plans clairs et sombres :
lipgloss. AdaptiveColor { Light : "236" , Dark : "248" }
La couleur d'arrière-plan du terminal sera automatiquement détectée et la couleur appropriée sera choisie au moment de l'exécution.
CompleteColor spécifie les valeurs exactes pour les profils de couleurs True Color, ANSI256 et ANSI.
lipgloss. CompleteColor { TrueColor : "#0000FF" , ANSI256 : "86" , ANSI : "5" }
Dans ce cas, aucune dégradation automatique des couleurs ne sera effectuée et elle sera basée sur la couleur spécifiée.
Vous pouvez utiliser CompleteColor
avec AdaptiveColor
pour spécifier les valeurs exactes des arrière-plans clairs et sombres sans dégradation automatique des couleurs.
lipgloss. CompleteAdaptiveColor {
Light : CompleteColor { TrueColor : "#d7ffae" , ANSI256 : "193" , ANSI : "11" },
Dark : CompleteColor { TrueColor : "#d75fee" , ANSI256 : "163" , ANSI : "5" },
}
Lip Gloss prend en charge les options de formatage de texte ANSI habituelles :
var style = lipgloss . NewStyle ().
Bold ( true ).
Italic ( true ).
Faint ( true ).
Blink ( true ).
Strikethrough ( true ).
Underline ( true ).
Reverse ( true )
Lip Gloss prend également en charge les règles de formatage au niveau des blocs :
// Padding
var style = lipgloss . NewStyle ().
PaddingTop ( 2 ).
PaddingRight ( 4 ).
PaddingBottom ( 2 ).
PaddingLeft ( 4 )
// Margins
var style = lipgloss . NewStyle ().
MarginTop ( 2 ).
MarginRight ( 4 ).
MarginBottom ( 2 ).
MarginLeft ( 4 )
Il existe également une syntaxe abrégée pour les marges et le remplissage, qui suit le même format que CSS :
// 2 cells on all sides
lipgloss . NewStyle (). Padding ( 2 )
// 2 cells on the top and bottom, 4 cells on the left and right
lipgloss . NewStyle (). Margin ( 2 , 4 )
// 1 cell on the top, 4 cells on the sides, 2 cells on the bottom
lipgloss . NewStyle (). Padding ( 1 , 4 , 2 )
// Clockwise, starting from the top: 2 cells on the top, 4 on the right, 3 on
// the bottom, and 1 on the left
lipgloss . NewStyle (). Margin ( 2 , 4 , 3 , 1 )
Vous pouvez aligner des paragraphes de texte à gauche, à droite ou au centre.
var style = lipgloss . NewStyle ().
Width ( 24 ).
Align ( lipgloss . Left ). // align it left
Align ( lipgloss . Right ). // no wait, align it right
Align ( lipgloss . Center ) // just kidding, align it in the center
Définir une largeur et une hauteur minimales est simple et direct.
var style = lipgloss . NewStyle ().
SetString ( "What’s for lunch?" ).
Width ( 24 ).
Height ( 32 ).
Foreground ( lipgloss . Color ( "63" ))
L'ajout de bordures est simple :
// Add a purple, rectangular border
var style = lipgloss . NewStyle ().
BorderStyle ( lipgloss . NormalBorder ()).
BorderForeground ( lipgloss . Color ( "63" ))
// Set a rounded, yellow-on-purple border to the top and left
var anotherStyle = lipgloss . NewStyle ().
BorderStyle ( lipgloss . RoundedBorder ()).
BorderForeground ( lipgloss . Color ( "228" )).
BorderBackground ( lipgloss . Color ( "63" )).
BorderTop ( true ).
BorderLeft ( true )
// Make your own border
var myCuteBorder = lipgloss. Border {
Top : "._.:*:" ,
Bottom : "._.:*:" ,
Left : "|*" ,
Right : "|*" ,
TopLeft : "*" ,
TopRight : "*" ,
BottomLeft : "*" ,
BottomRight : "*" ,
}
Il existe également des fonctions raccourcies pour définir des bordures, qui suivent un modèle similaire aux fonctions raccourcies margin et padding.
// Add a thick border to the top and bottom
lipgloss . NewStyle ().
Border ( lipgloss . ThickBorder (), true , false )
// Add a double border to the top and left sides. Rules are set clockwise
// from top.
lipgloss . NewStyle ().
Border ( lipgloss . DoubleBorder (), true , false , false , true )
Pour en savoir plus sur les frontières, consultez la documentation.
Utilisez simplement l'affectation :
style := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "219" ))
copiedStyle := style // this is a true copy
wildStyle := style . Blink ( true ) // this is also true copy, with blink added
Étant donné que les structures de données Style
ne contiennent que des types primitifs, l’attribution d’un style à un autre crée effectivement une nouvelle copie du style sans muter l’original.
Les styles peuvent hériter des règles d'autres styles. Lors de l'héritage, seules les règles non définies sur le récepteur sont héritées.
var styleA = lipgloss . NewStyle ().
Foreground ( lipgloss . Color ( "229" )).
Background ( lipgloss . Color ( "63" ))
// Only the background color will be inherited here, because the foreground
// color will have been already set:
var styleB = lipgloss . NewStyle ().
Foreground ( lipgloss . Color ( "201" )).
Inherit ( styleA )
Toutes les règles peuvent être annulées :
var style = lipgloss . NewStyle ().
Bold ( true ). // make it bold
UnsetBold (). // jk don't make it bold
Background ( lipgloss . Color ( "227" )). // yellow background
UnsetBackground () // never mind
Lorsqu'une règle n'est pas définie, elle ne sera ni héritée ni copiée.
Parfois, par exemple lors du développement d'un composant, vous souhaitez vous assurer que les définitions de style respectent leur objectif dans l'interface utilisateur. C'est là qu'interviennent Inline
, MaxWidth
et MaxHeight
:
// Force rendering onto a single line, ignoring margins, padding, and borders.
someStyle . Inline ( true ). Render ( "yadda yadda" )
// Also limit rendering to five cells
someStyle . Inline ( true ). MaxWidth ( 5 ). Render ( "yadda yadda" )
// Limit rendering to a 5x5 cell block
someStyle . MaxWidth ( 5 ). MaxHeight ( 5 ). Render ( "yadda yadda" )
Le caractère de tabulation ( t
) est rendu différemment selon les terminaux (souvent sous forme de 8 espaces, parfois 4). En raison de cette incohérence, Lip Gloss convertit les onglets en 4 espaces au moment du rendu. Ce comportement peut toutefois être modifié en fonction du style :
style := lipgloss . NewStyle () // tabs will render as 4 spaces, the default
style = style . TabWidth ( 2 ) // render tabs as 2 spaces
style = style . TabWidth ( 0 ) // remove tabs entirely
style = style . TabWidth ( lipgloss . NoTabConversion ) // leave tabs intact
Généralement, vous appelez simplement la méthode Render(string...)
sur un lipgloss.Style
:
style := lipgloss . NewStyle (). Bold ( true ). SetString ( "Hello," )
fmt . Println ( style . Render ( "kitty." )) // Hello, kitty.
fmt . Println ( style . Render ( "puppy." )) // Hello, puppy.
Mais vous pouvez également utiliser l'interface Stringer :
var style = lipgloss . NewStyle (). SetString ( "你好,猫咪。" ). Bold ( true )
fmt . Println ( style ) // 你好,猫咪。
Les moteurs de rendu personnalisés vous permettent d'effectuer un rendu vers des sorties spécifiques. Ceci est particulièrement important lorsque vous souhaitez effectuer un rendu sur différentes sorties et détecter correctement le profil de couleur et l'état d'arrière-plan sombre pour chacune, comme dans une situation serveur-client.
func myLittleHandler ( sess ssh. Session ) {
// Create a renderer for the client.
renderer := lipgloss . NewRenderer ( sess )
// Create a new style on the renderer.
style := renderer . NewStyle (). Background (lipgloss. AdaptiveColor { Light : "63" , Dark : "228" })
// Render. The color profile and dark background state will be correctly detected.
io . WriteString ( sess , style . Render ( "Heyyyyyyy" ))
}
Pour un exemple d'utilisation d'un moteur de rendu personnalisé sur SSH avec Wish, consultez l'exemple SSH.
En plus du style pur, Lip Gloss est également livré avec certains utilitaires pour vous aider à assembler vos mises en page.
Joindre des paragraphes horizontalement et verticalement est un jeu d’enfant.
// Horizontally join three paragraphs along their bottom edges
lipgloss . JoinHorizontal ( lipgloss . Bottom , paragraphA , paragraphB , paragraphC )
// Vertically join two paragraphs along their center axes
lipgloss . JoinVertical ( lipgloss . Center , paragraphA , paragraphB )
// Horizontally join three paragraphs, with the shorter ones aligning 20%
// from the top of the tallest
lipgloss . JoinHorizontal ( 0.2 , paragraphA , paragraphB , paragraphC )
Parfois, vous souhaiterez connaître la largeur et la hauteur des blocs de texte lors de la création de vos mises en page.
// Render a block of text.
var style = lipgloss . NewStyle ().
Width ( 40 ).
Padding ( 2 )
var block string = style . Render ( someLongString )
// Get the actual, physical dimensions of the text block.
width := lipgloss . Width ( block )
height := lipgloss . Height ( block )
// Here's a shorthand function.
w , h := lipgloss . Size ( block )
Parfois, vous souhaiterez simplement placer un bloc de texte dans des espaces.
// Center a paragraph horizontally in a space 80 cells wide. The height of
// the block returned will be as tall as the input paragraph.
block := lipgloss . PlaceHorizontal ( 80 , lipgloss . Center , fancyStyledParagraph )
// Place a paragraph at the bottom of a space 30 cells tall. The width of
// the text block returned will be as wide as the input paragraph.
block := lipgloss . PlaceVertical ( 30 , lipgloss . Bottom , fancyStyledParagraph )
// Place a paragraph in the bottom right corner of a 30x80 cell space.
block := lipgloss . Place ( 30 , 80 , lipgloss . Right , lipgloss . Bottom , fancyStyledParagraph )
Vous pouvez également styliser les espaces. Pour plus de détails, consultez la documentation.
Lip Gloss est livré avec un sous-package de rendu de tableau.
import "github.com/charmbracelet/lipgloss/table"
Définissez quelques lignes de données.
rows := [][] string {
{ "Chinese" , "您好" , "你好" },
{ "Japanese" , "こんにちは" , "やあ" },
{ "Arabic" , "أهلين" , "أهلا" },
{ "Russian" , "Здравствуйте" , "Привет" },
{ "Spanish" , "Hola" , "¿Qué tal?" },
}
Utilisez le package table pour styliser et afficher le tableau.
t := table . New ().
Border ( lipgloss . NormalBorder ()).
BorderStyle ( lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "99" ))).
StyleFunc ( func ( row , col int ) lipgloss. Style {
switch {
case row == 0 :
return HeaderStyle
case row % 2 == 0 :
return EvenRowStyle
default :
return OddRowStyle
}
}).
Headers ( "LANGUAGE" , "FORMAL" , "INFORMAL" ).
Rows ( rows ... )
// You can also add tables row-by-row
t . Row ( "English" , "You look absolutely fabulous." , "How's it going?" )
Imprimez le tableau.
fmt . Println ( t )
Avertissement
Rows
du tableau doivent être déclarées avant Offset
sinon cela ne fait rien.
Pour en savoir plus sur les tableaux, consultez la documentation et les exemples.
Lip Gloss est livré avec un sous-package de rendu de liste.
import "github.com/charmbracelet/lipgloss/list"
Définissez une nouvelle liste.
l := list . New ( "A" , "B" , "C" )
Imprimez la liste.
fmt . Println ( l )
// • A
// • B
// • C
Les listes ont la capacité de s'imbriquer.
l := list . New (
"A" , list . New ( "Artichoke" ),
"B" , list . New ( "Baking Flour" , "Bananas" , "Barley" , "Bean Sprouts" ),
"C" , list . New ( "Cashew Apple" , "Cashews" , "Coconut Milk" , "Curry Paste" , "Currywurst" ),
"D" , list . New ( "Dill" , "Dragonfruit" , "Dried Shrimp" ),
"E" , list . New ( "Eggs" ),
"F" , list . New ( "Fish Cake" , "Furikake" ),
"J" , list . New ( "Jicama" ),
"K" , list . New ( "Kohlrabi" ),
"L" , list . New ( "Leeks" , "Lentils" , "Licorice Root" ),
)
Imprimez la liste.
fmt . Println ( l )
Les listes peuvent être personnalisées via leur fonction d'énumération ainsi qu'en utilisant lipgloss.Style
s.
enumeratorStyle := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "99" )). MarginRight ( 1 )
itemStyle := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "212" )). MarginRight ( 1 )
l := list . New (
"Glossier" ,
"Claire’s Boutique" ,
"Nyx" ,
"Mac" ,
"Milk" ,
).
Enumerator ( list . Roman ).
EnumeratorStyle ( enumeratorStyle ).
ItemStyle ( itemStyle )
Imprimez la liste.
En plus des énumérateurs prédéfinis ( Arabic
, Alphabet
, Roman
, Bullet
, Tree
), vous pouvez également définir votre propre énumérateur personnalisé :
l := list . New ( "Duck" , "Duck" , "Duck" , "Duck" , "Goose" , "Duck" , "Duck" )
func DuckDuckGooseEnumerator ( l list. Items , i int ) string {
if l . At ( i ). Value () == "Goose" {
return "Honk →"
}
return ""
}
l = l . Enumerator ( DuckDuckGooseEnumerator )
Imprimez la liste :
Si vous en avez besoin, vous pouvez également créer des listes de manière incrémentielle :
l := list . New ()
for i := 0 ; i < repeat ; i ++ {
l . Item ( "Lip Gloss" )
}
Lip Gloss est livré avec un sous-package de rendu arborescent.
import "github.com/charmbracelet/lipgloss/tree"
Définir un nouvel arbre.
t := tree . Root ( "." ).
Child ( "A" , "B" , "C" )
Imprimez l'arbre.
fmt . Println ( t )
// .
// ├── A
// ├── B
// └── C
Les arbres ont la capacité de nicher.
t := tree . Root ( "." ).
Child ( "macOS" ).
Child (
tree . New ().
Root ( "Linux" ).
Child ( "NixOS" ).
Child ( "Arch Linux (btw)" ).
Child ( "Void Linux" ),
).
Child (
tree . New ().
Root ( "BSD" ).
Child ( "FreeBSD" ).
Child ( "OpenBSD" ),
)
Imprimez l'arbre.
fmt . Println ( t )
Les arbres peuvent être personnalisés via leur fonction d'énumération ainsi qu'à l'aide de lipgloss.Style
s.
enumeratorStyle := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "63" )). MarginRight ( 1 )
rootStyle := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "35" ))
itemStyle := lipgloss . NewStyle (). Foreground ( lipgloss . Color ( "212" ))
t := tree .
Root ( "⁜ Makeup" ).
Child (
"Glossier" ,
"Fenty Beauty" ,
tree . New (). Child (
"Gloss Bomb Universal Lip Luminizer" ,
"Hot Cheeks Velour Blushlighter" ,
),
"Nyx" ,
"Mac" ,
"Milk" ,
).
Enumerator ( tree . RoundedEnumerator ).
EnumeratorStyle ( enumeratorStyle ).
RootStyle ( rootStyle ).
ItemStyle ( itemStyle )
Imprimez l'arbre.
Les énumérateurs prédéfinis pour les arbres sont DefaultEnumerator
et RoundedEnumerator
.
Si vous en avez besoin, vous pouvez également créer des arbres de manière incrémentielle :
t := tree . New ()
for i := 0 ; i < repeat ; i ++ {
t . Child ( "Lip Gloss" )
}
Cela est probablement dû à vos paramètres régionaux et à votre encodage, notamment en ce qui concerne le chinois, le japonais et le coréen (par exemple, zh_CN.UTF-8
ou ja_JP.UTF-8
). Le moyen le plus direct de résoudre ce problème consiste à définir RUNEWIDTH_EASTASIAN=0
dans votre environnement.
Pour plus de détails, voir https://github.com/charmbracelet/lipgloss/issues/40.
Lip Gloss dégrade automatiquement les couleurs selon la meilleure option disponible dans le terminal donné, et si la sortie n'est pas un ATS, il supprimera entièrement la sortie couleur. Ceci est courant lors de l’exécution de tests, de CI ou lors de la transmission de la sortie ailleurs.
Si nécessaire, vous pouvez forcer un profil de couleurs dans vos tests avec SetColorProfile
.
import (
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
)
lipgloss . SetColorProfile ( termenv . TrueColor )
Remarque : cette option limite la flexibilité de votre application et peut entraîner l'émission de codes d'échappement ANSI dans les cas où cela n'est pas souhaité. Prenez soigneusement note de votre cas d’utilisation et de votre environnement avant de choisir de forcer un profil de couleur.
Le brillant à lèvres ne remplace pas le Bubble Tea. C’est plutôt un excellent compagnon du Bubble Tea. Il a été conçu pour rendre l'assemblage des vues de l'interface utilisateur du terminal aussi simple et amusant que possible afin que vous puissiez vous concentrer sur la création de votre application au lieu de vous soucier des détails de mise en page de bas niveau.
En termes simples, vous pouvez utiliser Lip Gloss pour vous aider à créer vos vues Bubble Tea.
Lip Gloss est construit sur les excellentes bibliothèques Termenv et Reflow qui traitent respectivement les opérations de couleur et de texte compatibles ANSI. Pour de nombreux cas d'utilisation, Termenv et Reflow suffiront à vos besoins.
Pour une solution de rendu plus centrée sur les documents avec prise en charge d'éléments tels que les listes, les tableaux et le code mis en évidence par la syntaxe, jetez un œil à Glamour, le moteur de rendu Markdown basé sur une feuille de style.
Voir contribuer.
Nous aimerions connaître votre avis sur ce projet. N'hésitez pas à nous laisser un message !
MIT
Une partie du charme.
Charm爱开源 • Charm aime l'open source