Create or overwrite a macro.
(self, args: argparse.Namespace)
| 4034 | |
| 4035 | @as_subcommand_to("macro", "create", _build_macro_create_parser, help="create or overwrite a macro") |
| 4036 | def _macro_create(self, args: argparse.Namespace) -> None: |
| 4037 | """Create or overwrite a macro.""" |
| 4038 | self.last_result = False |
| 4039 | |
| 4040 | # Validate the macro name |
| 4041 | valid, errmsg = self.statement_parser.is_valid_command(args.name) |
| 4042 | if not valid: |
| 4043 | self.perror(f"Invalid macro name: {errmsg}") |
| 4044 | return |
| 4045 | |
| 4046 | if args.name in self.get_all_commands(): |
| 4047 | self.perror("Macro cannot have the same name as a command") |
| 4048 | return |
| 4049 | |
| 4050 | if args.name in self.aliases: |
| 4051 | self.perror("Macro cannot have the same name as an alias") |
| 4052 | return |
| 4053 | |
| 4054 | # Unquote redirection and terminator tokens |
| 4055 | tokens_to_unquote = (*constants.REDIRECTION_TOKENS, *self.statement_parser.terminators) |
| 4056 | utils.unquote_specific_tokens(args.command_args, tokens_to_unquote) |
| 4057 | |
| 4058 | # Build the macro value string |
| 4059 | value = args.command |
| 4060 | if args.command_args: |
| 4061 | value += " " + " ".join(args.command_args) |
| 4062 | |
| 4063 | # Find all normal arguments |
| 4064 | macro_args = [] |
| 4065 | normal_matches = re.finditer(MacroArg.macro_normal_arg_pattern, value) |
| 4066 | max_arg_num = 0 |
| 4067 | arg_nums = set() |
| 4068 | |
| 4069 | try: |
| 4070 | while True: |
| 4071 | cur_match = normal_matches.__next__() |
| 4072 | |
| 4073 | # Get the number string between the braces |
| 4074 | cur_num_str = re.findall(MacroArg.digit_pattern, cur_match.group())[0] |
| 4075 | cur_num = int(cur_num_str) |
| 4076 | if cur_num < 1: |
| 4077 | self.perror("Argument numbers must be greater than 0") |
| 4078 | return |
| 4079 | |
| 4080 | arg_nums.add(cur_num) |
| 4081 | max_arg_num = max(max_arg_num, cur_num) |
| 4082 | |
| 4083 | macro_args.append(MacroArg(start_index=cur_match.start(), number_str=cur_num_str, is_escaped=False)) |
| 4084 | except StopIteration: |
| 4085 | pass |
| 4086 | |
| 4087 | # Make sure the argument numbers are continuous |
| 4088 | if len(arg_nums) != max_arg_num: |
| 4089 | self.perror(f"Not all numbers between 1 and {max_arg_num} are present in the argument placeholders") |
| 4090 | return |
| 4091 | |
| 4092 | # Find all escaped arguments |
| 4093 | escaped_matches = re.finditer(MacroArg.macro_escaped_arg_pattern, value) |
nothing calls this directly
no test coverage detected