Skip to content

Commit a7ecab4

Browse files
bleibiggraydon
authored andcommitted
Added support for multiline commands in the REPL with :{ .. :}
1 parent 34b7db3 commit a7ecab4

File tree

1 file changed

+96
-43
lines changed

1 file changed

+96
-43
lines changed

src/librusti/rusti.rs

Lines changed: 96 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ struct Repl {
1010
stmts: ~str
1111
}
1212

13+
// Action to do after reading a :command
14+
enum CmdAction {
15+
action_none,
16+
action_run_line(~str),
17+
}
18+
1319
/// A utility function that hands off a pretty printer to a callback.
1420
fn with_pp(intr: @token::ident_interner,
1521
cb: fn(pprust::ps, io::Writer)) -> ~str {
@@ -234,9 +240,26 @@ fn run(repl: Repl, input: ~str) -> Repl {
234240
record(repl, blk, sess.parse_sess.interner)
235241
}
236242

243+
/// Tries to get a line from rl after outputting a prompt. Returns
244+
/// None if no input was read (e.g. EOF was reached).
245+
fn get_line(prompt: ~str) -> Option<~str> {
246+
let result = unsafe { rl::read(prompt) };
247+
248+
if result.is_none() {
249+
return None;
250+
}
251+
252+
let line = result.get();
253+
254+
unsafe { rl::add_history(line) };
255+
256+
return Some(line);
257+
}
258+
237259
/// Run a command, e.g. :clear, :exit, etc.
238260
fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
239-
cmd: ~str, _args: ~[~str]) {
261+
cmd: ~str, _args: ~[~str]) -> CmdAction {
262+
let mut action = action_none;
240263
match cmd {
241264
~"exit" => repl.running = false,
242265
~"clear" => {
@@ -247,12 +270,74 @@ fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
247270
//rl::clear();
248271
}
249272
~"help" => {
250-
io::println(~":clear - clear the screen\n" +
273+
io::println(~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" +
274+
~":clear - clear the screen\n" +
251275
~":exit - exit from the repl\n" +
252276
~":help - show this message");
253277
}
278+
~"{" => {
279+
let mut multiline_cmd = ~"";
280+
let mut end_multiline = false;
281+
while (!end_multiline) {
282+
match get_line(~"rusti| ") {
283+
None => fail ~"unterminated multiline command :{ .. :}",
284+
Some(line) => {
285+
if str::trim(line) == ~":}" {
286+
end_multiline = true;
287+
} else {
288+
multiline_cmd += line + ~"\n";
289+
}
290+
}
291+
}
292+
}
293+
action = action_run_line(multiline_cmd);
294+
}
254295
_ => io::println(~"unknown cmd: " + cmd)
255296
}
297+
return action;
298+
}
299+
300+
/// Executes a line of input, which may either be rust code or a
301+
/// :command. Returns a new Repl if it has changed.
302+
fn run_line(repl: &mut Repl, in: io::Reader, out: io::Writer, line: ~str)
303+
-> Option<Repl> {
304+
if line.starts_with(~":") {
305+
let full = line.substr(1, line.len() - 1);
306+
let split = str::words(full);
307+
let len = split.len();
308+
309+
if len > 0 {
310+
let cmd = split[0];
311+
312+
if !cmd.is_empty() {
313+
let args = if len > 1 {
314+
do vec::view(split, 1, len - 1).map |arg| {
315+
*arg
316+
}
317+
} else { ~[] };
318+
319+
match run_cmd(repl, in, out, cmd, args) {
320+
action_none => { }
321+
action_run_line(multiline_cmd) => {
322+
if !multiline_cmd.is_empty() {
323+
return run_line(repl, in, out, multiline_cmd);
324+
}
325+
}
326+
}
327+
return None;
328+
}
329+
}
330+
}
331+
332+
let r = *repl;
333+
let result = do task::try |copy r| {
334+
run(r, line)
335+
};
336+
337+
if result.is_ok() {
338+
return Some(result.get());
339+
}
340+
return None;
256341
}
257342

258343
pub fn main() {
@@ -278,50 +363,18 @@ pub fn main() {
278363
}
279364

280365
while repl.running {
281-
let result = unsafe { rl::read(repl.prompt) };
282-
283-
if result.is_none() {
284-
break;
285-
}
286-
287-
let line = result.get();
288-
289-
if line.is_empty() {
290-
io::println(~"()");
291-
292-
loop;
293-
}
294-
295-
unsafe { rl::add_history(line) };
296-
297-
if line.starts_with(~":") {
298-
let full = line.substr(1, line.len() - 1);
299-
let split = full.split_char(' ');
300-
let len = split.len();
301-
302-
if len > 0 {
303-
let cmd = split[0];
304-
305-
if !cmd.is_empty() {
306-
let args = if len > 1 {
307-
do vec::view(split, 1, len - 1).map |arg| {
308-
*arg
309-
}
310-
} else { ~[] };
311-
312-
run_cmd(&mut repl, in, out, cmd, args);
313-
366+
match get_line(repl.prompt) {
367+
None => break,
368+
Some(line) => {
369+
if line.is_empty() {
370+
io::println(~"()");
314371
loop;
315372
}
373+
match run_line(&mut repl, in, out, line) {
374+
Some(new_repl) => repl = new_repl,
375+
None => { }
376+
}
316377
}
317378
}
318-
319-
let result = do task::try |copy repl| {
320-
run(copy repl, line)
321-
};
322-
323-
if result.is_ok() {
324-
repl = result.get();
325-
}
326379
}
327380
}

0 commit comments

Comments
 (0)