2021-03-28 18:57:23 +02:00
|
|
|
"""Rendering Gemtext in curses."""
|
2021-03-11 19:16:15 +01:00
|
|
|
|
2021-02-12 19:01:42 +01:00
|
|
|
import curses
|
|
|
|
|
2021-05-29 23:59:50 +02:00
|
|
|
from bebop.colors import A_ITALIC, ColorPair
|
2021-03-28 18:57:23 +02:00
|
|
|
from bebop.metalines import LineType
|
2021-02-12 19:01:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
def render_lines(metalines, window, max_width):
|
|
|
|
"""Write a list of metalines in window.
|
|
|
|
|
|
|
|
As this function does not know about the window/pad previous size, it
|
|
|
|
expects a cleared window, especially if the new content is shorter than the
|
|
|
|
previous one: merely clearing after the resize will not remove artefacts.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
- metalines: list of metalines to render, must have at least one element.
|
2021-05-08 22:41:42 +02:00
|
|
|
- window: window that will be resized and filled with rendered lines.
|
2021-02-12 19:01:42 +01:00
|
|
|
- max_width: line length limit for the pad.
|
|
|
|
|
2021-04-17 22:59:54 +02:00
|
|
|
Returns:
|
2021-06-04 02:25:15 +02:00
|
|
|
The tuple of integers (height, width), the new dimensions of the resized
|
|
|
|
window.
|
2021-02-12 19:01:42 +01:00
|
|
|
"""
|
|
|
|
num_lines = len(metalines)
|
2021-05-07 21:54:09 +02:00
|
|
|
new_dimensions = max(num_lines, 1), max_width
|
2021-03-05 19:28:56 +01:00
|
|
|
window.resize(*new_dimensions)
|
2021-02-12 19:01:42 +01:00
|
|
|
for line_index, metaline in enumerate(metalines):
|
2021-03-05 19:28:56 +01:00
|
|
|
try:
|
2021-03-08 22:30:39 +01:00
|
|
|
render_line(metaline, window, max_width)
|
2021-03-05 19:28:56 +01:00
|
|
|
except ValueError:
|
|
|
|
return new_dimensions
|
2021-02-12 19:01:42 +01:00
|
|
|
if line_index < num_lines - 1:
|
|
|
|
window.addstr("\n")
|
2021-03-05 19:28:56 +01:00
|
|
|
return new_dimensions
|
2021-03-08 22:30:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
def render_line(metaline, window, max_width):
|
|
|
|
"""Write a single line to the window."""
|
|
|
|
meta, line = metaline
|
|
|
|
line_type = meta["type"]
|
|
|
|
attributes = get_base_line_attributes(line_type)
|
|
|
|
line = line[:max_width - 1]
|
|
|
|
window.addstr(line, attributes)
|
|
|
|
if meta["type"] == LineType.LINK and "url" in meta:
|
2021-03-08 23:42:18 +01:00
|
|
|
url_text = f' {meta["url"]}'
|
2021-03-08 22:30:39 +01:00
|
|
|
attributes = (
|
|
|
|
curses.color_pair(ColorPair.LINK_PREVIEW)
|
|
|
|
| curses.A_DIM
|
2021-05-29 23:59:50 +02:00
|
|
|
| A_ITALIC
|
2021-03-08 22:30:39 +01:00
|
|
|
)
|
|
|
|
window.addstr(url_text, attributes)
|
|
|
|
|
|
|
|
|
2021-04-17 22:59:54 +02:00
|
|
|
def get_base_line_attributes(line_type) -> int:
|
2021-03-08 22:30:39 +01:00
|
|
|
"""Return the base attributes for this line type.
|
|
|
|
|
|
|
|
Other attributes may be freely used later for this line type but this is
|
|
|
|
what is used at the start of most lines of the given type.
|
|
|
|
"""
|
|
|
|
if line_type == LineType.TITLE_1:
|
|
|
|
return curses.color_pair(ColorPair.TITLE_1) | curses.A_BOLD
|
|
|
|
elif line_type == LineType.TITLE_2:
|
|
|
|
return curses.color_pair(ColorPair.TITLE_2) | curses.A_BOLD
|
|
|
|
elif line_type == LineType.TITLE_3:
|
|
|
|
return curses.color_pair(ColorPair.TITLE_3)
|
|
|
|
elif line_type == LineType.LINK:
|
|
|
|
return curses.color_pair(ColorPair.LINK)
|
|
|
|
elif line_type == LineType.PREFORMATTED:
|
|
|
|
return curses.color_pair(ColorPair.PREFORMATTED)
|
|
|
|
elif line_type == LineType.BLOCKQUOTE:
|
2021-05-29 23:59:50 +02:00
|
|
|
return curses.color_pair(ColorPair.BLOCKQUOTE) | A_ITALIC
|
2021-06-13 01:55:48 +02:00
|
|
|
elif line_type == LineType.ERROR:
|
|
|
|
return curses.color_pair(ColorPair.ERROR) | curses.A_BOLD
|
2021-03-08 22:30:39 +01:00
|
|
|
else: # includes LineType.PARAGRAPH
|
|
|
|
return curses.color_pair(ColorPair.NORMAL)
|