inlay 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +17 -1
- data/docs/index.html +28 -0
- data/docs/manual-checks.md +13 -0
- data/docs/spikes.md +5 -5
- data/lib/inlay/irb.rb +4 -1
- data/lib/inlay/iruby.rb +116 -0
- data/lib/inlay/sizer.rb +16 -4
- data/lib/inlay/terminal_output.rb +8 -6
- data/lib/inlay/version.rb +1 -1
- data/sig/inlay.rbs +9 -1
- metadata +53 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6273a1bf011d3c9cd941d30b87f50d5724eb203c00a06697c4a9247c992274ff
|
|
4
|
+
data.tar.gz: bdc9b71941f4742ba3b7ef41f2a9c597d4c60d1be5ebe84dbc918ea6561894d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1eceb81681746d2fcb025f69c78280be9eefbf8213aed812b398e37466dc9150afb603ef53c74d52e5885519603fb21d39103cd2e3722b5e67e7fa7d3e16cccf
|
|
7
|
+
data.tar.gz: 3765bcfe8b45a28d015f7339a5106ff52bc950667332d3bfd9e0c86b5d46eb076c4fd745d49d045008c33c37ba81aae39b54bcb156d61eb1cd589711e730beb8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - Unreleased
|
|
4
|
+
|
|
5
|
+
- Fit terminal images to protocol-specific cell dimensions.
|
|
6
|
+
- Preserve SVG chart output when optional PNG dependencies are unavailable.
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-09-25
|
|
9
|
+
|
|
10
|
+
- Add terminal image output, `Inlay.show`, normalization, and custom adapters.
|
|
11
|
+
- Integrate image display with IRB, Pry, and IRuby, including SVG, PNG, and animated GIF notebook output.
|
|
12
|
+
|
|
3
13
|
## [0.1.0] - 2026-09-25
|
|
4
14
|
|
|
5
15
|
Initial release
|
data/README.md
CHANGED
|
@@ -31,7 +31,21 @@ Pry uses the same integration style:
|
|
|
31
31
|
require "inlay/pry"
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
## Use in IRuby / Jupyter
|
|
35
|
+
|
|
36
|
+
Install [IRuby](https://github.com/SciRuby/iruby) 0.8 or newer, then require Inlay after the optional graphics gems you use:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require "inkplot" # optional: charts
|
|
40
|
+
require "inlay/iruby"
|
|
41
|
+
|
|
42
|
+
Tessel.read("brick.png")
|
|
43
|
+
Inkplot.line(prices, x: :date, y: :close) # when Inkplot is installed
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
IRuby provides PNG for images and both SVG and PNG for charts, with SVG listed first. Animations use an installed Flipbook to produce a GIF data URI; if Flipbook is unavailable, Inlay displays the first frame as PNG. These integrations are opt-in and do not load IRuby, Inkplot, or Flipbook when you only `require "inlay"`.
|
|
47
|
+
|
|
48
|
+
Inlay uses the terminal protocol selected by Termvas: Kitty, iTerm2, Sixel, or true-color half blocks. Image limits use terminal columns and rows; pixel protocols use Termvas cell-size estimates (8 × 16 by default, configurable with `TERMVAS_CELL_WIDTH` and `TERMVAS_CELL_HEIGHT`). Piped output, `TERM=dumb`, `INLAY=off`, and `NO_COLOR` with half blocks show only the summary.
|
|
35
49
|
|
|
36
50
|
## Use in a script
|
|
37
51
|
|
|
@@ -62,6 +76,8 @@ bundle install
|
|
|
62
76
|
bundle exec rake verify
|
|
63
77
|
```
|
|
64
78
|
|
|
79
|
+
Run `bundle exec rbs -I sig validate` to check the published signatures. The manual terminal and notebook checklist is in [docs/manual-checks.md](docs/manual-checks.md).
|
|
80
|
+
|
|
65
81
|
## License
|
|
66
82
|
|
|
67
83
|
MIT
|
data/docs/index.html
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="theme-color" content="#101114">
|
|
7
|
+
<meta name="description" content="Render Ruby graphics where you inspect them with Inlay.">
|
|
8
|
+
<title>Inlay — graphics where you work</title>
|
|
9
|
+
<style>
|
|
10
|
+
:root{color-scheme:dark;--bg:#101114;--panel:#191b20;--line:#2b2e35;--text:#f1f0ec;--muted:#a3a5ad;--accent:#f0a66e;--mono:ui-monospace,SFMono-Regular,Menlo,monospace;--sans:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
|
|
11
|
+
*{box-sizing:border-box}body{margin:0;background:radial-gradient(ellipse at 86% 0%,#3a2b21,transparent 38%),var(--bg);color:var(--text);font:16px/1.65 var(--sans)}a{color:inherit;text-decoration:none}a:hover{color:var(--accent)}.wrap{width:min(1020px,calc(100% - 40px));margin:auto}.nav{height:76px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line)}.brand{font-size:20px;font-weight:750;letter-spacing:-.04em}.brand i,.label{font-style:normal;color:var(--accent)}.navlinks{display:flex;gap:24px;color:var(--muted);font-size:14px}.hero{padding:94px 0 72px;max-width:780px}.label{font:12px var(--mono);text-transform:uppercase;letter-spacing:.14em}h1{font-size:clamp(48px,8vw,82px);line-height:1;letter-spacing:-.075em;margin:20px 0}.hero p{font-size:19px;color:var(--muted);max-width:620px}.actions{display:flex;gap:12px;flex-wrap:wrap;margin:28px 0}.button{padding:10px 16px;border:1px solid var(--line);border-radius:5px;font-weight:650}.primary{color:#21160f;background:var(--accent);border-color:var(--accent)}.install{display:inline-flex;gap:16px;background:#090a0c;border:1px solid var(--line);border-radius:6px;padding:12px 15px;font:14px var(--mono)}.install span{color:#777}.section{padding:42px 0 64px;border-top:1px solid var(--line)}.section h2{font-size:28px;letter-spacing:-.045em;margin:8px 0 10px}.section>p{color:var(--muted);max-width:640px}.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:25px}.card{padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:7px}.num{font:12px var(--mono);color:var(--accent)}.card h3{font-size:17px;margin:16px 0 6px}.card p{font-size:14px;color:var(--muted);margin:0}.code{background:#090a0c;border:1px solid var(--line);border-radius:7px;padding:18px;overflow:auto;font:14px/1.8 var(--mono);color:#e7d5c7}.foot{padding:24px 0 36px;border-top:1px solid var(--line);color:var(--muted);font-size:13px;display:flex;justify-content:space-between;gap:16px}
|
|
12
|
+
@media(max-width:700px){.hero{padding:68px 0 54px}.navlinks{gap:14px}.cards{grid-template-columns:1fr}.foot{flex-direction:column}}
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body><div class="wrap">
|
|
16
|
+
<nav class="nav" aria-label="Main navigation"><a class="brand" href="#top">inlay<i>.</i></a><div class="navlinks"><a href="#integrations">Integrations</a><a href="https://github.com/rbgfx/inlay">GitHub</a><a href="https://rubygems.org/gems/inlay">RubyGems</a></div></nav>
|
|
17
|
+
<main id="top">
|
|
18
|
+
<section class="hero"><div class="label">Ruby graphics, inline</div><h1>See what your<br>code makes.</h1><p>Inlay renders images, surfaces, charts, and animations where you inspect them: in IRB, Pry, Jupyter, or a supported terminal.</p><div class="actions"><a class="button primary" href="https://github.com/rbgfx/inlay#use-in-irb">Get started ↗</a><a class="button" href="https://github.com/rbgfx/inlay/blob/main/docs/manual-checks.md">Compatibility notes</a></div><div class="install"><span>$</span> gem install inlay</div></section>
|
|
19
|
+
<section class="section" id="integrations"><div class="label">One small adapter</div><h2>Fits the way you already work</h2><p>Install the optional adapter for your environment. Inlay keeps notebook and terminal integrations opt-in, so a basic install stays small.</p><div class="cards"><article class="card"><div class="num">01 / REPL</div><h3>IRB & Pry</h3><p>Return an image at the prompt and see it inline, with a short summary ready for the next command.</p></article><article class="card"><div class="num">02 / NOTEBOOK</div><h3>IRuby & Jupyter</h3><p>Display PNG images, SVG or PNG charts, and animated GIF output with a first-frame fallback.</p></article><article class="card"><div class="num">03 / TERMINAL</div><h3>Kitty, iTerm2 & Sixel</h3><p>Choose the terminal protocol through Termvas, with true-color blocks as a portable fallback.</p></article></div></section>
|
|
20
|
+
<section class="section"><div class="label">In IRB</div><h2>Require it once</h2><pre class="code"><code># ~/.irbrc
|
|
21
|
+
require "inlay/irb"
|
|
22
|
+
|
|
23
|
+
# Then return an image from any prompt
|
|
24
|
+
image = Tessel.read("brick.png").scale_nearest(64, 64)
|
|
25
|
+
image</code></pre></section>
|
|
26
|
+
</main><footer class="foot"><span>Inlay · Render Ruby graphics where you inspect them</span><span><a href="https://github.com/rbgfx/inlay">Source</a> · MIT License</span></footer>
|
|
27
|
+
</div></body>
|
|
28
|
+
</html>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Manual integration checks
|
|
2
|
+
|
|
3
|
+
Run these checks with a real terminal or JupyterLab session before marking them complete. Automated specs cover the IRB PTY path and IRuby's display registry, but cannot confirm each frontend's rendering.
|
|
4
|
+
|
|
5
|
+
| Frontend | Check | Status |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| Kitty | Image appears inline and the next prompt is intact | Not run |
|
|
8
|
+
| WezTerm | Image appears inline and the next prompt is intact | Not run |
|
|
9
|
+
| iTerm2 | Image appears inline and the next prompt is intact | Not run |
|
|
10
|
+
| Ghostty | Image appears inline and the next prompt is intact | Not run |
|
|
11
|
+
| VS Code integrated terminal | Image appears inline with image support enabled | Not run |
|
|
12
|
+
| tmux | Image appears inline and the next prompt is intact | Not run |
|
|
13
|
+
| JupyterLab | Image, chart SVG, and animation/fallback render in cells | Not run |
|
data/docs/spikes.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Integration spikes
|
|
2
2
|
|
|
3
|
-
- IRB 1.18
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
- Pry's configured printer receives `(output, value, pry_instance)`; the adapter retains that printer and passes it the summary.
|
|
7
|
-
- IRuby's
|
|
3
|
+
- Verified with IRB 1.18 in a PTY: Inlay's inspector writes the Kitty image sequence directly and leaves the one-line summary in IRB's result buffer. Both an assignment and a later expression display correctly, and the following prompt remains usable. The supported minimum is IRB 1.13, which provides the inspector API used here.
|
|
4
|
+
- Terminal protocol selection uses Termvas environment detection during `require "inlay/irb"`; Inlay does not send device queries. The PTY test forces IRB's pager through `tee` for a long value, then checks the following Kitty image sequence and prompt remain intact. Real pager navigation and terminal rendering still need frontend checks.
|
|
5
|
+
- Verified with a temporary Rails 8.1.4 console and project `.irbrc` loading `inlay/irb`: ordinary values and Tessel image assignments keep the prompt usable. This caught and fixed the wrapped Inspector's missing initializer call (`IRB::ColorPrinter` on pretty-print output).
|
|
6
|
+
- Pry's configured printer receives `(output, value, pry_instance)`; the adapter retains that printer and passes it the summary. The configured printer path is covered by a spec.
|
|
7
|
+
- IRuby 0.8.3's display registry supports predicate matchers and MIME-specific renderers. Registry specs verify PNG, SVG, and HTML GIF output; a local integration check against Flipbook also produced a GIF data URI. JupyterLab frontend rendering has not been manually checked.
|
|
8
8
|
- `@ruby/3.4-wasm-wasi` 2.10.1 / Ruby 3.4.1 with Larb and JS host bindings completed 3,600 simulated 60 fps callbacks in 61.95 seconds. With one stable JS trampoline and Ruby/JS GC every 600 frames, WASM memory changed from 71,499,776 to 71,565,312 bytes; JS heap grew 4,261,280 bytes. This validates the callback strategy under Node, not a browser or GPU workload.
|
data/lib/inlay/irb.rb
CHANGED
|
@@ -14,7 +14,10 @@ module Inlay
|
|
|
14
14
|
selected = mode.is_a?(IRB::Inspector) ? mode : IRB::Inspector::INSPECTORS[mode] || IRB::Inspector::INSPECTORS[mode.to_s] || IRB::Inspector::INSPECTORS[:p]
|
|
15
15
|
return false unless selected
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
unless mode.equal?(@wrapper)
|
|
18
|
+
@original = selected
|
|
19
|
+
@original.init
|
|
20
|
+
end
|
|
18
21
|
@protocol = TerminalOutput.protocol
|
|
19
22
|
@wrapper = IRB::Inspector.new(proc do |value, output, colorize: true|
|
|
20
23
|
begin
|
data/lib/inlay/iruby.rb
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "inlay"
|
|
5
|
+
require "iruby/display"
|
|
6
|
+
require "mime/types"
|
|
7
|
+
|
|
8
|
+
module Inlay
|
|
9
|
+
module IRubyIntegration
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
module MimeBundle
|
|
13
|
+
def to_iruby_mimebundle(include: [])
|
|
14
|
+
return super if defined?(super)
|
|
15
|
+
|
|
16
|
+
Inlay::IRubyIntegration.mimebundle(self, include: include)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def install
|
|
21
|
+
unless @registered
|
|
22
|
+
registry = IRuby::Display::Registry
|
|
23
|
+
registry.match { |object| Inlay.displayable?(object) }
|
|
24
|
+
registry.format("text/html") { |object| html(object) }
|
|
25
|
+
registry.format("image/svg+xml") { |object| svg(object) }
|
|
26
|
+
registry.format("image/png") { |object| png(object) }
|
|
27
|
+
@registered = true
|
|
28
|
+
end
|
|
29
|
+
install_mimebundle
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def html(object)
|
|
34
|
+
animation_html(Inlay.normalize(object))
|
|
35
|
+
rescue StandardError
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def svg(object)
|
|
40
|
+
Inlay.normalize(object).svg
|
|
41
|
+
rescue StandardError
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def png(object)
|
|
46
|
+
png_content(Inlay.normalize(object))
|
|
47
|
+
rescue LoadError, StandardError
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def mimebundle(object, include: [])
|
|
52
|
+
normalized = Inlay.normalize(object)
|
|
53
|
+
formats = {}
|
|
54
|
+
formats["text/html"] = animation_html(normalized) if normalized.frames
|
|
55
|
+
formats["image/svg+xml"] = normalized.svg if normalized.svg
|
|
56
|
+
png_bytes = png_content(normalized)
|
|
57
|
+
formats["image/png"] = Base64.strict_encode64(png_bytes) if png_bytes
|
|
58
|
+
formats.select! { |mime, _| include.empty? || include.include?(mime) }
|
|
59
|
+
[formats, {}]
|
|
60
|
+
rescue StandardError
|
|
61
|
+
[{}, {}]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def install_mimebundle
|
|
65
|
+
classes = [Tessel::Image]
|
|
66
|
+
classes << RBGL::Engine::Framebuffer if defined?(RBGL::Engine::Framebuffer)
|
|
67
|
+
classes << RBGL::Engine::Texture if defined?(RBGL::Engine::Texture)
|
|
68
|
+
classes << Inkplot::Chart if defined?(Inkplot::Chart)
|
|
69
|
+
classes.uniq.each do |klass|
|
|
70
|
+
klass.prepend(MimeBundle) unless klass.ancestors.include?(MimeBundle)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
private_class_method :install_mimebundle
|
|
74
|
+
|
|
75
|
+
def animation_html(normalized)
|
|
76
|
+
return unless normalized.frames
|
|
77
|
+
|
|
78
|
+
writer = flipbook_writer
|
|
79
|
+
return unless writer
|
|
80
|
+
|
|
81
|
+
require "tempfile"
|
|
82
|
+
gif = Tempfile.create(["inlay-", ".gif"]) do |file|
|
|
83
|
+
writer.write(file.path, normalized.frames, fps: normalized.fps)
|
|
84
|
+
File.binread(file.path)
|
|
85
|
+
end
|
|
86
|
+
"<img alt=\"Animation with #{normalized.frames.length} frames\" src=\"data:image/gif;base64,#{Base64.strict_encode64(gif)}\">"
|
|
87
|
+
rescue LoadError, StandardError
|
|
88
|
+
nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def png_content(normalized)
|
|
92
|
+
image = normalized.image || normalized.frames&.first
|
|
93
|
+
return Tessel::PNG.encode(image) if image
|
|
94
|
+
|
|
95
|
+
value = normalized.png
|
|
96
|
+
value = value.call if value.respond_to?(:call)
|
|
97
|
+
return value if value.is_a?(String)
|
|
98
|
+
return Tessel::PNG.encode(value) if value.is_a?(Tessel::Image)
|
|
99
|
+
rescue LoadError, StandardError
|
|
100
|
+
nil
|
|
101
|
+
end
|
|
102
|
+
private_class_method :animation_html, :png_content
|
|
103
|
+
|
|
104
|
+
def flipbook_writer
|
|
105
|
+
return Flipbook if defined?(Flipbook) && Flipbook.respond_to?(:write)
|
|
106
|
+
|
|
107
|
+
require "flipbook"
|
|
108
|
+
Flipbook if defined?(Flipbook) && Flipbook.respond_to?(:write)
|
|
109
|
+
rescue LoadError => error
|
|
110
|
+
raise unless error.path == "flipbook"
|
|
111
|
+
end
|
|
112
|
+
private_class_method :flipbook_writer
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
Inlay::IRubyIntegration.install
|
data/lib/inlay/sizer.rb
CHANGED
|
@@ -4,14 +4,26 @@ module Inlay
|
|
|
4
4
|
module Sizer
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
|
-
def fit(image, width: nil, height: nil, scale: :auto, columns: nil, rows: nil)
|
|
7
|
+
def fit(image, width: nil, height: nil, scale: :auto, columns: nil, rows: nil, protocol: :blocks, env: ENV)
|
|
8
8
|
raise TypeError, "expected a Tessel::Image" unless image.is_a?(Tessel::Image)
|
|
9
9
|
raise ArgumentError, "unknown scale mode: #{scale}" unless %i[auto fit pixel none].include?(scale)
|
|
10
10
|
return image if image.width.zero? || image.height.zero?
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
terminal = Termvas::Terminal.new(alt_screen: false, env: env)
|
|
13
|
+
terminal_columns, terminal_rows = terminal.size
|
|
14
|
+
columns ||= terminal_columns
|
|
15
|
+
rows ||= terminal_rows
|
|
16
|
+
block_pixels = protocol.to_sym == :blocks
|
|
17
|
+
cell_width, cell_height = terminal.cell_size
|
|
18
|
+
available_width = columns * (block_pixels ? 1 : cell_width)
|
|
19
|
+
available_height = [rows, Inlay.config.max_rows].min * (block_pixels ? 2 : cell_height)
|
|
20
|
+
if available_width * available_height > Inlay.config.max_pixels
|
|
21
|
+
factor = Math.sqrt(Inlay.config.max_pixels.to_f / (available_width * available_height))
|
|
22
|
+
available_width = [(available_width * factor).floor, 1].max
|
|
23
|
+
available_height = [(available_height * factor).floor, 1].max
|
|
24
|
+
end
|
|
25
|
+
width = [Integer(width || available_width), available_width].min
|
|
26
|
+
height = [Integer(height || available_height), available_height].min
|
|
15
27
|
raise ArgumentError, "display dimensions must be positive" unless width.positive? && height.positive?
|
|
16
28
|
pixel_scale = scale == :pixel || (scale == :auto && image.width <= 32 && image.height <= 32)
|
|
17
29
|
max_factor = [width / [image.width, 1].max, height / [image.height, 1].max].min
|
|
@@ -5,10 +5,7 @@ module Inlay
|
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
7
|
def protocol(output: $stdout, env: ENV)
|
|
8
|
-
return :none unless
|
|
9
|
-
return :none unless output.tty?
|
|
10
|
-
return :none unless env["INLAY"] != "off"
|
|
11
|
-
return :none if env["TERM"] == "dumb"
|
|
8
|
+
return :none unless enabled?(output: output, env: env)
|
|
12
9
|
|
|
13
10
|
selected = Termvas::Detector.protocol(env)
|
|
14
11
|
return :none if selected == :blocks && env.key?("NO_COLOR")
|
|
@@ -18,11 +15,11 @@ module Inlay
|
|
|
18
15
|
|
|
19
16
|
def write(image, width: nil, height: nil, scale: :auto, protocol: nil, output: $stdout, env: ENV)
|
|
20
17
|
selected = (protocol || self.protocol(output: output, env: env)).to_sym
|
|
21
|
-
return false unless
|
|
18
|
+
return false unless enabled?(output: output, env: env) && selected != :none
|
|
22
19
|
return false if selected == :blocks && env.key?("NO_COLOR")
|
|
23
20
|
return false if image.width * image.height > Inlay.config.max_pixels
|
|
24
21
|
|
|
25
|
-
image = Sizer.fit(image, width: width, height: height, scale: scale)
|
|
22
|
+
image = Sizer.fit(image, width: width, height: height, scale: scale, protocol: selected, env: env)
|
|
26
23
|
bytes = image.bytes
|
|
27
24
|
encoded = case selected.to_sym
|
|
28
25
|
when :blocks then Termvas::Encoders::Blocks.encode(bytes, image.width, image.height)
|
|
@@ -38,6 +35,11 @@ module Inlay
|
|
|
38
35
|
true
|
|
39
36
|
end
|
|
40
37
|
|
|
38
|
+
def enabled?(output:, env:)
|
|
39
|
+
Inlay.config.enabled && output.tty? && env["INLAY"] != "off" && env["TERM"] != "dumb"
|
|
40
|
+
end
|
|
41
|
+
private_class_method :enabled?
|
|
42
|
+
|
|
41
43
|
def next_kitty_id
|
|
42
44
|
@kitty_id_lock ||= Mutex.new
|
|
43
45
|
@kitty_id_lock.synchronize { @kitty_id = (@kitty_id.to_i % 2_147_483_647) + 1 }
|
data/lib/inlay/version.rb
CHANGED
data/sig/inlay.rbs
CHANGED
|
@@ -17,7 +17,7 @@ module Inlay
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def self.config: () -> Config
|
|
20
|
-
def self.register: (Module klass) { (untyped object) -> untyped } ->
|
|
20
|
+
def self.register: (Module klass) { (untyped object) -> untyped } -> untyped
|
|
21
21
|
def self.normalize: (untyped object, ?allow_path: bool) -> Normalized
|
|
22
22
|
def self.displayable?: (untyped object) -> bool
|
|
23
23
|
def self.protocol: () -> Symbol
|
|
@@ -26,6 +26,14 @@ module Inlay
|
|
|
26
26
|
def self.irb_uninstall!: () -> (bool | nil)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
module Inlay::IRubyIntegration
|
|
30
|
+
def self.install: () -> bool
|
|
31
|
+
def self.html: (untyped object) -> String?
|
|
32
|
+
def self.svg: (untyped object) -> String?
|
|
33
|
+
def self.png: (untyped object) -> String?
|
|
34
|
+
def self.mimebundle: (untyped object, ?include: Array[String]) -> [Hash[String, String], Hash[untyped, untyped]]
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
module Kernel
|
|
30
38
|
private
|
|
31
39
|
def inlay: (untyped object, **untyped options) -> String
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inlay
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yudai Takada
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-09-25 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: tessel
|
|
@@ -35,7 +36,7 @@ dependencies:
|
|
|
35
36
|
requirements:
|
|
36
37
|
- - ">="
|
|
37
38
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: 0.
|
|
39
|
+
version: 0.3.0
|
|
39
40
|
- - "<"
|
|
40
41
|
- !ruby/object:Gem::Version
|
|
41
42
|
version: '1'
|
|
@@ -45,7 +46,7 @@ dependencies:
|
|
|
45
46
|
requirements:
|
|
46
47
|
- - ">="
|
|
47
48
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: 0.
|
|
49
|
+
version: 0.3.0
|
|
49
50
|
- - "<"
|
|
50
51
|
- !ruby/object:Gem::Version
|
|
51
52
|
version: '1'
|
|
@@ -55,14 +56,20 @@ dependencies:
|
|
|
55
56
|
requirements:
|
|
56
57
|
- - ">="
|
|
57
58
|
- !ruby/object:Gem::Version
|
|
58
|
-
version: '0'
|
|
59
|
+
version: '0.2'
|
|
60
|
+
- - "<"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '1'
|
|
59
63
|
type: :runtime
|
|
60
64
|
prerelease: false
|
|
61
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
62
66
|
requirements:
|
|
63
67
|
- - ">="
|
|
64
68
|
- !ruby/object:Gem::Version
|
|
65
|
-
version: '0'
|
|
69
|
+
version: '0.2'
|
|
70
|
+
- - "<"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '1'
|
|
66
73
|
- !ruby/object:Gem::Dependency
|
|
67
74
|
name: irb
|
|
68
75
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,6 +77,9 @@ dependencies:
|
|
|
70
77
|
- - ">="
|
|
71
78
|
- !ruby/object:Gem::Version
|
|
72
79
|
version: '1.13'
|
|
80
|
+
- - "<"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '2'
|
|
73
83
|
type: :development
|
|
74
84
|
prerelease: false
|
|
75
85
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -77,6 +87,29 @@ dependencies:
|
|
|
77
87
|
- - ">="
|
|
78
88
|
- !ruby/object:Gem::Version
|
|
79
89
|
version: '1.13'
|
|
90
|
+
- - "<"
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '2'
|
|
93
|
+
- !ruby/object:Gem::Dependency
|
|
94
|
+
name: iruby
|
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0.8'
|
|
100
|
+
- - "<"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '1'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0.8'
|
|
110
|
+
- - "<"
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: '1'
|
|
80
113
|
- !ruby/object:Gem::Dependency
|
|
81
114
|
name: pry
|
|
82
115
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -84,6 +117,9 @@ dependencies:
|
|
|
84
117
|
- - ">="
|
|
85
118
|
- !ruby/object:Gem::Version
|
|
86
119
|
version: '0'
|
|
120
|
+
- - "<"
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: '1'
|
|
87
123
|
type: :development
|
|
88
124
|
prerelease: false
|
|
89
125
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -91,6 +127,9 @@ dependencies:
|
|
|
91
127
|
- - ">="
|
|
92
128
|
- !ruby/object:Gem::Version
|
|
93
129
|
version: '0'
|
|
130
|
+
- - "<"
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: '1'
|
|
94
133
|
- !ruby/object:Gem::Dependency
|
|
95
134
|
name: rspec
|
|
96
135
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -105,7 +144,8 @@ dependencies:
|
|
|
105
144
|
- - "~>"
|
|
106
145
|
- !ruby/object:Gem::Version
|
|
107
146
|
version: '3.0'
|
|
108
|
-
description: Render Tessel images
|
|
147
|
+
description: Render Tessel images, graphics buffers, charts, and animations in terminals,
|
|
148
|
+
IRB, Pry, and IRuby.
|
|
109
149
|
email:
|
|
110
150
|
- t.yudai92@gmail.com
|
|
111
151
|
executables: []
|
|
@@ -116,11 +156,14 @@ files:
|
|
|
116
156
|
- LICENSE.txt
|
|
117
157
|
- README.md
|
|
118
158
|
- Rakefile
|
|
159
|
+
- docs/index.html
|
|
160
|
+
- docs/manual-checks.md
|
|
119
161
|
- docs/spikes.md
|
|
120
162
|
- lib/inlay.rb
|
|
121
163
|
- lib/inlay/adapters.rb
|
|
122
164
|
- lib/inlay/config.rb
|
|
123
165
|
- lib/inlay/irb.rb
|
|
166
|
+
- lib/inlay/iruby.rb
|
|
124
167
|
- lib/inlay/kernel.rb
|
|
125
168
|
- lib/inlay/normalizer.rb
|
|
126
169
|
- lib/inlay/pry.rb
|
|
@@ -135,6 +178,7 @@ licenses:
|
|
|
135
178
|
metadata:
|
|
136
179
|
homepage_uri: https://github.com/rbgfx/inlay
|
|
137
180
|
source_code_uri: https://github.com/rbgfx/inlay/tree/main
|
|
181
|
+
post_install_message:
|
|
138
182
|
rdoc_options: []
|
|
139
183
|
require_paths:
|
|
140
184
|
- lib
|
|
@@ -149,7 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
149
193
|
- !ruby/object:Gem::Version
|
|
150
194
|
version: '0'
|
|
151
195
|
requirements: []
|
|
152
|
-
rubygems_version: 4.
|
|
196
|
+
rubygems_version: 3.4.19
|
|
197
|
+
signing_key:
|
|
153
198
|
specification_version: 4
|
|
154
199
|
summary: Display Ruby graphics in terminals and REPLs
|
|
155
200
|
test_files: []
|