diff --git a/Cargo.lock b/Cargo.lock index 756e986..4e523b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -294,9 +294,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -318,9 +318,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -482,14 +482,15 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1510,18 +1511,62 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ - "windows-targets", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "windows-link" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] [[package]] name = "windows-sys" diff --git a/Cargo.toml b/Cargo.toml index 1bfeb51..5393c1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ sixel-rs = { version = "0.4.1", optional = true } merge-struct = "0.1.0" itertools = "0.14" once_cell = "1.19" -schemars = "0.8" +schemars = { version = "0.8", optional = true } serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" serde_json = "1.0" @@ -45,6 +45,7 @@ rstest = { version = "0.25", default-features = false } [features] default = [] sixel = ["sixel-rs"] +json-schema = ["dep:schemars"] [profile.dev] opt-level = 0 diff --git a/scripts/validate-config-file-schema.sh b/scripts/validate-config-file-schema.sh index b2bac4e..1c260cf 100755 --- a/scripts/validate-config-file-schema.sh +++ b/scripts/validate-config-file-schema.sh @@ -1,10 +1,12 @@ #!/bin/bash +set -euo pipefail + script_dir=$(dirname "$0") root_dir="${script_dir}/../" current_schema=$(mktemp) -cargo run -q -- --generate-config-file-schema >"$current_schema" +cargo run --features json-schema -q -- --generate-config-file-schema >"$current_schema" diff=$(diff --color=always -u "${root_dir}/config-file-schema.json" "$current_schema") if [ $? -ne 0 ]; then diff --git a/src/code/snippet.rs b/src/code/snippet.rs index a257cdf..ce8e69b 100644 --- a/src/code/snippet.rs +++ b/src/code/snippet.rs @@ -15,7 +15,6 @@ use crate::{ }, theme::{Alignment, CodeBlockStyle}, }; -use schemars::JsonSchema; use serde::Deserialize; use serde_with::DeserializeFromStr; use std::{cell::RefCell, convert::Infallible, fmt::Write, ops::Range, path::PathBuf, rc::Rc, str::FromStr}; @@ -440,7 +439,8 @@ impl Snippet { } /// The language of a code snippet. -#[derive(Clone, Debug, PartialEq, Eq, EnumIter, PartialOrd, Ord, DeserializeFromStr, JsonSchema)] +#[derive(Clone, Debug, PartialEq, Eq, EnumIter, PartialOrd, Ord, DeserializeFromStr)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] pub enum SnippetLanguage { Ada, Asp, diff --git a/src/commands/keyboard.rs b/src/commands/keyboard.rs index 0f9df7f..21205bb 100644 --- a/src/commands/keyboard.rs +++ b/src/commands/keyboard.rs @@ -1,7 +1,6 @@ use super::listener::{Command, CommandDiscriminants}; use crate::config::KeyBindingsConfig; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, poll, read}; -use schemars::JsonSchema; use serde_with::DeserializeFromStr; use std::{fmt, io, iter, mem, str::FromStr, time::Duration}; @@ -162,8 +161,9 @@ enum BindingMatch { None, } -#[derive(Clone, Debug, PartialEq, Eq, DeserializeFromStr, JsonSchema)] -pub struct KeyBinding(#[schemars(with = "String")] Vec); +#[derive(Clone, Debug, PartialEq, Eq, DeserializeFromStr)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +pub struct KeyBinding(#[cfg_attr(feature = "json-schema", schemars(with = "String"))] Vec); impl KeyBinding { fn match_events(&self, mut events: &[KeyEvent]) -> BindingMatch { diff --git a/src/config.rs b/src/config.rs index d9302f1..1d57e4a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,6 @@ use crate::{ }, }; use clap::ValueEnum; -use schemars::JsonSchema; use serde::Deserialize; use std::{ collections::{BTreeMap, HashMap}, @@ -16,7 +15,8 @@ use std::{ path::Path, }; -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct Config { /// The default configuration for the presentation. @@ -73,7 +73,8 @@ pub enum ConfigLoadError { Invalid(#[from] serde_yaml::Error), } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct DefaultsConfig { /// The theme to use by default in every presentation unless overridden. @@ -81,7 +82,7 @@ pub struct DefaultsConfig { /// Override the terminal font size when in windows or when using sixel. #[serde(default = "default_terminal_font_size")] - #[validate(range(min = 1))] + #[cfg_attr(feature = "json-schema", validate(range(min = 1)))] pub terminal_font_size: u8, /// The image protocol to use. @@ -132,7 +133,8 @@ impl Default for DefaultsConfig { } /// The configuration for lists when incremental lists are enabled. -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct IncrementalListsConfig { /// Whether to pause before a list begins. @@ -149,7 +151,8 @@ fn default_terminal_font_size() -> u8 { } /// The alignment to use when `defaults.max_columns` is set. -#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum MaxColumnsAlignment { /// Align the presentation to the left. @@ -164,7 +167,8 @@ pub enum MaxColumnsAlignment { } /// The alignment to use when `defaults.max_rows` is set. -#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum MaxRowsAlignment { /// Align the presentation to the top. @@ -178,7 +182,8 @@ pub enum MaxRowsAlignment { Bottom, } -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum ValidateOverflows { #[default] @@ -188,7 +193,8 @@ pub enum ValidateOverflows { WhenDeveloping, } -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct OptionsConfig { /// Whether slides are automatically terminated when a slide title is found. @@ -214,7 +220,8 @@ pub struct OptionsConfig { pub auto_render_languages: Vec, } -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct SnippetConfig { /// The properties for snippet execution. @@ -230,7 +237,8 @@ pub struct SnippetConfig { pub render: SnippetRenderConfig, } -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct SnippetExecConfig { /// Whether to enable snippet execution. @@ -241,7 +249,8 @@ pub struct SnippetExecConfig { pub custom: BTreeMap, } -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct SnippetExecReplaceConfig { /// Whether to enable snippet replace-executions, which automatically run code snippets without @@ -249,7 +258,8 @@ pub struct SnippetExecReplaceConfig { pub enable: bool, } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct SnippetRenderConfig { /// The number of threads to use when rendering. @@ -267,7 +277,8 @@ pub(crate) fn default_snippet_render_threads() -> usize { 2 } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct TypstConfig { /// The pixels per inch when rendering latex/typst formulas. @@ -285,7 +296,8 @@ pub(crate) fn default_typst_ppi() -> u32 { 300 } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct MermaidConfig { /// The scaling parameter to be used in the mermaid CLI. @@ -308,7 +320,8 @@ pub(crate) fn default_u16_max() -> u16 { } /// The snippet execution configuration for a specific programming language. -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] pub struct LanguageSnippetExecutionConfig { /// The filename to use for the snippet input file. pub filename: String, @@ -324,7 +337,8 @@ pub struct LanguageSnippetExecutionConfig { pub hidden_line_prefix: Option, } -#[derive(Clone, Debug, Default, Deserialize, ValueEnum, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize, ValueEnum)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(rename_all = "kebab-case")] pub enum ImageProtocol { /// Automatically detect the best image protocol to use. @@ -378,7 +392,8 @@ impl TryFrom<&ImageProtocol> for GraphicsMode { } } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct KeyBindingsConfig { /// The keys that cause the presentation to move forwards. @@ -465,7 +480,8 @@ impl Default for KeyBindingsConfig { } } -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct SpeakerNotesConfig { /// The address in which to listen for speaker note events. @@ -492,7 +508,8 @@ impl Default for SpeakerNotesConfig { } /// The export configuration. -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct ExportConfig { /// The dimensions to use for presentation exports. @@ -504,7 +521,8 @@ pub struct ExportConfig { } /// The policy for pauses when exporting. -#[derive(Clone, Debug, Default, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields, rename_all = "snake_case")] pub enum PauseExportPolicy { /// Whether to ignore pauses. @@ -516,7 +534,8 @@ pub enum PauseExportPolicy { } /// The dimensions to use for presentation exports. -#[derive(Clone, Debug, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] #[serde(deny_unknown_fields)] pub struct ExportDimensionsConfig { /// The number of rows. @@ -527,9 +546,9 @@ pub struct ExportDimensionsConfig { } // The slide transition configuration. -#[derive(Clone, Debug, Deserialize, JsonSchema)] -#[serde(deny_unknown_fields)] -#[serde(tag = "style")] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +#[serde(tag = "style", deny_unknown_fields)] pub struct SlideTransitionConfig { /// The amount of time to take to perform the transition. #[serde(default = "default_transition_duration_millis")] @@ -544,9 +563,9 @@ pub struct SlideTransitionConfig { } // The slide transition style configuration. -#[derive(Clone, Debug, Deserialize, JsonSchema)] -#[serde(deny_unknown_fields)] -#[serde(tag = "style", rename_all = "snake_case")] +#[derive(Clone, Debug, Deserialize)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +#[serde(tag = "style", rename_all = "snake_case", deny_unknown_fields)] pub enum SlideTransitionStyleConfig { /// Slide horizontally. SlideHorizontal, diff --git a/src/main.rs b/src/main.rs index 7f4a6b8..b5156fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,6 +80,7 @@ struct Cli { /// Generate a JSON schema for the configuration file. #[clap(long)] + #[cfg(feature = "json-schema")] generate_config_file_schema: bool, /// Use presentation mode. @@ -348,11 +349,13 @@ fn overflow_validation_enabled(mode: &PresentMode, config: &ValidateOverflows) - } fn run(cli: Cli) -> Result<(), Box> { + #[cfg(feature = "json-schema")] if cli.generate_config_file_schema { let schema = schemars::schema_for!(Config); serde_json::to_writer_pretty(io::stdout(), &schema).map_err(|e| format!("failed to write schema: {e}"))?; return Ok(()); - } else if cli.acknowledgements { + } + if cli.acknowledgements { let acknowledgements = include_bytes!("../bat/acknowledgements.txt"); println!("{}", String::from_utf8_lossy(acknowledgements)); return Ok(());