131 个版本 (29 个重大更改)

0.30.0 2024年8月12日
0.29.4 2024年6月17日
0.29.2 2024年4月24日
0.29.1 2024年2月10日
0.6.2 2019年7月31日

#16 in 文本处理

Download history 9559/week @ 2024-04-30 8687/week @ 2024-05-07 9654/week @ 2024-05-14 7332/week @ 2024-05-21 9116/week @ 2024-05-28 9540/week @ 2024-06-04 9777/week @ 2024-06-11 12043/week @ 2024-06-18 7687/week @ 2024-06-25 8947/week @ 2024-07-02 10624/week @ 2024-07-09 10479/week @ 2024-07-16 11457/week @ 2024-07-23 11854/week @ 2024-07-30 10316/week @ 2024-08-06 10101/week @ 2024-08-13

45,481 每月下载量
用于 86 个 Crates (79 直接)

MIT 许可证

445KB
6.5K SLoC

MIT Latest Version docs Chat on Miaou

一个利用 Markdown 格式化终端渲染的 CLI 工具库,允许分离结构、数据和皮肤。

基于 crossterm,因此可以在大多数终端上运行(甚至是在 Windows 上)。

text

目标不是显示任何具有各种扩展的 Markdown 文本(终端实际上并不适合这样做)。目标更倾向于在文本和皮肤都容易配置的情况下,改善终端应用程序中的文本显示。

Termimad 还包括一些帮助在多线程应用程序中高效管理事件和用户输入的实用程序。

包装、表格平衡和 滚动 是 Termimad 的基本功能。

文本或表格可以显示在屏幕的未知部分,如果需要,可以滚动,并具有动态发现的宽度。

例如,这个 Markdown

|:-:|:-:|-
|**feature**|**supported**|**details**|
|-:|:-:|-
| tables | yes | pipe based, with or without alignments
| italic, bold | yes | star based |
| inline code | yes | `with backquotes` (it works in tables too)
| code bloc | yes |with tabs or code fences
| syntax coloring | no |
| crossed text |  ~~not yet~~ | wait... now it works `~~like this~~`
| horizontal rule | yes | Use 3 or more dashes (`---`)
| lists | yes|* unordered lists supported
|  | |* ordered lists *not* supported
| quotes |  yes |> What a wonderful time to be alive!
| links | no | (but your terminal already handles raw URLs)
|-

将根据宽度给出不同的结果

table

table

table

使用方法

[dependencies]
termimad = "0.20"

使用默认皮肤

termimad::print_inline("**some** *nested **style*** and `some(code)`");

print!("{}", termimad::inline("**some** *nested **style*** and `some(code)`"));

结果

simple example

具有自定义皮肤的行内代码片段

行内代码片段 是一行或更少的。

let mut skin = MadSkin::default();
skin.bold.set_fg(Yellow);
skin.print_inline("*Hey* **World!** Here's `some(code)`");
skin.paragraph.set_fgbg(Magenta, rgb(30, 30, 40));
skin.italic.add_attr(Underlined);
println!("\nand now {}\n", skin.inline("a little *too much* **style!** (and `some(code)` too)"));

结果

too much style

文本

文本 可以有多个行。表格和代码块会自动对齐、缩进和统一包装。

skin.print_text("# title\n* a list item\n* another item");

在原始终端中的可滚动 TextView

scrollable

此示例的代码位于 examples/scrollable。要读取整个文本,请执行以下操作

cargo run --example scrollable

模板

为了将渲染格式与内容分离,您可能希望有一些常量 Markdown,并用动态项填充一些占位符。

对于这个问题,format! 宏并不总是一个好的解决方案,因为您可能无法确定内容是否不包含可能破坏 Markdown 的字符。

一个解决方案是使用其中一个模板函数或宏。

模板对于 Markdown,就像预编译语句对于 SQL 一样:只解释一次,防止内容被解释为结构的一部分。

行内模板

示例

mad_print_inline!(
    &skin,
    "**$0 formula:** *$1*", // the markdown template, interpreted once
    "Disk",  // fills $0
    "2*π*r", // fills $1. Note that the stars don't mess the markdown
);

mad_print_inline

