import pprint import re import kutil def unescape_ktesc(s): """Resolve KTESC escape markers back to original characters. Use this for argument values used programmatically (filenames, etc.).""" def replace(match): hex_chars = match.group(1) result = '' for i in range(0, len(hex_chars), 4): result += chr(int(hex_chars[i:i+4], 16)) return result return re.sub(r'KTESC([0-9a-f]+)KTESC', replace, s) def escape_ktesc(s): """A KTESC marker for the characters of s -- the mirror of Target::escape_marker() in mac/target.cpp (4 lowercase hex digits per byte). The marker is inert through every re-read and through the target's typographic transform pass, and decodes back to the characters at final escape resolution (ktesc_resolve).""" return 'KTESC' + ''.join(f'{ord(c):04x}' for c in s) + 'KTESC' # The characters the SKS targets' typographic transforms act on: the # hyphen runs (-- and ---), the quote conventions (` ' `` ''), and ~. # Verbatim text (@c, @code, @source_listing) must reach the output exactly # as written, so the code klammers hide each of these as a KTESC marker -- # a transform source can then never match -- and the markers decode after # the transform pass has run. # SYNC: the transform tables of the html and txt targets in # sks/target/target.k. A transform built from a new character needs it # added here, or verbatim text will show the transformed form. TYPOGRAPHIC_CHARS = "-'`~" def hide_typographic(s): """Hide the typographically active characters of s as KTESC markers so the target's transform pass cannot change verbatim text.""" for c in TYPOGRAPHIC_CHARS: s = s.replace(c, escape_ktesc(c)) return s class Klammer_base: def __init__(self, K): #args = {k:escape(v) for k, v in K.__dict__.items() args = {k:v for k, v in K.__dict__.items() if not k.startswith('__')} for key in args: setattr(self, key, args[key]) #setattr(self, "_klammer_name", klammer_name) #pprint.pprint(self.__dict__) def html(self): #return '[{}: HTML]'.format(self.__class__.__name__) return None def tex(self): #return '[{}: LaTeX]'.format(self.__class__.__name__) return None def txt(self): #return '[{}: Plain text]'.format(self.__class__.__name__) return None def show(self, label=""): if label: print(label) pprint.pprint(self.__dict__) def __str__(self): result = None if self.K_target == 'html': result = self.html() elif self.K_target in {'tex', 'pdf'}: result = kutil.escape(self.tex()) elif self.K_target == 'txt': result = self.txt() if result is None: #print(self.__dict__) raise Exception( f'Target "{self.K_target}" is undefined for klammer "@{self.K_klammer}"') return result