summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2018-01-20 20:01:24 -0500
committerTodd Leonhardt <todd.leonhardt@gmail.com>2018-01-20 20:01:24 -0500
commit6bc3c7528b02f0160c31eb008f1218ee4c3344bc (patch)
tree48f369edfa4225e38afc5eca5695c14646e54979
parentbd948d727e0e13fa5fd77199c06fcd3dfdda9b39 (diff)
downloadcmd2-git-6bc3c7528b02f0160c31eb008f1218ee4c3344bc.tar.gz
History enhancements
History changes: - Unknown commands are no longer saved in the history - history command now has a -t option to generate a transcript based on commands in the history Also: - Moved examples transcripts from examples to examples/transcripts - Added a new transcript for use with the pirate.py example
-rwxr-xr-xcmd2.py43
-rwxr-xr-xexamples/pirate.py16
-rw-r--r--examples/transcripts/exampleSession.txt (renamed from examples/exampleSession.txt)0
-rw-r--r--examples/transcripts/pirate.transcript10
-rw-r--r--examples/transcripts/transcript_regex.txt (renamed from examples/transcript_regex.txt)0
-rw-r--r--tests/conftest.py8
6 files changed, 60 insertions, 17 deletions
diff --git a/cmd2.py b/cmd2.py
index 39522f27..0e57da89 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -962,8 +962,7 @@ class Cmd(cmd.Cmd):
(stop, statement) = self.postparsing_precmd(statement)
if stop:
return self.postparsing_postcmd(stop)
- if statement.parsed.command not in self.excludeFromHistory:
- self.history.append(statement.parsed.raw)
+
try:
if self.allow_redirection:
self._redirect_output(statement)
@@ -1012,7 +1011,11 @@ class Cmd(cmd.Cmd):
self.cmdqueue = list(cmds) + self.cmdqueue
try:
while self.cmdqueue and not stop:
- stop = self.onecmd_plus_hooks(self.cmdqueue.pop(0))
+ line = self.cmdqueue.pop(0)
+ if self.echo and line != 'eos':
+ self.poutput('{}{}'.format(self.prompt, line))
+
+ stop = self.onecmd_plus_hooks(line)
finally:
# Clear out the command queue and script directory stack, just in
# case we hit an error and they were not completed.
@@ -1154,6 +1157,10 @@ class Cmd(cmd.Cmd):
if not funcname:
return self.default(statement)
+ # Since we have a valid command store it in the history
+ if statement.parsed.command not in self.excludeFromHistory:
+ self.history.append(statement.parsed.raw)
+
try:
func = getattr(self, funcname)
except AttributeError:
@@ -1808,8 +1815,9 @@ Paths or arguments that contain spaces must be enclosed in quotes
history_parser_group.add_argument('-r', '--run', action='store_true', help='run selected history items')
history_parser_group.add_argument('-e', '--edit', action='store_true',
help='edit and then run selected history items')
- history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output to file')
- history_parser.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
+ history_parser_group.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
+ history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output commands to a script file')
+ history_parser_group.add_argument('-t', '--transcript', help='output commands and results to a transcript file')
_history_arg_help = """empty all history items
a one history item by number
a..b, a:b, a:, ..b items by indices (inclusive)
@@ -1838,7 +1846,8 @@ a..b, a:b, a:, ..b items by indices (inclusive)
else:
# If no arg given, then retrieve the entire history
cowardly_refuse_to_run = True
- history = self.history
+ # Get a copy of the history so it doesn't get mutated while we are using it
+ history = self.history[:]
if args.run:
if cowardly_refuse_to_run:
@@ -1871,6 +1880,28 @@ a..b, a:b, a:, ..b items by indices (inclusive)
self.pfeedback('{} command{} saved to {}'.format(len(history), plural, args.output_file))
except Exception as e:
self.perror('Saving {!r} - {}'.format(args.output_file, e), traceback_war=False)
+ elif args.transcript:
+ # Make sure echo is on so commands print to standard out
+ saved_echo = self.echo
+ self.echo = True
+
+ # Redirect stdout to the transcript file
+ saved_self_stdout = self.stdout
+ self.stdout = open(args.transcript, 'w')
+
+ # Run all of the commands in the history with output redirected to transcript and echo on
+ self.runcmds_plus_hooks(history)
+
+ # Restore stdout to its original state
+ self.stdout.close()
+ self.stdout = saved_self_stdout
+
+ # Set echo back to its original state
+ self.echo = saved_echo
+
+ plural = 's' if len(history) > 1 else ''
+ self.pfeedback('{} command{} and outputs saved to transcript file {!r}'.format(len(history), plural,
+ args.transcript))
else:
# Display the history items retrieved
for hi in history:
diff --git a/examples/pirate.py b/examples/pirate.py
index dd9fd98c..06fdb61b 100755
--- a/examples/pirate.py
+++ b/examples/pirate.py
@@ -25,13 +25,13 @@ class Pirate(Cmd):
"""Initialize the base class as well as this one"""
Cmd.__init__(self)
# prompts and defaults
- self.gold = 3
+ self.gold = 0
self.initial_gold = self.gold
self.prompt = 'arrr> '
def default(self, line):
"""This handles unknown commands."""
- print('What mean ye by "{0}"?'.format(line))
+ self.poutput('What mean ye by "{0}"?'.format(line))
def precmd(self, line):
"""Runs just before a command line is parsed, but after the prompt is presented."""
@@ -41,10 +41,10 @@ class Pirate(Cmd):
def postcmd(self, stop, line):
"""Runs right before a command is about to return."""
if self.gold != self.initial_gold:
- print('Now we gots {0} doubloons'
+ self.poutput('Now we gots {0} doubloons'
.format(self.gold))
if self.gold < 0:
- print("Off to debtorrr's prison.")
+ self.poutput("Off to debtorrr's prison.")
stop = True
return stop
@@ -61,17 +61,17 @@ class Pirate(Cmd):
self.gold -= int(arg)
except ValueError:
if arg:
- print('''What's "{0}"? I'll take rrrum.'''.format(arg))
+ self.poutput('''What's "{0}"? I'll take rrrum.'''.format(arg))
self.gold -= 1
def do_quit(self, arg):
"""Quit the application gracefully."""
- print("Quiterrr!")
+ self.poutput("Quiterrr!")
return True
def do_sing(self, arg):
"""Sing a colorful song."""
- print(self.colorize(arg, self.songcolor))
+ self.poutput(self.colorize(arg, self.songcolor))
yo_parser = argparse.ArgumentParser()
yo_parser.add_argument('--ho', type=int, default=2, help="How often to chant 'ho'")
@@ -84,7 +84,7 @@ class Pirate(Cmd):
chant = ['yo'] + ['ho'] * args.ho
separator = ', ' if args.commas else ' '
chant = separator.join(chant)
- print('{0} and a bottle of {1}'.format(chant, args.beverage))
+ self.poutput('{0} and a bottle of {1}'.format(chant, args.beverage))
if __name__ == '__main__':
diff --git a/examples/exampleSession.txt b/examples/transcripts/exampleSession.txt
index 840bee60..840bee60 100644
--- a/examples/exampleSession.txt
+++ b/examples/transcripts/exampleSession.txt
diff --git a/examples/transcripts/pirate.transcript b/examples/transcripts/pirate.transcript
new file mode 100644
index 00000000..570f0cd7
--- /dev/null
+++ b/examples/transcripts/pirate.transcript
@@ -0,0 +1,10 @@
+arrr> loot
+Now we gots 1 doubloons
+arrr> loot
+Now we gots 2 doubloons
+arrr> loot
+Now we gots 3 doubloons
+arrr> drink 3
+Now we gots 0 doubloons
+arrr> yo --ho 3 rum
+yo ho ho ho and a bottle of rum
diff --git a/examples/transcript_regex.txt b/examples/transcripts/transcript_regex.txt
index 7d017dee..7d017dee 100644
--- a/examples/transcript_regex.txt
+++ b/examples/transcripts/transcript_regex.txt
diff --git a/tests/conftest.py b/tests/conftest.py
index 030172a1..319e54fe 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -19,7 +19,7 @@ edit help history load py pyscript quit set shell shortcuts
"""
# Help text for the history command
-HELP_HISTORY = """usage: history [-h] [-r | -e | -o FILE] [-s] [arg]
+HELP_HISTORY = """usage: history [-h] [-r | -e | -s | -o FILE | -t TRANSCRIPT] [arg]
View, run, edit, and save previously entered commands.
@@ -34,9 +34,11 @@ optional arguments:
-h, --help show this help message and exit
-r, --run run selected history items
-e, --edit edit and then run selected history items
- -o FILE, --output-file FILE
- output to file
-s, --script script format; no separation lines
+ -o FILE, --output-file FILE
+ output commands to a script file
+ -t TRANSCRIPT, --transcript TRANSCRIPT
+ output commands and results to a transcript file
"""
# Output from the shortcuts command with default built-in shortcuts