diff --git a/flake-modules/dev/devshell.nix b/flake-modules/dev/devshell.nix index 67d987fc..c0231567 100644 --- a/flake-modules/dev/devshell.nix +++ b/flake-modules/dev/devshell.nix @@ -63,6 +63,11 @@ ${pkgs.lib.getExe pkgs.python3} -m http.server -d "$doc_derivation"/share/doc ''; } + { + name = "list-plugins"; + command = "${pkgs.python3.interpreter} ${./list-plugins.py}"; + help = "List plugins and get implementation infos"; + } ]; }; }; diff --git a/flake-modules/dev/list-plugins.py b/flake-modules/dev/list-plugins.py new file mode 100755 index 00000000..95efe225 --- /dev/null +++ b/flake-modules/dev/list-plugins.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 + +from enum import Enum +from dataclasses import dataclass +from typing import Optional +import glob +import re + +QUESTION_MARK = "❔" + +EXCLUDES: list[str] = [ + # Not plugin files + "colorschemes/base16/theme-list.nix", + "helpers.nix", + "Helpers.nix", + "TEMPLATE.nix", +] + + +class Kind(Enum): + UNKNOWN = 1 + NEOVIM = 2 + VIM = 3 + MISC = 4 + + +class State(Enum): + UNKNOWN = QUESTION_MARK + NEW = "✅" + OLD = "❌" + + +KNOWN_PATHS: dict[str, tuple[State, Kind, bool]] = { + # "plugins/utils/mkdnflow.nix": (True, Kind.NEOVIM), + "plugins/colorschemes/base16/default.nix": (State.NEW, Kind.VIM, True), +} + +DEPRECATION_REGEX: list[re.Pattern] = [ + re.compile(rf".*{pattern}", re.DOTALL) + for pattern in [ + "deprecateExtra", + "mkRemovedOptionModule", + "mkRenamedOptionModule", + "optionsRenamedToSettings", + ] +] + + +@dataclass +class Plugin: + path: str + state: State + kind: Kind + dep_warnings: bool + + def __str__(self) -> str: + state_icon: str = self.state.value + kind_icon: str + match self.kind: + case Kind.UNKNOWN: + kind_icon = "\033[93m" + QUESTION_MARK + case Kind.NEOVIM: + kind_icon = "\033[94m" + " " + case Kind.VIM: + kind_icon = "\033[92m" + " " + case _: + assert False + deprecation_icon: str = "⚠️" if self.dep_warnings else " " + + return f"| {kind_icon}\033[0m | {state_icon} | {deprecation_icon} | {self.path}" + + +def has_deprecation_warnings(string: str) -> bool: + for regex in DEPRECATION_REGEX: + if re.match(regex, string): + return True + return False + + +def parse_file(path: str) -> Optional[Plugin]: + file_content: str = "" + with open(path, "r") as f: + file_content = f.read() + + if path in KNOWN_PATHS: + props: tuple[State, Kind, bool] = KNOWN_PATHS[path] + return Plugin( + path=path, + state=props[0], + kind=props[1], + dep_warnings=props[2], + ) + + state: State = State.UNKNOWN + kind: Kind = Kind.UNKNOWN + if re.match( + re.compile(r".*mkNeovimPlugin", re.DOTALL), + file_content, + ): + kind = Kind.NEOVIM + state = State.NEW + elif re.match( + re.compile(r".*require.+setup", re.DOTALL), + file_content, + ): + kind = Kind.NEOVIM + state = State.OLD + elif re.match( + re.compile(r".*mkVimPlugin", re.DOTALL), + file_content, + ): + kind = Kind.VIM + state = State.NEW + + return Plugin( + path=path, + state=state, + kind=kind, + dep_warnings=has_deprecation_warnings(string=file_content), + ) + + +def _is_excluded(path: str) -> bool: + for exclude_pattern in EXCLUDES: + if exclude_pattern in path: + return False + return True + + +if __name__ == "__main__": + paths: list[str] = glob.glob( + pathname="plugins/**/*.nix", + recursive=True, + ) + + filtered_paths: list[str] = list( + filter( + _is_excluded, + paths, + ) + ) + filtered_paths.sort() + + print("| Typ | Sty | DW | path") + print("|-----|-----|----|--------------------------------------------------------") + for plugin_path in filtered_paths: + plugin: Optional[Plugin] = parse_file( + path=plugin_path, + ) + if plugin is not None: + print(plugin)