AST
This commit is contained in:
139
cmdlets/__init__.py
Normal file
139
cmdlets/__init__.py
Normal file
@@ -0,0 +1,139 @@
|
||||
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
|
||||
|
||||
|
||||
class AutoRegister:
|
||||
"""Decorator that automatically registers a cmdlet function using CMDLET.aliases.
|
||||
|
||||
Usage:
|
||||
CMDLET = Cmdlet(
|
||||
name="delete-file",
|
||||
aliases=["del", "del-file"],
|
||||
...
|
||||
)
|
||||
|
||||
@AutoRegister(CMDLET)
|
||||
def _run(result, args, config) -> int:
|
||||
...
|
||||
|
||||
Registers the cmdlet under:
|
||||
- Its main name from CMDLET.name
|
||||
- All aliases from CMDLET.aliases
|
||||
|
||||
This allows the help display to show: "cmd: delete-file | alias: del, del-file"
|
||||
"""
|
||||
def __init__(self, cmdlet):
|
||||
self.cmdlet = cmdlet
|
||||
|
||||
def __call__(self, fn: Cmdlet) -> Cmdlet:
|
||||
"""Register fn for the main name and all aliases in cmdlet."""
|
||||
normalized_name = None
|
||||
|
||||
# Register for main name first
|
||||
if hasattr(self.cmdlet, 'name') and self.cmdlet.name:
|
||||
normalized_name = self.cmdlet.name.replace('_', '-').lower()
|
||||
REGISTRY[normalized_name] = fn
|
||||
|
||||
# Register for all aliases
|
||||
if hasattr(self.cmdlet, 'aliases') and self.cmdlet.aliases:
|
||||
for alias in self.cmdlet.aliases:
|
||||
normalized_alias = alias.replace('_', '-').lower()
|
||||
# Always register (aliases are separate from main name)
|
||||
REGISTRY[normalized_alias] = fn
|
||||
|
||||
return fn
|
||||
|
||||
|
||||
def get(cmd_name: str) -> Cmdlet | None:
|
||||
return REGISTRY.get(cmd_name.replace('_', '-').lower())
|
||||
|
||||
|
||||
def format_cmd_help(cmdlet) -> str:
|
||||
"""Format a cmdlet for help display showing cmd:name and aliases.
|
||||
|
||||
Example output: "delete-file | aliases: del, del-file"
|
||||
"""
|
||||
if not hasattr(cmdlet, 'name'):
|
||||
return str(cmdlet)
|
||||
|
||||
cmd_str = f"cmd: {cmdlet.name}"
|
||||
|
||||
if hasattr(cmdlet, 'aliases') and cmdlet.aliases:
|
||||
aliases_str = ", ".join(cmdlet.aliases)
|
||||
cmd_str += f" | aliases: {aliases_str}"
|
||||
|
||||
return cmd_str
|
||||
|
||||
|
||||
# Dynamically import all cmdlet modules in this directory (ignore files starting with _ and __init__.py)
|
||||
import os
|
||||
cmdlet_dir = os.path.dirname(__file__)
|
||||
for filename in os.listdir(cmdlet_dir):
|
||||
if (
|
||||
filename.endswith(".py")
|
||||
and not filename.startswith("_")
|
||||
and filename != "__init__.py"
|
||||
):
|
||||
mod_name = filename[:-3]
|
||||
try:
|
||||
module = _import_module(f".{mod_name}", __name__)
|
||||
|
||||
# Auto-register based on CMDLET object with exec function
|
||||
# This allows cmdlets to be fully self-contained in the CMDLET object
|
||||
if hasattr(module, 'CMDLET'):
|
||||
cmdlet_obj = module.CMDLET
|
||||
|
||||
# Get the execution function from the CMDLET object
|
||||
run_fn = getattr(cmdlet_obj, 'exec', None) if hasattr(cmdlet_obj, 'exec') else None
|
||||
|
||||
if callable(run_fn):
|
||||
# Register main name
|
||||
if hasattr(cmdlet_obj, 'name') and cmdlet_obj.name:
|
||||
normalized_name = cmdlet_obj.name.replace('_', '-').lower()
|
||||
REGISTRY[normalized_name] = run_fn
|
||||
|
||||
# Register all aliases
|
||||
if hasattr(cmdlet_obj, 'aliases') and cmdlet_obj.aliases:
|
||||
for alias in cmdlet_obj.aliases:
|
||||
normalized_alias = alias.replace('_', '-').lower()
|
||||
REGISTRY[normalized_alias] = run_fn
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Import root-level modules that also register cmdlets
|
||||
# Note: search_libgen, search_soulseek, and search_debrid are now consolidated into search_provider.py
|
||||
# Use search-file -provider libgen, -provider soulseek, or -provider debrid instead
|
||||
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
|
||||
Reference in New Issue
Block a user