@@ -335,11 +335,12 @@ class Cmd(cmd.Cmd):
335335 DEFAULT_SHORTCUTS = {'?' : 'help' , '!' : 'shell' , '@' : 'load' , '@@' : '_relative_load' }
336336 DEFAULT_EDITOR = utils .find_editor ()
337337
338- def __init__ (self , completekey : str = 'tab' , stdin = None , stdout = None , persistent_history_file : str = '' ,
339- persistent_history_length : int = 1000 , startup_script : Optional [str ] = None , use_ipython : bool = False ,
340- transcript_files : Optional [List [str ]] = None , allow_redirection : bool = True ,
341- multiline_commands : Optional [List [str ]] = None , terminators : Optional [List [str ]] = None ,
342- shortcuts : Optional [Dict [str , str ]] = None ) -> None :
338+ def __init__ (self , completekey : str = 'tab' , stdin = None , stdout = None , * ,
339+ persistent_history_file : str = '' , persistent_history_length : int = 1000 ,
340+ startup_script : Optional [str ] = None , use_ipython : bool = False ,
341+ allow_cli_args : bool = True , transcript_files : Optional [List [str ]] = None ,
342+ allow_redirection : bool = True , multiline_commands : Optional [List [str ]] = None ,
343+ terminators : Optional [List [str ]] = None , shortcuts : Optional [Dict [str , str ]] = None ) -> None :
343344 """An easy but powerful framework for writing line-oriented command interpreters, extends Python's cmd package.
344345
345346 :param completekey: (optional) readline name of a completion key, default to Tab
@@ -349,6 +350,9 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, persistent
349350 :param persistent_history_length: (optional) max number of history items to write to the persistent history file
350351 :param startup_script: (optional) file path to a a script to load and execute at startup
351352 :param use_ipython: (optional) should the "ipy" command be included for an embedded IPython shell
353+ :param allow_cli_args: (optional) if True, then cmd2 will process command line arguments as either
354+ commands to be run or, if -t is specified, transcript files to run.
355+ This should be set to False if your application parses its own arguments.
352356 :param transcript_files: (optional) allows running transcript tests when allow_cli_args is False
353357 :param allow_redirection: (optional) should output redirection and pipes be allowed
354358 :param multiline_commands: (optional) list of commands allowed to accept multi-line input
@@ -372,7 +376,6 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, persistent
372376 super ().__init__ (completekey = completekey , stdin = stdin , stdout = stdout )
373377
374378 # Attributes which should NOT be dynamically settable at runtime
375- self .allow_cli_args = True # Should arguments passed on the command-line be processed as commands?
376379 self .default_to_shell = False # Attempt to run unrecognized commands as shell commands
377380 self .quit_on_sigint = False # Quit the loop on interrupt instead of just resetting prompt
378381
@@ -423,7 +426,6 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, persistent
423426 terminators = terminators ,
424427 multiline_commands = multiline_commands ,
425428 shortcuts = shortcuts )
426- self ._transcript_files = transcript_files
427429
428430 # True if running inside a Python script or interactive console, False otherwise
429431 self ._in_py = False
@@ -460,11 +462,33 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, persistent
460462 # If this string is non-empty, then this warning message will print if a broken pipe error occurs while printing
461463 self .broken_pipe_warning = ''
462464
465+ # Commands that will run at the beginning of the command loop
466+ self ._startup_commands = []
467+
463468 # If a startup script is provided, then add it in the queue to load
464469 if startup_script is not None :
465470 startup_script = os .path .abspath (os .path .expanduser (startup_script ))
466471 if os .path .exists (startup_script ) and os .path .getsize (startup_script ) > 0 :
467- self .cmdqueue .append ("load '{}'" .format (startup_script ))
472+ self ._startup_commands .append ("load '{}'" .format (startup_script ))
473+
474+ # Transcript files to run instead of interactive command loop
475+ self ._transcript_files = None
476+
477+ # Check for command line args
478+ if allow_cli_args :
479+ parser = argparse .ArgumentParser ()
480+ parser .add_argument ('-t' , '--test' , action = "store_true" ,
481+ help = 'Test against transcript(s) in FILE (wildcards OK)' )
482+ callopts , callargs = parser .parse_known_args ()
483+
484+ # If transcript testing was called for, use other arguments as transcript files
485+ if callopts .test :
486+ self ._transcript_files = callargs
487+ # If commands were supplied at invocation, then add them to the command queue
488+ elif callargs :
489+ self ._startup_commands .extend (callargs )
490+ elif transcript_files :
491+ self ._transcript_files = transcript_files
468492
469493 # The default key for sorting tab completion matches. This only applies when the matches are not
470494 # already marked as sorted by setting self.matches_sorted to True. Its default value performs a
@@ -2242,25 +2266,23 @@ def _cmdloop(self) -> None:
22422266 readline .parse_and_bind (self .completekey + ": complete" )
22432267
22442268 try :
2245- stop = False
2269+ # Run startup commands
2270+ stop = self .runcmds_plus_hooks (self ._startup_commands )
2271+ self ._startup_commands .clear ()
2272+
22462273 while not stop :
2247- if self .cmdqueue :
2248- # Run commands out of cmdqueue if nonempty (populated by commands at invocation)
2249- stop = self .runcmds_plus_hooks (self .cmdqueue )
2250- self .cmdqueue .clear ()
2251- else :
2252- # Otherwise, read a command from stdin
2253- try :
2254- line = self .pseudo_raw_input (self .prompt )
2255- except KeyboardInterrupt as ex :
2256- if self .quit_on_sigint :
2257- raise ex
2258- else :
2259- self .poutput ('^C' )
2260- line = ''
2274+ # Get commands from user
2275+ try :
2276+ line = self .pseudo_raw_input (self .prompt )
2277+ except KeyboardInterrupt as ex :
2278+ if self .quit_on_sigint :
2279+ raise ex
2280+ else :
2281+ self .poutput ('^C' )
2282+ line = ''
22612283
2262- # Run the command along with all associated pre and post hooks
2263- stop = self .onecmd_plus_hooks (line )
2284+ # Run the command along with all associated pre and post hooks
2285+ stop = self .onecmd_plus_hooks (line )
22642286 finally :
22652287 if self .use_rawinput and self .completekey and rl_type != RlType .NONE :
22662288
@@ -2274,7 +2296,6 @@ def _cmdloop(self) -> None:
22742296 elif rl_type == RlType .PYREADLINE :
22752297 # noinspection PyUnresolvedReferences
22762298 readline .rl .mode ._display_completions = orig_pyreadline_display
2277- self .cmdqueue .clear ()
22782299
22792300 # ----- Alias sub-command functions -----
22802301
@@ -2889,10 +2910,8 @@ def cmdenvironment(self) -> str:
28892910 """
28902911 read_only_settings = """
28912912 Commands may be terminated with: {}
2892- Arguments at invocation allowed: {}
28932913 Output redirection and pipes allowed: {}"""
2894- return read_only_settings .format (str (self .statement_parser .terminators ), self .allow_cli_args ,
2895- self .allow_redirection )
2914+ return read_only_settings .format (str (self .statement_parser .terminators ), self .allow_redirection )
28962915
28972916 def show (self , args : argparse .Namespace , parameter : str = '' ) -> None :
28982917 """Shows current settings of parameters.
@@ -3991,7 +4010,6 @@ def cmdloop(self, intro: Optional[str] = None) -> int:
39914010
39924011 _cmdloop() provides the main loop equivalent to cmd.cmdloop(). This is a wrapper around that which deals with
39934012 the following extra features provided by cmd2:
3994- - commands at invocation
39954013 - transcript testing
39964014 - intro banner
39974015 - exit code
@@ -4008,19 +4026,6 @@ def cmdloop(self, intro: Optional[str] = None) -> int:
40084026 original_sigint_handler = signal .getsignal (signal .SIGINT )
40094027 signal .signal (signal .SIGINT , self .sigint_handler )
40104028
4011- if self .allow_cli_args :
4012- parser = argparse .ArgumentParser ()
4013- parser .add_argument ('-t' , '--test' , action = "store_true" ,
4014- help = 'Test against transcript(s) in FILE (wildcards OK)' )
4015- callopts , callargs = parser .parse_known_args ()
4016-
4017- # If transcript testing was called for, use other arguments as transcript files
4018- if callopts .test :
4019- self ._transcript_files = callargs
4020- # If commands were supplied at invocation, then add them to the command queue
4021- elif callargs :
4022- self .cmdqueue .extend (callargs )
4023-
40244029 # Grab terminal lock before the prompt has been drawn by readline
40254030 self .terminal_lock .acquire ()
40264031
0 commit comments