@@ -486,7 +486,7 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, persistent_histor
486486
487487 ############################################################################################################
488488 # The following variables are used by tab-completion functions. They are reset each time complete() is run
489- # using set_completion_defaults () and it is up to completer functions to set them before returning results.
489+ # in reset_completion_defaults () and it is up to completer functions to set them before returning results.
490490 ############################################################################################################
491491
492492 # If true and a single match is returned to complete(), then a space will be appended
@@ -651,7 +651,7 @@ def colorize(self, val, color):
651651
652652 # ----- Methods related to tab completion -----
653653
654- def set_completion_defaults (self ):
654+ def reset_completion_defaults (self ):
655655 """
656656 Resets tab completion settings
657657 Needs to be called each time readline runs tab completion
@@ -1291,7 +1291,7 @@ def complete(self, text, state):
12911291 """
12921292 if state == 0 and rl_type != RlType .NONE :
12931293 unclosed_quote = ''
1294- self .set_completion_defaults ()
1294+ self .reset_completion_defaults ()
12951295
12961296 # lstrip the original line
12971297 orig_line = readline .get_line_buffer ()
@@ -2025,12 +2025,11 @@ def _cmdloop(self):
20252025 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
20262026 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
20272027 # rl_completer_quote_characters.
2028- basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
2029- old_basic_quote_characters = ctypes .cast (basic_quote_characters , ctypes .c_void_p ).value
2030- basic_quote_characters .value = None
2028+ rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
2029+ old_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
2030+ rl_basic_quote_characters .value = None
20312031
20322032 old_completer = readline .get_completer ()
2033- old_delims = readline .get_completer_delims ()
20342033 readline .set_completer (self .complete )
20352034
20362035 # Break words on whitespace and quotes when tab completing
@@ -2040,6 +2039,7 @@ def _cmdloop(self):
20402039 # If redirection is allowed, then break words on those characters too
20412040 completer_delims += '' .join (constants .REDIRECTION_CHARS )
20422041
2042+ old_delims = readline .get_completer_delims ()
20432043 readline .set_completer_delims (completer_delims )
20442044
20452045 # Enable tab completion
@@ -2076,7 +2076,7 @@ def _cmdloop(self):
20762076
20772077 if rl_type == RlType .GNU :
20782078 readline .set_completion_display_matches_hook (None )
2079- basic_quote_characters .value = old_basic_quote_characters
2079+ rl_basic_quote_characters .value = old_basic_quotes
20802080 elif rl_type == RlType .PYREADLINE :
20812081 readline .rl .mode ._display_completions = orig_pyreadline_display
20822082
@@ -2535,6 +2535,7 @@ def run(filename):
25352535 except IOError as e :
25362536 self .perror (e )
25372537
2538+ # noinspection PyUnusedLocal
25382539 def onecmd_plus_hooks (cmd_plus_args ):
25392540 """Run a cmd2.Cmd command from a Python script or the interactive Python console.
25402541
@@ -2556,6 +2557,8 @@ def onecmd_plus_hooks(cmd_plus_args):
25562557
25572558 if arg :
25582559 interp .runcode (arg )
2560+
2561+ # If there are no args, then we will open an interactive Python console
25592562 else :
25602563 # noinspection PyShadowingBuiltins
25612564 def quit ():
@@ -2567,6 +2570,25 @@ def quit():
25672570
25682571 keepstate = None
25692572 try :
2573+ if rl_type != RlType .NONE :
2574+ # Save cmd2 history
2575+ saved_cmd2_history = []
2576+ for i in range (1 , readline .get_current_history_length () + 1 ):
2577+ saved_cmd2_history .append (readline .get_history_item (i ))
2578+
2579+ # Keep a list of commands run in the Python console
2580+ # noinspection PyAttributeOutsideInit
2581+ self .py_history = getattr (self , 'py_history' , [])
2582+
2583+ # Restore py's history
2584+ readline .clear_history ()
2585+ for item in self .py_history :
2586+ readline .add_history (item )
2587+
2588+ if self .use_rawinput and self .completekey :
2589+ # Disable tab completion while in interactive Python shell
2590+ readline .parse_and_bind (self .completekey + ": " )
2591+
25702592 cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
25712593 keepstate = Statekeeper (sys , ('stdin' , 'stdout' ))
25722594 sys .stdout = self .stdout
@@ -2577,8 +2599,24 @@ def quit():
25772599 docstr ))
25782600 except EmbeddedConsoleExit :
25792601 pass
2580- if keepstate is not None :
2581- keepstate .restore ()
2602+
2603+ finally :
2604+ if keepstate is not None :
2605+ keepstate .restore ()
2606+
2607+ if rl_type != RlType .NONE :
2608+ # Save py's history
2609+ for i in range (1 , readline .get_current_history_length () + 1 ):
2610+ self .py_history .append (readline .get_history_item (i ))
2611+
2612+ # Restore cmd2 history
2613+ readline .clear_history ()
2614+ for item in saved_cmd2_history :
2615+ readline .add_history (item )
2616+
2617+ if self .use_rawinput and self .completekey :
2618+ # Enable tab completion since we are returning to cmd2
2619+ readline .parse_and_bind (self .completekey + ": complete" )
25822620 except Exception :
25832621 pass
25842622 finally :
@@ -3430,5 +3468,3 @@ class CmdResult(namedtuple_with_two_defaults('CmdResult', ['out', 'err', 'war'])
34303468 def __bool__ (self ):
34313469 """If err is an empty string, treat the result as a success; otherwise treat it as a failure."""
34323470 return not self .err
3433-
3434-
0 commit comments