Skip to content

Commit af2832e

Browse files
committed
Merge branch 'wes/improved-pmjs' into wes/pmjs-use-inspect
2 parents b595017 + 1b9bdee commit af2832e

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

pmjs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def repl():
109109
got_sigint = 0
110110
statement = ''
111111
readline_skip_chars = 0
112+
inner_loop = False
112113

113114
def save_history():
114115
nonlocal histfile
@@ -126,20 +127,43 @@ def repl():
126127
def sigint_handler(signum, frame):
127128
"""
128129
Handle ^C by aborting the entry of the current statement and quitting when double-struck.
130+
131+
Sometimes this happens in the main input() function. When that happens statement is "", because
132+
we have not yet returned from input(). Sometimes it happens in the middle of the inner loop's
133+
input() - in that case, statement is the beginning of a multiline expression. Hitting ^C in the
134+
middle of a multiline express cancels its input, but readline's input() doesn't return, so we
135+
have to print the extra > prompt and fake it by later getting rid of the first readline_skip_chars
136+
characters from the input buffer.
129137
"""
130138
nonlocal got_sigint
131139
nonlocal statement
132140
nonlocal readline_skip_chars
141+
nonlocal inner_loop
133142

134143
got_sigint = got_sigint + 1
135-
if (got_sigint == 1 and statement == "" and readline.get_line_buffer() == ""):
136-
sys.stdout.write("\n(To exit, press Ctrl+C again or Ctrl+D or type .exit)")
137-
elif (got_sigint > 1):
144+
if (got_sigint > 1):
138145
sys.stdout.write("\n")
139146
quit()
140147

148+
if (inner_loop != True):
149+
if (got_sigint == 1 and len(readline.get_line_buffer()) == readline_skip_chars):
150+
# First ^C with nothing in the input buffer
151+
sys.stdout.write("\n(To exit, press Ctrl+C again or Ctrl+D or type .exit)")
152+
elif (got_sigint == 1 and readline.get_line_buffer() != ""):
153+
# Input buffer has text - clear it
154+
got_sigint = 0
155+
readline_skip_chars = len(readline.get_line_buffer())
156+
else:
157+
if (got_sigint == 1 and statement == "" and len(readline.get_line_buffer()) == readline_skip_chars):
158+
# statement == "" means that the inner loop has already seen ^C and is now faking the outer loop
159+
sys.stdout.write("\n(To exit, press Ctrl+C again or Ctrl+D or type .exit)")
160+
elif (got_sigint == 1 and statement != ""):
161+
# ^C happened on inner loop while it was still thinking we were doing a multiline-expression; since
162+
# we can't break the input() function, we set it up to return an outer expression and fake the outer loop
163+
got_sigint = 0
164+
readline_skip_chars = len(readline.get_line_buffer())
165+
141166
sys.stdout.write("\n> ")
142-
readline_skip_chars = len(readline.get_line_buffer())
143167
statement = ""
144168
signal.signal(signal.SIGINT, sigint_handler)
145169

@@ -156,6 +180,7 @@ def repl():
156180
#
157181
while got_sigint < 2:
158182
try:
183+
inner_loop = False
159184
if (statement == ""):
160185
statement = input('> ')[readline_skip_chars:]
161186
readline_skip_chars = 0
@@ -177,10 +202,11 @@ def repl():
177202
# SIGINT is received, so we have to patch things up so that the next-entered line is
178203
# treated as the input at the top of the loop.
179204
while (got_sigint == 0):
180-
more = input('... ')[readline_skip_chars:]
205+
inner_loop = True
206+
lineBuffer = input('... ')
207+
more = lineBuffer[readline_skip_chars:]
181208
readline_skip_chars = 0
182209
if (got_sigint > 0):
183-
got_sigint = 0
184210
statement = more
185211
break
186212
statement = statement + '\n' + more

0 commit comments

Comments
 (0)