implement general interface for tex formatters
This commit is contained in:
parent
9ae70fae13
commit
1094fce0a4
2 changed files with 75 additions and 4 deletions
25
PyTeX/format/macros.py
Normal file
25
PyTeX/format/macros.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from typing import List, Union
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class MacroReplacement(Enum):
|
||||||
|
author = 'author'
|
||||||
|
shortauthor = 'shortauthor'
|
||||||
|
date = 'date'
|
||||||
|
year = 'year'
|
||||||
|
version = 'version',
|
||||||
|
file_name = 'file_name'
|
||||||
|
name = 'name' # class or package name
|
||||||
|
repo_version = 'repo_version'
|
||||||
|
pytex_version = 'pytex_version'
|
||||||
|
|
||||||
|
|
||||||
|
class Macro:
|
||||||
|
def __init__(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def matches(self, line: str) -> bool:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def apply(self, line: str, *args, **kwargs) -> Union[str, List[str]]:
|
||||||
|
raise NotImplementedError
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import List, TextIO
|
from typing import List, TextIO, Optional, Tuple, Dict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .pytex_formatter import PyTeXFormatter
|
from .pytex_formatter import PyTeXFormatter
|
||||||
from .macros import Macro
|
from .macros import Macro
|
||||||
|
@ -9,6 +9,7 @@ class LineStream:
|
||||||
self._file = filename
|
self._file = filename
|
||||||
self._handle = open(filename, 'r')
|
self._handle = open(filename, 'r')
|
||||||
self._cached_lines: List[str] = []
|
self._cached_lines: List[str] = []
|
||||||
|
self._file_exhausted: bool = False
|
||||||
|
|
||||||
def current_line(self):
|
def current_line(self):
|
||||||
return self.future_line(0)
|
return self.future_line(0)
|
||||||
|
@ -43,21 +44,66 @@ class LineStream:
|
||||||
)
|
)
|
||||||
if self._cached_lines[-1] == '':
|
if self._cached_lines[-1] == '':
|
||||||
self._handle.close()
|
self._handle.close()
|
||||||
|
self._file_exhausted = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def exhausted(self) -> bool:
|
||||||
|
return self._file_exhausted & len(self._cached_lines) == 0
|
||||||
|
|
||||||
|
|
||||||
class TexFormatter(PyTeXFormatter):
|
class TexFormatter(PyTeXFormatter):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._macros: List[Macro] = []
|
self._macros: List[Macro] = []
|
||||||
|
self._line_stream: LineStream = None
|
||||||
self._output_file: TextIO = None
|
self._output_file: TextIO = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def line_stream(self) -> LineStream:
|
||||||
|
if self._line_stream is None:
|
||||||
|
self._line_stream = LineStream(self.input_file)
|
||||||
|
return self._line_stream
|
||||||
|
|
||||||
|
@property
|
||||||
|
def macros(self) -> List[Macro]:
|
||||||
|
return self._macros
|
||||||
|
|
||||||
def _handle_macro(self, macro: Macro):
|
def _handle_macro(self, macro: Macro):
|
||||||
self._current_line = macro.apply(self._current_line, self)
|
res = macro.apply(
|
||||||
|
self.line_stream.current_line(),
|
||||||
|
self
|
||||||
|
)
|
||||||
|
if isinstance(res, str):
|
||||||
|
self.line_stream.set_line(res)
|
||||||
|
else:
|
||||||
|
self.line_stream.pop_line()
|
||||||
|
self.line_stream.push_lines(res)
|
||||||
|
|
||||||
def _shipout_line(self):
|
def _shipout_line(self):
|
||||||
self.write_line(self._current_line.rstrip())
|
line = self.line_stream.pop_line().rstrip()
|
||||||
|
self.write_line(line)
|
||||||
|
|
||||||
def write_line(self, line: str):
|
def write_line(self, line: str):
|
||||||
self._output_file.writelines([line])
|
self._output_file.write(line)
|
||||||
|
|
||||||
|
def open_output_stream(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def future_config(self) -> Optional[List[Tuple[str, Dict]]]:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def format(self, build_dir: Path, overwrite: bool = False) -> Optional[List[Tuple[str, Dict]]]:
|
||||||
|
self.open_output_stream()
|
||||||
|
while not self.line_stream.exhausted:
|
||||||
|
recent_replacement = True
|
||||||
|
while recent_replacement:
|
||||||
|
recent_replacement = False
|
||||||
|
for macro in self.macros:
|
||||||
|
if macro.matches(self.line_stream.current_line()):
|
||||||
|
self._handle_macro(macro)
|
||||||
|
recent_replacement = True
|
||||||
|
break
|
||||||
|
self._shipout_line()
|
||||||
|
self._output_file.close()
|
||||||
|
return self.future_config
|
||||||
|
|
Loading…
Reference in a new issue