@@ -10,6 +10,12 @@ struct Repl {
10
10
stmts : ~str
11
11
}
12
12
13
+ // Action to do after reading a :command
14
+ enum CmdAction {
15
+ action_none,
16
+ action_run_line( ~str ) ,
17
+ }
18
+
13
19
/// A utility function that hands off a pretty printer to a callback.
14
20
fn with_pp ( intr : @token:: ident_interner ,
15
21
cb : fn ( pprust:: ps , io:: Writer ) ) -> ~str {
@@ -234,9 +240,26 @@ fn run(repl: Repl, input: ~str) -> Repl {
234
240
record ( repl, blk, sess. parse_sess . interner )
235
241
}
236
242
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
+
237
259
/// Run a command, e.g. :clear, :exit, etc.
238
260
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;
240
263
match cmd {
241
264
~"exit" => repl. running = false ,
242
265
~"clear" => {
@@ -247,12 +270,74 @@ fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
247
270
//rl::clear();
248
271
}
249
272
~"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 " +
251
275
~": exit - exit from the repl\n " +
252
276
~": help - show this message") ;
253
277
}
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
+ }
254
295
_ => io:: println( ~"unknown cmd: " + cmd)
255
296
}
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 ;
256
341
}
257
342
258
343
pub fn main ( ) {
@@ -278,50 +363,18 @@ pub fn main() {
278
363
}
279
364
280
365
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 ( ~"( ) ") ;
314
371
loop ;
315
372
}
373
+ match run_line ( & mut repl, in, out, line) {
374
+ Some ( new_repl) => repl = new_repl,
375
+ None => { }
376
+ }
316
377
}
317
378
}
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
- }
326
379
}
327
380
}
0 commit comments