78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Callable, Dict, Iterable, Sequence
|
|
from importlib import import_module as _import_module
|
|
|
|
# A cmdlet is a callable taking (result, args, config) -> int
|
|
Cmdlet = Callable[[Any, Sequence[str], Dict[str, Any]], int]
|
|
|
|
# Registry of command-name -> cmdlet function
|
|
REGISTRY: Dict[str, Cmdlet] = {}
|
|
|
|
|
|
def register(names: Iterable[str]):
|
|
"""Decorator to register a function under one or more command names.
|
|
|
|
Usage:
|
|
@register(["add-tag", "add-tags"])
|
|
def _run(result, args, config) -> int: ...
|
|
"""
|
|
def _wrap(fn: Cmdlet) -> Cmdlet:
|
|
for name in names:
|
|
REGISTRY[name.replace('_', '-').lower()] = fn
|
|
return fn
|
|
return _wrap
|
|
|
|
|
|
def get(cmd_name: str) -> Cmdlet | None:
|
|
return REGISTRY.get(cmd_name.replace('_', '-').lower())
|
|
|
|
|
|
# Dynamically import all cmdlet modules in this directory (ignore files starting with _ and __init__.py)
|
|
# Cmdlets self-register when instantiated via their __init__ method
|
|
import os
|
|
cmdlet_dir = os.path.dirname(__file__)
|
|
for filename in os.listdir(cmdlet_dir):
|
|
if not (
|
|
filename.endswith(".py")
|
|
and not filename.startswith("_")
|
|
and filename != "__init__.py"
|
|
):
|
|
continue
|
|
|
|
mod_name = filename[:-3]
|
|
|
|
# Enforce Powershell-style two-word cmdlet naming (e.g., add_file, get_file)
|
|
# Skip native/utility scripts that are not cmdlets (e.g., adjective, worker, matrix, pipe)
|
|
if "_" not in mod_name:
|
|
continue
|
|
|
|
try:
|
|
_import_module(f".{mod_name}", __name__)
|
|
except Exception as e:
|
|
import sys
|
|
print(f"Error importing cmdlet '{mod_name}': {e}", file=sys.stderr)
|
|
continue
|
|
|
|
# Import and register native commands that are not considered cmdlets
|
|
try:
|
|
from cmdnats import register_native_commands as _register_native_commands
|
|
_register_native_commands(REGISTRY)
|
|
except Exception:
|
|
# Native commands are optional; ignore if unavailable
|
|
pass
|
|
|
|
# Import root-level modules that also register cmdlets
|
|
for _root_mod in ("select_cmdlet",):
|
|
try:
|
|
_import_module(_root_mod)
|
|
except Exception:
|
|
# Allow missing optional modules
|
|
continue
|
|
|
|
# Also import helper modules that register cmdlets
|
|
try:
|
|
import helper.alldebrid as _alldebrid
|
|
except Exception:
|
|
pass
|