Initial upload: Shell History Alias Generator with full test suite
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
173
shell_alias_gen/export_manager.py
Normal file
173
shell_alias_gen/export_manager.py
Normal file
@@ -0,0 +1,173 @@
|
||||
"""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())
|
||||
Reference in New Issue
Block a user