srctrait_common_tomlx/
starter.rs

1//! Serializes / Deserializes between Self and an example TOML file with
2//! configuration values commented out.
3//! 
4//! This is inteded to be used once per config as a first-run that introduces
5//! defaults to the user.
6//! 
7//! Any comments remaining after the the user makes their edits are removed.
8//! 
9//! Trimming comments out, is potentially destructive, as the user may create
10//! comments of their own, so we attempt to format our comments in a way that
11//! we, hopefully, do not trample on the user's.
12//! 
13//! This is also the reason why we only use this method as a first-run. The
14//! split-view method is preferred, if the user's $EDITOR supports it (and
15//! they know how to use split-view in that editor).
16
17use std::{fs, path::Path};
18use crate::*;
19
20pub trait ToStarterToml: ToToml {
21    fn to_starter_toml(&self, intro: Option<&str>) -> Result<String>
22    where
23        Self: serde::ser::Serialize
24    {
25        let intro = intro.map(comment_out_text).unwrap_or_default();
26        let content = comment_out_data(&self.to_toml()?);
27        Ok(format!("{intro}{content}"))
28    }
29    
30    fn to_starter_toml_file(&self, toml_file: &Path, intro: Option<&str>) -> Result<()>
31    where
32        Self: serde::ser::Serialize
33    {
34        let toml = self.to_starter_toml(intro)?;
35        fs::write(toml_file, toml)
36            .map_err(|e| Error::Io(format!("Unable to write to TOML file: {}", toml_file.display()), e))?;
37        
38        Ok(())
39    }
40}
41
42pub fn trim_starter_toml_comments(toml: &str) -> String {
43    toml
44        .lines()
45        .filter(|line| !line.starts_with('#') || line.starts_with("# "))
46        .collect::<Vec<_>>()
47        .join("\n")
48}
49
50pub fn trim_starter_toml_file_comments(toml_file: &Path) -> Result<()> {
51    let toml = fs::read_to_string(toml_file)
52        .map_err(|e| Error::Io(format!("Unable to read from TOML file: {}", toml_file.display()), e))?;
53    
54    fs::write(toml_file, trim_starter_toml_comments(&toml))
55        .map_err(|e| Error::Io(format!("Unable to write to TOML file: {}", toml_file.display()), e))?;
56    
57    Ok(())
58}
59
60pub const GENERIC_INTRO: Option<&'static str> = Some("Uncomment the settings that you wish to change.\nThe rest will be removed after you save this file.");
61
62fn comment_out_data(toml: &str) -> String {
63    toml
64        .lines()
65        .map(|line| format!("#{line}"))
66        .collect::<Vec<_>>()
67        .join("\n")
68}
69
70fn comment_out_text(toml: &str) -> String {
71    let mut toml = toml
72        .lines()
73        .map(|line| format!("#- {line}"))
74        .collect::<Vec<_>>()
75        .join("\n");
76    
77    toml.push_str("\n#\n");
78    toml
79}