1use clap::{Parser, arg, command};
2
3use crate::log;
4
5#[derive(clap::Parser, serde::Serialize)]
7#[command(version, about, long_about = None)]
8pub struct Arguments {
9 #[command(subcommand)]
10 pub command: Command,
11
12 #[clap(short, long)]
14 pub wait_for_daemon: bool,
15
16 #[arg(allow_hyphen_values = true, trailing_var_arg = true)]
18 pub gtk_options: Vec<String>,
19}
20
21impl Arguments {
22 pub fn parse(after_help: impl clap::builder::IntoResettable<clap::builder::StyledStr>) -> Self {
23 let mut matches = <Self as clap::CommandFactory>::command()
24 .after_help(after_help)
25 .get_matches();
26 let res = <Self as clap::FromArgMatches>::from_arg_matches_mut(&mut matches);
27 match res {
28 Ok(s) => s,
29 Err(e) => {
30 log::error!("Failed to parse cli arguments {e}");
31 }
32 }
33 }
34}
35
36#[derive(Parser, serde::Serialize, serde::Deserialize, Debug)]
38pub enum Command {
39 #[command(subcommand)]
40 Daemon(daemon::Command),
41
42 #[command(subcommand)]
43 Window(window::Command),
44
45 #[command(subcommand)]
46 Layer(layer_shell::Command),
47
48 #[command(subcommand)]
49 Config(config::Command),
50
51 Monitors,
52
53 #[command(subcommand)]
54 Style(style::Command),
55 }
57
58pub mod daemon {
59 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
60 pub enum Command {
61 Start {
62 #[clap(long)]
63 config: Option<String>,
64 },
65 Stop,
66 }
67}
68
69pub mod window {
70 use crate::config;
71
72 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
73 pub enum Command {
74 Create(CreateArgs),
75 Toggle(ToggleArgs),
76 Uuid,
77 }
78
79 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
80 pub struct ToggleArgs {
81 pub uuid: String,
82 }
83
84 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
85 pub struct CreateArgs {
86 pub id: config::window::Id,
87 }
88}
89
90pub mod layer_shell {
91 use gtk4_layer_shell::LayerShell;
92
93 use crate::config::layer_shell::{Anchor, Layer};
94
95 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
96 pub enum Command {
97 Toggle(Arguments),
98 }
99
100 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
101 pub struct Arguments {
102 pub namespace: crate::config::layer_shell::Namespace,
103
104 #[clap(long)]
105 pub layer: Option<Layer>,
106
107 #[clap(long)]
108 pub anchors: Vec<Anchor>,
109 }
110
111 impl Arguments {
112 pub fn cmp(&self, window: >k::Window) -> bool {
113 let Some(namespace) = window.namespace() else {
114 return false;
115 };
116 if self.namespace != namespace {
117 return false;
118 }
119
120 if let Some(layer) = &self.layer {
121 let win_layer = window.layer();
122 if Into::<gtk4_layer_shell::Layer>::into(layer) != win_layer {
123 return false;
124 }
125 }
126
127 for anchor in &self.anchors {
128 if !window.is_anchor(anchor.into()) {
129 return false;
130 };
131 }
132
133 return true;
134 }
135 }
136}
137
138pub mod config {
139 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
140 pub enum Command {
141 View {
142 #[clap(long)]
143 json: bool,
144 },
145 }
146}
147
148pub mod style {
149 #[derive(clap::Parser, serde::Serialize, serde::Deserialize, Debug)]
150 pub enum Command {
151 Reload {
153 #[clap(long)]
155 file: Option<std::path::PathBuf>,
156 },
157 Default,
159 }
160}
161
162#[derive(serde::Serialize, serde::Deserialize)]
163pub enum Response {
164 Success(String),
165 Error(String),
166}