util.rs (7242B)
1 use crate::change::Change; 2 use crate::change::Direction; 3 use crate::identify::Index; 4 5 use winsys::input::Button; 6 use winsys::input::Modifier; 7 8 use std::cmp::Ord; 9 use std::hash::BuildHasher; 10 use std::hash::Hasher; 11 use std::ops::Add; 12 use std::ops::AddAssign; 13 use std::ops::Mul; 14 use std::ops::MulAssign; 15 use std::ops::Sub; 16 use std::ops::SubAssign; 17 use std::process::Command; 18 use std::process::Stdio; 19 20 use x11rb::protocol::xproto::ModMask; 21 22 #[derive(Default)] 23 pub struct IdHasher { 24 state: u64, 25 } 26 27 impl Hasher for IdHasher { 28 #[inline] 29 fn write( 30 &mut self, 31 bytes: &[u8], 32 ) { 33 for &byte in bytes { 34 self.state = self.state.rotate_left(8) + u64::from(byte); 35 } 36 } 37 38 #[inline] 39 fn finish(&self) -> u64 { 40 self.state 41 } 42 } 43 44 #[derive(Default, Clone)] 45 pub struct BuildIdHasher; 46 47 impl BuildHasher for BuildIdHasher { 48 type Hasher = IdHasher; 49 50 #[inline] 51 fn build_hasher(&self) -> Self::Hasher { 52 Self::Hasher { 53 state: 0, 54 } 55 } 56 } 57 58 pub struct Util; 59 60 impl Util { 61 #[inline] 62 pub fn last_index(iter: impl ExactSizeIterator) -> Index { 63 if iter.len() != 0 { 64 iter.len() - 1 65 } else { 66 0 67 } 68 } 69 70 #[inline] 71 pub fn next_index( 72 iter: impl ExactSizeIterator, 73 index: Index, 74 dir: Direction, 75 ) -> Index { 76 match dir { 77 Direction::Forward => (index + 1) % iter.len(), 78 Direction::Backward => { 79 if index == 0 { 80 iter.len() - 1 81 } else { 82 index - 1 83 } 84 }, 85 } 86 } 87 88 #[inline] 89 pub fn change_within_range<T>( 90 min: T, 91 max: T, 92 mut base: T, 93 change: Change<T>, 94 ) -> T 95 where 96 T: Ord 97 + Add<Output = T> 98 + AddAssign 99 + Mul<Output = T> 100 + MulAssign 101 + Sub<Output = T> 102 + SubAssign 103 + Copy, 104 { 105 match change { 106 Change::Inc(delta) => { 107 base += delta; 108 if base > max { 109 max 110 } else { 111 base 112 } 113 }, 114 Change::Dec(delta) => { 115 if base >= min + delta { 116 base - delta 117 } else { 118 min 119 } 120 }, 121 } 122 } 123 124 pub fn spawn<S: Into<String>>(cmd: S) { 125 let cmd = cmd.into(); 126 let args: Vec<&str> = cmd.split_whitespace().collect(); 127 128 if args.len() > 1 { 129 Command::new(args[0]) 130 .args(&args[1..]) 131 .stdout(Stdio::null()) 132 .stderr(Stdio::null()) 133 .spawn() 134 .ok(); 135 } else { 136 Command::new(args[0]) 137 .stdout(Stdio::null()) 138 .stderr(Stdio::null()) 139 .spawn() 140 .ok(); 141 }; 142 } 143 144 pub fn spawn_shell<S: Into<String>>(cmd: S) { 145 let cmd = cmd.into(); 146 147 Command::new("sh") 148 .arg("-c") 149 .arg(cmd) 150 .stdout(Stdio::null()) 151 .stderr(Stdio::null()) 152 .spawn() 153 .ok(); 154 } 155 156 // pub fn system_keycodes() -> CodeMap { 157 // match Command::new("xmodmap").arg("-pke").output() { 158 // Err(e) => panic!("unable to fetch keycodes via xmodmap: {}", e), 159 // Ok(o) => match String::from_utf8(o.stdout) { 160 // Err(e) => panic!("invalid utf8 from xmodmap: {}", e), 161 // Ok(s) => s 162 // .lines() 163 // .flat_map(|l| { 164 // let mut words = l.split_whitespace(); 165 // let key_code: u8 = words.nth(1).unwrap().parse().unwrap(); 166 167 // words.skip(1).map(move |name| (name.into(), key_code)) 168 // }) 169 // .collect::<CodeMap>(), 170 // }, 171 // } 172 // } 173 174 // pub fn parse_key_binding( 175 // key_binding: impl Into<String>, 176 // keycodes: &CodeMap, 177 // ) -> Option<KeyCode> { 178 // let s = key_binding.into(); 179 // let mut constituents: Vec<&str> = s.split('-').collect(); 180 181 // match keycodes.get(constituents.remove(constituents.len() - 1)) { 182 // Some(&code) => { 183 // let mask = constituents 184 // .iter() 185 // .map(|&modifier| match modifier { 186 // "A" | "Alt" | "Meta" => u16::from(ModMask::M1), 187 // "M" | "Super" => u16::from(ModMask::M4), 188 // "S" | "Shift" => u16::from(ModMask::SHIFT), 189 // "C" | "Ctrl" | "Control" => u16::from(ModMask::CONTROL), 190 // "1" | "Mod" => u16::from(if cfg!(debug_assertions) { 191 // ModMask::M1 192 // } else { 193 // ModMask::M4 194 // }), 195 // "2" | "Sec" => u16::from(if cfg!(debug_assertions) { 196 // ModMask::M4 197 // } else { 198 // ModMask::M1 199 // }), 200 // _ => panic!("invalid modifier: {}", s), 201 // }) 202 // .fold(0, |acc, modifier| acc | modifier); 203 204 // Some(KeyCode { 205 // mask, 206 // code, 207 // }) 208 // }, 209 // None => None, 210 // } 211 // } 212 213 // pub fn parse_mouse_binding(mouse_binding: impl Into<String>) -> Option<MouseShortcut> { 214 // let s = mouse_binding.into(); 215 // let mut constituents: Vec<&str> = s.split('-').collect(); 216 217 // let button = match constituents.remove(constituents.len() - 1) { 218 // "1" | "Left" => Button::Left, 219 // "2" | "Middle" => Button::Middle, 220 // "3" | "Right" => Button::Right, 221 // "4" | "ScrollUp" => Button::ScrollUp, 222 // "5" | "ScrollDown" => Button::ScrollDown, 223 // "8" | "Backward" => Button::Backward, 224 // "9" | "Forward" => Button::Forward, 225 // s => panic!("invalid button: {}", s), 226 // }; 227 228 // let mut modifiers = constituents 229 // .iter() 230 // .map(|&modifier| match modifier { 231 // "A" | "Alt" | "Meta" => Modifier::Alt, 232 // "AGr" | "AltGr" => Modifier::AltGr, 233 // "M" | "Super" => Modifier::Super, 234 // "S" | "Shift" => Modifier::Shift, 235 // "C" | "Ctrl" | "Control" => Modifier::Ctrl, 236 // "N" | "NumLock" => Modifier::NumLock, 237 // "L" | "ScrollLock" => Modifier::ScrollLock, 238 // "1" | "Mod" => { 239 // if cfg!(debug_assertions) { 240 // Modifier::Alt 241 // } else { 242 // Modifier::Super 243 // } 244 // }, 245 // "2" | "Sec" => { 246 // if cfg!(debug_assertions) { 247 // Modifier::Super 248 // } else { 249 // Modifier::Alt 250 // } 251 // }, 252 // _ => panic!("invalid modifier: {}", s), 253 // }) 254 // .collect::<Vec<Modifier>>(); 255 256 // modifiers.sort(); 257 258 // Some(MouseShortcut { 259 // button, 260 // modifiers, 261 // }) 262 // } 263 }