From fb9bfdeda81772e8f5998c4bb337275f3200d153 Mon Sep 17 00:00:00 2001 From: rick Date: Mon, 10 Apr 2023 19:43:12 +0200 Subject: [PATCH] first files --- .gitignore | 41 ++++++++++ Cargo.toml | 9 +++ src/buffer.rs | 61 +++++++++++++++ src/main.rs | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/buffer.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..985606c --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Created by https://www.toptal.com/developers/gitignore/api/vim,rust +# Edit at https://www.toptal.com/developers/gitignore?templates=vim,rust + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +# End of https://www.toptal.com/developers/gitignore/api/vim,rust diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8ec2e0e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "red" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nom = "7.1.3" diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 0000000..b50d214 --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,61 @@ +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::io::prelude::*; +use std::io; +use nom::bytes::complete::{tag, take_while, take_till}; +use nom::character::complete::one_of; +use nom::sequence::Tuple; +use nom::branch::alt; +use nom::error::ErrorKind; +use nom::error::Error; + +pub struct Buffer { + has_changed: bool, + buffer: Vec>, + current_line: usize, +} + +impl Buffer { + pub fn new(buffer: Vec>) -> Self { + let tmp = buffer.len().saturating_sub(1); + Self { + has_changed: false, + buffer, + current_line: tmp + } + } + + // Return the actual line of the buffer + pub fn act(&self) -> usize { + self.current_line + } + + // change la ligne actuelle + pub fn change_act(&mut self, new: usize) { + // TODO check si > len + self.current_line = new; + } + + // affiche une ligne + pub fn print_line(&self, nb: usize, print_numbers: bool) { + if nb >= self.buffer.len() { + println!("?"); + } else if let Ok(line) = &self.buffer[nb] { + if print_numbers { + println!("{}\t{}", nb + 1, line); + } else { + println!("{}", line); + } + } else { + println!("?"); + } + } + + // affiche plusieurs lignes + pub fn print_range(&self, first: usize, last: usize, print_numbers: bool) { + for i in first..last { + self.print_line(i, print_numbers); + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8120547 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,208 @@ +mod buffer; +pub use self::buffer::Buffer; + +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::io::prelude::*; +use std::io; +use nom::bytes::complete::{tag, take_while, take_till}; +use nom::character::complete::one_of; +use nom::sequence::Tuple; +use nom::branch::alt; +use nom::error::ErrorKind; +use nom::error::Error; + +const FILE : &'static str = "test"; + +enum Address { + Actual, + Last, + Line(u32), + FromStartTo(u32), + FromToEnd(u32), + FromTo(u32, u32), + Null, +} + +enum Command { + Append(Address), + Insert(Address), + Change(Address), + Delete(Address), + // bool pour check ou pas (e et E) TODO mettre le chemin vers le fichier + Edit(bool), + // TODO chemin vers fichier + File(), + // TODO + Help, + // TODO + SetHelp, + Join(Address), + // TODO nom de la marque + Mark(Address), + List(Address), + // TODO + Move(Address), + Number(Address), + Print(Address), + Prompt, + // bool pour check ou pas (q et Q) + Quit(bool), + // TODO + Read, + // TODO + Substitute, + // TODO + CopyLines, + Undo, + // TODO + Write, + // TODO + Line, + // TODO + ShellCommand, + // TODO + Null, + // TODO + Global, + // TODO + NonMatched, +} + +/* + * . + * $ + * [:digit:] + * '[:alpha:] + * /BRE/ + * +[:digit:] + * -[:digit:] + * [:digit:],[:digit:] + * [:digit:];[:digit:] + */ + +// TODO juste $ pour l'instant dans l'adresse +// TODO faire les commandes mais juste p pour l'instant + +/* +fn read_address(input: &str) -> Result<&str, Address> { + +} +*/ + +/* + * Le char doit ĂȘtre une commande valide. + */ + +fn parse_without_addr(c: char) -> Command { + Command::Help +} + +fn parse_with_addr(c: char, addr: Address) -> Command { + match c { + 'p' => Command::Print(addr), + 'n' => Command::Number(addr), + _ => Command::Help, + } +} + +fn parse_command(c: char, addr: Option
) -> Command { + if let Some(a) = addr { + parse_with_addr(c, a) + } else { + parse_without_addr(c) + } +} + +/* +fn parse_multi_addr(addr: &str) -> Address { + //let extract = take_till::<&str, &str, Error>(|c| c == ','); + let extract = take_till::<&str, &str, Error<&str>>(|c| c != ","); + if let Ok((still, before)) = extract(addr) { + if let Ok((still, after)) = extract(addr) { + } + } + + Address::Null +} +*/ + +fn parse_address(addr: &str) -> Address { + let mut tmp = String::from(addr); + tmp.retain(|c| c != ' '); + let addr = tmp.as_str(); + + if addr.is_empty() { + Address::Actual + } else { + match addr { + "." => Address::Actual, + "$" => Address::Last, + _ => Address::Null, + } + } +} + +fn check_address(c: char) -> bool { + c.is_digit(10) || c == '$' || c == ' ' || c == '.' +} + +fn check_address_complete(c: char) -> bool { + check_address(c) || c == ',' +} + +fn print(buffer: Buffer, addr: Address, print_numbers: bool) { + match addr { + Address::Actual => buffer.print_line(buffer.act(), print_numbers), + Address::Null => println!("nul !"), + _ => println!("coucou2"), + } +} + +fn execute_command(buffer: Buffer, c: Command) { + match c { + Command::Print(a) => print(buffer, a, false), + Command::Number(a) => print(buffer, a, true), + _ => println!("coucou"), + } +} + +fn parse_line(input: &str) -> Result { + let address = take_while(check_address_complete); + let command = one_of::<_, _, (&str, ErrorKind)>("pn"); + + //if let Ok((input, (a, c))) = alt(address, command).parse(input) { + if let Ok((input, (a, c))) = (address, command).parse(input) { + //println!("{:?} - {:?} - {:?}", input, a, c); + let addr = parse_address(a); + Ok(parse_command(c, Some(addr))) + } else { + Err(String::from("bruh moment")) + } +} + +fn main() { + let buffer : Vec> = if let Ok(f) = File::open(FILE) { + let buff = BufReader::new(f); + buff.lines().collect() + } else { + panic!("Le fichier n'existe pas."); + }; + + let buffer_struct = Buffer::new(buffer); + + println!("fichier lu !"); + + let mut input = String::new(); + match io::stdin().read_line(&mut input) { + Ok(n) => { + if let Ok(c) = parse_line(&input) { + execute_command(buffer_struct, c); + } else { + println!("coucou"); + } + }, + Err(e) => println!("error"), + } +}