summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkotfu <kotfu@kotfu.net>2019-02-09 18:39:17 -0700
committerkotfu <kotfu@kotfu.net>2019-02-09 18:39:17 -0700
commit3911335e5533405dd7f65195fe1f20bf3ac08ef8 (patch)
tree1aa2c2b19b3256ce55e145823fdda8dad984d08b
parent321a8c72a48d227011177bb91006ed20607a1e44 (diff)
downloadcmd2-git-3911335e5533405dd7f65195fe1f20bf3ac08ef8.tar.gz
Added -x option to history command for #545
-rw-r--r--cmd2/cmd2.py42
-rw-r--r--cmd2/history.py27
-rw-r--r--tests/test_history.py61
3 files changed, 108 insertions, 22 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 69a6c2aa..1d9cbe85 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -3155,21 +3155,25 @@ class Cmd(cmd.Cmd):
load_ipy(bridge)
history_parser = ACArgumentParser()
- history_parser_group = history_parser.add_mutually_exclusive_group()
- 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',
+ history_action_group = history_parser.add_mutually_exclusive_group()
+ history_action_group.add_argument('-r', '--run', action='store_true', help='run selected history items')
+ history_action_group.add_argument('-e', '--edit', action='store_true',
help='edit and then run selected history items')
- history_parser_group.add_argument('-s', '--script', action='store_true', help='output commands in script format')
- setattr(history_parser_group.add_argument('-o', '--output-file', metavar='FILE',
- help='output commands to a script file'),
+ setattr(history_action_group.add_argument('-o', '--output-file', metavar='FILE',
+ help='output commands to a script file, implies -s'),
ACTION_ARG_CHOICES, ('path_complete',))
- setattr(history_parser_group.add_argument('-t', '--transcript',
- help='output commands and results to a transcript file'),
+ setattr(history_action_group.add_argument('-t', '--transcript',
+ help='output commands and results to a transcript file, implies -s'),
ACTION_ARG_CHOICES, ('path_complete',))
- history_parser_group.add_argument('-v', '--verbose', action='store_true',
+ history_action_group.add_argument('-c', '--clear', action='store_true', help='clear all history')
+
+ history_format_group = history_parser.add_argument_group(title='formatting')
+ history_format_group.add_argument('-s', '--script', action='store_true', help='output commands in script format, i.e. without command numbers')
+ history_format_group.add_argument('-x', '--expanded', action='store_true', help='output expanded commands instead of entered command')
+ history_format_group.add_argument('-v', '--verbose', action='store_true',
help='display history and include expanded commands if they'
' differ from the typed command.')
- history_parser_group.add_argument('-c', '--clear', action="store_true", help='clear all history')
+
history_arg_help = ("empty all history items\n"
"a one history item by number\n"
"a..b, a:b, a:, ..b items by indices (inclusive)\n"
@@ -3181,6 +3185,19 @@ class Cmd(cmd.Cmd):
def do_history(self, args: argparse.Namespace) -> None:
"""View, run, edit, save, or clear previously entered commands"""
+ # -v must be used alone with no other options
+ if args.verbose:
+ if args.clear or args.edit or args.output_file or args.run or args.transcript or args.expanded or args.script:
+ self.poutput("-v can not be used with any other options")
+ self.poutput(self.history_parser.format_usage())
+ return
+
+ # -s and -x can only be used if none of these options are present: [-c -r -e -o -t]
+ if (args.script or args.expanded) and (args.clear or args.edit or args.output_file or args.run or args.transcript):
+ self.poutput("-s and -x can not be used with -c, -r, -e, -o, or -t")
+ self.poutput(self.history_parser.format_usage())
+ return
+
if args.clear:
# Clear command and readline history
self.history.clear()
@@ -3249,10 +3266,7 @@ class Cmd(cmd.Cmd):
else:
# Display the history items retrieved
for hi in history:
- if args.script:
- self.poutput(hi)
- else:
- self.poutput(hi.pr(args.verbose))
+ self.poutput(hi.pr(script=args.script, expanded=args.expanded, verbose=args.verbose))
def _generate_transcript(self, history: List[HistoryItem], transcript_file: str) -> None:
"""Generate a transcript file from a given history of commands."""
diff --git a/cmd2/history.py b/cmd2/history.py
index 0989b7db..ad4b23aa 100644
--- a/cmd2/history.py
+++ b/cmd2/history.py
@@ -14,7 +14,7 @@ from .parsing import Statement
class HistoryItem(str):
"""Class used to represent one command in the History list"""
listformat = ' {:>4} {}\n'
- ex_listformat = ' Ex: {}\n'
+ ex_listformat = ' {:>4}x {}\n'
def __new__(cls, statement: Statement):
"""Create a new instance of HistoryItem
@@ -32,15 +32,30 @@ class HistoryItem(str):
"""Return the command as run which includes shortcuts and aliases resolved plus any changes made in hooks"""
return self.statement.expanded_command_line
- def pr(self, verbose: bool) -> str:
+ def pr(self, script=False, expanded=False, verbose=False) -> str:
"""Represent a HistoryItem in a pretty fashion suitable for printing.
+ If you pass verbose=True, script and expanded will be ignored
+
:return: pretty print string version of a HistoryItem
"""
- ret_str = self.listformat.format(self.idx, str(self).rstrip())
- if verbose and self != self.expanded:
- ret_str += self.ex_listformat.format(self.expanded.rstrip())
-
+ if verbose:
+ ret_str = self.listformat.format(self.idx, str(self).rstrip())
+ if self != self.expanded:
+ ret_str += self.ex_listformat.format(self.idx, self.expanded.rstrip())
+ else:
+ if script:
+ # display without entry numbers
+ if expanded:
+ ret_str = self.expanded.rstrip()
+ else:
+ ret_str = str(self)
+ else:
+ # display a numbered list
+ if expanded:
+ ret_str = self.listformat.format(self.idx, self.expanded.rstrip())
+ else:
+ ret_str = self.listformat.format(self.idx, str(self).rstrip())
return ret_str
diff --git a/tests/test_history.py b/tests/test_history.py
index 0eddcc1f..98d72512 100644
--- a/tests/test_history.py
+++ b/tests/test_history.py
@@ -29,7 +29,7 @@ def hist():
HistoryItem(Statement('', raw='fourth'))])
return h
-def test_history_span(hist):
+def test_history_class_span(hist):
h = hist
assert h == ['first', 'second', 'third', 'fourth']
assert h.span('-2..') == ['third', 'fourth']
@@ -41,7 +41,7 @@ def test_history_span(hist):
assert h.span('-2..-3') == ['third', 'second']
assert h.span('*') == h
-def test_history_get(hist):
+def test_history_class_get(hist):
h = hist
assert h == ['first', 'second', 'third', 'fourth']
assert h.get('') == h
@@ -207,3 +207,60 @@ def test_history_clear(base_app):
# Make sure history is empty
out = run_cmd(base_app, 'history')
assert out == []
+
+def test_history_verbose_with_other_options(base_app):
+ # make sure -v shows a usage error if any other options are present
+ options_to_test = ['-r', '-e', '-o file', '-t file', '-c', '-x']
+ for opt in options_to_test:
+ output = run_cmd(base_app, 'history -v ' + opt)
+ assert len(output) == 3
+ assert output[1].startswith('Usage:')
+
+def test_history_verbose(base_app):
+ # validate function of -v option
+ run_cmd(base_app, 'alias create s shortcuts')
+ run_cmd(base_app, 's')
+ output = run_cmd(base_app, 'history -v')
+ assert len(output) == 3
+ # TODO test for basic formatting once we figure it out
+
+def test_history_script_with_invalid_options(base_app):
+ # make sure -s shows a usage error if -c, -r, -e, -o, or -t are present
+ options_to_test = ['-r', '-e', '-o file', '-t file', '-c']
+ for opt in options_to_test:
+ output = run_cmd(base_app, 'history -s ' + opt)
+ assert len(output) == 3
+ assert output[1].startswith('Usage:')
+
+def test_history_script(base_app):
+ cmds = ['alias create s shortcuts', 's']
+ for cmd in cmds:
+ run_cmd(base_app, cmd)
+ output = run_cmd(base_app, 'history -s')
+ assert output == cmds
+
+def test_history_expanded_with_invalid_options(base_app):
+ # make sure -x shows a usage error if -c, -r, -e, -o, or -t are present
+ options_to_test = ['-r', '-e', '-o file', '-t file', '-c']
+ for opt in options_to_test:
+ output = run_cmd(base_app, 'history -x ' + opt)
+ assert len(output) == 3
+ assert output[1].startswith('Usage:')
+
+def test_history_expanded(base_app):
+ # validate function of -x option
+ cmds = ['alias create s shortcuts', 's']
+ for cmd in cmds:
+ run_cmd(base_app, cmd)
+ output = run_cmd(base_app, 'history -x')
+ expected = [' 1 alias create s shortcuts', ' 2 shortcuts']
+ assert output == expected
+
+def test_history_script_expanded(base_app):
+ # validate function of -s -x options together
+ cmds = ['alias create s shortcuts', 's']
+ for cmd in cmds:
+ run_cmd(base_app, cmd)
+ output = run_cmd(base_app, 'history -sx')
+ expected = ['alias create s shortcuts', 'shortcuts']
+ assert output == expected