Posters in macOS Terminal as plain colored cells
Terminal.app draws block elements from the font, with the halves off the cell's middle, so quadrant posters came out as rows of shifted dots. The new cover style "cells" uses one background color per cell and no glyph; auto picks it when TERM_PROGRAM is Apple_Terminal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019reK4DUGYqDUjniWYJvwUW
This commit is contained in:
+13
-2
@@ -95,6 +95,10 @@ var (
|
||||
// sextantStyle (2×3 pixels): sharper, but the glyphs live in the Symbols
|
||||
// for Legacy Computing block, which many fonts lack.
|
||||
sextantStyle = coverStyle{"sextant", 2, 3, sextantGlyph}
|
||||
// cellsStyle (1 pixel per cell): only background colors, no glyphs at all.
|
||||
// Coarse, but exact in terminals that draw block elements from the font
|
||||
// with the halves off the cell's middle (macOS Terminal).
|
||||
cellsStyle = coverStyle{"cells", 1, 1, func(int) rune { return ' ' }}
|
||||
)
|
||||
|
||||
// quadrants[mask] is the glyph that fills the quadrants set in mask
|
||||
@@ -127,14 +131,21 @@ func sextantGlyph(mask int) rune {
|
||||
}
|
||||
|
||||
// coverStyleFor resolves the block-character style for the setting. "auto"
|
||||
// picks sextants on terminals known to have the glyphs and quadrants everywhere
|
||||
// else.
|
||||
// picks sextants on terminals known to have the glyphs, plain cells in macOS
|
||||
// Terminal and quadrants everywhere else.
|
||||
func coverStyleFor(setting string, env func(string) string) coverStyle {
|
||||
switch setting {
|
||||
case "sextant":
|
||||
return sextantStyle
|
||||
case "quadrant":
|
||||
return quadrantStyle
|
||||
case "cells":
|
||||
return cellsStyle
|
||||
}
|
||||
// Terminal.app draws block elements from the font, and their halves do
|
||||
// not meet at the cell's middle: rows of a poster come out uneven.
|
||||
if env("TERM_PROGRAM") == "Apple_Terminal" {
|
||||
return cellsStyle
|
||||
}
|
||||
term, program := strings.ToLower(env("TERM")), strings.ToLower(env("TERM_PROGRAM"))
|
||||
for _, known := range []string{"kitty", "foot", "ghostty", "wezterm"} {
|
||||
|
||||
@@ -275,6 +275,9 @@ func TestCoverStyleFor(t *testing.T) {
|
||||
{"auto", nil, "quadrant"},
|
||||
{"quadrant", map[string]string{"TERM": "xterm-kitty"}, "quadrant"},
|
||||
{"sextant", nil, "sextant"},
|
||||
{"auto", map[string]string{"TERM": "xterm-256color", "TERM_PROGRAM": "Apple_Terminal"}, "cells"},
|
||||
{"cells", map[string]string{"TERM": "xterm-kitty"}, "cells"},
|
||||
{"quadrant", map[string]string{"TERM_PROGRAM": "Apple_Terminal"}, "quadrant"},
|
||||
} {
|
||||
if got := coverStyleFor(tc.setting, env(tc.env)).name; got != tc.want {
|
||||
t.Errorf("%q %v = %s, want %s", tc.setting, tc.env, got, tc.want)
|
||||
@@ -347,3 +350,11 @@ func TestDescribeBytesAndTheErrorItGives(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCellsStyleIsFlat(t *testing.T) {
|
||||
c := color.RGBA{10, 200, 30, 255}
|
||||
ch, fg, bg := cellsStyle.bestCell([]color.RGBA{c})
|
||||
if ch != ' ' || fg != c || bg != c {
|
||||
t.Errorf("got %q %v %v", ch, fg, bg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ type settingsValues struct {
|
||||
notify, bell bool
|
||||
}
|
||||
|
||||
var coverStyles = []string{"auto", "kitty", "sextant", "quadrant"}
|
||||
var coverStyles = []string{"auto", "kitty", "sextant", "quadrant", "cells"}
|
||||
|
||||
// settingsFrom reads the settings in use.
|
||||
func settingsFrom(c *config.Config) settingsValues {
|
||||
|
||||
Reference in New Issue
Block a user