Skip to main content

worktree_io/config/
ser.rs

1use std::fmt::Write as _;
2
3use super::Config;
4
5/// Wrap a string value in TOML basic-string quotes, escaping special characters.
6fn toml_quoted(s: &str) -> String {
7    let escaped = s
8        .replace('\\', "\\\\")
9        .replace('"', "\\\"")
10        .replace('\n', "\\n")
11        .replace('\r', "\\r")
12        .replace('\t', "\\t");
13    format!("\"{escaped}\"")
14}
15
16impl Config {
17    /// Serialize the config to a TOML string with inline documentation comments.
18    ///
19    /// Each section header and field is preceded by a `#` comment that matches
20    /// the doc-comment on the corresponding struct field.  The resulting string
21    /// round-trips cleanly through [`toml::from_str`].
22    #[must_use]
23    pub fn to_toml_with_comments(&self) -> String {
24        let mut out = String::new();
25
26        // [editor] ------------------------------------------------------------
27        out.push_str("# Editor configuration.\n");
28        out.push_str("[editor]\n");
29        if let Some(cmd) = &self.editor.command {
30            out.push_str("# Command to launch the editor, e.g. \"code .\" or \"nvim .\"\n");
31            writeln!(out, "command = {}", toml_quoted(cmd)).unwrap();
32        }
33        out.push('\n');
34
35        // [open] --------------------------------------------------------------
36        out.push_str("# Workspace open behavior.\n");
37        out.push_str("[open]\n");
38        out.push_str("# Whether to launch the configured editor when opening a workspace.\n");
39        writeln!(out, "editor = {}", self.open.editor).unwrap();
40        out.push('\n');
41
42        // [hooks] -------------------------------------------------------------
43        out.push_str("# Hook scripts run around the open command.\n");
44        out.push_str("[hooks]\n");
45        if let Some(pre) = &self.hooks.pre_open {
46            out.push_str("# Script run before opening the workspace.\n");
47            writeln!(out, "\"pre:open\" = {}", toml_quoted(pre)).unwrap();
48        }
49        if let Some(post) = &self.hooks.post_open {
50            out.push_str("# Script run after opening the workspace.\n");
51            writeln!(out, "\"post:open\" = {}", toml_quoted(post)).unwrap();
52        }
53
54        out
55    }
56}
57
58#[cfg(test)]
59#[path = "ser_tests.rs"]
60mod ser_tests;