Skip to content

Commit

Permalink
Îmbunătățire CLI, organizare cod, primul release!
Browse files Browse the repository at this point in the history
Signed-off-by: Slendi <[email protected]>
  • Loading branch information
slendidev committed Jul 16, 2023
1 parent 887ab75 commit 0132211
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 126 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
[package]
name = "rolang"
version = "0.1.0"
version = "1.0.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.71"
crossterm = "0.26.1"
Expand Down
134 changes: 12 additions & 122 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,26 @@
use std::fs::read_to_string;
use std::io::Write;
use std::process::exit;
use std::{path::Path, rc::Rc, cell::RefCell};
use std::path::Path;
use std::env;
use crossterm::cursor;
use home::home_dir;
use interpreter::{Environment, eval};
use rustyline::{Editor, history::DefaultHistory, validate::Validator, hint::{Hinter, HistoryHinter}, Context, highlight::Highlighter, Helper, completion::{Completer, Pair}, error::ReadlineError, config::Configurer};

use lexer::Lexer;
use parser::Parser;

use crate::interpreter::Object;
use repl::{repl, exec};

mod lexer;
mod parser;
mod interpreter;
mod repl;

struct CustomHelper {
hinter: HistoryHinter,
}

impl Validator for CustomHelper {}
impl Highlighter for CustomHelper {}
impl Helper for CustomHelper {}
impl Completer for CustomHelper {
type Candidate = Pair;

fn complete(&self, line: &str, pos: usize, _: &Context<'_>) -> Result<(usize, Vec<Pair>), ReadlineError> {
let mut completions = Vec::new();
let word_start = match line[..pos].rfind(|c: char| c.is_whitespace() || c == '(' || c == ')') {
Some(index) => index + 1,
None => 0,
};
let word = &line[word_start..pos];

if !word.is_empty() {
for i in vec!["dacă", "până când", "pânăcând", "cât timp", "câttimp", "atunci", "altfel", "pentru", "execută", "scrie", "citește"] {
if i.starts_with(word) {
completions.push(Pair {
display: i.to_string(),
replacement: i.to_string(),
});
}
}
}

Ok((word_start, completions))
}
}

impl Hinter for CustomHelper {
type Hint = String;
fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<Self::Hint> {
self.hinter.hint(line, pos, ctx)
}
}

type CustomEditor = Editor<CustomHelper, DefaultHistory>;
const VERSION: &str = env!("CARGO_PKG_VERSION");

fn main() {
let envb = Rc::new(RefCell::new(Environment::new()));

let args: Vec<_> = env::args().collect();
for i in &args {
if matches!(i.as_str(), "--version" | "-v" | "--versiune") {
println!("{} v{}", args[0], VERSION);
exit(0);
}
}
if args.len() > 1 {
let mut filep = args[1].clone();
let mut file = Path::new(&filep);
Expand All @@ -78,77 +36,9 @@ fn main() {
}
let input = read_to_string(file).unwrap();

let lex = Lexer::new(input);
let mut parser = Parser::new(lex);
let root = parser.parse();
//root.print(String::new(), true);

if parser.errors.len() > 0 {
println!("Erori găsite:");
for (pos, msg) in parser.errors.iter().enumerate() {
println!(" {}: {}", pos+1, msg);
}
return;
}

eval(root, Some(Rc::clone(&envb))).unwrap();
exec(&input).unwrap();
return;
}

let mut rl_hist = home_dir().unwrap();
rl_hist.push(Path::new(".rolang_history"));
let rl_hist = rl_hist.to_str().unwrap();

let mut rl = CustomEditor::new().unwrap();
if rl.load_history(rl_hist).is_err() {
println!("Istoric nou creat.");
}

rl.set_helper(Some(CustomHelper { hinter: HistoryHinter { }}));
rl.set_completion_type(rustyline::CompletionType::Circular);

loop {
let readline = rl.readline("> ");
if readline.is_err() {
break;
}
let mut input = readline.unwrap();

if input.trim().is_empty() {
continue;
}

rl.add_history_entry(input.clone()).unwrap();

input.push('\n');

let lex = Lexer::new(input);
let mut parser = Parser::new(lex);
let root = parser.parse();
//root.print(String::new(), true);

if parser.errors.len() > 0 {
println!("Erori găsite:");
for (pos, msg) in parser.errors.iter().enumerate() {
println!(" {}: {}", pos+1, msg);
}
continue;
}

let res = eval(root, Some(Rc::clone(&envb)));
match cursor::position() {
Ok((x, _)) => if x != 0 {
println!("\x1b[7m%\x1b[0m");
},
Err(_) => ()
};
match res {
Err(e) => println!("Eroare ROLang: {}", e),
Ok(res) => if res != Object::Null {
println!("Rezultat: {}", res);
}
}
}

rl.save_history(rl_hist).unwrap();
repl();
}
119 changes: 119 additions & 0 deletions src/repl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use rustyline::{Editor, history::DefaultHistory, validate::Validator, hint::{Hinter, HistoryHinter}, Context, highlight::Highlighter, Helper, completion::{Completer, Pair}, error::ReadlineError, config::Configurer};
use crossterm::cursor;
use home::home_dir;
use std::{rc::Rc, cell::RefCell};
use std::path::Path;
use anyhow::{anyhow, Result};

