77from typing import List , Tuple
88
99from . import constants
10+ from . import utils
1011
1112LINE_FEED = '\n '
1213
@@ -33,6 +34,10 @@ class Statement(str):
3334 redirection or terminators. quoted arguments remain
3435 quoted.
3536 :type args: str or None
37+ :var: argv: a list of arguments a la sys.argv. Quotes, if any, are removed
38+ from the elements of the list, and aliases and shortcuts
39+ are expanded
40+ :type argv: list
3641 :var terminator: the charater which terminated the multiline command, if
3742 there was one
3843 :type terminator: str or None
@@ -53,6 +58,7 @@ def __init__(self, obj):
5358 self .command = None
5459 self .multiline_command = None
5560 self .args = None
61+ self .argv = None
5662 self .terminator = None
5763 self .suffix = None
5864 self .pipe_to = None
@@ -65,7 +71,14 @@ def command_and_args(self):
6571
6672 Quoted arguments remain quoted.
6773 """
68- return '{} {}' .format ('' if self .command is None else self .command , self .args ).strip ()
74+ if self .command and self .args :
75+ rtn = '{} {}' .format (self .command , self .args )
76+ elif self .command :
77+ # we are trusting that if we get here that self.args is None
78+ rtn = self .command
79+ else :
80+ rtn = None
81+ return rtn
6982
7083
7184class StatementParser ():
@@ -175,6 +188,7 @@ def parse(self, rawinput: str) -> Statement:
175188
176189 command = None
177190 args = None
191+ argv = None
178192
179193 # lex the input into a list of tokens
180194 tokens = self .tokenize (rawinput )
@@ -198,7 +212,8 @@ def parse(self, rawinput: str) -> Statement:
198212 else :
199213 terminator_pos = tokens .index (terminator )
200214 # everything before the first terminator is the command and the args
201- (command , args ) = self ._command_and_args (tokens [:terminator_pos ])
215+ argv = tokens [:terminator_pos ]
216+ (command , args ) = self ._command_and_args (argv )
202217 # we will set the suffix later
203218 # remove all the tokens before and including the terminator
204219 tokens = tokens [terminator_pos + 1 :]
@@ -210,6 +225,7 @@ def parse(self, rawinput: str) -> Statement:
210225 # because redirectors can only be after a terminator
211226 command = testcommand
212227 args = testargs
228+ argv = tokens
213229 tokens = []
214230
215231 # check for output redirect
@@ -253,7 +269,8 @@ def parse(self, rawinput: str) -> Statement:
253269 suffix = None
254270 if not command :
255271 # command could already have been set, if so, don't set it again
256- (command , args ) = self ._command_and_args (tokens )
272+ argv = tokens
273+ (command , args ) = self ._command_and_args (argv )
257274
258275 # set multiline
259276 if command in self .multiline_commands :
@@ -268,8 +285,9 @@ def parse(self, rawinput: str) -> Statement:
268285 statement .raw = rawinput
269286 statement .command = command
270287 # if there are no args we will use None since we don't have to worry
271- # about compatibility wiht standard library cmd
288+ # about compatibility with standard library cmd
272289 statement .args = args
290+ statement .argv = list (map (lambda x : utils .strip_quotes (x ), argv ))
273291 statement .terminator = terminator
274292 statement .output = output
275293 statement .output_to = output_to
@@ -291,10 +309,13 @@ def parse_command_only(self, rawinput: str) -> Statement:
291309 (command , args ) = self ._command_and_args (tokens )
292310
293311 # build the statement
294- statement = Statement (args )
312+ # string representation of args must be an empty string instead of
313+ # None for compatibility with standard library cmd
314+ statement = Statement ('' if args is None else args )
295315 statement .raw = rawinput
296316 statement .command = command
297317 statement .args = args
318+ statement .argv = tokens
298319 return statement
299320
300321 def _expand (self , line : str ) -> str :
@@ -341,7 +362,7 @@ def _command_and_args(tokens: List[str]) -> Tuple[str, str]:
341362 with cmd in the standard library.
342363 """
343364 command = None
344- args = ''
365+ args = None
345366
346367 if tokens :
347368 command = tokens [0 ]
0 commit comments