漂亮的終端佈局的樣式定義。建置時考慮了 TUI。
Lip Gloss 採用富有表現力的聲明性方法進行終端渲染。熟悉 CSS 的用戶會對 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" ))
唇彩支援以下顏色設定檔:
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 指定真彩色、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" },
}
Lip Gloss 支援常用的 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
當規則被取消設定時,它不會被繼承或複製。
有時,例如在開發元件時,您希望確保樣式定義尊重其在 UI 中的預期用途。這就是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
通常,您只需在lipgloss.Style
上呼叫Render(string...)
方法:
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 範例。
除了純粹的造型之外,唇彩還附帶一些實用程式來幫助您組裝佈局。
水平和垂直連接段落輕而易舉。
// 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 )
警告
Table 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 )
注意:此選項限制了應用程式的靈活性,並且可能會導致在不需要的情況下輸出 ANSI 轉義碼。在選擇強制使用顏色設定檔之前,請仔細記下您的用例和環境。
唇彩並不能取代珍珠奶茶。相反,它是絕佳的珍珠奶茶伴侶。它旨在使組裝終端使用者介面視圖盡可能簡單和有趣,以便您可以專注於建立應用程序,而不用擔心底層佈局細節。
簡而言之,您可以使用唇彩來幫助建立您的珍珠奶茶視野。
Lip Gloss 建立在優秀的 Termenv 和 Reflow 庫之上,它們分別處理顏色和 ANSI 感知文字操作。對於許多用例,Termenv 和 Reflow 足以滿足您的需求。
要獲得更以文件為中心的渲染解決方案,並支援清單、表格和語法突出顯示程式碼等內容,請查看 Glamour,它是基於樣式表的 Markdown 渲染器。
請參閱貢獻。
我們很想聽聽您對此項目的想法。請隨時給我們留言!
麻省理工學院
魅力的一部分。
Charm熱愛開源 • Charm熱愛開源