Initial commit
This commit is contained in:
194
skills/zellij-config/scripts/convert_themes.py
Normal file
194
skills/zellij-config/scripts/convert_themes.py
Normal file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Zellij Theme Converter - Convert themes between formats and create custom themes
|
||||
|
||||
Usage:
|
||||
convert_themes.py [COMMAND] [OPTIONS]
|
||||
|
||||
Commands:
|
||||
create - Create a new custom theme
|
||||
convert - Convert legacy YAML theme to KDL
|
||||
list - List available theme templates
|
||||
|
||||
Examples:
|
||||
convert_themes.py create --name mytheme --rgb
|
||||
convert_themes.py convert /path/to/theme.yaml
|
||||
convert_themes.py list
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
THEME_TEMPLATES = {
|
||||
"nord": {
|
||||
"fg": "#D8DEE9",
|
||||
"bg": "#2E3440",
|
||||
"black": "#3B4252",
|
||||
"red": "#BF616A",
|
||||
"green": "#A3BE8C",
|
||||
"yellow": "#EBCB8B",
|
||||
"blue": "#81A1C1",
|
||||
"magenta": "#B48EAD",
|
||||
"cyan": "#88C0D0",
|
||||
"white": "#E5E9F0",
|
||||
"orange": "#D08770"
|
||||
},
|
||||
"dracula": {
|
||||
"fg": "248 248 242",
|
||||
"bg": "40 42 54",
|
||||
"black": "0 0 0",
|
||||
"red": "255 85 85",
|
||||
"green": "80 250 123",
|
||||
"yellow": "241 250 140",
|
||||
"blue": "98 114 164",
|
||||
"magenta": "255 121 198",
|
||||
"cyan": "139 233 253",
|
||||
"white": "255 255 255",
|
||||
"orange": "255 184 108"
|
||||
},
|
||||
"gruvbox-dark": {
|
||||
"fg": "#ebdbb2",
|
||||
"bg": "#282828",
|
||||
"black": "#1d2021",
|
||||
"red": "#cc241d",
|
||||
"green": "#98971a",
|
||||
"yellow": "#d79921",
|
||||
"blue": "#83a598",
|
||||
"magenta": "#d3869b",
|
||||
"cyan": "#8ec07c",
|
||||
"white": "#ebdbb2",
|
||||
"orange": "#fe8019"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def create_theme(name, use_rgb=True):
|
||||
"""Create a new custom theme interactively."""
|
||||
theme_data = {}
|
||||
|
||||
print(f"🎨 Creating theme: {name}")
|
||||
print("Enter theme colors (press Enter for defaults):")
|
||||
|
||||
colors = ["fg", "bg", "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"]
|
||||
|
||||
for color in colors:
|
||||
if use_rgb:
|
||||
print(f"{color} (RGB format: r g b):")
|
||||
value = input(f" {color}: ").strip()
|
||||
if value:
|
||||
# Parse RGB values
|
||||
parts = value.split()
|
||||
if len(parts) == 3 and all(p.isdigit() for p in parts):
|
||||
theme_data[color] = f"{parts[0]} {parts[1]} {parts[2]}"
|
||||
else:
|
||||
print(f" Using default {color}")
|
||||
else:
|
||||
print(f"{color} (hex format: #RRGGBB):")
|
||||
value = input(f" {color}: ").strip()
|
||||
if value:
|
||||
theme_data[color] = value
|
||||
|
||||
return theme_data
|
||||
|
||||
|
||||
def generate_kdl_theme(name, theme_data, output_path):
|
||||
"""Generate KDL format theme file."""
|
||||
content = f"themes {{\n {name} {{\n"
|
||||
|
||||
for color, value in theme_data.items():
|
||||
content += f' {color} {value}\n'
|
||||
|
||||
content += " }}\n}}\n"
|
||||
|
||||
try:
|
||||
with open(output_path, 'w') as f:
|
||||
f.write(content)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Error writing theme file: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def convert_yaml_to_kdl(yaml_path):
|
||||
"""Convert legacy YAML theme to KDL format."""
|
||||
try:
|
||||
import yaml
|
||||
with open(yaml_path, 'r') as f:
|
||||
theme_data = yaml.safe_load(f)
|
||||
|
||||
if not theme_data:
|
||||
print("❌ No theme data found in YAML file")
|
||||
return False
|
||||
|
||||
# Extract theme name from filename
|
||||
theme_name = Path(yaml_path).stem
|
||||
output_path = Path(yaml_path).with_suffix('.kdl')
|
||||
|
||||
return generate_kdl_theme(theme_name, theme_data, output_path)
|
||||
except ImportError:
|
||||
print("❌ PyYAML not installed. Install with: pip install pyyaml")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Error converting YAML theme: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def list_templates():
|
||||
"""List available theme templates."""
|
||||
print("📋 Available theme templates:")
|
||||
for name, colors in THEME_TEMPLATES.items():
|
||||
print(f" {name}:")
|
||||
if isinstance(colors["fg"], str):
|
||||
print(f" Type: Hexadecimal")
|
||||
print(f" Preview: FG={colors['fg']}, BG={colors['bg']}")
|
||||
else:
|
||||
print(f" Type: RGB")
|
||||
print(f" Preview: FG=({colors['fg']}), BG=({colors['bg']})")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Manage Zellij themes")
|
||||
subparsers = parser.add_subparsers(dest='command', help='Available commands')
|
||||
|
||||
# Create command
|
||||
create_parser = subparsers.add_parser('create', help='Create new custom theme')
|
||||
create_parser.add_argument('--name', required=True, help='Theme name')
|
||||
create_parser.add_argument('--hex', action='store_true', help='Use hexadecimal color format (default: RGB)')
|
||||
create_parser.add_argument('--output', help='Output file path (default: ~/.config/zellij/themes/name.kdl)')
|
||||
|
||||
# Convert command
|
||||
convert_parser = subparsers.add_parser('convert', help='Convert YAML theme to KDL')
|
||||
convert_parser.add_argument('yaml_path', help='Path to YAML theme file')
|
||||
|
||||
# List command
|
||||
list_parser = subparsers.add_parser('list', help='List theme templates')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == 'create':
|
||||
theme_data = create_theme(args.name, not args.hex)
|
||||
output_path = args.output or Path.home() / ".config" / "zellij" / "themes" / f"{args.name}.kdl"
|
||||
|
||||
if generate_kdl_theme(args.name, theme_data, output_path):
|
||||
print(f"✅ Theme created: {output_path}")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
elif args.command == 'convert':
|
||||
if convert_yaml_to_kdl(args.yaml_path):
|
||||
print("✅ Theme conversion complete")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
elif args.command == 'list':
|
||||
list_templates()
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
178
skills/zellij-config/scripts/create_layout.py
Normal file
178
skills/zellij-config/scripts/create_layout.py
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Zellij Layout Creator - Generate custom layouts from templates or parameters
|
||||
|
||||
Usage:
|
||||
create_layout.py [LAYOUT_TYPE] [OPTIONS]
|
||||
|
||||
Layout Types:
|
||||
dev - Development layout with editor and git
|
||||
monitor - Monitoring layout with system metrics
|
||||
terminal - Simple terminal layout
|
||||
custom - Interactive custom layout creation
|
||||
|
||||
Examples:
|
||||
create_layout.py dev --name myproject
|
||||
create_layout.py monitor --theme nord
|
||||
create_layout.py terminal --horizontal-split 2
|
||||
create_layout.py custom --panes 3 --direction vertical
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
LAYOUT_TEMPLATES = {
|
||||
"dev": """layout {
|
||||
default_tab_template {{
|
||||
pane size=1 borderless=true {{
|
||||
plugin location="zellij:tab-bar"
|
||||
}}
|
||||
children
|
||||
pane size=2 borderless=true {{
|
||||
plugin location="zellij:status-bar"
|
||||
}}
|
||||
}}
|
||||
tab name="{name}" cwd="{cwd}" focus=true {{
|
||||
pane command="nvim" size="80%"
|
||||
pane size="20%" split_direction="vertical" {{
|
||||
pane command="git" {{
|
||||
args "status"
|
||||
size="50%"
|
||||
}}
|
||||
pane command="htop"
|
||||
}}
|
||||
}}
|
||||
tab name="terminal" {{
|
||||
pane command="bash"
|
||||
}}
|
||||
}}""",
|
||||
|
||||
"monitor": """layout {{
|
||||
default_tab_template {{
|
||||
pane size=1 borderless=true {{
|
||||
plugin location="zellij:tab-bar"
|
||||
}}
|
||||
children
|
||||
pane size=2 borderless=true {{
|
||||
plugin location="zellij:status-bar"
|
||||
}}
|
||||
}}
|
||||
tab name="monitoring" split_direction="horizontal" {{
|
||||
pane command="htop"
|
||||
pane command="btop"
|
||||
pane command="iotop"
|
||||
pane command="nethogs"
|
||||
}}
|
||||
}}""",
|
||||
|
||||
"terminal": """layout {{
|
||||
tab name="main" {{
|
||||
pane command="bash"{split}
|
||||
}}
|
||||
}}"""
|
||||
}
|
||||
|
||||
|
||||
def create_custom_layout(panes, direction, name):
|
||||
"""Create a custom layout with specified number of panes."""
|
||||
if direction == "horizontal":
|
||||
split_attr = 'split_direction="horizontal"'
|
||||
else:
|
||||
split_attr = 'split_direction="vertical"'
|
||||
|
||||
layout = f'''layout {{
|
||||
tab name="{name}" {{
|
||||
pane command="bash"
|
||||
{split_attr} {{
|
||||
'''
|
||||
|
||||
# Add panes
|
||||
for i in range(1, panes):
|
||||
if i == panes:
|
||||
layout += f' pane command="bash"\n'
|
||||
else:
|
||||
layout += f' pane command="bash"\n'
|
||||
|
||||
layout += f' }}\n }}\n}}'''
|
||||
|
||||
return layout
|
||||
|
||||
|
||||
def get_layout_path(layouts_dir, layout_name):
|
||||
"""Get full path for layout file."""
|
||||
return layouts_dir / f"{layout_name}.kdl"
|
||||
|
||||
|
||||
def write_layout_file(layout_path, content):
|
||||
"""Write layout content to file."""
|
||||
try:
|
||||
layout_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(layout_path, 'w') as f:
|
||||
f.write(content)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Error writing layout file: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def get_layout_cwd():
|
||||
"""Get current working directory for layout."""
|
||||
return os.getcwd()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Create Zellij layouts from templates")
|
||||
parser.add_argument("layout_type", choices=["dev", "monitor", "terminal", "custom"],
|
||||
help="Type of layout to create")
|
||||
parser.add_argument("--name", default="workspace",
|
||||
help="Name for the layout (default: workspace)")
|
||||
parser.add_argument("--cwd", help="Working directory for layout (default: current directory)")
|
||||
parser.add_argument("--theme", help="Theme to apply (e.g., nord, dracula)")
|
||||
|
||||
# Custom layout options
|
||||
parser.add_argument("--panes", type=int, default=2,
|
||||
help="Number of panes for custom layout (default: 2)")
|
||||
parser.add_argument("--direction", choices=["horizontal", "vertical"], default="horizontal",
|
||||
help="Split direction for custom layout (default: horizontal)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Determine layouts directory
|
||||
layouts_dir = Path.home() / ".config" / "zellij" / "layouts"
|
||||
|
||||
# Get layout name and cwd
|
||||
layout_name = args.name
|
||||
cwd = args.cwd or get_layout_cwd()
|
||||
|
||||
print(f"🚀 Creating {args.layout_type} layout...")
|
||||
|
||||
# Generate layout content
|
||||
if args.layout_type == "custom":
|
||||
content = create_custom_layout(args.panes, args.direction, layout_name)
|
||||
elif args.layout_type in LAYOUT_TEMPLATES:
|
||||
content = LAYOUT_TEMPLATES[args.layout_type].format(
|
||||
name=layout_name,
|
||||
cwd=cwd
|
||||
)
|
||||
else:
|
||||
print(f"❌ Unknown layout type: {args.layout_type}")
|
||||
sys.exit(1)
|
||||
|
||||
# Add theme if specified
|
||||
if args.theme:
|
||||
content += f'\ntheme "{args.theme}"\n'
|
||||
|
||||
# Write layout file
|
||||
layout_path = get_layout_path(layouts_dir, layout_name)
|
||||
if write_layout_file(layout_path, content):
|
||||
print(f"✅ Layout created: {layout_path}")
|
||||
print(f"💡 Use with: zellij --layout {layout_path}")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
19
skills/zellij-config/scripts/example.py
Executable file
19
skills/zellij-config/scripts/example.py
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example helper script for zellij-config
|
||||
|
||||
This is a placeholder script that can be executed directly.
|
||||
Replace with actual implementation or delete if not needed.
|
||||
|
||||
Example real scripts from other skills:
|
||||
- pdf/scripts/fill_fillable_fields.py - Fills PDF form fields
|
||||
- pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images
|
||||
"""
|
||||
|
||||
def main():
|
||||
print("This is an example script for zellij-config")
|
||||
# TODO: Add actual script logic here
|
||||
# This could be data processing, file conversion, API calls, etc.
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
217
skills/zellij-config/scripts/setup_zellij.py
Normal file
217
skills/zellij-config/scripts/setup_zellij.py
Normal file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Zellij Setup Script - Automates initial Zellij configuration setup
|
||||
|
||||
Usage:
|
||||
setup_zellij.py [--theme THEME] [--layout LAYOUT] [--keybindings] [--clean]
|
||||
|
||||
Examples:
|
||||
setup_zellij.py --theme nord --layout dev
|
||||
setup_zellij.py --clean
|
||||
setup_zellij.py --keybindings
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def create_config_directory():
|
||||
"""Create Zellij configuration directory if it doesn't exist."""
|
||||
config_dir = Path.home() / ".config" / "zellij"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
return config_dir
|
||||
|
||||
|
||||
def dump_default_config(config_path):
|
||||
"""Dump default Zellij configuration to file."""
|
||||
import subprocess
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["zellij", "setup", "--dump-config"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
with open(config_path, 'w') as f:
|
||||
f.write(result.stdout)
|
||||
print(f"✅ Default config written to {config_path}")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ Failed to dump default config: {result.stderr}")
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
print("❌ zellij command not found. Please install Zellij first.")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Error running zellij: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def create_layout_directory(config_dir):
|
||||
"""Create layouts directory within config directory."""
|
||||
layouts_dir = config_dir / "layouts"
|
||||
layouts_dir.mkdir(exist_ok=True)
|
||||
return layouts_dir
|
||||
|
||||
|
||||
def setup_theme(theme_name, config_path):
|
||||
"""Set theme in configuration file."""
|
||||
if not theme_name:
|
||||
return True
|
||||
|
||||
try:
|
||||
with open(config_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if theme block exists, if not add it
|
||||
if 'theme "' not in content:
|
||||
content += '\ntheme "' + theme_name + '"\n'
|
||||
else:
|
||||
# Replace existing theme
|
||||
import re
|
||||
content = re.sub(r'theme\s+"[^"]*"', f'theme "{theme_name}"', content)
|
||||
|
||||
with open(config_path, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"✅ Theme set to: {theme_name}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Error setting theme: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def create_default_layout(layout_name, layouts_dir):
|
||||
"""Create a default layout template."""
|
||||
import subprocess
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["zellij", "setup", "--dump-layout", "default"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
layout_path = layouts_dir / f"{layout_name}.kdl"
|
||||
with open(layout_path, 'w') as f:
|
||||
f.write(result.stdout)
|
||||
print(f"✅ Default layout created: {layout_path}")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ Failed to create layout: {result.stderr}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Error creating layout: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def setup_keybindings_hint():
|
||||
"""Provide hint for setting up keybindings."""
|
||||
print("""
|
||||
📝 Keybinding Setup Tips:
|
||||
|
||||
1. Edit ~/.config/zellij/config.kdl
|
||||
2. Add keybinds section:
|
||||
keybinds {
|
||||
normal {
|
||||
bind "Ctrl g" { SwitchToMode "locked"; }
|
||||
bind "Ctrl p" { SwitchToMode "pane"; }
|
||||
// ... add more bindings
|
||||
}
|
||||
}
|
||||
3. Common modes: normal, pane, locked, shared, session
|
||||
4. Use 'zellij setup --check' to validate
|
||||
""")
|
||||
|
||||
|
||||
def validate_config(config_path):
|
||||
"""Validate Zellij configuration."""
|
||||
import subprocess
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["zellij", "setup", "--check"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
print("✅ Configuration is valid")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ Configuration errors: {result.stderr}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Error validating config: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Setup Zellij configuration with optional theme and layout",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("--theme", help="Set theme (e.g., nord, dracula, default)")
|
||||
parser.add_argument("--layout", help="Create default layout with specified name")
|
||||
parser.add_argument("--keybindings", action="store_true", help="Show keybinding setup hints")
|
||||
parser.add_argument("--clean", action="store_true", help="Start fresh (clean setup)")
|
||||
parser.add_argument("--validate", action="store_true", help="Validate existing configuration")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Create config directory
|
||||
config_dir = create_config_directory()
|
||||
config_path = config_dir / "config.kdl"
|
||||
|
||||
print(f"🚀 Setting up Zellij configuration...")
|
||||
print(f" Config directory: {config_dir}")
|
||||
|
||||
if args.clean:
|
||||
print("Starting with clean configuration...")
|
||||
if dump_default_config(config_path):
|
||||
print("✅ Clean setup complete")
|
||||
else:
|
||||
sys.exit(1)
|
||||
return
|
||||
|
||||
if args.validate:
|
||||
if config_path.exists():
|
||||
validate_config(config_path)
|
||||
else:
|
||||
print("❌ No configuration found to validate")
|
||||
return
|
||||
|
||||
# Setup basic config if it doesn't exist
|
||||
if not config_path.exists():
|
||||
print("Creating default configuration...")
|
||||
if not dump_default_config(config_path):
|
||||
sys.exit(1)
|
||||
|
||||
# Create layouts directory
|
||||
layouts_dir = create_layout_directory(config_dir)
|
||||
|
||||
# Set theme if specified
|
||||
if args.theme:
|
||||
setup_theme(args.theme, config_path)
|
||||
|
||||
# Create default layout if specified
|
||||
if args.layout:
|
||||
create_default_layout(args.layout, layouts_dir)
|
||||
|
||||
# Show keybinding hints if requested
|
||||
if args.keybindings:
|
||||
setup_keybindings_hint()
|
||||
|
||||
# Validate final configuration
|
||||
if config_path.exists():
|
||||
validate_config(config_path)
|
||||
|
||||
print("✅ Zellij setup complete!")
|
||||
print(f"📁 Configuration file: {config_path}")
|
||||
print(f"📁 Layouts directory: {layouts_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user