1use std::path::{Path, PathBuf};
2
3use anyhow::{anyhow, Result};
4use clap::{CommandFactory, Parser, ValueEnum};
5use clap_complete::{generate_to, Shell};
6use serde::Deserialize;
7
8use crate::{consts::DEFAULT_ALPHA, consts::DEFAULT_DURATION};
9
10#[derive(Debug, Deserialize, Parser)]
11#[command(author, version, about)]
12pub struct DimOpts {
13 #[arg(
14 short,
15 long,
16 help = format!("Duration in seconds, 0 is infinite, [default: {DEFAULT_DURATION}]")
17 )]
18 pub duration: Option<u64>,
19
20 #[arg(
21 short,
22 long,
23 help = format!("0.0 is transparent, 1.0 is opaque. When opaque, cursor will be hidden. [default: {DEFAULT_ALPHA}]")
24 )]
25 pub alpha: Option<f32>,
26
27 #[arg(
28 short,
29 long,
30 help = "Make dim ignore input, passing it to lower surfaces. (You probably want to use `-d 0` with this)"
31 )]
32 #[serde(default)]
33 pub passthrough: bool,
34
35 #[serde(skip)]
36 #[arg(long, value_name = "PATH", help = "Generate completions at given path")]
37 pub gen_completions: Option<PathBuf>,
38
39 #[serde(skip)]
40 #[arg(short, long, value_name = "PATH", help = "Use config at path")]
41 pub config: Option<PathBuf>,
42}
43
44impl DimOpts {
45 pub fn generate_completions(dir: &Path) -> anyhow::Result<()> {
46 let mut cli = Self::command();
47
48 for &shell in Shell::value_variants() {
49 let comp_file = generate_to(shell, &mut cli, "dim", dir)?;
50 println!("Generated completion for {shell} at {comp_file:?}");
51 }
52
53 Ok(())
54 }
55
56 pub fn merge_onto_self(self, other: DimOpts) -> Self {
58 Self {
59 duration: other.duration.or(self.duration),
60 alpha: other.alpha.or(self.alpha),
61 passthrough: self.passthrough || other.passthrough,
62
63 ..self
64 }
65 }
66
67 pub fn validate(&self) -> Result<()> {
70 if let Some(alpha) = self.alpha {
71 if !(0.0..=1.0).contains(&alpha) {
72 return Err(anyhow!("Alpha can only be from 0.0 to 1.0 inclusive."));
73 }
74 }
75
76 Ok(())
77 }
78
79 pub fn alpha(&self) -> f32 {
81 self.alpha.unwrap_or(DEFAULT_ALPHA)
82 }
83
84 pub fn duration(&self) -> u64 {
86 self.duration.unwrap_or(DEFAULT_DURATION)
87 }
88}