Documentation
¶
Overview ¶
Package art fetches cover art and draws it in the terminal: with the Kitty graphics protocol, iTerm2 inline images, or sixel when the terminal supports one of them, and with colored half-block characters otherwise.
Index ¶
- Constants
- Variables
- func Accent(img image.Image, appleBG string) lipgloss.Color
- func DetectFullScreen(env func(string) string, isTTY bool, t Terminal) (Protocol, Probe)
- func Fetch(ctx context.Context, songLink, appleArtworkURL string, size int) (image.Image, error)
- func KittyDelete(id uint32) string
- func KittyPlaceholders(id uint32, cols, rows int) string
- func KittyTransmit(img image.Image, id uint32, cols, rows int, cell CellSize) string
- func Render(img image.Image, cols, rows int, p Protocol) string
- func RenderCell(img image.Image, cols, rows int, p Protocol, cell CellSize) string
- func SourceURL(songLink, appleArtworkURL string, size int) string
- func To256(r, g, b uint8) int
- type CellSize
- type Probe
- type Protocol
- type Terminal
Constants ¶
const QueryTimeout = 150 * time.Millisecond
QueryTimeout is how long Query waits for the terminal to answer.
const RemoteQueryTimeout = 600 * time.Millisecond
RemoteQueryTimeout is how long Query waits over SSH, where a reply can take a network round trip. A reply that came after the wait would be read as keystrokes once the view starts.
Variables ¶
CacheDir is where fetched images are kept (CacheDir()/art by default).
var DefaultCell = CellSize{W: 10, H: 20}
DefaultCell is the cell size assumed when the terminal does not report one: about twice as tall as wide, like most terminal fonts.
var ErrNoArt = errors.New("no cover art for this result")
ErrNoArt means the result has no cover art source (no Apple Music artwork and a song_link that is not on lis.tn).
var HTTPClient = &http.Client{Timeout: 10 * time.Second}
HTTPClient fetches cover art. Tests replace it.
Functions ¶
func Accent ¶
Accent picks a color that matches the cover: Apple Music's artwork bgColor when known (a hex string such as "1a2b3c"), else the dominant saturated color of img. It returns "" (no color) when there is neither. Very dark or very light colors are pulled toward the middle so the accent stays readable on both dark and light terminals.
func DetectFullScreen ¶
DetectFullScreen picks the protocol for full-screen views, which redraw the screen as text and so need images that can be placed in cells:
- Kitty and Ghostty: Kitty graphics with Unicode placeholders.
- iTerm2 and WezTerm: iTerm2 inline images. WezTerm draws Kitty images but not Unicode placeholders.
- VS Code: iTerm2 inline images when its terminal has images turned on, which it reports as sixel support in DA1.
- Konsole, and any terminal whose DA1 reply lists sixel: sixel.
- Everything else: half-blocks, in true color when available.
t is the terminal to query, or nil when stdin is not a terminal; it is asked for DA1 and its cell size unless AUDD_ART turns art off or picks half-blocks, or a multiplexer (tmux, screen) is in between, which would answer for itself. The wait is longer over SSH. AUDD_ART overrides the choice as in Detect.
func Fetch ¶
Fetch downloads (or reads from the disk cache) the cover for a result and decodes it. size is the requested edge in pixels for Apple artwork.
func KittyDelete ¶
KittyDelete frees image id and its placements in the terminal.
func KittyPlaceholders ¶
KittyPlaceholders returns rows lines of cols Unicode placeholder cells (U+10EEEE) for image id. The foreground color carries the image id and two combining marks on each cell carry its row and column, so the cells show the image wherever they are drawn and can be moved, redrawn, or replaced like any other text.
func KittyTransmit ¶
KittyTransmit sends img to the terminal under image id and creates a virtual placement of cols×rows cells (U=1), which KittyPlaceholders then shows wherever its cells are printed. q=2 silences the terminal's replies. id must be between 1 and 2^24-1.
func Render ¶
Render draws img in a box of cols×rows terminal cells. The half-block protocols return rows lines of colored "▀" cells separated by newlines; Kitty, iTerm2, and sixel return a single escape sequence that the terminal draws over cols×rows cells starting at the cursor. ProtoNone and an empty box return "".
Cover art is square and a cell is about twice as tall as it is wide, so cols = 2×rows keeps the picture square.
func RenderCell ¶
RenderCell is Render for a terminal whose cells are cell pixels in size, which sets the pixel size of images sent with Kitty, iTerm2, and sixel.
Types ¶
type CellSize ¶
type CellSize struct{ W, H int }
CellSize is the size of one terminal character cell in pixels.
func CellSizeOf ¶
CellSizeOf returns the cell size of the terminal on f from the pixel fields of TIOCGWINSZ. Terminals that leave them at zero report false.
type Probe ¶
type Probe struct {
// Answered is set when the terminal replied to the device attributes
// (DA1) query.
Answered bool
// Sixel is set when the DA1 reply lists sixel graphics (attribute 4).
Sixel bool
// Cell is the cell size from the CSI 16 t reply; zero when unknown.
Cell CellSize
}
Probe is what a terminal said about itself.
type Protocol ¶
type Protocol int
Protocol is a way of drawing an image in a terminal.
const ( ProtoNone Protocol = iota // no images (not a terminal, TERM=dumb, or turned off) ProtoKitty // Kitty graphics protocol (Kitty, Ghostty, WezTerm, Konsole) ProtoITerm2 // iTerm2 inline images ProtoSixel // DEC sixel graphics ProtoHalfBlock // true-color "▀" cells // ProtoHalfBlock256 is the half-block fallback for terminals without // true color; colors are mapped to the 256-color palette. ProtoHalfBlock256 )
func Cells ¶
Cells returns the character-cell fallback for p: half-blocks in true color or 256 colors, following the terminal's color support.
func Detect ¶
Detect picks the best protocol from the environment. Images are only drawn on a terminal. AUDD_ART (kitty, iterm2, sixel, blocks, blocks256, none) overrides the detection. Inside tmux or screen, which do not pass images through by default, it uses half-blocks.
Detect does not query the terminal. Sixel is found from TERM (names containing "sixel", foot, mlterm, contour); DetectFullScreen also asks the terminal (DA1) and so finds the others.
func (Protocol) IsGraphics ¶
IsGraphics reports whether p draws real pixels (Kitty, iTerm2, sixel) rather than colored characters.
type Terminal ¶
type Terminal interface {
io.Writer
// ReadTimeout reads what the terminal sent, waiting at most d. It
// returns 0 and a nil error when nothing arrived in time.
ReadTimeout(p []byte, d time.Duration) (int, error)
}
Terminal is a terminal that can be asked questions: requests are written to it and replies read back with a timeout.