From 60956b6303ff0d0e0da0bb58d5ce2e4cfa57578c Mon Sep 17 00:00:00 2001
From: nobody <nobody+git-spam@afra-berlin.de>
Date: Tue, 20 Aug 2024 08:38:20 +0200
Subject: [PATCH] lib target; working doctests

also paves the way for further cleanups
---
 Cargo.toml         | 10 +++++++++-
 src/config_spec.rs |  9 ++++++++-
 src/hedgedoc.rs    |  4 +++-
 src/key_value.rs   |  4 +++-
 src/lib.rs         | 18 ++++++++++++++++++
 src/main.rs        | 30 ++++++++----------------------
 src/template.rs    |  2 +-
 7 files changed, 50 insertions(+), 27 deletions(-)
 create mode 100644 src/lib.rs

diff --git a/Cargo.toml b/Cargo.toml
index 5d32839..cfad095 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "Plenum-Bot"
+name = "plenum_bot"
 version = "0.1.0"
 edition = "2021"
 
@@ -21,3 +21,11 @@ serde = {version = "1.0.204", features = ["derive"]}
 serde_json = "1.0.122"
 colored = "2.1.0"
 nom = "7.1.3"
+
+[[bin]]
+name = "Plenum-Bot"
+path = "src/main.rs"
+
+[lib]
+name = "cccron_lib"
+path = "src/lib.rs"
diff --git a/src/config_spec.rs b/src/config_spec.rs
index 3365dd1..a4d838f 100644
--- a/src/config_spec.rs
+++ b/src/config_spec.rs
@@ -2,6 +2,7 @@
 //!
 //! Per module that wants config fields, declare a
 //! ```rust
+//! # use cccron_lib::config_spec::{CfgGroup, CfgField};
 //! pub const CONFIG: CfgGroup<'static> = CfgGroup {
 //!     name: "modname", // this will be the field name prefix in the KV store
 //!     description: "what this module is for",
@@ -17,7 +18,10 @@
 //! and then in the main module, glue them all together and use them to populate defaults etc.
 //!
 //! ```rust
+//! # use cccron_lib::config_spec::{self, CfgSpec};
+//! # use cccron_lib::key_value::KeyValueStore;
 //! # mod modname {
+//! #     use cccron_lib::config_spec::{CfgGroup, CfgField};
 //! #     pub const CONFIG: CfgGroup<'static> = CfgGroup {
 //! #         name: "modname", // this will be the field name prefix in the KV store
 //! #         description: "what this module is for",
@@ -35,12 +39,15 @@
 //!         // etc.
 //!     ],
 //! };
+//! # fn main() -> rusqlite::Result<()> {
 //! // open a config file somewhere (we use a dummy to not cause side-effects)
 //! let config = KeyValueStore::new_dummy()?;
 //! // always:
-//! CONFIG_SPEC.populate_defaults(&config);
+//! config_spec::populate_defaults(&CONFIG_SPEC, &config);
 //! // (and then defaults will be set:)
 //! assert_eq!( config.get("modname-user").unwrap(), "xyzzy" );
+//! # Ok(())
+//! # }
 //! ```
 //!
 //! ```ignore
diff --git a/src/hedgedoc.rs b/src/hedgedoc.rs
index edd8e77..a8c8f6d 100644
--- a/src/hedgedoc.rs
+++ b/src/hedgedoc.rs
@@ -115,6 +115,8 @@ pub fn summarize(pad_content: String) -> String {
 }
 
 /// For the config, make a new pad ID (by actually making a pad.)
