self.account = data['account']
+ hp = text.HTMLParser()
+ hp.feed(data['content'])
+ hp.done()
+ self.content = hp.paras
+
def text(self):
yield text.SeparatorLine(self.datestamp)
yield text.FromLine('@' + self.account['acct'],
self.account['display_name'])
+ yield text.BlankLine()
+ yield from self.content
+ yield text.BlankLine()
class MainUI(Client):
def run(self):
for item in self.get_public("timelines/public", limit=10):
p = Post(item)
for thing in p.text():
- print(thing.render(79))
+ for line in thing.render(80):
+ print(line)
def main():
parser = argparse.ArgumentParser(
# Represent colourised terminal text in a width-independent form.
+import html.parser
import time
+import wcwidth
+
+class BlankLine:
+ def render(self, width):
+ yield ""
class SeparatorLine:
def __init__(self, timestamp):
time.localtime(self.timestamp))
# FIXME: colours
suffix = "[" + date + "]--"
- return "-" * (width - len(suffix)) + suffix
+ yield "-" * (width - 1 - len(suffix)) + suffix
class FromLine:
def __init__(self, account, nameline):
def render(self, width):
# FIXME: truncate
- return f"From: {self.nameline} ({self.account})"
+ yield f"From: {self.nameline} ({self.account})"
+
+class Paragraph:
+ def __init__(self):
+ self.words = []
+ self.unfinished_word = ''
+
+ def render(self, width):
+ # For the moment, greedy algorithm. We can worry about cleverness later
+ line, space = '', ''
+ for word in self.words:
+ if line != "" and wcwidth.wcswidth(line + space + word) >= width:
+ yield line
+ line, space = '', ''
+
+ line += space + word
+ space = ' '
+
+ if wcwidth.wcswidth(line) >= width:
+ # FIXME: wrap explicitly?
+ yield line
+ line, space = '', ''
+
+ if line != "":
+ yield line
+
+ def empty(self):
+ return len(self.words) == 0
+
+ def end_word(self):
+ if len(self.unfinished_word) > 0:
+ self.words.append(self.unfinished_word)
+ self.unfinished_word = ''
+
+ def add(self, text):
+ for c in text:
+ if c == ' ':
+ self.end_word()
+ else:
+ self.unfinished_word += c
+
+class HTMLParser(html.parser.HTMLParser):
+ def __init__(self):
+ super().__init__()
+ self.paras = [Paragraph()]
+
+ def handle_starttag(self, tag, attrs):
+ if tag in {"a", "span"}:
+ # FIXME: maybe handle some cases of this to spot hashtags,
+ # usernames etc?
+ return
+
+ if tag == "p":
+ if not self.paras[-1].empty():
+ self.paras.append(Paragraph())
+ self.paras.append(Paragraph())
+ return
+
+ if tag == "br":
+ self.paras.append(Paragraph())
+ return
+
+ print("UNKNOWN START", tag, attrs)
+
+ def handle_endtag(self, tag):
+ if tag in {"a", "span"}:
+ return
+
+ if tag == "p":
+ if not self.paras[-1].empty():
+ self.paras.append(Paragraph())
+ return
+
+ def handle_data(self, data):
+ self.paras[-1].add(data)
+
+ def done(self):
+ for para in self.paras:
+ para.end_word()
+ while len(self.paras) > 0 and self.paras[0].empty():
+ self.paras.pop(0)
+ while len(self.paras) > 0 and self.paras[-1].empty():
+ self.paras.pop()