@cnc-tools/cli-kit (英语)
节点CLI的终端外观-feel:能力检测,ANSI剥取,一个小主题,a live-region stream sink,以及用于多步指令的相位运行渲染器.
阶段运行显示在 TTY 上更新的检查表 :
Deploying web
✓ Build bundle ready
compiling…
⠹ Push Pushing layer 3/5
uploading…
• Verify pending
sha256:3f2a… done
被取代的标签 仍然停留在他们的排 淡的历史。 当输出被管道或捕获时,运行 打印一个简单的固定框架.
工具箱唯一的运行时间依赖是 log-update,只有 stream 财务报告和审定财务报表 phase-run 切入点
装上它。 这个 clinkr 切入点 剪辑器
应用和进口 @vercel/clinkr,可选择的对等依赖;没有其他切入点.
安装
npm install @cnc-tools/cli-kit
需要节点22.19或更新. 该套装只采用无害环境管理,船舶编译了JavaScript和类型申报.
入境点
| 导入 | 它给你什么 |
|---|---|
@cnc-tools/cli-kit/caps | Caps, (中文(简体) ), resolveCaps, (中文(简体) ), resolveProcessCaps, (中文(简体) ), resolveStreamCaps, (中文(简体) ), resolveSettledNonInteractiveCaps |
@cnc-tools/cli-kit/ansi | stripAnsi |
@cnc-tools/cli-kit/clinkr | renderOutcome, (中文(简体) ), ui, (中文(简体) ), path, (中文(简体) ), muted, (中文(简体) ), status, (中文(简体) ), capsFor: cli- kit 寻找 Clinkr 应用程序 |
@cnc-tools/cli-kit/theme | paint, (中文(简体) ), dim, (中文(简体) ), bold, (中文(简体) ), glyph, (中文(简体) ), renderTable, (中文(简体) ), renderResultBlock, (中文(简体) ), statusLine,文本帮助 |
@cnc-tools/cli-kit/stream | createStreamSink, (中文(简体) ), runStream:活区及其非TTY合同 |
@cnc-tools/cli-kit/phases | PhaseEvent, (中文(简体) ), PhaseSpec, (中文(简体) ), PhaseState, (中文(简体) ), createPhaseStateStore (纯粹,不渲染) |
@cnc-tools/cli-kit/phase-run | startPhaseRun, (中文(简体) ), createPhaseRun,以及框架、生命周期和尾部构件 |
Clinkr 应用程序
克林克解决终端,应用颜色优先,选择流,并写出JSON和一个脚本读取的内容.
cli-kit画的是人们所看到的。 调用它的 renderOutcome 每个结果 render数字 :
import { muted, path, renderOutcome } from "@cnc-tools/cli-kit/clinkr";
// In a command's outcomes:
render: ({ worktreePath, slotName }) =>
renderOutcome({ done: ["Moved to", path(worktreePath)], rows: [["Slot", slotName ?? muted("—")]] }),
传过来 ui 改为 createApplication 所以每一个错误, 克林克自己的和应用程序的 canceled 共享
听着 该布局为cli-kit自有:一双柱地沟,标签/值行取自第18栏的值, ✓ 完成的项目
结果, ! 警告者, ✗ 用于错误标题,最多5个列表项目,最多2个恢复步骤。 颜色关闭
它打印的布局没有逃生代码; 上面有颜色画出格言、 标签、 值和表格页眉
每一个部分的溪流。 当地语无法渲染出Unicode时,地语会倒回ASCII.
renderOutcome(content)使结果的内容带有默认限制。 内容取自克林克ResultContent, (中文(简体) ), 和有字符串的样式值:done,行、行和表格单元格。 表格单元格也可能是 Clinker 的 链接,{ text, url }: 上面的颜色以口音的 OSC 8 超链接来显示其文本, 链接的颜色, 其 在文字上测量的栏;用彩色去掉,在管子上,它就是一个文字.path(text), (中文(简体) ),muted(text),以及status(text, tone)是样式值: 文件系统路径, 递归文本 作为占位符, 和状态词在一个基调。 每个人为JSON和剧本读取的 保留了纯文本.ui是应用程序带有默认限制的 UI .createOutcomeRenderer({ maximumListItems })财务报告和审定财务报表createUi({ maximumListItems, maximumRecoverySteps })让你 拥有其他限制。 每个限值是一个正安全整数;其他任何投出一个RangeError。 。 。 .
能力
每个渲染器都需要 Caps 明确并返回字符串,因此输出在测试中具有决定性.
import { resolveCaps, resolveProcessCaps, resolveStreamCaps } from "@cnc-tools/cli-kit/caps";
const caps = resolveProcessCaps(); // reads process.stdout and process.env
const stderrCaps = resolveStreamCaps(process.stderr); // for progress drawn on stderr
const testCaps = resolveCaps({ isTty: false, columns: 100, env: {} });
isTty 财务报告和审定财务报表 columns 描述你所解决的溪流。 保持低调的CLI
可读取的机器和从 stderr 上提取进度应解决顶盖 process.stderr。 。 。 .
颜色从正色降解为256和16个颜色,最后变为零. 无空 NO_COLOR 转弯
颜色脱落和分数 FORCE_COLOR。非 TTY 获得没有颜色,除非 FORCE_COLOR 问取来. 胶片
回到ASCII,当地方, LC_ALL,则 LC_CTYPE,则 LANG,不是 UTF-8;是空的
计数为未设置。 使用 resolveSettledNonInteractiveCaps() 汇的汇
终端出价未知,如回调和捕获输出等.
主题
import { renderResultBlock, renderTable, cell } from "@cnc-tools/cli-kit/theme";
console.log(renderResultBlock(caps, { kind: "success", headline: "Deployed.", body: "3 services" }));
console.log(
renderTable({
caps,
columns: [
{ header: "SERVICE", width: "auto" },
{ header: "STATUS", width: "fill" },
],
rows: [[cell("web"), cell("ok")]],
}).join("\n"),
);
statusLine 使一个相行。 它的名称列垫默认为 13; 通过 nameWidth 改为
换一下.
布局测量终端单元格,而不是字符串长度. terminalWidth 将CJK和大多数emoji计为两个
单元格和结合标记为零,而截断则不会分出一个石墨. 这是一个近似:
终端对于一些emoji和模糊的width字符仍有分歧.
流槽
createStreamSink(caps, deps) 使框架被传递。 它不排序工作.
- {\FN黑体\FS22\BORD1\SHAD0\3AHBE\4AH00\FSCX67\FSCY66\2CHFFFFFF\3CH808080}TTY: 重新绘制 a
log-update活区域,隐藏并恢复光标,并旋转所持帧 每90ms (英语). 活地重画会暂停终端自动包装, 这样一个 Stale 宽度不能留下孤行 . - 非 TTY 类型 : 没有动画,没有光标代码,没有重画出逃生. 换行
onOutput。 。 。 . 固定的相框写了一次,从ANSI取出. 捕获输出的主机依赖于 这个.
每一个接缝都可以注射: writer (默认通过) log-update, (中文(简体) ), clock (违约)
setTimeout, (中文(简体) ), onOutput (默认写入每条流线通过) writer,所以一个作家
指向起伏器,以及 dwellMs,每个时间间隔规则 hold。默认住有一个
base 勾选; 将您自己的规则传递给慢步 :
const sink = createStreamSink(caps, {
dwellMs: (transient, tickMs) => (transient?.startsWith("Uploading") ? tickMs * 3 : tickMs),
});
使用 runStream(caps, deps, body) 以恢复光标,即使 body 掷出.
sink.emitTransient(line) 一个非TTY水槽通过它
onOutput,而一个 TTY 槽则没有写作,所以现场区域仍然是唯一的作家. 从一个掷出
onOutput 到达呼叫者 emitTransient 同步; 通过 hold,它拒绝
回到承诺.
sink.finish(finalLines, { persist: false }) 抹去活区域 而不是持续它,a
非 TTY 槽写入未解析帧 。 仅 finalLines 已写入。 习惯 writer 执行
clear() 这条路.
阶段运行快速启动
import { startPhaseRun } from "@cnc-tools/cli-kit/phase-run";
const run = startPhaseRun({
title: "Deploying web",
phases: [
{ key: "build", name: "Build", label: "compiling…", detail: "bundle ready" },
{ key: "push", name: "Push", label: "uploading…", detail: "image pushed" },
{ key: "verify", name: "Verify", label: "checking health…", detail: "healthy" },
],
});
try {
run.start("build");
run.done("build");
run.start("push");
run.progress("push", "Pushing layer 3/5");
run.note("sha256:3f2a… done\n");
run.done("push");
await run.finish({ finalLines: ["Deployed web."] });
} finally {
await run.stop();
}
finish 解决每个阶段仍然开放。 如果你打电话 fail() 首先,失败的行保持红色
以后的阶段仍待处理. skip(key, detail?) 财务报告和审定财务报表 cancel(key, detail?) 将一行作为跳过
(单位:千美元)–)或已取消(⊖,用于中断的工作). note 将原始子进程输出输入 TTY 上的暗尾线,所以
生活区仍然是唯一的作家. startPhaseRun 还接受 caps, (中文(简体) ), writer, (中文(简体) ), clock, (中文(简体) ),
onOutput, (中文(简体) ), dwellMs, (中文(简体) ), showRuntimeDetails (排列行显示 detail 转至 done, (中文(简体) ),
nameWidth, (中文(简体) ), sequencing,以及 collapse。 。 。 .
过 finish({ persist: false }) 当活的检查表是短暂的 和其他的东西,例如
报告Stdout,是永久记录。 活体区域被抹去,没有固定框架
写在TTY或其他地方.
如果 TTY 旋转器在背景中失败( 抛出) writer.redraw 或拒绝
clock.sleep),运行记录了第一个出错,停止重绘,从不让它作为一个出错
无所取弃. finish 仍试图恢复已解决的框架和光标 stop
仍然试图恢复,然后用这个自旋器错误拒绝。 通过断裂恢复
写作失败,所以 finally 以上事项: stop 复试取之.
如果画第一帧扔, startPhaseRun (或 run.begin试图恢复光标,
然后抛出油漆出错,即使修复也失败. startPhaseRun 返回无会话
然后,所以快速启动 finally 从不运行; 失败后 run.begin, (中文(简体) ), run.stop() 重试
修复。 在TTY外, 扔东西 onOutput (或默认) writer.write(中文(简体) )
从助手中同步抛出或 emit 相继出现后,就叫它浮出水面
国家进步 finally 仍在运行 stop。 。 。 .
分步骤
一个阶段 substeps 宣布一个级别的儿童行。 子步骤不筑巢: PhaseSpec 类型
拒绝子步骤 substeps,而州商店 扔一个在建筑或一个
phases-declared 事件,然后使标题和行保持不变.
活动
制作人报告这些进展 PhaseEvent编号:
| 活动 | 效果 |
|---|---|
phases-declared | 替换标题和行集. |
title-changed | 替换标题. |
phase-started | 标记一行活动,带有可选标签. |
phase-progress | 更改活动行的标签 . history: "replace" 放弃旧标签而不是保留它. |
phase-notes | 替换一行的笔记:在其下方显示纯文本,被包而不是被切. |
phase-done | 解决一行. |
phase-skipped | 解决一行跳过: 它从来没有运行. |
phase-cancelled | 解决一行已取消: 它被中断 . |
phase-failed | 解决一行失败, 以事业为标签 . |
使用 history: "replace" 用于快速变化状态,例如一步内的一个艺名. 这行的
历史仅保留您想要保存的标签, 并且一个非 TTY 运行日志不会对此进行瞬态行 .
使用 phase-notes 对于文本,阅读器需要全部内容,例如为什么一个步骤被重审. 历史和尾巴
线被切到终端宽度; 笔记包, 续行缩入两个单元格。 A 类
排行保存它的笔记 在它和解后, 他们改变不了它的状态.
顺序
默认 sequencing: "implicit" 适合线性工作流程。 每打开一个行标记
行已完成, 解决父程序会解开子程序, 而失败的子程序会失效 .
继续过去的失败的跑步,例如试跑者,应该通过 sequencing: "explicit"。 。 。 .
然后每行只能通过自己的活动解决。 启动子步骤激活待决父程序, 但是
解决不了其他问题。 失败的子步骤让其父母独自一人 finish 标记每行
打开作为跳过, 不管失败。 制作人和每家商店 制作它的活动,必须使用
同样的模式.
折叠高高的核对表
collapse: true 保持长清单短。 固定的行会变成一行 加上任何分步骤
失败或携带笔记。 待决行会隐藏其子步骤直到开始,只有活动行
扩展。 在一个活跃的行中,定居的子步骤会降低历史. 框架比终端高 仍然失去他们的上行 log-update剪辑.
如果您的工作流程已经发布 PhaseEvents, 用途 createPhaseRun({ caps, phases, deps }) 输入
事件改为 run.emit(event)。用于自定义显示,例如主机部件,使用
createPhaseStateStore 从 phases 并表达自己的观点.