From 5bb50aeda995b8a0aa48ca7428cfb185e4d884f1 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 6 Jun 2026 10:32:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20CLI=20REPL=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E7=AC=A6=E5=8F=B7=E8=A1=A8=E4=B8=8E=E5=A4=9A=E8=A1=8C=E8=BE=93?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_cli/src/main.rs | 46 +++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/oxide_cli/src/main.rs b/crates/oxide_cli/src/main.rs index 22264086..9a87a7d3 100644 --- a/crates/oxide_cli/src/main.rs +++ b/crates/oxide_cli/src/main.rs @@ -211,6 +211,18 @@ fn compile(expr: Option, file: Option) -> ExitCode { } } +fn bracket_balance(line: &str) -> i32 { + let mut count = 0i32; + for ch in line.chars() { + match ch { + '(' | '[' | '{' => count += 1, + ')' | ']' | '}' => count -= 1, + _ => {} + } + } + count +} + fn repl() -> ExitCode { use rustyline::error::ReadlineError; use rustyline::DefaultEditor; @@ -225,9 +237,16 @@ fn repl() -> ExitCode { let kernel = make_kernel(); let pool = make_pool(&kernel); + let mut source = String::new(); + let mut input_buf = String::new(); loop { - match rl.readline("oxide> ") { + let prompt = if input_buf.is_empty() { + "oxide> " + } else { + "...> " + }; + match rl.readline(prompt) { Ok(line) => { let trimmed = line.trim(); if trimmed.is_empty() { @@ -238,7 +257,29 @@ fn repl() -> ExitCode { return ExitCode::SUCCESS; } rl.add_history_entry(trimmed).ok(); - eval(trimmed, &kernel, &pool); + + if !input_buf.is_empty() { + input_buf.push('\n'); + } + input_buf.push_str(trimmed); + + let balance = bracket_balance(&input_buf); + if balance > 0 { + continue; + } + + let mut full_code = source.clone(); + if !full_code.is_empty() { + full_code.push(';'); + } + full_code.push_str(&input_buf); + + let result = eval(&full_code, &kernel, &pool); + input_buf.clear(); + + if result == ExitCode::SUCCESS { + source = full_code; + } } Err(ReadlineError::Interrupted) => { println!("^C"); @@ -255,7 +296,6 @@ fn repl() -> ExitCode { } } } - fn not_implemented(command: &str) -> ExitCode { use ansi_term::Colour::Yellow; eprintln!(