summaryrefslogtreecommitdiff
path: root/cmd2.py
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2017-02-03 00:07:49 -0500
committerTodd Leonhardt <todd.leonhardt@gmail.com>2017-02-03 00:07:49 -0500
commita9b9cce70bd9aea81141c7e02d4be953cafe5ec2 (patch)
tree799889b05a74bd50ebe6e740caa4eea2787812e9 /cmd2.py
parent1a6dd328d834a8475acceb9211ec4f24fecc9af7 (diff)
downloadcmd2-git-a9b9cce70bd9aea81141c7e02d4be953cafe5ec2.tar.gz
Fixed optparse parsing of arguments so it works correctly both with embedded quotes and mid-line options.
Diffstat (limited to 'cmd2.py')
-rwxr-xr-xcmd2.py25
1 files changed, 21 insertions, 4 deletions
diff --git a/cmd2.py b/cmd2.py
index 190a5c8f..4941580e 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -33,6 +33,7 @@ import optparse
import os
import platform
import re
+import shlex
import six
import subprocess
import sys
@@ -76,6 +77,13 @@ __version__ = '0.7.0'
pyparsing.ParserElement.enablePackrat()
+# If this is False (default), then non-option arguments are passed to the "do" methods using @options as one big string.
+# If this is True, then non-option arguments are passed to the "do" methods using @options as a list of strings (shlex).
+# TODO: Figure out a good way to make this configurable by the user in cmd2.Cmd __init__ or something
+# But it needs to remain False by default for reasons of backwards compatibility.
+USE_ARGUMENT_LISTS_INSTEAD_OF_STRINGS = False
+
+
class OptionParser(optparse.OptionParser):
def exit(self, status=0, msg=None):
self.values._exit = True
@@ -109,7 +117,13 @@ def remaining_args(oldArgs, newArgList):
'''
pattern = '\s+'.join(re.escape(a) for a in newArgList) + '\s*$'
matchObj = re.search(pattern, oldArgs)
- return oldArgs[matchObj.start():]
+ try:
+ remaining = oldArgs[matchObj.start():]
+ except:
+ # Don't preserve spacing, but at least we don't crash and we do preserve args and their order
+ remaining = ' '.join(newArgList)
+
+ return remaining
def _attr_get_(obj, attr):
@@ -135,7 +149,7 @@ optparse.Values.get = _attr_get_
options_defined = [] # used to distinguish --options from SQL-style --comments
-def options(option_list, arg_desc="arg"):
+def options(option_list, arg_desc="arg", arg_list=USE_ARGUMENT_LISTS_INSTEAD_OF_STRINGS):
'''Used as a decorator and passed a list of optparse-style options,
alters a cmd2 method to populate its ``opts`` argument from its
raw text argument.
@@ -165,12 +179,15 @@ def options(option_list, arg_desc="arg"):
def new_func(instance, arg):
try:
- opts, newArgList = optionParser.parse_args(arg.split())
+ opts, newArgList = optionParser.parse_args(shlex.split(arg))
# Must find the remaining args in the original argument list, but
# mustn't include the command itself
# if hasattr(arg, 'parsed') and newArgList[0] == arg.parsed.command:
# newArgList = newArgList[1:]
- newArgs = remaining_args(arg, newArgList)
+ if arg_list:
+ newArgs = newArgList
+ else:
+ newArgs = remaining_args(arg, newArgList)
if isinstance(arg, ParsedString):
arg = arg.with_args_replaced(newArgs)
else: