use crate::commands::command::CommandData;
use crate::commands::command_operation::SimulatedData;
use crate::commands::{
ColorSupport, Command, CommandBuildError, CommandOperation, CommandOperationImpl, DirectoryReader, ListData,
RestowData, StowData, StowOptions, UnstowData,
};
use std::collections::HashSet;
use std::path::PathBuf;
#[derive(Default)]
pub struct CommandBuilder<T: CommandOperation<DirectoryReader>> {
target: Option<PathBuf>,
directory: Option<PathBuf>,
dot_file_prefix: Option<String>,
operation: T,
}
#[derive(Default)]
pub struct StowCommandBuilder<T: CommandOperation<DirectoryReader>> {
builder: CommandBuilder<T>,
ignored: HashSet<String>,
overrides: HashSet<String>,
no_folding: bool,
}
#[derive(Default)]
pub struct UnstowCommandBuilder<T: CommandOperation<DirectoryReader>> {
builder: CommandBuilder<T>,
}
#[derive(Default)]
pub struct RestowCommandBuilder<T: CommandOperation<DirectoryReader>> {
stow_command: StowCommandBuilder<T>,
}
#[derive(Default)]
pub struct ListCommandBuilder<T: CommandOperation<DirectoryReader>> {
builder: CommandBuilder<T>,
color_support: ColorSupport,
}
#[allow(unused)]
impl<T: CommandOperation<DirectoryReader> + Default> CommandBuilder<T> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_target(mut self, target: PathBuf) -> Self {
self.target = Some(target);
self
}
#[must_use]
pub fn with_directory(mut self, directory: PathBuf) -> Self {
self.directory = Some(directory);
self
}
#[must_use]
pub fn with_dot_file_prefix(mut self, prefix: Option<String>) -> Self {
self.dot_file_prefix = prefix;
self
}
#[must_use]
pub fn simulate(self, color_support: ColorSupport) -> CommandBuilder<CommandOperationImpl> {
CommandBuilder::<CommandOperationImpl> {
target: self.target,
directory: self.directory,
operation: CommandOperationImpl::Simulated(SimulatedData::default().with_color_support(color_support)),
dot_file_prefix: self.dot_file_prefix,
}
}
#[must_use]
pub fn command(self) -> CommandBuilder<CommandOperationImpl> {
CommandBuilder::<CommandOperationImpl> {
target: self.target,
directory: self.directory,
operation: CommandOperationImpl::Default,
dot_file_prefix: self.dot_file_prefix,
}
}
#[must_use]
pub fn stow(self) -> StowCommandBuilder<T> {
StowCommandBuilder {
builder: self,
ignored: HashSet::new(),
overrides: HashSet::new(),
no_folding: false,
}
}
#[must_use]
pub const fn unstow(self) -> UnstowCommandBuilder<T> {
UnstowCommandBuilder { builder: self }
}
#[must_use]
pub fn restow(self) -> RestowCommandBuilder<T> {
RestowCommandBuilder {
stow_command: self.stow(),
}
}
#[must_use]
pub const fn list(self) -> ListCommandBuilder<T> {
ListCommandBuilder {
builder: self,
color_support: ColorSupport::None,
}
}
}
#[allow(unused)]
impl<T: CommandOperation<DirectoryReader> + Default> UnstowCommandBuilder<T> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_target(mut self, target: PathBuf) -> Self {
self.builder = self.builder.with_target(target);
self
}
#[must_use]
pub fn with_directory(mut self, directory: PathBuf) -> Self {
self.builder = self.builder.with_directory(directory);
self
}
#[must_use]
pub fn simulate(self, color_support: ColorSupport) -> UnstowCommandBuilder<CommandOperationImpl> {
UnstowCommandBuilder::<CommandOperationImpl> {
builder: self.builder.simulate(color_support),
}
}
#[must_use]
pub fn command(self) -> UnstowCommandBuilder<CommandOperationImpl> {
UnstowCommandBuilder::<CommandOperationImpl> {
builder: self.builder.command(),
}
}
#[must_use]
pub fn with_dot_file_prefix(mut self, prefix: Option<String>) -> Self {
self.builder = self.builder.with_dot_file_prefix(prefix);
self
}
pub fn build(self) -> Result<Command<DirectoryReader, T>, CommandBuildError> {
let target = self
.builder
.target
.map_or_else(|| Err(CommandBuildError::MissingTargetDirectory), Ok)?;
let directory = self
.builder
.directory
.map_or_else(|| Err(CommandBuildError::MissingStowDirectory), Ok)?;
let data = UnstowData::new(target, directory, self.builder.dot_file_prefix);
Ok(Command::Unstow(CommandData {
data,
operation: self.builder.operation,
_marker: std::marker::PhantomData,
}))
}
}
#[allow(unused)]
impl<T: CommandOperation<DirectoryReader> + Default> StowCommandBuilder<T> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub const fn with_no_folding(mut self, no_folding: bool) -> Self {
self.no_folding = no_folding;
self
}
#[must_use]
pub fn with_target(mut self, target: PathBuf) -> Self {
self.builder = self.builder.with_target(target);
self
}
#[must_use]
pub fn with_directory(mut self, directory: PathBuf) -> Self {
self.builder = self.builder.with_directory(directory);
self
}
#[must_use]
pub fn with_ignored(mut self, ignored: HashSet<String>) -> Self {
self.ignored = ignored;
self
}
#[must_use]
pub fn with_ignored_item(mut self, item: String) -> Self {
self.ignored.insert(item);
self
}
#[must_use]
pub fn with_overrides(mut self, overrides: HashSet<String>) -> Self {
self.overrides = overrides;
self
}
#[must_use]
pub fn with_override_item(mut self, item: String) -> Self {
self.overrides.insert(item);
self
}
#[must_use]
pub fn with_dot_file_prefix(mut self, prefix: Option<String>) -> Self {
self.builder = self.builder.with_dot_file_prefix(prefix);
self
}
#[must_use]
pub fn simulate(self, color_support: ColorSupport) -> StowCommandBuilder<CommandOperationImpl> {
StowCommandBuilder::<CommandOperationImpl> {
builder: self.builder.simulate(color_support),
ignored: self.ignored,
overrides: HashSet::new(),
no_folding: self.no_folding,
}
}
#[must_use]
pub fn command(self) -> StowCommandBuilder<CommandOperationImpl> {
StowCommandBuilder::<CommandOperationImpl> {
builder: self.builder.command(),
ignored: self.ignored,
overrides: self.overrides,
no_folding: self.no_folding,
}
}
pub fn build(self) -> Result<Command<DirectoryReader, T>, CommandBuildError> {
let operation = self.builder.operation;
let target = self
.builder
.target
.map_or_else(|| Err(CommandBuildError::MissingTargetDirectory), Ok)?;
let directory = self
.builder
.directory
.map_or_else(|| Err(CommandBuildError::MissingStowDirectory), Ok)?;
let stow_options = StowOptions::new(
self.builder.dot_file_prefix,
self.no_folding,
self.ignored.iter(),
self.overrides.iter(),
);
let data = StowData::new(target, directory, stow_options);
Ok(Command::Stow(CommandData {
data,
operation,
_marker: std::marker::PhantomData,
}))
}
}
#[allow(unused)]
impl<T: CommandOperation<DirectoryReader> + Default> RestowCommandBuilder<T> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_no_folding(mut self, no_folding: bool) -> Self {
self.stow_command = self.stow_command.with_no_folding(no_folding);
self
}
#[must_use]
pub fn with_target(mut self, target: PathBuf) -> Self {
self.stow_command = self.stow_command.with_target(target);
self
}
#[must_use]
pub fn with_directory(mut self, directory: PathBuf) -> Self {
self.stow_command = self.stow_command.with_directory(directory);
self
}
#[must_use]
pub fn with_ignored(mut self, ignored: HashSet<String>) -> Self {
self.stow_command = self.stow_command.with_ignored(ignored);
self
}
#[must_use]
pub fn with_ignored_item(mut self, item: String) -> Self {
self.stow_command = self.stow_command.with_ignored_item(item);
self
}
#[must_use]
pub fn with_overrides(mut self, overrides: HashSet<String>) -> Self {
self.stow_command = self.stow_command.with_overrides(overrides);
self
}
#[must_use]
pub fn with_override_item(mut self, item: String) -> Self {
self.stow_command = self.stow_command.with_override_item(item);
self
}
#[must_use]
pub fn simulate(self, color_support: ColorSupport) -> RestowCommandBuilder<CommandOperationImpl> {
RestowCommandBuilder::<CommandOperationImpl> {
stow_command: self.stow_command.simulate(color_support),
}
}
#[must_use]
pub fn command(self) -> RestowCommandBuilder<CommandOperationImpl> {
RestowCommandBuilder::<CommandOperationImpl> {
stow_command: self.stow_command.command(),
}
}
#[must_use]
pub fn with_dot_file_prefix(mut self, prefix: Option<String>) -> Self {
self.stow_command = self.stow_command.with_dot_file_prefix(prefix);
self
}
pub fn build(self) -> Result<Command<DirectoryReader, T>, CommandBuildError> {
let cmd = self.stow_command;
let operation = cmd.builder.operation;
let target = cmd
.builder
.target
.map_or_else(|| Err(CommandBuildError::MissingTargetDirectory), Ok)?;
let directory = cmd
.builder
.directory
.map_or_else(|| Err(CommandBuildError::MissingStowDirectory), Ok)?;
let stow_options = StowOptions::new(
cmd.builder.dot_file_prefix,
cmd.no_folding,
cmd.ignored.iter(),
cmd.overrides.iter(),
);
let data = RestowData::new(target, directory, stow_options);
Ok(Command::Restow(CommandData {
data,
operation,
_marker: std::marker::PhantomData,
}))
}
}
#[allow(unused)]
impl<T: CommandOperation<DirectoryReader> + Default> ListCommandBuilder<T> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_target(mut self, target: PathBuf) -> Self {
self.builder = self.builder.with_target(target);
self
}
#[must_use]
pub fn with_directory(mut self, directory: PathBuf) -> Self {
self.builder = self.builder.with_directory(directory);
self
}
#[must_use]
pub fn simulate(self, color_support: ColorSupport) -> ListCommandBuilder<CommandOperationImpl> {
ListCommandBuilder::<CommandOperationImpl> {
builder: self.builder.simulate(color_support),
color_support: self.color_support,
}
}
#[must_use]
pub fn command(self) -> UnstowCommandBuilder<CommandOperationImpl> {
UnstowCommandBuilder::<CommandOperationImpl> {
builder: self.builder.command(),
}
}
#[must_use]
pub fn with_dot_file_prefix(mut self, prefix: Option<String>) -> Self {
self.builder = self.builder.with_dot_file_prefix(prefix);
self
}
#[must_use]
pub const fn with_color_support(mut self, color_support: ColorSupport) -> Self {
self.color_support = color_support;
self
}
pub fn build(self) -> Result<Command<DirectoryReader, T>, CommandBuildError> {
let target = self
.builder
.target
.map_or_else(|| Err(CommandBuildError::MissingTargetDirectory), Ok)?;
let directory = self
.builder
.directory
.map_or_else(|| Err(CommandBuildError::MissingStowDirectory), Ok)?;
let data = ListData::new(
target,
directory,
self.builder.dot_file_prefix,
self.color_support,
);
Ok(Command::List(CommandData {
data,
operation: self.builder.operation,
_marker: std::marker::PhantomData,
}))
}
}