慣性聚合 高效追蹤和閱讀你感興趣的部落格、新聞、科技資訊
閱讀原文 在慣性聚合中打開

推薦訂閱源

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Кто решает судьбу вашего проекта? Разбираем заинтересованные стороны. BABOK #1 Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как Фалькон Тех меняет пространство к лучшему
Marcli: Markdown 介面
amcured · 2026-05-24 · via Все публикации подряд на Хабре

在 Rust 的 CLI 生態系中,正靜靜地爆發流行病。症狀:參考文檔文字,讓人想測試自己是否有色盲,錯誤訊息,平鋪直敘到可以塞在門下,以及文檔,其風格表達力甚至不如收據。但同時,任何現代終端模擬器都支援粗體字、斜體字、顏色和 Unicode 繪圖符號。終端 所能與其應有的功能之間的差距。 要顯示,並且,大多數 CLI 工具 允許 顯示,按規模來說與大峡谷相當,按深度來說 — 與無視用戶的馬里亞納海溝相當.

Marcli 這次斷裂被關閉了。它取用 CommonMark Markdown,回傳給終端機帶有樣式的 ANSI 輸出。您在寫 Markdown。您的使用者看到的是美觀排版好的文字。整個想法都在一句話裡,而且這剛好夠了。

Marcli terminal output

Marcli 終端輸出

它做了什麼

Marcli 解析 Markdown 通過 comrak — 那個驅動 GitHub 渲染的解析器 — 會遍歷 AST,為每個支援的元素產生 ANSI 逃脫序列。被包圍的代码塊中的語法高亮由 syntect 提供。 — 與 Sublime Text 相同的語法。沒有 Pygments 的調用,沒有在執行時加載,沒有任何配置儀式。只是直接運行 — 這個概念似乎讓其他生態系認為是激進的.

單次函數調用:

let output = marcli::render("# Hello\n\nSome **bold** text.", &Default::default());
println!("{}", output);

這是一個典型情況下的全部公開 API。函數 render 接受一個 Markdown 字符串和一個 RenderOptions 的結構,返回String 裝載了 ANSI 字串序列。沒有任何「建構者」模式需要透過鏈接呼叫十七次。沒有任何需要事先實現的 trait。沒有任何隱藏在依賴樹中的非同步執行時,等待著吞噬你的組件的機會。

支援的元素

Marcli 處理完整的 CommonMark 規範加上幾個擴充功能:

  • 標題 — h1 顯示為黃色粗體,h2 — 藍色粗體,h3 及以下 — 白色粗體。三個層級的視覺層次結構,沒有一行配置。

  • 行內格式化 — 粗體、斜體、劃線和行內代碼,每種都有自己樣式的 ANSI。

  • 標記列表 — 以三角形标记(▸)取代慣用的 ASCII 標點符號。雖是細節,但可讀性卻異常提升.

  • 編號列表 — 圈起的數字符號(①, ②, ③, …)最多到二十項。超過二十項後則使用括號中的數字。雖然目前沒有人抱怨,不過,如果理智正常,也沒人會編制超過二十項的列表.

  • 被圈起的程式碼塊 — 在由 Unicode 繪圖符號組成的框架中,帶有語言標題。當指定語言時,語法高亮會自動啟用.

  • 引言 — 左側帶有暗淡的垂直線條,在視覺上與周圍文本區分開,無需憤怒.

  • 表格 — 全套符號繪圖框架,列對齊正確(左對齊、右對齊、居中)。標題加粗顯示.

  • 任務清單 — 帶有複選框的標記(☑ / ☐)。

  • 主題分隔符 — 淺色水平線(使用繪圖符號)。

  • 連結 — 文本藍色加粗,後面URL使用淺色字體.

  • 圖片 — 替代文本帶URL在括號內,因為終端機,儘管我們盡了全力,仍然不是圖片查看程序.

這不是窮人的子集。這是任何理性的人希望在終端機中顯示的所有內容,沒有任何超出的部分。

自動亮語法,無需設定

