first files
This commit is contained in:
commit
fb9bfdeda8
4 changed files with 319 additions and 0 deletions
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
|
@ -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
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -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"
|
61
src/buffer.rs
Normal file
61
src/buffer.rs
Normal file
|
@ -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<Result<String, io::Error>>,
|
||||||
|
current_line: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Buffer {
|
||||||
|
pub fn new(buffer: Vec<Result<String, io::Error>>) -> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
208
src/main.rs
Normal file
208
src/main.rs
Normal file
|
@ -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<Address>) -> 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<Command, String> {
|
||||||
|
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<Result<String, io::Error>> = 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"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue