-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a new config command with four subcommands: - `get`: gets the given keys - `set`: sets the given key - `list`: displays the full config - `default`: displays the default config
- Loading branch information
Showing
7 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
use std::collections::BTreeMap; | ||
use std::io; | ||
use std::io::Write; | ||
|
||
use serde::Serialize; | ||
use termcolor::{Color, WriteColor}; | ||
use thiserror::Error; | ||
use typst_test_lib::config::Config; | ||
use typst_test_stdx::fmt::Separators; | ||
|
||
use super::Context; | ||
use crate::error::Failure; | ||
use crate::report::{Report, Verbosity}; | ||
use crate::ui; | ||
use crate::ui::{Indented, Ui}; | ||
|
||
pub mod default; | ||
pub mod get; | ||
pub mod list; | ||
pub mod set; | ||
|
||
#[derive(clap::Args, Debug, Clone)] | ||
#[group(id = "config-args")] | ||
pub struct Args { | ||
/// The sub command to run | ||
#[command(subcommand)] | ||
pub cmd: Command, | ||
} | ||
|
||
#[derive(clap::Subcommand, Debug, Clone)] | ||
pub enum Command { | ||
/// Get a single config value | ||
#[command()] | ||
Get(get::Args), | ||
|
||
/// Set a single config value | ||
#[command()] | ||
Set(set::Args), | ||
|
||
/// List the full config | ||
#[command()] | ||
List, | ||
|
||
/// Show the default config | ||
#[command()] | ||
Default(default::Args), | ||
} | ||
|
||
impl Command { | ||
pub fn run(&self, ctx: &mut Context) -> anyhow::Result<()> { | ||
match self { | ||
Command::Get(args) => get::run(ctx, args), | ||
Command::Set(args) => set::run(ctx, args), | ||
Command::List => list::run(ctx), | ||
Command::Default(args) => default::run(ctx, args), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
#[serde(untagged)] | ||
pub enum ConfigJson<'c> { | ||
Pretty { | ||
#[serde(flatten)] | ||
inner: BTreeMap<&'c str, &'c Option<String>>, | ||
}, | ||
Toml { | ||
#[serde(flatten)] | ||
inner: &'c Config, | ||
}, | ||
} | ||
|
||
impl Report for ConfigJson<'_> { | ||
fn report<W: WriteColor>(&self, mut writer: W, verbosity: Verbosity) -> anyhow::Result<()> { | ||
match self { | ||
ConfigJson::Pretty { inner } => { | ||
writeln!(writer, "Config")?; | ||
|
||
let writer = &mut Indented::new(writer, 2); | ||
let pad = Ord::min( | ||
inner | ||
.iter() | ||
.map(|(&k, _)| k.len()) | ||
.max() | ||
.unwrap_or(usize::MAX), | ||
50, | ||
); | ||
|
||
for (&k, &v) in inner { | ||
if verbosity <= Verbosity::Less && v.is_none() { | ||
continue; | ||
} | ||
|
||
ui::write_colored(writer, Color::Cyan, |w| write!(w, "{:<pad$}", k))?; | ||
write!(writer, " = ")?; | ||
if let Some(v) = v { | ||
ui::write_colored(writer, Color::Green, |w| writeln!(w, "{:?}", v))?; | ||
} else { | ||
ui::write_colored(writer, Color::Magenta, |w| writeln!(w, "null"))?; | ||
} | ||
} | ||
} | ||
ConfigJson::Toml { inner } => { | ||
let mut doc = toml_edit::DocumentMut::new(); | ||
inner.write_into(&mut doc)?; | ||
// NOTE: DocumentMut::fmt writes a newline by itself | ||
write!(&mut writer, "{doc}")?; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
#[derive(Debug, Error)] | ||
#[error("unknown config keys {0:?}")] | ||
pub struct UnknownConfigKeys(Vec<String>); | ||
|
||
impl Failure for UnknownConfigKeys { | ||
fn report(&self, ui: &Ui) -> io::Result<()> { | ||
ui.error_with(|w| { | ||
writeln!( | ||
w, | ||
"Unknown config keys: {}", | ||
Separators::comma_and().with(self.0.iter()) | ||
) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use typst_test_lib::config; | ||
|
||
use super::ConfigJson; | ||
use crate::cli::Context; | ||
|
||
#[derive(clap::Args, Debug, Clone)] | ||
#[group(id = "config-set-args")] | ||
pub struct Args { | ||
/// Whether to output the config as a manifest tool section | ||
#[arg(long, conflicts_with = "format")] | ||
toml: bool, | ||
} | ||
|
||
pub fn run(ctx: &mut Context, args: &Args) -> anyhow::Result<()> { | ||
let mut config = config::Config::default(); | ||
config.set_fallbacks(); | ||
|
||
ctx.reporter.report(&if args.toml { | ||
ConfigJson::Toml { inner: &config } | ||
} else { | ||
ConfigJson::Pretty { | ||
inner: config.pairs().collect(), | ||
} | ||
})?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use typst_test_lib::config::ConfigError; | ||
|
||
use super::{ConfigJson, UnknownConfigKeys}; | ||
use crate::cli::Context; | ||
use crate::error::OperationFailure; | ||
|
||
#[derive(clap::Args, Debug, Clone)] | ||
#[group(id = "config-get-args")] | ||
pub struct Args { | ||
/// The key to get the value for | ||
#[arg(num_args(1..), required = true)] | ||
keys: Vec<String>, | ||
} | ||
|
||
pub fn run(ctx: &mut Context, args: &Args) -> anyhow::Result<()> { | ||
let project = ctx.ensure_project()?; | ||
|
||
let config = project.config(); | ||
let kvs: Vec<_> = args | ||
.keys | ||
.iter() | ||
.map(|key| (key.as_str(), config.get(key))) | ||
.collect(); | ||
|
||
let mut errors = vec![]; | ||
let mut vals = vec![]; | ||
|
||
for (k, res) in kvs { | ||
match res { | ||
Ok(v) => vals.push((k, v)), | ||
Err(ConfigError::UnknownKey { .. }) => errors.push(k.to_owned()), | ||
Err(err) => anyhow::bail!(err), | ||
} | ||
} | ||
|
||
if !errors.is_empty() { | ||
anyhow::bail!(OperationFailure::from(UnknownConfigKeys(errors))); | ||
}; | ||
|
||
ctx.reporter.report(&ConfigJson::Pretty { | ||
inner: vals.into_iter().collect(), | ||
})?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use super::ConfigJson; | ||
use crate::cli::Context; | ||
|
||
pub fn run(ctx: &mut Context) -> anyhow::Result<()> { | ||
let project = ctx.ensure_project()?; | ||
|
||
ctx.reporter.report(&ConfigJson::Pretty { | ||
inner: project.config().pairs().collect(), | ||
})?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
use serde::Serialize; | ||
use termcolor::{Color, WriteColor}; | ||
|
||
use crate::cli::config::UnknownConfigKeys; | ||
use crate::cli::Context; | ||
use crate::error::OperationFailure; | ||
use crate::report::{Report, Verbosity}; | ||
use crate::ui; | ||
|
||
#[derive(clap::Args, Debug, Clone)] | ||
#[group(id = "config-set-args")] | ||
pub struct Args { | ||
/// The key to set | ||
#[arg()] | ||
key: String, | ||
|
||
/// The value to set the key to or nothing to unset it | ||
#[arg()] | ||
value: Option<String>, | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
pub struct SetReport<'c> { | ||
key: &'c str, | ||
old: Option<&'c str>, | ||
new: Option<&'c str>, | ||
} | ||
|
||
impl Report for SetReport<'_> { | ||
fn report<W: WriteColor>(&self, mut writer: W, _verbosity: Verbosity) -> anyhow::Result<()> { | ||
write!(writer, "Set ")?; | ||
ui::write_colored(&mut writer, Color::Cyan, |w| write!(w, "{}", self.key))?; | ||
write!(writer, " from ")?; | ||
if let Some(old) = self.old { | ||
ui::write_colored(&mut writer, Color::Green, |w| write!(w, "{:?}", old))?; | ||
} else { | ||
ui::write_colored(&mut writer, Color::Magenta, |w| write!(w, "null"))?; | ||
} | ||
write!(writer, " to ")?; | ||
if let Some(new) = self.new { | ||
ui::write_colored(&mut writer, Color::Green, |w| writeln!(w, "{:?}", new))?; | ||
} else { | ||
ui::write_colored(&mut writer, Color::Magenta, |w| writeln!(w, "null"))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
pub fn run(ctx: &mut Context, args: &Args) -> anyhow::Result<()> { | ||
let mut project = ctx.ensure_project()?; | ||
|
||
// TODO: validation | ||
let Ok(val) = project.config_mut().get_mut(&args.key) else { | ||
anyhow::bail!(OperationFailure::from(UnknownConfigKeys(vec![args | ||
.key | ||
.clone()]))); | ||
}; | ||
|
||
let mut old = args.value.clone(); | ||
std::mem::swap(val, &mut old); | ||
|
||
project.write_config()?; | ||
|
||
ctx.reporter.report(&SetReport { | ||
key: &args.key, | ||
old: old.as_deref(), | ||
new: args.value.as_deref(), | ||
})?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters