324 lines
9.9 KiB
Python
Executable File
324 lines
9.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
Claude Filter Vim Plugin - Automatic Installation Script
|
||
|
||
Detects Vim/Neovim installation and installs the plugin with proper handling
|
||
for existing installations (updates/overrides).
|
||
|
||
Features:
|
||
- Auto-detects Vim vs Neovim
|
||
- Auto-detects config directory
|
||
- Installs both Lua (Neovim) and VimScript (Vim) versions
|
||
- Handles existing installations (updates)
|
||
- Cross-platform (Linux, macOS, Windows)
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import shutil
|
||
import argparse
|
||
from pathlib import Path
|
||
|
||
|
||
class PluginInstaller:
|
||
def __init__(self, verbose=False, override=False):
|
||
self.verbose = verbose
|
||
self.override = override
|
||
self.installed = []
|
||
self.errors = []
|
||
|
||
def log(self, message, level="INFO"):
|
||
"""Log messages if verbose mode is enabled"""
|
||
if self.verbose or level in ["ERROR", "SUCCESS"]:
|
||
prefix = "✅" if level == "SUCCESS" else "❌" if level == "ERROR" else "ℹ️"
|
||
print(f"{prefix} [{level}] {message}")
|
||
|
||
def check_editor_installed(self):
|
||
"""Check which editors are installed"""
|
||
editors = {}
|
||
|
||
# Check Neovim
|
||
if shutil.which("nvim"):
|
||
editors["neovim"] = True
|
||
self.log("Neovim detected")
|
||
else:
|
||
editors["neovim"] = False
|
||
self.log("Neovim not found", "WARN")
|
||
|
||
# Check Vim
|
||
if shutil.which("vim"):
|
||
editors["vim"] = True
|
||
self.log("Vim detected")
|
||
else:
|
||
editors["vim"] = False
|
||
self.log("Vim not found", "WARN")
|
||
|
||
return editors
|
||
|
||
def get_neovim_config_dir(self):
|
||
"""Get Neovim config directory (works on all platforms)"""
|
||
# Check XDG_CONFIG_HOME first (Linux/macOS)
|
||
xdg_config = os.environ.get("XDG_CONFIG_HOME")
|
||
if xdg_config:
|
||
nvim_dir = Path(xdg_config) / "nvim"
|
||
if nvim_dir.exists():
|
||
return nvim_dir
|
||
|
||
# Check standard locations
|
||
home = Path.home()
|
||
|
||
# macOS
|
||
if sys.platform == "darwin":
|
||
nvim_dir = home / ".config" / "nvim"
|
||
if nvim_dir.exists():
|
||
return nvim_dir
|
||
|
||
# Linux
|
||
if sys.platform.startswith("linux"):
|
||
nvim_dir = home / ".config" / "nvim"
|
||
if nvim_dir.exists():
|
||
return nvim_dir
|
||
|
||
# Windows
|
||
if sys.platform == "win32":
|
||
# Try AppData first
|
||
appdata = os.environ.get("APPDATA")
|
||
if appdata:
|
||
nvim_dir = Path(appdata) / "nvim"
|
||
if nvim_dir.exists():
|
||
return nvim_dir
|
||
|
||
# Try local AppData
|
||
local_appdata = os.environ.get("LOCALAPPDATA")
|
||
if local_appdata:
|
||
nvim_dir = Path(local_appdata) / "nvim"
|
||
if nvim_dir.exists():
|
||
return nvim_dir
|
||
|
||
# Fallback: Create in ~/.config/nvim
|
||
return home / ".config" / "nvim"
|
||
|
||
def get_vim_config_dir(self):
|
||
"""Get Vim config directory"""
|
||
home = Path.home()
|
||
|
||
# Check for .vim directory
|
||
vim_dir = home / ".vim"
|
||
if vim_dir.exists():
|
||
return vim_dir
|
||
|
||
# Windows: check vimfiles
|
||
if sys.platform == "win32":
|
||
vimfiles = home / "vimfiles"
|
||
if vimfiles.exists():
|
||
return vimfiles
|
||
|
||
# Default to .vim
|
||
return vim_dir
|
||
|
||
def install_neovim_plugin(self):
|
||
"""Install Lua version for Neovim"""
|
||
self.log("Installing Neovim plugin...")
|
||
|
||
nvim_dir = self.get_neovim_config_dir()
|
||
plugin_dir = nvim_dir / "plugin"
|
||
|
||
# Create directory if it doesn't exist
|
||
plugin_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
# Source and destination
|
||
source = Path(__file__).parent / "plugin" / "claude_filter.lua"
|
||
destination = plugin_dir / "claude_filter.lua"
|
||
|
||
if not source.exists():
|
||
self.log(f"Source file not found: {source}", "ERROR")
|
||
self.errors.append(f"Neovim: Source file not found")
|
||
return False
|
||
|
||
# Check if already installed
|
||
if destination.exists():
|
||
if not self.override:
|
||
self.log(f"Already installed at {destination}")
|
||
self.log("Use --override to update")
|
||
return True
|
||
else:
|
||
self.log(f"Removing existing: {destination}")
|
||
destination.unlink()
|
||
|
||
# Copy file
|
||
try:
|
||
shutil.copy2(source, destination)
|
||
self.log(f"✅ Installed to {destination}", "SUCCESS")
|
||
self.installed.append(("Neovim", destination))
|
||
return True
|
||
except Exception as e:
|
||
self.log(f"Failed to copy: {e}", "ERROR")
|
||
self.errors.append(f"Neovim: {str(e)}")
|
||
return False
|
||
|
||
def install_vim_plugin(self):
|
||
"""Install VimScript version for Vim"""
|
||
self.log("Installing Vim plugin...")
|
||
|
||
vim_dir = self.get_vim_config_dir()
|
||
plugin_dir = vim_dir / "plugin"
|
||
|
||
# Create directory if it doesn't exist
|
||
plugin_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
# Source and destination
|
||
source = Path(__file__).parent / "plugin" / "claude_filter.vim"
|
||
destination = plugin_dir / "claude_filter.vim"
|
||
|
||
if not source.exists():
|
||
self.log(f"Source file not found: {source}", "ERROR")
|
||
self.errors.append(f"Vim: Source file not found")
|
||
return False
|
||
|
||
# Check if already installed
|
||
if destination.exists():
|
||
if not self.override:
|
||
self.log(f"Already installed at {destination}")
|
||
self.log("Use --override to update")
|
||
return True
|
||
else:
|
||
self.log(f"Removing existing: {destination}")
|
||
destination.unlink()
|
||
|
||
# Copy file
|
||
try:
|
||
shutil.copy2(source, destination)
|
||
self.log(f"✅ Installed to {destination}", "SUCCESS")
|
||
self.installed.append(("Vim", destination))
|
||
return True
|
||
except Exception as e:
|
||
self.log(f"Failed to copy: {e}", "ERROR")
|
||
self.errors.append(f"Vim: {str(e)}")
|
||
return False
|
||
|
||
def install(self):
|
||
"""Main installation logic"""
|
||
self.log("=" * 60)
|
||
self.log("Claude Filter Vim Plugin - Installer", "SUCCESS")
|
||
self.log("=" * 60)
|
||
|
||
# Check what's installed
|
||
editors = self.check_editor_installed()
|
||
|
||
if not any(editors.values()):
|
||
self.log("Neither Vim nor Neovim found on this system", "ERROR")
|
||
self.log("Install one of them first:")
|
||
self.log(" - Neovim: https://neovim.io")
|
||
self.log(" - Vim: https://www.vim.org")
|
||
return False
|
||
|
||
success = True
|
||
|
||
# Install for Neovim
|
||
if editors["neovim"]:
|
||
if not self.install_neovim_plugin():
|
||
success = False
|
||
|
||
# Install for Vim
|
||
if editors["vim"]:
|
||
if not self.install_vim_plugin():
|
||
success = False
|
||
|
||
# Summary
|
||
self.log("=" * 60)
|
||
if self.installed:
|
||
self.log("Installation Summary:", "SUCCESS")
|
||
for editor, path in self.installed:
|
||
self.log(f" {editor}: {path}")
|
||
|
||
if self.errors:
|
||
self.log("Errors encountered:", "ERROR")
|
||
for error in self.errors:
|
||
self.log(f" - {error}")
|
||
|
||
self.log("=" * 60)
|
||
|
||
# Usage instructions
|
||
if self.installed:
|
||
self.log("\n✅ Installation successful!\n", "SUCCESS")
|
||
self.log("Usage:")
|
||
self.log(" 1. Select text in visual mode (V + arrows)")
|
||
self.log(" 2. Press <leader>a (usually comma+a)")
|
||
self.log(" 3. Enter your instruction")
|
||
self.log(" 4. Text is transformed instantly")
|
||
self.log("\nDocumentation:")
|
||
self.log(" - Quick start: QUICK_START.md")
|
||
self.log(" - Detailed setup: SETUP.md")
|
||
self.log(" - Test cases: TEST_CASES.md")
|
||
self.log(" - Technical details: TECHNICAL.md")
|
||
return True
|
||
else:
|
||
self.log("Installation failed", "ERROR")
|
||
return False
|
||
|
||
def verify_installation(self):
|
||
"""Verify that plugin files exist and are readable"""
|
||
self.log("\nVerifying installation...")
|
||
|
||
all_good = True
|
||
for editor, path in self.installed:
|
||
if path.exists() and path.is_file():
|
||
size = path.stat().st_size
|
||
self.log(f"✓ {editor} plugin verified ({size} bytes)")
|
||
else:
|
||
self.log(f"✗ {editor} plugin not found at {path}", "ERROR")
|
||
all_good = False
|
||
|
||
return all_good
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(
|
||
description="Install Claude Filter Vim plugin",
|
||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
epilog="""
|
||
Examples:
|
||
python3 install.py # Install with auto-detection
|
||
python3 install.py --verbose # Show detailed output
|
||
python3 install.py --override # Update existing installation
|
||
python3 install.py -v -o # Both verbose and override
|
||
"""
|
||
)
|
||
|
||
parser.add_argument(
|
||
"-v", "--verbose",
|
||
action="store_true",
|
||
help="Show detailed installation messages"
|
||
)
|
||
|
||
parser.add_argument(
|
||
"-o", "--override",
|
||
action="store_true",
|
||
help="Override existing installation (update)"
|
||
)
|
||
|
||
parser.add_argument(
|
||
"--verify",
|
||
action="store_true",
|
||
help="Only verify existing installation"
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
installer = PluginInstaller(verbose=args.verbose, override=args.override)
|
||
|
||
if args.verify:
|
||
installer.install()
|
||
installer.verify_installation()
|
||
else:
|
||
success = installer.install()
|
||
if success:
|
||
installer.verify_installation()
|
||
sys.exit(0)
|
||
else:
|
||
sys.exit(1)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|