From a6cf2e15272a554474ee13a571fce58e5c6af4c9 Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Tue, 13 Nov 2018 10:28:44 +0100 Subject: [PATCH] Stylize code blocks as actual boxes with margins. --- matrix/colors.py | 60 +++++++++++++++++++++++++++++++++--------------- matrix/utils.py | 35 +++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/matrix/colors.py b/matrix/colors.py index a8a7376..218cfe2 100644 --- a/matrix/colors.py +++ b/matrix/colors.py @@ -37,7 +37,9 @@ from . import globals as G from .globals import W from .utils import (string_strikethrough, string_color_and_reset, - color_pair) + color_pair, + text_block, + colored_text_block) try: from HTMLParser import HTMLParser @@ -275,7 +277,7 @@ class Formatted(object): def to_weechat(self): # TODO BG COLOR - def add_attribute(string, name, value): + def add_attribute(string, name, value, attributes): if not value: return string elif name == "bold": @@ -303,23 +305,40 @@ class Formatted(object): W.string_remove_color(string.replace("\n", ""), "") ) elif name == "code": - try: - lexer = get_lexer_by_name(value) - except ClassNotFound: - return string_color_and_reset( - string, - color_pair(G.CONFIG.color.untagged_code_fg, - G.CONFIG.color.untagged_code_bg)) + code_color_pair = color_pair( + G.CONFIG.color.untagged_code_fg, + G.CONFIG.color.untagged_code_bg + ) - try: - style = get_style_by_name(G.CONFIG.look.pygments_style) - except ClassNotFound: - style = "native" + if attributes["preformatted"]: + # code block - # highlight adds a newline to the end of the string, remove it - # from the output - return highlight(string, lexer, - WeechatFormatter(style=style)).rstrip() + try: + lexer = get_lexer_by_name(value) + except ClassNotFound: + return colored_text_block( + string, + margin=2, + color_pair=code_color_pair) + + try: + style = get_style_by_name(G.CONFIG.look.pygments_style) + except ClassNotFound: + style = "native" + + code_block = text_block(string, margin=2) + + # highlight adds a newline to the end of the string, remove it + # from the output + highlighted_code = highlight( + code_block, + lexer, + WeechatFormatter(style=style) + ).rstrip() + + return highlighted_code + else: + return string_color_and_reset(string, code_color_pair) elif name == "fgcolor": return "{color_on}{text}{color_off}".format( color_on=W.color(value), @@ -344,7 +363,10 @@ class Formatted(object): # terminal, but doing it the other way around results in garbage. if "strikethrough" in attributes: text = add_attribute( - text, "strikethrough", attributes["strikethrough"] + text, + "strikethrough", + attributes["strikethrough"], + attributes ) attributes.pop("strikethrough") @@ -363,7 +385,7 @@ class Formatted(object): if key == "code" and not attributes["preformatted"]: text = text.strip().replace('\n', ' ') - text = add_attribute(text, key, value) + text = add_attribute(text, key, value, attributes) # If we're quoted code add quotation marks now. if key == "code" and attributes["quote"]: diff --git a/matrix/utils.py b/matrix/utils.py index d77b6f6..91d122d 100644 --- a/matrix/utils.py +++ b/matrix/utils.py @@ -14,7 +14,7 @@ # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import unicode_literals +from __future__ import unicode_literals, division import time from typing import Any, Dict, List @@ -132,3 +132,36 @@ def color_pair(color_fg, color_bg): return "{},{}".format(color_fg, color_bg) else: return color_fg + + +def text_block(text, margin=0): + """ + Pad block of text with whitespace to form a regular block, optionally + adding a margin. + """ + + # add vertical margin + vertical_margin = margin // 2 + text = "{}{}{}".format( + "\n" * vertical_margin, + text, + "\n" * vertical_margin + ) + + lines = text.split("\n") + longest_len = max(len(l) for l in lines) + margin + + # pad block and add horizontal margin + text = "\n".join( + "{pre}{line}{post}".format( + pre=" " * margin, + line=l, + post=" " * (longest_len - len(l))) + for l in lines) + + return text + + +def colored_text_block(text, margin=0, color_pair=""): + """ Like text_block, but also colors it.""" + return string_color_and_reset(text_block(text, margin=margin), color_pair)