@@ -3332,18 +3332,17 @@ def do_history(self, args: argparse.Namespace) -> None:
33323332 for hi in history :
33333333 self .poutput (hi .pr (script = args .script , expanded = args .expanded , verbose = args .verbose ))
33343334
3335- def _generate_transcript (self , history : List [HistoryItem ], transcript_file : str ) -> None :
3335+ def _generate_transcript (self , history : List [Union [ HistoryItem , str ] ], transcript_file : str ) -> None :
33363336 """Generate a transcript file from a given history of commands."""
3337- # Save the current echo state, and turn it off. We inject commands into the
3338- # output using a different mechanism
33393337 import io
33403338
3339+ # Disable echo and redirection while we manually redirect stdout to a StringIO buffer
3340+ saved_allow_redirection = self .allow_redirection
33413341 saved_echo = self .echo
3342+ saved_stdout = self .stdout
3343+ self .allow_redirection = False
33423344 self .echo = False
33433345
3344- # Redirect stdout to the transcript file
3345- saved_self_stdout = self .stdout
3346-
33473346 # The problem with supporting regular expressions in transcripts
33483347 # is that they shouldn't be processed in the command, just the output.
33493348 # In addition, when we generate a transcript, any slashes in the output
@@ -3379,10 +3378,10 @@ def _generate_transcript(self, history: List[HistoryItem], transcript_file: str)
33793378 # and add the regex-escaped output to the transcript
33803379 transcript += output .replace ('/' , r'\/' )
33813380
3382- # Restore stdout to its original state
3383- self .stdout = saved_self_stdout
3384- # Set echo back to its original state
3381+ # Restore altered attributes to their original state
3382+ self .allow_redirection = saved_allow_redirection
33853383 self .echo = saved_echo
3384+ self .stdout = saved_stdout
33863385
33873386 # finally, we can write the transcript out to the file
33883387 try :
@@ -3438,9 +3437,21 @@ def do_eos(self, _: argparse.Namespace) -> None:
34383437 load_description = ("Run commands in script file that is encoded as either ASCII or UTF-8 text\n "
34393438 "\n "
34403439 "Script should contain one command per line, just like the command would be\n "
3441- "typed in the console." )
3440+ "typed in the console.\n "
3441+ "\n "
3442+ "It loads commands from a script file into a queue and then the normal cmd2\n "
3443+ "REPL resumes control and executes the commands in the queue in FIFO order.\n "
3444+ "If you attempt to redirect/pipe a load command, it will capture the output\n "
3445+ "of the load command itself, not what it adds to the queue.\n "
3446+ "\n "
3447+ "If the -r/--record_transcript flag is used, this command instead records\n "
3448+ "the output of the script commands to a transcript for testing purposes.\n "
3449+ )
34423450
34433451 load_parser = ACArgumentParser (description = load_description )
3452+ setattr (load_parser .add_argument ('-r' , '--record_transcript' ,
3453+ help = 'record the output of the script as a transcript file' ),
3454+ ACTION_ARG_CHOICES , ('path_complete' ,))
34443455 setattr (load_parser .add_argument ('script_path' , help = "path to the script file" ),
34453456 ACTION_ARG_CHOICES , ('path_complete' ,))
34463457
@@ -3474,11 +3485,16 @@ def do_load(self, args: argparse.Namespace) -> None:
34743485 # command queue. Add an "end of script (eos)" command to cleanup the
34753486 # self._script_dir list when done.
34763487 with open (expanded_path , encoding = 'utf-8' ) as target :
3477- self . cmdqueue = target .read ().splitlines () + [ 'eos' ] + self . cmdqueue
3488+ script_commands = target .read ().splitlines ()
34783489 except OSError as ex : # pragma: no cover
34793490 self .perror ("Problem accessing script from '{}': {}" .format (expanded_path , ex ))
34803491 return
34813492
3493+ if args .record_transcript :
3494+ self ._generate_transcript (script_commands , args .record_transcript )
3495+ return
3496+
3497+ self .cmdqueue = script_commands + ['eos' ] + self .cmdqueue
34823498 self ._script_dir .append (os .path .dirname (expanded_path ))
34833499
34843500 relative_load_description = load_description
0 commit comments