from escpos.printer import CupsPrinter from itertools import zip_longest class CallbackContext: def __init__(self, enter=None, exit=None): self.enter = enter self.exit = exit def __enter__(self): if self.enter: return self.enter() def __exit__(self, *_): if self.exit: self.exit() class Split2Context: def __init__( self, printer, num_cols=2, widths=None, align="<", aligns=None, columns=48 ): self.printer = printer self.num_cols = num_cols or len(widths) self.widths = widths or [columns // self.num_cols] * self.num_cols self.aligns = aligns or [align] * self.num_cols self.col_length = columns // 2 self.columns = [[] for i in range(self.num_cols)] def col(self, num, text): self.columns[num].append(f"{text:{self.aligns[num]}{self.widths[num]}}") def left(self, text): self.col(0, text) def right(self, text): self.col(-1, text) def __enter__(self): return self def __exit__(self, *_): lines = map("".join, zip_longest(*self.columns, fillvalue=" " * self.num_cols)) for line in lines: self.printer.textln(line) class ReceiptPrinter(CupsPrinter): def __init__(self, *args, autocut=True, **kwargs): self.autocut = autocut super().__init__(*args, **kwargs) def __enter__(self): self.open() return self def __exit__(self, _type, _value, _traceback): if self.autocut: self.cut() self.close() def set(self, *args, **kwargs): super().set(*args, **kwargs) return CallbackContext(exit=super().set_with_default) def set_with_default(self, *args, **kwargs): super().set_with_default(*args, **kwargs) return CallbackContext(exit=super().set_with_default) def split(self, left, right, cols=48): self.textln(f"{left:<{cols//2}}{right:<{cols//2}}") def vsplit(self, *args, **kwargs): return Split2Context(self, *args, **kwargs) def invert(self, text): with self.set(invert=True): self.text(text) def invertln(self, text): self.invert(text) self.ln() def bold(self, text): with self.set(bold=True): self.text(text) def boldln(self, text): self.bold(text) self.ln() def title(self, text, size=6, width=None, height=None): width = width or size height = height or size with self.set(align="center", bold=True, invert=True, smooth=True, custom_size=True, width=width, height=height): self.textln(text) self.ln() def subtitle(self, text): with self.set(align="center", double_height=True, double_width=True): p.textln(text) #p = ReceiptPrinter("EPSON-TM-m30", profile="default") p = ReceiptPrinter("EPSON-TM-m30-remote", profile="default")