petr_pkg/
manifest.rs

1use serde::{Deserialize, Serialize};
2
3use crate::Dependency;
4
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct Manifest {
7    pub author:       Option<String>,
8    pub license:      Option<String>,
9    pub name:         String,
10    #[serde(default)]
11    pub formatter:    FormatterConfigManifestFormat,
12    #[serde(default)]
13    pub dependencies: BTreeMap<String, Dependency>,
14}
15
16#[derive(Debug, Serialize, Deserialize, Clone, Default)]
17pub struct FormatterConfigManifestFormat {
18    pub put_fn_params_on_new_lines: Option<bool>,
19    pub use_set_notation_for_types: Option<bool>,
20    pub join_comments: Option<bool>,
21    pub newlines_between_items: Option<usize>,
22    pub newlines_between_comment_and_item: Option<usize>,
23    pub put_variants_on_new_lines: Option<bool>,
24    pub put_list_elements_on_new_lines: Option<bool>,
25    pub put_fn_body_on_new_line: Option<bool>,
26    pub tab_size: Option<usize>,
27    pub max_line_length: Option<usize>,
28    pub put_fn_args_on_new_lines: Option<bool>,
29    pub put_trailing_semis_on_let_bindings: Option<bool>,
30    pub backup: Option<bool>,
31}
32
33// TODO: this kind of sucks that we have to manually convert this to get a good serde serialization.
34// It would be nice to get a compile error if we add something to FormatterConfig but forget it here.
35impl From<FormatterConfigManifestFormat> for petr_fmt::FormatterConfig {
36    fn from(value: FormatterConfigManifestFormat) -> Self {
37        let mut builder = petr_fmt::FormatterConfigBuilder::default();
38        if let Some(conf) = value.put_fn_params_on_new_lines {
39            builder = builder.put_fn_params_on_new_lines(conf);
40        };
41        if let Some(conf) = value.use_set_notation_for_types {
42            builder = builder.use_set_notation_for_types(conf);
43        };
44        if let Some(conf) = value.join_comments {
45            builder = builder.join_comments(conf);
46        };
47        if let Some(conf) = value.newlines_between_items {
48            builder = builder.newlines_between_items(conf);
49        };
50        if let Some(conf) = value.newlines_between_comment_and_item {
51            builder = builder.newlines_between_comment_and_item(conf);
52        };
53        if let Some(conf) = value.put_variants_on_new_lines {
54            builder = builder.put_variants_on_new_lines(conf);
55        };
56        if let Some(conf) = value.put_list_elements_on_new_lines {
57            builder = builder.put_list_elements_on_new_lines(conf);
58        };
59        if let Some(conf) = value.put_fn_body_on_new_line {
60            builder = builder.put_fn_body_on_new_line(conf);
61        };
62        if let Some(conf) = value.tab_size {
63            builder = builder.tab_size(conf);
64        };
65        if let Some(conf) = value.max_line_length {
66            builder = builder.max_line_length(conf);
67        };
68        if let Some(conf) = value.put_fn_args_on_new_lines {
69            builder = builder.put_fn_args_on_new_lines(conf);
70        };
71        if let Some(conf) = value.put_trailing_semis_on_let_bindings {
72            builder = builder.put_trailing_semis_on_let_bindings(conf);
73        };
74        if let Some(conf) = value.backup {
75            builder = builder.backup(conf);
76        };
77
78        builder.build()
79    }
80}
81
82// check the current folder, then recursively upwards until a petr manfiest is found
83use std::{
84    collections::BTreeMap,
85    fs,
86    path::{Path, PathBuf},
87};
88
89pub fn find_manifest(path: Option<PathBuf>) -> Result<Manifest, Box<dyn std::error::Error>> {
90    fn search_dir(path: &Path) -> Option<PathBuf> {
91        let manifest_path = path.join("pete.toml");
92        if manifest_path.exists() {
93            return Some(manifest_path);
94        }
95        path.parent().and_then(search_dir)
96    }
97
98    let start_path = path.unwrap_or_else(|| std::env::current_dir().unwrap());
99    let manifest_path = search_dir(&start_path).ok_or("Manifest file not found")?;
100    let manifest_content = fs::read_to_string(manifest_path)?;
101    let manifest = toml::from_str(&manifest_content)?;
102    Ok(manifest)
103}