aboutsummaryrefslogtreecommitdiff
path: root/src/socket
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-11-28 22:16:43 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-11-28 22:16:43 -0300
commite1ec354306742a5804a20e2651cf49945cd17287 (patch)
tree7f607096fa43f96680d933b7a046f603227e566c /src/socket
parent901d03b3a8ac0b7d8533fd9a8d43238d665d9cb8 (diff)
downloaddotwm-e1ec354306742a5804a20e2651cf49945cd17287.tar.gz
Better socket handling
The socket interface now allows almost everything that vould be done by the internals of the window manager. Also the Window manager now closes fine (on a success exit).
Diffstat (limited to 'src/socket')
-rw-r--r--src/socket/mod.rs49
-rw-r--r--src/socket/parser.rs215
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);
+ }
}