Module: Everywhere::UI
- Defined in:
- lib/everywhere/ui.rb
Overview
Terminal output helpers. Colors follow the informal standard: on when stdout is a TTY or CLICOLOR_FORCE=1, always off when NO_COLOR is set.
The hosted runner streams every release through a pipe (not a TTY) into the
Platform web log, so it exports CLICOLOR_FORCE=1 to keep our color — the web
UI renders ANSI. That's why we force rather than sniff the TTY there.
Class Method Summary collapse
- .bad(msg) ⇒ Object
- .bad_line(msg) ⇒ Object
- .blue(t) ⇒ Object
- .bold(t) ⇒ Object
- .color? ⇒ Boolean
- .cyan(t) ⇒ Object
- .detail(msg) ⇒ Object
- .detail_line(msg) ⇒ Object
- .die!(msg) ⇒ Object
- .dim(t) ⇒ Object
-
.gray(t) ⇒ Object
bright black — dimmer than dim() on most themes.
- .green(t) ⇒ Object
- .magenta(t) ⇒ Object
- .note(msg, marker: "·", color: :gray) ⇒ Object
-
.note_line(msg, marker: "·", color: :gray) ⇒ Object
An indented, dim outcome under a substep — e.g.
- .ok(msg) ⇒ Object
- .ok_line(msg) ⇒ Object
- .paint(text, *codes) ⇒ Object
- .phase(msg) ⇒ Object
-
.phase_line(msg) ⇒ Object
--- output levels --------------------------------------------------------.
- .red(t) ⇒ Object
-
.short_path(str) ⇒ Object
Collapse the noisy machine paths that external tools echo (codesign, notarytool, stapler) down to something a human can scan.
- .step(msg) ⇒ Object
- .step_line(msg) ⇒ Object
- .substep(msg) ⇒ Object
- .substep_line(msg) ⇒ Object
- .success(msg) ⇒ Object
- .success_line(msg) ⇒ Object
- .warn(msg) ⇒ Object
- .warn_line(msg) ⇒ Object
- .yellow(t) ⇒ Object
-
.yn(bool) ⇒ Object
A yes/no fact, colored by truthiness (for signing receipts).
Class Method Details
.bad(msg) ⇒ Object
59 |
# File 'lib/everywhere/ui.rb', line 59 def bad(msg) = puts(bad_line(msg)) |
.bad_line(msg) ⇒ Object
50 |
# File 'lib/everywhere/ui.rb', line 50 def bad_line(msg) = "#{red("✗")} #{msg}" |
.blue(t) ⇒ Object
29 |
# File 'lib/everywhere/ui.rb', line 29 def blue(t) = paint(t, 34) |
.bold(t) ⇒ Object
24 |
# File 'lib/everywhere/ui.rb', line 24 def bold(t) = paint(t, 1) |
.color? ⇒ Boolean
13 14 15 16 17 18 |
# File 'lib/everywhere/ui.rb', line 13 def color? return false if ENV["NO_COLOR"] return true if ENV["CLICOLOR_FORCE"] == "1" $stdout.tty? end |
.cyan(t) ⇒ Object
31 |
# File 'lib/everywhere/ui.rb', line 31 def cyan(t) = paint(t, 36) |
.detail(msg) ⇒ Object
57 |
# File 'lib/everywhere/ui.rb', line 57 def detail(msg) = puts(detail_line(msg)) |
.detail_line(msg) ⇒ Object
48 |
# File 'lib/everywhere/ui.rb', line 48 def detail_line(msg) = " #{gray("·")} #{gray(msg)}" |
.die!(msg) ⇒ Object
71 72 73 |
# File 'lib/everywhere/ui.rb', line 71 def die!(msg) abort "#{red("✗")} #{red(msg)}" end |
.dim(t) ⇒ Object
25 |
# File 'lib/everywhere/ui.rb', line 25 def dim(t) = paint(t, 2) |
.gray(t) ⇒ Object
bright black — dimmer than dim() on most themes
32 |
# File 'lib/everywhere/ui.rb', line 32 def gray(t) = paint(t, 90) # bright black — dimmer than dim() on most themes |
.green(t) ⇒ Object
27 |
# File 'lib/everywhere/ui.rb', line 27 def green(t) = paint(t, 32) |
.magenta(t) ⇒ Object
30 |
# File 'lib/everywhere/ui.rb', line 30 def magenta(t) = paint(t, 35) |
.note(msg, marker: "·", color: :gray) ⇒ Object
69 |
# File 'lib/everywhere/ui.rb', line 69 def note(msg, marker: "·", color: :gray) = puts(note_line(msg, marker: marker, color: color)) |
.note_line(msg, marker: "·", color: :gray) ⇒ Object
An indented, dim outcome under a substep — e.g. "accepted", "valid on disk".
64 65 66 67 |
# File 'lib/everywhere/ui.rb', line 64 def note_line(msg, marker: "·", color: :gray) tint = respond_to?(color) ? method(color) : method(:gray) " #{tint.call(marker)} #{tint.call(msg)}" end |
.ok(msg) ⇒ Object
58 |
# File 'lib/everywhere/ui.rb', line 58 def ok(msg) = puts(ok_line(msg)) |
.ok_line(msg) ⇒ Object
49 |
# File 'lib/everywhere/ui.rb', line 49 def ok_line(msg) = "#{green("✓")} #{msg}" |
.paint(text, *codes) ⇒ Object
20 21 22 |
# File 'lib/everywhere/ui.rb', line 20 def paint(text, *codes) color? ? "\e[#{codes.join(";")}m#{text}\e[0m" : text.to_s end |
.phase(msg) ⇒ Object
54 |
# File 'lib/everywhere/ui.rb', line 54 def phase(msg) = puts(phase_line(msg)) |
.phase_line(msg) ⇒ Object
--- output levels --------------------------------------------------------
phase ● a major phase boundary (build / sign / notarize)
step → a top-level action inside a phase
substep ▸ a sub-action under a step (indented)
detail · raw-ish detail under a substep (indented + dim)
Every level has a *_line string builder (used by LogFilter, which returns lines for someone else to print) and a printer that puts it. ok / success / warn / bad / die! carry outcomes at any level.
45 |
# File 'lib/everywhere/ui.rb', line 45 def phase_line(msg) = "\n#{bold(cyan("●"))} #{bold(msg)}" |
.red(t) ⇒ Object
26 |
# File 'lib/everywhere/ui.rb', line 26 def red(t) = paint(t, 31) |
.short_path(str) ⇒ Object
Collapse the noisy machine paths that external tools echo (codesign,
notarytool, stapler) down to something a human can scan. In particular the
runner works out of a deep /var/folders/…/every-runner…/src/ sandbox — we
strip that prefix so only the meaningful dist/App.app tail remains. Then
$HOME → ~ and the cwd → a leading (dropped) prefix.
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/everywhere/ui.rb', line 85 def short_path(str) s = str.to_s.dup # Runner/local temp sandboxes: keep only the part after the extracted src/. s = s.gsub(%r{/(?:private/)?(?:var|tmp)/[^\s"']*?/every-[a-z]+[0-9A-Za-z_-]+/src/}, "") # Any other everywhere-* scratch dir: keep the basename tail. s = s.gsub(%r{/(?:private/)?(?:var|tmp)/[^\s"']*?/everywhere-[a-z]+[0-9A-Za-z_.-]*/}, "") home = ENV["HOME"] s = s.gsub("#{home}/", "~/") if home && !home.empty? s end |
.step(msg) ⇒ Object
55 |
# File 'lib/everywhere/ui.rb', line 55 def step(msg) = puts(step_line(msg)) |
.step_line(msg) ⇒ Object
46 |
# File 'lib/everywhere/ui.rb', line 46 def step_line(msg) = "#{cyan("→")} #{msg}" |
.substep(msg) ⇒ Object
56 |
# File 'lib/everywhere/ui.rb', line 56 def substep(msg) = puts(substep_line(msg)) |
.substep_line(msg) ⇒ Object
47 |
# File 'lib/everywhere/ui.rb', line 47 def substep_line(msg) = " #{cyan("▸")} #{msg}" |
.success(msg) ⇒ Object
61 |
# File 'lib/everywhere/ui.rb', line 61 def success(msg) = puts(success_line(msg)) |
.success_line(msg) ⇒ Object
52 |
# File 'lib/everywhere/ui.rb', line 52 def success_line(msg) = "#{green("✓")} #{bold(msg)}" |
.warn(msg) ⇒ Object
60 |
# File 'lib/everywhere/ui.rb', line 60 def warn(msg) = puts(warn_line(msg)) |
.warn_line(msg) ⇒ Object
51 |
# File 'lib/everywhere/ui.rb', line 51 def warn_line(msg) = "#{yellow("!")} #{msg}" |
.yellow(t) ⇒ Object
28 |
# File 'lib/everywhere/ui.rb', line 28 def yellow(t) = paint(t, 33) |
.yn(bool) ⇒ Object
A yes/no fact, colored by truthiness (for signing receipts).
76 |
# File 'lib/everywhere/ui.rb', line 76 def yn(bool) = bool ? green("yes") : red("no") |