use anyhow::Context;
use color_print::cformat;
use std::path::PathBuf;
use worktrunk::git::Repository;
use worktrunk::path::format_path_for_display;
use worktrunk::styling::{eprintln, hint_message, info_message, success_message};
use super::state::require_user_config_path;
const USER_CONFIG_EXAMPLE: &str = include_str!("../../../dev/config.example.toml");
const PROJECT_CONFIG_EXAMPLE: &str = include_str!("../../../dev/wt.example.toml");
pub(super) fn comment_out_config(content: &str) -> String {
let has_trailing_newline = content.ends_with('\n');
let result = content
.lines()
.map(|line| {
if !line.is_empty() && !line.starts_with('#') {
format!("# {}", line)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n");
if has_trailing_newline {
format!("{}\n", result)
} else {
result
}
}
pub fn handle_config_create(project: bool) -> anyhow::Result<()> {
if project {
let repo = Repository::current()?;
let config_path = repo
.project_config_path()?
.context("Cannot determine project config location — no worktree found")?;
let user_config_exists = require_user_config_path()
.map(|p| p.exists())
.unwrap_or(false);
create_config_file(
config_path,
PROJECT_CONFIG_EXAMPLE,
"Project config",
&[
"Edit this file to configure hooks for this repository",
"See https://worktrunk.dev/hook/ for hook documentation",
],
user_config_exists,
true, )
} else {
let project_config_exists = Repository::current()
.and_then(|repo| repo.project_config_path())
.ok()
.and_then(|opt| opt)
.map(|path| path.exists())
.unwrap_or(false);
create_config_file(
require_user_config_path()?,
USER_CONFIG_EXAMPLE,
"User config",
&["Edit this file to customize worktree paths and LLM settings"],
project_config_exists,
false, )
}
}
fn create_config_file(
path: PathBuf,
content: &str,
config_type: &str,
success_hints: &[&str],
other_config_exists: bool,
is_project: bool,
) -> anyhow::Result<()> {
if path.exists() {
eprintln!(
"{}",
info_message(cformat!(
"{config_type} already exists: <bold>{}</>",
format_path_for_display(&path)
))
);
let hint = if other_config_exists {
cformat!("To view both user and project configs, run <underline>wt config show</>")
} else if is_project {
cformat!(
"To view, run <underline>wt config show</>. To create a user config, run <underline>wt config create</>"
)
} else {
cformat!(
"To view, run <underline>wt config show</>. To create a project config, run <underline>wt config create --project</>"
)
};
eprintln!("{}", hint_message(hint));
return Ok(());
}
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).context("Failed to create config directory")?;
}
let commented_config = comment_out_config(content);
std::fs::write(&path, commented_config).context("Failed to write config file")?;
eprintln!(
"{}",
success_message(cformat!(
"Created {}: <bold>{}</>",
config_type.to_lowercase(),
format_path_for_display(&path)
))
);
for hint in success_hints {
eprintln!("{}", hint_message(*hint));
}
Ok(())
}