diff --git a/Cargo.toml b/Cargo.toml index 0e3d5dd9..134c6045 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,13 +40,24 @@ exclude = [ # The oldest version I've tested that should still build - note this is not an official MSRV! rust-version = "1.81.0" -[[bin]] -name = "btm" -path = "src/main.rs" +[lib] test = true doctest = true doc = true +[[bin]] +name = "btm" +path = "src/bin/main.rs" +doc = false + +[[bin]] +name = "schema" +path = "src/bin/schema.rs" +test = false +doctest = false +doc = false +required-features = ["generate_schema"] + # Compile dependencies with optimizations enabled, even in debug mode. [profile.dev.package."*"] opt-level = 3 diff --git a/scripts/schema/generate.sh b/scripts/schema/generate.sh index 656b51bb..c7b89b41 100755 --- a/scripts/schema/generate.sh +++ b/scripts/schema/generate.sh @@ -5,4 +5,4 @@ set -e cd "$(dirname "$0")"; cd ../.. -cargo run --features="generate_schema" -- --generate_schema > schema/nightly/bottom.json +cargo run --bin schema --features="generate_schema" -- $1 > schema/nightly/bottom.json diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 00000000..5b2f20ac --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,5 @@ +use bottom::start_bottom; + +fn main() -> anyhow::Result<()> { + start_bottom() +} diff --git a/src/bin/schema.rs b/src/bin/schema.rs new file mode 100644 index 00000000..d04fdd9f --- /dev/null +++ b/src/bin/schema.rs @@ -0,0 +1,73 @@ +#![cfg(feature = "generate_schema")] + +use bottom::{options::config, widgets}; +use clap::Parser; +use itertools::Itertools; +use strum::VariantArray; + +#[derive(Parser)] +struct SchemaOptions { + /// The version of the schema. + version: Option, +} + +fn generate_schema(schema_options: SchemaOptions) -> anyhow::Result<()> { + let mut schema = schemars::schema_for!(config::Config); + { + // TODO: Maybe make this case insensitive? See https://stackoverflow.com/a/68639341 + + let proc_columns = schema.definitions.get_mut("ProcColumn").unwrap(); + match proc_columns { + schemars::schema::Schema::Object(proc_columns) => { + let enums = proc_columns.enum_values.as_mut().unwrap(); + *enums = widgets::ProcColumn::VARIANTS + .iter() + .flat_map(|var| var.get_schema_names()) + .sorted() + .map(|v| serde_json::Value::String(v.to_string())) + .dedup() + .collect(); + } + _ => anyhow::bail!("missing proc columns definition"), + } + + let disk_columns = schema.definitions.get_mut("DiskColumn").unwrap(); + match disk_columns { + schemars::schema::Schema::Object(disk_columns) => { + let enums = disk_columns.enum_values.as_mut().unwrap(); + *enums = widgets::DiskColumn::VARIANTS + .iter() + .flat_map(|var| var.get_schema_names()) + .sorted() + .map(|v| serde_json::Value::String(v.to_string())) + .dedup() + .collect(); + } + _ => anyhow::bail!("missing disk columns definition"), + } + } + + let metadata = schema.schema.metadata.as_mut().unwrap(); + let version = schema_options.version.unwrap_or("nightly".to_string()); + metadata.id = Some(format!( + "https://github.com/ClementTsang/bottom/blob/main/schema/{version}/bottom.json" + )); + metadata.description = Some(format!( + "https://clementtsang.github.io/bottom/{}/configuration/config-file", + if version == "nightly" { + "nightly" + } else { + "stable" + } + )); + println!("{}", serde_json::to_string_pretty(&schema).unwrap()); + + Ok(()) +} + +fn main() -> anyhow::Result<()> { + let schema_options = SchemaOptions::parse(); + generate_schema(schema_options)?; + + Ok(()) +} diff --git a/src/data_collection/processes/windows.rs b/src/data_collection/processes/windows.rs index a597f264..175239aa 100644 --- a/src/data_collection/processes/windows.rs +++ b/src/data_collection/processes/windows.rs @@ -3,8 +3,7 @@ use std::time::Duration; use super::ProcessHarvest; -use crate::data_collection::error::CollectionResult; -use crate::data_collection::DataCollector; +use crate::data_collection::{error::CollectionResult, DataCollector}; // TODO: There's a lot of shared code with this and the unix impl. pub fn sysinfo_process_data( diff --git a/src/main.rs b/src/lib.rs similarity index 90% rename from src/main.rs rename to src/lib.rs index 55eba7e7..d110361a 100644 --- a/src/main.rs +++ b/src/lib.rs @@ -272,67 +272,13 @@ fn create_collection_thread( }) } -#[cfg(feature = "generate_schema")] -fn generate_schema() -> anyhow::Result<()> { - let mut schema = schemars::schema_for!(crate::options::config::Config); - { - use itertools::Itertools; - use strum::VariantArray; - - // TODO: Maybe make this case insensitive? See https://stackoverflow.com/a/68639341 - - let proc_columns = schema.definitions.get_mut("ProcColumn").unwrap(); - match proc_columns { - schemars::schema::Schema::Object(proc_columns) => { - let enums = proc_columns.enum_values.as_mut().unwrap(); - *enums = widgets::ProcColumn::VARIANTS - .iter() - .flat_map(|var| var.get_schema_names()) - .sorted() - .map(|v| serde_json::Value::String(v.to_string())) - .dedup() - .collect(); - } - _ => anyhow::bail!("missing proc columns definition"), - } - - let disk_columns = schema.definitions.get_mut("DiskColumn").unwrap(); - match disk_columns { - schemars::schema::Schema::Object(disk_columns) => { - let enums = disk_columns.enum_values.as_mut().unwrap(); - *enums = widgets::DiskColumn::VARIANTS - .iter() - .flat_map(|var| var.get_schema_names()) - .sorted() - .map(|v| serde_json::Value::String(v.to_string())) - .dedup() - .collect(); - } - _ => anyhow::bail!("missing disk columns definition"), - } - } - - 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()); - - Ok(()) -} - -fn main() -> anyhow::Result<()> { +/// Main code to call. +#[inline] +pub fn start_bottom() -> anyhow::Result<()> { // let _profiler = dhat::Profiler::new_heap(); let args = args::get_args(); - #[cfg(feature = "generate_schema")] - if args.other.generate_schema { - return generate_schema(); - } - #[cfg(feature = "logging")] { if let Err(err) = init_logger( diff --git a/src/options.rs b/src/options.rs index 1692d24a..8e365a4d 100644 --- a/src/options.rs +++ b/src/options.rs @@ -195,6 +195,7 @@ pub fn get_or_create_config(config_path: Option<&Path>) -> anyhow::Result Result<(App, BottomLayout, ColourPalette)> { @@ -1235,10 +1236,10 @@ mod test { #[cfg(target_os = "macos")] #[test] fn test_get_config_path_macos() { - use super::get_config_path; - use super::DEFAULT_CONFIG_FILE_LOCATION; use std::path::PathBuf; + use super::{get_config_path, DEFAULT_CONFIG_FILE_LOCATION}; + // Case three: no previous config, no XDG var. // SAFETY: this is the only test that does this unsafe { diff --git a/src/options/args.rs b/src/options/args.rs index e49cf16d..2cefebc1 100644 --- a/src/options/args.rs +++ b/src/options/args.rs @@ -566,10 +566,6 @@ 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`]. diff --git a/src/options/config.rs b/src/options/config.rs index 602408e8..2c105a77 100644 --- a/src/options/config.rs +++ b/src/options/config.rs @@ -18,6 +18,7 @@ use temperature::TempConfig; pub use self::ignore_list::IgnoreList; use self::{cpu::CpuConfig, layout::Row, process::ProcessesConfig}; +/// Overall config for `bottom`. #[derive(Clone, Debug, Default, Deserialize)] #[cfg_attr( feature = "generate_schema", @@ -65,9 +66,10 @@ mod test { #[test] #[cfg(feature = "default")] fn test_integration_valid_configs() { - use super::Config; use std::fs; + use super::Config; + for config_path in fs::read_dir("./tests/valid_configs").unwrap() { let config_path = config_path.unwrap(); let config_path_str = config_path.path().display().to_string(); diff --git a/src/options/config/disk.rs b/src/options/config/disk.rs index a8b9962e..d6c32a51 100644 --- a/src/options/config/disk.rs +++ b/src/options/config/disk.rs @@ -1,8 +1,7 @@ use serde::Deserialize; -use crate::options::DiskColumn; - use super::IgnoreList; +use crate::options::DiskColumn; /// Disk configuration. #[derive(Clone, Debug, Default, Deserialize)] diff --git a/src/options/config/style.rs b/src/options/config/style.rs index 525f6746..b2b87950 100644 --- a/src/options/config/style.rs +++ b/src/options/config/style.rs @@ -23,9 +23,8 @@ use tui::style::Style; use utils::{opt, set_colour, set_colour_list, set_style}; use widgets::WidgetStyle; -use crate::options::{args::BottomArgs, OptionError, OptionResult}; - use super::Config; +use crate::options::{args::BottomArgs, OptionError, OptionResult}; #[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] diff --git a/src/options/config/style/themes.rs b/src/options/config/style/themes.rs index eeb1b0e6..f7db6557 100644 --- a/src/options/config/style/themes.rs +++ b/src/options/config/style/themes.rs @@ -17,4 +17,5 @@ macro_rules! hex { }; } -pub(super) use {color, hex}; +pub(super) use color; +pub(super) use hex; diff --git a/src/options/config/style/themes/default.rs b/src/options/config/style/themes/default.rs index d1cc3e36..5e165b8c 100644 --- a/src/options/config/style/themes/default.rs +++ b/src/options/config/style/themes/default.rs @@ -1,8 +1,7 @@ use tui::style::{Color, Modifier, Style}; -use crate::options::config::style::ColourPalette; - use super::color; +use crate::options::config::style::ColourPalette; impl ColourPalette { pub(crate) fn default_palette() -> Self { diff --git a/src/options/config/style/themes/gruvbox.rs b/src/options/config/style/themes/gruvbox.rs index b619b05a..4ec6454b 100644 --- a/src/options/config/style/themes/gruvbox.rs +++ b/src/options/config/style/themes/gruvbox.rs @@ -1,8 +1,7 @@ use tui::style::{Color, Modifier}; -use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette}; - use super::{color, hex}; +use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette}; impl ColourPalette { pub(crate) fn gruvbox_palette() -> Self { diff --git a/src/options/config/style/themes/nord.rs b/src/options/config/style/themes/nord.rs index 2919c873..e445fd3b 100644 --- a/src/options/config/style/themes/nord.rs +++ b/src/options/config/style/themes/nord.rs @@ -1,8 +1,7 @@ use tui::style::{Color, Modifier}; -use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette}; - use super::{color, hex}; +use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette}; impl ColourPalette { pub(crate) fn nord_palette() -> Self { diff --git a/src/options/config/style/utils.rs b/src/options/config/style/utils.rs index eaded70f..f589e7a6 100644 --- a/src/options/config/style/utils.rs +++ b/src/options/config/style/utils.rs @@ -247,16 +247,18 @@ macro_rules! set_colour_list { }; } -pub(super) use {opt, set_colour, set_colour_list, set_style}; +pub(super) use opt; +pub(super) use set_colour; +pub(super) use set_colour_list; +pub(super) use set_style; #[cfg(test)] mod test { use tui::style::{Modifier, Style}; - use crate::options::config::style::{ColorStr, TextStyleConfig}; - use super::*; + use crate::options::config::style::{ColorStr, TextStyleConfig}; #[test] fn general_str_to_colour() { diff --git a/tests/integration/valid_config_tests.rs b/tests/integration/valid_config_tests.rs index 98450754..bbaab0de 100644 --- a/tests/integration/valid_config_tests.rs +++ b/tests/integration/valid_config_tests.rs @@ -1,7 +1,6 @@ //! Tests config files that have sometimes caused issues despite being valid. use std::{io::Read, thread, time::Duration}; - #[cfg(feature = "default")] use std::{io::Write, path::Path};