Module: Unmagic::Browser::Console::Renderer
- Defined in:
- lib/unmagic/browser/console/renderer.rb
Overview
Turns whatever the last expression evaluated to into something worth looking at.
IRB normally echoes inspect, which for this gem means a screenful of
escaped HTML or, worse, a megabyte of PNG bytes. Every result comes
through here instead: source gets highlighted, images get drawn, and
everything else falls back to a highlighted inspect.
Constant Summary collapse
- MAX_LINES =
Long enough to read a page's shape, short enough not to lose the prompt. The value itself is untouched —
puts _still gives you all of it. 60- MAX_CHARS =
A belt to MAX_LINES' braces: one minified line of HTML is a screenful on its own.
8_000
Class Attribute Summary collapse
-
.theme ⇒ Class
Defaults to Monokai.
Class Method Summary collapse
-
.array(value) ⇒ String
A numbered list for elements, highlighted Ruby otherwise.
-
.browser(value) ⇒ String
The driver it's running against.
-
.code(value) ⇒ String
The source, highlighted and truncated.
-
.document(value) ⇒ String
Where it was written.
-
.element(value) ⇒ String
The element's tag and the text in it.
-
.emulation(value) ⇒ String
The knobs that are set, or that none are.
-
.formatter ⇒ Rouge::Formatter
Every terminal that can draw an image can also do 24-bit colour, so there's no reason to quantise to 256.
-
.highlight(source, language) ⇒ String
The source with terminal colour, or untouched without a tty or without Rouge.
-
.highlighting? ⇒ Boolean
Whether Rouge is loaded and can highlight.
-
.image(value) ⇒ String
Drawing happens as a side effect, because the image goes out as a raw escape sequence rather than as text IRB could indent or wrap.
-
.render(value) ⇒ String
What to print.
-
.ruby(source) ⇒ String
It, highlighted.
-
.session(value) ⇒ String
Where the session is, and what it's emulating.
-
.string(value) ⇒ String
The string, as prose if it's long, as Ruby if it's short.
Class Attribute Details
.theme ⇒ Class
Returns defaults to Monokai.
39 40 41 |
# File 'lib/unmagic/browser/console/renderer.rb', line 39 def theme @theme ||= Rouge::Themes::Monokai if highlighting? end |
Class Method Details
.array(value) ⇒ String
Returns a numbered list for elements, highlighted Ruby otherwise.
130 131 132 133 134 135 136 137 |
# File 'lib/unmagic/browser/console/renderer.rb', line 130 def array(value) return ruby(value.inspect) unless value.any? && value.all?(Unmagic::Browser::Element) width = value.size.to_s.length value.each_with_index.map do |item, index| "#{Terminal.dim("[#{index.to_s.rjust(width)}]")} #{element(item)}" end.join("\n") end |
.browser(value) ⇒ String
Returns the driver it's running against.
141 142 143 |
# File 'lib/unmagic/browser/console/renderer.rb', line 141 def browser(value) "#{Terminal.paint(Terminal::BOLD, "browser")} #{Terminal.dim("via #{value.driver.name}")}" end |
.code(value) ⇒ String
Returns the source, highlighted and truncated.
89 90 91 92 |
# File 'lib/unmagic/browser/console/renderer.rb', line 89 def code(value) body, omitted = clamp(value) [highlight(body, value.language), (value, omitted)].compact.join("\n") end |
.document(value) ⇒ String
Returns where it was written.
81 82 83 84 85 |
# File 'lib/unmagic/browser/console/renderer.rb', line 81 def document(value) path = Graphics.save(value) "#{Terminal.paint(Terminal::YELLOW, "[#{value.extension}]")} " + Terminal.dim("#{value.bytesize} bytes · #{path}") end |
.element(value) ⇒ String
Returns the element's tag and the text in it.
121 122 123 124 125 126 |
# File 'lib/unmagic/browser/console/renderer.rb', line 121 def element(value) text = value.text text = "#{text[0, 80]}…" if text.length > 80 tag = Terminal.paint(Terminal::BLUE, "<#{value.tag_name}>") text.empty? ? tag : "#{tag} #{text.inspect}" end |
.emulation(value) ⇒ String
Returns the knobs that are set, or that none are.
147 148 149 150 151 152 |
# File 'lib/unmagic/browser/console/renderer.rb', line 147 def emulation(value) knobs = value.to_h.compact return Terminal.dim("emulating nothing — desktop, light, screen") if knobs.empty? knobs.map { |key, setting| "#{Terminal.paint(Terminal::BLUE, key.to_s)} #{setting.inspect}" }.join("\n") end |
.formatter ⇒ Rouge::Formatter
Every terminal that can draw an image can also do 24-bit colour, so there's no reason to quantise to 256.
177 178 179 |
# File 'lib/unmagic/browser/console/renderer.rb', line 177 def formatter @formatter ||= Rouge::Formatters::TerminalTruecolor.new(theme.new) end |
.highlight(source, language) ⇒ String
Returns the source with terminal colour, or untouched without a tty or without Rouge.
164 165 166 167 168 169 170 171 |
# File 'lib/unmagic/browser/console/renderer.rb', line 164 def highlight(source, language) return source unless Terminal.tty? && highlighting? lexer = Rouge::Lexer.find(language) || Rouge::Lexers::PlainText formatter.format(lexer.new.lex(source)).chomp rescue StandardError source # Never let a highlighting failure swallow the value itself. end |
.highlighting? ⇒ Boolean
Returns whether Rouge is loaded and can highlight.
44 45 46 |
# File 'lib/unmagic/browser/console/renderer.rb', line 44 def highlighting? defined?(Rouge) ? true : false end |
.image(value) ⇒ String
Drawing happens as a side effect, because the image goes out as a raw escape sequence rather than as text IRB could indent or wrap.
71 72 73 74 75 76 77 |
# File 'lib/unmagic/browser/console/renderer.rb', line 71 def image(value) path = Graphics.show(value) width, height = value.dimensions size = width ? "#{width}×#{height}" : "#{value.bytesize} bytes" caption = Terminal.dim("#{size} · #{path}") Terminal.graphics? ? caption : "#{Terminal.paint(Terminal::YELLOW, "[image]")} #{caption}" end |
.render(value) ⇒ String
Returns what to print.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/unmagic/browser/console/renderer.rb', line 50 def render(value) case value when Image then image(value) when Document then document(value) when Code then code(value) when Unmagic::Browser::Session then session(value) when Unmagic::Browser::Element then element(value) when Unmagic::Browser then browser(value) when Unmagic::Browser::Emulation then emulation(value) when Array then array(value) when String then string(value) when nil then Terminal.dim("nil") else ruby(value.inspect) end end |
.ruby(source) ⇒ String
Returns it, highlighted.
156 157 158 |
# File 'lib/unmagic/browser/console/renderer.rb', line 156 def ruby(source) highlight(source, "ruby") end |
.session(value) ⇒ String
Returns where the session is, and what it's emulating.
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/unmagic/browser/console/renderer.rb', line 105 def session(value) return Terminal.paint(Terminal::GREY, "session (closed)") if value.closed? # Plenty of pages have no <title> — Hacker News' login page, for one # — and a bold empty string reads as something having gone wrong. title = value.title.to_s.strip heading = title.empty? ? Terminal.dim("(untitled)") : Terminal.paint(Terminal::BOLD, title) lines = ["#{Terminal.paint(Terminal::GREEN, "●")} #{heading}"] lines << Terminal.dim(" #{value.current_url}") knobs = value.emulation.to_h.compact lines << Terminal.dim(" emulating #{describe(knobs)}") if knobs.any? lines.join("\n") end |
.string(value) ⇒ String
Returns the string, as prose if it's long, as Ruby if it's short.
96 97 98 99 100 101 |
# File 'lib/unmagic/browser/console/renderer.rb', line 96 def string(value) return ruby(value.inspect) unless value.include?("\n") || value.length > 100 body, omitted = clamp(value) [body, (value, omitted)].compact.join("\n") end |