@heyhuynhgiabuu/pi-pretty 0.1.6 → 0.1.7
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.
- package/package.json +1 -1
- package/src/index.ts +46 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyhuynhgiabuu/pi-pretty",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Pretty terminal output for pi — syntax-highlighted file reads, colored bash output, tree-view directory listings, and more.",
|
|
5
5
|
"author": "huynhgiabuu",
|
|
6
6
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -157,12 +157,41 @@ function lang(fp: string): BundledLanguage | undefined {
|
|
|
157
157
|
|
|
158
158
|
// ---------------------------------------------------------------------------
|
|
159
159
|
// Terminal image rendering (iTerm2 / Kitty / Ghostty inline image protocols)
|
|
160
|
+
// Handles tmux passthrough for image protocols.
|
|
160
161
|
// ---------------------------------------------------------------------------
|
|
161
162
|
|
|
162
163
|
type ImageProtocol = "iterm2" | "kitty" | "none";
|
|
163
164
|
|
|
164
|
-
|
|
165
|
+
const IS_TMUX = !!process.env.TMUX;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Detect the outer terminal when running inside tmux.
|
|
169
|
+
* tmux sets TERM_PROGRAM=tmux, but the real terminal is often in
|
|
170
|
+
* the environment of the tmux server or can be inferred.
|
|
171
|
+
*/
|
|
172
|
+
function getOuterTerminal(): string {
|
|
173
|
+
// Direct terminal (not in tmux)
|
|
165
174
|
const term = process.env.TERM_PROGRAM ?? "";
|
|
175
|
+
if (term !== "tmux" && term !== "screen") return term;
|
|
176
|
+
|
|
177
|
+
// Inside tmux: check common env vars that leak through
|
|
178
|
+
// Ghostty sets this; iTerm2 sets LC_TERMINAL
|
|
179
|
+
if (process.env.LC_TERMINAL === "iTerm2") return "iTerm.app";
|
|
180
|
+
|
|
181
|
+
// TERM_PROGRAM_VERSION sometimes survives into tmux
|
|
182
|
+
// Try to detect via COLORTERM or other hints
|
|
183
|
+
if (process.env.GHOSTTY_RESOURCES_DIR) return "ghostty";
|
|
184
|
+
|
|
185
|
+
// Default: assume modern terminal if truecolor is supported
|
|
186
|
+
if (process.env.COLORTERM === "truecolor" || process.env.COLORTERM === "24bit") {
|
|
187
|
+
// Can't determine exact terminal, but likely modern
|
|
188
|
+
return "unknown-modern";
|
|
189
|
+
}
|
|
190
|
+
return term;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function detectImageProtocol(): ImageProtocol {
|
|
194
|
+
const term = getOuterTerminal();
|
|
166
195
|
// Ghostty and Kitty use the Kitty graphics protocol
|
|
167
196
|
if (term === "ghostty" || term === "kitty") return "kitty";
|
|
168
197
|
// iTerm2, WezTerm, Mintty support the iTerm2 protocol
|
|
@@ -171,6 +200,18 @@ function detectImageProtocol(): ImageProtocol {
|
|
|
171
200
|
return "none";
|
|
172
201
|
}
|
|
173
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Wrap escape sequence for tmux passthrough.
|
|
205
|
+
* tmux requires: ESC Ptmux; <escaped-sequence> ESC \
|
|
206
|
+
* Inner ESC chars must be doubled.
|
|
207
|
+
*/
|
|
208
|
+
function tmuxWrap(seq: string): string {
|
|
209
|
+
if (!IS_TMUX) return seq;
|
|
210
|
+
// Double all ESC chars inside the sequence
|
|
211
|
+
const escaped = seq.replace(/\x1b/g, "\x1b\x1b");
|
|
212
|
+
return `\x1bPtmux;${escaped}\x1b\\`;
|
|
213
|
+
}
|
|
214
|
+
|
|
174
215
|
/**
|
|
175
216
|
* Render base64 image inline using iTerm2 inline image protocol.
|
|
176
217
|
* Protocol: ESC ] 1337 ; File=[args] : base64data BEL
|
|
@@ -184,7 +225,8 @@ function renderIterm2Image(
|
|
|
184
225
|
if (opts.name) args.push(`name=${Buffer.from(opts.name).toString("base64")}`);
|
|
185
226
|
const byteSize = Math.ceil(base64Data.length * 3 / 4);
|
|
186
227
|
args.push(`size=${byteSize}`);
|
|
187
|
-
|
|
228
|
+
const seq = `\x1b]1337;File=${args.join(";")}:${base64Data}\x07`;
|
|
229
|
+
return tmuxWrap(seq);
|
|
188
230
|
}
|
|
189
231
|
|
|
190
232
|
/**
|
|
@@ -207,13 +249,10 @@ function renderKittyImage(
|
|
|
207
249
|
const more = isLast ? 0 : 1;
|
|
208
250
|
|
|
209
251
|
if (isFirst) {
|
|
210
|
-
// First chunk: include all metadata
|
|
211
|
-
// a=T (transmit+display), f=100 (PNG), t=d (direct data)
|
|
212
252
|
const colPart = opts.cols ? `,c=${opts.cols}` : "";
|
|
213
|
-
chunks.push(`\x1b_Ga=T,f=100,t=d,m=${more}${colPart};${chunk}\x1b\\`);
|
|
253
|
+
chunks.push(tmuxWrap(`\x1b_Ga=T,f=100,t=d,m=${more}${colPart};${chunk}\x1b\\`));
|
|
214
254
|
} else {
|
|
215
|
-
|
|
216
|
-
chunks.push(`\x1b_Gm=${more};${chunk}\x1b\\`);
|
|
255
|
+
chunks.push(tmuxWrap(`\x1b_Gm=${more};${chunk}\x1b\\`));
|
|
217
256
|
}
|
|
218
257
|
}
|
|
219
258
|
|