use crate::interpreter::{Environment, eval};
use crate::lexer::Lexer;
use crate::parser::Parser;
use crate::interpreter::Object;

pub struct CustomHelper {
pub hinter: HistoryHinter,
}

impl Validator for CustomHelper {}
impl Highlighter for CustomHelper {}
impl Helper for CustomHelper {}
impl Completer for CustomHelper {
type Candidate = Pair;

fn complete(&self, line: &str, pos: usize, _: &Context<'_>) -> Result<(usize, Vec<Pair>), ReadlineError> {
let mut completions = Vec::new();
let word_start = match line[..pos].rfind(|c: char| c.is_whitespace() || c == '(' || c == ')') {
Some(index) => index + 1,
None => 0,
};
let word = &line[word_start..pos];

if !word.is_empty() {
for i in vec!["dacă", "până când", "pânăcând", "cât timp", "câttimp", "atunci", "altfel", "pentru", "execută", "scrie", "citește"] {
if i.starts_with(word) {
completions.push(Pair {
display: i.to_string(),
replacement: i.to_string(),
});
}
}
}

Ok((word_start, completions))
}
}

impl Hinter for CustomHelper {
type Hint = String;
fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<Self::Hint> {
self.hinter.hint(line, pos, ctx)
}
}

pub type RoLangReadlineEditor = Editor<CustomHelper, DefaultHistory>;

pub fn exec(input: &str) -> Result<Object> {
let envb = Rc::new(RefCell::new(Environment::new()));

let lex = Lexer::new(input.to_string());
let mut parser = Parser::new(lex);
let root = parser.parse();
//root.print(String::new(), true);

if parser.errors.len() > 0 {
println!("Erori găsite:");
for (pos, msg) in parser.errors.iter().enumerate() {
println!(" {}: {}", pos+1, msg);
}
return Err(anyhow!("Există erori."));
}

eval(root, Some(Rc::clone(&envb)))
}

pub fn repl() {
let mut rl_hist = home_dir().unwrap();
rl_hist.push(Path::new(".rolang_history"));
let rl_hist = rl_hist.to_str().unwrap();

let mut rl = RoLangReadlineEditor::new().unwrap();
if rl.load_history(rl_hist).is_err() {
println!("Istoric nou creat.");
}

rl.set_helper(Some(CustomHelper { hinter: HistoryHinter { }}));
rl.set_completion_type(rustyline::CompletionType::Circular);

loop {
let readline = rl.readline("> ");
if readline.is_err() {
break;
}
let mut input = readline.unwrap();

if input.trim().is_empty() {
continue;
}

rl.add_history_entry(input.clone()).unwrap();

input.push('\n');

let res = exec(&input);
match cursor::position() {
Ok((x, _)) => if x != 0 {
println!("\x1b[7m%\x1b[0m");
},
Err(_) => ()
};
match res {
Err(e) => println!("Eroare ROLang: {}", e),
Ok(res) => if res != Object::Null {
println!("Rezultat: {}", res);
}
}
}

rl.save_history(rl_hist).unwrap();

}

0 comments on commit 0132211

Please sign in to comment.