plotty 1.0.0__tar.gz

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.
plotty-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xuesoso
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
plotty-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.4
2
+ Name: plotty
3
+ Version: 1.0.0
4
+ Summary: Inline matplotlib plots in your terminal via sixel, in a tmux pane, over SSH
5
+ Author-email: xuesoso <xuesoso@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/xuesoso/plotty
8
+ Project-URL: Repository, https://github.com/xuesoso/plotty
9
+ Keywords: matplotlib,sixel,tmux,ssh,terminal,plotting,repl
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Framework :: Matplotlib
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: POSIX
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Scientific/Engineering :: Visualization
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: matplotlib>=3.5
22
+ Requires-Dist: numpy>=1.17
23
+ Dynamic: license-file
24
+
25
+ # plotty
26
+
27
+ [![CI](https://github.com/xuesoso/plotty/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/xuesoso/plotty/actions/workflows/ci.yml)
28
+ [![security: pip-audit](https://img.shields.io/badge/security-pip--audit-blue.svg)](https://github.com/xuesoso/plotty/actions/workflows/ci.yml)
29
+ [![Python](https://img.shields.io/badge/python-3.7%2B-blue.svg)](pyproject.toml)
30
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
31
+
32
+ > Inline matplotlib plots in your terminal — rendered as **sixel** in a dedicated
33
+ > tmux pane, **including over SSH**. No browser, no X11, no Jupyter server.
34
+
35
+ <p align="center">
36
+ <img src="images/plotty_1.gif" alt="plotty demo" width="720">
37
+ </p>
38
+
39
+ `plotty` is a matplotlib backend that draws figures directly in your terminal, so
40
+ a `tmux` + `ipython` (+ `nvim`) workflow shows plots the way a Jupyter or VS Code
41
+ notebook does. Activate it once and your figures appear in a tmux pane next to
42
+ your REPL — locally or on a remote machine over SSH. It's inspired by and the Python analogue of
43
+ [MuxDisplay.jl](https://github.com/goerz/MuxDisplay.jl).
44
+
45
+ ```python
46
+ import plotty
47
+ plotty.enable()
48
+
49
+ import matplotlib.pyplot as plt
50
+ plt.plot([1, 4, 9, 16]) # shows up in the plot pane
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Why / when to use it
56
+
57
+ If you do interactive analysis in a terminal — `ipython` inside `tmux`, editing
58
+ in `nvim`, frequently SSH'd into a remote box — you normally lose inline plots:
59
+ `plt.show()` wants a GUI and Jupyter wants a browser. plotty fills that gap and
60
+ covers three setups:
61
+
62
+ - **Local tmux.** Run your REPL in one pane; plots render in another.
63
+ - **Remote over SSH.** Run everything on the remote inside tmux. Only the
64
+ rendered **sixel bytes** cross the wire (drawn by your local terminal); the
65
+ control plane — signals, pidfile, image hand-off — stays host-local, so it
66
+ behaves exactly like a local session.
67
+ - **Nested tmux** (`local tmux → ssh → remote tmux`). Supported with a small,
68
+ one-time tmux config change — see [Nested tmux](#nested-tmux-local--remote).
69
+
70
+ ## Requirements
71
+
72
+ | | |
73
+ |---|---|
74
+ | **Python** | ≥ 3.7 |
75
+ | **tmux** | ≥ **3.4**, built with sixel support (`--enable-sixel`) |
76
+ | **Terminal** | a sixel-capable terminal for display — e.g. WezTerm, foot, Konsole, `xterm -ti vt340` |
77
+ | **Python deps** | `matplotlib` (and `numpy`, which ships with matplotlib) — that's all |
78
+
79
+ Check tmux:
80
+
81
+ ```bash
82
+ tmux -V # need >= 3.4
83
+ strings "$(command -v tmux)" | grep -qi sixel && echo "sixel: yes" || echo "sixel: MISSING"
84
+ ```
85
+
86
+ > Not in tmux? plotty falls back to writing sixel straight to your terminal's
87
+ > stdout, so it still works in any sixel-capable terminal without tmux.
88
+
89
+ ## Install
90
+
91
+ plotty installs with uv (which indexes PyPI) or pip:
92
+
93
+ ```bash
94
+ uv add plotty # add to your project (resolved + locked)
95
+ # or
96
+ uv pip install plotty # into the active environment
97
+ # or
98
+ pip install plotty
99
+ ```
100
+
101
+ From source:
102
+
103
+ ```bash
104
+ git clone https://github.com/xuesoso/plotty && cd plotty
105
+ uv pip install .
106
+ ```
107
+
108
+ ## Quick start
109
+
110
+ ```python
111
+ import plotty
112
+ plotty.enable() # auto-detect a renderer, target the last tmux pane,
113
+ # and spawn a tiny viewer there
114
+
115
+ import matplotlib.pyplot as plt
116
+ plt.plot([1, 4, 9, 16])
117
+ # IPython: the figure appears automatically after each cell.
118
+ # Plain REPL: call plt.show().
119
+
120
+ plotty.disable() # stop the viewer and restore matplotlib
121
+ ```
122
+
123
+ Inside tmux, plotty draws into the **last pane** of the current window by default,
124
+ so split a pane first (`Ctrl-b "`), then call `enable()`. Target another pane with
125
+ `enable(target_pane=...)`.
126
+
127
+ Public API: `enable()`, `disable()`, `redraw()`, `view()`.
128
+
129
+ ### Demo
130
+
131
+ Run the bundled example to see it in action (split off a plot pane first, then
132
+ `python examples/demo.py`). The GIF below is the expected output:
133
+
134
+ ```bash
135
+ python examples/demo.py
136
+ ```
137
+
138
+ <p align="center">
139
+ <img src="images/plotty_2.gif" alt="plotty rendering the examples/demo.py plots in a tmux pane" width="720">
140
+ </p>
141
+
142
+ ## How it works
143
+
144
+ Two cooperating pieces share state via the filesystem + OS signals:
145
+
146
+ - **Backend** (`module://plotty`, runs in your REPL): on each figure it saves a
147
+ PNG, atomically publishes it to `~/.cache/plotty/last.png`, and signals the
148
+ viewer.
149
+ - **Viewer** (runs in the plot pane): redraws on a new figure (`SIGUSR1`) and on
150
+ pane resize/zoom (`SIGWINCH`). It's event-driven (`signal.pause()`), idle at
151
+ zero CPU, and self-cleaning.
152
+
153
+ Because only sixel bytes cross SSH and everything else is host-local, remote use
154
+ is identical to local.
155
+
156
+ ## Display modes
157
+
158
+ - **Viewer mode** (default in tmux) — a small viewer process lives in the target
159
+ pane and redraws on new figures *and* on pane resize/zoom. Recommended; it's
160
+ the mode that survives resizing.
161
+ - **Inline mode** (default outside tmux, or `enable(inline=True)`) — the backend
162
+ renders sixel itself, with no helper process, and writes it to the target
163
+ pane's tty (in tmux) or to your stdout (no tmux). It does **not** auto-redraw
164
+ on resize.
165
+
166
+ ```python
167
+ plotty.enable(inline=True) # force inline even inside tmux
168
+ ```
169
+
170
+ ## Sixel encoders
171
+
172
+ plotty ships with a **built-in, dependency-free sixel encoder** (pure stdlib +
173
+ numpy), so it works out of the box with no external tools.
174
+
175
+ If one is on your `PATH`, plotty auto-detects an external encoder for
176
+ higher-quality (dithered) output, in priority order:
177
+
178
+ 1. [`chafa`](https://github.com/hpjansson/chafa) — recommended
179
+ 2. [`img2sixel`](https://github.com/saitoha/libsixel) (libsixel)
180
+ 3. ImageMagick (`magick` / `convert`)
181
+
182
+ Force the built-in encoder regardless of what's installed:
183
+
184
+ ```python
185
+ plotty.enable(imgcat="builtin") # or: PLOTTY_IMGCAT=builtin
186
+ ```
187
+
188
+ > plotty is **sixel-only** by design — sixel is the only path that survives tmux
189
+ > and SSH. Non-sixel terminal-image protocols (kitty / iTerm) are not used. A
190
+ > custom non-sixel `imgcat=` may be passed but will warn that it may not display
191
+ > over SSH.
192
+
193
+ ## tmux configuration
194
+
195
+ plotty works with no config on a single tmux as long as tmux is ≥ 3.4 with sixel
196
+ and your terminal supports sixel (i.e. Wezterm, iTerm2, xterm, xfce term, VSCode). Reference [Are We Sixel Yet?](https://www.arewesixelyet.com/) for a complete list. If plots don't appear (or you see raw
197
+ escape-sequence junk instead of an image), tmux hasn't recognized that your
198
+ terminal can render sixel — its auto-detection isn't always reliable, especially
199
+ over SSH. Tell it explicitly in `~/.tmux.conf`:
200
+
201
+ ```tmux
202
+ set -as terminal-features ',*:sixel'
203
+ ```
204
+
205
+ ### Nested tmux (local + remote)
206
+
207
+ A common remote setup is a tmux **inside** a tmux:
208
+
209
+ ```
210
+ local terminal → local tmux → ssh → remote tmux → REPL + plot pane
211
+ ```
212
+
213
+ For the image to flow all the way out, **every** tmux layer must render and
214
+ forward the sixel — which means setting the feature on **both** the local and the
215
+ remote tmux:
216
+
217
+ ```tmux
218
+ # add to ~/.tmux.conf on BOTH the local laptop and the remote machine
219
+ set -as terminal-features ',*:sixel'
220
+ ```
221
+
222
+ Without this, the inner (remote) tmux doesn't know to forward sixel and the raw
223
+ escape sequence leaks through as garbage characters. Verify a layer sees the
224
+ feature with:
225
+
226
+ ```bash
227
+ tmux display-message -p '#{client_termfeatures}' # should contain "sixel"
228
+ ```
229
+
230
+ Both tmux layers must be ≥ 3.4 and built with sixel.
231
+
232
+ ## Configuration reference
233
+
234
+ `enable()` arguments (each has an environment-variable default):
235
+
236
+ | argument | env var | default | meaning |
237
+ |---|---|---|---|
238
+ | `target_pane` | `PLOTTY_PANE` | `-1` | tmux pane for the plot; negative indexes from the end (`-1` = last) |
239
+ | `size` | `PLOTTY_SIZE` | `60` | display width in terminal cells |
240
+ | `dpi` | `PLOTTY_DPI` | matplotlib default | `savefig` DPI of the source image (raise it for sharper plots at large `size`) |
241
+ | `imgcat` | `PLOTTY_IMGCAT` | auto | renderer command; `"builtin"` forces the built-in encoder |
242
+ | `inline` | `PLOTTY_INLINE` | auto | `True`/`False` to force inline vs viewer-pane mode |
243
+ | `clear` | `PLOTTY_CLEAR` | `True` | clear the pane before each draw |
244
+ | `close` | `PLOTTY_CLOSE` | `True` | close figures after display |
245
+ | `tmux` | `PLOTTY_TMUX` | `tmux` | tmux binary to use |
246
+ | `viewer` | — | `True` | spawn the viewer process (tmux mode) |
247
+ | `verbose` | — | `1` | print startup health-check warnings |
248
+ | — | `PLOTTY_CACHE` | `~/.cache/plotty` | state directory (`last.png`, pidfile) |
249
+
250
+ `size` and `dpi` are independent: `size` is how wide the image is *displayed*,
251
+ `dpi` is how many pixels the *source* has. For a crisp image at a large `size`,
252
+ raise `dpi` so the source has enough pixels.
253
+
254
+ ## Troubleshooting
255
+
256
+ - **Garbage / `+++` instead of an image:** a tmux layer isn't forwarding sixel.
257
+ Add `set -as terminal-features ',*:sixel'` to that layer (both layers if
258
+ nested) and confirm tmux ≥ 3.4 with sixel.
259
+ - **Nothing appears:** check `tmux -V` ≥ 3.4 and sixel support
260
+ (`strings $(command -v tmux) | grep -i sixel`); confirm your terminal supports
261
+ sixel; run `plotty.enable(verbose=1)` to print diagnostics.
262
+ - **Image too large / small:** tune `size`. Blurry when enlarged? raise `dpi`.
263
+ - **Plot doesn't refresh when you resize the pane:** use viewer mode (the default
264
+ in tmux); inline mode doesn't auto-redraw on resize.
265
+
266
+ ## License
267
+
268
+ MIT
plotty-1.0.0/README.md ADDED
@@ -0,0 +1,244 @@
1
+ # plotty
2
+
3
+ [![CI](https://github.com/xuesoso/plotty/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/xuesoso/plotty/actions/workflows/ci.yml)
4
+ [![security: pip-audit](https://img.shields.io/badge/security-pip--audit-blue.svg)](https://github.com/xuesoso/plotty/actions/workflows/ci.yml)
5
+ [![Python](https://img.shields.io/badge/python-3.7%2B-blue.svg)](pyproject.toml)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+
8
+ > Inline matplotlib plots in your terminal — rendered as **sixel** in a dedicated
9
+ > tmux pane, **including over SSH**. No browser, no X11, no Jupyter server.
10
+
11
+ <p align="center">
12
+ <img src="images/plotty_1.gif" alt="plotty demo" width="720">
13
+ </p>
14
+
15
+ `plotty` is a matplotlib backend that draws figures directly in your terminal, so
16
+ a `tmux` + `ipython` (+ `nvim`) workflow shows plots the way a Jupyter or VS Code
17
+ notebook does. Activate it once and your figures appear in a tmux pane next to
18
+ your REPL — locally or on a remote machine over SSH. It's inspired by and the Python analogue of
19
+ [MuxDisplay.jl](https://github.com/goerz/MuxDisplay.jl).
20
+
21
+ ```python
22
+ import plotty
23
+ plotty.enable()
24
+
25
+ import matplotlib.pyplot as plt
26
+ plt.plot([1, 4, 9, 16]) # shows up in the plot pane
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Why / when to use it
32
+
33
+ If you do interactive analysis in a terminal — `ipython` inside `tmux`, editing
34
+ in `nvim`, frequently SSH'd into a remote box — you normally lose inline plots:
35
+ `plt.show()` wants a GUI and Jupyter wants a browser. plotty fills that gap and
36
+ covers three setups:
37
+
38
+ - **Local tmux.** Run your REPL in one pane; plots render in another.
39
+ - **Remote over SSH.** Run everything on the remote inside tmux. Only the
40
+ rendered **sixel bytes** cross the wire (drawn by your local terminal); the
41
+ control plane — signals, pidfile, image hand-off — stays host-local, so it
42
+ behaves exactly like a local session.
43
+ - **Nested tmux** (`local tmux → ssh → remote tmux`). Supported with a small,
44
+ one-time tmux config change — see [Nested tmux](#nested-tmux-local--remote).
45
+
46
+ ## Requirements
47
+
48
+ | | |
49
+ |---|---|
50
+ | **Python** | ≥ 3.7 |
51
+ | **tmux** | ≥ **3.4**, built with sixel support (`--enable-sixel`) |
52
+ | **Terminal** | a sixel-capable terminal for display — e.g. WezTerm, foot, Konsole, `xterm -ti vt340` |
53
+ | **Python deps** | `matplotlib` (and `numpy`, which ships with matplotlib) — that's all |
54
+
55
+ Check tmux:
56
+
57
+ ```bash
58
+ tmux -V # need >= 3.4
59
+ strings "$(command -v tmux)" | grep -qi sixel && echo "sixel: yes" || echo "sixel: MISSING"
60
+ ```
61
+
62
+ > Not in tmux? plotty falls back to writing sixel straight to your terminal's
63
+ > stdout, so it still works in any sixel-capable terminal without tmux.
64
+
65
+ ## Install
66
+
67
+ plotty installs with uv (which indexes PyPI) or pip:
68
+
69
+ ```bash
70
+ uv add plotty # add to your project (resolved + locked)
71
+ # or
72
+ uv pip install plotty # into the active environment
73
+ # or
74
+ pip install plotty
75
+ ```
76
+
77
+ From source:
78
+
79
+ ```bash
80
+ git clone https://github.com/xuesoso/plotty && cd plotty
81
+ uv pip install .
82
+ ```
83
+
84
+ ## Quick start
85
+
86
+ ```python
87
+ import plotty
88
+ plotty.enable() # auto-detect a renderer, target the last tmux pane,
89
+ # and spawn a tiny viewer there
90
+
91
+ import matplotlib.pyplot as plt
92
+ plt.plot([1, 4, 9, 16])
93
+ # IPython: the figure appears automatically after each cell.
94
+ # Plain REPL: call plt.show().
95
+
96
+ plotty.disable() # stop the viewer and restore matplotlib
97
+ ```
98
+
99
+ Inside tmux, plotty draws into the **last pane** of the current window by default,
100
+ so split a pane first (`Ctrl-b "`), then call `enable()`. Target another pane with
101
+ `enable(target_pane=...)`.
102
+
103
+ Public API: `enable()`, `disable()`, `redraw()`, `view()`.
104
+
105
+ ### Demo
106
+
107
+ Run the bundled example to see it in action (split off a plot pane first, then
108
+ `python examples/demo.py`). The GIF below is the expected output:
109
+
110
+ ```bash
111
+ python examples/demo.py
112
+ ```
113
+
114
+ <p align="center">
115
+ <img src="images/plotty_2.gif" alt="plotty rendering the examples/demo.py plots in a tmux pane" width="720">
116
+ </p>
117
+
118
+ ## How it works
119
+
120
+ Two cooperating pieces share state via the filesystem + OS signals:
121
+
122
+ - **Backend** (`module://plotty`, runs in your REPL): on each figure it saves a
123
+ PNG, atomically publishes it to `~/.cache/plotty/last.png`, and signals the
124
+ viewer.
125
+ - **Viewer** (runs in the plot pane): redraws on a new figure (`SIGUSR1`) and on
126
+ pane resize/zoom (`SIGWINCH`). It's event-driven (`signal.pause()`), idle at
127
+ zero CPU, and self-cleaning.
128
+
129
+ Because only sixel bytes cross SSH and everything else is host-local, remote use
130
+ is identical to local.
131
+
132
+ ## Display modes
133
+
134
+ - **Viewer mode** (default in tmux) — a small viewer process lives in the target
135
+ pane and redraws on new figures *and* on pane resize/zoom. Recommended; it's
136
+ the mode that survives resizing.
137
+ - **Inline mode** (default outside tmux, or `enable(inline=True)`) — the backend
138
+ renders sixel itself, with no helper process, and writes it to the target
139
+ pane's tty (in tmux) or to your stdout (no tmux). It does **not** auto-redraw
140
+ on resize.
141
+
142
+ ```python
143
+ plotty.enable(inline=True) # force inline even inside tmux
144
+ ```
145
+
146
+ ## Sixel encoders
147
+
148
+ plotty ships with a **built-in, dependency-free sixel encoder** (pure stdlib +
149
+ numpy), so it works out of the box with no external tools.
150
+
151
+ If one is on your `PATH`, plotty auto-detects an external encoder for
152
+ higher-quality (dithered) output, in priority order:
153
+
154
+ 1. [`chafa`](https://github.com/hpjansson/chafa) — recommended
155
+ 2. [`img2sixel`](https://github.com/saitoha/libsixel) (libsixel)
156
+ 3. ImageMagick (`magick` / `convert`)
157
+
158
+ Force the built-in encoder regardless of what's installed:
159
+
160
+ ```python
161
+ plotty.enable(imgcat="builtin") # or: PLOTTY_IMGCAT=builtin
162
+ ```
163
+
164
+ > plotty is **sixel-only** by design — sixel is the only path that survives tmux
165
+ > and SSH. Non-sixel terminal-image protocols (kitty / iTerm) are not used. A
166
+ > custom non-sixel `imgcat=` may be passed but will warn that it may not display
167
+ > over SSH.
168
+
169
+ ## tmux configuration
170
+
171
+ plotty works with no config on a single tmux as long as tmux is ≥ 3.4 with sixel
172
+ and your terminal supports sixel (i.e. Wezterm, iTerm2, xterm, xfce term, VSCode). Reference [Are We Sixel Yet?](https://www.arewesixelyet.com/) for a complete list. If plots don't appear (or you see raw
173
+ escape-sequence junk instead of an image), tmux hasn't recognized that your
174
+ terminal can render sixel — its auto-detection isn't always reliable, especially
175
+ over SSH. Tell it explicitly in `~/.tmux.conf`:
176
+
177
+ ```tmux
178
+ set -as terminal-features ',*:sixel'
179
+ ```
180
+
181
+ ### Nested tmux (local + remote)
182
+
183
+ A common remote setup is a tmux **inside** a tmux:
184
+
185
+ ```
186
+ local terminal → local tmux → ssh → remote tmux → REPL + plot pane
187
+ ```
188
+
189
+ For the image to flow all the way out, **every** tmux layer must render and
190
+ forward the sixel — which means setting the feature on **both** the local and the
191
+ remote tmux:
192
+
193
+ ```tmux
194
+ # add to ~/.tmux.conf on BOTH the local laptop and the remote machine
195
+ set -as terminal-features ',*:sixel'
196
+ ```
197
+
198
+ Without this, the inner (remote) tmux doesn't know to forward sixel and the raw
199
+ escape sequence leaks through as garbage characters. Verify a layer sees the
200
+ feature with:
201
+
202
+ ```bash
203
+ tmux display-message -p '#{client_termfeatures}' # should contain "sixel"
204
+ ```
205
+
206
+ Both tmux layers must be ≥ 3.4 and built with sixel.
207
+
208
+ ## Configuration reference
209
+
210
+ `enable()` arguments (each has an environment-variable default):
211
+
212
+ | argument | env var | default | meaning |
213
+ |---|---|---|---|
214
+ | `target_pane` | `PLOTTY_PANE` | `-1` | tmux pane for the plot; negative indexes from the end (`-1` = last) |
215
+ | `size` | `PLOTTY_SIZE` | `60` | display width in terminal cells |
216
+ | `dpi` | `PLOTTY_DPI` | matplotlib default | `savefig` DPI of the source image (raise it for sharper plots at large `size`) |
217
+ | `imgcat` | `PLOTTY_IMGCAT` | auto | renderer command; `"builtin"` forces the built-in encoder |
218
+ | `inline` | `PLOTTY_INLINE` | auto | `True`/`False` to force inline vs viewer-pane mode |
219
+ | `clear` | `PLOTTY_CLEAR` | `True` | clear the pane before each draw |
220
+ | `close` | `PLOTTY_CLOSE` | `True` | close figures after display |
221
+ | `tmux` | `PLOTTY_TMUX` | `tmux` | tmux binary to use |
222
+ | `viewer` | — | `True` | spawn the viewer process (tmux mode) |
223
+ | `verbose` | — | `1` | print startup health-check warnings |
224
+ | — | `PLOTTY_CACHE` | `~/.cache/plotty` | state directory (`last.png`, pidfile) |
225
+
226
+ `size` and `dpi` are independent: `size` is how wide the image is *displayed*,
227
+ `dpi` is how many pixels the *source* has. For a crisp image at a large `size`,
228
+ raise `dpi` so the source has enough pixels.
229
+
230
+ ## Troubleshooting
231
+
232
+ - **Garbage / `+++` instead of an image:** a tmux layer isn't forwarding sixel.
233
+ Add `set -as terminal-features ',*:sixel'` to that layer (both layers if
234
+ nested) and confirm tmux ≥ 3.4 with sixel.
235
+ - **Nothing appears:** check `tmux -V` ≥ 3.4 and sixel support
236
+ (`strings $(command -v tmux) | grep -i sixel`); confirm your terminal supports
237
+ sixel; run `plotty.enable(verbose=1)` to print diagnostics.
238
+ - **Image too large / small:** tune `size`. Blurry when enlarged? raise `dpi`.
239
+ - **Plot doesn't refresh when you resize the pane:** use viewer mode (the default
240
+ in tmux); inline mode doesn't auto-redraw on resize.
241
+
242
+ ## License
243
+
244
+ MIT
@@ -0,0 +1,74 @@
1
+ [project]
2
+ name = "plotty"
3
+ version = "1.0.0"
4
+ description = "Inline matplotlib plots in your terminal via sixel, in a tmux pane, over SSH"
5
+ readme = "README.md"
6
+ requires-python = ">=3.7"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "xuesoso", email = "xuesoso@gmail.com" }]
9
+ keywords = ["matplotlib", "sixel", "tmux", "ssh", "terminal", "plotting", "repl"]
10
+ classifiers = [
11
+ "Development Status :: 5 - Production/Stable",
12
+ "Environment :: Console",
13
+ "Framework :: Matplotlib",
14
+ "Intended Audience :: Science/Research",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Operating System :: POSIX",
17
+ "Programming Language :: Python :: 3",
18
+ "Topic :: Scientific/Engineering :: Visualization",
19
+ ]
20
+
21
+ # Runtime deps only. numpy ships with matplotlib but plotty imports it directly,
22
+ # so it's declared. Floors are kept low for Python 3.7 support — the resolver
23
+ # picks newer versions automatically on newer Pythons. Everything else (pandas,
24
+ # jupyter, ...) is dev-only — see below.
25
+ dependencies = [
26
+ "matplotlib>=3.5",
27
+ "numpy>=1.17",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/xuesoso/plotty"
32
+ Repository = "https://github.com/xuesoso/plotty"
33
+
34
+ [project.scripts]
35
+ plotty-view = "plotty:view"
36
+
37
+ [build-system]
38
+ requires = ["setuptools>=61.0"]
39
+ build-backend = "setuptools.build_meta"
40
+
41
+ # Single-module package living at src/plotty.py -> importable as `plotty`.
42
+ [tool.setuptools]
43
+ package-dir = { "" = "src" }
44
+ py-modules = ["plotty"]
45
+
46
+ # Tools for developing/testing plotty itself. Add your analysis packages here
47
+ # (pandas, seaborn, plotly, jupyter, ...) if you want `uv sync` to install them.
48
+ [dependency-groups]
49
+ dev = [
50
+ "pytest>=7.0",
51
+ "ipython>=7.0",
52
+ ]
53
+
54
+ [tool.ruff]
55
+ line-length = 100
56
+ target-version = "py37"
57
+
58
+ [tool.ruff.lint]
59
+ select = ["E", "F", "I", "W", "UP", "B", "SIM"]
60
+ ignore = ["E501"] # line length handled by formatter
61
+
62
+ [tool.ruff.format]
63
+ quote-style = "double"
64
+ indent-style = "space"
65
+
66
+ [tool.mypy]
67
+ python_version = "3.7"
68
+ ignore_missing_imports = true
69
+ warn_unused_ignores = true
70
+ check_untyped_defs = true
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["tests"]
74
+ addopts = "-ra --strict-markers"
plotty-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+