当前位置: 首页 > news >正文

【typst-rs】Typst CLI Eval 命令实现解析

这是一个Rust语言中的Typst文档处理命令解析模块,用于在Typst文档上下文中执行表达式求值。

主要功能

这个eval函数用于执行Typst文档的查询命令,主要功能是:

  1. 编译Typst文档(支持分页PDF或HTML格式)
  2. 在文档上下文中执行一个表达式
  3. 输出表达式的计算结果

完整代码

usecomemo::Track;useecow::eco_format;usetypst::diag::{HintedStrResult,SourceResult,Warned};usetypst::foundations::{Context,Output,Scope,StyleChain,Value};usetypst::syntax::{Span,SyntaxMode};usetypst::{World,engine::Sink,introspection::Introspector};usetypst_eval::eval_string;usetypst_html::HtmlDocument;usetypst_layout::PagedDocument;usecrate::args::{EvalCommand,Target};usecrate::compile::print_diagnostics;usecrate::set_failed;usecrate::world::SystemWorld;/// Execute a query command.pubfneval(command:&'staticEvalCommand)->HintedStrResult<()>{letmutworld=SystemWorld::new(command.r#in.as_ref(),&command.world,&command.process)?;// Reset everything and ensure that the main file is present.world.reset();world.source(world.main()).map_err(|err|err.to_string())?;// Compile the main file and get the introspector.letWarned{output,mutwarnings}=matchcommand.target{Target::Paged=>typst::compile::<PagedDocument>(&world).map(|result|result.map(|output|Box::new(output)asBox<dynOutput>)),Target::Html=>typst::compile::<HtmlDocument>(&world).map(|result|result.map(|output|Box::new(output)asBox<dynOutput>)),};matchoutput{// Retrieve and print evaluation results.Ok(document)=>{letmutsink=Sink::new();leteval_result=evaluate_expression(command.expression.clone(),&mutsink,&world,document.introspector(),);leterrors=match&eval_result{Err(errors)=>errors.as_slice(),Ok(value)=>{letserialized=crate::serialize(value,command.format,command.pretty)?;println!("{serialized}");&[]}};// Collect additional warnings from evaluating the expression.warnings.extend(sink.warnings());print_diagnostics(&world,errors,&warnings,command.process.diagnostic_format,).map_err(|err|eco_format!("failed to print diagnostics ({err})"))?;}// Print diagnostics.Err(errors)=>{set_failed();print_diagnostics(&world,&errors,&warnings,command.process.diagnostic_format,).map_err(|err|eco_format!("failed to print diagnostics ({err})"))?;}}Ok(())}/// Evaluates the expression with code syntax mode and no scope.fnevaluate_expression(expression:String,sink:&mutSink,world:&dynWorld,introspector:&dynIntrospector,)->SourceResult<Value>{eval_string(&typst::ROUTINES,world.track(),sink.track_mut(),introspector.track(),Context::new(None,Some(StyleChain::new(&world.library().styles))).track(),&expression,Span::detached(),SyntaxMode::Code,Scope::default(),)}

代码结构解析

1. 初始化世界环境

