use std::collections::HashMap;
use std::fmt;
use clap::{Args, Parser, ValueEnum};
use super::basic;
use crate::{textbuf::alphabet, tmux, ui, Error, Result};
#[derive(Parser, Debug)]
#[clap(author, about, version)]
pub enum MainConfig {
Run {
#[command(flatten)]
config_ext: ConfigExt,
},
Init,
}
#[derive(Args, Debug)]
pub struct ConfigExt {
#[arg(short = 'n', long)]
pub ignore_tmux_options: bool,
#[arg(short = 'W', long, default_value = "[copyrat]")]
pub window_name: String,
#[arg(
value_enum,
long,
rename_all = "kebab-case",
default_value = "visible-area"
)]
pub capture_region: CaptureRegion,
#[arg(long, default_value = "pbcopy")]
pub clipboard_exe: String,
#[command(flatten)]
pub basic_config: basic::Config,
}
impl ConfigExt {
pub fn build(mut self) -> Result<ConfigExt> {
if !self.ignore_tmux_options {
let tmux_options: HashMap<String, String> = tmux::get_options("@copyrat-")?;
let inner = &mut self.basic_config;
for (name, value) in &tmux_options {
log::debug!("Processing tmux option: {name} = {value}");
match name.as_ref() {
"@copyrat-alphabet" => {
inner.alphabet = alphabet::parse_alphabet(value)?;
}
"@copyrat-reverse" => {
inner.reverse = value.parse::<bool>()?;
}
"@copyrat-unique-hint" => {
inner.unique_hint = value.parse::<bool>()?;
}
"@copyrat-focus-wrap-around" => {
inner.focus_wrap_around = value.parse::<bool>()?
}
"@copyrat-text-fg" => inner.colors.text_fg = ui::colors::parse_color(value)?,
"@copyrat-text-bg" => inner.colors.text_bg = ui::colors::parse_color(value)?,
"@copyrat-span-fg" => inner.colors.span_fg = ui::colors::parse_color(value)?,
"@copyrat-span-bg" => inner.colors.span_bg = ui::colors::parse_color(value)?,
"@copyrat-focused-fg" => {
inner.colors.focused_fg = ui::colors::parse_color(value)?
}
"@copyrat-focused-bg" => {
inner.colors.focused_bg = ui::colors::parse_color(value)?
}
"@copyrat-hint-fg" => inner.colors.hint_fg = ui::colors::parse_color(value)?,
"@copyrat-hint-bg" => inner.colors.hint_bg = ui::colors::parse_color(value)?,
"@copyrat-hint-alignment" => {
let case_insensitive = true;
inner.hint_alignment = ui::HintAlignment::from_str(value, case_insensitive)
.map_err(Error::ExpectedEnumVariant)?
}
"@copyrat-hint-style" => {
let case_insensitive = true;
inner.hint_style_arg = Some(
basic::HintStyleArg::from_str(value, case_insensitive)
.map_err(Error::ExpectedEnumVariant)?,
)
}
"@copyrat-hint-surroundings" => {
inner.hint_surroundings = basic::try_parse_chars(value)?;
}
"@copyrat-default-output" => {
let case_insensitive = true;
inner.default_output = OutputDestination::from_str(value, case_insensitive)
.map_err(Error::ExpectedEnumVariant)?
}
"@copyrat-multi-select" => {
inner.multi_select = value.parse::<bool>()?;
}
"@copyrat-separator" => {
inner.separator = value.clone();
}
"@copyrat-selected-fg" => {
inner.colors.selected_fg = ui::colors::parse_color(value)?
}
"@copyrat-selected-bg" => {
inner.colors.selected_bg = ui::colors::parse_color(value)?
}
_ => (),
}
}
}
Ok(self)
}
}
#[derive(Debug, Clone, ValueEnum, Parser)]
pub enum CaptureRegion {
EntireHistory,
VisibleArea,
}
#[derive(Clone, Debug, ValueEnum)]
pub enum OutputDestination {
Tmux,
Clipboard,
}
impl OutputDestination {
pub fn toggle(&mut self) {
match *self {
Self::Tmux => *self = Self::Clipboard,
Self::Clipboard => *self = Self::Tmux,
}
}
}
impl fmt::Display for OutputDestination {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Tmux => write!(f, "tmux buffer"),
Self::Clipboard => write!(f, "clipboard"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_output_destination_toggle() {
let mut dest = OutputDestination::Tmux;
dest.toggle();
assert!(matches!(dest, OutputDestination::Clipboard));
dest.toggle();
assert!(matches!(dest, OutputDestination::Tmux));
}
#[test]
fn test_output_destination_display() {
assert_eq!(OutputDestination::Tmux.to_string(), "tmux buffer");
assert_eq!(OutputDestination::Clipboard.to_string(), "clipboard");
}
}