Files
2026-02-01 08:51:32 +00:00

174 lines
5.3 KiB
Python

"""Export aliases to various shell configuration formats."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional, Protocol
from .command_analyzer import AliasSuggestion
class ExportFormatter(ABC):
"""Abstract base class for export formatters."""
@abstractmethod
def format_alias(self, suggestion: AliasSuggestion) -> str:
"""Format a single alias for export."""
pass
@abstractmethod
def format_header(self) -> str:
"""Format the file header."""
pass
@abstractmethod
def get_file_extension(self) -> str:
"""Return the file extension for this format."""
pass
class BashFormatter(ExportFormatter):
"""Formatter for Bash alias syntax."""
def format_alias(self, suggestion: AliasSuggestion) -> str:
escaped = suggestion.original_command.replace("'", "'\\''")
return f"alias {suggestion.alias_name}='{escaped}'"
def format_header(self) -> str:
return "# Shell Aliases - Auto-generated by shell-alias-gen\n" \
"# Generated on: {date}\n\n".format(
date=self._get_timestamp()
)
def get_file_extension(self) -> str:
return ".bash"
def _get_timestamp(self) -> str:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
class ZshFormatter(ExportFormatter):
"""Formatter for Zsh alias syntax."""
def format_alias(self, suggestion: AliasSuggestion) -> str:
escaped = suggestion.original_command.replace("'", "'\\''")
return f"alias {suggestion.alias_name}='{escaped}'"
def format_header(self) -> str:
return "# Shell Aliases - Auto-generated by shell-alias-gen\n" \
"# Generated on: {date}\n" \
"# Mode: extended_glob\n\n".format(
date=self._get_timestamp()
)
def get_file_extension(self) -> str:
return ".zsh"
def _get_timestamp(self) -> str:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
class FishFormatter(ExportFormatter):
"""Formatter for Fish shell alias syntax."""
def format_alias(self, suggestion: AliasSuggestion) -> str:
escaped = suggestion.original_command.replace("'", "'\\''")
return f"alias {suggestion.alias_name}='{escaped}'"
def format_header(self) -> str:
return "# Shell Aliases - Auto-generated by shell-alias-gen\n" \
"# Generated on: {date}\n\n".format(
date=self._get_timestamp()
)
def get_file_extension(self) -> str:
return ".fish"
def _get_timestamp(self) -> str:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
class GenericFormatter(ExportFormatter):
"""Generic formatter that can be used for any shell."""
def format_alias(self, suggestion: AliasSuggestion) -> str:
return f"alias {suggestion.alias_name}='{suggestion.original_command}'"
def format_header(self) -> str:
return f"# Shell Aliases\n# Generated by shell-alias-gen\n\n"
def get_file_extension(self) -> str:
return ".sh"
class ExportManager:
"""Manages exporting aliases to various formats."""
FORMATTERS = {
'bash': BashFormatter,
'zsh': ZshFormatter,
'fish': FishFormatter,
'generic': GenericFormatter,
}
def __init__(self):
self._formatters: dict = {}
def get_formatter(self, shell_type: str) -> ExportFormatter:
"""Get a formatter for the specified shell type."""
shell = shell_type.lower()
if shell not in self.FORMATTERS:
shell = 'generic'
if shell not in self._formatters:
self._formatters[shell] = self.FORMATTERS[shell]()
return self._formatters[shell]
def export(
self,
suggestions: List[AliasSuggestion],
shell_type: str,
output_path: Optional[str] = None
) -> str:
"""Export aliases to a string or file."""
formatter = self.get_formatter(shell_type)
lines = [formatter.format_header()]
for suggestion in suggestions:
lines.append(formatter.format_alias(suggestion))
result = '\n'.join(lines) + '\n'
if output_path:
with open(output_path, 'w') as f:
f.write(result)
return result
def export_to_rcfile(
self,
suggestions: List[AliasSuggestion],
shell_type: str,
rcfile_path: str
) -> bool:
"""Append aliases to an existing rc file."""
formatter = self.get_formatter(shell_type)
section_header = f"\n# === Shell Aliases (shell-alias-gen) ===\n"
aliases = [formatter.format_alias(s) for s in suggestions]
content = section_header + '\n'.join(aliases) + '\n'
try:
with open(rcfile_path, 'a') as f:
f.write(content)
return True
except Exception:
return False
def get_supported_formats(self) -> List[str]:
"""Return list of supported export formats."""
return list(self.FORMATTERS.keys())