feat: add way to automatically generate new json schemas (#1482)

This commit is contained in:
Clement Tsang 2024-06-16 19:28:24 -04:00 committed by GitHub
parent 982b7181a6
commit 7666a09162
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 789 additions and 357 deletions

42
Cargo.lock generated
View file

@ -181,6 +181,7 @@ dependencies = [
"ratatui",
"regex",
"rustix",
"schemars",
"serde",
"serde_json",
"starship-battery",
@ -515,6 +516,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]]
name = "dyn-clone"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]]
name = "either"
version = "1.11.0"
@ -1152,6 +1159,30 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schemars"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
dependencies = [
"dyn-clone",
"schemars_derive",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -1178,6 +1209,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_derive_internals"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.117"

View file

@ -15,11 +15,13 @@ build = "build.rs"
exclude = [
".cargo-husky/",
".github/",
".vscode/",
"assets/",
"desktop/",
"docs/",
"flamegraphs/",
"sample_configs/",
"schema",
"schema/",
"scripts/",
"wix/",
".all-contributorsrc",
@ -70,6 +72,7 @@ nvidia = ["nvml-wrapper"]
gpu = ["nvidia"]
zfs = []
logging = ["fern", "log", "time/local-offset"]
generate_schema = ["schemars", "serde_json"]
deploy = ["battery", "gpu", "zfs"]
default = ["deploy"]
@ -91,7 +94,9 @@ itertools = "0.13.0"
log = { version = "0.4.21", optional = true }
nvml-wrapper = { version = "0.10.0", optional = true, features = ["legacy-functions"] }
regex = "1.10.4"
schemars = { version = "0.8.21", optional = true }
serde = { version = "1.0.203", features = ["derive"] }
serde_json = { version = "1.0.117", optional = true }
starship-battery = { version = "0.8.3", optional = true }
sysinfo = "=0.30.12"
thiserror = "1.0.61"
@ -143,7 +148,6 @@ clap_complete_nushell = "4.5.1"
clap_complete_fig = "4.5.0"
clap_mangen = "0.2.20"
indoc = "2.0.5"
# schemars = "0.8.21"
[package.metadata.deb]
section = "utility"

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://github.com/ClementTsang/bottom/tree/main/schema/nightly/schema.json",
"$comment": "https://clementtsang.github.io/bottom/nightly/configuration/config-file",
"title": "Schema for bottom's configs (v1)",
"$id": "https://github.com/ClementTsang/bottom/blob/main/schema/v1.0/bottom.json",
"$comment": "https://clementtsang.github.io/bottom/0.9.6/configuration/config-file",
"title": "Schema for bottom's configs (v1.0)",
"type": "object",
"definitions": {
"row": {

View file

@ -283,6 +283,25 @@ fn main() -> anyhow::Result<()> {
let args = args::get_args();
#[cfg(feature = "generate_schema")]
{
if args.other.generate_schema {
let mut schema = schemars::schema_for!(crate::options::config::ConfigV1);
let metadata = schema.schema.metadata.as_mut().unwrap();
metadata.id = Some(
"https://github.com/ClementTsang/bottom/blob/main/schema/nightly/bottom.json"
.to_string(),
);
metadata.description = Some(
"https://clementtsang.github.io/bottom/nightly/configuration/config-file"
.to_string(),
);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
return Ok(());
}
}
#[cfg(feature = "logging")]
{
if let Err(err) = init_logger(

View file

@ -1105,7 +1105,7 @@ mod test {
// Skip battery since it's tricky to test depending on the platform/features
// we're testing with.
let skip = ["help", "version", "celsius", "battery"];
let skip = ["help", "version", "celsius", "battery", "generate_schema"];
for arg in app.get_arguments().collect::<Vec<_>>() {
let arg_name = arg

View file

@ -567,6 +567,10 @@ pub struct OtherArgs {
#[arg(short = 'V', long, action = ArgAction::Version, help = "Prints version information.")]
version: (),
#[cfg(feature = "generate_schema")]
#[arg(long, action = ArgAction::SetTrue)]
pub generate_schema: bool,
}
/// Returns a [`BottomArgs`].

View file

@ -3,6 +3,7 @@ use std::borrow::Cow;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct ColoursConfig {
pub table_header_color: Option<Cow<'static, str>>,
pub all_cpu_color: Option<Cow<'static, str>>,

View file

@ -16,6 +16,11 @@ use self::{cpu::CpuConfig, layout::Row, process::ProcessesConfig};
use super::ColoursConfig;
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(
feature = "generate_schema",
derive(schemars::JsonSchema),
schemars(title = "Schema for bottom's configs (nightly)")
)]
pub struct ConfigV1 {
pub(crate) flags: Option<FlagConfig>,
pub(crate) colors: Option<ColoursConfig>,
@ -29,6 +34,7 @@ pub struct ConfigV1 {
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub(crate) enum StringOrNum {
String(String),
Num(u64),
@ -47,6 +53,7 @@ impl From<u64> for StringOrNum {
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub(crate) struct FlagConfig {
pub(crate) hide_avg_cpu: Option<bool>,
pub(crate) dot_marker: Option<bool>,

View file

@ -3,6 +3,7 @@ use serde::Deserialize;
/// The default selection of the CPU widget. If the given selection is invalid,
/// we will fall back to all.
#[derive(Clone, Copy, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum CpuDefault {
#[default]
@ -13,6 +14,7 @@ pub enum CpuDefault {
/// Process column settings.
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct CpuConfig {
#[serde(default)]
pub default: CpuDefault,

View file

@ -4,6 +4,7 @@ use super::IgnoreList;
/// Disk configuration.
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct DiskConfig {
/// A filter over the disk names.
pub name_filter: Option<IgnoreList>,

View file

@ -6,6 +6,7 @@ fn default_as_true() -> bool {
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct IgnoreList {
#[serde(default = "default_as_true")]
// TODO: Deprecate and/or rename, current name sounds awful.

View file

@ -5,6 +5,7 @@ use crate::{app::layout_manager::*, error::Result};
/// Represents a row. This has a length of some sort (optional) and a vector
/// of children.
#[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[serde(rename = "row")]
pub struct Row {
pub ratio: Option<u32>,
@ -214,6 +215,7 @@ impl Row {
/// to have FinalWidgets as children, lest we get some amount of mutual
/// recursion between Row and Col.
#[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub enum RowChildren {
Widget(FinalWidget),
@ -225,6 +227,7 @@ pub enum RowChildren {
/// Represents a widget.
#[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct FinalWidget {
pub ratio: Option<u32>,
#[serde(rename = "type")]

View file

@ -4,6 +4,7 @@ use super::IgnoreList;
/// Network configuration.
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct NetworkConfig {
/// A filter over the network interface names.
pub interface_filter: Option<IgnoreList>,

View file

@ -4,6 +4,7 @@ use crate::widgets::ProcWidgetColumn;
/// Process configuration.
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct ProcessesConfig {
/// A list of process widget columns.
#[serde(default)]

View file

@ -4,6 +4,7 @@ use super::IgnoreList;
/// Temperature configuration.
#[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub struct TempConfig {
/// A filter over the sensor names.
pub sensor_filter: Option<IgnoreList>,

View file

@ -111,6 +111,7 @@ pub struct ProcTableConfig {
/// A hacky workaround for now.
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
pub enum ProcWidgetColumn {
PidOrCount,
ProcNameOrCommand,