Resolve a macro and return the resulting string. :param statement: the parsed statement from the command line :return: the resolved macro string :raises KeyError: if its not a macro :raises MacroError: if the macro cannot be resolved (e.g. not enough args)
(self, statement: Statement)
| 3150 | return statement |
| 3151 | |
| 3152 | def _resolve_macro(self, statement: Statement) -> str: |
| 3153 | """Resolve a macro and return the resulting string. |
| 3154 | |
| 3155 | :param statement: the parsed statement from the command line |
| 3156 | :return: the resolved macro string |
| 3157 | :raises KeyError: if its not a macro |
| 3158 | :raises MacroError: if the macro cannot be resolved (e.g. not enough args) |
| 3159 | """ |
| 3160 | if statement.command not in self.macros: |
| 3161 | raise KeyError(f"{statement.command} is not a macro") |
| 3162 | |
| 3163 | macro = self.macros[statement.command] |
| 3164 | |
| 3165 | # Make sure enough arguments were passed in |
| 3166 | if len(statement.arg_list) < macro.minimum_arg_count: |
| 3167 | plural = "" if macro.minimum_arg_count == 1 else "s" |
| 3168 | raise MacroError(f"The macro '{statement.command}' expects at least {macro.minimum_arg_count} argument{plural}") |
| 3169 | |
| 3170 | # Resolve the arguments in reverse and read their values from statement.argv since those |
| 3171 | # are unquoted. Macro args should have been quoted when the macro was created. |
| 3172 | resolved = macro.value |
| 3173 | reverse_arg_list = sorted(macro.args, key=lambda ma: ma.start_index, reverse=True) |
| 3174 | |
| 3175 | for macro_arg in reverse_arg_list: |
| 3176 | if macro_arg.is_escaped: |
| 3177 | to_replace = "{{" + macro_arg.number_str + "}}" |
| 3178 | replacement = "{" + macro_arg.number_str + "}" |
| 3179 | else: |
| 3180 | to_replace = "{" + macro_arg.number_str + "}" |
| 3181 | replacement = statement.argv[int(macro_arg.number_str)] |
| 3182 | |
| 3183 | parts = resolved.rsplit(to_replace, maxsplit=1) |
| 3184 | resolved = parts[0] + replacement + parts[1] |
| 3185 | |
| 3186 | # Append extra arguments and use statement.arg_list since these arguments need their quotes preserved |
| 3187 | for stmt_arg in statement.arg_list[macro.minimum_arg_count :]: |
| 3188 | resolved += " " + stmt_arg |
| 3189 | |
| 3190 | # Restore any terminator, suffix, redirection, etc. |
| 3191 | return resolved + statement.post_command |
| 3192 | |
| 3193 | def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState: |
| 3194 | """Set up a command's output redirection for >, >>, and |. |