| 671 | | |
|---|
| 672 | | def print_table(table, header=None, sep=' ', numfmt='%g'): |
|---|
| 673 | | """Print a list of lists as a table, so that columns line up nicely. |
|---|
| 674 | | header, if specified, will be printed as the first row. |
|---|
| 675 | | numfmt is the format for all numbers; you might want e.g. '%6.2f'. |
|---|
| 676 | | (If you want different formats in different columns, don't use |
|---|
| 677 | | print_table.) sep is the separator between columns.""" |
|---|
| 678 | | justs = [if_(isnumber(x), 'rjust', 'ljust') for x in table[0]] |
|---|
| 679 | | if header: |
|---|
| 680 | | table = [header] + table |
|---|
| 681 | | table = [[if_(isnumber(x), lambda: numfmt % x, x) for x in row] |
|---|
| 682 | | for row in table] |
|---|
| 683 | | maxlen = lambda seq: max(map(lambda txt: len(__cprint_strip.sub('', txt)), seq)) |
|---|
| 684 | | sizes = map(maxlen, zip(*[map(str, row) for row in table])) |
|---|
| 685 | | for row in table: |
|---|
| 686 | | for (j, size, x) in zip(justs, sizes, row): |
|---|
| 687 | | cwrite(sys.stdout, getattr(str(x), j)(size), sep) |
|---|
| 688 | | print |
|---|
| 750 | | __cprint_re = re.compile(r'[^^]+|\^([N0-7BU])') |
|---|
| 751 | | __cprint_strip = re.compile('\^([N0-7BU])') |
|---|
| 752 | | __colour_terminal = 0 |
|---|
| 753 | | try: |
|---|
| 754 | | import curses |
|---|
| 755 | | curses.setupterm() |
|---|
| 756 | | if curses.tigetnum('colors') >= 0: |
|---|
| 757 | | __colour_terminal = 1 |
|---|
| 758 | | except ImportError: |
|---|
| 759 | | pass |
|---|
| 760 | | |
|---|
| 761 | | if sys.stdout.isatty() and __colour_terminal: |
|---|
| 762 | | def cwrite(io, *args): |
|---|
| 763 | | """ Print using colour escape codes similar to the Quake engine. That is, |
|---|
| 764 | | ^0-7 correspond to colours, ^B toggles bold, ^U toggles underline and |
|---|
| 765 | | ^N is reset to normal text. Colour is not automatically reset at the |
|---|
| 766 | | end of output. """ |
|---|
| 767 | | text = ' '.join(map(str, args)) |
|---|
| 768 | | bold = underline = 0 |
|---|
| 769 | | out = [] |
|---|
| 770 | | for token in __cprint_re.finditer(text): |
|---|
| 771 | | if token.group(1): |
|---|
| 772 | | c = token.group(1) |
|---|
| 773 | | if c == 'B': |
|---|
| 774 | | if bold: |
|---|
| 775 | | out.append("[22m") |
|---|
| 776 | | else: |
|---|
| 777 | | out.append("[1m") |
|---|
| 778 | | bold = not bold |
|---|
| 779 | | elif c == 'U': |
|---|
| 780 | | if underline: |
|---|
| 781 | | out.append("[24m") |
|---|
| 782 | | else: |
|---|
| 783 | | out.append("[4m") |
|---|
| 784 | | underline = not underline |
|---|
| 785 | | elif c == 'N': |
|---|
| 786 | | underline = bold = 0 |
|---|
| 787 | | out.append("[0m") |
|---|
| 788 | | elif c >= '0' and c <= '7': |
|---|
| 789 | | out.append("[3" + c + "m") |
|---|
| 790 | | else: |
|---|
| 791 | | out.append(token.group(0)) |
|---|
| 792 | | else: |
|---|
| 793 | | out.append(token.group(0)) |
|---|
| 794 | | io.write(''.join(out)) |
|---|
| 795 | | |
|---|
| 796 | | else: |
|---|
| 797 | | def cwrite(io, *args): |
|---|
| 798 | | io.write(__cprint_strip.sub('', ' '.join(map(str, args)))) |
|---|
| 799 | | |
|---|
| 800 | | def cprint(*args): |
|---|
| 801 | | cwrite(sys.stdout, *(args + ('\n',))) |
|---|
| 802 | | |
|---|
| 803 | | def cprintstrip(*args): |
|---|
| 804 | | return __cprint_strip.sub('', ' '.join(map(str, args))) |
|---|
| 805 | | |
|---|
| 806 | | def clen(arg): |
|---|
| 807 | | return len(cprintstrip(arg)) |
|---|
| 808 | | |
|---|
| 809 | | def error(*args): |
|---|
| 810 | | """ Print a red error message prefixed by ERR. """ |
|---|
| 811 | | cprint("^1^BERR " + ' '.join(map(str, args)) + '^N') |
|---|
| 812 | | |
|---|
| 813 | | def fatal(*args): |
|---|
| 814 | | """ Print a red error message prefixed by FTL, then exit with status -1 """ |
|---|
| 815 | | cprint("^1^BFTL " + ' '.join(map(str, args)) + '^N') |
|---|
| 816 | | sys.exit(-1) |
|---|
| 817 | | |
|---|
| 818 | | def warning(*args): |
|---|
| 819 | | """ Print a yellow warning message prefixed by WRN """ |
|---|
| 820 | | cprint("^3^BWRN " + ' '.join(map(str, args)) + '^N') |
|---|
| 821 | | |
|---|
| 822 | | def info(*args): |
|---|
| 823 | | """ Print a green notice prefixed by INF. """ |
|---|
| 824 | | cprint("^2^BINF ^B" + ' '.join(map(str, args)) + '^N') |
|---|
| 825 | | |
|---|