gemtext: handle list items
This commit is contained in:
parent
4cb8ac11d6
commit
15f56289b9
|
@ -34,6 +34,12 @@ class Blockquote:
|
||||||
RE = re.compile(r">\s*(.*)")
|
RE = re.compile(r">\s*(.*)")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ListItem:
|
||||||
|
text: str
|
||||||
|
RE = re.compile(r"\*\s(.*)")
|
||||||
|
|
||||||
|
|
||||||
def parse_gemtext(data):
|
def parse_gemtext(data):
|
||||||
"""Parse UTF-8 encoded Gemtext as a list of elements."""
|
"""Parse UTF-8 encoded Gemtext as a list of elements."""
|
||||||
text = data.decode(encoding="utf8", errors="ignore")
|
text = data.decode(encoding="utf8", errors="ignore")
|
||||||
|
@ -71,6 +77,12 @@ def parse_gemtext(data):
|
||||||
elements.append(Blockquote(text))
|
elements.append(Blockquote(text))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
match = ListItem.RE.match(line)
|
||||||
|
if match:
|
||||||
|
text = match.groups()[0]
|
||||||
|
elements.append(ListItem(text))
|
||||||
|
continue
|
||||||
|
|
||||||
if preformatted:
|
if preformatted:
|
||||||
preformatted.lines.append(line)
|
preformatted.lines.append(line)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -3,11 +3,13 @@ import string
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
|
|
||||||
from bebop.colors import ColorPair
|
from bebop.colors import ColorPair
|
||||||
from bebop.gemtext import Blockquote, Link, Paragraph, Preformatted, Title
|
from bebop.gemtext import (Blockquote, Link, ListItem, Paragraph, Preformatted,
|
||||||
|
Title)
|
||||||
|
|
||||||
|
|
||||||
SPLIT_CHARS = " \t-"
|
SPLIT_CHARS = " \t-"
|
||||||
JOIN_CHAR = "-"
|
JOIN_CHAR = "-"
|
||||||
|
LIST_ITEM_MARK = "• "
|
||||||
|
|
||||||
|
|
||||||
class LineType(IntEnum):
|
class LineType(IntEnum):
|
||||||
|
@ -24,6 +26,7 @@ class LineType(IntEnum):
|
||||||
LINK = 5
|
LINK = 5
|
||||||
PREFORMATTED = 6
|
PREFORMATTED = 6
|
||||||
BLOCKQUOTE = 7
|
BLOCKQUOTE = 7
|
||||||
|
LIST_ITEM = 8
|
||||||
|
|
||||||
|
|
||||||
def format_elements(elements, width):
|
def format_elements(elements, width):
|
||||||
|
@ -60,6 +63,8 @@ def format_elements(elements, width):
|
||||||
elif isinstance(element, Blockquote):
|
elif isinstance(element, Blockquote):
|
||||||
element_metalines = format_blockquote(element, context)
|
element_metalines = format_blockquote(element, context)
|
||||||
has_margins = True
|
has_margins = True
|
||||||
|
elif isinstance(element, ListItem):
|
||||||
|
element_metalines = format_list_item(element, context)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
# If current element requires margins and is not the first elements,
|
# If current element requires margins and is not the first elements,
|
||||||
|
@ -131,6 +136,15 @@ def format_blockquote(blockquote: Blockquote, context: dict):
|
||||||
return [({"type": LineType.BLOCKQUOTE}, line) for line in lines]
|
return [({"type": LineType.BLOCKQUOTE}, line) for line in lines]
|
||||||
|
|
||||||
|
|
||||||
|
def format_list_item(item: ListItem, context: dict):
|
||||||
|
"""Return metalines for this list item."""
|
||||||
|
indent = len(LIST_ITEM_MARK)
|
||||||
|
lines = wrap_words(item.text, context["width"], indent=indent)
|
||||||
|
first_line = LIST_ITEM_MARK + lines[0][indent:]
|
||||||
|
lines[0] = first_line
|
||||||
|
return [({"type": LineType.LIST_ITEM}, line) for line in lines]
|
||||||
|
|
||||||
|
|
||||||
def wrap_words(text, width, indent=0):
|
def wrap_words(text, width, indent=0):
|
||||||
"""Wrap a text in several lines according to the renderer's width."""
|
"""Wrap a text in several lines according to the renderer's width."""
|
||||||
lines = []
|
lines = []
|
||||||
|
|
Reference in a new issue