1use crate::errwarn::ErrorGenerator;
2use crate::lexer::Lexer;
3use crate::parser::Parser;
4use crate::runtime::Run;
5use crate::store::VERSION;
6use crate::util::{get_lang, SupportedLanguage};
7use lazy_static::lazy_static;
8use regex::Regex;
9use rustyline::completion::Completer;
10use rustyline::completion::Pair;
11use rustyline::error::ReadlineError;
12use rustyline::Editor;
13
14struct InteractiveCompleter;
17impl Completer for InteractiveCompleter {
18 type Candidate = Pair;
19 fn complete(
20 &self,
21 line: &str,
22 pos: usize,
23 _ctx: &rustyline::Context<'_>,
24 ) -> rustyline::Result<(usize, Vec<Pair>)> {
25 lazy_static! {
26 static ref RE: Regex =
27 Regex::new(r#"[^()\d,'"+\-*/><!=%?.@\s][^\s"':?=<>!/%*@,()]*"#).unwrap();
28 static ref KNOWN_KEYWORDS: Vec<&'static str> = vec![
29 "at", "ver", "de", "ise", "son", "iken", "yoksa", "doğru", "yanlış", "kpy", "tks",
30 "üst", "veya", "ve", "dön", "girdi", "işlev", "yükle",
31 ];
32 }
33 let matches = RE.find_iter(line);
34 for m in matches.into_iter() {
35 if m.end() == pos {
36 return Ok((
37 m.start(),
38 KNOWN_KEYWORDS
39 .iter()
40 .filter(|a| a.starts_with(m.as_str()))
41 .map(|a| Pair {
42 display: a.to_string(),
43 replacement: a.to_string(),
44 })
45 .collect(),
46 ));
47 }
48 }
49 Ok((0, Vec::with_capacity(0)))
50 }
51}
52
53#[derive(Debug, PartialEq, Eq)]
54pub enum QuietLevel {
55 None,
56 Quiet,
57 Quieter,
58 Quietest,
59}
60impl QuietLevel {
61 pub fn inc(&mut self) {
62 match self {
63 Self::None => *self = Self::Quiet,
64 Self::Quiet => *self = Self::Quieter,
65 Self::Quieter => *self = Self::Quietest,
66 Self::Quietest => (),
67 }
68 }
69 pub fn inc_by(&mut self, i: usize) {
70 for _ in 0..i {
71 self.inc()
72 }
73 }
74}
75
76pub struct Interactive {
77 line: usize,
78 quiet: QuietLevel,
79}
80impl Default for Interactive {
81 fn default() -> Self {
82 Self {
83 line: 1,
84 quiet: QuietLevel::None,
85 }
86 }
87}
88impl Interactive {
89 pub fn new(quiet: QuietLevel) -> Self {
90 Self {
91 quiet,
92 ..Default::default()
93 }
94 }
95 pub fn start(&mut self) {
96 if self.quiet == QuietLevel::None {
97 match get_lang() {
98 SupportedLanguage::Turkish => {
99 println!("tr-lang ({VERSION}) interaktif konsol");
100 println!("çıkmak için `#çık` yazın");
101 println!("yürütmek için `#yürüt` yazın");
102 }
103 SupportedLanguage::English => {
104 println!("tr-lang ({VERSION}) interactive console");
105 println!("type `#çık` to exit");
106 println!("type `#yürüt` to run");
107 }
108 }
109 }
110 let mut fbuf = String::new();
111 let mut editor = Editor::<()>::new();
112 if editor.load_history(".trlhistory").is_err() {
113 match get_lang() {
114 SupportedLanguage::Turkish => println!("Tarih bulunamadı."),
115 SupportedLanguage::English => println!("No previous history."),
116 }
117 }
118 loop {
119 let pr = match self.quiet {
120 QuietLevel::None => format!("trli:{:03}#> ", self.line),
121 QuietLevel::Quiet => format!("{:03}#> ", self.line),
122 QuietLevel::Quieter => "#> ".to_string(),
123 QuietLevel::Quietest => "".to_string(),
124 };
125 let rl = editor.readline(&pr);
126 match rl {
127 Ok(buf) => match buf.as_str() {
128 "#çık" => break,
129 "#yürüt" => {
130 let (mut memcs, _) = Run::new(
131 match match Parser::from_lexer(&mut Lexer::new(fbuf.clone()), ".".to_string()) {
132 Ok(parser) => parser,
133 Err(e) => {
134 e.eprint();
135 continue;
136 }
137 }.parse() {
138 Ok(ptk) => ptk,
139 Err(e) => { e.eprint(); continue; }
140 },
141 )
142 .run("<trli>".to_string(), None, true)
143 .unwrap_or_else(|(s, h, e)| {
144 e.eprint();
145 (s, h)
146 });
147 println!();
148 if memcs.len() > 0 {
149 println!("=> {:?}", memcs.iter_vec());
150 }
151 fbuf = String::new();
152 self.line = 1;
153 }
154 _ => {
155 editor.add_history_entry(&buf);
156 fbuf.push_str(&buf);
157 fbuf.push('\n');
158 self.line += 1;
159 }
160 },
161 Err(ReadlineError::Interrupted) => {
162 eprintln!("Ctrl+C");
163 }
164 Err(ReadlineError::Eof) => break,
165 Err(e) => match get_lang() {
166 SupportedLanguage::Turkish => ErrorGenerator::error(
167 "EditörHatası",
168 &format!("{}", e),
169 self.line,
170 0,
171 "<trli>".to_string(),
172 None,
173 ),
174 SupportedLanguage::English => ErrorGenerator::error(
175 "EditorError",
176 &format!("{}", e),
177 self.line,
178 0,
179 "<trli>".to_string(),
180 None,
181 ),
182 }
183 .eprint(),
184 }
185 }
186 editor.save_history(".trlhistory").unwrap();
187 }
188}