包含語言標示的區塊碼會自動透過內建的syntect語法高亮顯示。Rust、Python、Elixir、JavaScript、Go、C、SQL、TOML、YAML、Markdown本身——只要syntect認識該語言,Marcli就會為其高亮顯示。若不認識,則區塊會以同樣的框架顯示為純粹的樣式化文本。沒有任何錯誤、警告或經驗值降級——只是沒有顏色的代碼。這種「不因未知輸入而失敗」的革命性概念,看起來行業正以地球變遷的速度朝其發展。

fn main() {
    let md = "```rust\nfn greet(name: &str) {\n    println!(\"Hello, {}!\", name);\n}\n```";
    let output = marcli::render(md, &Default::default());
    println!("{}", output);
}

關鍵字會被著上一種顏色,字串則會被著上另一種顏色,註解會被變淡並以斜體突出,函數名稱會在背景中突出顯示。從 TextMate-範圍(syntect)映射到 ANSI 序列的過程是內建的,並涵蓋了所有主要的標記類別:關鍵字、字串、數字、註解、運算符、名稱、儲存修飾詞、實體名稱、支援宏、常數、變數和差異標記。每個類別都有合理的預設值,而且每個都可以被重新設定。

可以完全關閉語法高亮:

let mut theme = marcli::Theme::default();
theme.syntax_highlight = false;
let opts = marcli::RenderOptions { theme, ..Default::default() };

透過 TOML 完整設定顏色主題

Marcli 的輸出視覺方面均由其結構控制Theme:標題顏色、清單標記、代碼塊邊框、表格符號、語法高亮代碼樣式、主題分隔線寬度、引文前綴——所有這些。預設值是合理的,但如果你需要企業色彩或高對比主題以提升無障礙性,你只需要覆蓋你感興趣的特定字段。其他的保持不變。Marcli 不是那種庫,它不需要你更改一個參數就要求你從頭重新構建整個配置,嘟囔著什麼「完整性」。

主題會從TOML檔案載入:

let theme = marcli::Theme::load(".marcli.toml").unwrap_or_default();
let opts = marcli::RenderOptions { theme, ..Default::default() };
let output = marcli::render(markdown, &opts);

部分TOML檔案僅覆寫指定欄位;其餘內容保持預設值。未知鍵值會被靜默忽略,因此主題能與未來版本保持兼容。

主題系統並非後期通過特性旗標強行附加的權宜之計,這是一種架構設計。渲染器不包含任何硬編碼的ANSI序列——每個樣式都從結構中讀取。Theme在渲染時。這意味著可以產生完全未經風格化輸出,將所有樣式置於空白行中,或根據特定終端的顯示能力調整輸出,僅修改必要的序列。設計如此明顯,令人驚訝為何還需要解釋。

支援 xterm.js 和網頁終端 CRLF

若您的 CLI 工具也能在網頁終端中運作(xterm.js,例如),換行符就有意義。Marcli 允許設定換行符序列:

let opts = marcli::RenderOptions {
    newline: "\r\n".into(),
    ..Default::default()
};
let output = marcli::render(markdown, &opts);

每一個內部換行符——在列表元素之間、代碼塊內部、段落之間——都使用配置的序列。沒有後處理的正則表達式。沒有「用\n替換」\r\n 和我們將會禱告》。在結構上正確 — 這種方法會引發一些開發者接近文化衝擊的狀態.

刪除 ANSI 以獲得純文本

有時候需要沒有顏色的結構化渲染 — 用於記錄、重定向到文件、用於那些被 escape 序列壓制的可訪問性工具。選項 escape_sequences 解決了這個問題:

let opts = marcli::RenderOptions {
    escape_sequences: false,
    ..Default::default()
};
let output = marcli::render(markdown, &opts);
// output содержит структурированный текст
// с маркерами и отступами, но без ANSI-кодов

Marcli 也將 strip_ansi 作為公共函數導出,如果需要清除任意文本中的逃逸序列:

let plain = marcli::strip_ansi(some_ansi_string);

依賴歷史

