Skip to content

Commit 6bc3c75

Browse files
committed
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
1 parent bd948d7 commit 6bc3c75

File tree

6 files changed

+60
-17
lines changed

6 files changed

+60
-17
lines changed

cmd2.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,7 @@ def onecmd_plus_hooks(self, line):
962962
(stop, statement) = self.postparsing_precmd(statement)
963963
if stop:
964964
return self.postparsing_postcmd(stop)
965-
if statement.parsed.command not in self.excludeFromHistory:
966-
self.history.append(statement.parsed.raw)
965+
967966
try:
968967
if self.allow_redirection:
969968
self._redirect_output(statement)
@@ -1012,7 +1011,11 @@ def runcmds_plus_hooks(self, cmds):
10121011
self.cmdqueue = list(cmds) + self.cmdqueue
10131012
try:
10141013
while self.cmdqueue and not stop:
1015-
stop = self.onecmd_plus_hooks(self.cmdqueue.pop(0))
1014+
line = self.cmdqueue.pop(0)
1015+
if self.echo and line != 'eos':
1016+
self.poutput('{}{}'.format(self.prompt, line))
1017+
1018+
stop = self.onecmd_plus_hooks(line)
10161019
finally:
10171020
# Clear out the command queue and script directory stack, just in
10181021
# case we hit an error and they were not completed.
@@ -1154,6 +1157,10 @@ def onecmd(self, line):
11541157
if not funcname:
11551158
return self.default(statement)
11561159

