summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared Crapo <jared@kotfu.net>2018-01-15 23:18:21 -0700
committerJared Crapo <jared@kotfu.net>2018-01-15 23:18:21 -0700
commitcb7269f21cafb58053be06f2e68df142ca969d73 (patch)
tree2a8add333ca148db53309814ec5b86eba14182d6
parente3bc19fb0d88403d5a4906afe0f323a99e373942 (diff)
downloadcmd2-git-cb7269f21cafb58053be06f2e68df142ca969d73.tar.gz
Implement -o, -r, and -e options for issue #252
-rwxr-xr-xcmd2.py52
-rw-r--r--tests/conftest.py7
-rw-r--r--tests/test_cmd2.py47
3 files changed, 93 insertions, 13 deletions
diff --git a/cmd2.py b/cmd2.py
index a1f02756..f3ec1599 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -1697,14 +1697,14 @@ Paths or arguments that contain spaces must be enclosed in quotes
embed(banner1=banner, exit_msg=exit_msg)
history_parser = argparse.ArgumentParser(
- description='run, edit, and save past commands',
+ description='run, edit, and save previously entered commands',
formatter_class=argparse.RawTextHelpFormatter,
)
- history_parser.add_argument('-s', '--script', action='store_true', help='script format; no separation lines')
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', help='edit and then run selected history items')
- history_parser_group.add_argument('-o', '--output-file', metavar='FILE', type=argparse.FileType('w'), help='output to file')
+ 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_arg_help = """empty all history items
a one history item by number
a..b, a:b, a:, ..b items by indices (inclusive)
@@ -1714,9 +1714,12 @@ a..b, a:b, a:, ..b items by indices (inclusive)
@with_argument_parser(history_parser)
def do_history(self, args):
- # If an argument was supplied, then retrieve partial contents of the history
+ # If an argument was supplied, then retrieve partial contents of the
+ # history
+ cowerdly_refuse_to_run = False
if args.arg:
- # If a character indicating a slice is present, retrieve a slice of the history
+ # If a character indicating a slice is present, retrieve
+ # a slice of the history
arg = args.arg
if '..' in arg or ':' in arg:
try:
@@ -1729,14 +1732,43 @@ a..b, a:b, a:, ..b items by indices (inclusive)
history = self.history.get(arg)
else:
# If no arg given, then retrieve the entire history
+ cowerdly_refuse_to_run = True
history = self.history
- # Display the history items retrieved
- for hi in history:
- if args.script:
- self.poutput(hi)
+ if args.run:
+ if cowerdly_refuse_to_run:
+ self.perror("Cowerdly refusing to run all previously entered commands.", traceback_war=False)
+ self.perror("If this is what you want to do, specify '1:' as the range of history.", traceback_war=False)
else:
- self.poutput(hi.pr())
+ self.cmdqueue.extend(history)
+ elif args.edit:
+ fd, fname = tempfile.mkstemp(suffix='.txt', text=True)
+ with os.fdopen(fd, 'w') as fobj:
+ for cmd in history:
+ fobj.write('{}\n'.format(cmd))
+ try:
+ os.system('"{}" "{}"'.format(self.editor, fname))
+ self.do_load(fname)
+ except:
+ raise
+ finally:
+ os.remove(fname)
+ elif args.output_file:
+ try:
+ with open(os.path.expanduser(args.output_file), 'w') as fobj:
+ for cmd in history:
+ fobj.write('{}\n'.format(cmd))
+ plural = 's' if len(history) > 1 else ''
+ 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)
+ else:
+ # Display the history items retrieved
+ for hi in history:
+ if args.script:
+ self.poutput(hi)
+ else:
+ self.poutput(hi.pr())
def _last_matching(self, arg):
"""Return the last item from the history list that matches arg. Or if arg not provided, return last item.
diff --git a/tests/conftest.py b/tests/conftest.py
index e20d2511..5ecb6f82 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -19,9 +19,9 @@ edit help history load py pyscript quit run save set shell shortcuts
"""
# Help text for the history command
-HELP_HISTORY = """usage: history [-h] [-s] [-r | -e | -o FILE] [arg]
+HELP_HISTORY = """usage: history [-h] [-r | -e | -o FILE] [-s] [arg]
-run, edit, and save past commands
+run, edit, and save previously entered commands
positional arguments:
arg empty all history items
@@ -32,11 +32,12 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
- -s, --script script format; no separation lines
-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
+
"""
# Output from the shortcuts command with default built-in shortcuts
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index 0df3b80a..280df5ab 100644
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -316,6 +316,53 @@ def test_history_with_span_index_error(base_app):
""")
assert out == expected
+def test_history_output_file(base_app):
+ run_cmd(base_app, 'help')
+ run_cmd(base_app, 'shortcuts')
+ run_cmd(base_app, 'help history')
+
+ fd, fname = tempfile.mkstemp(prefix='', suffix='.txt')
+ os.close(fd)
+ run_cmd(base_app, 'history -o "{}"'.format(fname))
+ expected = normalize('\n'.join(['help', 'shortcuts', 'help history']))
+ with open(fname) as f:
+ content = normalize(f.read())
+ assert content == expected
+
+def test_history_edit(base_app, monkeypatch):
+ # Set a fake editor just to make sure we have one. We aren't really
+ # going to call it due to the mock
+ base_app.editor = 'fooedit'
+
+ # Mock out the os.system call so we don't actually open an editor
+ m = mock.MagicMock(name='system')
+ monkeypatch.setattr("os.system", m)
+
+ # Run help command just so we have a command in history
+ run_cmd(base_app, 'help')
+ run_cmd(base_app, 'edit')
+
+ # We have an editor, so should expect a system call
+ m.assert_called_once()
+
+def test_history_run_all_commands(base_app):
+ # make sure we refuse to run all commands as a default
+ run_cmd(base_app, 'shortcuts')
+ out = run_cmd(base_app, 'history -r')
+ # this should generate an error, but we don't currently have a way to
+ # capture stderr in these tests. So we assume that if we got nothing on
+ # standard out, that the error occured because if the commaned executed
+ # then we should have a list of shortcuts in our output
+ assert out == []
+
+def test_history_run_one_command(base_app):
+ run_cmd(base_app, 'help')
+ # because of the way run_cmd works, it will not
+ # process the cmdqueue. So we can check to see
+ # if the cmdqueue has a waiting item
+ run_cmd(base_app, 'history -r 1')
+ assert len(base_app.cmdqueue) == 1
+
def test_base_load(base_app, request):
test_dir = os.path.dirname(request.module.__file__)
filename = os.path.join(test_dir, 'script.txt')