From 96e8f5246bca926bf16f1b7eb5263bef377540f6 Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Mon, 12 Nov 2018 19:25:30 +0100 Subject: [PATCH] Improve handling of code blocks. * Don't try to guess the language of code blocks without a language specifier ("untagged" blocks). * Colour untagged and inline code blocks (and make the colour configurable). * Reflow inline code blocks. --- matrix/colors.py | 25 +++++++++++++++++++------ matrix/config.py | 10 ++++++++++ matrix/utils.py | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/matrix/colors.py b/matrix/colors.py index aa4a452..eff7697 100644 --- a/matrix/colors.py +++ b/matrix/colors.py @@ -30,12 +30,12 @@ from typing import List import webcolors from pygments import highlight from pygments.formatter import Formatter, get_style_by_name -from pygments.lexers import get_lexer_by_name, guess_lexer +from pygments.lexers import get_lexer_by_name from pygments.util import ClassNotFound from . import globals as G from .globals import W -from .utils import string_strikethrough +from .utils import string_strikethrough, string_color_and_reset try: from HTMLParser import HTMLParser @@ -302,7 +302,8 @@ class Formatted(object): try: lexer = get_lexer_by_name(value) except ClassNotFound: - lexer = guess_lexer(string) + return string_color_and_reset(string, + G.CONFIG.color.untagged_code) try: style = get_style_by_name(G.CONFIG.look.pygments_style) @@ -345,14 +346,21 @@ class Formatted(object): return prefix + text.replace("\n", "\n{}".format(prefix)) for key, value in attributes.items(): - # Don't use textwrap to quote the code - if attributes["code"] and key == "quote" and value: + if not value: continue + # Don't use textwrap to quote the code + if key == "quote" and attributes["code"]: + continue + + # Reflow inline code blocks + if key == "code" and not attributes["preformatted"]: + text = text.strip().replace('\n', ' ') + text = add_attribute(text, key, value) # If we're quoted code add quotation marks now. - if attributes["quote"] and key == "code" and value: + if key == "code" and attributes["quote"]: text = indent( text, "{}>{} ".format( @@ -382,6 +390,7 @@ DEFAULT_ATTRIBUTES = { "italic": False, "underline": False, "strikethrough": False, + "preformatted": False, "quote": False, "code": None, "fgcolor": None, @@ -430,6 +439,8 @@ class MatrixHtmlParser(HTMLParser): self._toggle_attribute("strikethrough") elif tag == "blockquote": self._toggle_attribute("quote") + elif tag == "pre": + self._toggle_attribute("preformatted") elif tag == "code": lang = None @@ -480,6 +491,8 @@ class MatrixHtmlParser(HTMLParser): self._toggle_attribute("underline") elif tag == "del": self._toggle_attribute("strikethrough") + elif tag == "pre": + self._toggle_attribute("preformatted") elif tag == "code": if self.text: self.add_substring(self.text, self.attributes.copy()) diff --git a/matrix/config.py b/matrix/config.py index 8914938..c8655f7 100644 --- a/matrix/config.py +++ b/matrix/config.py @@ -671,6 +671,16 @@ class MatrixConfig(WeechatConfig): ("Color for messages that are printed out but the server " "hasn't confirmed the that he received them."), ), + Option( + "untagged_code", + "color", + "", + 0, + 0, + "blue", + ("Color for code without a language specifier. Also used for " + "`inline code`."), + ), ] sections = [ diff --git a/matrix/utils.py b/matrix/utils.py index 060fd14..e711953 100644 --- a/matrix/utils.py +++ b/matrix/utils.py @@ -105,3 +105,21 @@ def shorten_sender(sender): def string_strikethrough(string): return "".join(["{}\u0336".format(c) for c in string]) + + +def string_color_and_reset(string, color): + """Color string with color, then reset all attributes.""" + + lines = string.split('\n') + lines = ("{}{}{}".format(W.color(color), line, W.color("reset")) + for line in lines) + return "\n".join(lines) + + +def string_color(string, color): + """Color string with color, then reset the color attribute.""" + + lines = string.split('\n') + lines = ("{}{}{}".format(W.color(color), line, W.color("resetcolor")) + for line in lines) + return "\n".join(lines)