Marcli 依賴六個庫:comrak (Markdown 解析)、syntect (語法高亮)、serdetoml (主題序列化)、regex (移除 ANSI) 和once_cell (懶惰的靜態檔案)。所有預設情況下都關閉了可能的功能。沒有任何 tokio。沒有任何 hyper。沒有任何 tower。沒有任何 serde_json。沒有任何組合爆炸的 feature-旗標。沒有任何超出 serde 所需的過程式宏。

依賴樹設計上非常狹窄。CLI 工具,用於添加 Marcli 以渲染輸出。--help 或診斷錯誤,並非突然繼承 HTTP 客戶端和 TLS 堆疊。在 Rust 的世界裡,為了格式化日期添加一個 crate 有時會牽連上網絡堆疊的一半,這值得特別提及——或許還值得喝一杯香檳吧。

為何是 Marcli,而不是替代方案

Rust 的生態系統提供幾種針對終端機的樣式化輸出方法,每種方法都解決自己的問題。麻煩在於,它們大多數並不適用於你。

用於「著色」的套件(例如,coloredowo-colorsansi_term — 這是一系列筆刷。它們允許塗鴉獨立的行。它們不解析結構、不處理清單、不渲染表格、不高亮程式碼。如果你的內容已經是結構化的,所有格式化邏輯你都要自己寫。Marcli 將 非結構化的 Markdown 轉換成 完全結構化的終端輸出 完全不同的抽象層。比較它們——就像問,鐵錘和房子哪個更好一樣。

TUI-框架(例如,ratatuitui-rs — 這是完整的終端 UI 工具。它們控制佈局、小工具、事件循環、替代螢幕緩衝區。如果你正在開發互動應用程式 — 它們非常出色。如果你需要印製樣式化的說明並離開 — 這是針對文具按鈕的鎚子。Marcli — 一個像文具按鈕大小的工具。沒有任何對更大的聲稱,也幸好如此。

termimad — 最近的可替代方案。它也能在終端渲染 Markdown。但 termimad 使用自己的解析器(與 CommonMark 不兼容),擁有另一種(且更不透明)的主題化模型,並且不提供透過 syntect 的語法高亮。Marcli 使用 comrak 進行解析(CommonMark,與 GitHub 兼容),使用 syntect 進行語法高亮(Sublime Text 的語法),並且透過扁平的、可序列化的結構設定每個視覺參數。Theme。如果您重視符合規範和可配置性——選擇是明顯的.

mdcat — 一個獨立的命令行工具,而不是庫。您無法將其嵌入到您的二進制檔案中並調用render()。它要么作為外部進程啟動,要么需要用戶機上存在其二進制檔案。Marcli — 一個庫:添加到Cargo.toml,呼叫函數,獲取字串。無共同居住義務。

輕鬆的理由

每個用於 CLI 且需要與人溝通的 Rust 庫都會遇到同樣的問題:如何呈現結構化文本?答案幾乎總是三種之一:ⓐ 直接輸出裸文本並希望用戶能讀懂(一種近乎精神病的樂觀主義),ⓑ 手動編寫 ANSI 格式化,需要數十次調用format! 使用硬编码的 escape 字串序列(帶有自虐色彩的工匠精神),ⓒ 強迫框架體積大於應用程式本身(來自 node modules 的架構設計)。

Marcli 提供了一個方案 ⓓ: 使用 Markdown 格式來編寫訊息、參考文本、錯誤說明、變更日誌和診斷,這是一種您的團隊已經熟悉的格式,您的編輯器已經能夠高亮顯示,您的文件化流水線已經能夠渲染,通過單一調用函數,就能將其轉換為人們 希望閱讀的終端輸出。

價格 — 一個函數調用和六個傳遞性依賴。效益 — 你的 CLI 發布到世界上的每一個文本片段,都可以是粗體、斜體、語法高亮、標記、表格和引用,完全支援主題且無需手動處理 ANSI 結束序列.

你的終端值得更好的。println! Marcli — 一種讓他變得更好的方法。而如果他不值得 — 嗯,至少你的用戶值得.

連結

▸ 存儲庫: github.com/Oeditus/marcli-rust
▸ 文檔: docs.rs/marcli
▸ 套件: crates.io/crates/marcli