Определения стилей для удобной компоновки терминалов. Создан с учетом TUI.
Lip Gloss использует выразительный, декларативный подход к терминальному рендерингу. Пользователи, знакомые с CSS, будут чувствовать себя как дома с блеском для губ.
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" ))
Блеск для губ поддерживает следующие цветовые профили:
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
...а также 1-битный профиль ASCII, который является только черно-белым.
Цветовой профиль терминала будет определен автоматически, а цвета за пределами гаммы текущей палитры будут автоматически приведены к ближайшему доступному значению.
Вы также можете указать параметры цвета для светлого и темного фона:
lipgloss. AdaptiveColor { Light : "236" , Dark : "248" }
Цвет фона терминала будет определен автоматически, и соответствующий цвет будет выбран во время выполнения.
CompleteColor определяет точные значения для цветовых профилей True Color, ANSI256 и ANSI.
lipgloss. CompleteColor { TrueColor : "#0000FF" , ANSI256 : "86" , ANSI : "5" }
В этом случае автоматическое ухудшение цвета выполняться не будет и оно будет основано на указанном цвете.
Вы можете использовать CompleteColor
с AdaptiveColor
, чтобы указать точные значения для светлого и темного фона без автоматического ухудшения цвета.
lipgloss. CompleteAdaptiveColor {
Light : CompleteColor { TrueColor : "#d7ffae" , ANSI256 : "193" , ANSI : "11" },
Dark : CompleteColor { TrueColor : "#d75fee" , ANSI256 : "163" , ANSI : "5" },
}
Блеск для губ поддерживает обычные параметры форматирования текста ANSI:
var style = lipgloss . NewStyle ().
Bold ( true ).
Italic ( true ).
Faint ( true ).
Blink ( true ).
Strikethrough ( true ).
Underline ( true ).
Reverse ( true )
Lip Gloss также поддерживает правила форматирования на уровне блоков:
// 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 )
Существует также сокращенный синтаксис для полей и отступов, который соответствует тому же формату, что и 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 )
Вы можете выровнять абзацы текста по левому, правому или центру.
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
Установка минимальной ширины и высоты проста и понятна.
var style = lipgloss . NewStyle ().
SetString ( "What’s for lunch?" ).
Width ( 24 ).
Height ( 32 ).
Foreground ( lipgloss . Color ( "63" ))
Добавить границы легко:
// 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 : "*" ,
}
Существуют также сокращенные функции для определения границ, которые следуют тому же шаблону, что и сокращенные функции поля и заполнения.
// 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 )
Дополнительную информацию о границах см. в документации.
Просто используйте назначение:
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
Поскольку структуры данных Style
содержат только примитивные типы, присвоение стиля другому эффективно создает новую копию стиля без изменения оригинала.
Стили могут наследовать правила других стилей. При наследовании наследуются только неустановленные правила на получателе.
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 )
Все правила можно отменить:
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
Если правило не установлено, оно не будет унаследовано или скопировано.
Иногда, например, при разработке компонента, вы хотите убедиться, что определения стилей соответствуют своему назначению в пользовательском интерфейсе. Здесь на помощь приходят Inline
, MaxWidth
и 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" )
Символ табуляции ( t
) отображается по-разному в разных терминалах (часто как 8 пробелов, иногда 4). Из-за этого несоответствия Lip Gloss преобразует табуляцию в 4 пробела во время рендеринга. Однако это поведение можно изменить для каждого стиля:
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
Обычно вы просто вызываете метод Render(string...)
для lipgloss.Style
:
style := lipgloss . NewStyle (). Bold ( true ). SetString ( "Hello," )
fmt . Println ( style . Render ( "kitty." )) // Hello, kitty.
fmt . Println ( style . Render ( "puppy." )) // Hello, puppy.
Но вы также можете использовать интерфейс Stringer:
var style = lipgloss . NewStyle (). SetString ( "你好,猫咪。" ). Bold ( true )
fmt . Println ( style ) // 你好,猫咪。
Пользовательские средства визуализации позволяют выполнять рендеринг для определенных выходных данных. Это особенно важно, когда вы хотите выполнить рендеринг на разные выходные данные и правильно определить цветовой профиль и состояние темного фона для каждого из них, например, в ситуации сервер-клиент.
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" ))
}
Пример использования пользовательского средства визуализации через SSH с Wish см. в примере SSH.
Помимо простого оформления, Lip Gloss также поставляется с некоторыми утилитами, которые помогут собрать ваши макеты.
Горизонтальное и вертикальное соединение абзацев очень просто.
// 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 )
Иногда при создании макетов вам может понадобиться знать ширину и высоту текстовых блоков.
// 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 )
Иногда вам просто захочется поместить блок текста в пробел.
// 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 )
Вы также можете стилизовать пробелы. Подробности смотрите в документации.
Блеск для губ поставляется с подпакетом для настольного рендеринга.
import "github.com/charmbracelet/lipgloss/table"
Определите несколько строк данных.
rows := [][] string {
{ "Chinese" , "您好" , "你好" },
{ "Japanese" , "こんにちは" , "やあ" },
{ "Arabic" , "أهلين" , "أهلا" },
{ "Russian" , "Здравствуйте" , "Привет" },
{ "Spanish" , "Hola" , "¿Qué tal?" },
}
Используйте пакет table для стилизации и визуализации таблицы.
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?" )
Распечатайте таблицу.
fmt . Println ( t )
Предупреждение
Rows
таблицы должны быть объявлены перед Offset
иначе ничего не произойдет.
Дополнительную информацию о таблицах см. в документации и примерах.
Блеск для губ поставляется с дополнительным пакетом рендеринга списка.
import "github.com/charmbracelet/lipgloss/list"
Определите новый список.
l := list . New ( "A" , "B" , "C" )
Распечатайте список.
fmt . Println ( l )
// • A
// • B
// • C
Списки имеют возможность вложенности.
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" ),
)
Распечатайте список.
fmt . Println ( l )
Списки можно настраивать с помощью функции перечисления, а также с помощью lipgloss.Style
.
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 )
Распечатайте список.
В дополнение к предопределенным перечислителям ( Arabic
, Alphabet
, Roman
, Bullet
, Tree
) вы также можете определить свой собственный перечислитель:
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 )
Распечатайте список:
Если вам нужно, вы также можете создавать списки постепенно:
l := list . New ()
for i := 0 ; i < repeat ; i ++ {
l . Item ( "Lip Gloss" )
}
Блеск для губ поставляется с подпакетом для рендеринга дерева.
import "github.com/charmbracelet/lipgloss/tree"
Определите новое дерево.
t := tree . Root ( "." ).
Child ( "A" , "B" , "C" )
Распечатайте дерево.
fmt . Println ( t )
// .
// ├── A
// ├── B
// └── C
Деревья обладают способностью гнездиться.
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" ),
)
Распечатайте дерево.
fmt . Println ( t )
Деревья можно настраивать с помощью функции перечисления, а также с помощью lipgloss.Style
.
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 )
Распечатайте дерево.
Предопределенными перечислителями для деревьев являются DefaultEnumerator
и RoundedEnumerator
.
Если вам нужно, вы также можете строить деревья постепенно:
t := tree . New ()
for i := 0 ; i < repeat ; i ++ {
t . Child ( "Lip Gloss" )
}
Скорее всего, это связано с вашей локалью и кодировкой, особенно в отношении китайского, японского и корейского языков (например, zh_CN.UTF-8
или ja_JP.UTF-8
). Самый прямой способ исправить это — установить RUNEWIDTH_EASTASIAN=0
в вашей среде.
Подробности см. на https://github.com/charmbracelet/lipgloss/issues/40.
Lip Gloss автоматически снижает качество цветов до наилучшего доступного варианта в данном терминале, а если вывод не является TTY, он полностью удаляет цветной вывод. Это часто случается при запуске тестов, CI или при передаче вывода в другое место.
При необходимости вы можете принудительно использовать цветовой профиль в своих тестах с помощью SetColorProfile
.
import (
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
)
lipgloss . SetColorProfile ( termenv . TrueColor )
Примечание. Этот параметр ограничивает гибкость вашего приложения и может привести к выводу escape-кодов ANSI в тех случаях, когда это может быть нежелательно. Прежде чем принудительно использовать цветовой профиль, внимательно изучите свой вариант использования и среду.
Блеск для губ не заменяет Bubble Tea. Скорее, это отличный компаньон Bubble Tea. Он был разработан, чтобы сделать сборку представлений пользовательского интерфейса терминала максимально простой и увлекательной, чтобы вы могли сосредоточиться на создании своего приложения, а не беспокоиться о деталях макета низкого уровня.
Проще говоря, вы можете использовать блеск для губ, чтобы создать образ Bubble Tea.
Lip Gloss построен на основе превосходных библиотек Termenv и Reflow, которые работают с цветом и текстовыми операциями с поддержкой ANSI соответственно. Во многих случаях использования Termenv и Reflow будет достаточно для ваших нужд.
Чтобы получить более ориентированное на документы решение для рендеринга с поддержкой таких вещей, как списки, таблицы и код с подсветкой синтаксиса, обратите внимание на Glamour, средство рендеринга Markdown на основе таблиц стилей.
См. вклад.
Мы хотели бы услышать ваши мысли об этом проекте. Не стесняйтесь, напишите нам!
Массачусетский технологический институт
Часть очарования.
Charm热爱开源 • Charm любит открытый исходный код