@@ -142,15 +142,21 @@ def __init__(
142142 )
143143
144144 # aliases have to be a word, so make a regular expression
145- # that matches the first word in the line. This regex has two
146- # parts, the first parenthesis enclosed group matches one
147- # or more non-whitespace characters with a non-greedy match
148- # (that's what the '+?' part does). The second group must be
149- # dynamically created because it needs to match either whitespace,
150- # something in REDIRECTION_CHARS, one of the terminators,
151- # or the end of the string. We use \A and \Z to ensure we always
152- # match the beginning and end of a string that may have multiple
153- # lines (if it's a multiline command)
145+ # that matches the first word in the line. This regex has three
146+ # parts:
147+ # - the '\A\s*' matches the beginning of the string (even
148+ # if contains multiple lines) and gobbles up any leading
149+ # whitespace
150+ # - the first parenthesis enclosed group matches one
151+ # or more non-whitespace characters with a non-greedy match
152+ # (that's what the '+?' part does). The non-greedy match
153+ # ensures that this first group doesn't include anything
154+ # matched by the second group
155+ # - the second parenthesis group must be dynamically created
156+ # because it needs to match either whitespace, something in
157+ # REDIRECTION_CHARS, one of the terminators, or the end of
158+ # the string (\Z matches the end of the string even if it
159+ # contains multiple lines)
154160 second_group_items = []
155161 second_group_items .extend (constants .REDIRECTION_CHARS )
156162 second_group_items .extend (terminators )
@@ -162,7 +168,7 @@ def __init__(
162168 # join them up with a pipe
163169 second_group = '|' .join (second_group_items )
164170 # build the regular expression
165- expr = r'\A(\S+?)({})' .format (second_group )
171+ expr = r'\A\s* (\S+?)({})' .format (second_group )
166172 self .command_pattern = re .compile (expr )
167173
168174 def tokenize (self , line : str ) -> List [str ]:
0 commit comments