cargo_auto_lib/
public_api_mod.rs

1// public_api_mod.rs
2
3// region: auto_md_to_doc_comments include doc_comments/public_api_mod.md A //!
4//! public_api_mod gives more control over changes in the public api.
5//!
6//! The Public API of a library is a pain in the a...  
7//! Every time I modify something I have to think how it will affect the users of the library.  
8//! They could have tens or hundreds of places where they use the library. Breaking changes are terrible things.  
9//! The developers are not willing to change their code every time a library changes slightly.  
10//! Yes, there is the semver to show if the new library is API compatible. That helps a lot.  
11//! It is dreaded if the first version of a function does not return a Result<>.  
12//! Then later we will surely come to the point, that we need to return a Result<>. This is a terrible breaking change.  
13//! It is wise to return a Result always. Even when that is not needed right now. It will surely be needed in the future.  
14//! Another tactic is to make new functions with a different name and mark the old functions as Obsolete.
15//!
16//! This library is used by the automation_tasks_rs executable.  
17//! I want to have here the complete and exact definition of the public API.  
18//! Therefore I will not use reexports like `pub use` or `pub mod`.  
19//! This way I can always know easily if my public API has changed.  
20//! Just compare the `public_api_mod.rs` file in git diff.  
21//! Adding functions, structs, methods and enums is ok, it does not break the Public API.  
22//! But modifying existing functions, methods or enums will break the compatibility.  
23//!
24// endregion: auto_md_to_doc_comments include doc_comments/public_api_mod.md A //!
25
26// region: Public API constants
27// ANSI colors for Linux terminal
28// https://github.com/shiena/ansicolor/blob/master/README.md
29/// ANSI color
30pub const RED: &str = "\x1b[31m";
31/// ANSI color
32pub const GREEN: &str = "\x1b[32m";
33/// ANSI color
34pub const YELLOW: &str = "\x1b[33m";
35/// ANSI color
36pub const BLUE: &str = "\x1b[34m";
37/// ANSI color
38pub const RESET: &str = "\x1b[0m";
39// endregion: Public API constants
40
41// region: re-export entire dependencies
42pub use inquire;
43// endregion: re-export entire dependencies
44
45// region: Public API structs and methods
46
47/// Result type with fixed LibError using thiserror.  
48///
49/// It makes simpler to write returns from functions.  
50pub use crate::error_mod::{Error, Result};
51
52/// Similar to std::process::Output, but with i32 and Strings for easier work.
53pub use crate::auto_shell_mod::ShellOutput;
54
55// reexporting a struct needs to export the trait to also reexports all the methods
56
57/// Read data from Cargo.toml.  
58pub use crate::auto_cargo_toml_mod::CargoToml;
59
60// Just for making the struct methods obvious as public methods
61// I created a special trait for this struct
62// AFTERTHOUGHT: This makes me think if most the functions are methods,
63// then it is consistent how to make the public API definition.
64// There is a downside: the caller must bring the trait into scope. A little annoying.
65
66/// Trait with methods to read data from Cargo.toml.
67pub trait CargoTomlPublicApiMethods {
68    /// read Cargo.toml, for workspaces it is the Cargo.toml of the first member
69    fn read() -> Result<Self>
70    where
71        Self: Sized;
72    /// Cargo.toml package name
73    fn package_name(&self) -> String;
74    /// Cargo.toml package version
75    fn package_version(&self) -> String;
76    /// Cargo.toml package authors as string
77    fn package_authors_string(&self) -> String;
78    /// Cargo.toml package authors as string without emails
79    fn package_author_name(&self) -> String;
80    /// Cargo.toml package repository
81    fn package_repository(&self) -> Option<String>;
82    /// Cargo.toml package description
83    fn package_description(&self) -> Option<String>;
84    /// Cargo.toml package homepage
85    fn package_homepage(&self) -> String;
86    /// Cargo.toml workspace members
87    fn workspace_members(&self) -> Option<Vec<String>>;
88    /// github_owner from package.repository
89    fn github_owner(&self) -> Option<String>;
90    /// Cargo.toml package keywords
91    fn package_keywords(&self) -> Vec<String>;
92}
93
94/// Shell command builder with simple but limited sanitizer.
95///
96/// The limited sanitization will error if the value contains double quotes.
97/// Command injections attack is possible because the shell command mixes executable code and data in a single string.
98/// The attacker could format the "user input" data in a way that it transforms it into "executable code".
99/// A true sanitization is hard to do in software. It would mean to understand all the intricacies of bash syntax?!
100/// Another solution is to create a complex object model to have every command and data separated. Too complicated and developer unfriendly.
101/// Instead here we take that the developer is a trusted person and he knows how to create the template correctly,
102/// so that the placeholders are always de-facto delimited with double-quote inside the shell command.
103/// This avoids the problem of injection of any other symbol except double-quotes.
104/// The injection of double quote would finish the double-quote data and open the door tho write executable code.
105/// It would be very complicated to check if "escaped double quotes" are or not correct in the context of the template.
106/// So I don't allow them at all. This covers the vast majority of simple use cases.
107/// Placeholders are delimited with curly brackets.
108pub use crate::auto_shell_mod::ShellCommandLimitedDoubleQuotesSanitizer;
109
110/// Trait with methods for ShellCommandLimitedDoubleQuotesSanitizer.
111pub trait ShellCommandLimitedDoubleQuotesSanitizerTrait {
112    /// Template for the shell command with placeholders
113    ///
114    /// The limited sanitization will error if the value contains double quotes.
115    /// Placeholders are delimited with curly brackets.
116    /// The developer must be super careful to write the template correctly.
117    /// The placeholders must be inside a block delimited with double quotes.
118    /// In a way that only an injection of a double quote can cause problems.
119    /// There is no software check of the correctness of the template.
120    fn new(template: &str) -> Result<Self>
121    where
122        Self: Sized;
123    /// Replace placeholders with the value
124    ///
125    /// The limited sanitization will error if the value contains double quotes.
126    /// Enter the placeholder parameter delimited with curly brackets.
127    /// It would be very complicated to check if "escaped double quotes" are or not correct in the context of the template.
128    /// So I don't allow them at all. This covers the vast majority of simple use cases.
129    fn arg(&mut self, placeholder: &str, value: &str) -> Result<&mut Self>;
130
131    /// Just like arg(), but for secrets that must be not echoed on the screen
132    fn arg_secret(&mut self, placeholder: &str, value: &secrecy::SecretString) -> Result<&mut Self>;
133
134    /// Run the sanitized command with no additional checks
135    fn run(&self) -> Result<()>;
136}
137
138// endregion: Public API structs and methods
139
140// region: Public API functions
141/// Find 'from pos'.
142pub fn find_from(text: &str, from_pos: usize, find: &str) -> Result<usize> {
143    crate::utils_mod::find_from(text, from_pos, find)
144}
145
146/// Return the position of end of the delimited data before the delimiter.
147pub fn find_pos_end_data_before_delimiter(md_text_content: &str, pos: usize, delimiter: &str) -> Result<usize> {
148    crate::utils_mod::find_pos_end_data_before_delimiter(md_text_content, pos, delimiter)
149}
150
151/// Return the position of start of the delimited data after the delimiter.
152pub fn find_pos_start_data_after_delimiter(md_text_content: &str, pos: usize, delimiter: &str) -> Result<usize> {
153    crate::utils_mod::find_pos_start_data_after_delimiter(md_text_content, pos, delimiter)
154}
155
156/// The original `concat()` function does not have a delimiter.
157pub fn concatenate_vec_to_string(vec: &[String], delimiter: &str) -> String {
158    crate::utils_mod::concatenate_vec_to_string(vec, delimiter)
159}
160
161// region: auto_md_to_doc_comments include doc_comments/traverse_dir_with_exclude_dir.md A ///
162/// Traverse dir and its sub-dir, but avoid excluded dirs.
163///
164/// The find_file and the exclude dir strings must start with /.
165///
166/// ## Example
167///
168/// ```Rust ignore
169///
170/// let files = cargo_auto_lib::traverse_dir_with_exclude_dir(
171///     Path::new("/home/project/src"),
172///     "/*.rs",
173///     // avoid big folders
174///     &vec![
175///         "/.git".to_string(),
176///         "/target".to_string(),
177///         "/docs".to_string()
178///     ]
179/// ).expect("error");
180/// for rs_file_name in files.iter() {
181///     println!("{}", &rs_file_name);
182/// }
183/// ```
184///
185// endregion: auto_md_to_doc_comments include doc_comments/traverse_dir_with_exclude_dir.md A ///
186pub fn traverse_dir_with_exclude_dir(dir: &std::path::Path, find_file: &str, exclude_dirs: &[String]) -> Result<Vec<String>> {
187    crate::utils_mod::traverse_dir_with_exclude_dir(dir, find_file, exclude_dirs)
188}
189
190// region: auto_md_to_doc_comments include doc_comments/auto_cargo_toml_to_md.md A ///
191/// This function includes data from Cargo.toml to markdown files.  
192///
193/// ![auto_cargo_toml_to_md.png](https://github.com/automation-tasks-rs/cargo_auto_lib/blob/main/images/auto_cargo_toml_to_md.png?raw=true)
194///
195/// This is nice for avoiding out of sync data.  
196/// Run it on every build with `automation_tasks_rs` and [cargo auto](https://crates.io/crates/cargo-auto).  
197///   
198/// In the md file write these markers in invisible markdown comments.
199///
200/// ```markdown
201/// [//comment]: # (auto_cargo_toml_to_md start)
202///
203/// [//comment]: # (auto_cargo_toml_to_md end)
204///
205/// ```
206///
207/// In this instructions I changed `[//]` to `[//comment]` to not process these markers.
208///
209/// `auto_cargo_toml_to_md` deletes the old lines between the markers and includes the Cargo.toml data:  
210/// description, repository, version, utc_now, authors and creates badges for keywords and categories.
211///
212/// The words topics, keywords, hashtags and tags all mean the same concept.  
213/// In cargo.toml we have keywords.  
214/// In README.md I want to have badges with different color. And hashtags for SEO.  
215/// In GitHub they are topics.
216///
217/// Some keywords have defined colors, others are orange like Rust.  
218/// This can be expanded in the future.  
219///
220/// - Yellow: work-in-progress
221/// - Green: maintained, ready-for-use
222/// - Red: obsolete, archived
223///
224// endregion: auto_md_to_doc_comments include doc_comments/auto_cargo_toml_to_md.md A ///
225pub fn auto_cargo_toml_to_md() -> Result<()> {
226    crate::auto_cargo_toml_to_md_mod::auto_cargo_toml_to_md()
227}
228
229/// I want html pages to be correct microXML when I use them for single page application.
230///
231/// Before build or release this function will check for correctness.
232pub fn auto_check_micro_xml(path_to_html_pages: &str) -> Result<()> {
233    crate::auto_check_micro_xml_mod::auto_check_micro_xml(path_to_html_pages)
234}
235
236/// Deletes old js snippets when working with wasm-pack.  
237///
238/// The old folders for `js snippets` are not automatically deleted on building with `wasm-pack`.  
239/// This utils do that.  
240/// The function must be executed in the root project folder where is the Cargo.toml.  
241pub fn auto_delete_old_js_snippets() -> Result<()> {
242    crate::auto_delete_old_js_snippets_mod::auto_delete_old_js_snippets()
243}
244
245/// Print one or more sub_commands.
246pub fn completion_return_one_or_more_sub_commands(sub_commands: Vec<&str>, word_being_completed: &str) {
247    crate::auto_helper_functions_mod::completion_return_one_or_more_sub_commands(sub_commands, word_being_completed)
248}
249
250// region: auto_md_to_doc_comments include doc_comments/exit_if_not_run_in_rust_project_root_directory.md A ///
251/// Check if the code was run inside the Rust project root directory.  
252///
253/// There must be the `Cargo.toml` file and the directory `automation_tasks_rs`  
254/// If not, exit with error message.  
255///
256// endregion: auto_md_to_doc_comments include doc_comments/exit_if_not_run_in_rust_project_root_directory.md A ///
257pub fn exit_if_not_run_in_rust_project_root_directory() {
258    crate::auto_helper_functions_mod::exit_if_not_run_in_rust_project_root_directory()
259}
260
261/// Run one shell command with static str.
262///
263/// We trust the "developer" that he will not make "command injection" in his own code.
264/// The problem that must be sanitized is always "user input".
265/// Exit task execution if the command has Exit Status != 0.
266pub fn run_shell_command_static(shell_command: &'static str) -> Result<()> {
267    crate::auto_shell_mod::run_shell_command_static(shell_command)
268}
269
270/// Run one shell command.
271///
272/// Exit task execution if the command has Exit Status != 0.
273/// TODO: vulnerable to command injection
274pub fn run_shell_command(shell_command: &str) -> Result<()> {
275    crate::auto_shell_mod::run_shell_command(shell_command)
276}
277
278// region: auto_md_to_doc_comments include doc_comments/auto_lines_of_code.md A ///
279/// This function inserts shield badges with lines_of_code into README.rs.  
280///
281/// ![auto_lines_of_code.png](https://github.com/automation-tasks-rs/cargo_auto_lib/blob/main/images/auto_lines_of_code.png?raw=true)
282///
283/// The parameter Link will be used for shield badge. If empty_string, the git remote repository will be used.  
284/// Lines of code are not a "perfect" measurement of anything.  
285/// Anybody can write a very big number of lines of useless code and comments.  
286/// But for 95% of the cases they are good enough.  
287/// Most of the developers use some "standard" coding practices and that is quantifiable and comparable.  
288///
289/// The `src_code_lines` is the most important count.  
290/// That is actual code written for that project without doc comments, comments, unit tests, integration tests and examples.  
291/// Sometimes is great to see a big number here. It means there was a lot of work invested. But other times we want to see a small number. It
292/// means the developer understands the problem very well and don't try to solve anything outside that scope.  
293/// The `src_doc_comment_lines` counts doc comments. They will eventually become docs. The count of lines shows how many documentation is written.  
294/// The `src_comment_lines` counts code comments. Code comments are important to understand the code. The count of lines shows how understandable is the code.  
295/// The `tests_lines` counts lines in tests and shows how good is the code tested. Here are the unit tests and integration test combined.  
296/// The `examples_lines` counts lines in examples and shows how good is explained how to use the code.  
297///
298///
299/// ## Folder and file structure
300///
301/// The folder structure of a single Rust project is simple.  
302/// The project starts in the folder that contains `Cargo.toml`.  
303/// The `src/` folder contains all the rust `*.rs` files.  
304/// The `tests/` folder contains integration tests.  
305/// The `examples/` folder contains examples.  
306/// Some rs files can be excluded from the count adding this line near the start of the file: // exclude from auto_lines_of_code
307/// Inside a rs file the doc comment line start with `///` or `//!`.  
308/// The normal comments start with `//` or `/!`.  
309/// I will ignore the block comments. They are usually NOT used for comments, but to temporarily disable a piece of code. So I count this as code and not comments.  
310/// The `src/*.rs` file can contain unit tests that start with `#[cfg(test)]`. I assume that these are always at the end of the file.  
311/// There should not be any normal code after `#[cfg(test)]`, only tests.  
312/// All other files: `md`, `toml`, `html`, `js`, ... are not counted.  
313///
314/// ## Include into README.md
315///
316/// If the README.md file contains these markers (don't copy the numbers 1 and 2):  
317///
318/// ```md
319/// [//comment]: # (auto_lines_of_code start)
320///
321/// [//comment]: # (auto_lines_of_code end)
322/// ```
323///
324/// In this instructions I changed `[//]` to `[//comment]` to not process these markers.
325///
326/// The function will include the shield badges code between them.  
327/// It will erase the previous content.  
328/// Use git diff to see the change.  
329///
330// endregion: auto_md_to_doc_comments include doc_comments/auto_lines_of_code.md A ///
331pub fn auto_lines_of_code(link: &str) -> Result<()> {
332    crate::auto_lines_of_code_mod::auto_lines_of_code(link)
333}
334
335// region: auto_md_to_doc_comments include doc_comments/auto_md_to_doc_comments.md A ///
336/// Finds rs files with markers and include segments from md files as doc comments.  
337///
338/// ![auto_md_to_doc_comments.png](https://github.com/automation-tasks-rs/cargo_auto_lib/blob/main/images/auto_md_to_doc_comments.png?raw=true)
339///
340/// From this doc comments `cargo doc` will generated the documentation and auto-completion.  
341/// We don't want to manually copy this segments. We want them to be automatically in sync.  
342/// We will just run this function before every `cargo doc` with an automation task.  
343/// The `auto_md_to_doc_comments` function must be executed in the project root folder where is the Cargo.toml file.  
344/// First it searches all the rs files in src, tests and examples folders.  
345/// If they contain the markers, than finds the md file and the named segment and include it as doc comments into the rs file.  
346/// The markers are always in pairs: start and end. So exactly the content in between is changed.  
347/// The markers are always comments, so they don't change the code.  
348/// It works only for files with LF line delimiter. No CR and no CRLF.  
349///
350/// ## markers
351///
352/// In the rs file write these markers:  
353///
354/// ```code
355/// //comment region: auto_md_to_doc_comments include README.md A ///
356/// //comment endregion: auto_md_to_doc_comments include README.md A ///
357/// ```
358///
359/// In your rust code, change the word `comment` with double slash `//`.  
360/// In the md file put markers to mark the segment:  
361///
362/// ```markdown
363/// [//comment]: # (auto_md_to_doc_comments segment start A)  
364/// [//comment]: # (auto_md_to_doc_comments segment end A)  
365/// ```
366///
367/// In this instructions I changed `[//]` to `[//comment]` to not process these markers.
368///
369/// The marker must be exclusively in one line. No other text in the same line.  
370/// auto_md_to_doc_comments will delete the old lines between the markers.  
371/// It will find the md file and read the content between the markers.  
372/// Before each line it will add the doc comment symbol as is defined in the marker.  
373/// Finally it will include the new lines as doc comments in the rs file.
374///
375// endregion: auto_md_to_doc_comments include doc_comments/auto_md_to_doc_comments.md A ///
376pub fn auto_md_to_doc_comments() -> Result<()> {
377    crate::auto_md_to_doc_comments_mod::auto_md_to_doc_comments()
378}
379
380/// Process plantuml in current directory.  
381///
382/// Finds markers (auto_plantuml start) and (auto_plantuml end) in md files.  
383/// If needed, calls the web service and saves the svg file.  
384/// Between markers adds the link to the svg file.  
385/// repo_url like <https://github.com/automation-tasks-rs/sey_currency_converter_pwa>
386/// So the image file link is from the repository and accessible everywhere.  
387pub fn auto_plantuml(repo_url: &str) -> Result<()> {
388    crate::auto_plantuml_mod::auto_plantuml(repo_url)
389}
390
391/// Process plantuml for all md files.
392///
393/// For test and examples I need to provide the path.
394pub fn auto_plantuml_for_path(path: &std::path::Path, repo_url: &str) -> Result<()> {
395    crate::auto_plantuml_mod::auto_plantuml_for_path(path, repo_url)
396}
397
398/// Hash text.
399pub fn hash_text(text: &str) -> String {
400    crate::auto_plantuml_mod::hash_text(text)
401}
402
403/// Increment the minor version in Cargo.toml file only if files are changed.
404pub fn auto_semver_increment_minor() -> Result<()> {
405    crate::auto_semver_mod::auto_semver_increment_minor()
406}
407
408/// Increment the minor version in Cargo.toml file even if files are not changed.
409pub fn auto_semver_increment_minor_forced() -> Result<()> {
410    crate::auto_semver_mod::auto_semver_increment_minor_forced()
411}
412
413/// Increment the patch version in Cargo.toml file only if files are changed.
414pub fn auto_semver_increment_patch() -> Result<()> {
415    crate::auto_semver_mod::auto_semver_increment_patch()
416}
417
418/// Increment the patch version in Cargo.toml file even if files are not changed.
419pub fn auto_semver_increment_patch_forced() -> Result<()> {
420    crate::auto_semver_mod::auto_semver_increment_patch_forced()
421}
422
423/// Increment the version in Cargo.toml.
424///
425/// If the major version is greater than 2000, it is a date version  
426/// else it is semver and increments the patch part.  
427pub fn auto_version_increment_semver_or_date() -> Result<()> {
428    crate::auto_semver_or_date_mod::auto_version_increment_semver_or_date()
429}
430
431/// Increment the version in Cargo.toml, forced.
432///
433/// If the major version is greater than 2000, it is a date version  
434/// else it is semver and increments the patch part.  
435/// Forced is used in workspaces to force all members to have the same date version.  
436pub fn auto_version_increment_semver_or_date_forced() -> Result<()> {
437    crate::auto_semver_or_date_mod::auto_version_increment_semver_or_date_forced()
438}
439
440// region: auto_md_to_doc_comments include doc_comments/auto_version_from_date.md A ///
441/// New version from date is written to Cargo.toml and service_worker.js.
442///
443/// In Cargo.toml writes the version as the date `yyyy.mmdd.HHMM` ex. `2019.1221.2359`.  
444/// For non-library projects, the semver specification is not really useful.  
445/// Having the version as the date is just fine for executables and much more human readable.  
446///
447/// ### service_worker.js
448///
449/// Inside the PWA service worker javascript file is also needed to change the version.  
450/// The program searches for `service_worker.js` and modify the version.  
451///
452/// ### no need to change version if no files changed
453///
454/// If src/*.rs or Cargo.toml files are not changed from last compile, than no need to change version.  
455/// The dates of the files will be stored in the file .automation_tasks_rs_file_hashes.json near to Cargo.toml.  
456/// Warning: I don't check if the service worker has changed because it rarely does.  
457/// To know if the projects has changed or not, this function saves the dates of all files into `.automation_tasks_rs_file_hashes.json` near Cargo.toml
458///
459// endregion: auto_md_to_doc_comments include doc_comments/auto_version_from_date.md A ///
460pub fn auto_version_from_date() -> Result<()> {
461    crate::auto_version_from_date_mod::auto_version_from_date()
462}
463
464/// Just like auto_version_from_date(), but force the new version even if no files are changed.
465///
466/// For workspaces `release` I want to have the same version in all members.  
467/// It is slower, but easier to understand when deployed.
468pub fn auto_version_from_date_forced() -> Result<()> {
469    crate::auto_version_from_date_mod::auto_version_from_date_forced()
470}
471
472/// Pretty HTML for docs.  
473///
474/// The HTML generated by `cargo doc` is ugly and difficult to `git diff`.
475/// Tidy HTML is a HTML checker and formatter installed on most Linuxes.
476pub fn auto_doc_tidy_html() -> Result<()> {
477    crate::auto_doc_tidy_html_mod::auto_doc_tidy_html()
478}
479
480/// Does git have settings for remote.
481pub fn git_has_remote() -> Result<bool> {
482    crate::auto_git_mod::git_has_remote()
483}
484
485/// Check if this folder is a local Git repository.
486pub fn git_is_local_repository() -> Result<bool> {
487    crate::auto_git_mod::git_is_local_repository()
488}
489
490/// Run one shell command and return ShellOutput {exit_status, stdout, stderr}.
491///
492/// TODO: vulnerable to command injection
493pub fn run_shell_command_output(shell_command: &str) -> Result<ShellOutput> {
494    crate::auto_shell_mod::run_shell_command_output(shell_command)
495}
496
497/// Run one shell command and return true if success.
498///
499/// TODO: vulnerable to command injection
500pub fn run_shell_command_success(shell_command: &str) -> Result<bool> {
501    crate::auto_shell_mod::run_shell_command_success(shell_command)
502}
503
504/// Get home dir using the home crate.
505///
506/// Error if HOME not found.
507pub fn home_dir() -> Result<std::path::PathBuf> {
508    crate::auto_helper_functions_mod::home_dir()
509}
510
511/// Replace tilde with home::home_dir, only for utf8.
512pub fn tilde_expand_to_home_dir_utf8(path_str: &str) -> Result<camino::Utf8PathBuf> {
513    crate::auto_helper_functions_mod::tilde_expand_to_home_dir_utf8(path_str)
514}
515
516/// Sync, check, create, push git tag.
517pub fn git_tag_sync_check_create_push(version: &str) -> Result<String> {
518    crate::auto_github_mod::git_tag_sync_check_create_push(version)
519}
520
521/// Get release text from RELEASES.md.
522///
523/// First, the user must write the content into file RELEASES.md in the section ## Unreleased.  
524/// Then the automation task will copy the content to GitHub release  
525/// and create a new Version title in RELEASES.md.  
526pub fn body_text_from_releases_md() -> Result<String> {
527    crate::auto_github_mod::body_text_from_releases_md()
528}
529
530/// Create a new Version title in RELEASES.md.
531pub fn create_new_version_in_releases_md(release_name: &str) -> Result<()> {
532    crate::auto_github_mod::create_new_version_in_releases_md(release_name)
533}
534
535/// UTC  date in iso standard like 2024-12-31
536pub fn now_utc_date_iso() -> String {
537    crate::utils_mod::now_utc_date_iso()
538}
539
540// region: auto_md_to_doc_comments include doc_comments/copy_folder_files_into_module.md A ///
541/// Copy all files from the folder into a module as strings (static &str).
542///
543/// The Rust code to modify has the markers:
544///
545/// ```Rust ignore
546/// //comment region: files copied into strings by automation tasks
547///
548/// //comment endregion: files copied into strings by automation tasks
549///
550/// ```
551///
552/// In this instructions I changed `[//]` to `[//comment]` to not process these markers.
553///
554/// First we create the complete text, then we check if the old text needs to be replaced.
555///
556/// Binary files need a special treatment:
557///
558/// ```Rust ignore
559/// ext_for_binary_files=vec![".ico",".jpg",".png",".woff2"];
560/// ```
561///
562/// Exclude big folders:
563///
564/// ```Rust ignore
565/// exclude_big_folders = vec!["/.git","/target","/docs"];
566/// ```
567///
568// endregion: auto_md_to_doc_comments include doc_comments/copy_folder_files_into_module.md A ///
569pub fn copy_folder_files_into_module(
570    folder_path: &std::path::Path,
571    module_path: &std::path::Path,
572    ext_for_binary_files: &[&str],
573    exclude_big_folders: &[String],
574) -> Result<()> {
575    crate::auto_copy_files_to_strings_mod::copy_folder_files_into_module(
576        folder_path,
577        module_path,
578        ext_for_binary_files,
579        exclude_big_folders,
580    )
581}
582
583/// Add commit message to Unreleased in RELEASES.md.
584pub fn add_message_to_unreleased(message: &str) -> Result<()> {
585    crate::auto_github_mod::add_message_to_unreleased(message)
586}
587
588// region: auto_md_to_doc_comments include doc_comments/auto_playground_run_code.md A ///
589/// Include the link to run code in Rust playground.
590///
591/// The function searches in all markdown files for markers like this:
592///
593/// ```markdown
594/// [//comment]: # (auto_playground start)
595///
596/// Run this code in the [Rust playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=fn%20m%0A%7D):
597///
598/// '''Rust ignore
599/// fn main(){
600///     println!("Hello World!");
601/// }
602/// '''
603///
604/// [//comment]: # (auto_playground end)
605/// ```
606///
607/// In this instructions I changed `[//]` to `[//comment]` and  ticks to single quotes to not process these markers.
608///
609/// Between the start marker and the first triple backtick there is the link in "()" parentheses. The link to Rust playground encodes the code with url_encoding (percents) and sends it as an Url parameter.
610///
611/// Info: docs.rs has already a functionality that shows the `Run` button on your code and can run code the playground if you put this line at the top of lib.rs:
612///
613/// ``` Rust ignore
614/// #![doc(html_playground_url = "https://play.rust-lang.org")]
615/// ```
616///
617/// But it works only on docs.rs.  
618/// I want to run my code examples from everywhere: from GitHub README.md, GitHub pages and crates.io.  
619///
620// endregion: auto_md_to_doc_comments include doc_comments/auto_playground_run_code.md A ///
621pub fn auto_playground_run_code() -> Result<()> {
622    crate::auto_playground_mod::auto_playground_run_code()
623}
624
625/// Interactive ask to create a new local git repository.
626pub fn new_local_repository(message: &str) -> Result<()> {
627    crate::auto_git_mod::new_local_repository(message)
628}
629// endregion: Public API functions