From c2a95af8767d4aad217f51f0fc899c4ebbcaa5e0 Mon Sep 17 00:00:00 2001 From: Alen Date: Sun, 19 Jan 2025 18:37:43 +0400 Subject: Make jflatten.py and nano_config.py executable --- dot_local/bin/executable_jflatten.py | 113 +++++++++++ dot_local/bin/executable_nano_config.py | 346 ++++++++++++++++++++++++++++++++ dot_local/bin/jflatten.py | 113 ----------- dot_local/bin/nano_config.py | 346 -------------------------------- 4 files changed, 459 insertions(+), 459 deletions(-) create mode 100644 dot_local/bin/executable_jflatten.py create mode 100644 dot_local/bin/executable_nano_config.py delete mode 100755 dot_local/bin/jflatten.py delete mode 100755 dot_local/bin/nano_config.py diff --git a/dot_local/bin/executable_jflatten.py b/dot_local/bin/executable_jflatten.py new file mode 100644 index 0000000..99849dc --- /dev/null +++ b/dot_local/bin/executable_jflatten.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +import argparse +import decimal +import json +import sys + +GREEN = "\033[1;32m" +GREY = "\033[0;37m" +CLEAR = "\033[0m" +RED = "\033[1;31m" +YELLOW = "\033[1;33m" +BLUE = "\033[1;34m" +MAGENTA = "\033[1;35m" + + +def flatten(*path, obj): + if isinstance(obj, list): + yield path, obj + for n, value in enumerate(obj): + yield from flatten(*path, n, obj=value) + elif isinstance(obj, dict): + yield path, obj + for key, value in obj.items(): + yield from flatten(*path, key, obj=value) + else: + yield path, obj + + +def fmt_path(*path, colour): + parts = [] + if not colour: + for part in path: + parts.append(f"[{part}]" if isinstance(part, int) else f".{part}") + else: + for part in path: + if isinstance(part, int): + parts.append(f"{GREY}[{BLUE}{part}{GREY}]{CLEAR}") + else: + parts.append(f"{GREY}.{MAGENTA}{part}{CLEAR}") + return "".join(parts) + + +def fmt_value(value, colour): + if not colour: + return { + None: "null", + True: "true", + False: "false", + }.get(value, str(value)) + if value is None: + return f"{GREY}null{CLEAR}" + if value is True: + return f"{GREEN}true{CLEAR}" + if value is False: + return f"{RED}false{CLEAR}" + if isinstance(value, str): + return f"{YELLOW}{value}{CLEAR}" + if isinstance(value, (int, float, decimal.Decimal)): + return f"{BLUE}{value}{CLEAR}" + return str(value) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--sort-keys", "-s", action="store_true") + parser.add_argument("--json", "-j", action="store_true") + parser.add_argument("--show-empty-collections", action="store_true") + parser.add_argument("--colour", "-c", action="store_true") + parser.add_argument("--no-colour", "-C", action="store_true") + parser.add_argument("file", nargs="?") + args = parser.parse_args() + + if args.file: + with open(args.file) as f: + data = json.load(f) + else: + data = json.load(sys.stdin) + + flattened = ( + (path, value) + for path, value in flatten(obj=data) + if not isinstance(value, (dict, list)) + or not value + and args.show_empty_collections + ) + + if args.json: + print( + json.dumps( + {fmt_path(*path, colour=False): value for path, value in flattened}, + indent=True, + sort_keys=args.sort_keys, + ), + ) + return + + if args.sort_keys: + flattened = sorted(flattened) + colour = not args.no_colour and (args.colour or sys.stdout.isatty()) + flattened_fmt = ( + (fmt_path(*path, colour=colour), fmt_value(value, colour=colour)) + for path, value in flattened + ) + + if args.json: + print(json.dumps(dict(flattened_fmt), indent=True)) + else: + print("\n".join(f"{path}:{value}" for path, value in flattened_fmt)) + + +if __name__ == "__main__": + main() diff --git a/dot_local/bin/executable_nano_config.py b/dot_local/bin/executable_nano_config.py new file mode 100644 index 0000000..8d35801 --- /dev/null +++ b/dot_local/bin/executable_nano_config.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import argparse +import json +import subprocess +import tempfile +from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from collections.abc import Mapping + from typing import TypeAlias + +Version: TypeAlias = tuple[int, ...] + +OPTIONS: Mapping[str, tuple[str, Version, Version | None]] = { + "afterends": ("nextword function (Ctrl+Right) stops at word ends", (4, 0), None), + "atblanks": ("Soft wrapping breaks on spaces", (4, 0), None), + "nonewlines": ("Do not ensure final newline", (4, 1), None), + "historylog": ("Remember search history", (4, 0), None), + "linenumbers": ("Show line numbers", (4, 0), None), + "locking": ("Vim-style soft lock files", (4, 0), None), + "mouse": ("Enable mouse", (4, 0), None), + "multibuffer": ("Allow multiple buffers", (4, 0), None), + "positionlog": ("Remember place in file", (4, 0), None), + "quickblank": ("Clear status bar after one keystroke", (4, 0), None), + "regexp": ("Regex search by default", (4, 0), None), + "smarthome": ("Home toggles start of line and start of text", (4, 0), None), + "speller": ("Spelling checker", (4, 0), None), + "suspend": ("Allow suspending", (4, 0), (4, 9)), + "suspendable": ("Allow suspending", (4, 9), (6, 0)), + "tabsize 4": ("Sane tab size", (4, 0), None), + "tabstospaces": ("Convert tabs to spaces", (4, 0), None), + "whitespace": ("Whitespace characters", (4, 0), None), + "zap": ("Let delete/backspace delete selection", (4, 0), None), + "indicator": ("Scrollbar on the right", (5, 0), None), + "minibar": ("Supress title bar and show state at the bottom", (5, 5), None), + "guidestripe 80": ("Show guide stripe", (6, 1), None), + "stateflags": ("Show state in title bar", (5, 3), None), + "magic": ("Fall back to libmagic for syntax choosing", (4, 0), (5, 3)), +} +BINDS: Mapping[str, tuple[str, Version, Version | None]] = { + "suspend main": ("Allow suspending", (6, 0), None), +} +DEFAULT_BINDS: Mapping[str, tuple[str, Version, Version | None]] = {} + + +def _named_colour( + version: Version, + colour: str, + base16: bool, +) -> str: + """Based on src/rcfile.c""" + _ansi_8 = [ + "red", + "green", + "blue", + "magenta", + "yellow", + "cyan", + "white", + "black", + ] + _ansi_16 = [ + *_ansi_8, + *(f"light{colour}" for colour in _ansi_8), + *(f"bright{colour}" for colour in _ansi_8), + "grey", + "gray", + ] + _named_256 = [ + "pink", + "purple", + "mauve", + "lagoon", + "mint", + "lime", + "peach", + "orange", + "latte", + "rosy", + "beet", + "plum", + "sea", + "sky", + "slate", + "teal", + "sage", + "brown", + "ocher", + "sand", + "tawny", + "brick", + "crimson", + "normal", + ] + if colour in _named_256: + if base16: + raise ValueError("Fuck off, use base 16 colours") + elif colour not in _ansi_16: + raise ValueError(f"Unknown colour {colour}") + if colour.startswith("light") and version < (5, 0): + colour = f"bright{colour[5:]}" + if colour.startswith("bright") and version >= (5, 0): + colour = f"light{colour[5:]}" + return colour + + +def _segment( + version: Version, + name: str, + value: str, + base16: bool, +) -> str | None: + # Segment name part + valid = { + "titlecolor": (4, 0), + "statuscolor": (4, 0), + "errorcolor": (4, 0), + "selectedcolor": (4, 0), + "stripecolor": (4, 0), + "numbercolor": (4, 0), + "keycolor": (4, 0), + "functioncolor": (4, 0), + "scrollercolor": (5, 3), + "promptcolor": (5, 5), + "spotlightcolor": (5, 6), + } + if name not in valid: + raise ValueError(f"Unknown segment: {name}") + if version < valid[name]: + return None + if name == "spotlightcolor" and version < (5, 6, 1): + name = "highlightcolor" + + # Colour value part + raw_parts = value.split(",") + bold = "bold" in raw_parts + italic = "italic" in raw_parts + fg_bg = [part for part in raw_parts if part != "bold" if part != "italic"] + if len(fg_bg) == 1: + (fg,) = fg_bg + bg = None + else: + fg, bg = fg_bg + parts = [] + if version >= (5, 0): + if bold: + parts.append("bold") + if italic: + parts.append("italic") + elif bold: + try: + fg = _named_colour(version, f"bright{fg}", base16) + except ValueError: + pass + + parts.append(_named_colour(version, fg, base16) if fg else "") + if bg: + parts.append(_named_colour(version, bg, base16)) + value = ",".join(parts) + + return f"set {name} {value}" + + +def _version(string: str) -> Version: + if string.startswith("v"): + string = string[1:] + return tuple(map(int, string.split("."))) + + +def generate_changes(start_version: Version): + with tempfile.TemporaryDirectory() as temp_dir: + nano_git = Path(temp_dir) / "nano.git" + + # Clone repo + subprocess.check_call( + [ + "git", + "clone", + "--bare", + "https://git.savannah.gnu.org/git/nano.git", + nano_git, + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + # Find relevant tags + tags = [ + tag + for tag in subprocess.check_output( + [ + "git", + "--git-dir", + nano_git, + "tag", + "--list", + ], + stderr=subprocess.PIPE, + ) + .decode() + .splitlines() + if tag.startswith("v") + if all(map(str.isnumeric, tag[1:].split("."))) + ] + + # Built a history of changes to the sample configuration + _configs_per_version = [] + _versions = [] + tracked_config = set() + for tag in sorted(tags, key=_version): + version = _version(tag) + if version < start_version: + continue + nanorc = subprocess.check_output( + ["git", "--git-dir", nano_git, "show", f"{tag}:doc/sample.nanorc.in"], + stderr=subprocess.PIPE, + ).decode() + config_lines = { + line + for line in nanorc.splitlines() + if line.strip() + if not line.startswith("##") + if line != '" main' + if line != '\x1bu" main' + } + assert all(line.startswith("#") for line in config_lines) + added = config_lines - tracked_config + removed = tracked_config - config_lines + tracked_config = config_lines + if added or removed: + _configs_per_version.append((version, removed, added)) + _versions.append(version) + + return _versions, _configs_per_version + + +def generate_config( + version: Version, + config_path: Path, + out_path: Path | None, + base16: bool, +) -> None: + config = json.loads(config_path.read_text()) + + output = [] + + # Non-theme options + for option, value in config["set"].items(): + if option not in OPTIONS: + raise ValueError(f"Untracked option {option}") + doc, start, stop = OPTIONS[option] + if version >= start and (stop is None or version < stop): + if value is True: + output.extend((f"# {doc}", f"set {option}", "")) + else: + output.extend((f"# {doc}", f'set {option} "{value}"', "")) + + # Binds + for key, bind in config["bind"].items(): + if bind not in BINDS: + raise ValueError(f"Untracked binding {bind}") + doc, start, stop = BINDS[bind] + if version >= start and (stop is None or version < stop): + output.extend((f"# {doc}", f"bind {key} {bind}", "")) + + # Unbinds + for key, _ in config["unbind"].items(): + if key not in DEFAULT_BINDS: + raise ValueError(f"Untracked unbinding {key}") + doc, start, stop = DEFAULT_BINDS + if version >= start and (stop is None or version < stop): + output.extend((f"# {doc}", f"unbind {key}", "")) + + # Theme + output.append("# Theme") + for name, value in config["theme"].items(): + segment = _segment(version, name, value, base16) + if segment: + output.append(segment) + output.append("") + + if out_path: + out_path.write_text("\n".join(output)) + else: + print("\n".join(output)) + + +def check_updates( + start_version: Version, + last_checked_version: Version, +) -> None: + versions, configs_per_version = generate_changes(start_version) + last_changed_version, _, _ = configs_per_version[-1] + if last_changed_version > last_checked_version: + version_str = ".".join(map(str, last_changed_version)) + raise RuntimeError(f"Update for newest version: {version_str}") + + +def main(): + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest="action") + check_parser = subparsers.add_parser("check") + check_parser.add_argument( + "--start", + type=_version, + default=(4, 0), + ) + check_parser.add_argument( + "--last-checked", + type=_version, + default=(7, 2), + ) + generate_parser = subparsers.add_parser("generate") + generate_parser.add_argument( + "--version", + type=_version, + default=(7, 2), + ) + generate_parser.add_argument( + "--config", + type=Path, + required=True, + ) + generate_parser.add_argument( + "--out", + type=Path, + ) + generate_parser.add_argument( + "--256-colours", + action="store_false", + default=True, + dest="base16", + ) + args = parser.parse_args() + if args.action == "check": + check_updates(args.start, args.last_checked) + elif args.action == "generate": + generate_config(args.version, args.config, args.out, args.base16) + + +if __name__ == "__main__": + main() diff --git a/dot_local/bin/jflatten.py b/dot_local/bin/jflatten.py deleted file mode 100755 index 99849dc..0000000 --- a/dot_local/bin/jflatten.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import decimal -import json -import sys - -GREEN = "\033[1;32m" -GREY = "\033[0;37m" -CLEAR = "\033[0m" -RED = "\033[1;31m" -YELLOW = "\033[1;33m" -BLUE = "\033[1;34m" -MAGENTA = "\033[1;35m" - - -def flatten(*path, obj): - if isinstance(obj, list): - yield path, obj - for n, value in enumerate(obj): - yield from flatten(*path, n, obj=value) - elif isinstance(obj, dict): - yield path, obj - for key, value in obj.items(): - yield from flatten(*path, key, obj=value) - else: - yield path, obj - - -def fmt_path(*path, colour): - parts = [] - if not colour: - for part in path: - parts.append(f"[{part}]" if isinstance(part, int) else f".{part}") - else: - for part in path: - if isinstance(part, int): - parts.append(f"{GREY}[{BLUE}{part}{GREY}]{CLEAR}") - else: - parts.append(f"{GREY}.{MAGENTA}{part}{CLEAR}") - return "".join(parts) - - -def fmt_value(value, colour): - if not colour: - return { - None: "null", - True: "true", - False: "false", - }.get(value, str(value)) - if value is None: - return f"{GREY}null{CLEAR}" - if value is True: - return f"{GREEN}true{CLEAR}" - if value is False: - return f"{RED}false{CLEAR}" - if isinstance(value, str): - return f"{YELLOW}{value}{CLEAR}" - if isinstance(value, (int, float, decimal.Decimal)): - return f"{BLUE}{value}{CLEAR}" - return str(value) - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--sort-keys", "-s", action="store_true") - parser.add_argument("--json", "-j", action="store_true") - parser.add_argument("--show-empty-collections", action="store_true") - parser.add_argument("--colour", "-c", action="store_true") - parser.add_argument("--no-colour", "-C", action="store_true") - parser.add_argument("file", nargs="?") - args = parser.parse_args() - - if args.file: - with open(args.file) as f: - data = json.load(f) - else: - data = json.load(sys.stdin) - - flattened = ( - (path, value) - for path, value in flatten(obj=data) - if not isinstance(value, (dict, list)) - or not value - and args.show_empty_collections - ) - - if args.json: - print( - json.dumps( - {fmt_path(*path, colour=False): value for path, value in flattened}, - indent=True, - sort_keys=args.sort_keys, - ), - ) - return - - if args.sort_keys: - flattened = sorted(flattened) - colour = not args.no_colour and (args.colour or sys.stdout.isatty()) - flattened_fmt = ( - (fmt_path(*path, colour=colour), fmt_value(value, colour=colour)) - for path, value in flattened - ) - - if args.json: - print(json.dumps(dict(flattened_fmt), indent=True)) - else: - print("\n".join(f"{path}:{value}" for path, value in flattened_fmt)) - - -if __name__ == "__main__": - main() diff --git a/dot_local/bin/nano_config.py b/dot_local/bin/nano_config.py deleted file mode 100755 index 8d35801..0000000 --- a/dot_local/bin/nano_config.py +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import argparse -import json -import subprocess -import tempfile -from pathlib import Path -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from collections.abc import Mapping - from typing import TypeAlias - -Version: TypeAlias = tuple[int, ...] - -OPTIONS: Mapping[str, tuple[str, Version, Version | None]] = { - "afterends": ("nextword function (Ctrl+Right) stops at word ends", (4, 0), None), - "atblanks": ("Soft wrapping breaks on spaces", (4, 0), None), - "nonewlines": ("Do not ensure final newline", (4, 1), None), - "historylog": ("Remember search history", (4, 0), None), - "linenumbers": ("Show line numbers", (4, 0), None), - "locking": ("Vim-style soft lock files", (4, 0), None), - "mouse": ("Enable mouse", (4, 0), None), - "multibuffer": ("Allow multiple buffers", (4, 0), None), - "positionlog": ("Remember place in file", (4, 0), None), - "quickblank": ("Clear status bar after one keystroke", (4, 0), None), - "regexp": ("Regex search by default", (4, 0), None), - "smarthome": ("Home toggles start of line and start of text", (4, 0), None), - "speller": ("Spelling checker", (4, 0), None), - "suspend": ("Allow suspending", (4, 0), (4, 9)), - "suspendable": ("Allow suspending", (4, 9), (6, 0)), - "tabsize 4": ("Sane tab size", (4, 0), None), - "tabstospaces": ("Convert tabs to spaces", (4, 0), None), - "whitespace": ("Whitespace characters", (4, 0), None), - "zap": ("Let delete/backspace delete selection", (4, 0), None), - "indicator": ("Scrollbar on the right", (5, 0), None), - "minibar": ("Supress title bar and show state at the bottom", (5, 5), None), - "guidestripe 80": ("Show guide stripe", (6, 1), None), - "stateflags": ("Show state in title bar", (5, 3), None), - "magic": ("Fall back to libmagic for syntax choosing", (4, 0), (5, 3)), -} -BINDS: Mapping[str, tuple[str, Version, Version | None]] = { - "suspend main": ("Allow suspending", (6, 0), None), -} -DEFAULT_BINDS: Mapping[str, tuple[str, Version, Version | None]] = {} - - -def _named_colour( - version: Version, - colour: str, - base16: bool, -) -> str: - """Based on src/rcfile.c""" - _ansi_8 = [ - "red", - "green", - "blue", - "magenta", - "yellow", - "cyan", - "white", - "black", - ] - _ansi_16 = [ - *_ansi_8, - *(f"light{colour}" for colour in _ansi_8), - *(f"bright{colour}" for colour in _ansi_8), - "grey", - "gray", - ] - _named_256 = [ - "pink", - "purple", - "mauve", - "lagoon", - "mint", - "lime", - "peach", - "orange", - "latte", - "rosy", - "beet", - "plum", - "sea", - "sky", - "slate", - "teal", - "sage", - "brown", - "ocher", - "sand", - "tawny", - "brick", - "crimson", - "normal", - ] - if colour in _named_256: - if base16: - raise ValueError("Fuck off, use base 16 colours") - elif colour not in _ansi_16: - raise ValueError(f"Unknown colour {colour}") - if colour.startswith("light") and version < (5, 0): - colour = f"bright{colour[5:]}" - if colour.startswith("bright") and version >= (5, 0): - colour = f"light{colour[5:]}" - return colour - - -def _segment( - version: Version, - name: str, - value: str, - base16: bool, -) -> str | None: - # Segment name part - valid = { - "titlecolor": (4, 0), - "statuscolor": (4, 0), - "errorcolor": (4, 0), - "selectedcolor": (4, 0), - "stripecolor": (4, 0), - "numbercolor": (4, 0), - "keycolor": (4, 0), - "functioncolor": (4, 0), - "scrollercolor": (5, 3), - "promptcolor": (5, 5), - "spotlightcolor": (5, 6), - } - if name not in valid: - raise ValueError(f"Unknown segment: {name}") - if version < valid[name]: - return None - if name == "spotlightcolor" and version < (5, 6, 1): - name = "highlightcolor" - - # Colour value part - raw_parts = value.split(",") - bold = "bold" in raw_parts - italic = "italic" in raw_parts - fg_bg = [part for part in raw_parts if part != "bold" if part != "italic"] - if len(fg_bg) == 1: - (fg,) = fg_bg - bg = None - else: - fg, bg = fg_bg - parts = [] - if version >= (5, 0): - if bold: - parts.append("bold") - if italic: - parts.append("italic") - elif bold: - try: - fg = _named_colour(version, f"bright{fg}", base16) - except ValueError: - pass - - parts.append(_named_colour(version, fg, base16) if fg else "") - if bg: - parts.append(_named_colour(version, bg, base16)) - value = ",".join(parts) - - return f"set {name} {value}" - - -def _version(string: str) -> Version: - if string.startswith("v"): - string = string[1:] - return tuple(map(int, string.split("."))) - - -def generate_changes(start_version: Version): - with tempfile.TemporaryDirectory() as temp_dir: - nano_git = Path(temp_dir) / "nano.git" - - # Clone repo - subprocess.check_call( - [ - "git", - "clone", - "--bare", - "https://git.savannah.gnu.org/git/nano.git", - nano_git, - ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - - # Find relevant tags - tags = [ - tag - for tag in subprocess.check_output( - [ - "git", - "--git-dir", - nano_git, - "tag", - "--list", - ], - stderr=subprocess.PIPE, - ) - .decode() - .splitlines() - if tag.startswith("v") - if all(map(str.isnumeric, tag[1:].split("."))) - ] - - # Built a history of changes to the sample configuration - _configs_per_version = [] - _versions = [] - tracked_config = set() - for tag in sorted(tags, key=_version): - version = _version(tag) - if version < start_version: - continue - nanorc = subprocess.check_output( - ["git", "--git-dir", nano_git, "show", f"{tag}:doc/sample.nanorc.in"], - stderr=subprocess.PIPE, - ).decode() - config_lines = { - line - for line in nanorc.splitlines() - if line.strip() - if not line.startswith("##") - if line != '" main' - if line != '\x1bu" main' - } - assert all(line.startswith("#") for line in config_lines) - added = config_lines - tracked_config - removed = tracked_config - config_lines - tracked_config = config_lines - if added or removed: - _configs_per_version.append((version, removed, added)) - _versions.append(version) - - return _versions, _configs_per_version - - -def generate_config( - version: Version, - config_path: Path, - out_path: Path | None, - base16: bool, -) -> None: - config = json.loads(config_path.read_text()) - - output = [] - - # Non-theme options - for option, value in config["set"].items(): - if option not in OPTIONS: - raise ValueError(f"Untracked option {option}") - doc, start, stop = OPTIONS[option] - if version >= start and (stop is None or version < stop): - if value is True: - output.extend((f"# {doc}", f"set {option}", "")) - else: - output.extend((f"# {doc}", f'set {option} "{value}"', "")) - - # Binds - for key, bind in config["bind"].items(): - if bind not in BINDS: - raise ValueError(f"Untracked binding {bind}") - doc, start, stop = BINDS[bind] - if version >= start and (stop is None or version < stop): - output.extend((f"# {doc}", f"bind {key} {bind}", "")) - - # Unbinds - for key, _ in config["unbind"].items(): - if key not in DEFAULT_BINDS: - raise ValueError(f"Untracked unbinding {key}") - doc, start, stop = DEFAULT_BINDS - if version >= start and (stop is None or version < stop): - output.extend((f"# {doc}", f"unbind {key}", "")) - - # Theme - output.append("# Theme") - for name, value in config["theme"].items(): - segment = _segment(version, name, value, base16) - if segment: - output.append(segment) - output.append("") - - if out_path: - out_path.write_text("\n".join(output)) - else: - print("\n".join(output)) - - -def check_updates( - start_version: Version, - last_checked_version: Version, -) -> None: - versions, configs_per_version = generate_changes(start_version) - last_changed_version, _, _ = configs_per_version[-1] - if last_changed_version > last_checked_version: - version_str = ".".join(map(str, last_changed_version)) - raise RuntimeError(f"Update for newest version: {version_str}") - - -def main(): - parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers(dest="action") - check_parser = subparsers.add_parser("check") - check_parser.add_argument( - "--start", - type=_version, - default=(4, 0), - ) - check_parser.add_argument( - "--last-checked", - type=_version, - default=(7, 2), - ) - generate_parser = subparsers.add_parser("generate") - generate_parser.add_argument( - "--version", - type=_version, - default=(7, 2), - ) - generate_parser.add_argument( - "--config", - type=Path, - required=True, - ) - generate_parser.add_argument( - "--out", - type=Path, - ) - generate_parser.add_argument( - "--256-colours", - action="store_false", - default=True, - dest="base16", - ) - args = parser.parse_args() - if args.action == "check": - check_updates(args.start, args.last_checked) - elif args.action == "generate": - generate_config(args.version, args.config, args.out, args.base16) - - -if __name__ == "__main__": - main() -- cgit 1.4.1-2-gfad0