diff options
Diffstat (limited to 'src/xpit_/args_helpers.py')
| -rw-r--r-- | src/xpit_/args_helpers.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/xpit_/args_helpers.py b/src/xpit_/args_helpers.py new file mode 100644 index 0000000..1e79911 --- /dev/null +++ b/src/xpit_/args_helpers.py @@ -0,0 +1,102 @@ +from sys import stderr +from . import error +Err = error.Err + +def print_error(msg: str) -> None: + stderr.write(f"{msg}\n") + +def err_arg_unrecognized(arg: str) -> None: + print_error(f"Unrecognized argument: {arg}") + +ERR_UNRECOGNIZED_ARG = "ERR_UNRECOGNIZED_ARG" +ERR_NOT_ENOUGH_ARGS = "ERR_NOT_ENOUGH_ARGS" + +def parse_arg( + argv: list[str], + i: int, + flag_value_map: dict[str, int] +) -> tuple[str, list[str], int, Err | None]: + def success( + flag: str, + values: list[str], + new_i: int + ) -> tuple[str, list[str], int, Err | None]: + return flag, values, new_i, None + def fail(msg: str) -> tuple[str, list[str], int, Err | None]: + return "", [], 0, Err(msg) + + flag: str + values: list[str] = [] + arg: str = argv[i] + i += 1 + if arg[0] != '-': + err_arg_unrecognized(arg) + return fail(ERR_UNRECOGNIZED_ARG) + + value_index = 0 + if arg[1] == '-': + # --flag + delimiter_index = arg.find('=') + if delimiter_index == -1: + flag = arg[2:] + value_index = 0 + else: + flag = arg[2:delimiter_index] + values.append(arg[delimiter_index+1:]) + value_index = 1 + + else: + # -f + flag = arg[1] + value_index = 0 + + if len(arg) != 2: + value = arg[2:] + if value[0] == '=': + value = value[1:] + values.append(value) + value_index += 1 + target_flag_set_arr = None + value_count: int = 0 + for flag_set in flag_value_map: + flag_set_arr = flag_set.split('|') + if flag in flag_set_arr: + target_flag_set_arr = flag_set_arr + value_count = flag_value_map[flag_set] + break + if target_flag_set_arr is None: + err_arg_unrecognized(flag) + return fail(ERR_UNRECOGNIZED_ARG) + while value_index < value_count: + if i >= len(argv): + print_error(f"Not enough arguments for flag '{flag}'") + return fail(ERR_NOT_ENOUGH_ARGS) + values.append(argv[i]) + i += 1 + value_index += 1 + + # NOTE: we always return the first flag in the flag-set for normalization + return success(target_flag_set_arr[0], values, i) + +def parse_generic( + flag_value_map: dict[str, int], + argv: list[str], + i: int +) -> dict[str, list[str]] | None: + res: dict[str, list[str]] = {} + while i < len(argv): + arg = argv[i] + if len(arg) >= 2: + flag, values, i, err = parse_arg(argv, i, flag_value_map) + if err is not None: + return None + + res[flag] = values + #if not callback(flag, values): + # return False + else: + err_arg_unrecognized(arg) + return None + + return res + |
