##// END OF EJS Templates
Fix #4777 and #7887...
Fix #4777 and #7887 The function in charge of actually converting cursor offset to CodeMirror line number and character number was actually crashing when the cursor was at the last character (loop until undefined, then access length of variable, which is undefined). This was hiding a bug in which when you would completer to a single completion pressing tab after as-you-type filtering, the completion would be completed twice. The logic that was supposed to detect whether or not all completions had a common prefix was actually faulty as the common prefix used to be a string but was then changed to an object. Hence the logic to check whether or not there was actually a common prefix was always true, even for empty string, leading to the deletion of the line (replace by '') in some cases.

File last commit:

r11176:7462fe1a
r20538:ae7f6d6a
Show More
app.py
149 lines | 4.8 KiB | text/x-python | PythonLexer
""" A minimal application using the ZMQ-based terminal IPython frontend.
This is not a complete console app, as subprocess will not be able to receive
input, there is no real readline support, among other limitations.
Authors:
* Min RK
* Paul Ivanov
"""
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import signal
from IPython.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags
from IPython.utils.traitlets import (
Dict, Any
)
from IPython.utils.warn import error
from IPython.consoleapp import (
IPythonConsoleApp, app_aliases, app_flags, aliases, flags
)
from IPython.terminal.console.interactiveshell import ZMQTerminalInteractiveShell
#-----------------------------------------------------------------------------
# Globals
#-----------------------------------------------------------------------------
_examples = """
ipython console # start the ZMQ-based console
ipython console --existing # connect to an existing ipython session
"""
#-----------------------------------------------------------------------------
# Flags and Aliases
#-----------------------------------------------------------------------------
# copy flags from mixin:
flags = dict(flags)
# start with mixin frontend flags:
frontend_flags = dict(app_flags)
# add TerminalIPApp flags:
frontend_flags.update(term_flags)
# disable quick startup, as it won't propagate to the kernel anyway
frontend_flags.pop('quick')
# update full dict with frontend flags:
flags.update(frontend_flags)
# copy flags from mixin
aliases = dict(aliases)
# start with mixin frontend flags
frontend_aliases = dict(app_aliases)
# load updated frontend flags into full dict
aliases.update(frontend_aliases)
# get flags&aliases into sets, and remove a couple that
# shouldn't be scrubbed from backend flags:
frontend_aliases = set(frontend_aliases.keys())
frontend_flags = set(frontend_flags.keys())
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
name = "ipython-console"
"""Start a terminal frontend to the IPython zmq kernel."""
description = """
The IPython terminal-based Console.
This launches a Console application inside a terminal.
The Console supports various extra features beyond the traditional
single-process Terminal IPython shell, such as connecting to an
existing ipython session, via:
ipython console --existing
where the previous session could have been created by another ipython
console, an ipython qtconsole, or by opening an ipython notebook.
"""
examples = _examples
classes = [ZMQTerminalInteractiveShell] + IPythonConsoleApp.classes
flags = Dict(flags)
aliases = Dict(aliases)
frontend_aliases = Any(frontend_aliases)
frontend_flags = Any(frontend_flags)
subcommands = Dict()
def parse_command_line(self, argv=None):
super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
self.build_kernel_argv(argv)
def init_shell(self):
IPythonConsoleApp.initialize(self)
# relay sigint to kernel
signal.signal(signal.SIGINT, self.handle_sigint)
self.shell = ZMQTerminalInteractiveShell.instance(parent=self,
display_banner=False, profile_dir=self.profile_dir,
ipython_dir=self.ipython_dir,
manager=self.kernel_manager,
client=self.kernel_client,
)
def init_gui_pylab(self):
# no-op, because we don't want to import matplotlib in the frontend.
pass
def handle_sigint(self, *args):
if self.shell._executing:
if self.kernel_manager:
# interrupt already gets passed to subprocess by signal handler.
# Only if we prevent that should we need to explicitly call
# interrupt_kernel, until which time, this would result in a
# double-interrupt:
# self.kernel_manager.interrupt_kernel()
pass
else:
self.shell.write_err('\n')
error("Cannot interrupt kernels we didn't start.\n")
else:
# raise the KeyboardInterrupt if we aren't waiting for execution,
# so that the interact loop advances, and prompt is redrawn, etc.
raise KeyboardInterrupt
def init_code(self):
# no-op in the frontend, code gets run in the backend
pass
launch_new_instance = ZMQTerminalIPythonApp.launch_instance
if __name__ == '__main__':
launch_new_instance()