summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <matthias.beyer@ifm.com>2022-05-12 11:32:37 +0200
committerMatthias Beyer <matthias.beyer@ifm.com>2022-05-12 14:52:34 +0200
commit7943a469372878c53ad089cef908e47950906f4d (patch)
treeaca4f4d4a33383dc0918c09ae58d64f9ddd5d609
parent16338c0edf223126cca82513e01f4cbd64b6c240 (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.lock11
-rw-r--r--tedge/Cargo.toml1
-rw-r--r--tedge/src/cli.rs7
-rw-r--r--tedge/src/main.rs48
4 files changed, 64 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 36e0e83b..9379c13a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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(())
+ }
}
}