-fn make_pad_id(_key: &str, config: &crate::KV, is_dry_run: bool) -> Result<String, Box<dyn Error>> {
+fn make_pad_id(
+    _key: &str, config: &crate::key_value::KeyValueStore, is_dry_run: bool,
+) -> Result<String, Box<dyn Error>> {
     HedgeDoc::new(&config.get("hedgedoc-server-url").unwrap(), is_dry_run).create_pad()
 }
diff --git a/src/key_value.rs b/src/key_value.rs
index 07c2171..f840432 100644
--- a/src/key_value.rs
+++ b/src/key_value.rs
@@ -6,6 +6,7 @@
 //! ```
 //!
 //! ```
+//! # use cccron_lib::key_value::KeyValueStore;
 //! # let cfg = KeyValueStore::new_dummy()?;
 //! // Ensure defaults exist. (Do this early, this function panics on error.)
 //! cfg.default( "foo", "bar" );
@@ -13,11 +14,12 @@
 //! // Normal use after that.
 //! let foo = cfg.get( "foo" ).unwrap();
 //! let baz = &cfg["baz"]; // shorthand that LEAKS the string and panics on error
-//! let asdf = cfg.get( "asdf" ).unwrap_or_default( "abc" );
+//! let asdf = cfg.get( "asdf" ).unwrap_or( "abc".to_string() );
 //! cfg.set( "fnord", "23" )?;
 //! cfg.delete( "foo" )?;
 //! // If any writes failed, this flag will be set and the data got logged to stderr.
 //! let all_ok = !cfg.has_errors();
+//! # Ok::<(),rusqlite::Error>(())
 //! ```
 
 use colored::Colorize;
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..4b27f86
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,18 @@
+pub mod config_spec;
+pub mod date;
+pub mod email;
+pub mod hedgedoc;
+pub mod key_value;
+pub mod mediawiki;
+pub mod template;
+
+use std::env;
+
+/// Checks environment variable `DRY_RUN` to see if any external operations
+/// should *actually* be done.
+///
+/// If `is_dry_run` returns `true`, just report what you *would* do, and
+/// don't actually e.g. send emails.
+pub fn is_dry_run() -> bool {
+    env::var("DRY_RUN").map(|v| !v.is_empty()).unwrap_or(false)
+}
diff --git a/src/main.rs b/src/main.rs
index 60c8846..ce1c9a4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -43,20 +43,15 @@ use std::error::Error;
 use std::fmt::Display;
 use std::io::IsTerminal;
 
-mod key_value;
-use key_value::KeyValueStore as KV;
-mod config_spec;
-use config_spec::{CfgField, CfgGroup, CfgSpec};
-mod template;
-pub mod variables_and_settings;
+use cccron_lib::config_spec::{self, CfgField, CfgGroup, CfgSpec};
+use cccron_lib::key_value::KeyValueStore as KV;
+mod variables_and_settings;
 
-mod email;
-use email::{Email, SimpleEmail};
-mod hedgedoc;
-use hedgedoc::HedgeDoc;
-mod mediawiki;
-use mediawiki::Mediawiki;
-mod date;
+use cccron_lib::date;
+use cccron_lib::email::{self, Email, SimpleEmail};
+use cccron_lib::hedgedoc::{self, HedgeDoc};
+use cccron_lib::is_dry_run;
+use cccron_lib::mediawiki::{self, Mediawiki};
 
 const FALLBACK_TEMPLATE: &str = variables_and_settings::FALLBACK_TEMPLATE;
 
@@ -113,15 +108,6 @@ const CONFIG_SPEC: CfgSpec<'static> = CfgSpec {
 
 /* ***** Runtime Configuration (Arguments & Environment Variables) ***** */
 
-/// Checks environment variable `DRY_RUN` to see if any external operations
-/// should *actually* be done.
-///
-/// If `is_dry_run` returns `true`, just report what you *would* do, and
-/// don't actually e.g. send emails.
-fn is_dry_run() -> bool {
-    env::var("DRY_RUN").map(|v| !v.is_empty()).unwrap_or(false)
-}
-
 /// Checks environment variable `VERBOSE` to see if status messages should be
 /// printed.
 ///
diff --git a/src/template.rs b/src/template.rs
index f6dfb1a..bf1d0c9 100644
--- a/src/template.rs
+++ b/src/template.rs
@@ -9,7 +9,7 @@ where
 }
 
 pub fn config_replacer<'a>(
-    config: &'a crate::KV, blacklist_substrings: &'a [&'a str],
+    config: &'a crate::key_value::KeyValueStore, blacklist_substrings: &'a [&'a str],
 ) -> impl Fn(&Captures) -> String + 'a {
     move |caps: &Captures| {
         let key = &caps[1];