Skip to content

Commit

Permalink
feat: add cleaner way to parse either a path or raw string
Browse files Browse the repository at this point in the history
  • Loading branch information
lavafroth committed Jul 4, 2024
1 parent c23baca commit cc94c41
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
27 changes: 20 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use itertools::Itertools;
use pest::{iterators::Pair, Parser};
use pest_derive::Parser;
use range::Bounds;
use std::{collections::BTreeSet, fmt::Display, fs};
use std::{collections::BTreeSet, fmt::Display, fs, path::Path};
use thiserror::Error;
mod range;
pub mod token;
Expand All @@ -16,6 +16,8 @@ pub enum ParseError {
Grammar(#[from] Box<pest::error::Error<Rule>>),
#[error("hotkey config must contain one and only one main section")]
MainSection,
#[error("unable to read config file")]
ReadingConfig(#[from] std::io::Error),
}

#[derive(Parser)]
Expand All @@ -37,17 +39,28 @@ pub struct SwhkdParser {
pub modes: Vec<Mode>,
}

/// Input to the grammar parser.
/// Can be either a string or a path.
pub enum ParserInput<'a> {
Raw(&'a str),
Path(&'a Path),
}

impl SwhkdParser {
pub fn from(raw: &str) -> Result<Self, ParseError> {
pub fn from(input: ParserInput) -> Result<Self, ParseError> {
let mut root_imports = BTreeSet::new();
let mut root = Self::as_import(raw, &mut root_imports)?;
let mut root = Self::as_import(input, &mut root_imports)?;
root.imports = root_imports;
Ok(root)
}
pub fn as_import(raw: &str, seen: &mut BTreeSet<String>) -> Result<Self, ParseError> {
let parse_result = SwhkdGrammar::parse(Rule::main, raw)
.map_err(|err| ParseError::Grammar(Box::new(err)))?;
// TODO: set the source for raw strings as `anonymous`
fn as_import(input: ParserInput, seen: &mut BTreeSet<String>) -> Result<Self, ParseError> {
let (raw, source) = match input {
ParserInput::Raw(s) => (s.to_string(), "<anonymous>"),
// TODO: Use mmap instead of fs::read_to_string
ParserInput::Path(p) => (fs::read_to_string(p)?, p.to_str().unwrap_or_default()),
};
let parse_result = SwhkdGrammar::parse(Rule::main, &raw)
.map_err(|err| ParseError::Grammar(Box::new(err.with_path(source))))?;

let Some(contents) = parse_result.into_iter().next() else {
return Err(ParseError::MainSection);
Expand Down
7 changes: 3 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use anyhow::{bail, Result};
use std::fs;
use sweet::SwhkdParser;
use std::path::Path;
use sweet::{ParserInput, SwhkdParser};

fn main() -> Result<()> {
let Some(arg) = std::env::args().nth(1) else {
bail!("please supply a path to a hotkeys config file");
};
let raw_content = fs::read_to_string(arg)?;
let parser = SwhkdParser::from(&raw_content)?;
let parser = SwhkdParser::from(ParserInput::Path(Path::new(&arg)))?;

for binding in parser.bindings {
println!("{}", binding);
Expand Down
30 changes: 15 additions & 15 deletions tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sweet::{
token::{Key, KeyAttribute, Modifier},
Binding, Definition, ParseError, SwhkdParser,
Binding, Definition, ParseError, ParserInput, SwhkdParser,
};

#[test]
Expand All @@ -9,7 +9,7 @@ fn test_basic_keybind() -> Result<(), ParseError> {
r
alacritty
";
SwhkdParser::from(&contents)?;
SwhkdParser::from(ParserInput::Raw(&contents))?;
Ok(())
}

Expand All @@ -25,7 +25,7 @@ w
t
/bin/firefox
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let known = vec![
Binding {
Expand Down Expand Up @@ -68,7 +68,7 @@ w
#t
#/bin/firefox
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let known = vec![
Binding {
Expand Down Expand Up @@ -99,7 +99,7 @@ super + 5
alacritty
";

let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;
let known = vec![Binding {
definition: Definition {
modifiers: vec![Modifier("super".to_string())],
Expand All @@ -120,7 +120,7 @@ shift + k + m
notify-send 'Hello world!'
";

assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand All @@ -130,7 +130,7 @@ shift + k + alt
notify-send 'Hello world!'
";

assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand All @@ -141,7 +141,7 @@ fn test_unfinished_plus_sign() {
shift + alt +
notify-send 'Hello world!'
";
assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand All @@ -151,7 +151,7 @@ fn test_plus_sign_at_start() {
notify-send 'Hello world!'
";

assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand All @@ -172,7 +172,7 @@ altgr + i
super + z
notify-send 'Hello world!'
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let command = "notify-send 'Hello world!'".to_string();
let known = vec![
Expand Down Expand Up @@ -224,7 +224,7 @@ fn test_command_with_many_spaces() -> Result<(), ParseError> {
p
xbacklight -inc 10 -fps 30 -time 200
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let known = vec![Binding {
definition: Definition {
Expand All @@ -249,7 +249,7 @@ pesto
xterm
";

assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand All @@ -264,7 +264,7 @@ w
";

assert!(SwhkdParser::from(&contents).is_err());
assert!(SwhkdParser::from(ParserInput::Raw(&contents)).is_err());
}

#[test]
Expand Down Expand Up @@ -292,7 +292,7 @@ ctrl + 0
super + minus
play-song.sh album
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let known = vec![
Binding {
Expand Down Expand Up @@ -352,7 +352,7 @@ k
mpc ls | dmenu | \\
sed -i 's/foo/bar/g'
";
let parsed = SwhkdParser::from(&contents)?;
let parsed = SwhkdParser::from(ParserInput::Raw(&contents))?;

let known = vec![Binding {
definition: Definition {
Expand Down

0 comments on commit cc94c41

Please sign in to comment.