91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
|
import re
|
||
|
|
||
|
from docutils import nodes, utils
|
||
|
from docutils.parsers.rst import Directive, directives, roles
|
||
|
|
||
|
from pygments import highlight
|
||
|
from pygments.formatters import HtmlFormatter
|
||
|
from pygments.lexers import TextLexer, get_lexer_by_name
|
||
|
|
||
|
import pelican.settings as pys
|
||
|
|
||
|
|
||
|
class Pygments(Directive):
|
||
|
""" Source code syntax highlighting.
|
||
|
"""
|
||
|
required_arguments = 1
|
||
|
optional_arguments = 0
|
||
|
final_argument_whitespace = True
|
||
|
option_spec = {
|
||
|
'anchorlinenos': directives.flag,
|
||
|
'classprefix': directives.unchanged,
|
||
|
'hl_lines': directives.unchanged,
|
||
|
'lineanchors': directives.unchanged,
|
||
|
'linenos': directives.unchanged,
|
||
|
'linenospecial': directives.nonnegative_int,
|
||
|
'linenostart': directives.nonnegative_int,
|
||
|
'linenostep': directives.nonnegative_int,
|
||
|
'lineseparator': directives.unchanged,
|
||
|
'linespans': directives.unchanged,
|
||
|
'nobackground': directives.flag,
|
||
|
'nowrap': directives.flag,
|
||
|
'tagsfile': directives.unchanged,
|
||
|
'tagurlformat': directives.unchanged,
|
||
|
}
|
||
|
has_content = True
|
||
|
|
||
|
def run(self):
|
||
|
self.assert_has_content()
|
||
|
try:
|
||
|
lexer = get_lexer_by_name(self.arguments[0])
|
||
|
except ValueError:
|
||
|
# no lexer found - use the text one instead of an exception
|
||
|
lexer = TextLexer()
|
||
|
|
||
|
# Fetch the defaults
|
||
|
if pys.PYGMENTS_RST_OPTIONS is not None:
|
||
|
for k, v in pys.PYGMENTS_RST_OPTIONS.items():
|
||
|
# Locally set options overrides the defaults
|
||
|
if k not in self.options:
|
||
|
self.options[k] = v
|
||
|
|
||
|
if ('linenos' in self.options and
|
||
|
self.options['linenos'] not in ('table', 'inline')):
|
||
|
if self.options['linenos'] == 'none':
|
||
|
self.options.pop('linenos')
|
||
|
else:
|
||
|
self.options['linenos'] = 'table'
|
||
|
|
||
|
for flag in ('nowrap', 'nobackground', 'anchorlinenos'):
|
||
|
if flag in self.options:
|
||
|
self.options[flag] = True
|
||
|
|
||
|
# noclasses should already default to False, but just in case...
|
||
|
formatter = HtmlFormatter(noclasses=False, **self.options)
|
||
|
parsed = highlight('\n'.join(self.content), lexer, formatter)
|
||
|
return [nodes.raw('', parsed, format='html')]
|
||
|
|
||
|
|
||
|
directives.register_directive('code-block', Pygments)
|
||
|
directives.register_directive('sourcecode', Pygments)
|
||
|
|
||
|
|
||
|
_abbr_re = re.compile(r'\((.*)\)$', re.DOTALL)
|
||
|
|
||
|
|
||
|
class abbreviation(nodes.Inline, nodes.TextElement):
|
||
|
pass
|
||
|
|
||
|
|
||
|
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||
|
text = utils.unescape(text)
|
||
|
m = _abbr_re.search(text)
|
||
|
if m is None:
|
||
|
return [abbreviation(text, text)], []
|
||
|
abbr = text[:m.start()].strip()
|
||
|
expl = m.group(1)
|
||
|
return [abbreviation(abbr, abbr, explanation=expl)], []
|
||
|
|
||
|
|
||
|
roles.register_local_role('abbr', abbr_role)
|