From fac75837458e4f7be4f501e40331b8162d90a1f8 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 1 Nov 2024 21:02:27 +0100 Subject: [PATCH] Basic feature flag mechanism (#5350) --- crates/typst-cli/src/args.rs | 9 ++++++ crates/typst-cli/src/world.rs | 5 +++- crates/typst-library/src/lib.rs | 52 ++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/crates/typst-cli/src/args.rs b/crates/typst-cli/src/args.rs index a4ac4bd93..9437f848c 100644 --- a/crates/typst-cli/src/args.rs +++ b/crates/typst-cli/src/args.rs @@ -274,8 +274,17 @@ pub struct SharedArgs { /// defaults to number of CPUs. Setting it to 1 disables parallelism. #[clap(long, short)] pub jobs: Option, + + /// Enables in-development features that may be changed or removed at any + /// time. + #[arg(long = "feature", value_delimiter = ',')] + pub feature: Vec, } +/// An in-development feature that may be changed or removed at any time. +#[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum)] +pub enum Feature {} + /// Arguments related to where packages are stored in the system. #[derive(Debug, Clone, Args)] pub struct PackageStorageArgs { diff --git a/crates/typst-cli/src/world.rs b/crates/typst-cli/src/world.rs index f35975442..a04de2c05 100644 --- a/crates/typst-cli/src/world.rs +++ b/crates/typst-cli/src/world.rs @@ -112,7 +112,10 @@ impl SystemWorld { .map(|(k, v)| (k.as_str().into(), v.as_str().into_value())) .collect(); - Library::builder().with_inputs(inputs).build() + let features = + command.feature.iter().map(|&feature| match feature {}).collect(); + + Library::builder().with_inputs(inputs).with_features(features).build() }; let fonts = Fonts::searcher() diff --git a/crates/typst-library/src/lib.rs b/crates/typst-library/src/lib.rs index 34c2e5261..55cd11328 100644 --- a/crates/typst-library/src/lib.rs +++ b/crates/typst-library/src/lib.rs @@ -30,7 +30,7 @@ use std::ops::{Deref, Range}; use ecow::EcoString; use typst_syntax::package::PackageSpec; use typst_syntax::{FileId, Source, Span}; -use typst_utils::LazyHash; +use typst_utils::{LazyHash, SmallBitSet}; use crate::diag::FileResult; use crate::foundations::{Array, Bytes, Datetime, Dict, Module, Scope, Styles, Value}; @@ -161,9 +161,10 @@ pub struct Library { /// The default style properties (for page size, font selection, and /// everything else configurable via set and show rules). pub styles: Styles, - /// The standard library as a value. - /// Used to provide the `std` variable. + /// The standard library as a value. Used to provide the `std` variable. pub std: Value, + /// In-development features that were enabled. + pub features: Features, } impl Library { @@ -186,6 +187,7 @@ impl Default for Library { #[derive(Debug, Clone, Default)] pub struct LibraryBuilder { inputs: Option, + features: Features, } impl LibraryBuilder { @@ -195,16 +197,58 @@ impl LibraryBuilder { self } + /// Configure in-development features that should be enabled. + /// + /// No guarantees whatsover! + pub fn with_features(mut self, features: Features) -> Self { + self.features = features; + self + } + /// Consumes the builder and returns a `Library`. pub fn build(self) -> Library { let math = math::module(); let inputs = self.inputs.unwrap_or_default(); let global = global(math.clone(), inputs); let std = Value::Module(global.clone()); - Library { global, math, styles: Styles::new(), std } + Library { + global, + math, + styles: Styles::new(), + std, + features: self.features, + } } } +/// A selection of in-development features that should be enabled. +/// +/// Can be collected from an iterator of [`Feature`]s. +#[derive(Debug, Default, Clone, Hash)] +pub struct Features(SmallBitSet); + +impl Features { + /// Check whether the given feature is enabled. + pub fn is_enabled(&self, feature: Feature) -> bool { + self.0.contains(feature as usize) + } +} + +impl FromIterator for Features { + fn from_iter>(iter: T) -> Self { + let mut set = SmallBitSet::default(); + for feature in iter { + set.insert(feature as usize); + } + Self(set) + } +} + +/// An in-development feature that should be enabled. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +#[non_exhaustive] +pub enum Feature {} + /// Construct the module with global definitions. fn global(math: Module, inputs: Dict) -> Module { let mut global = Scope::deduplicating();