aliasindex/aliasindex/__main__.py

158 lines
3.9 KiB
Python
Executable File

#!/usr/bin/python3
from datetime import datetime, timezone
from jinja2 import Environment, select_autoescape
from pathlib import Path
from .schema import Document
import argparse
import re
import shlex
import unicodedata
import yaml
BASE_DIR = Path(__file__).absolute().parent
ENV = Environment(
extensions=[
'jinja2_highlight.HighlightExtension',
'jinja2_markdown.MarkdownExtension',
],
autoescape=select_autoescape(['html']),
trim_blocks=True,
lstrip_blocks=True,
)
def slugify(text):
text = unicodedata \
.normalize('NFKD', text) \
.encode('ascii', 'ignore') \
.decode('ascii')
text = re.sub(r'[^\w\s-]', '', text).strip().lower()
return re.sub(r'[-\s]+', '-', text)
ENV.filters.update({
'slug': slugify,
'quote': shlex.quote,
})
def build_html(*, data=None, template=None, dest_dir=None):
with template.open() as f:
tpl = ENV.from_string(f.read())
timestamp = datetime.now(timezone.utc).isoformat(timespec='seconds')
with (dest_dir / 'index.html').open('w') as f:
f.write(tpl.render(timestamp=timestamp, data=data))
def build_sh(*, data=None, template=None, dest_dir=None):
with template.open() as f:
tpl = ENV.from_string(f.read())
with (dest_dir / 'aliases.sh').open('w') as f:
f.write(tpl.render(data=data))
def validate_args(args):
assert args.src.is_file(), 'src should be an existing file'
assert args.dest_dir.is_dir(), 'dest_dir should be an existing directory'
assert any([
args.validate,
args.html_template,
args.shell_template,
]), 'Nothing to do!'
if args.html_template:
assert args.html_template.is_file(), 'HTML template does not exist'
if args.shell_template:
assert args.shell_template.is_file(), 'Shell template does not exist'
def absolute_path(value):
return Path(value).expanduser().absolute()
def main():
parser = argparse.ArgumentParser(description='Generate the alias index.')
parser.add_argument(
'--src',
type=absolute_path,
help='YAML file to fetch alias data from',
default='./aliases.yml',
)
parser.add_argument(
'--dest-dir',
type=absolute_path,
help='Destination path',
default='./output',
)
action_group = parser.add_mutually_exclusive_group()
action_group.add_argument(
'--validate',
help='Validate the schema without generating anything',
action='store_true',
)
html_group = parser.add_mutually_exclusive_group()
html_group.add_argument(
'-H', '--html-template',
type=absolute_path,
help='HTML template path',
default=BASE_DIR / 'template.html',
)
html_group.add_argument(
'--no-html',
help='Disable HTML generation',
action='store_false',
dest='html_template',
)
shell_group = parser.add_mutually_exclusive_group()
shell_group.add_argument(
'-S', '--shell-template',
type=absolute_path,
help='Shell script template path',
default=BASE_DIR / 'template.sh',
)
shell_group.add_argument(
'--no-shell',
help='Disable shell script generation',
action='store_false',
dest='shell_template',
)
args = parser.parse_args()
try:
validate_args(args)
except AssertionError as e:
parser.error(str(e))
with args.src.open() as f:
data = yaml.load(f.read())
data = Document.validate(data)
if args.validate:
return
if args.html_template:
build_html(
data=data,
template=args.html_template,
dest_dir=args.dest_dir,
)
if args.shell_template:
build_sh(
data=data,
template=args.shell_template,
dest_dir=args.dest_dir,
)
if __name__ == '__main__':
main()