├── prescons ├── __init__.py ├── __main__.py ├── utils.py └── prescons.py ├── dist ├── prescons-0.1.tar.gz ├── prescons-0.2.tar.gz └── prescons-0.2.1.tar.gz ├── MANIFEST ├── setup.py ├── LICENSE └── README /prescons/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prescons/__main__.py: -------------------------------------------------------------------------------- 1 | from .prescons import main 2 | 3 | main() 4 | -------------------------------------------------------------------------------- /dist/prescons-0.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inglesp/prescons/HEAD/dist/prescons-0.1.tar.gz -------------------------------------------------------------------------------- /dist/prescons-0.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inglesp/prescons/HEAD/dist/prescons-0.2.tar.gz -------------------------------------------------------------------------------- /dist/prescons-0.2.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inglesp/prescons/HEAD/dist/prescons-0.2.1.tar.gz -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | README 3 | setup.py 4 | prescons/__init__.py 5 | prescons/__main__.py 6 | prescons/prescons.py 7 | prescons/utils.py 8 | -------------------------------------------------------------------------------- /prescons/utils.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import subprocess 3 | 4 | def clear_screen(): 5 | if platform.system() == 'Windows': 6 | subprocess.call('cls') 7 | else: 8 | subprocess.call('clear') 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='prescons', 5 | version='0.2.1', 6 | description='Presentation Console', 7 | long_description=open('README').read(), 8 | packages=['prescons'], 9 | license='License :: OSI Approved :: MIT License', 10 | url='http://github.com/inglesp/prescons', 11 | author='Peter Inglesby', 12 | author_email='peter.inglesby@gmail.com', 13 | ) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Peter Inglesby 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Presentation Console: prescons.py 2 | 3 | This is a "pseudo-interactive" python console for giving presentations that 4 | involve some live coding. It reads code from an input file and runs it line by 5 | line. You can move through the code by hitting the space bar. 6 | 7 | You can also switch to (and from) a normal interactive console by pressing 8 | Ctrl-C. This allows you to inspect, and even make changes to, the console's 9 | environment in the middle of a presentation. 10 | 11 | There is a video of it in action, for my Europython talk on the descriptor 12 | protocol, at youtube.com/watch?v=D3-NZXHO5QI. The input file can be found at 13 | github.com/inglesp/Discovering-Descriptors/blob/master/descriptors.py. 14 | 15 | Suggestions, bug reports, patches welcome at github.com/inglesp/prescons. 16 | 17 | Usage: 18 | 19 | $ python prescons.py 20 | 21 | Alternatively, install the library from PyPI (eg with $ pip install prescons) 22 | and then run: 23 | 24 | $ python -m prescons 25 | 26 | Tested on Posix and Windows, and with pythons 2.7 and 3.2+ 27 | 28 | Thanks to Asim Ihsan (github.com/asimihsan) and Tom Close (github.com/TomClose) 29 | for testing and ideas. 30 | -------------------------------------------------------------------------------- /prescons/prescons.py: -------------------------------------------------------------------------------- 1 | from code import InteractiveConsole 2 | 3 | try: 4 | # python2 5 | from StringIO import StringIO 6 | except ImportError: 7 | # python3 8 | from io import StringIO 9 | 10 | import os.path, sys 11 | 12 | try: 13 | # python2 14 | input = raw_input 15 | except NameError: 16 | # python3 17 | pass 18 | 19 | # get character from stdin 20 | # based on http://code.activestate.com/recipes/134892/ 21 | try: 22 | # *nix 23 | import termios, tty 24 | def getch(): 25 | fd = sys.stdin.fileno() 26 | old_settings = termios.tcgetattr(fd) 27 | gotch = None 28 | try: 29 | tty.setraw(fd) 30 | gotch = sys.stdin.read(1) 31 | finally: 32 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 33 | return gotch 34 | except ImportError: 35 | # Windows 36 | import msvcrt 37 | def getch(): 38 | return msvcrt.getch() 39 | 40 | try: 41 | import readline 42 | except ImportError: 43 | pass 44 | 45 | # lines in input file with this prefix will be executed but not displayed 46 | hide_line_prefix = '#! ' 47 | 48 | class PresentationConsole(InteractiveConsole): 49 | def __init__(self, path): 50 | full_path = os.path.join(os.getcwd(), path) 51 | sys.path.append(os.path.dirname(full_path)) 52 | self.file = open(path) 53 | self.skip_wait = False 54 | InteractiveConsole.__init__(self) 55 | 56 | def switch_mode(self): 57 | transitions = { 58 | RealInteractiveConsole: PseudoInteractiveConsole, 59 | PseudoInteractiveConsole: RealInteractiveConsole 60 | } 61 | 62 | print('') 63 | print('switching mode!') 64 | self.__class__ = transitions[self.__class__] 65 | 66 | def raw_input(self, prompt=''): 67 | try: 68 | return self.get_raw_input(prompt) 69 | except KeyboardInterrupt: 70 | self.switch_mode() 71 | return '' 72 | 73 | class PseudoInteractiveConsole(PresentationConsole): 74 | def get_raw_input(self, prompt): 75 | line = self.get_next_line(prompt) 76 | if line.startswith(hide_line_prefix): 77 | line = line.replace(hide_line_prefix, '', 1).rstrip() 78 | self.skip_wait = True 79 | else: 80 | self.write(line) 81 | line = line.rstrip() 82 | self.skip_wait = False 83 | try: 84 | readline.add_history(line) 85 | except NameError: 86 | pass 87 | return line 88 | 89 | def get_next_line(self, prompt): 90 | self.write(prompt) 91 | sys.stderr.flush() 92 | if prompt == sys.ps1: 93 | self.wait_for_user_input() 94 | line = self.file.readline() 95 | if len(line) == 0: 96 | self.file.close() 97 | raise EOFError 98 | return line 99 | 100 | def runcode(self, code): 101 | sys.stdout, sys.stderr = StringIO(), StringIO() 102 | InteractiveConsole.runcode(self, code) 103 | output, errors = sys.stdout.getvalue(), sys.stderr.getvalue() 104 | sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__ 105 | if output or errors: 106 | self.wait_for_user_input() 107 | if output: 108 | self.write(output) 109 | if errors: 110 | self.write(errors) 111 | 112 | def wait_for_user_input(self): 113 | if self.skip_wait: 114 | return 115 | while True: 116 | gotch = getch() 117 | if gotch == ' ': 118 | break 119 | elif ord(gotch) == 3: 120 | # Ctrl-C 121 | raise KeyboardInterrupt 122 | elif ord(gotch) in (4, 26): 123 | # Ctrl-D or Ctrl-Z 124 | print('') 125 | raise SystemExit 126 | 127 | class RealInteractiveConsole(PresentationConsole): 128 | def get_raw_input(self, prompt): 129 | return input(prompt) 130 | 131 | def main(): 132 | if len(sys.argv) != 2: 133 | print('Usage: python {} '.format(sys.argv[0])) 134 | else: 135 | path = sys.argv[1] 136 | console = PseudoInteractiveConsole(path) 137 | console.interact() 138 | 139 | if __name__ == '__main__': 140 | main() 141 | --------------------------------------------------------------------------------