@@ -610,10 +610,62 @@ def _prompt_result(self, text):
610610 callback (text )
611611
612612
613- class IPythonHistory (object ):
614- # make this
613+ class NotIPythonKernel (Exception ):
615614 pass
616615
616+ class IPythonHistory (repl .History ):
617+ """A history mechanism that interacts with IPython.
618+
619+ This relies on the standard IPython kernel, because it uses
620+ `get_ipyton().history_manager` to fetch results.
621+
622+ As a fall back, local readline completion should be implemented when a new
623+ instance of IPythonHistory can not initialize and raises an error.
624+ """
625+
626+ def __init__ (self , repl ):
627+ """The required argument is a handle on the repl, which will be ued to
628+ communicate with the IPython kernel. If a connection cannot be made,
629+ or no expected results are returned, we raise a NotIPythonKernel
630+ error, so that the vanilla readline completion can continue to be used
631+ as a fallback.
632+ """
633+ msg_id = repl .send_ipython ('' , silent = False , user_expressions = { 'hist' :
634+ "list(get_ipython().history_manager.get_range())" })
635+ # XXX: for now we only grab history from current sesssion
636+ #"list(get_ipython().history_manager.get_tail(100))"})
637+ #silent=True)
638+
639+
640+ output = repl .ipython_get_child_msg (msg_id )['content' ]
641+ hist = eval (output ['user_expressions' ]['hist' ]['data' ]['text/plain' ])
642+ self .hist = hist
643+ repl .debug_docstring = str (hist )
644+ repl .debug_docstring = ''
645+ self .entries = ['' ]
646+ self .index = 0
647+ self .saved_line = ''
648+ self .duplicates = True # allow duplicates
649+ self .repl = repl
650+ self .load ()
651+ #raise NotIPythonKernel()
652+
653+ def load (self , * args , ** kwargs ):
654+ """Load history from a live IPython session.
655+
656+ Arguments are ignored, and are only listed here for API compatibility
657+ with bpython's History class, which takes `filename` and `encoding`
658+ arguments, but those don't make sense in this instance.
659+ """
660+ # XXX: stopgap: get the history from ipython, write it to a file, and
661+ # proceed with the normal load after that
662+ for line in self .hist :
663+ self .append (line [- 1 ])
664+ self .repl .stdout_hist += "\n " + line [- 1 ]
665+
666+ def save (self , * args , ** kw ):
667+ pass
668+
617669class URWIDRepl (repl .Repl ):
618670
619671 _time_between_redraws = .05 # seconds
@@ -663,9 +715,10 @@ def __init__(self, event_loop, palette, interpreter, config):
663715 self .exit_value = ()
664716
665717 load_urwid_command_map (config )
718+ self .debug_docstring = ''
666719 self .ipython = self .connect_ipython_kernel ()
720+
667721 self .ipy_execution_count = '0'
668- self .debug_docstring = ''
669722 self .docstring_widget = None
670723
671724 @property
@@ -768,15 +821,23 @@ def echo(x):
768821 self .km = km
769822 self .kc = kc
770823 print (km )
771- msg_id = self .send_ipython ('# bpython ' + version + ' connected' )
824+ msg_id = self .send_ipython ('# bpython ' + version + ' connected\n ' )
772825 try :
773826 child = self .ipython_get_child_msg (msg_id )
774827 except Empty :
775828 over_the_line ()
776829
777830 self .send_ipython (bipy_func , silent = True )
778831 # TODO: get a proper history navigator
779- #self.rl_history = IPythonHistory(kc)
832+ #
833+ try :
834+ self .rl_history = IPythonHistory (self )
835+ except NotIPythonKernel :
836+ # We must not be running an IPython Kernel
837+ #sys.stderr.write(
838+ self .debug_docstring = "could not access IPython history, falling back to readline"
839+ sys .stderr .flush ()
840+ pass
780841 self .ipython_set_pid ()
781842
782843 return km
@@ -1428,6 +1489,9 @@ def push(self, s, insert_into_history=True):
14281489 if hasattr (repl .Repl , 'insert_into_history' ):
14291490 # this is only in unreleased version of bpython
14301491 self .insert_into_history (s )
1492+ # on the IPython side, at least for the Python kernel, history
1493+ # is managed for us by the history manager, so there's no need
1494+ # to do anything here.
14311495 if self .edit is not None :
14321496 self .edit .make_readonly ()
14331497 self .buffer = []
@@ -1586,12 +1650,12 @@ def handle_input(self, event):
15861650 # "back" from bpython.cli
15871651 self .rl_history .enter (self .edit .get_edit_text ())
15881652 self .edit .set_edit_text ('' )
1589- self .edit .insert_text (self .rl_history .back ())
1653+ self .edit .insert_text (self .rl_history .back ()) # + "#previous")
15901654 elif urwid .command_map [event ] == 'cursor down' :
15911655 # "fwd" from bpython.cli
15921656 self .rl_history .enter (self .edit .get_edit_text ())
15931657 self .edit .set_edit_text ('' )
1594- self .edit .insert_text (self .rl_history .forward ())
1658+ self .edit .insert_text (self .rl_history .forward ()) # + "#next")
15951659 elif urwid .command_map [event ] == 'next selectable' :
15961660 self .tab ()
15971661 elif urwid .command_map [event ] == 'prev selectable' :
0 commit comments