使用 skin.print_inline(format!( ... )) 来构建某些 Markdown 并解析它,与使用的主要区别

  • Markdown 解析和模板构建仅执行一次(内部使用 once_cell
  • 给定的值不会被解释为 Markdown 片段,也不会影响样式
  • 参数可以省略、重复,以任何顺序给出
  • 不支持 fmt 参数或其他除了 &str 的参数 (当前版本)

内联模板与自动展开或省略号结合使用特别方便,用于在终端应用程序中填充字段。

inline-template 示例中,您可以找到更多示例和建议。

文本模板

当您想要填充多行区域时,例如终端应用程序的帮助页面,您可以使用文本模板。

模板定义占位符为 ${name},您可以在使用它时填充这些占位符。

例如

let text_template = TextTemplate::from(r#"
    # ${app-name} v${app-version}
    It is *very* ${adj}.
    "#);
let mut expander = text_template.expander();
expander
    .set("app-name", "MyApp")
    .set("adj", "pretty")
    .set("app-version", "42.5.3");
skin.print_expander(expander);

这将渲染成这样

text_template_01

使用 set 设置的值不会被解析为 Markdown,因此它们可以自由地包含星号或反引号。

模板是可重用的,并且可以从文本内容或任何字符串定义。

通过使用 子模板,您可以处理重复。它们在处理列表或表格时很有用。

例如

let text_template = TextTemplate::from(r#"
    |:-:|:-:|:-:|
    |**name**|**path**|**description**|
    |-:|:-:|:-|
    ${module-rows
    |**${module-name}**|`${app-version}/${module-key}`|${module-description}|
    }
    |-|-|-|
    "#);
let mut expander = text_template.expander();
expander
    .set("app-version", "2");
expander.sub("module-rows")
    .set("module-name", "lazy-regex")
    .set("module-key", "lrex")
    .set("module-description", "eases regexes");
expander.sub("module-rows")
    .set("module-name", "termimad")
    .set("module-key", "tmd")
    .set_md("module-description", "do things on *terminal*");
skin.print_expander(expander);

要获取

text_template_02

在这个示例中,您可以看到

  • sub("module-rows") 获取一个名为 module-rows 的子模板展开器
  • set_md 可以在您想要插入不仅仅是原始未解释的字符串,而是一些内联 Markdown 时使用。
  • 您不需要再次填充全局占位符(在这里是 ${app-version})。

如果您想要插入一个代码块,您可以使用 set_lines,它将行样式应用于所有传递的行。

例如

let text_template = TextTemplate::from(r#"
    ## Example of a code block
        ${some-function}
    "#);
let mut expander = text_template.expander();
expander.set_lines("some-function", r#"
    fun test(a rational) {
    irate(a)
    }
    "#);
skin.print_expander(expander);

要获取

text_template_03

您可以在文档和示例中找到更多文本模板函数(运行 cargo run --example text-template)。

您可能还对 OwningTemplateExpander 感兴趣:这是一个拥有值的替代展开器,这在您在子模板中迭代构建它们时可能很有用。

提问

在 CLI 应用程序中,经常需要要求用户选择一个答案。 Question API 和 ask! 宏涵盖了大多数基本需求。

以下是一个带有默认选项(通过按 enter 获取)和返回值的提问示例

let choice = ask!(skin, "Do you want to drink something ?", ('n') {
    ('w', "I'd like some **w**ater, please.") => {
        mad_print_inline!(skin, "*Wait a minute, please, I'll fetch some.*\n");
        Some("water")
    }
    ('b', "Could I get a **b**eer glass ?") => {
        mad_print_inline!(skin, "We have no glass, so here's a *bottle*.\n");
        Some("beer")
    }
    ('n', "*No*, thank you.") => {
        None
    }
});
dbg!(choice);

ask example

皮肤文件

MadSkin 可以使用 serde 反序列化。

例如,Hjson 中的此类皮肤可以是

bold: "#fb0 bold"
italic: dim italic
strikeout: crossedout red
bullet: ○ yellow bold
paragraph: gray(20)
code_block: gray(2) gray(15) center
headers: [
    yellow bold center
    yellow underlined
    yellow
]
quote: > red
horizontal-rule: "~ #00cafe"
table: "#540 center"
scrollbar: "#fb0 gray(11) |"

执行 cargo run --example skin-file 以获取示例和说明。

入门建议

  • 首先阅读示例(在 /examples 中):它们涵盖了几乎整个 API,包括模板、如何使用备用屏幕或滚动页面等。许多示例打印了大量的相关文档。
  • “render-input-markdown”示例允许你在文本区域中输入一些Markdown,并在下面查看渲染效果。
  • 请注意,某些颜色在所有终端上可能无法显示。您应用程序的默认颜色集不应包括任意的RGB颜色。
  • Termimad的事件/事件源部分目前针对少量应用程序进行了优化。如果您使用它或想使用它,请告诉我,以便考虑您的需求!
  • 如果您想格式化一些CLI应用程序的输出,例如一些表格,请查看dysk,这是最简单可能的用法之一。
  • 如果缺少功能或您不知道如何使用某个部分,请在欧洲西部时间来我的聊天中ping我。

使用termimad的开源应用程序

  • broot是一个文件管理器,它使用termimad为其帮助屏幕、状态信息和事件管理提供支持。

  • lfs是一个显示文件系统的Linux实用程序。Termimad模板用于在表格中显示数据。

  • SafeCloset是一个秘密保险库。它的TUI大量使用Termimad,特别是输入。

  • Rhit是一个nginx日志分析器。Termimad模板用于在表格中显示数据。

  • bacon是一个后台Rust编译器。它使用Termimad进行显示和事件管理。

  • lapin是一个终端游戏。它使用Termimad进行显示和事件管理。

  • backdown是一个文件去重器。它使用Termimad在屏幕上打印并提问。

  • Humility是一个嵌入式系统的调试器。它使用Termimad通过humility doc子命令打印Markdown文档。

如果您是使用Termimad的另一个应用程序的作者,请告诉我。

Crossterm兼容性

Crossterm是一个0.x库,这意味着它的API尚未冻结。因此,有时它会发生变化,因此基于Crossterm的库不能总是使用其最新版本。

Termimad重新导出Crossterm 0.27.x,因此您不必自己声明导入。您可以像这样使用crossterm:termimad::crossterm

依赖关系

~6–16MB
~212K SLoC