From 60ff9b3e992561f433c15613c7292fb57864b8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Wed, 6 Oct 2021 17:08:53 +0200 Subject: [PATCH] initial commit: first working version --- config.py | 4 ++ enums.py | 20 +++++++ package_formatter.py | 135 +++++++++++++++++++++++++++++++++++++++++++ replacements.py | 24 ++++++++ 4 files changed, 183 insertions(+) create mode 100644 config.py create mode 100644 enums.py create mode 100644 package_formatter.py create mode 100644 replacements.py diff --git a/config.py b/config.py new file mode 100644 index 0000000..b3b1bd3 --- /dev/null +++ b/config.py @@ -0,0 +1,4 @@ + + +DEFAULT_DESCRIPTION = 'Simple math package' +DEFAULT_AUTHOR = 'Maximilian Keßler' diff --git a/enums.py b/enums.py new file mode 100644 index 0000000..b062c3a --- /dev/null +++ b/enums.py @@ -0,0 +1,20 @@ +from enum import Enum + + +class Attributes(Enum): + package_name_raw = 'package_name_raw' + description = 'description' + author = 'author' + author_acronym = 'author_acronym' + package_name = 'package_name' + package_prefix = 'package_prefix' + file_name = 'file_name' + date = 'date' + + +class Args(Enum): + one = 0 + two = 1 + three = 2 + four = 3 + five = 4 diff --git a/package_formatter.py b/package_formatter.py new file mode 100644 index 0000000..073882b --- /dev/null +++ b/package_formatter.py @@ -0,0 +1,135 @@ +import datetime +import re +from pathlib import Path +from typing import Dict +from datetime import * +from config import DEFAULT_DESCRIPTION, DEFAULT_AUTHOR +from enums import Attributes, Args + + +class PackageFormatter: + def __init__(self, package_name: str, description: str = DEFAULT_DESCRIPTION, author: str = DEFAULT_AUTHOR): + self.package_name_raw = package_name + self.description = description + self.author = author + author_parts = self.author.lower().replace('ß', 'ss').split(' ') + self.author_acronym = author_parts[0][0] + author_parts[-1] + self.package_name = r'{prefix}-{name}'.format(prefix=self.author_acronym, + name=self.package_name_raw.lower().strip().replace(' ', '-')) + self.package_prefix = self.package_name.replace('-', '@') + '@' + self.file_name = self.package_name + '.sty' + self.date = datetime.now().strftime('%Y/%m/%d') + self.replace_dict: Dict = {} + self.arg_replace_dict: Dict = {} + + @staticmethod + def command_name2keyword(keyword: str): + return '__' + keyword.upper().strip().replace(' ', '_') + '__' + + def parse_replacement_args(self, *user_args, **user_kwargs): + new_args = [] + for arg in user_args: + if type(arg) == Attributes: + new_args.append(getattr(self, arg.value)) + elif type(arg) == Args: + new_args.append('{}') # Do *not* format this entry in the string + elif type(arg) == str: + new_args.append(arg) + else: + new_args += 'ERROR' + new_args = tuple(new_args) + new_kwargs = {} + for kw in user_kwargs: + if type(user_kwargs[kw]) == Attributes: + new_kwargs[kw] = getattr(self, user_kwargs[kw].value) + elif type(user_kwargs[kw]) == Args: + new_kwargs[kw] = '{{{}}}'.format(kw) # Do *not* format this entry in the string + elif type(user_kwargs[kw]) == str: + new_kwargs[kw] = user_kwargs[kw] + else: + new_kwargs[kw] = 'ERROR' + return new_args, new_kwargs + + @staticmethod + def filter_replacement_args(*user_args, **user_kwargs): + new_args = [] + for arg in user_args: + if type(arg) == Args: + new_args.append(arg) + new_args = tuple(new_args) + new_kwargs = {} + for kw in user_kwargs: + if type(user_kwargs[kw]) == Args: + new_kwargs[kw] = user_kwargs[kw] + return new_args, new_kwargs + + def add_replacement(self, keyword: str, replacement: str, *args, **kwargs) -> bool: + if keyword in self.replace_dict.keys(): + return False + args, kwargs = self.parse_replacement_args(*args, **kwargs) + self.replace_dict[self.command_name2keyword(keyword)] = replacement.format(*args, **kwargs) + return True + + @staticmethod + def parse_replacement_args2(match_groups, *user_args, **user_kwargs): + new_args = [] + for arg in user_args: + if type(arg) == Args: + new_args.append(match_groups[arg.value]) + new_args += 'ERROR' + new_args = tuple(new_args) + new_kwargs = {} + for kw in user_kwargs: + if type(user_kwargs[kw]) == Args: + new_kwargs[kw] = match_groups[user_kwargs[kw].value] + else: + new_kwargs[kw] = 'ERROR' + return new_args, new_kwargs + + def add_arg_replacement(self, num_args: int, keyword: str, replacement: str, *args, **kwargs): + if keyword in self.arg_replace_dict.keys(): + return False + format_args, format_kwargs = self.parse_replacement_args(*args, **kwargs) + filtered_args, filtered_kwargs = self.filter_replacement_args(*args, **kwargs) + self.arg_replace_dict[self.command_name2keyword(keyword)] = { + 'num_args': num_args, + 'replacement': replacement.format(*format_args, **format_kwargs), + 'format_args': filtered_args, + 'format_kwargs': filtered_kwargs + } + return True + + def format(self, contents: str) -> str: + for key in self.replace_dict.keys(): + contents = contents.replace(key, self.replace_dict[key]) + return contents + + def format_with_arg(self, contents: str) -> str: + for command in self.arg_replace_dict.keys(): + search_regex = re.compile(r'{keyword}\({arguments}\)'.format( + keyword=command, + arguments=','.join(['(.*)'] * self.arg_replace_dict[command]['num_args']) + )) + match = re.search(search_regex, contents) + while match is not None: + format_args, format_kwargs = self.parse_replacement_args2( + match.groups(), + *self.arg_replace_dict[command]['format_args'], + **self.arg_replace_dict[command]['format_kwargs'] + ) + contents = contents.replace( + match.group(), + self.arg_replace_dict[command]['replacement'].format(*format_args, **format_kwargs) + ) + match = re.search(search_regex, contents) + return contents + + def format_package(self, input_path: Path, output_dir: Path = None): + input_file = input_path.open() + lines = input_file.readlines() + newlines = [] + for line in lines: + newlines += self.format_with_arg(self.format(line)) + if output_dir is None: + output_dir = input_path.parent + (output_dir / self.file_name).write_text(''.join(newlines)) diff --git a/replacements.py b/replacements.py new file mode 100644 index 0000000..eed331d --- /dev/null +++ b/replacements.py @@ -0,0 +1,24 @@ +from enums import Attributes, Args +from package_formatter import PackageFormatter + + +def make_default_commands(package_formatter: PackageFormatter): + package_formatter.add_replacement('package name', '{}', Attributes.package_name) + package_formatter.add_replacement('package prefix', '{}', Attributes.package_prefix) + package_formatter.add_replacement('file name', '{name}', name=Attributes.file_name) + package_formatter.add_replacement('header', '\\NeedsTeXFormat{{LaTeX2e}}\n' + '\\ProvidesPackage{{{name}}}[{} - {}]\n' + '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%', + Attributes.date, + Attributes.description, + name=Attributes.package_name) + package_formatter.add_replacement('date', '{}', Attributes.date) + package_formatter.add_replacement('author', '{}', Attributes.author) + package_formatter.add_arg_replacement(1, 'newif', r'\newif\if{prefix}{condition}', + prefix=Attributes.package_prefix, condition=Args.one) + package_formatter.add_arg_replacement(2, 'setif', r'\{prefix}{condition}{value}', + prefix=Attributes.package_prefix, condition=Args.one, value=Args.two) + package_formatter.add_arg_replacement(1, 'if', r'\if{prefix}{condition}', prefix=Attributes.package_prefix, + condition=Args.one) + package_formatter.add_arg_replacement(1, 'info', r'\PackageInfo{{{name}}}{{{info}}}', name=Attributes.package_name, + info=Args.one)