Skip to content

Instantly share code, notes, and snippets.

@framp
Last active December 8, 2022 18:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save framp/3388eff1d8896288133011becfbef0b0 to your computer and use it in GitHub Desktop.
Save framp/3388eff1d8896288133011becfbef0b0 to your computer and use it in GitHub Desktop.
for @ksnll with love
use std::{borrow::BorrowMut, cell::RefCell, fs, ops::Deref, rc::Rc};
use nom::{
branch::alt,
bytes::complete::{tag, take_till, take_until},
character::complete::{alpha1, char, newline, u32},
combinator::{eof, rest},
multi::many1,
sequence::{preceded, terminated, tuple},
IResult,
};
#[derive(Debug)]
enum LsNode {
Directory(String),
File(String, u32),
}
#[derive(Debug)]
struct TreeNode {
pub parent: Option<Rc<RefCell<TreeNode>>>,
pub value: LsNode,
pub children: Vec<Rc<RefCell<TreeNode>>>,
}
#[derive(Debug)]
enum Command {
Ls(Vec<LsNode>),
Cd(String),
}
fn ls_node(input: &str) -> Option<LsNode> {
let vec = input.split(' ').collect::<Vec<&str>>();
match vec[0] {
"" => None,
"dir" => Some(LsNode::Directory(vec[1].to_string())),
size @ _ => Some(LsNode::File(
vec[1].to_string(),
size.parse::<u32>().unwrap(),
)),
}
}
fn command(input: &str) -> IResult<&str, Command> {
let (input, command) = alt((tag("ls"), tag("cd")))(input)?;
let (input, arg) = alt((tag("\n"), preceded(tag(" "), take_till(|c| c == '\n'))))(input)?;
let content = input.split("\n").collect::<Vec<&str>>();
match command {
"ls" => {
let content = content
.into_iter()
.map(|content| ls_node(content))
.filter(|x| x.is_some())
.map(|x| x.unwrap())
.collect();
Ok((input, Command::Ls(content)))
}
"cd" => Ok((input, Command::Cd(String::from(arg)))),
a @ _ => panic!("Command not found {a}"),
}
}
fn main() {
let mut tree = TreeNode {
parent: None,
value: LsNode::Directory("/".to_string()),
children: vec![],
};
let mut current_position = Rc::new(RefCell::new(tree));
let input = fs::read_to_string("./inputs/07-test.txt").unwrap();
let commands_and_results = input.split("$ ");
for command_and_result in commands_and_results.skip(1) {
match command(command_and_result) {
Ok((_, Command::Cd(val))) => {
dbg!(&val, &current_position);
let parent = current_position.clone();
current_position = parent
.borrow()
.children
.iter()
.find(|x| match &x.clone().borrow().value {
LsNode::Directory(f) => *f == val,
LsNode::File(_, _) => false,
})
.unwrap()
.clone();
}
Ok((_, Command::Ls(val))) => {
for ls_node in val {
let child = Rc::new(RefCell::new(TreeNode {
parent: Some(current_position.clone()),
value: ls_node,
children: vec![],
}));
(*current_position)
.borrow_mut()
.children
.push(child.clone());
}
}
Err(_) => panic!("Command not found"),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment