#[macro_export]
macro_rules! run_external {
($cmd:tt) => {{
Box::new(move |_: &mut $crate::core::manager::WindowManager<_>| {
$crate::core::helpers::spawn($cmd)
}) as $crate::core::bindings::KeyEventHandler<_>
}};
}
#[macro_export]
macro_rules! run_internal {
($func:ident) => {
Box::new(|wm: &mut $crate::core::manager::WindowManager<_>| {
wm.$func()
}) as $crate::core::bindings::KeyEventHandler<_>
};
($func:ident, $($arg:expr),+) => {
Box::new(move |wm: &mut $crate::core::manager::WindowManager<_>| {
wm.$func($($arg),+)
}) as $crate::core::bindings::KeyEventHandler<_>
};
}
#[macro_export]
macro_rules! spawn {
{ $cmd:expr } => {
$crate::core::helpers::spawn($cmd)
};
{ $cmd:expr, $($arg:expr),+ } => {
$crate::core::helpers::spawn_with_args($cmd, &[$($arg),+])
};
}
#[macro_export]
macro_rules! spawn_for_output {
{ $cmd:expr } => {
$crate::core::helpers::spawn_for_output($cmd).map(|s|
s.trim().split('\n').map(String::from).collect::<Vec<String>>()
)
};
{ $cmd:expr, $($arg:expr),+ } => {
$crate::core::helpers::spawn_for_output_with_args($cmd, &[$($arg),+]).map(|s|
s.trim().split('\n').map(String::from).collect::<Vec<String>>()
)
};
}
#[macro_export]
macro_rules! map {
{} => { ::std::collections::HashMap::new() };
{ $($key:expr => $value:expr),+, } => {
{
let mut _map = ::std::collections::HashMap::new();
$(_map.insert($key, $value);)+
_map
}
};
}
#[macro_export]
macro_rules! gen_keybindings {
{ $($tokens:tt)* } => {
{
let mut map = ::std::collections::HashMap::new();
let codes = $crate::core::helpers::keycodes_from_xmodmap();
let parse = $crate::xcb::helpers::parse_key_binding;
__private!(@parsekey map, codes, parse, [], [], $($tokens)*);
map
}
};
}
#[macro_export]
macro_rules! gen_mousebindings {
{
$($kind:ident $button:ident + [$($modifier:ident),+] => $action:expr),+
} => {
{
let mut _map = ::std::collections::HashMap::new();
$(
let mut modifiers = Vec::new();
$(modifiers.push($crate::core::bindings::ModifierKey::$modifier);)+
let state = $crate::core::bindings::MouseState::new(
$crate::core::bindings::MouseButton::$button,
modifiers
);
let kind = $crate::core::bindings::MouseEventKind::$kind;
_map.insert(
(kind, state),
Box::new($action) as $crate::core::bindings::MouseEventHandler<_>
);
)+
_map
}
};
}
#[macro_export]
macro_rules! perror {
($msg:expr) => {
$crate::PenroseError::Raw($msg.to_string())
};
($template:expr, $($arg:expr),+) => {
$crate::PenroseError::Raw(format!($template, $($arg),+))
};
}
macro_rules! str_slice {
($string_vec:expr) => {
&$string_vec.iter().map(AsRef::as_ref).collect::<Vec<&str>>()
};
}
macro_rules! strings {
{ $($arg:expr),+ } => { vec![$(format!("{:?}", $arg)),+] }
}
macro_rules! cast_slice {
($s:expr, $t:ty) => {
$s.iter().map(|&v| v as $t).collect::<Vec<$t>>()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __with_builder_and_getters {
{
$(#[$struct_outer:meta])*
$name:ident;
$(#[$builder_outer:meta])*
$builder_name:ident;
$(
$(#[$field_outer:meta])*
$(VecImplInto $vecintofield:ident : $vecintoty:ty;)?
$(ImplInto $intofield:ident : $intoty:ty;)?
$(ImplTry $errty:ty; $tryfield:ident : $tryty:ty;)?
$(Concrete $field:ident : $ty:ty;)?
=> $default:expr;
)+
} => {
$(#[$struct_outer])*
pub struct $name {
$(
pub(crate)
$($vecintofield : Vec<$vecintoty>,)?
$($intofield : $intoty,)?
$($tryfield : $tryty,)?
$($field: $ty,)?
)+
}
impl $name {
pub fn builder(&self) -> $builder_name {
$builder_name {
inner: self.clone(),
}
}
$(
$(#[$field_outer])*
$(pub fn $vecintofield(&self) -> &Vec<$vecintoty> {
&self.$vecintofield
})?
$(pub fn $intofield(&self) -> &$intoty {
&self.$intofield
})?
$(pub fn $tryfield(&self) -> &$tryty {
&self.$tryfield
})?
$(pub fn $field(&self) -> &$ty {
&self.$field
})?
)+
}
impl Default for $name {
fn default() -> Self {
Self {
$(
$($vecintofield: $default.into_iter().map(|e| e.into()).collect(),)?
$($intofield: $default.into(),)?
$($tryfield: $default.try_into().unwrap(),)?
$($field: $default,)?
)+
}
}
}
$(#[$builder_outer])*
pub struct $builder_name {
inner: $name,
}
impl $builder_name {
pub fn build(&self) -> std::result::Result<$name, String> {
self.validate()?;
Ok(self.inner.clone())
}
$(
$(#[$field_outer])*
$(pub fn $vecintofield<T, U>(&mut self, val: T) -> &mut $builder_name
where
T: IntoIterator<Item = U>,
U: Into<$vecintoty>,
{
self.inner.$vecintofield = val.into_iter().map(|elem| elem.into()).collect();
self
})?
$(pub fn $intofield<T>(&mut self, val: T) -> &mut $builder_name
where
T: Into<$intoty>
{
self.inner.$intofield = val.into();
self
})?
$(pub fn $tryfield<T>(&mut self, val: T) -> crate::Result<&mut $builder_name>
where
T: TryInto<$tryty, Error=$errty>,
{
self.inner.$tryfield = val.try_into()?;
Ok(self)
})?
$(pub fn $field(&mut self, val: $ty) -> &mut $builder_name {
self.inner.$field = val;
self
})?
)+
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_stub_xcon {
{
for $struct:ident;
atom_queries: { $($atomquery:tt)* }
client_properties: { $($cprops:tt)* }
client_handler: { $($chandler:tt)* }
client_config: { $($cconfig:tt)* }
event_handler: { $($ehandler:tt)* }
state: { $($state:tt)* }
conn: { $($conn:tt)* }
} => {
impl $crate::core::xconnection::StubXAtomQuerier for $struct { $($atomquery)* }
impl $crate::core::xconnection::StubXClientProperties for $struct { $($cprops)* }
impl $crate::core::xconnection::StubXClientHandler for $struct { $($chandler)* }
impl $crate::core::xconnection::StubXClientConfig for $struct { $($cconfig)* }
impl $crate::core::xconnection::StubXEventHandler for $struct { $($ehandler)* }
impl $crate::core::xconnection::StubXState for $struct { $($state)* }
impl $crate::core::xconnection::StubXConn for $struct { $($conn)* }
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! test_cases {
{
$test_name:ident;
args: ( $($arg:ident: $t:ty),* $(,)? );
$(
case: $case_name:ident => ( $($param:expr),* );
)+
body: $body:expr
} => {
paste::paste! {
fn [<$test_name _helper>]($($arg: $t),*) {
$body
}
}
$(
paste::paste! {
#[test]
fn [<$test_name _ $case_name>]() {
[<$test_name _helper>]($($param),*)
}
}
)+
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private {
{ @parsekey $map:expr, $codes:expr, $parse:expr,
[ $($patt:expr,)* ], [ $(($($template:expr),+; $($name:expr),+)),* ],
map: { $($str:expr),+ } to $to:expr => {
$( $binding:expr => $method:ident ( $($params:tt)* ); )+
};
$($tail:tt)*
} => {
{
let keynames = &[$($str),+];
$(
for (name, arg) in keynames.iter().zip($to.into_iter()) {
let binding = format!($binding, name);
match $parse(binding.clone(), &$codes) {
None => panic!("invalid key binding: {}", binding),
Some(key_code) => $map.insert(
key_code,
run_internal!(
$method,
__private!(@parsemapparams arg; []; $($params,)*)
)
),
};
}
)+
__private!(@parsekey $map, $codes, $parse,
[ $($patt,)* ], [ $(($($template),+; $($name),+),)* ($($binding),+; $($str),+) ],
$($tail)*
);
}
};
{ @parsekey $map:expr, $codes:expr, $parse:expr,
[ $($patt:expr,)* ], [ $(($($template:expr),+; $($name:expr),+)),* ],
$binding:expr => $action:expr;
$($tail:tt)*
} => {
match $parse($binding.to_string(), &$codes) {
None => panic!("invalid key binding: {}", $binding),
Some(key_code) => $map.insert(key_code, $action),
};
__private!(@parsekey $map, $codes, $parse,
[ $binding, $($patt,)* ], [ $(($($template),+; $($name),+)),* ],
$($tail)*
);
};
{ @parsekey $map:expr, $codes:expr, $parse:expr,
[ $($patt:expr,)* ], [ $(($($template:expr),+; $($name:expr),+)),* ],
$(refmap)? $(map)? [ $from:expr ] in { $($binding:expr => $method:ident [ $to:expr ];)+ };
$($tail:tt)*
} => {
compile_error!(
"the '(ref)map [ <impl Iterator> ] in { ... }' pattern is deprecated: please use \
'map: { ... } to <impl Iterator> => { ... }' instead. Examples are available in \
the documentation for the 'gen_keybindings' macro."
)
};
{ @parsekey $map:expr, $codes:expr, $parse:expr,
[ $($patt:expr,)* ], [ $(($($template:expr),+; $($name:expr),+)),* ],
$($tail:tt)*
} => {
$(compile_error!(stringify!("unexpected tokens in gen_keybindings macro: " $tail));)*
validate_user_bindings!(
( $($patt),* )
( $((($($template),+) ($($name),+)))* )
)
};
{ @parsemapparams $replacement:expr; [ $(,$arg:expr)* ];
REF, $($params:tt)*
} => {
__private!(@parsemapparams $replacement; [$($arg),* , &$replacement]; $($params)*)
};
{ @parsemapparams $replacement:expr; [ $(,$arg:expr)* ];
VAL, $($params:tt)*
} => {
__private!(@parsemapparams $replacement; [$($arg),* , $replacement]; $($params)*)
};
{ @parsemapparams $replacement:expr; [ $(,$arg:expr),* ];
$expr:expr, $($params:tt)*
} => {
__private!(@parsemapparams $replacement; [$($arg),* , $expr]; $($params)*)
};
{ @parsemapparams $replacement:expr; [ $(,$arg:expr)* ]; } => { $($arg),* };
}