diff options
Diffstat (limited to 'src/socket')
-rw-r--r-- | src/socket/mod.rs | 49 | ||||
-rw-r--r-- | src/socket/parser.rs | 215 |
2 files changed, 191 insertions, 73 deletions
diff --git a/src/socket/mod.rs b/src/socket/mod.rs index e260284..667969b 100644 --- a/src/socket/mod.rs +++ b/src/socket/mod.rs @@ -2,7 +2,6 @@ pub mod parser; -use std::io::{Read,Write}; use std::sync::mpsc::{Receiver, TryRecvError}; use unix_socket::UnixStream; @@ -10,6 +9,34 @@ use unix_socket::UnixStream; use dotwm::DotWM; use command::*; +#[derive(Debug,PartialEq)] +pub enum FnType { + Bind, + Exec, +} + +pub struct ParsedCmd<'a> { + pub f: FnType, + pub modifiers: Vec<u32>, + pub key: u32, + pub args: Vec<&'a str>, + pub func: ExecFn, +} + +impl<'a> ParsedCmd<'a> { + pub fn handle(self, wm: &mut DotWM, bindings: &mut BindingHash) { + match self.f { + FnType::Bind => { + let modifier = self.modifiers.iter() + .fold(0, |acc, x| acc | x ); + add_binding(wm, bindings, + self.key, modifier, self.func, &self.args); + }, + _ => (), + } + } +} + pub fn next_socket_event(rx: &Receiver<UnixStream>) -> Option<UnixStream> { match rx.try_recv() { Ok(stream) => Some(stream), @@ -17,23 +44,3 @@ pub fn next_socket_event(rx: &Receiver<UnixStream>) -> Option<UnixStream> { Err(TryRecvError::Disconnected) => panic!("Socket disconnected"), } } - -/// Listen a socket parsing and executing all the commands. -pub fn listen_socket(dotwm: &mut DotWM, bindings: &mut BindingHash, rx: &Receiver<UnixStream>) { - loop { - match rx.try_recv() { - Ok(stream) => { - let mut s = stream.try_clone().unwrap(); - let mut buf = String::new(); - s.read_to_string(&mut buf).unwrap(); - - for line in buf.lines() { - let result = parser::parse(dotwm, bindings, &line); - let _ = write!(s, "{}", result); - } - }, - Err(TryRecvError::Empty) => break, - Err(TryRecvError::Disconnected) => panic!("Socket disconnected"), - } - } -} diff --git a/src/socket/parser.rs b/src/socket/parser.rs index e8dd9ec..0de0248 100644 --- a/src/socket/parser.rs +++ b/src/socket/parser.rs @@ -9,94 +9,205 @@ use x11::xlib; use x11::keysym; use command::*; -use dotwm::DotWM; +use ::socket::ParsedCmd; +use ::socket::FnType; -use nom::{IResult,alpha,multispace}; -use nom::IResult::*; -use std::str; - -named!(token<&str>, - map_res!( - alpha, str::from_utf8)); +macro_rules! simple_try { + ($expr:expr) => (match $expr { + Ok(val) => val, + Err(err) => { + return Err(err) + } + }) +} -fn slice2str(input: Vec<&[u8]>) -> Vec<&str> { - let res: Vec<&str> = input.iter() - .map(|x| str::from_utf8(x).unwrap()) - .collect(); - res +fn modifier_from<'a>(s: &'a str) -> Result<u32, &'static str> { + match s { + "Mod1" => Ok(xlib::Mod4Mask), + "Mod2" => Ok(xlib::Mod4Mask), + "Mod3" => Ok(xlib::Mod4Mask), + "Mod4" => Ok(xlib::Mod4Mask), + "Control" => Ok(xlib::ControlMask), + "Shift" => Ok(xlib::ShiftMask), + _ => Err("unknown modifier"), + } } -named!(args<Vec<&str> >, - map!( - separated_list!( - multispace, alpha), - slice2str)); +fn modifiers<'a>(s: &'a str) -> Result<Vec<u32>, &'static str> { + let mut result = vec![]; -fn modifier<'a>(s: &'a str) -> Result<u32, ()> { - match s { - "Mod1Mask" => Ok(xlib::Mod4Mask), - "Mod2Mask" => Ok(xlib::Mod4Mask), - "Mod3Mask" => Ok(xlib::Mod4Mask), - "Mod4Mask" => Ok(xlib::Mod4Mask), - "ControlMask" => Ok(xlib::ControlMask), - "ShiftMask" => Ok(xlib::ShiftMask), - _ => Err(()), + for smod in s.split("-") { + let modifier = simple_try!(modifier_from(smod)); + result.push(modifier); } + + Ok(result) } -fn str_to_key<'a>(s: &'a str) -> Result<u32, ()> { +fn key<'a>(s: &'a str) -> Result<u32, &'static str> { match s { + "a" => Ok(keysym::XK_a), + "b" => Ok(keysym::XK_b), + "c" => Ok(keysym::XK_c), + "d" => Ok(keysym::XK_d), + "e" => Ok(keysym::XK_e), + "f" => Ok(keysym::XK_f), + "g" => Ok(keysym::XK_g), "h" => Ok(keysym::XK_h), + "i" => Ok(keysym::XK_i), "j" => Ok(keysym::XK_j), "k" => Ok(keysym::XK_k), "l" => Ok(keysym::XK_l), - "Tab" => Ok(keysym::XK_Tab), + "m" => Ok(keysym::XK_m), + "n" => Ok(keysym::XK_n), + "o" => Ok(keysym::XK_o), "p" => Ok(keysym::XK_p), - "Return" => Ok(keysym::XK_Return), "q" => Ok(keysym::XK_q), - _ => Err(()), + "r" => Ok(keysym::XK_r), + "s" => Ok(keysym::XK_s), + "t" => Ok(keysym::XK_t), + "u" => Ok(keysym::XK_u), + "v" => Ok(keysym::XK_v), + "w" => Ok(keysym::XK_w), + "x" => Ok(keysym::XK_x), + "y" => Ok(keysym::XK_y), + "z" => Ok(keysym::XK_z), + "A" => Ok(keysym::XK_A), + "B" => Ok(keysym::XK_B), + "C" => Ok(keysym::XK_C), + "D" => Ok(keysym::XK_D), + "E" => Ok(keysym::XK_E), + "F" => Ok(keysym::XK_F), + "G" => Ok(keysym::XK_G), + "H" => Ok(keysym::XK_H), + "I" => Ok(keysym::XK_I), + "J" => Ok(keysym::XK_J), + "K" => Ok(keysym::XK_K), + "L" => Ok(keysym::XK_L), + "M" => Ok(keysym::XK_M), + "N" => Ok(keysym::XK_N), + "O" => Ok(keysym::XK_O), + "P" => Ok(keysym::XK_P), + "Q" => Ok(keysym::XK_Q), + "R" => Ok(keysym::XK_R), + "S" => Ok(keysym::XK_S), + "T" => Ok(keysym::XK_T), + "U" => Ok(keysym::XK_U), + "V" => Ok(keysym::XK_V), + "W" => Ok(keysym::XK_W), + "X" => Ok(keysym::XK_X), + "Y" => Ok(keysym::XK_Y), + "Z" => Ok(keysym::XK_Z), + "Tab" => Ok(keysym::XK_Tab), + "Return" => Ok(keysym::XK_Return), + _ => Err("unknown key"), } } -fn str_to_func<'a>(s: &'a str) -> Result<ExecFn,()> { +fn func<'a>(s: &'a str) -> Result<ExecFn, &'static str> { match s { "exec" => Ok(exec), - "move_win" => Ok(move_win), - "resize_win" => Ok(resize_win), - _ => Err(()), + "move-win" => Ok(move_win), + "move-win-to" => Ok(move_win_to), + "resize-win" => Ok(resize_win), + "focus-next" => Ok(focus_next), + "quit" => Ok(quit_dotwm), + _ => Err("unknown function"), } } -pub fn parse<'a>(dotwm: &mut DotWM, bindings: &mut BindingHash, input: &'a str) -> &'a str { - let args: Vec<&str> = input.split_whitespace().collect(); +pub fn parse<'a>(input: &'a str) -> Result<ParsedCmd<'a>, &'static str> { + let args: Vec<&'a str> = input.split_whitespace().collect(); match args.first() { Some(cmd) => { match cmd { - &"add-binding" => { - let modifier = modifier(args[1]).unwrap(); - let key = str_to_key(args[2]).unwrap(); - let func = str_to_func(args[3]).unwrap(); - let arguments = &args[4..]; + &"bind" => { + if args.len() > 2 { + let modifiers = simple_try!(modifiers(args[1])); + let key = simple_try!(key(args[2])); + let func = simple_try!(func(args[3])); + let arguments: &[&'a str]= &args[4..]; - add_binding(dotwm, bindings, key, modifier, func, arguments); + Ok(ParsedCmd { + f: FnType::Bind, + modifiers: modifiers, + key: key, + args: arguments.to_vec(), + func: func, + }) + } else { + Err("missing arguments") + } + }, + &"exec" => { + Ok(ParsedCmd { + f: FnType::Exec, + modifiers: vec![], + key: 0, + args: vec![], + func: exec + }) + }, + _ => { + Err("unknown command") }, - &"exec" => { println!("exec"); }, - _ => { println!("anotherthing ._."); }, } }, - None => println!("error"), + None => Err("no input"), + } +} + +#[test] +fn parse_unknown() { + let res = parse("unknown"); + if let Err(e) = res { + assert_eq!(e, "unknown command"); + } else { + assert!(false); } - "ok" } #[test] -fn parse_test() { - assert_eq!(token(&b"exec"[..]), IResult::Done(&b""[..], "exec")); +fn parse_bind_modifier() { + let res = parse("bind modifier1 k exec "); + if let Err(e) = res { + assert_eq!(e, "unknown modifier"); + } else { + assert!(false); + } + + let res2 = parse("bind Mod4 k exec "); + if let Ok(modifier) = res2 { + assert_eq!(modifier.modifiers[0], xlib::Mod4Mask); + } else { + assert!(false); + } } #[test] -fn parse_args() { - assert_eq!(args(&b"hola chau"[..]), - IResult::Done(&b""[..], vec!["hola", "chau"])); +fn parse_bind_key() { + let res = parse("bind Mod4 ' exec "); + if let Err(e) = res { + assert_eq!(e, "unknown key"); + } else { + assert!(false); + } + + let res2 = parse("bind Mod4 k exec "); + if let Ok(modifier) = res2 { + assert_eq!(modifier.key, keysym::XK_k); + } else { + assert!(false); + } +} + +#[test] +fn parse_exec() { + let res = parse("exec Mod4 ' exec "); + if let Ok(pcmd) = res { + assert_eq!(pcmd.f, FnType::Exec); + } else { + assert!(false); + } } |