I'm implementing a custom (Iron)Python console.
I need to display a >>> prompt in general, but when a statement is incomplete, I need to change the prompt to ... and gather more lines before executing them.
How do I know if a line entered by a user is complete or if I need to read more lines?
A simple way seems to be checking if : is present. But I'm not sure if I'm not missing other cases where : is not present.
I looked into the IronPython source code to figure how it does this, but there are many steps involved and my simple reproduction failed to completely work.
It's impractical to try to guess from just looking at the code string for colons and brackets. You would end up needing to implement half the Python parser to get that right.
The standard library code module reproduces the behaviour of the interactive Python interpreter, and I believe it is this module that IronPython uses to implement its console. (The CPython one isn't implemented in Python itself.)
The line-continuation logic you're interested in comes from the codeop.compile_command function.
It's a bit of a hack. Essentially it tries to compile() the given code using the obscure PyCF_DONT_IMPLY_DEDENT flag, which means it doesn't assume that any open indents are closed automatically at the end of the block. It then tries to compile it again with newlines added (causing explicit DEDENTs). If the second works but the first doesn't, you've got a potential continuation, more can be typed into the block.
There are a few different ways I can think of to get the ... prompt.
def foo():x = (x = {x = [x = '''x = \If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With