Source code for blume.console
import code
import asyncio
import sys
from pathlib import Path
if sys.platform != 'emscripten':
import readline
import rlcompleter
InteractiveConsole = code.InteractiveConsole
else:
from pyodide.console import Console as InteractiveConsole
readline = False
from blume import magic
[docs]
class Console(magic.Ball):
""" Prompt for input """
def __init__(self, **kwargs):
super().__init__()
self.prompt = '>>> '
self.history = Path('~/.blume_history').expanduser()
if kwargs:
self.__dict__.update(kwargs)
def complete(self, text):
completions, index = self.console.complete(text)
if len(completions) == 1:
return completions[0]
print(' '.join(completions))
return None
async def start(self):
# kludge together a namespace for the console and completer
names = {}
names.update(self.__dict__)
names.update(globals())
names.update(locals())
self.console = InteractiveConsole(names)
# incantation to make tab completion work
if readline:
completer = rlcompleter.Completer(names)
readline.set_completer(completer.complete)
readline.parse_and_bind("tab: complete")
readline.set_auto_history(True)
if self.history.exists():
readline.read_history_file(self.history)
if sys.platform != 'emscripten':
self.stdin_relay = magic.spawn(self.relay_stdin())
[docs]
async def relay_stdin(self, txt=None):
""" Put stdin into a queue
This is useful(?) since code below can just wait on that
queue and not worry about actual stdin eg on a pyodide web page.
"""
loop = asyncio.get_running_loop()
while True:
key = await loop.run_in_executor(
None, input, txt or self.prompt)
await self.put(key, 'stdin')
async def run(self):
banner = """
********************************
Welcome to the magic console.
Your wish is my command!
********************************
"""
print(banner)
# print(self.prompt, end='')
while True:
key = await self.get('stdin')
# Single character inputs => put them into the
# Magic RoundAbout
if len(key.strip()) == 1 and not self.console.buffer:
char = key.strip()
await self.put(char, char)
else:
try:
result = self.console.push(key)
if sys.platform == 'emscripten':
""" emscriptem returns a promise
that needs to be awaited
TODO: unravel how it deals with incomplete
lines of input.
"""
result = await result
if result is not None: print(result)
#print(self.prompt, end='')
else:
if result:
[print(x) for x in self.console.buffer]
else:
pass
#print()
#print(self.prompt, end='')
readline and readline.write_history_file(self.history)
except Exception as e:
print("exception")
print(e)
result = e
#await self.put(result, 'stdout')
if __name__ == '__main__':
curio.run(run())