diff options
author | Matthias Beyer <matthias.beyer@ifm.com> | 2022-05-12 11:32:37 +0200 |
---|---|---|
committer | Matthias Beyer <matthias.beyer@ifm.com> | 2022-05-12 14:52:34 +0200 |
commit | 7943a469372878c53ad089cef908e47950906f4d (patch) | |
tree | aca4f4d4a33383dc0918c09ae58d64f9ddd5d609 | |
parent | 16338c0edf223126cca82513e01f4cbd64b6c240 (diff) |
Add CLI interface for printing plugin documentation
This patch adds a CLI interface for printing the plugin documentation
using the new infrastructure for self-describing configuration objects.
Signed-off-by: Matthias Beyer <matthias.beyer@ifm.com>
-rw-r--r-- | Cargo.lock | 11 | ||||
-rw-r--r-- | tedge/Cargo.toml | 1 | ||||
-rw-r--r-- | tedge/src/cli.rs | 7 | ||||
-rw-r--r-- | tedge/src/main.rs | 48 |
4 files changed, 64 insertions, 3 deletions
@@ -3437,6 +3437,7 @@ dependencies = [ "tedge_api", "tedge_core", "tedge_lib", + "term_size", "termcolor", "termimad", "tokio", @@ -3667,6 +3668,16 @@ dependencies = [ ] [[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] name = "termcolor" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/tedge/Cargo.toml b/tedge/Cargo.toml index d2585fc7..d00b13bc 100644 --- a/tedge/Cargo.toml +++ b/tedge/Cargo.toml @@ -19,6 +19,7 @@ nu-ansi-term = "0.45.1" pretty = { version = "0.11.3", features = ["termcolor"] } termcolor = "1.1.3" termimad = "0.20.1" +term_size = "0.3.2" tedge_api = { path = "../crates/core/tedge_api" } tedge_core = { path = "../crates/core/tedge_core" } diff --git a/tedge/src/cli.rs b/tedge/src/cli.rs index a8fd7235..b61308e6 100644 --- a/tedge/src/cli.rs +++ b/tedge/src/cli.rs @@ -30,4 +30,11 @@ pub(crate) enum CliCommand { /// Print the supported plugin kinds #[clap(name = "get-plugin-kinds")] GetPluginKinds, + + /// Print the documentation of the configuration of the available plugins + #[clap(name = "doc")] + Doc { + /// Print the doc only for this plugin + plugin_name: Option<String> + }, } diff --git a/tedge/src/main.rs b/tedge/src/main.rs index 95ec66b0..5bc0a41d 100644 --- a/tedge/src/main.rs +++ b/tedge/src/main.rs @@ -1,9 +1,11 @@ use std::collections::HashMap; use std::collections::HashSet; +use std::io::Write; use clap::Parser; use miette::IntoDiagnostic; +use pretty::Arena; use tedge_api::PluginBuilder; use tedge_core::TedgeApplication; use tedge_core::TedgeApplicationBuilder; @@ -22,7 +24,7 @@ mod logging; struct Registry { app_builder: TedgeApplicationBuilder, plugin_kinds: HashSet<String>, - doc_printers: HashMap<String, Box<dyn FnOnce()>>, + doc_printers: HashMap<String, Box<dyn FnOnce() -> Result<(), miette::Error>>>, } macro_rules! register_plugin { @@ -36,6 +38,29 @@ macro_rules! register_plugin { miette::bail!("Plugin kind '{}' was already registered, cannot register!", kind_name) } + let kind_name_str = kind_name.to_string(); + registry.doc_printers.insert(kind_name.to_string(), Box::new(move || { + let mut stdout = std::io::stdout(); + if let Some(config_desc) = <$pluginbuilder as PluginBuilder<tedge_core::PluginDirectory>>::kind_configuration() { + let terminal_width = term_size::dimensions().map(|(w, _)| w).unwrap_or(80); + let arena = Arena::new(); + + let rendered_doc = crate::config::as_terminal_doc(&config_desc, &arena); + + let mut output = String::new(); + rendered_doc.render_fmt(terminal_width, &mut output).into_diagnostic()?; + + writeln!(stdout, " ----- Documentation for {}", kind_name_str) + .into_diagnostic()?; + + writeln!(stdout, "{}", output).into_diagnostic()?; + } else { + writeln!(stdout, " Documentation for {} is unavailable", kind_name) + .into_diagnostic()?; + } + Ok(()) + })); + Registry { app_builder: registry.app_builder.with_plugin_builder($pbinstance)?, plugin_kinds: registry.plugin_kinds, @@ -68,7 +93,6 @@ async fn main() -> miette::Result<()> { }; info!("Building application"); - let registry = { cfg_table::cfg_table! { [not(feature = "mqtt")] => register_plugin!( @@ -138,7 +162,8 @@ async fn main() -> miette::Result<()> { match args.command { cli::CliCommand::Run { config } => { - let (cancel_sender, application) = registry.app_builder.with_config_from_path(config).await?; + let (cancel_sender, application) = + registry.app_builder.with_config_from_path(config).await?; info!("Application built"); debug!("Verifying the configuration"); @@ -165,6 +190,23 @@ async fn main() -> miette::Result<()> { } Ok(()) } + cli::CliCommand::Doc { plugin_name } => { + let mut registry = registry; + if let Some(plugin_name) = plugin_name { + let printer = registry + .doc_printers + .remove(&plugin_name) + .ok_or_else(|| miette::miette!("Plugin named '{}' not found", plugin_name))?; + + (printer)()?; + } else { + for printer in registry.doc_printers.into_values() { + printer()?; + } + } + + Ok(()) + } } } |