tformula 0.1.0

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/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # TFormula
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ Render LaTeX from **any CLI agent** directly inside your terminal.
6
+
7
+ > **Ghostty is the recommended terminal.** TFormula is developed and tested
8
+ > primarily with Ghostty and also works with terminals that implement the Kitty
9
+ > graphics protocol, including Kitty and WezTerm.
10
+
11
+ TFormula is a terminal-agnostic PTY proxy. It does not use Codex, Claude,
12
+ Gemini, or any other agent-specific API.
13
+
14
+ The child program still sees a normal terminal. TFormula forwards its ANSI
15
+ output unchanged, maintains a headless copy of the terminal screen, detects
16
+ visible TeX, renders it locally with MathJax, and places the result over the
17
+ source text using the Kitty graphics protocol. The original text remains in
18
+ the terminal buffer for copying.
19
+
20
+ ## Quick start in Ghostty
21
+
22
+ Open Ghostty and run an agent immediately without a global install:
23
+
24
+ ```sh
25
+ npx --yes tformula@latest codex
26
+ ```
27
+
28
+ Or install the short `tformula` command once:
29
+
30
+ ```sh
31
+ npm install --global tformula
32
+ ```
33
+
34
+ Then place `tformula` before whichever agent command you already use:
35
+
36
+ | Agent | Command |
37
+ |---|---|
38
+ | OpenAI Codex | `tformula codex` |
39
+ | Claude Code | `tformula claude` |
40
+ | Cursor Agent | `tformula agent` |
41
+ | Pi coding agent | `tformula pi` |
42
+ | Gemini CLI | `tformula gemini` |
43
+ | OpenCode | `tformula opencode` |
44
+ | Aider | `tformula aider` |
45
+ | Goose | `tformula goose` |
46
+ | Qwen Code | `tformula qwen` |
47
+ | Any other CLI agent | `tformula -- <agent-command> [args...]` |
48
+
49
+ The agent itself must already be installed and available on your `PATH`.
50
+ TFormula simply wraps the command; it has no agent-specific integration.
51
+
52
+ To use npx instead, replace `tformula` in any row with
53
+ `npx --yes tformula@latest`. For example:
54
+
55
+ ```sh
56
+ npx --yes tformula@latest codex
57
+ npx --yes tformula@latest claude
58
+ npx --yes tformula@latest agent
59
+ npx --yes tformula@latest pi
60
+ npx --yes tformula@latest gemini
61
+ npx --yes tformula@latest opencode
62
+ npx --yes tformula@latest aider
63
+ npx --yes tformula@latest goose
64
+ npx --yes tformula@latest -- claude --resume
65
+ npx --yes tformula@latest --shell
66
+ ```
67
+
68
+ `--shell` starts an enhanced login shell, so commands launched inside that shell
69
+ can be wrapped without creating an alias for each agent:
70
+
71
+ ```sh
72
+ tformula --shell
73
+ ```
74
+
75
+ Running `tformula` without arguments is equivalent to `tformula --shell`.
76
+
77
+ ## Requirements
78
+
79
+ - Ghostty recommended; Kitty, WezTerm, or another Kitty-graphics terminal
80
+ - macOS or Linux
81
+ - Node.js 20 or newer
82
+ - The CLI agent you want to run
83
+
84
+ The current implementation has been developed against Ghostty 1.3.1.
85
+
86
+ ## Install from this checkout
87
+
88
+ ```sh
89
+ npm install
90
+ npm run check
91
+ npm link
92
+ tformula codex
93
+ ```
94
+
95
+ ## Formula sizing
96
+
97
+ At startup and after terminal resize events, TFormula queries the terminal for
98
+ its cell dimensions in pixels. MathJax's natural `ex` dimensions are mapped to
99
+ the terminal cell height, so an ordinary mathematical symbol has approximately
100
+ the same visual size as neighboring terminal text. Fractions, sums, and other
101
+ tall constructs retain their natural proportions.
102
+
103
+ Formulas are never enlarged merely to fill the source rectangle. They are only
104
+ scaled down when they would exceed the columns or rows already occupied by the
105
+ source. This is necessary because inserting terminal rows behind a full-screen
106
+ TUI would desynchronize its cursor coordinates.
107
+
108
+ Formula scans are coalesced during streaming output instead of waiting for the
109
+ terminal to become completely idle. Unrelated status-bar or spinner updates do
110
+ not cancel formulas that remain unchanged on screen. Long PTY output bursts are
111
+ forwarded at line-boundary checkpoints of roughly one third of the terminal
112
+ height. TFormula completes a formula scan at each checkpoint before forwarding
113
+ more rows, so rendered images enter scrollback together with their source text
114
+ instead of being missed after an entire response scrolls past. When the terminal
115
+ grid or cell pixel size changes, TFormula replaces only the affected Kitty
116
+ placements.
117
+ The underlying PNG is retained and shared by every placement with the same
118
+ formula, size, and colors. Normal resizing only replaces images still in the
119
+ live viewport; off-screen placements are preserved so the terminal can scroll
120
+ and scale them with its own scrollback. Replacement is transactional: the old
121
+ placement is deleted only after the new cached variant is ready, and xterm
122
+ markers track its source rows through terminal reflow. A rapid sequence of font
123
+ size changes therefore keeps the previous rendered formula instead of exposing
124
+ the underlying TeX. `CSI 2J` invalidates visible placements,
125
+ while `CSI 3J` and `RIS` invalidate all placements and cached terminal images.
126
+ TFormula reserves a private image-ID range and deletes that complete range on
127
+ full reset and shutdown, including interrupted transmissions.
128
+
129
+ When an agent emits display math as a single standalone `$$...$$` or
130
+ `\[...\]` line, TFormula borrows adjacent blank terminal rows when available.
131
+ This gives fractions and derivatives enough vertical space to retain the same
132
+ base glyph size as simple equations. Inline math and display delimiters mixed
133
+ with prose are never expanded, so neighboring text is not covered.
134
+
135
+ A trailing inline formula can similarly use one following blank row for tall
136
+ fraction content. TFormula absorbs terminal punctuation into that overlay so it
137
+ stays next to the rendered expression. The common reciprocal-root form
138
+ `1/\sqrt{...}` is typeset as `\frac{1}{\sqrt{...}}`; slashes in ordinary units
139
+ such as `m/s` are left unchanged.
140
+
141
+ If a terminal does not answer pixel-size queries, TFormula falls back to 9x18
142
+ pixels. You can override that explicitly:
143
+
144
+ ```sh
145
+ tformula --cell-size 10x20 claude
146
+ ```
147
+
148
+ The default text-relative scale is 1.0. It can be adjusted without changing the
149
+ terminal font:
150
+
151
+ ```sh
152
+ tformula --scale 1.1 codex
153
+ TFORMULA_SCALE=0.9 tformula --shell
154
+ ```
155
+
156
+ ## Formula cache
157
+
158
+ Math rendering is content-addressed and shared by every TFormula-wrapped Agent
159
+ run for the current user. A normalized formula is typeset to SVG once. Each
160
+ terminal-ready PNG variant is then rasterized once for its exact display mode,
161
+ cell dimensions, scale, foreground, background, and source rectangle. Returning
162
+ to an earlier terminal font size reuses the existing PNG instead of invoking
163
+ MathJax or the rasterizer again.
164
+
165
+ Cache writes use per-item cross-process locks and atomic renames, so concurrent
166
+ Agents can safely request the same formula. In a live terminal session, one PNG
167
+ is uploaded once and reused by independent Kitty placements wherever the same
168
+ variant appears. The original TeX text remains in terminal scrollback.
169
+
170
+ On macOS the disk cache defaults to `~/Library/Caches/TFormula`; on Linux it
171
+ uses `$XDG_CACHE_HOME/tformula` or `~/.cache/tformula`. Override the location or
172
+ the default 256 MB limit with:
173
+
174
+ ```sh
175
+ TFORMULA_CACHE_DIR=/path/to/cache tformula codex
176
+ TFORMULA_CACHE_MAX_MB=512 tformula claude
177
+ ```
178
+
179
+ ## Detection
180
+
181
+ TFormula recognizes these explicit forms:
182
+
183
+ ```text
184
+ \[ ... \]
185
+ $$ ... $$
186
+ \( ... \)
187
+ $ ... $
188
+ ```
189
+
190
+ Some agent TUIs consume the backslashes around `\[` and `\]` while rendering
191
+ Markdown. For that case TFormula conservatively recognizes a bare `[`/`]`
192
+ block only when its body contains strong TeX features such as `\frac`, `\sum`,
193
+ subscripts, superscripts, or braced arguments.
194
+
195
+ The same compatibility rule applies when a TUI turns inline delimiters such as
196
+ `\(\rho\)` into `(\rho)`. TFormula renders the parenthesized span only when its
197
+ contents contain a recognized TeX command or similarly strong math structure;
198
+ ordinary prose in parentheses remains unchanged.
199
+
200
+ Short equations such as `E=mc^2`, `p=0`, and `c^2` are also recognized from
201
+ their operator structure. A single letter is inferred only in a symbol
202
+ definition item, where forms such as `- (E):energy` are unambiguous.
203
+
204
+ Consecutive definition items such as `- (\rho):电荷密度` are rendered as one
205
+ compact two-column MathJax array. This keeps symbols, colons, and descriptions
206
+ aligned even though their original TeX source strings have different widths.
207
+ Math expressions embedded in a description, including units written with
208
+ `\text{...}`, remain mathematical content inside that array.
209
+
210
+ Single-dollar expressions also require mathematical structure, which prevents
211
+ ordinary prices such as `$12.50` from being rendered.
212
+
213
+ ## Options
214
+
215
+ ```text
216
+ --shell Start the login shell
217
+ --no-math Run only as a transparent PTY proxy
218
+ --scale <number> Formula-to-terminal text scale (0.5 to 2.0)
219
+ --cell-size <WxH> Override terminal cell pixels
220
+ -C, --cwd <directory> Child working directory
221
+ --debug Print detection and sizing diagnostics
222
+ ```
223
+
224
+ Use `--` when an agent command or its arguments could be mistaken for TFormula
225
+ options:
226
+
227
+ ```sh
228
+ tformula -- claude --resume
229
+ ```
230
+
231
+ ## Safety and fallback behavior
232
+
233
+ - MathJax and fonts are installed locally; rendering does not use a CDN.
234
+ - Formula length is limited to 8192 characters.
235
+ - Commands that can load or embed external content, including `\require`,
236
+ `\href`, `\url`, and MathJax HTML/style commands, are rejected.
237
+ - A parse or render failure leaves the original LaTeX visible.
238
+ - On terminals without Kitty graphics support, TFormula remains a transparent
239
+ PTY proxy.
240
+
241
+ ## Development
242
+
243
+ ```sh
244
+ npm run build
245
+ npm test
246
+ npm run check
247
+ ```
248
+
249
+ The test suite covers delimiter inference, false-positive filtering, Unicode
250
+ column positions, terminal response parsing, text-relative geometry, Kitty
251
+ encoding, MathJax-to-PNG rendering, and generic command wrapping.
252
+
253
+ For an end-to-end diagnostic, add `--debug`. A successful render reports the
254
+ terminal cell size, source location, and generated pixel rectangle without
255
+ printing the formula image bytes.
@@ -0,0 +1,221 @@
1
+ # TFormula
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ 直接在终端中渲染**任意 CLI Agent** 输出的 LaTeX 公式。
6
+
7
+ > **推荐在 Ghostty 中使用。** TFormula 主要基于 Ghostty 开发和测试,也支持
8
+ > Kitty、WezTerm 等实现了 Kitty Graphics Protocol 的终端。
9
+
10
+ TFormula 是一个与 Agent 无关的 PTY 代理。它不调用 Codex、Claude、Gemini
11
+ 或其他 Agent 的专用 API,因此只要 Agent 能在终端中运行,就可以尝试使用
12
+ TFormula 包装。
13
+
14
+ Agent 看到的仍然是普通终端。TFormula 原样转发 ANSI 输出,同时维护一份
15
+ headless 终端画面,检测其中的 TeX,使用本地 MathJax 渲染,再通过 Kitty
16
+ 图形协议把公式图片覆盖到原始文字上。原始 LaTeX 仍保留在终端缓冲区中,
17
+ 可以正常复制。
18
+
19
+ ## 在 Ghostty 中快速开始
20
+
21
+ 打开 Ghostty,无需全局安装即可直接运行:
22
+
23
+ ```sh
24
+ npx --yes tformula@latest codex
25
+ ```
26
+
27
+ 也可以先全局安装一次,以后使用更短的命令:
28
+
29
+ ```sh
30
+ npm install --global tformula
31
+ ```
32
+
33
+ 然后把 `tformula` 放在你平时使用的 Agent 命令前面:
34
+
35
+ | Agent | 命令 |
36
+ |---|---|
37
+ | OpenAI Codex | `tformula codex` |
38
+ | Claude Code | `tformula claude` |
39
+ | Cursor Agent | `tformula agent` |
40
+ | Pi coding agent | `tformula pi` |
41
+ | Gemini CLI | `tformula gemini` |
42
+ | OpenCode | `tformula opencode` |
43
+ | Aider | `tformula aider` |
44
+ | Goose | `tformula goose` |
45
+ | Qwen Code | `tformula qwen` |
46
+ | 任意其他 CLI Agent | `tformula -- <agent命令> [参数...]` |
47
+
48
+ 相应的 Agent 本身需要已经安装,并且可以从当前 `PATH` 中找到。TFormula
49
+ 只负责包装命令,不负责安装 Agent。
50
+
51
+ 如果不想全局安装,把上表中的 `tformula` 换成
52
+ `npx --yes tformula@latest` 即可。例如:
53
+
54
+ ```sh
55
+ npx --yes tformula@latest codex
56
+ npx --yes tformula@latest claude
57
+ npx --yes tformula@latest agent
58
+ npx --yes tformula@latest pi
59
+ npx --yes tformula@latest gemini
60
+ npx --yes tformula@latest opencode
61
+ npx --yes tformula@latest aider
62
+ npx --yes tformula@latest goose
63
+ npx --yes tformula@latest -- claude --resume
64
+ npx --yes tformula@latest --shell
65
+ ```
66
+
67
+ `--shell` 会启动一个增强的登录 Shell。在这个 Shell 中启动命令时,不需要
68
+ 为每一个 Agent 单独创建别名:
69
+
70
+ ```sh
71
+ tformula --shell
72
+ ```
73
+
74
+ 不带参数运行 `tformula` 等价于 `tformula --shell`。
75
+
76
+ ## 环境要求
77
+
78
+ - 推荐 Ghostty;也支持 Kitty、WezTerm 或其他兼容 Kitty 图形协议的终端
79
+ - macOS 或 Linux
80
+ - Node.js 20 或更高版本
81
+ - 需要运行的 CLI Agent
82
+
83
+ 当前实现主要基于 Ghostty 1.3.1 开发和验证。
84
+
85
+ ## 从源码安装
86
+
87
+ ```sh
88
+ git clone https://github.com/mikewang817/TFormula.git
89
+ cd TFormula
90
+ npm install
91
+ npm run check
92
+ npm link
93
+ tformula codex
94
+ ```
95
+
96
+ ## 公式大小
97
+
98
+ TFormula 会在启动时以及终端尺寸变化后查询单元格的像素尺寸,再把 MathJax
99
+ 公式的自然 `ex` 高度映射到终端文字高度。因此普通数学符号会与周围文字大小
100
+ 接近,而分式、求和与导数仍保留自然的上下结构。
101
+
102
+ 公式不会为了填满源码区域而强制放大;只有在超出原始行列范围时才会缩小。
103
+ 这是因为全屏 TUI 中不能随意插入额外行,否则会破坏 Agent 的光标坐标。
104
+
105
+ 对于很长的 Agent 输出,TFormula 大约每输出三分之一屏就建立一个检查点,
106
+ 先完成公式检测和 placement,再继续输出。这样公式会与文字一起进入 scrollback,
107
+ 不会因为整段回复一次滚过屏幕而漏掉。
108
+
109
+ 当使用 `CMD +` 或 `CMD -` 改变字体大小时,新尺寸图片准备完成之前,旧公式
110
+ 会继续保留。替换操作是事务式的:只有新 placement 可以创建时,才删除旧
111
+ placement。xterm marker 会在终端 reflow 后继续跟踪公式所在行,因此滚出屏幕
112
+ 的已渲染公式不会退回 LaTeX 源码。
113
+
114
+ 如果终端无法返回单元格像素尺寸,默认使用 9×18 像素。也可以手动指定:
115
+
116
+ ```sh
117
+ tformula --cell-size 10x20 claude
118
+ ```
119
+
120
+ 默认公式比例为 1.0,可以独立调整:
121
+
122
+ ```sh
123
+ tformula --scale 1.1 codex
124
+ TFORMULA_SCALE=0.9 tformula --shell
125
+ ```
126
+
127
+ ## 公式缓存
128
+
129
+ 公式缓存采用内容寻址方式,并由当前用户启动的所有 TFormula Agent 进程共享:
130
+
131
+ - 同一个规范化公式只进行一次 MathJax SVG 排版。
132
+ - 每一种精确的字号、颜色、终端单元格和显示区域只生成一次 PNG。
133
+ - 多个 Agent 同时请求相同公式时,通过跨进程文件锁避免重复生成。
134
+ - 同一终端会话中的相同 PNG 只上传一次,不同位置共用图片数据并创建各自的
135
+ placement。
136
+ - 缩放回之前使用过的字号时,直接复用已有 PNG。
137
+
138
+ macOS 默认缓存目录:
139
+
140
+ ```text
141
+ ~/Library/Caches/TFormula
142
+ ```
143
+
144
+ Linux 默认使用:
145
+
146
+ ```text
147
+ $XDG_CACHE_HOME/tformula
148
+ ```
149
+
150
+ 或:
151
+
152
+ ```text
153
+ ~/.cache/tformula
154
+ ```
155
+
156
+ 可以修改目录或默认的 256 MB 上限:
157
+
158
+ ```sh
159
+ TFORMULA_CACHE_DIR=/path/to/cache tformula codex
160
+ TFORMULA_CACHE_MAX_MB=512 tformula claude
161
+ ```
162
+
163
+ ## 可识别的公式
164
+
165
+ TFormula 支持这些显式形式:
166
+
167
+ ```text
168
+ \[ ... \]
169
+ $$ ... $$
170
+ \( ... \)
171
+ $ ... $
172
+ ```
173
+
174
+ 某些 Agent TUI 在渲染 Markdown 时会吃掉 `\[`、`\]` 或 `\(`、`\)` 外层的
175
+ 反斜杠。为兼容这种情况,TFormula 也会谨慎识别:
176
+
177
+ - 包含 `\frac`、`\sum`、上下标或花括号参数的裸 `[` / `]` 公式块;
178
+ - 包含明确 TeX 命令或数学结构的 `(\rho)` 等括号表达式;
179
+ - `E=mc^2`、`p=0`、`c^2` 等短方程;
180
+ - `- (\rho):电荷密度` 等符号定义项;
181
+ - 连续符号定义列表,并将其渲染为对齐的两列表格。
182
+
183
+ 普通文字括号和 `$12.50` 等价格不会被当作公式。
184
+
185
+ ## 命令选项
186
+
187
+ ```text
188
+ --shell 启动登录 Shell
189
+ --no-math 仅作为透明 PTY 代理,不渲染公式
190
+ --scale <number> 公式相对终端文字的比例,范围 0.5~2.0
191
+ --cell-size <WxH> 手动指定终端单元格像素尺寸
192
+ -C, --cwd <directory> 指定 Agent 的工作目录
193
+ --debug 输出检测与尺寸调试信息
194
+ ```
195
+
196
+ 当 Agent 参数可能被误认为 TFormula 参数时,使用 `--` 分隔:
197
+
198
+ ```sh
199
+ tformula -- claude --resume
200
+ tformula -- opencode --continue
201
+ ```
202
+
203
+ ## 安全与降级行为
204
+
205
+ - MathJax 和字体全部在本地运行,不使用 CDN。
206
+ - 单个公式最长 8192 个字符。
207
+ - 禁止 `\require`、`\href`、`\url` 以及 MathJax HTML/样式命令等可能加载
208
+ 外部内容的命令。
209
+ - 解析或渲染失败时保留原始 LaTeX,不阻断 Agent。
210
+ - 终端不支持 Kitty 图形协议时,TFormula 会退化为透明 PTY 代理。
211
+
212
+ ## 开发
213
+
214
+ ```sh
215
+ npm run build
216
+ npm test
217
+ npm run check
218
+ ```
219
+
220
+ 需要端到端诊断时添加 `--debug`。成功渲染会报告终端单元格尺寸、源码位置和
221
+ 最终像素矩形,但不会打印图片数据。
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import type { CliOptions } from "./types.js";
3
+ export declare function parseArgs(argv: string[]): CliOptions | "help" | "version";
package/dist/cli.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ import process from "node:process";
3
+ import { realpathSync } from "node:fs";
4
+ import { createRequire } from "node:module";
5
+ import { fileURLToPath } from "node:url";
6
+ import { probeTerminal } from "./probe.js";
7
+ import { runProxy } from "./proxy.js";
8
+ const { version: VERSION } = createRequire(import.meta.url)("../package.json");
9
+ const HELP = `TFormula ${VERSION}
10
+
11
+ Render LaTeX produced by any terminal agent while preserving the original TUI.
12
+
13
+ Usage:
14
+ tformula [options] [--] [command ...]
15
+ tformula --shell
16
+
17
+ Examples:
18
+ tformula codex
19
+ tformula claude
20
+ tformula -- gemini --model gemini-2.5-pro
21
+ tformula --shell
22
+
23
+ Options:
24
+ --shell Start the login shell (default when no command is given)
25
+ --no-math Run only as a transparent PTY proxy
26
+ --scale <number> Formula-to-terminal text scale, default 1.0
27
+ --cell-size <WxH> Override terminal cell pixels, for example 9x18
28
+ -C, --cwd <directory> Child working directory
29
+ --debug Print diagnostics
30
+ -h, --help Show help
31
+ -V, --version Show version
32
+
33
+ TFormula queries the terminal's actual cell pixel size. Formulas keep their
34
+ natural MathJax proportions and are only reduced when they do not fit.
35
+ `;
36
+ function fail(message) {
37
+ process.stderr.write(`tformula: ${message}\n`);
38
+ process.exit(2);
39
+ }
40
+ export function parseArgs(argv) {
41
+ let cwd = process.cwd();
42
+ let renderMath = true;
43
+ let debug = false;
44
+ let scale = Number(process.env.TFORMULA_SCALE ?? "1");
45
+ let cellOverride;
46
+ let forceShell = false;
47
+ const commandParts = [];
48
+ for (let index = 0; index < argv.length; index += 1) {
49
+ const value = argv[index];
50
+ if (value === "--") {
51
+ commandParts.push(...argv.slice(index + 1));
52
+ break;
53
+ }
54
+ if (commandParts.length > 0 || !value.startsWith("-")) {
55
+ commandParts.push(value);
56
+ continue;
57
+ }
58
+ if (value === "-h" || value === "--help")
59
+ return "help";
60
+ if (value === "-V" || value === "--version")
61
+ return "version";
62
+ if (value === "--shell")
63
+ forceShell = true;
64
+ else if (value === "--no-math")
65
+ renderMath = false;
66
+ else if (value === "--debug")
67
+ debug = true;
68
+ else if (value === "--scale")
69
+ scale = Number(argv[++index]);
70
+ else if (value === "-C" || value === "--cwd")
71
+ cwd = argv[++index] ?? fail(`${value} requires a directory`);
72
+ else if (value === "--cell-size") {
73
+ const raw = argv[++index] ?? fail("--cell-size requires WIDTHxHEIGHT");
74
+ const match = raw.match(/^(\d+(?:\.\d+)?)x(\d+(?:\.\d+)?)$/u);
75
+ if (!match)
76
+ fail("--cell-size must look like 9x18");
77
+ cellOverride = { width: Number(match[1]), height: Number(match[2]) };
78
+ }
79
+ else
80
+ fail(`unknown option ${value}`);
81
+ }
82
+ if (!Number.isFinite(scale) || scale < 0.5 || scale > 2)
83
+ fail("--scale must be between 0.5 and 2");
84
+ if (forceShell && commandParts.length > 0)
85
+ fail("--shell cannot be combined with a command");
86
+ const shell = process.env.SHELL || "/bin/zsh";
87
+ const command = forceShell || commandParts.length === 0 ? shell : commandParts[0];
88
+ const args = forceShell || commandParts.length === 0 ? ["-l"] : commandParts.slice(1);
89
+ return { command, args, cwd, renderMath, debug, scale, cellOverride };
90
+ }
91
+ async function main() {
92
+ const parsed = parseArgs(process.argv.slice(2));
93
+ if (parsed === "help") {
94
+ process.stdout.write(HELP);
95
+ return;
96
+ }
97
+ if (parsed === "version") {
98
+ process.stdout.write(`${VERSION}\n`);
99
+ return;
100
+ }
101
+ const { capabilities, pendingInput } = await probeTerminal(parsed.cellOverride);
102
+ const exitCode = await runProxy(parsed, capabilities, pendingInput);
103
+ process.exitCode = exitCode;
104
+ }
105
+ let invokedDirectly = false;
106
+ if (process.argv[1]) {
107
+ try {
108
+ // npm link invokes this file through a symlink in the global bin folder.
109
+ invokedDirectly = realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
110
+ }
111
+ catch {
112
+ invokedDirectly = false;
113
+ }
114
+ }
115
+ if (invokedDirectly) {
116
+ main().catch((error) => {
117
+ process.stderr.write(`tformula: ${error instanceof Error ? error.message : String(error)}\n`);
118
+ process.exitCode = 1;
119
+ });
120
+ }
121
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { FormulaRegion } from "./types.js";
2
+ declare function mathScore(value: string): number;
3
+ declare function visualColumn(line: string, utf16Index: number): number;
4
+ interface ParenthesizedSegment {
5
+ start: number;
6
+ end: number;
7
+ body: string;
8
+ }
9
+ declare function parenthesizedSegments(line: string): ParenthesizedSegment[];
10
+ declare function looksLikeAsciiMath(value: string): boolean;
11
+ declare function isLikelyMath(value: string): boolean;
12
+ declare function inferredParenthesizedMath(line: string): ParenthesizedSegment[];
13
+ interface DefinitionItem {
14
+ body: string;
15
+ descriptionLatex: string;
16
+ startCol: number;
17
+ lineWidth: number;
18
+ }
19
+ declare function escapeTexText(value: string): string;
20
+ declare function descriptionToLatex(value: string): string;
21
+ declare function definitionItem(line: string): DefinitionItem | undefined;
22
+ declare function inferredDefinitionGroup(lines: string[], startRow: number): FormulaRegion | undefined;
23
+ declare function isStandaloneDisplayLine(line: string): boolean;
24
+ declare function expandStandaloneDisplayRegions(lines: string[], regions: FormulaRegion[]): FormulaRegion[];
25
+ declare function trailingInlineRegion(lines: string[], row: number, line: string, startIndex: number, endIndex: number, latex: string, confidence: FormulaRegion["confidence"]): FormulaRegion;
26
+ /**
27
+ * Detect formulas in the post-ANSI terminal screen. Explicit TeX delimiters are
28
+ * preferred. A conservative inferred form handles TUIs that turn `\[`/`\]`
29
+ * into bare bracket lines while leaving the TeX body visible.
30
+ */
31
+ export declare function detectFormulaRegions(lines: string[]): FormulaRegion[];
32
+ export declare const detectorInternals: {
33
+ descriptionToLatex: typeof descriptionToLatex;
34
+ definitionItem: typeof definitionItem;
35
+ escapeTexText: typeof escapeTexText;
36
+ expandStandaloneDisplayRegions: typeof expandStandaloneDisplayRegions;
37
+ inferredDefinitionGroup: typeof inferredDefinitionGroup;
38
+ inferredParenthesizedMath: typeof inferredParenthesizedMath;
39
+ isLikelyMath: typeof isLikelyMath;
40
+ isStandaloneDisplayLine: typeof isStandaloneDisplayLine;
41
+ looksLikeAsciiMath: typeof looksLikeAsciiMath;
42
+ mathScore: typeof mathScore;
43
+ parenthesizedSegments: typeof parenthesizedSegments;
44
+ trailingInlineRegion: typeof trailingInlineRegion;
45
+ visualColumn: typeof visualColumn;
46
+ };
47
+ export {};