Definisi gaya untuk tata letak terminal yang bagus. Dibangun dengan mempertimbangkan TUI.
Lip Gloss mengambil pendekatan deklaratif dan ekspresif pada rendering terminal. Pengguna yang akrab dengan CSS akan merasa betah dengan 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 mendukung profil warna berikut:
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
...serta profil ASCII 1-bit, yang hanya berwarna hitam putih.
Profil warna terminal akan terdeteksi secara otomatis, dan warna di luar gamut palet saat ini akan secara otomatis dipaksa ke nilai terdekat yang tersedia.
Anda juga dapat menentukan pilihan warna untuk latar belakang terang dan gelap:
lipgloss. AdaptiveColor { Light : "236" , Dark : "248" }
Warna latar belakang terminal secara otomatis akan terdeteksi dan warna yang sesuai akan dipilih pada saat runtime.
CompleteColor menentukan nilai pasti untuk profil warna True Color, ANSI256, dan ANSI.
lipgloss. CompleteColor { TrueColor : "#0000FF" , ANSI256 : "86" , ANSI : "5" }
Degradasi warna otomatis tidak akan dilakukan dalam kasus ini dan akan didasarkan pada warna yang ditentukan.
Anda dapat menggunakan CompleteColor
dengan AdaptiveColor
untuk menentukan nilai pasti untuk latar belakang terang dan gelap tanpa degradasi warna otomatis.
lipgloss. CompleteAdaptiveColor {
Light : CompleteColor { TrueColor : "#d7ffae" , ANSI256 : "193" , ANSI : "11" },
Dark : CompleteColor { TrueColor : "#d75fee" , ANSI256 : "163" , ANSI : "5" },
}
Lip Gloss mendukung opsi pemformatan teks ANSI yang biasa:
var style = lipgloss . NewStyle ().
Bold ( true ).
Italic ( true ).
Faint ( true ).
Blink ( true ).
Strikethrough ( true ).
Underline ( true ).
Reverse ( true )
Lip Gloss juga mendukung aturan untuk pemformatan tingkat blok:
// 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 )
Ada juga sintaks singkat untuk margin dan padding, yang mengikuti format yang sama seperti 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 )
Anda dapat meratakan paragraf teks ke kiri, kanan, atau tengah.
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
Menetapkan lebar dan tinggi minimum itu sederhana dan mudah.
var style = lipgloss . NewStyle ().
SetString ( "What’s for lunch?" ).
Width ( 24 ).
Height ( 32 ).
Foreground ( lipgloss . Color ( "63" ))
Menambahkan batas itu mudah:
// 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 : "*" ,
}
Ada juga fungsi singkatan untuk menentukan batas, yang mengikuti pola yang mirip dengan fungsi singkatan margin dan 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 )
Untuk informasi lebih lanjut mengenai perbatasan, lihat dokumen.
Cukup gunakan tugas:
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
Karena struktur data Style
hanya berisi tipe primitif, menetapkan gaya ke gaya lain secara efektif akan membuat salinan gaya baru tanpa mengubah gaya aslinya.
Gaya dapat mewarisi aturan dari gaya lain. Saat mewarisi, hanya aturan yang tidak ditetapkan pada penerima yang diwarisi.
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 )
Semua aturan dapat dibatalkan:
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
Jika aturan tidak disetel, aturan tersebut tidak akan diwarisi atau disalin.
Terkadang, misalnya saat mengembangkan komponen, Anda ingin memastikan definisi gaya sesuai dengan tujuan yang dimaksudkan di UI. Di sinilah Inline
dan MaxWidth
, dan MaxHeight
berperan:
// 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" )
Karakter tab ( t
) ditampilkan secara berbeda di terminal yang berbeda (seringkali 8 spasi, terkadang 4). Karena ketidakkonsistenan ini, Lip Gloss mengubah tab menjadi 4 spasi pada waktu render. Namun perilaku ini dapat diubah berdasarkan gaya:
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
Umumnya, Anda cukup memanggil metode Render(string...)
pada lipgloss.Style
:
style := lipgloss . NewStyle (). Bold ( true ). SetString ( "Hello," )
fmt . Println ( style . Render ( "kitty." )) // Hello, kitty.
fmt . Println ( style . Render ( "puppy." )) // Hello, puppy.
Tapi Anda juga bisa menggunakan antarmuka Stringer:
var style = lipgloss . NewStyle (). SetString ( "你好,猫咪。" ). Bold ( true )
fmt . Println ( style ) // 你好,猫咪。
Perender khusus memungkinkan Anda merender ke keluaran tertentu. Hal ini sangat penting ketika Anda ingin merender ke keluaran yang berbeda dan mendeteksi dengan benar profil warna dan status latar belakang gelap untuk masing-masing keluaran, seperti dalam situasi server-klien.
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" ))
}
Untuk contoh penggunaan penyaji khusus melalui SSH dengan Wish, lihat contoh SSH.
Selain penataan murni, Lip Gloss juga dilengkapi dengan beberapa utilitas untuk membantu menyusun tata letak Anda.
Menggabungkan paragraf secara horizontal dan vertikal sangatlah mudah.
// 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 )
Terkadang Anda ingin mengetahui lebar dan tinggi blok teks saat membuat tata letak.
// 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 )
Terkadang Anda hanya ingin menempatkan blok teks di spasi.
// 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 )
Anda juga dapat menata spasi. Untuk detailnya, lihat dokumen.
Lip Gloss dikirimkan dengan sub-paket rendering tabel.
import "github.com/charmbracelet/lipgloss/table"
Tentukan beberapa baris data.
rows := [][] string {
{ "Chinese" , "您好" , "你好" },
{ "Japanese" , "こんにちは" , "やあ" },
{ "Arabic" , "أهلين" , "أهلا" },
{ "Russian" , "Здравствуйте" , "Привет" },
{ "Spanish" , "Hola" , "¿Qué tal?" },
}
Gunakan paket tabel untuk menata gaya dan merender tabel.
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?" )
Cetak tabelnya.
fmt . Println ( t )
Peringatan
Rows
Tabel perlu dideklarasikan sebelum Offset
jika tidak maka tidak akan menghasilkan apa-apa.
Untuk informasi lebih lanjut tentang tabel, lihat dokumen dan contoh.
Lip Gloss dikirimkan dengan sub-paket rendering daftar.
import "github.com/charmbracelet/lipgloss/list"
Tentukan daftar baru.
l := list . New ( "A" , "B" , "C" )
Cetak daftarnya.
fmt . Println ( l )
// • A
// • B
// • C
Daftar memiliki kemampuan untuk bersarang.
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" ),
)
Cetak daftarnya.
fmt . Println ( l )
Daftar dapat dikustomisasi melalui fungsi enumerasinya serta menggunakan 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 )
Cetak daftarnya.
Selain enumerator yang telah ditentukan sebelumnya ( Arabic
, Alphabet
, Roman
, Bullet
, Tree
), Anda juga dapat menentukan enumerator khusus Anda sendiri:
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 )
Cetak daftarnya:
Jika perlu, Anda juga dapat membuat daftar secara bertahap:
l := list . New ()
for i := 0 ; i < repeat ; i ++ {
l . Item ( "Lip Gloss" )
}
Lip Gloss dikirimkan dengan sub-paket rendering pohon.
import "github.com/charmbracelet/lipgloss/tree"
Tentukan pohon baru.
t := tree . Root ( "." ).
Child ( "A" , "B" , "C" )
Cetak pohonnya.
fmt . Println ( t )
// .
// ├── A
// ├── B
// └── C
Pohon mempunyai kemampuan untuk bersarang.
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" ),
)
Cetak pohonnya.
fmt . Println ( t )
Pohon dapat dikustomisasi melalui fungsi enumerasinya serta menggunakan 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 )
Cetak pohonnya.
Enumerator yang telah ditentukan sebelumnya untuk pohon adalah DefaultEnumerator
dan RoundedEnumerator
.
Jika perlu, Anda juga dapat membangun pohon secara bertahap:
t := tree . New ()
for i := 0 ; i < repeat ; i ++ {
t . Child ( "Lip Gloss" )
}
Hal ini kemungkinan besar disebabkan oleh lokal dan pengkodean Anda, terutama yang berkaitan dengan bahasa China, Jepang, dan Korea (misalnya, zh_CN.UTF-8
atau ja_JP.UTF-8
). Cara paling langsung untuk memperbaikinya adalah dengan menyetel RUNEWIDTH_EASTASIAN=0
di lingkungan Anda.
Untuk detailnya lihat https://github.com/charmbracelet/lipgloss/issues/40.
Lip Gloss secara otomatis menurunkan warna ke pilihan terbaik yang tersedia di terminal tertentu, dan jika keluarannya bukan TTY maka akan menghilangkan keluaran warna seluruhnya. Hal ini biasa terjadi saat menjalankan pengujian, CI, atau saat menyalurkan output ke tempat lain.
Jika perlu, Anda dapat memaksakan profil warna dalam pengujian Anda dengan SetColorProfile
.
import (
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
)
lipgloss . SetColorProfile ( termenv . TrueColor )
Catatan: opsi ini membatasi fleksibilitas aplikasi Anda dan dapat menyebabkan kode escape ANSI dikeluarkan jika hal tersebut mungkin tidak diinginkan. Perhatikan baik-baik kasus penggunaan dan lingkungan Anda sebelum memilih untuk memaksakan profil warna.
Lip Gloss tidak menggantikan Bubble Tea. Sebaliknya, ini adalah pendamping Bubble Tea yang luar biasa. Ini dirancang untuk membuat perakitan tampilan antarmuka pengguna terminal sesederhana dan semenyenangkan mungkin sehingga Anda dapat fokus membangun aplikasi Anda alih-alih memikirkan detail tata letak tingkat rendah.
Secara sederhana, Anda dapat menggunakan Lip Gloss untuk membantu membangun tampilan Bubble Tea Anda.
Lip Gloss dibangun di atas pustaka Termenv dan Reflow luar biasa yang masing-masing menangani pengoperasian teks yang mendukung warna dan ANSI. Untuk banyak kasus penggunaan, Termenv dan Reflow akan mencukupi kebutuhan Anda.
Untuk solusi rendering yang lebih berpusat pada dokumen dengan dukungan untuk hal-hal seperti daftar, tabel, dan kode yang disorot sintaks, lihat Glamour, perender Markdown berbasis stylesheet.
Lihat berkontribusi.
Kami ingin mendengar pendapat Anda tentang proyek ini. Jangan ragu untuk mengirimkan pesan kepada kami!
MIT
Bagian dari Pesona.
Charm热爱开源 • Charm menyukai open source