feat: hook manager
This commit is contained in:
128
scientific_surfing/hook_manager.py
Normal file
128
scientific_surfing/hook_manager.py
Normal file
@ -0,0 +1,128 @@
|
||||
"""Hook manager for scientific-surfing application."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from scientific_surfing.storage import StorageManager
|
||||
|
||||
|
||||
class HookManager:
|
||||
"""Manages hook scripts for scientific-surfing."""
|
||||
|
||||
def __init__(self, storage: StorageManager) -> None:
|
||||
"""Initialize hook manager.
|
||||
|
||||
Args:
|
||||
config_dir: Optional configuration directory path.
|
||||
If not provided, uses default user config directory.
|
||||
"""
|
||||
self.storage = storage
|
||||
self.config_dir = storage.config_dir
|
||||
self.hooks_dir = self.config_dir / "hooks"
|
||||
self.template_hooks_dir = Path(__file__).parent / "templates" / "hooks"
|
||||
|
||||
def init(self) -> None:
|
||||
"""Initialize hooks directory by copying template hooks."""
|
||||
if not self.template_hooks_dir.exists():
|
||||
print(f"Template hooks directory not found: {self.template_hooks_dir}")
|
||||
return
|
||||
|
||||
self.hooks_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
copied_count = 0
|
||||
for hook_file in self.template_hooks_dir.iterdir():
|
||||
if hook_file.is_file():
|
||||
dest_file = self.hooks_dir / hook_file.name
|
||||
if not dest_file.exists():
|
||||
shutil.copy2(hook_file, dest_file)
|
||||
copied_count += 1
|
||||
print(f"Copied: {hook_file.name}")
|
||||
else:
|
||||
print(f"Skipped (already exists): {hook_file.name}")
|
||||
|
||||
print(f"\nInitialized hooks directory with {copied_count} new scripts.")
|
||||
print(f"Location: {self.hooks_dir}")
|
||||
|
||||
def list(self) -> None:
|
||||
"""Display hooks directory location and list all hook scripts."""
|
||||
print(f"Hooks directory: {self.hooks_dir}")
|
||||
|
||||
if not self.hooks_dir.exists():
|
||||
print("Hooks directory does not exist. Run 'init' to create it.")
|
||||
return
|
||||
|
||||
hook_files = self._get_hook_files()
|
||||
|
||||
if not hook_files:
|
||||
print("No hook scripts found.")
|
||||
else:
|
||||
print(f"\nFound {len(hook_files)} hook script(s):")
|
||||
for hook_file in hook_files:
|
||||
print(f" - {hook_file}")
|
||||
|
||||
def edit(self, script_name: str) -> None:
|
||||
"""Open a hook script with system default editor.
|
||||
|
||||
Args:
|
||||
script_name: Name of the hook script to edit.
|
||||
"""
|
||||
if not self.hooks_dir.exists():
|
||||
print("Hooks directory does not exist. Run 'init' to create it.")
|
||||
return
|
||||
|
||||
script_path = self.hooks_dir / script_name
|
||||
|
||||
if not script_path.exists():
|
||||
available = self._get_hook_files()
|
||||
print(f"Script '{script_name}' not found.")
|
||||
if available:
|
||||
print(f"Available scripts: {', '.join(available)}")
|
||||
return
|
||||
|
||||
editor = os.environ.get('EDITOR', 'notepad' if os.name == 'nt' else 'nano')
|
||||
|
||||
try:
|
||||
subprocess.run([editor, str(script_path)], check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Failed to open editor: {e}")
|
||||
except FileNotFoundError:
|
||||
print(f"Editor '{editor}' not found. Please set EDITOR environment variable.")
|
||||
|
||||
def rm(self, script_name: str) -> None:
|
||||
"""Remove a hook script.
|
||||
|
||||
Args:
|
||||
script_name: Name of the hook script to remove.
|
||||
"""
|
||||
if not self.hooks_dir.exists():
|
||||
print("Hooks directory does not exist.")
|
||||
return
|
||||
|
||||
script_path = self.hooks_dir / script_name
|
||||
|
||||
if not script_path.exists():
|
||||
available = self._get_hook_files()
|
||||
print(f"Script '{script_name}' not found.")
|
||||
if available:
|
||||
print(f"Available scripts: {', '.join(available)}")
|
||||
return
|
||||
|
||||
try:
|
||||
script_path.unlink()
|
||||
print(f"Removed: {script_name}")
|
||||
except OSError as e:
|
||||
print(f"Failed to remove script: {e}")
|
||||
|
||||
def _get_hook_files(self) -> List[str]:
|
||||
"""Get list of hook script files.
|
||||
|
||||
Returns:
|
||||
List of hook script filenames.
|
||||
"""
|
||||
if not self.hooks_dir.exists():
|
||||
return []
|
||||
|
||||
return [f.name for f in self.hooks_dir.iterdir() if f.is_file()]
|
||||
Reference in New Issue
Block a user