prompt-toolkit / ptpython

A better Python REPL
BSD 3-Clause "New" or "Revised" License
5.23k stars 280 forks source link

ctrl+c will stop ptipython #272

Closed nasyxx closed 6 years ago

nasyxx commented 6 years ago

ctrl+c will stop ptipython on macOS. Here is the traceback.

λ ptipython                                                                                                                                                   
In [1]:                                                                                                                                                                 
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
/usr/local/bin/ptipython in <module>
      9 if __name__ == '__main__':
     10     sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
---> 11     sys.exit(run())

/usr/local/lib/python3.7/site-packages/ptpython/entry_points/run_ptipython.py in run(user_ns)
     93               configure=configure,
     94               user_ns=user_ns,
---> 95               title='IPython REPL (ptipython)')
     96 
     97 

/usr/local/lib/python3.7/site-packages/ptpython/ipython.py in embed(**kwargs)
    253     shell = InteractiveShellEmbed.instance(**kwargs)
    254     initialize_extensions(shell, config['InteractiveShellApp']['extensions'])
--> 255     shell(header=header, stack_depth=2, compile_flags=compile_flags)

/usr/local/lib/python3.7/site-packages/IPython/terminal/embed.py in __call__(self, header, local_ns, module, dummy, stack_depth, global_ns, compile_flags, **kw)
    227         # our call and get the original caller's namespaces.
    228         self.mainloop(local_ns, module, stack_depth=stack_depth,
--> 229                       global_ns=global_ns, compile_flags=compile_flags)
    230 
    231         self.banner2 = self.old_banner2

/usr/local/lib/python3.7/site-packages/IPython/terminal/embed.py in mainloop(self, local_ns, module, stack_depth, display_banner, global_ns, compile_flags)
    322 
    323         with self.builtin_trap, self.display_trap:
--> 324             self.interact()
    325 
    326         # now, purge out the local namespace of IPython's hidden variables.

/usr/local/lib/python3.7/site-packages/IPython/terminal/interactiveshell.py in interact(self, display_banner)
    453 
    454             try:
--> 455                 code = self.prompt_for_code()
    456             except EOFError:
    457                 if (not self.confirm_exit) \

/usr/local/lib/python3.7/site-packages/ptpython/ipython.py in prompt_for_code(self)
    218 
    219     def prompt_for_code(self):
--> 220         return self.python_input.app.run()
    221 
    222 

/usr/local/lib/python3.7/site-packages/prompt_toolkit/application/application.py in run(self, pre_run, set_exception_handler, inputhook)
    696             loop.set_exception_handler(handle_exception)
    697             try:
--> 698                 return run()
    699             finally:
    700                 loop.set_exception_handler(previous_exc_handler)

/usr/local/lib/python3.7/site-packages/prompt_toolkit/application/application.py in run()
    670             f = self.run_async(pre_run=pre_run)
    671             run_until_complete(f, inputhook=inputhook)
--> 672             return f.result()
    673 
    674         def handle_exception(context):

/usr/local/lib/python3.7/site-packages/prompt_toolkit/eventloop/future.py in result(self)
    147         self._retrieved_result = True
    148         if self._exception:
--> 149             raise self._exception
    150         else:
    151             return self._result

/usr/local/lib/python3.7/site-packages/prompt_toolkit/eventloop/coroutine.py in step_next(f)
     88                 exc = f.exception()
     89                 if exc:
---> 90                     new_f = coroutine.throw(exc)
     91                 else:
     92                     new_f = coroutine.send(f.result())

/usr/local/lib/python3.7/site-packages/prompt_toolkit/application/application.py in _run_async2()
    649                 try:
    650                     f = From(_run_async())
--> 651                     result = yield f
    652                 finally:
    653                     assert not self._is_running

/usr/local/lib/python3.7/site-packages/prompt_toolkit/eventloop/coroutine.py in step_next(f)
     90                     new_f = coroutine.throw(exc)
     91                 else:
---> 92                     new_f = coroutine.send(f.result())
     93         except StopIteration as e:
     94             # Stop coroutine. Make sure that a result has been set in the future,

/usr/local/lib/python3.7/site-packages/prompt_toolkit/application/application.py in _run_async()
    601                     # Wait for UI to finish.
    602                     try:
--> 603                         result = yield From(f)
    604                     finally:
    605                         # In any case, when the application finishes. (Successful,

KeyboardInterrupt: 
Time: 0h:00m:06s  
ajkerrigan commented 6 years ago

Based on this it looks like this behavior is by design. That said, I had gotten in the (bad?) habit of using Ctrl-C to abort my current train of thought and undo typing (similar to Ctrl-G in other applications).

Adding this to my ~/.ptpython/config.py seems to restore that behavior, while still allowing Ctrl-C to interrupt long-running calls:

    @repl.add_key_binding(Keys.ControlC)
    def _(event):
        event.cli.current_buffer.text = ""

Maybe this will be useful to you too.

nasyxx commented 6 years ago

Based on this it looks like this behavior is by design. That said, I had gotten in the (bad?) habit of using Ctrl-C to abort my current train of thought and undo typing (similar to Ctrl-G in other applications).

Adding this to my ~/.ptpython/config.py seems to restore that behavior, while still allowing Ctrl-C to interrupt long-running calls:

    @repl.add_key_binding(Keys.ControlC)
    def _(event):
        event.cli.current_buffer.text = ""

Maybe this will be useful to you too.

Thanks a lot for teaching me to execute C-c like this.

And it seems that it has not happened again.

sisrfeng commented 2 years ago

done:

~/.ptpython/config.py:

def configure(repl):
     # ......

    @repl.add_key_binding("c-c", filter=ViInsertMode())
    def _(event):
        "类似shell的ctrl-c "
        event.cli.current_buffer.text = ""
        #  event.cli.key_processor.feed(KeyPress("escape"))