1160+
# Since we have a valid command store it in the history
1161+
if statement.parsed.command not in self.excludeFromHistory:
1162+
self.history.append(statement.parsed.raw)
1163+
11571164
try:
11581165
func = getattr(self, funcname)
11591166
except AttributeError:
@@ -1808,8 +1815,9 @@ def do_ipy(self, arg):
18081815
history_parser_group.add_argument('-r', '--run', action='store_true', help='run selected history items')
18091816
history_parser_group.add_argument('-e', '--edit', action='store_true',
18101817
help='edit and then run selected history items')
1811-
history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output to file')
1812-
history_parser.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
1818+
history_parser_group.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
1819+
history_parser_group.add_argument('-o', '--output-file', metavar='FILE', help='output commands to a script file')
1820+
history_parser_group.add_argument('-t', '--transcript', help='output commands and results to a transcript file')
18131821
_history_arg_help = """empty all history items
18141822
a one history item by number
18151823
a..b, a:b, a:, ..b items by indices (inclusive)
@@ -1838,7 +1846,8 @@ def do_history(self, args):
18381846
else:
18391847
# If no arg given, then retrieve the entire history
18401848
cowardly_refuse_to_run = True
1841-
history = self.history
1849+
# Get a copy of the history so it doesn't get mutated while we are using it
1850+
history = self.history[:]
18421851

18431852
if args.run:
18441853
if cowardly_refuse_to_run:
@@ -1871,6 +1880,28 @@ def do_history(self, args):
18711880
self.pfeedback('{} command{} saved to {}'.format(len(history), plural, args.output_file))
18721881
except Exception as e:
18731882
self.perror('Saving {!r} - {}'.format(args.output_file, e), traceback_war=False)
1883+
elif args.transcript:
1884+
# Make sure echo is on so commands print to standard out
1885+
saved_echo = self.echo
1886+
self.echo = True
1887+
1888+
# Redirect stdout to the transcript file
1889+
saved_self_stdout = self.stdout
1890+
self.stdout = open(args.transcript, 'w')
1891+
1892+
# Run all of the commands in the history with output redirected to transcript and echo on
1893+
self.runcmds_plus_hooks(history)
1894+
1895+
# Restore stdout to its original state
1896+
self.stdout.close()
1897+
self.stdout = saved_self_stdout
1898+
1899+
# Set echo back to its original state
1900+
self.echo = saved_echo
1901+
1902+
plural = 's' if len(history) > 1 else ''
1903+
self.pfeedback('{} command{} and outputs saved to transcript file {!r}'.format(len(history), plural,
1904+
args.transcript))
18741905
else:
18751906
# Display the history items retrieved
18761907
for hi in history:

examples/pirate.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ def __init__(self):
2525
"""Initialize the base class as well as this one"""
2626
Cmd.__init__(self)
2727
# prompts and defaults
28-
self.gold = 3
28+
self.gold = 0
2929
self.initial_gold = self.gold
3030
self.prompt = 'arrr> '
3131

3232
def default(self, line):
3333
"""This handles unknown commands."""
34-
print('What mean ye by "{0}"?'.format(line))
34+
self.poutput('What mean ye by "{0}"?'.format(line))
3535

3636
def precmd(self, line):
3737
"""Runs just before a command line is parsed, but after the prompt is presented."""
@@ -41,10 +41,10 @@ def precmd(self, line):
4141
def postcmd(self, stop, line):
4242
"""Runs right before a command is about to return."""
4343
if self.gold != self.initial_gold:
44-
print('Now we gots {0} doubloons'
44+
self.poutput('Now we gots {0} doubloons'
4545
.format(self.gold))
4646
if self.gold < 0:
47-
print("Off to debtorrr's prison.")
47+
self.poutput("Off to debtorrr's prison.")
4848
stop = True
4949
return stop
5050

@@ -61,17 +61,17 @@ def do_drink(self, arg):
6161
self.gold -= int(arg)
6262
except ValueError:
6363
if arg:
64-
print('''What's "{0}"? I'll take rrrum.'''.format(arg))
64+
self.poutput('''What's "{0}"? I'll take rrrum.'''.format(arg))
6565
self.gold -= 1
6666

6767
def do_quit(self, arg):
6868
"""Quit the application gracefully."""
69-
print("Quiterrr!")
69+
self.poutput("Quiterrr!")
7070
return True
7171

7272
def do_sing(self, arg):
7373
"""Sing a colorful song."""
74-
print(self.colorize(arg, self.songcolor))
74+
self.poutput(self.colorize(arg, self.songcolor))
7575

7676
yo_parser = argparse.ArgumentParser()
7777
yo_parser.add_argument('--ho', type=int, default=2, help="How often to chant 'ho'")
@@ -84,7 +84,7 @@ def do_yo(self, args):
8484
chant = ['yo'] + ['ho'] * args.ho
8585
separator = ', ' if args.commas else ' '
8686
chant = separator.join(chant)
87-
print('{0} and a bottle of {1}'.format(chant, args.beverage))
87+
self.poutput('{0} and a bottle of {1}'.format(chant, args.beverage))
8888

8989

9090
if __name__ == '__main__':
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
arrr> loot
2+
Now we gots 1 doubloons
3+
arrr> loot
4+
Now we gots 2 doubloons
5+
arrr> loot
6+
Now we gots 3 doubloons
7+
arrr> drink 3
8+
Now we gots 0 doubloons
9+
arrr> yo --ho 3 rum
10+
yo ho ho ho and a bottle of rum

tests/conftest.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"""
2020

2121
# Help text for the history command
22-
HELP_HISTORY = """usage: history [-h] [-r | -e | -o FILE] [-s] [arg]
22+
HELP_HISTORY = """usage: history [-h] [-r | -e | -s | -o FILE | -t TRANSCRIPT] [arg]
2323
2424
View, run, edit, and save previously entered commands.
2525
@@ -34,9 +34,11 @@
3434
-h, --help show this help message and exit
3535
-r, --run run selected history items
3636
-e, --edit edit and then run selected history items
37-
-o FILE, --output-file FILE
38-
output to file
3937
-s, --script script format; no separation lines
38+
-o FILE, --output-file FILE
39+
output commands to a script file
40+
-t TRANSCRIPT, --transcript TRANSCRIPT
41+
output commands and results to a transcript file
4042
"""
4143

4244
# Output from the shortcuts command with default built-in shortcuts

0 commit comments

Comments
 (0)