mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-07 13:35:14 +02:00
refactor(komorebic): gen more clap boilerplate
Following on from the last commit, I jumped on the Rust Community Discord and @danielhenrymantilla was kind enough to show me a working example of how an optional macro argument can be used together with cfg_attr to conditionally add a doc comment. I took his example and reworked it a little, in the process refactoring all the macros in the komorebic crate to give them a sense of internal consistency.
This commit is contained in:
+81
-65
@@ -9,6 +9,7 @@ use clap::ArgEnum;
|
|||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use color_eyre::eyre::ContextCompat;
|
use color_eyre::eyre::ContextCompat;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
use paste::paste;
|
||||||
use uds_windows::UnixListener;
|
use uds_windows::UnixListener;
|
||||||
use uds_windows::UnixStream;
|
use uds_windows::UnixStream;
|
||||||
|
|
||||||
@@ -39,38 +40,84 @@ impl From<BooleanState> for bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! gen_enum_subcommand {
|
macro_rules! gen_enum_subcommand_args {
|
||||||
($name:ident, $element:ty) => {
|
// SubCommand Pattern: Enum Type
|
||||||
paste::paste! {
|
( $( $name:ident: $element:ty ),+ ) => {
|
||||||
#[derive(clap::Clap)]
|
$(
|
||||||
pub struct $name {
|
paste! {
|
||||||
#[clap(arg_enum)]
|
#[derive(clap::Clap)]
|
||||||
[<$element:snake>]: $element
|
pub struct $name {
|
||||||
|
#[clap(arg_enum)]
|
||||||
|
[<$element:snake>]: $element
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_enum_subcommand!(Focus, OperationDirection);
|
gen_enum_subcommand_args! {
|
||||||
gen_enum_subcommand!(Move, OperationDirection);
|
Focus: OperationDirection,
|
||||||
gen_enum_subcommand!(Stack, OperationDirection);
|
Move: OperationDirection,
|
||||||
gen_enum_subcommand!(CycleStack, CycleDirection);
|
Stack: OperationDirection,
|
||||||
gen_enum_subcommand!(WatchConfiguration, BooleanState);
|
CycleStack: CycleDirection,
|
||||||
gen_enum_subcommand!(FlipLayout, LayoutFlip);
|
FlipLayout: LayoutFlip,
|
||||||
gen_enum_subcommand!(FocusFollowsMouse, BooleanState);
|
WatchConfiguration: BooleanState,
|
||||||
|
FocusFollowsMouse: BooleanState
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! gen_target_subcommands {
|
macro_rules! gen_target_subcommand_args {
|
||||||
|
// SubCommand Pattern
|
||||||
( $( $name:ident ),+ ) => {
|
( $( $name:ident ),+ ) => {
|
||||||
$(
|
$(
|
||||||
#[derive(clap::Clap)]
|
#[derive(clap::Clap)]
|
||||||
pub struct $name {
|
pub struct $name {
|
||||||
|
/// Target index (zero-indexed)
|
||||||
target: usize,
|
target: usize,
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_target_subcommands!(MoveToMonitor, MoveToWorkspace, FocusMonitor, FocusWorkspace);
|
gen_target_subcommand_args! {
|
||||||
|
MoveToMonitor,
|
||||||
|
MoveToWorkspace,
|
||||||
|
FocusMonitor,
|
||||||
|
FocusWorkspace
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thanks to @danielhenrymantilla for showing me how to use cfr_attr with an optional argument like
|
||||||
|
// this on the Rust Programming Language Community Discord Server
|
||||||
|
macro_rules! gen_workspace_subcommand_args {
|
||||||
|
// Workspace Property: #[enum] Value Enum (if the value is an Enum)
|
||||||
|
// Workspace Property: Value Type (if the value is anything else)
|
||||||
|
( $( $name:ident: $(#[enum] $(@$arg_enum:tt)?)? $value:ty ),+ ) => (
|
||||||
|
paste! {
|
||||||
|
$(
|
||||||
|
#[derive(clap::Clap)]
|
||||||
|
pub struct [<Workspace $name>] {
|
||||||
|
/// Monitor index (zero-indexed)
|
||||||
|
monitor: usize,
|
||||||
|
|
||||||
|
/// Workspace index on the specified monitor (zero-indexed)
|
||||||
|
workspace: usize,
|
||||||
|
|
||||||
|
$(#[clap(arg_enum)] $($arg_enum)?)?
|
||||||
|
#[cfg_attr(
|
||||||
|
all($(FALSE $($arg_enum)?)?),
|
||||||
|
doc = ""$name" of the workspace as a "$value""
|
||||||
|
)]
|
||||||
|
value: $value,
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_workspace_subcommand_args! {
|
||||||
|
Name: String,
|
||||||
|
Layout: #[enum] Layout,
|
||||||
|
Tiling: #[enum] BooleanState
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
struct Resize {
|
struct Resize {
|
||||||
@@ -82,60 +129,22 @@ struct Resize {
|
|||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
struct EnsureWorkspaces {
|
struct EnsureWorkspaces {
|
||||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
/// Monitor index (zero-indexed)
|
||||||
monitor: usize,
|
monitor: usize,
|
||||||
/// Number of desired workspaces
|
/// Number of desired workspaces
|
||||||
workspace_count: usize,
|
workspace_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
struct SizeForMonitorWorkspace {
|
struct Padding {
|
||||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
/// Monitor index (zero-indexed)
|
||||||
monitor: usize,
|
monitor: usize,
|
||||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
/// Workspace index on the specified monitor (zero-indexed)
|
||||||
workspace: usize,
|
workspace: usize,
|
||||||
/// Pixels to pad with as an integer
|
/// Pixels to pad with as an integer
|
||||||
size: i32,
|
size: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
|
||||||
struct WorkspaceName {
|
|
||||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
|
||||||
monitor: usize,
|
|
||||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
|
||||||
workspace: usize,
|
|
||||||
/// Name of the workspace as a string
|
|
||||||
value: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clap)]
|
|
||||||
struct WorkspaceLayout {
|
|
||||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
|
||||||
monitor: usize,
|
|
||||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
|
||||||
workspace: usize,
|
|
||||||
#[clap(arg_enum)]
|
|
||||||
layout: Layout,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clap)]
|
|
||||||
struct WorkspaceTiling {
|
|
||||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
|
||||||
monitor: usize,
|
|
||||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
|
||||||
workspace: usize,
|
|
||||||
#[clap(arg_enum)]
|
|
||||||
tile: BooleanState,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clap)]
|
|
||||||
struct ApplicationTarget {
|
|
||||||
#[clap(arg_enum)]
|
|
||||||
identifier: ApplicationIdentifier,
|
|
||||||
/// Identifier as a string
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
struct PaddingAdjustment {
|
struct PaddingAdjustment {
|
||||||
#[clap(arg_enum)]
|
#[clap(arg_enum)]
|
||||||
@@ -144,6 +153,14 @@ struct PaddingAdjustment {
|
|||||||
adjustment: i32,
|
adjustment: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clap)]
|
||||||
|
struct ApplicationTarget {
|
||||||
|
#[clap(arg_enum)]
|
||||||
|
identifier: ApplicationIdentifier,
|
||||||
|
/// Identifier as a string
|
||||||
|
id: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
#[clap(version = "0.1.0", author = "Jade Iqbal <jadeiqbal@fastmail.com>")]
|
#[clap(version = "0.1.0", author = "Jade Iqbal <jadeiqbal@fastmail.com>")]
|
||||||
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
||||||
@@ -208,10 +225,10 @@ enum SubCommand {
|
|||||||
EnsureWorkspaces(EnsureWorkspaces),
|
EnsureWorkspaces(EnsureWorkspaces),
|
||||||
/// Set the container padding for the specified workspace
|
/// Set the container padding for the specified workspace
|
||||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
ContainerPadding(SizeForMonitorWorkspace),
|
ContainerPadding(Padding),
|
||||||
/// Set the workspace padding for the specified workspace
|
/// Set the workspace padding for the specified workspace
|
||||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
WorkspacePadding(SizeForMonitorWorkspace),
|
WorkspacePadding(Padding),
|
||||||
/// Set the layout for the specified workspace
|
/// Set the layout for the specified workspace
|
||||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
WorkspaceLayout(WorkspaceLayout),
|
WorkspaceLayout(WorkspaceLayout),
|
||||||
@@ -313,19 +330,18 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
SubCommand::WorkspaceLayout(arg) => {
|
SubCommand::WorkspaceLayout(arg) => {
|
||||||
send_message(
|
send_message(
|
||||||
&*SocketMessage::WorkspaceLayout(arg.monitor, arg.workspace, arg.layout)
|
&*SocketMessage::WorkspaceLayout(arg.monitor, arg.workspace, arg.value)
|
||||||
.as_bytes()?,
|
.as_bytes()?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
SubCommand::WorkspaceTiling(arg) => {
|
SubCommand::WorkspaceTiling(arg) => {
|
||||||
send_message(
|
send_message(
|
||||||
&*SocketMessage::WorkspaceTiling(arg.monitor, arg.workspace, arg.tile.into())
|
&*SocketMessage::WorkspaceTiling(arg.monitor, arg.workspace, arg.value.into())
|
||||||
.as_bytes()?,
|
.as_bytes()?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
SubCommand::Start => {
|
SubCommand::Start => {
|
||||||
let script = r#"Start-Process komorebi -WindowStyle hidden"#;
|
match powershell_script::run("Start-Process komorebi -WindowStyle hidden", true) {
|
||||||
match powershell_script::run(script, true) {
|
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
println!("{}", output);
|
println!("{}", output);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user