use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct FormatOptions {
pub indent_size: usize,
pub use_tabs: bool,
pub max_line_length: usize,
#[serde(default)]
pub preserve_unformatted: bool,
#[serde(default = "default_blank_lines_between_classes")]
pub blank_lines_between_classes: usize,
}
fn default_blank_lines_between_classes() -> usize {
1
}
impl Default for FormatOptions {
fn default() -> Self {
Self {
indent_size: 2,
use_tabs: false,
max_line_length: 100,
preserve_unformatted: true,
blank_lines_between_classes: 1,
}
}
}
pub const CONFIG_FILE_NAMES: &[&str] = &[".rumoca_fmt.toml", "rumoca_fmt.toml"];
impl FormatOptions {
pub fn with_spaces(indent_size: usize) -> Self {
Self {
indent_size,
use_tabs: false,
max_line_length: 100,
preserve_unformatted: true,
blank_lines_between_classes: 1,
}
}
pub fn with_tabs() -> Self {
Self {
indent_size: 1,
use_tabs: true,
max_line_length: 100,
preserve_unformatted: true,
blank_lines_between_classes: 1,
}
}
pub fn from_config_file(start_dir: &std::path::Path) -> Option<Self> {
let mut current = start_dir.to_path_buf();
if current.is_file() {
current = current.parent()?.to_path_buf();
}
loop {
for config_name in CONFIG_FILE_NAMES {
let config_path = current.join(config_name);
if config_path.exists()
&& let Ok(contents) = std::fs::read_to_string(&config_path)
&& let Ok(options) = toml::from_str::<FormatOptions>(&contents)
{
return Some(options);
}
}
if let Some(parent) = current.parent() {
current = parent.to_path_buf();
} else {
break;
}
}
None
}
pub fn merge_cli_options(
&mut self,
cli_indent_size: Option<usize>,
cli_use_tabs: Option<bool>,
cli_max_line_length: Option<usize>,
) {
if let Some(indent_size) = cli_indent_size {
self.indent_size = indent_size;
}
if let Some(use_tabs) = cli_use_tabs {
self.use_tabs = use_tabs;
}
if let Some(max_line_length) = cli_max_line_length {
self.max_line_length = max_line_length;
}
}
pub fn merge_cli_options_ext(
&mut self,
cli_indent_size: Option<usize>,
cli_use_tabs: Option<bool>,
cli_max_line_length: Option<usize>,
cli_blank_lines_between_classes: Option<usize>,
) {
self.merge_cli_options(cli_indent_size, cli_use_tabs, cli_max_line_length);
if let Some(blank_lines) = cli_blank_lines_between_classes {
self.blank_lines_between_classes = blank_lines;
}
}
}