[bat-cli] docs | 控制器
链接:https://github.com/sharkdp/bat
前文传送:
- 【探索Linux命令行】从基础指令到高级管道操作的介绍与实践
- 【Linux命令行】从时间管理->文件查找压缩的指令详解
- 【Linux】1w详解如何实现一个简单的shell
docs:bat
bat
是一个**命令行文件查看器
**,能够美化代码和文本文件。
它的工作原理是接收原始输入,智能地检测编程语言,然后应用生动的语法高亮和其他视觉装饰(如行号或 Git 变更)。
最终,增强后的输出会*直接显示或通过分页器(如 less
)*输出,从而提供更好的查看体验。
可视化
章节
- 控制器
- 输入管理
- 输出处理
- 配置 (Config)
- 高亮资源
- 语法映射
- 行范围处理
- 打印器
第一章:控制器
欢迎来到 bat
🐻❄️
如果你想通过漂亮的语法高亮、行号等功能让你的代码和文本文件更加清晰,那么你来对地方了ovo。
在这第一章中,我们将介绍“控制器”,它是 bat
强大显示功能背后的核心大脑。
控制器解决了什么问题?
假设我们有一个纯文本文件,比如一个 Python 脚本,我们想在屏幕上显示它。不仅仅是原始文本,而是带有各种装饰效果:不同关键词的鲜艳颜色、清晰的行号,甚至可能还有版本控制中的变更标记。如何从一个简单的文本文件变成这样丰富、视觉上吸引人的输出呢?
这就是控制器的作用!它就像是整个显示操作的项目经理。我们告诉它想要显示哪些文件以及如何显示(我们的“配置”),然后控制器负责确保一切正确执行。
本章的目标是理解控制器如何协调这一过程,将一个简单的文件准备好,以便进行漂亮的显示。
控制器:我们的项目经理
控制器本身并不直接执行高亮或行号添加。相反,它协调所有其他专业化的组件。可以将其视为:
- 协调者:确保从读取文件到最终显示的每一步都按正确顺序进行。
- 指挥官:根据我们的设置告诉其他组件该做什么。
- 错误处理者:如果出现问题(例如文件无法找到),控制器会捕获错误。
使用控制器
虽然 bat
提供了一个用户友好的 PrettyPrinter
来处理常见任务,但直接理解 Controller
有助于掌握核心逻辑。让我们看一个基本示例,展示如何使用 bat
的 Controller
来显示一个简单的 Rust 文件。
以下是一个最小化的代码片段,灵感来自 bat
的示例,直接使用 Controller
将文件内容(这里是 examples/buffer.rs
本身)打印到一个字符串缓冲区:
use bat::{assets::HighlightingAssets, // 管理语法定义和主题config::Config, // 我们的显示偏好controller::Controller, // 协调者!output::OutputHandle, // 输出目标Input, // 表示输入文件
};fn main() {let mut buffer = String::new(); // 输出将存储在这里let config = Config {colored_output: true, // 是的,我们需要颜色!..Default::default()};let assets = HighlightingAssets::from_binary(); // 加载内置的高亮信息let controller = Controller::new(&config, &assets); // 创建控制器// 为当前文件创建输入let input = Input::from_file(file!());// 运行控制器处理并打印输入controller.run(vec![input.into()], // 提供输入文件Some(OutputHandle::FmtWrite(&mut buffer)), // 告诉它写入字符串缓冲区).unwrap();println!("{buffer}"); // 最终打印缓冲区中的结果
}
说明:
- 我们设置了一个名为
buffer
的String
,用于存储高亮后的输出。 - 我们创建了一个
Config
对象,其中包含所有偏好设置,比如是否需要彩色输出。..Default::default()
为其他设置填充默认值。 HighlightingAssets::from_binary()
加载所有内置的语法定义(例如如何高亮 Rust、Python 等)和颜色主题。- 然后,我们使用
Controller::new(&config, &assets)
创建控制器。我们提供偏好设置(config
)和高亮规则(assets
)。 - 我们定义要显示的内容为
Input
。这里,Input::from_file(file!())
表示我们要求bat
处理包含这段代码的 Rust 文件! - 最后,
controller.run(...)
是魔法发生的地方。我们给控制器提供input
(要处理的文件),并告诉它将输出写入buffer
通过OutputHandle
。
运行这段代码时,bat
会处理 examples/buffer.rs
文件,根据 Rust 规则和默认主题应用语法高亮,并将格式化后的输出存储在 buffer
中,然后打印到控制台。
控制器内部工作原理
让我们揭开控制器的面纱,看看调用 controller.run()
时发生了什么。控制器作为我们的项目经理,与多个专业团队协调完成任务。
以下是简化的步骤分解:
- 接收请求:我们(程序员)告诉控制器处理一组文件,并提供特定配置。
- 准备输入:对于每个文件,控制器要求输入管理团队读取其内容。该团队负责打开文件、从标准输入读取,甚至处理字节数组。
- 收集设置:控制器使用我们提供的
Config
(即配置)。Config
包含所有指令:“使用这个颜色主题”、“显示行号”、“换行长行”等。 - 加载高亮信息:控制器查询
HighlightingAssets
以找到正确的语法定义(例如,“这是一个 Rust 文件,这是它的关键词和结构”)和选择的颜色主题。 - 启动打印机:对于每个输入文件的每一行,控制器将原始行连同所有配置和高亮规则交给打印机团队。打印机是实际应用颜色、添加行号并格式化文本的艺术家。
- 定向输出:打印机的格式化输出随后发送到输出处理。这可能意味着直接写入终端,或通过分页程序(如
less
)以便于浏览大文件。 - 处理错误:如果任何团队遇到问题(例如文件不可读),控制器会捕获并报告。
以下是描述这一流程的序列图:
深入代码
让我们看看 bat
源代码中控制器的结构。
首先是 Controller
结构体本身(来自 src/controller.rs
):
// src/controller.rs
pub struct Controller<'a> {config: &'a Config<'a>,assets: &'a HighlightingAssets,// ... 其他字段(用于 lessopen 特性的预处理器)
}
说明:
config: &'a Config<'a>
:这是对配置对象的引用,包含用户的所有偏好设置。控制器需要这些指令来知道如何显示文件。assets: &'a HighlightingAssets
:这是对HighlightingAssets
的引用,包含所有语法定义和主题。这告诉控制器应用哪些高亮规则和颜色。
接下来是控制器的构造函数(new
)和主要的 run
方法:
// src/controller.rs
impl Controller<'_> {pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> {Controller {config,assets,// ... 初始化其他字段}}pub fn run(&self, inputs: Vec<Input>, output_handle: Option<OutputHandle<'_>>) -> Result<bool> {// ... 设置输出 ...let mut no_errors: bool = true;for (index, input) in inputs.into_iter().enumerate() {let result = if input.is_stdin() {// 处理标准输入self.print_input(input, &mut writer, io::stdin().lock(), identifier, is_first)} else {// 处理文件输入self.print_input(input, &mut writer, io::empty(), identifier, is_first)};if let Err(error) = result {// ... 错误处理 ...no_errors = false;}}Ok(no_errors)}fn print_input<R: BufRead>(&self,input: Input,writer: &mut OutputHandle,stdin: R,stdout_identifier: Option<&Identifier>,is_first: bool,) -> Result<()> {let mut opened_input = input.open(stdin, stdout_identifier)?;// ... 可能获取 git diff ...let mut printer: Box<dyn Printer> = /* ... 创建 InteractivePrinter 或 SimplePrinter ... */;self.print_file(&mut *printer,writer,&mut opened_input,!is_first,// ... line_changes ...)}// ... 其他辅助方法如 print_file, print_file_ranges ...
}
说明:
Controller::new
:这是创建控制器的方式。只需传递Config
和HighlightingAssets
。Controller::run
:这是启动处理的主要方法。- 它准备
output_type
,确定输出去向(例如直接到终端或通过分页程序)。这将在输出处理中进一步讨论。 - 然后遍历每个提供的
Input
文件或流。 - 对于每个输入,调用
self.print_input
。
- 它准备
Controller::print_input
:此方法处理单个输入的流程:- 使用输入管理组件
open
输入,使其内容可读。 - 创建一个
printer
(SimplePrinter
或InteractivePrinter
)。printer
是实际根据Config
和HighlightingAssets
对原始文本应用样式的组件。我们将在打印机章节深入探讨。 - 最后调用
self.print_file
,将逐行打印的实际工作委托给选定的printer
。
- 使用输入管理组件
这表明控制器确实是核心枢纽,将 Config
、HighlightingAssets
、输入管理、输出处理和打印机结合在一起完成任务。
结论
在本章中,我们了解到控制器是 bat
项目的核心协调者。
它像项目经理一样,接收我们的配置和文件列表,然后指导其他专业组件读取、处理、高亮并漂亮地显示代码。虽然它不直接执行细节工作,但其协调角色对 bat
的功能至关重要。
现在我们已经理解了控制器在显示流程中的协调作用,下一步是了解 bat
如何处理我们想要显示的文件。在下一章中,我们将深入探讨输入管理,学习 bat
如何高效读取文件和其他数据源。
下一章:输入管理