letmutworld=SystemWorld::new(command.r#in.as_ref(),&command.world,&command.process)?;world.reset();world.source(world.main()).map_err(|err|err.to_string())?;
  • 创建SystemWorld实例,管理文件系统、字体等资源
  • 重置状态并确保主文件存在

2. 编译文档

matchcommand.target{Target::Paged=>typst::compile::<PagedDocument>(&world),Target::Html=>typst::compile::<HtmlDocument>(&world),}

根据目标类型编译为分页文档(PDF)或HTML文档

3. 执行表达式求值

leteval_result=evaluate_expression(command.expression.clone(),&mutsink,&world,document.introspector(),// 提供文档内省能力);

4. 核心求值函数 -evaluate_expression

fnevaluate_expression(...)->SourceResult<Value>{eval_string(&typst::ROUTINES,// Typst内置函数world.track(),// 文件追踪(用于增量编译)sink.track_mut(),// 警告收集器introspector.track(),// 文档内省(查询元素位置等)Context::new(...),// 样式上下文&expression,// 要执行的表达式Span::detached(),// 位置信息(分离状态)SyntaxMode::Code,// 代码语法模式Scope::default(),// 空作用域)}

5. 结果处理

  • 成功:序列化结果并打印(支持自定义格式和美化输出)
  • 失败:打印诊断信息(错误和警告)

关键依赖项说明

依赖用途
comemo::Track增量编译的追踪机制
typst::World抽象文件系统接口
typst::Introspector文档内省(查询元素位置、计数等)
typst_html::HtmlDocumentHTML文档输出
typst_layout::PagedDocument分页文档输出

典型使用场景

# 查询文档中的标题数量typstevaldocument.typ--expression'query(heading).len()'# 获取特定元素位置typstevaldocument.typ--expression'locate(here).position()'

设计特点

  1. 增量编译支持:通过Track特性实现
  2. 双目标输出:同时支持分页和HTML文档
  3. 表达式求值:可以在编译后的文档上下文中执行Typst代码
  4. 诊断友好:完整的错误和警告报告机制

总结

这个模块本质上是Typst CLI工具中eval子命令的实现,用于在Typst文档环境中执行脚本表达式。它允许用户在不修改原始文档的情况下,动态查询文档的各种属性和元素信息。

http://www.jsqmd.com/news/604419/

相关文章:

  • 摄影行业抖音AI客服推荐,精准承接本地摄影流量,解锁获客新商机
  • 2026年SRM软件选型指南:6大主流供应商深度横评与排行榜
  • IoT 智能设备云端架构全解析:从 App 到设备的全链路设计(AWS 实战)
  • 20254118 于欣灵 2025-2026-2 《Python程序设计》实验二报告
  • Java高频面试题:MyBatis如何实现动态数据源切换?
  • Ostrakon-VL自动化测试报告生成:扫描UI并对比需求文档
  • 铸造车间混砂机的传动装置设计【solidworks三维+cad图纸+毕业论文】
  • Windows下玩转Llama.cpp量化:从HF模型到GGUF格式的保姆级转换教程
  • 解放双手!这些PPT生成网站,轻松开启高效创作 - 品牌测评鉴赏家
  • 医美抖音AI客服推荐,低成本撬动本地医美获客增长
  • NFT系统开发:在数字荒原上播种「文明契约」
  • 开箱即用!Qwen3-VL-8B AI聊天系统一键启动,小白也能玩转
  • 嵌入式开发实战:如何用STM32实现串口控制LED灯(附完整代码)
  • Tsuru平台安全加固终极指南:10个关键步骤保护你的PaaS环境
  • 牙科(口腔科)小红书AI客服推荐,高净值流量精准转化
  • 莫比乌斯反演 学习笔记
  • LS-DYNA R11与R13安装包|专注爆炸冲击与瞬态动力学仿真
  • 如何使用HVM2实现高效并行数据处理:从基础到实战指南
  • AI博主实测|3款封神PPT工具,新手也能10分钟出质感大片 - 品牌测评鉴赏家
  • 永生代码刑责:数字灵魂崩溃致死案开庭
  • React on Rails 国际化(i18n)终极指南:如何快速实现多语言支持
  • 杀死Scrum Master:智能体接管敏捷全流程的灾难
  • 终极指南:如何用Instructor实现舞蹈动作的结构化解析与智能编舞建议
  • 易语言自动寻路算法源代码下载|脚本开发参考范例
  • 基于FPGA的信号处理算法,FFT法相差检测verilog实现 1.硬件平台:altera芯片...
  • STM32H7实战:用CubeMX动态切换主频(72M到16M)的保姆级避坑指南
  • nnUNet实战调优笔记:batch_size与patch_size参数调整策略详解
  • 前端开发连续面了一周,我现在强的可怕!
  • 7个终极技巧:用nbdev实现完美的测试覆盖率分析
  • 计算机考研408真题实战:CRC校验与模2除法的C语言实现