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.
This commit is contained in:
Denis Kasak 2018-11-12 19:25:30 +01:00 committed by Damir Jelić
parent 6203a84553
commit 96e8f5246b
3 changed files with 47 additions and 6 deletions

View file

@ -30,12 +30,12 @@ from typing import List
import webcolors import webcolors
from pygments import highlight from pygments import highlight
from pygments.formatter import Formatter, get_style_by_name 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 pygments.util import ClassNotFound
from . import globals as G from . import globals as G
from .globals import W from .globals import W
from .utils import string_strikethrough from .utils import string_strikethrough, string_color_and_reset
try: try:
from HTMLParser import HTMLParser from HTMLParser import HTMLParser
@ -302,7 +302,8 @@ class Formatted(object):
try: try:
lexer = get_lexer_by_name(value) lexer = get_lexer_by_name(value)
except ClassNotFound: except ClassNotFound:
lexer = guess_lexer(string) return string_color_and_reset(string,
G.CONFIG.color.untagged_code)
try: try:
style = get_style_by_name(G.CONFIG.look.pygments_style) 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)) return prefix + text.replace("\n", "\n{}".format(prefix))
for key, value in attributes.items(): for key, value in attributes.items():
# Don't use textwrap to quote the code if not value:
if attributes["code"] and key == "quote" and value:
continue 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) text = add_attribute(text, key, value)
# If we're quoted code add quotation marks now. # 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 = indent(
text, text,
"{}>{} ".format( "{}>{} ".format(
@ -382,6 +390,7 @@ DEFAULT_ATTRIBUTES = {
"italic": False, "italic": False,
"underline": False, "underline": False,
"strikethrough": False, "strikethrough": False,
"preformatted": False,
"quote": False, "quote": False,
"code": None, "code": None,
"fgcolor": None, "fgcolor": None,
@ -430,6 +439,8 @@ class MatrixHtmlParser(HTMLParser):
self._toggle_attribute("strikethrough") self._toggle_attribute("strikethrough")
elif tag == "blockquote": elif tag == "blockquote":
self._toggle_attribute("quote") self._toggle_attribute("quote")
elif tag == "pre":
self._toggle_attribute("preformatted")
elif tag == "code": elif tag == "code":
lang = None lang = None
@ -480,6 +491,8 @@ class MatrixHtmlParser(HTMLParser):
self._toggle_attribute("underline") self._toggle_attribute("underline")
elif tag == "del": elif tag == "del":
self._toggle_attribute("strikethrough") self._toggle_attribute("strikethrough")
elif tag == "pre":
self._toggle_attribute("preformatted")
elif tag == "code": elif tag == "code":
if self.text: if self.text:
self.add_substring(self.text, self.attributes.copy()) self.add_substring(self.text, self.attributes.copy())

View file

@ -671,6 +671,16 @@ class MatrixConfig(WeechatConfig):
("Color for messages that are printed out but the server " ("Color for messages that are printed out but the server "
"hasn't confirmed the that he received them."), "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 = [ sections = [

View file

@ -105,3 +105,21 @@ def shorten_sender(sender):
def string_strikethrough(string): def string_strikethrough(string):
return "".join(["{}\u0336".format(c) for c in 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)