1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
use std::path::PathBuf;
#[cfg(any(feature = "completions", feature = "color_picker"))]
use clap::ValueEnum;
use clap::{
Parser,
builder::{
Styles,
styling::{AnsiColor, Effects},
},
};
#[cfg(feature = "logger")]
use tracing::Level;
use crate::utils::EncodingFormat;
/// Shell variants for completion generation.
#[cfg(feature = "completions")]
#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum Shell {
Bash,
Elvish,
Fish,
Pwsh,
Zsh,
Nushell,
}
/// Output format for the color picker (`--color`).
#[cfg(feature = "color_picker")]
#[derive(ValueEnum, Clone, Debug, Default, PartialEq)]
pub enum ColorFormat {
/// Print all channels in human-readable form (RGBA, float, hex).
#[default]
Plain,
Hex,
HexAlpha,
Rgb,
Rgba,
Hsl,
}
fn get_styles() -> Styles {
Styles::styled()
.header(AnsiColor::Yellow.on_default() | Effects::BOLD)
.usage(AnsiColor::Green.on_default() | Effects::BOLD)
.literal(AnsiColor::Blue.on_default() | Effects::BOLD)
.placeholder(AnsiColor::Green.on_default())
}
#[derive(Parser)]
#[command(version, about, styles=get_styles())]
pub struct Cli {
// ─── Shell completions ────────────────────────────────────────────────────
/// Generate shell completions and print to stdout.
/// Example: wayshot --completions fish | source
#[cfg(feature = "completions")]
#[arg(long, value_name = "SHELL", exclusive = true, verbatim_doc_comment)]
pub completions: Option<Shell>,
// ─── Positional argument ──────────────────────────────────────────────────
/// Custom screenshot file path. Accepts:
/// 1. A directory — default naming scheme is applied.
/// 2. A file path — encoding is inferred from the extension.
/// 3. `-` — write raw image bytes to stdout (no file is saved).
#[arg(value_name = "FILE", verbatim_doc_comment)]
pub file: Option<PathBuf>,
// ─── Query commands (print info then exit; no screenshot is taken) ────────
/// List all connected outputs by name.
#[arg(short, long, alias = "list-outputs")]
pub list_outputs: bool,
/// List all connected outputs with name, description, size, and position.
#[arg(long)]
pub list_outputs_info: bool,
/// List all active toplevel windows.
#[arg(long, alias = "list-windows")]
pub list_toplevels: bool,
/// Click a point on screen and print its color values.
/// Optionally accepts a format: plain (default), hex, hex-alpha, rgb, rgba, hsl.
#[cfg(feature = "color_picker")]
#[arg(
long,
value_name = "FORMAT",
conflicts_with_all = ["geometry", "output", "choose_output"],
default_missing_value = "plain",
num_args = 0..=1,
)]
pub color: Option<ColorFormat>,
// ─── Capture target (what to capture) ────────────────────────────────────
/// Select a screen region to capture.
/// Without a value: interactively select a region (requires the `selector` feature).
/// With a value: parse the geometry string in slurp/grim format "x,y widthxheight".
/// Example: wayshot -g "$(slurp)" or wayshot -g "783,746 177x251"
#[arg(short, long, value_name = "GEOMETRY", num_args = 0..=1, verbatim_doc_comment)]
pub geometry: Option<Option<String>>,
/// Background color (rgba hex) while selecting a region (geometry).
/// Example: #00000050
#[arg(long, value_name = "HEX_COLOR")]
pub geometry_background_color: Option<String>,
/// Foreground color (rgba hex) while selecting a region (geometry).
/// Example: #ffffffff
#[arg(long, value_name = "HEX_COLOR")]
pub geometry_foreground_color: Option<String>,
/// Capture a specific output/display by name.
#[arg(short, long, conflicts_with = "geometry")]
pub output: Option<String>,
/// Interactively choose an output/display to capture.
#[arg(long, alias = "choose-output", conflicts_with_all = ["geometry", "output"])]
pub choose_output: bool,
/// Capture a specific toplevel window by its "app_id title" string.
#[arg(long, alias = "window", conflicts_with_all = ["geometry", "output", "choose_output", "choose_toplevel"])]
pub toplevel: Option<String>,
/// Interactively choose a toplevel window to capture.
#[arg(long, alias = "choose-window", conflicts_with_all = ["geometry", "output", "choose_output", "toplevel"])]
pub choose_toplevel: bool,
// ─── Capture options (how to capture) ────────────────────────────────────
/// Include the cursor in the screenshot.
#[arg(short, long)]
pub cursor: bool,
/// Do not freeze the screen when selecting a region (geometry) or a point (color picker).
/// Selection happens on the live display; the capture is taken after selection.
#[arg(long)]
pub no_freeze: bool,
/// Wait this many milliseconds before taking the screenshot. No delay when unset.
#[arg(long, value_name = "MS")]
pub delay: Option<u32>,
// ─── Output options (where/how to save the image) ─────────────────────────
/// Image encoding format. Defaults to the FILE extension, then to `png`.
#[arg(
long,
verbatim_doc_comment,
visible_aliases = ["extension", "format", "file-format"],
value_name = "FILE_EXTENSION"
)]
pub encoding: Option<EncodingFormat>,
/// `strftime`-style format for the output file name.
/// Defaults to `wayshot-%Y_%m_%d-%H_%M_%S`.
#[arg(long, verbatim_doc_comment)]
pub file_name_format: Option<String>,
/// Copy the screenshot to the Wayland clipboard.
/// Wayshot stays in the background offering the image until it is overwritten.
#[cfg(feature = "clipboard")]
#[arg(long, verbatim_doc_comment)]
pub clipboard: bool,
// ─── Notification options ─────────────────────────────────────────────────
/// Silents notification after screenshot
#[cfg(feature = "notifications")]
#[arg(long, alias = "no-notifications")]
pub silent: bool,
// ─── Global options ───────────────────────────────────────────────────────
/// Path to the config file. Defaults to:
/// 1. `$XDG_CONFIG_HOME/wayshot/config.toml`
/// 2. `$HOME/wayshot/config.toml`
/// 3. Built-in defaults when no file is found.
#[arg(long, verbatim_doc_comment)]
pub config: Option<PathBuf>,
/// Log level written to stderr.
#[cfg(feature = "logger")]
#[arg(long)]
pub log_level: Option<Level>,
}