|
36 | 36 | import pyboard
|
37 | 37 |
|
38 | 38 |
|
| 39 | +CMD_EXIT = 0 |
39 | 40 | CMD_STAT = 1
|
40 | 41 | CMD_ILISTDIR_START = 2
|
41 | 42 | CMD_ILISTDIR_NEXT = 3
|
|
47 | 48 |
|
48 | 49 | fs_hook_code = """\
|
49 | 50 | import os, io, select, ustruct as struct, micropython, pyb, sys
|
| 51 | +CMD_EXIT = 0 |
50 | 52 | CMD_STAT = 1
|
51 | 53 | CMD_ILISTDIR_START = 2
|
52 | 54 | CMD_ILISTDIR_NEXT = 3
|
|
55 | 57 | CMD_READ = 6
|
56 | 58 | CMD_WRITE = 7
|
57 | 59 | CMD_SEEK = 8
|
| 60 | +
|
| 61 | +def exit(code=0): |
| 62 | + cmd = RemoteCommand() |
| 63 | + cmd.begin(CMD_EXIT) |
| 64 | + cmd.wr_int32(code) |
| 65 | + cmd.end() |
| 66 | +
|
58 | 67 | class RemoteCommand:
|
59 | 68 | use_second_port = False
|
60 | 69 | def __init__(self):
|
@@ -380,6 +389,10 @@ def wr_str(self, s):
|
380 | 389 | data_ilistdir = []
|
381 | 390 | data_files = []
|
382 | 391 |
|
| 392 | +def do_exit(cmd): |
| 393 | + exitcode = cmd.rd_int32() |
| 394 | + return exitcode |
| 395 | + |
383 | 396 | def do_stat(cmd):
|
384 | 397 | path = root + cmd.rd_str()
|
385 | 398 | try:
|
@@ -452,6 +465,7 @@ def do_write(cmd):
|
452 | 465 | cmd.wr_int32(n)
|
453 | 466 |
|
454 | 467 | cmd_table = {
|
| 468 | + CMD_EXIT: do_exit, |
455 | 469 | CMD_STAT: do_stat,
|
456 | 470 | CMD_ILISTDIR_START: do_ilistdir_start,
|
457 | 471 | CMD_ILISTDIR_NEXT: do_ilistdir_next,
|
@@ -494,24 +508,31 @@ def main_loop(console, dev_in, dev_out, pyfiles):
|
494 | 508 |
|
495 | 509 | console.write(bytes('Connected to MicroPython at %s\r\n' % dev_in, 'utf8'))
|
496 | 510 | console.write(bytes('Local directory %s is mounted at /remote\r\n' % root, 'utf8'))
|
497 |
| - console.write(bytes('Use Ctrl-X to exit this shell\r\n', 'utf8')) |
498 |
| - |
| 511 | + repl = True |
499 | 512 | if pyfiles:
|
500 | 513 | for pyfile in pyfiles:
|
501 | 514 | script = Path(pyfile)
|
502 | 515 | if not script.exists():
|
503 | 516 | console.write(bytes('\r\nERROR: Provided script not found!\r\n', 'utf8'))
|
504 | 517 | else:
|
505 |
| - pyb.exec_(script.read_bytes()) |
| 518 | + ret = pyb.exec_(script.read_bytes()) |
| 519 | + print(ret.strip(b'\x18\x00\r\n').decode()) |
| 520 | + if ret.strip(b'\x00\r\n').endswith(b'\x18'): |
| 521 | + # Script ends with exit(), don't start repl. |
| 522 | + repl = False |
506 | 523 |
|
507 | 524 | pyb.exit_raw_repl()
|
508 | 525 |
|
509 |
| - while True: |
| 526 | + if repl: |
| 527 | + console.write(bytes('Use Ctrl-X to exit this shell\r\n', 'utf8')) |
| 528 | + |
| 529 | + |
| 530 | + while repl: |
510 | 531 | if isinstance(console, ConsolePosix):
|
511 | 532 | select.select([console.infd, pyb.serial.fd], [], []) # TODO pyb.serial might not have fd
|
512 | 533 | else:
|
513 | 534 | while not (console.inWaiting() or pyb.serial.inWaiting()):
|
514 |
| - time.sleep(0.1) |
| 535 | + time.sleep(0.01) |
515 | 536 | c = console.readchar()
|
516 | 537 | if c:
|
517 | 538 | if c == b'\x18': # ctrl-X, quit
|
@@ -546,7 +567,9 @@ def main_loop(console, dev_in, dev_out, pyfiles):
|
546 | 567 | if c == b'\x18':
|
547 | 568 | # a special command
|
548 | 569 | c = pyb.serial.read(1)[0]
|
549 |
| - cmd_table[c](cmd) |
| 570 | + exitcode = cmd_table[c](cmd) |
| 571 | + if exitcode is not None: |
| 572 | + return exitcode |
550 | 573 |
|
551 | 574 | elif not VT_ENABLED and c == b'\x1b':
|
552 | 575 | # ESC code, ignore these on windows
|
@@ -590,9 +613,10 @@ def main():
|
590 | 613 | console = Console()
|
591 | 614 | console.enter()
|
592 | 615 | try:
|
593 |
| - main_loop(console, dev, args.port2, args.scripts) |
| 616 | + ret = main_loop(console, dev, args.port2, args.scripts) |
594 | 617 | finally:
|
595 | 618 | console.exit()
|
| 619 | + return ret |
596 | 620 |
|
597 | 621 | if __name__ == '__main__':
|
598 |
| - main() |
| 622 | + sys.exit(main() or 0) |
0 commit comments