@effect/printer

中文文档
0.51.0发布于 2026/07/30MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 100.1万

一个易于使用、可扩展的打印文件

中文使用文档
文档目录13 节
  1. 安装
  2. @effect/printer
  3. 概览
  4. 终端输出和不信任文本
  5. 简单示例
  6. 一般工作流程
  7. 版式如何运作
  8. 可用宽度
  9. 分组
  10. 漂亮打印机无法完成的事情
  11. 帮助提示
  12. 我应该用什么样的注释?
  13. 鸣谢

效果- TS 的漂亮打印机

安装

@effect/printer

npm install @effect/printer
pnpm install @effect/printer
yarn add @effect/printer
deno add npm:@effect/printer
bun add @effect/printer

概览

这个模块定义了一个漂亮的打印机,以灵活而方便的方式格式化文本. 想法是结合 Doc从许多小部件中取出,然后使用布局器将其转换为易于渲染 DocStream,然后可以将其转化为多种格式.

终端输出和不信任文本

叶子构造器将控制字符逐字保存 。 渲染返回字符串,不会使终端的不可信文本安全。 在将攻击者控制的文本写入终端之前, 应用 Doc.sanitize 在输入或子树边界。 只有在嵌入式终端序列可信和有意的情况下才能使用已存在的原始构造器和渲染器.

该文件由几个部分组成:

  1. 下面是图书馆的概况
  2. 拥有大量文件和实例的实际图书馆

简单示例

作为简单的示范,让我们使用 @effect/printer 来打印以下简单的Haskell类型定义.

example :: Int -> Bool -> Char -> IO ()

首先,我们来安排进口

import * as Doc from "@effect/printer/Doc"
import * as Array from "effect/Array"
import { pipe } from "effect/Function"

接下来,我们穿梭 "->" 字符介于我们类型之间,并添加线索 "::" 字符 :

const prettyTypes = (types: ReadonlyArray<string>): Doc.Doc<never> => {
  const symbolDocuments = pipe(
    Array.makeBy(types.length - 1, () => Doc.text("->")),
    Array.prepend(Doc.text("::"))
  )
  const typeDocuments = types.map(Doc.text)
  const documents = pipe(
    Array.zipWith(
      symbolDocuments,
      typeDocuments,
      (left, right) => Doc.catWithSpace(left, right)
    )
  )
  return Doc.align(Doc.seps(documents))
}

