nix-community.nixvim/flake/dev/list-plugins/list-plugins.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

274 lines
7.7 KiB
Python
Raw Normal View History

import glob
import os
import re
from argparse import ArgumentParser, RawTextHelpFormatter
from dataclasses import dataclass
from enum import Enum
from typing import Optional
# Ignore files that are not plugin definitions
EXCLUDES: list[str] = [
# Patterns
"TEMPLATE.nix",
"deprecations.nix",
"helpers.nix",
2024-12-18 22:29:56 +01:00
"renamed-options",
"settings-options.nix",
# Specific files
"colorschemes/base16/theme-list.nix",
2024-12-30 23:55:58 +01:00
"plugins/by-name/blink-cmp/provider-config.nix",
"plugins/by-name/dap/dapHelpers.nix",
"plugins/by-name/efmls-configs/packages.nix",
"plugins/by-name/hydra/hydras-option.nix",
"plugins/by-name/hydra/settings-options.nix",
"plugins/by-name/neotest/adapters-list.nix",
"plugins/by-name/neotest/adapters.nix",
"plugins/by-name/none-ls/_mk-source-plugin.nix",
"plugins/by-name/none-ls/packages.nix",
"plugins/by-name/none-ls/prettier.nix",
"plugins/by-name/none-ls/prettierd.nix",
"plugins/by-name/none-ls/settings.nix",
"plugins/by-name/none-ls/sources.nix",
"plugins/by-name/openscad/fuzzy-finder-plugin-option.nix",
"plugins/by-name/rustaceanvim/renamed-options.nix",
"plugins/by-name/telescope/extensions/_mk-extension.nix",
"plugins/by-name/telescope/extensions/default.nix",
"plugins/cmp/auto-enable.nix",
"plugins/cmp/options/",
"plugins/cmp/sources/cmp-fish.nix",
"plugins/cmp/sources/default.nix",
"plugins/default.nix",
"plugins/deprecation.nix",
"plugins/lsp/language-servers/",
"plugins/lsp/lsp-packages.nix",
]
class Kind(Enum):
NEOVIM = 1
VIM = 2
MISC = 3
class State(Enum):
2024-12-18 18:27:36 +01:00
UNKNOWN = ""
NEW = ""
OLD = ""
KNOWN_PATHS: dict[
str,
tuple[
State, # If the implem is "legacy" or up to date
Kind, # Vim / Neovim / misc
bool, # Has deprecation warnings
],
] = {
"plugins/by-name/chadtree/default.nix": (State.OLD, Kind.NEOVIM, False),
"plugins/by-name/coq-thirdparty/default.nix": (State.OLD, Kind.NEOVIM, False),
"plugins/by-name/leap/default.nix": (State.OLD, Kind.NEOVIM, False),
"plugins/by-name/lspkind/default.nix": (State.OLD, Kind.NEOVIM, False),
"plugins/by-name/rainbow-delimiters/default.nix": (State.OLD, Kind.NEOVIM, False),
"plugins/by-name/treesitter-refactor/default.nix": (State.OLD, Kind.MISC, True),
"plugins/by-name/treesitter-textobjects/default.nix": (
State.OLD,
Kind.NEOVIM,
True,
),
}
for telescope_extension_name, has_depr_warnings in {
"file-browser": True,
"frecency": True,
"fzf-native": True,
"fzy-native": True,
"live-greps-args": False,
"manix": False,
"media-files": True,
"project": False,
"ui-select": False,
"undo": True,
2025-04-06 01:57:17 +02:00
"zoxide": False,
}.items():
KNOWN_PATHS[
f"plugins/by-name/telescope/extensions/{telescope_extension_name}.nix"
] = (
State.NEW,
Kind.MISC,
has_depr_warnings,
)
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.NEOVIM:
kind_icon = "\033[94m" + ""
case Kind.VIM:
kind_icon = "\033[92m" + ""
case Kind.MISC:
kind_icon = "\033[92m" + "🟢"
case _:
assert False
deprecation_icon: str = "⚠️ " if self.dep_warnings else " "
2024-07-08 16:16:16 +01:00
return (
f"| {kind_icon}\033[0m | {state_icon} | {deprecation_icon} | {self.path}"
)
def print_markdown(self) -> None:
print(f"- [ ] {self.path} ({self.kind.name.lower()})")
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()
known_path: str
props: tuple[State, Kind, bool]
for known_path, props in KNOWN_PATHS.items():
if known_path in path:
return Plugin(
path=path,
state=props[0],
kind=props[1],
dep_warnings=props[2],
)
state: State = State.UNKNOWN
kind: Kind
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
else:
raise ValueError(
f"I was not able to categorize `{path}`. Consider adding it to `EXCLUDES` or `KNOWN_PATHS`."
)
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
def main(args) -> None:
pathname: str = os.path.join(args.root_path, "plugins/**/*.nix")
paths: list[str] = glob.glob(pathname=pathname, recursive=True)
filtered_paths: list[str] = list(filter(_is_excluded, paths))
filtered_paths.sort()
if not args.markdown:
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:
if (
(args.kind is None or plugin.kind.name.lower() == args.kind)
and (args.state is None or plugin.state.name.lower() == args.state)
and (not args.deprecation_warnings or plugin.dep_warnings)
):
if args.markdown:
plugin.print_markdown()
else:
print(plugin)
if __name__ == "__main__":
parser: ArgumentParser = ArgumentParser(
description="""
Analyze Nixvim plugin files
Output formats a table showing:
If a plugin is written for Neovim or Vim.
If the plugin has been updated to latest style standards.
If a plugin contains any deprecation warnings.
""",
formatter_class=RawTextHelpFormatter,
)
# TODO: consider automatically localizing the flake's root.
parser.add_argument(
"--root-path",
type=str,
default="./",
help="The path to the root of the nixvim repo",
)
parser.add_argument(
"-k",
"--kind",
choices=[k.name.lower() for k in Kind],
help="Filter plugins by kind (neovim, vim, misc)",
)
parser.add_argument(
"-s",
"--state",
choices=[s.name.lower() for s in State],
help="Filter plugins by state (new, old, unknown)",
)
parser.add_argument(
"-d",
"--deprecation-warnings",
action="store_true",
help="Show only plugins with deprecation warnings",
)
parser.add_argument(
"-m",
"--markdown",
action="store_true",
help="Markdown output",
)
main(parser.parse_args())