diff --git a/changelog.d/20231231_212945_GitHub_Actions_rs2md-utility-struct.ron b/changelog.d/20231231_212945_GitHub_Actions_rs2md-utility-struct.ron new file mode 100644 index 00000000..5da11969 --- /dev/null +++ b/changelog.d/20231231_212945_GitHub_Actions_rs2md-utility-struct.ron @@ -0,0 +1,15 @@ +( + references: {}, + changes: { + "Added": [ + "Rs2md", + "src/utilities.rs", + "tests/utilities.rs", + "tests/assets/gpl-3.0-inner.rs", + "tests/assets/gpl-3.0-outer.rs", + ], + "Changed": [ + "rs2md: outsource logic to dedicated struct", + ], + }, +) diff --git a/src/application.rs b/src/application.rs index 1ca8af92..3c8f5f71 100644 --- a/src/application.rs +++ b/src/application.rs @@ -85,25 +85,7 @@ pub enum Action { Ronlog(crate::Ronlog), /// Extract Markdown code from Rust documentation comments. - Rs2md { - /// Whether to extract Rust documentation comments starting with `///`. - #[arg(long = "inner")] - extract_inner: bool, - - /// Whether to extract Rust documentation comments starting with `//!`. - #[arg(long = "outer")] - extract_outer: bool, - - /// The Rust files to read from, defaulting to [`std::io::Stdin`], if - /// omitted. - #[arg(long = "input", short)] - input_file: Vec, - - /// The Markdown file to write to, defaulting to [`std::io::Stdout`], if - /// omitted. - #[arg(long = "output", short)] - output_file: Option, - }, + Rs2md(crate::Rs2md), /// Remove CRLFs from the given file. Uncrlf { @@ -122,23 +104,6 @@ pub enum Action { } impl Action { - fn rs2md(s: &str, extract_inner: bool, extract_outer: bool) -> String { - s.lines() - .map(str::trim_start) - .filter(|l| { - (extract_inner && l.starts_with("///")) - || (extract_outer && l.starts_with("//!")) - }) - .map(|l| { - if l.len() > 3 { - l.split_at(4).1.trim_end().to_string() + "\n" - } else { - "\n".to_string() - } - }) - .collect::() - } - /// Execute the selected action. /// /// # Errors @@ -196,15 +161,7 @@ impl Action { + "\", }, ], \"settings\" : [], }\n", )), Self::Ronlog(r) => r.main(), - Self::Rs2md { - extract_inner, - extract_outer, - input_file, - output_file, - } => (|s: String| -> String { - Self::rs2md(&s, *extract_inner, *extract_outer) - }) - .io(input_file, output_file), + Self::Rs2md(r) => r.main(), Self::Uncrlf { file_to_edit, input_file, diff --git a/src/lib.rs b/src/lib.rs index dc0e62c4..36c39db8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -450,6 +450,7 @@ mod macros; mod pattern; mod running; mod traits; +mod utilities; mod version; pub use crate::{ @@ -474,6 +475,7 @@ pub use crate::{ AppendAsLine, ColourMessage, ConvertBuffer, FromMd, FromRon, FromRst, FromXml, Prefer, ReadFile, ToMd, ToRon, ToRst, ToStderr, ToXml, }, + utilities::Rs2md, version::{Range as VersionRange, Version}, }; diff --git a/src/utilities.rs b/src/utilities.rs new file mode 100644 index 00000000..c1f66d49 --- /dev/null +++ b/src/utilities.rs @@ -0,0 +1,101 @@ +/*********************** GNU General Public License 3.0 ***********************\ +| | +| Copyright (C) 2023 Kevin Matthes | +| | +| This program is free software: you can redistribute it and/or modify | +| it under the terms of the GNU General Public License as published by | +| the Free Software Foundation, either version 3 of the License, or | +| (at your option) any later version. | +| | +| This program is distributed in the hope that it will be useful, | +| but WITHOUT ANY WARRANTY; without even the implied warranty of | +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | +| GNU General Public License for more details. | +| | +| You should have received a copy of the GNU General Public License | +| along with this program. If not, see . | +| | +\******************************************************************************/ + +use crate::PatternIOProcessor; +use std::path::PathBuf; +use sysexits::Result; + +/// Extract Markdown code from Rust documentation comments. +#[derive(clap::Parser, Clone)] +pub struct Rs2md { + /// Whether to extract Rust documentation comments starting with `///`. + #[arg(long = "inner")] + extract_inner: bool, + + /// Whether to extract Rust documentation comments starting with `//!`. + #[arg(long = "outer")] + extract_outer: bool, + + /// The Rust files to read from, defaulting to [`std::io::Stdin`], if + /// omitted. + #[arg(long = "input", short)] + input_file: Vec, + + /// The Markdown file to write to, defaulting to [`std::io::Stdout`], if + /// omitted. + #[arg(long = "output", short)] + output_file: Option, +} + +impl Rs2md { + /// Extract Markdown code from Rust documentation comments. + /// + /// # Errors + /// + /// See + /// + /// - [`PatternIOProcessor::io`] + pub fn main(&self) -> Result<()> { + (|s: String| { + s.lines() + .map(str::trim_start) + .filter(|l| { + (self.extract_inner && l.starts_with("///")) + || (self.extract_outer && l.starts_with("//!")) + }) + .map(|l| { + if l.len() > 3 { + l.split_at(4).1.trim_end().to_string() + "\n" + } else { + "\n".to_string() + } + }) + .collect::() + }) + .io(&self.input_file, &self.output_file) + } + + /// Create a new instance. + pub fn new( + input_file: Vec, + output_file: Option, + extract_inner: bool, + extract_outer: bool, + ) -> Self + where + PathBuf: From, + { + Self { + extract_inner, + extract_outer, + input_file: { + let mut i = Vec::new(); + + for file in input_file { + i.push(file.into()); + } + + i + }, + output_file: output_file.map(Into::into), + } + } +} + +/******************************************************************************/ diff --git a/tests/assets/gpl-3.0-inner.rs b/tests/assets/gpl-3.0-inner.rs new file mode 100644 index 00000000..99ad6503 --- /dev/null +++ b/tests/assets/gpl-3.0-inner.rs @@ -0,0 +1,14 @@ +/// Copyright (C) 2023 Kevin Matthes +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU General Public License as published by +/// the Free Software Foundation, either version 3 of the License, or +/// (at your option) any later version. +/// +/// This program is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU General Public License for more details. +/// +/// You should have received a copy of the GNU General Public License +/// along with this program. If not, see . diff --git a/tests/assets/gpl-3.0-outer.rs b/tests/assets/gpl-3.0-outer.rs new file mode 100644 index 00000000..455a722b --- /dev/null +++ b/tests/assets/gpl-3.0-outer.rs @@ -0,0 +1,14 @@ +//! Copyright (C) 2023 Kevin Matthes +//! +//! This program is free software: you can redistribute it and/or modify +//! it under the terms of the GNU General Public License as published by +//! the Free Software Foundation, either version 3 of the License, or +//! (at your option) any later version. +//! +//! This program is distributed in the hope that it will be useful, +//! but WITHOUT ANY WARRANTY; without even the implied warranty of +//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//! GNU General Public License for more details. +//! +//! You should have received a copy of the GNU General Public License +//! along with this program. If not, see . diff --git a/tests/utilities.rs b/tests/utilities.rs new file mode 100644 index 00000000..d11e6e7c --- /dev/null +++ b/tests/utilities.rs @@ -0,0 +1,156 @@ +/*********************** GNU General Public License 3.0 ***********************\ +| | +| Copyright (C) 2023 Kevin Matthes | +| | +| This program is free software: you can redistribute it and/or modify | +| it under the terms of the GNU General Public License as published by | +| the Free Software Foundation, either version 3 of the License, or | +| (at your option) any later version. | +| | +| This program is distributed in the hope that it will be useful, | +| but WITHOUT ANY WARRANTY; without even the implied warranty of | +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | +| GNU General Public License for more details. | +| | +| You should have received a copy of the GNU General Public License | +| along with this program. If not, see . | +| | +\******************************************************************************/ + +use aeruginous::{ReadFile, Rs2md}; +use std::fs::remove_file; + +macro_rules! make_test { + ( @rs2md @none $( $n:ident -> $i:expr , $o:expr ),+ ) => { + $( + #[test] + fn $n() { + assert!(Rs2md::new( + vec![ + "tests/assets/gpl-3.0-inner.rs", + "tests/assets/gpl-3.0-outer.rs" + ], + Some(concat!(stringify!($n), ".md")), + $i, + $o + ).main().is_ok()); + + assert!( + concat!(stringify!($n), ".md") + .read() + .unwrap() + .is_empty() + ); + + remove_file(concat!(stringify!($n), ".md")).unwrap(); + } + )+ + }; + + ( @rs2md @once $( $n:ident -> $i:expr , $o:expr ),+ ) => { + $( + #[test] + fn $n() { + assert!(Rs2md::new( + vec![ + "tests/assets/gpl-3.0-inner.rs", + "tests/assets/gpl-3.0-outer.rs" + ], + Some(concat!(stringify!($n), ".md")), + $i, + $o + ).main().is_ok()); + + assert_eq!( + concat!(stringify!($n), ".md").read().unwrap(), + "\ +Copyright (C) 2023 Kevin Matthes + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +" + ); + + remove_file(concat!(stringify!($n), ".md")).unwrap(); + } + )+ + }; + + ( @rs2md @twice $( $n:ident -> $i:expr , $o:expr ),+ ) => { + $( + #[test] + fn $n() { + assert!(Rs2md::new( + vec![ + "tests/assets/gpl-3.0-inner.rs", + "tests/assets/gpl-3.0-outer.rs" + ], + Some(concat!(stringify!($n), ".md")), + $i, + $o + ).main().is_ok()); + + assert_eq!( + concat!(stringify!($n), ".md").read().unwrap(), + "\ +Copyright (C) 2023 Kevin Matthes + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +Copyright (C) 2023 Kevin Matthes + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +" + ); + + remove_file(concat!(stringify!($n), ".md")).unwrap(); + } + )+ + }; +} + +make_test!(@rs2md @none + rs2md_neither_inner_nor_outer -> false, false +); + +make_test!(@rs2md @once + rs2md_only_inner -> true, false, + rs2md_only_outer -> false, true +); + +make_test!(@rs2md @twice + rs2md_both_inner_and_outer -> true, true +); + +/******************************************************************************/