From 22ba6825db3b82e0b0f83ef6052f17289893e385 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 18 Dec 2023 12:18:41 +0100 Subject: [PATCH] Key/Value data from CLI (#2894) --- crates/typst-cli/src/args.rs | 26 ++++++++++++++++++ crates/typst-cli/src/world.rs | 17 +++++++++--- crates/typst-docs/src/lib.rs | 2 +- crates/typst/src/foundations/mod.rs | 4 +-- crates/typst/src/foundations/sys.rs | 5 ++-- crates/typst/src/lib.rs | 41 ++++++++++++++++++++++------- docs/reference/groups.yml | 16 ++++++++--- tests/fuzz/src/compile.rs | 2 +- tests/src/benches.rs | 2 +- tests/src/tests.rs | 2 +- 10 files changed, 94 insertions(+), 23 deletions(-) diff --git a/crates/typst-cli/src/args.rs b/crates/typst-cli/src/args.rs index 075412cd2..8f0261f1d 100644 --- a/crates/typst-cli/src/args.rs +++ b/crates/typst-cli/src/args.rs @@ -1,6 +1,7 @@ use std::fmt::{self, Display, Formatter}; use std::path::PathBuf; +use clap::builder::ValueParser; use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum}; use semver::Version; @@ -116,6 +117,15 @@ pub struct SharedArgs { #[clap(long = "root", env = "TYPST_ROOT", value_name = "DIR")] pub root: Option, + /// Add a string key-value pair visible through `sys.inputs` + #[clap( + long = "input", + value_name = "key=value", + action = ArgAction::Append, + value_parser = ValueParser::new(parse_input_pair), + )] + pub inputs: Vec<(String, String)>, + /// Adds additional directories to search for fonts #[clap( long = "font-path", @@ -134,6 +144,22 @@ pub struct SharedArgs { pub diagnostic_format: DiagnosticFormat, } +/// Parses key/value pairs split by the first equal sign. +/// +/// This function will return an error if the argument contains no equals sign +/// or contains the key (before the equals sign) is empty. +fn parse_input_pair(raw: &str) -> Result<(String, String), String> { + let (key, val) = raw + .split_once('=') + .ok_or("input must be a key and a value separated by an equal sign")?; + let key = key.trim().to_owned(); + if key.is_empty() { + return Err("the key was missing or empty".to_owned()); + } + let val = val.trim().to_owned(); + Ok((key, val)) +} + /// Lists all discovered fonts in system and custom font paths #[derive(Debug, Clone, Parser)] pub struct FontsCommand { diff --git a/crates/typst-cli/src/world.rs b/crates/typst-cli/src/world.rs index 8f8a7e5c0..cd4244fcd 100644 --- a/crates/typst-cli/src/world.rs +++ b/crates/typst-cli/src/world.rs @@ -7,7 +7,7 @@ use chrono::{DateTime, Datelike, Local}; use comemo::Prehashed; use ecow::eco_format; use typst::diag::{FileError, FileResult, StrResult}; -use typst::foundations::{Bytes, Datetime}; +use typst::foundations::{Bytes, Datetime, Dict, IntoValue}; use typst::syntax::{FileId, Source, VirtualPath}; use typst::text::{Font, FontBook}; use typst::{Library, World}; @@ -68,14 +68,25 @@ impl SystemWorld { // Resolve the virtual path of the main file within the project root. let main_path = VirtualPath::within_root(&input, &root) - .ok_or("input file must be contained in project root")?; + .ok_or("source file must be contained in project root")?; + + let library = { + // Convert the input pairs to a dictionary. + let inputs: Dict = command + .inputs + .iter() + .map(|(k, v)| (k.as_str().into(), v.as_str().into_value())) + .collect(); + + Library::builder().with_inputs(inputs).build() + }; Ok(Self { workdir: std::env::current_dir().ok(), input, root, main: FileId::new(None, main_path), - library: Prehashed::new(Library::build()), + library: Prehashed::new(library), book: Prehashed::new(searcher.book), fonts: searcher.fonts, slots: RwLock::new(HashMap::new()), diff --git a/crates/typst-docs/src/lib.rs b/crates/typst-docs/src/lib.rs index 444dda32c..ad40b9879 100644 --- a/crates/typst-docs/src/lib.rs +++ b/crates/typst-docs/src/lib.rs @@ -55,7 +55,7 @@ static GROUPS: Lazy> = Lazy::new(|| { }); static LIBRARY: Lazy> = Lazy::new(|| { - let mut lib = Library::build(); + let mut lib = Library::default(); lib.styles .set(PageElem::set_width(Smart::Custom(Abs::pt(240.0).into()))); lib.styles.set(PageElem::set_height(Smart::Auto)); diff --git a/crates/typst/src/foundations/mod.rs b/crates/typst/src/foundations/mod.rs index 4ddc2162e..04380beef 100644 --- a/crates/typst/src/foundations/mod.rs +++ b/crates/typst/src/foundations/mod.rs @@ -83,7 +83,7 @@ use crate::syntax::Spanned; pub static FOUNDATIONS: Category; /// Hook up all `foundations` definitions. -pub(super) fn define(global: &mut Scope) { +pub(super) fn define(global: &mut Scope, inputs: Dict) { global.category(FOUNDATIONS); global.define_type::(); global.define_type::(); @@ -110,7 +110,7 @@ pub(super) fn define(global: &mut Scope) { global.define_func::(); global.define_func::