From e96b453f33345ba08c8150192157077f310f1b01 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Mon, 20 Aug 2018 10:51:54 +0200 Subject: Parse multiple maps and modes intermixed Create a new `Definition` item type that groups `Map` and `Mode` into a single type that we can expect on a parser. This allows us to make a parser that can parse both modes & maps. A bunch of failed attempts, but finally managed to get something working, yay! --- src/lib.rs | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 7cb2444..6adfd3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,12 @@ pub struct MapGroup { modes: HashMap, } +#[derive(Debug, PartialEq)] +enum Definition { + Map(Map), + Mode(Mode), +} + fn map_kind() -> impl Parser where @@ -177,6 +183,95 @@ where ) } +fn definitions() -> impl Parser> +where + I: Stream, + I::Error: ParseError, +{ + // many::, _>( + // map() + // .map(|map| Definition::Map(map)) + // .or( + // mode() + // .map(|mode| Definition::Mode(mode)) + // .skip(blank()) + // ) + // .skip(blank()) + // ) + + // many( + // choice!( + // map(), + // mode(), + // blank() + // ) + // ) + + // many::, _>( + // many( + // choice!( + // map() + // .skip(blank()) + // .map(|map| Definition::Map(map)), + // mode() + // .skip(blank()) + // .map(|mode| Definition::Mode(mode)) + // ) + // ) + + // choice!( + // many( + // map() + // .skip(blank()) + // .map(|map| Definition::Map(map)) + // ), + // many( + // mode() + // .skip(blank()) + // .map(|mode| Definition::Mode(mode)) + // ) + // ) + + // many( + // try( + // map().map(|map| Definition::Map(map)) + // .skip(blank()) + // ).or( + // try( + // mode().map(|mode| Definition::Mode(mode)) + // .skip(blank()) + // ) + // ) + // ) + + // many( + // map().map(|map| Definition::Map(map)) + // .or( + // mode().map(|mode| Definition::Mode(mode)) + // ).skip(blank()) + // ) + + // ( + // blank(), + // many( + // choice!( + // try(map().map(|map| Definition::Map(map))), + // try(mode().map(|mode| Definition::Mode(mode))) + // ).skip(blank()) + // ) + // ).map(|(_, definitions)| definitions) + + ( + blank(), + many( + choice!( + try(map()).map(|map| Definition::Map(map)), + try(mode()).map(|mode| Definition::Mode(mode)) + ).skip(blank()) + ) + ).map(|(_, definitions)| definitions) +} + fn map_group() -> impl Parser where I: Stream, @@ -368,6 +463,64 @@ cmd /usr/bin/say 'hello' assert_eq!(result, Ok(expected)); } + #[test] + fn definitions_parses_modes_and_maps() { + let text = " + +mode { + cmd j +} +map m +mode { + cmd j +} + +map k +"; + let result = definitions().easy_parse(text).map(|t| t.0); + + let mut mode_up_maps = HashMap::new(); + mode_up_maps.insert( + vec![HeadphoneButton::Down], + MapAction { + action: "j".to_owned(), + kind: MapKind::Command, + } + ); + + let mut mode_down_up_maps = HashMap::new(); + mode_down_up_maps.insert( + vec![HeadphoneButton::Down], + MapAction { + action: "j".to_owned(), + kind: MapKind::Command, + } + ); + + let expected = vec![ + Definition::Mode(Mode { + trigger: vec![HeadphoneButton::Up], + maps: mode_up_maps, + }), + Definition::Map(Map { + trigger: vec![HeadphoneButton::Play], + action: "m".to_owned(), + kind: MapKind::Map, + }), + Definition::Mode(Mode { + trigger: vec![HeadphoneButton::Down, HeadphoneButton::Up], + maps: mode_down_up_maps, + }), + Definition::Map(Map { + trigger: vec![HeadphoneButton::Down], + action: "k".to_owned(), + kind: MapKind::Map, + }), + ]; + + assert_eq!(result, Ok(expected)); + } + #[test] fn map_group_parses_a_whole_map_file_string() { let text = "map some text -- cgit v1.2.3