diff --git a/pyproject.toml b/pyproject.toml index 5e90228..d7af3be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ dependencies = [ "argparse>=1.4.0", "configparser>=7.2.0", "datetime>=6.0", + "rich>=14.3.3", ] [project.scripts] diff --git a/src/forthlift/forthlift.py b/src/forthlift/forthlift.py index 8592dcd..31bb264 100755 --- a/src/forthlift/forthlift.py +++ b/src/forthlift/forthlift.py @@ -6,7 +6,10 @@ import locale import logging import argparse import datetime + from configparser import ConfigParser +from rich.panel import Panel +from rich import print # # LIBRARY @@ -33,6 +36,19 @@ class consume: def __call__(self, stream): return stream.readlines() + class paragraphs(Consume): + def __call__(self, stream): + pars = [] + current = "" + for item in stream.readlines(): + # Not counting spaces as legit content. + if item.strip(): + current += item + else: + pars.append( current ) + current = "" + return pars + class format: class Format: def __call__(self, items): @@ -43,22 +59,23 @@ class format: return items class trim(Format): - def __init__(self, max = "14"): + # Every argument is a string. + def __init__(self, max = "140"): self.max = int(max) - def trim(self, line): - if len(line) > self.max: - yield line[:self.max] - for subline in self.trim(line[self.max:]): - yield subline + def trim(self, item): + if len(item) > self.max: + yield item[:self.max] + for subitem in self.trim(item[self.max:]): + yield subitem else: - yield line + yield item def __call__(self, items): trimmed = [] for item in items: - for subline in self.trim(item): - trimmed.append(subline) + for separated in self.trim(item): + trimmed.append(separated) return trimmed class eol(Format): @@ -75,6 +92,63 @@ class format: stripped.append( item.strip() ) return stripped + class skip(Format): + def __call__(self, items): + res = [] + for item in items: + if item.strip(): + res.append( item ) + return res + + class paragraph(Format): + def __call__(self, items): + glued = [] + current = "" + for item in items: + if item.strip(): + current += item + else: + glued.append( current ) + current = "" + return glued + + class panel(Format): + def __call__(self, items): + panel = [] + for item in items: + panel.append( Panel.fit(item.strip()) ) + return panel + + class count(Format): + def __init__(self, end = ' ␄', sep = '\n'): + self.sep = sep + self.end = end + + def __call__(self, items): + total = len(items) + res = [] + for i,item in enumerate(items): + res.append(f"{item}{self.sep}{i+1}/{total}") + if res: + res[-1] += self.end + return res + + class suffix(Format): + def __init__(self, content = "", sep = '\n'): + self.content = content + self.sep = sep + + def __call__(self, items): + return [i+self.sep+self.content for i in items] + + class prefix(Format): + def __init__(self, content = "", sep = '\n'): + self.content = content + self.sep = sep + + def __call__(self, items): + return [self.content+self.sep+i for i in items] + class lift: class Lift: @@ -84,10 +158,13 @@ class lift: class stdout(Lift): def __call__(self, items): for item in items: - if __debug__: - print(item, end = '', file = sys.stdout, flush = True) + if item: + if __debug__: + print(item, end = '', file = sys.stdout, flush = True) + else: + print(item, end = '') else: - print(item, end = '') + logger.debug("Empty item") class Forthlifter: @@ -97,14 +174,14 @@ class Forthlifter: formatters = [format.as_is()], lifters = [lift.stdout()], ): - self.consumer = consumer - logger.debug(f"├ consumer: {type(consumer).__name__}") - if not isinstance(streamers, list): streamers = [streamers] self.streamers = streamers logger.debug(f"├ streamers: {', '.join(type(i).__name__ for i in self.streamers)}") + self.consumer = consumer + logger.debug(f"├ consumer: {type(consumer).__name__}") + if not isinstance(formatters, list): formatters = [formatters] self.formatters = formatters @@ -166,7 +243,7 @@ def operator(asked_op): # because the shell would try to interpret # any unescaped/unquoted parentheses. # It is faster to use f:a for the user. - m = re.match("(\w+):(.+)", op) + m = re.match(r"(\w+):(.+)", op) if m: name = m.group(1) args = [a.strip() for a in m.group(2).split(',')]