|
|
@@ -0,0 +1,124 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+"""Quick editor for dotfiles directories"""
|
|
|
+
|
|
|
+import os
|
|
|
+import subprocess
|
|
|
+import sys
|
|
|
+from pathlib import Path
|
|
|
+
|
|
|
+DOTFILES_DIR = Path.home() / "dotfiles"
|
|
|
+
|
|
|
+
|
|
|
+def find_config_dir(base_dir):
|
|
|
+ """Find the actual config directory within a dotfiles package."""
|
|
|
+ base_path = Path(base_dir)
|
|
|
+
|
|
|
+ # Common patterns: .config/package, .config/package/package, etc.
|
|
|
+ common_paths = [
|
|
|
+ base_path / ".config" / base_path.name, # ~/dotfiles/niri/.config/niri
|
|
|
+ base_path / ".config", # ~/dotfiles/niri/.config
|
|
|
+ base_path, # fallback to base
|
|
|
+ ]
|
|
|
+
|
|
|
+ # Check for .config/package pattern first
|
|
|
+ config_package = base_path / ".config" / base_path.name
|
|
|
+ if config_package.exists() and config_package.is_dir():
|
|
|
+ return config_package
|
|
|
+
|
|
|
+ # Check for .config directory
|
|
|
+ config_dir = base_path / ".config"
|
|
|
+ if config_dir.exists() and config_dir.is_dir():
|
|
|
+ return config_dir
|
|
|
+
|
|
|
+ # Fallback to base directory
|
|
|
+ return base_path
|
|
|
+
|
|
|
+
|
|
|
+def get_dotfiles_dirs():
|
|
|
+ """Get list of dotfiles directories with their config paths."""
|
|
|
+ if not DOTFILES_DIR.exists():
|
|
|
+ return []
|
|
|
+
|
|
|
+ dirs = []
|
|
|
+ for item in sorted(DOTFILES_DIR.iterdir()):
|
|
|
+ if item.is_dir() and not item.name.startswith("."):
|
|
|
+ config_path = find_config_dir(item)
|
|
|
+ dirs.append((item.name, config_path))
|
|
|
+ return dirs
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ dirs_configs = get_dotfiles_dirs()
|
|
|
+ if not dirs_configs:
|
|
|
+ sys.exit(1)
|
|
|
+
|
|
|
+ # Format with icons/emojis for better visual appeal
|
|
|
+ formatted_dirs = []
|
|
|
+ name_to_config = {}
|
|
|
+ icons = {
|
|
|
+ "niri": "🪟",
|
|
|
+ "zsh": "🐚",
|
|
|
+ "alacritty": "💻",
|
|
|
+ "kitty": "🐱",
|
|
|
+ "ghostty": "👻",
|
|
|
+ "git": "📦",
|
|
|
+ "fuzzel": "🔍",
|
|
|
+ "nvim": "⚡",
|
|
|
+ "vim": "⚡",
|
|
|
+ "tmux": "📺",
|
|
|
+ "zellij": "📺",
|
|
|
+ "env": "🌍",
|
|
|
+ "fonts": "🔤",
|
|
|
+ "applications": "📱",
|
|
|
+ }
|
|
|
+
|
|
|
+ for dir_name, config_path in dirs_configs:
|
|
|
+ icon = icons.get(dir_name.lower(), "📁")
|
|
|
+ formatted_dirs.append(f"{icon} {dir_name}")
|
|
|
+ name_to_config[dir_name] = config_path
|
|
|
+
|
|
|
+ # Present in fuzzel with styling
|
|
|
+ fuzzel_process = subprocess.Popen(
|
|
|
+ [
|
|
|
+ "fuzzel",
|
|
|
+ "--dmenu",
|
|
|
+ "--prompt", "📝 Edit: ",
|
|
|
+ "--width", "40",
|
|
|
+ "--lines", "15",
|
|
|
+ "--border-width", "2",
|
|
|
+ "--background-color", "#191724ff",
|
|
|
+ "--text-color", "#e0def4ff",
|
|
|
+ "--match-color", "#31748fff",
|
|
|
+ "--selection-color", "#1f1d2eff",
|
|
|
+ "--selection-text-color", "#31748fff",
|
|
|
+ "--selection-match-color", "#31748fff",
|
|
|
+ "--prompt-color", "#f6c177ff",
|
|
|
+ ],
|
|
|
+ stdin=subprocess.PIPE,
|
|
|
+ stdout=subprocess.PIPE,
|
|
|
+ text=True,
|
|
|
+ )
|
|
|
+
|
|
|
+ stdout, _ = fuzzel_process.communicate(input="\n".join(formatted_dirs))
|
|
|
+ selected = stdout.strip()
|
|
|
+
|
|
|
+ if not selected:
|
|
|
+ sys.exit(0)
|
|
|
+
|
|
|
+ # Remove icon and extract directory name
|
|
|
+ selected_dir = selected.split(" ", 1)[-1] if " " in selected else selected
|
|
|
+ selected_path = name_to_config.get(selected_dir)
|
|
|
+
|
|
|
+ if not selected_path or not selected_path.is_dir():
|
|
|
+ sys.exit(1)
|
|
|
+
|
|
|
+ # Open alacritty with nvim in the actual config directory
|
|
|
+ subprocess.Popen(
|
|
|
+ ["alacritty", f"--working-directory={selected_path}", "-e", "nvim"],
|
|
|
+ start_new_session=True,
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|
|
|
+
|