这个 seps 函数是使文档缩合的一种方法,但还有其他许多方法(例如:. vsep, (中文(简体) ), cat 财务报告和审定财务报表 fillSep(见A/C.5/49/70,附件)。 在我们的例子中, seps 如果当前行中还有空格,则用于分隔所有文档,如果剩余行太短,则用于新行.

接下来,我们把名字放在类型上,

const prettyDeclaration = (
  name: string,
  types: ReadonlyArray<string>
): Doc.Doc<never> => Doc.catWithSpace(Doc.text(name), prettyTypes(types))

现在我们可以定义包含某种类型签名的文档:

const name = "example"
const types = ["Int", "Bool", "Char", "IO ()"]
const doc: Doc.Doc<never> = prettyDeclaration(name, types)

该文件现在可以打印了! 作为奖金,它会自动适应可用的空间.

如果页面足够宽 (80 在此情况下,定义是空格分隔的.

const rendered = Doc.render(doc, { style: 'pretty' })
console.log(rendered)
// example :: Int -> Bool -> Char -> IO ()

如果我们将页面宽度缩小到 20 字符,同一文档使垂直对齐:

const rendered = Doc.render(doc, { style: 'pretty', options: { lineWidth: 20 } })
console.log(rendered)
// example :: Int
//         -> Bool
//         -> Char
//         -> IO ()

说到对齐,如果我们不使用 align 组合符 "->" 在每一行的开头, 而不是在下面 "::"。 。 。 .

一般工作流程

╔══════════╗
║          ║                         ╭────────────────────╮
║          ║                         │ vsep, pretty, <+>, │
║          ║                         │ nest, align, …     │
║          ║                         ╰─────────┬──────────╯
║          ║                                   │
║  Create  ║                                   │
║          ║                                   │
║          ║                                   ▽
║          ║                         ╭───────────────────╮
║          ║                         │        Doc        │
╠══════════╣                         │  (rich document)  │
║          ║                         ╰─────────┬─────────╯
║          ║                                   │
║          ║                                   │ Layout algorithms
║  Layout  ║                                   │ e.g. Layout.pretty
║          ║                                   ▽
║          ║                         ╭───────────────────╮
║          ║                         │     DocStream     │
╠══════════╣                         │ (simple document) │
║          ║                         ╰─────────┬─────────╯
║          ║                                   │
║          ║                                   ├─────────────────────────────╮
║          ║                                   │                             │ treeForm
║          ║                                   │                             ▽
║          ║                                   │                     ╭───────────────╮
║          ║                                   │                     │    DocTree    │
║  Render  ║                                   │                     ╰───────┬───────╯
║          ║                                   │                             │
║          ║               ╭───────────────────┼─────────────────╮  ╭────────┴────────╮
║          ║               │                   │                 │  │                 │
║          ║               ▽                   ▽                 ▽  ▽                 ▽
║          ║       ╭───────────────╮   ╭───────────────╮   ╭───────────────╮   ╭───────────────╮
║          ║       │ ANSI terminal │   │  Plain Text   │   │ other/custom  │   │     HTML      │
║          ║       ╰───────────────╯   ╰───────────────╯   ╰───────────────╯   ╰───────────────╯
║          ║
╚══════════╝

版式如何运作

提出文档有两个关键概念:可用的宽度和分组.

可用宽度

布局算法将尽量避免超过最大宽度 Doc尽可能插入换行符。 可用的布局梳理器使得可以相当直截了当地说明布局算法(例如通过 seps 函数).

还有丝带宽度的概念. 丝带是一行被印出的部分(即行长没有主缩进). 布局算法采用丝带分数参数,该参数指定了一行在试图分解之前需要填充多少. 宽度80的文档中带宽为0.5会使布局算法尽量避免超过 0.5 * 80 = 40 (指当前缩入深度).

分组

文档可以是 grouped,它告诉布局算法,它应该试图将其倒塌为一行. 如果结果不符合限制(以页和丝带宽表示),则文档不会被更改。 这样可以进行倒向渲染,这样即使原始文档会超过布局限制,我们也能获得良好的效果.

漂亮打印机无法完成的事情

由于Wadler/Leijen算法的设计方式,目前有几件事是不支持的,极有可能没有合理的执行而不显著地改变布局算法. 特别是,这包括:

  • 引导符号,而不只是缩进的空格(例如Linux树工具使用)
  • 多列布局,特别是相邻有多个等宽单元格的表格

帮助提示

我应该用什么样的注释?

TL; DR - 使用语义注释 Doc,然后在列出“文件”之后,只绘制到后端特定说明.

例如,假设您想要漂亮地打印一些编程语言代码. 如果要将关键词为红色,请注明 Doc 类型有: Keyword 字段(没有任何颜色概念),然后在显示文档后,将注释转换为映射 Keyword 改为 Red (使用时) DocStream.reAnnotate) (中文(简体) ). 备选案文(不建议采用)直接说明 Doc 与 Red。 。 。 .

虽然这两个版本同样运作良好,并会产生相同的产出,但建议的方法有两个重大优点:模块性和可扩展性.

模块化: 改变颜色 Keyword铺设后 Document 意味着只需要一个修改(即: DocStream.reAnnotate)的颜色 Keyword未来需要改变。 如果你有直接注解 Doc有颜色的微量 Red如果需要改变颜色,则需要进行全文搜索/替换.

扩展性: 添加不同的渲染 Keyword 在建议的版本中,与增加以下变式一样简单: DocStream.reAnnotate 转换 Doc 对别的东西的注释。 另一方面,让我们假设你有 Red 作为注释 Doc 而您想要执行的后端没有色彩的概念(考虑纯正的文字, 你现在需要担心什么是地图 红色 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}这个案子没有可听的 应否略去? 怎么样 红色 在新后端的背景? 此外,请考虑关键字和变量已被标记为红色的情况,但您只想要更改变量的颜色.

鸣谢

此软件包为 https://github.com/quchen/prettyprinter (中文(简体) )

版本与发布记录

@effect/printer 共发布 305 个版本,首次发布于 2022/05/27;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.51.0latest2026/07/303 个月前
0.50.02026/07/134 个月前
0.49.02026/03/207 个月前
0.48.02026/03/177 个月前
0.47.02025/11/041 年前
0.46.02025/09/301.1 年前

其他发布通道:snapshot → 0.0.0-snapshot-6ebc752baf28354006ca2a0ae783a5bccf5de9ad。

关于 @effect/printer 的常见问题

@effect/printer 是什么?

一个易于使用、可扩展的打印文件

如何安装 @effect/printer?

在项目目录运行 npm install @effect/printer,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:effect(^3.22.1)、@effect/typeclass(^0.41.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@effect/printer 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@effect/printer 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@effect/printer 可以商用吗?

@effect/printer 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@effect/printer 的下载量有多少?

根据 npm 官方下载统计,@effect/printer 在 2026/10/13 – 2026/11/11 这 30 天内被下载 1,001,051 次,日均约 33,368 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@effect/printer 还在维护吗?

最新版本 0.51.0 发布于 2026/07/30(3 个月前);至今共发布 305 个版本,其中过去 12 个月发布了 4 个;首次发布于 2022/05/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。