This repository has been archived by the owner on May 12, 2018. It is now read-only.
forked from pygments/pygments.rb
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
354 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
pygments.formatters.gitlab | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
GitLab specific formatter for HTML output. | ||
Based on the standard HTML formatter. | ||
:copyright: Copyright 2012 by the GitLab team (http://www.gitlab.org). | ||
:license: BSD, see LICENSE for details. | ||
""" | ||
|
||
import os | ||
import sys | ||
import StringIO | ||
|
||
from pygments.formatter import Formatter | ||
from pygments.token import Token, Text, STANDARD_TYPES | ||
from pygments.util import get_bool_opt, get_int_opt | ||
|
||
|
||
__all__ = ['GitlabFormatter'] | ||
|
||
|
||
_escape_html_table = { | ||
ord('&'): u'&', | ||
ord('<'): u'<', | ||
ord('>'): u'>', | ||
ord('"'): u'"', | ||
ord("'"): u''', | ||
} | ||
|
||
def escape_html(text, table=_escape_html_table): | ||
"""Escape &, <, > as well as single and double quotes for HTML.""" | ||
return text.translate(table) | ||
|
||
|
||
def _get_ttype_class(ttype): | ||
fname = STANDARD_TYPES.get(ttype) | ||
if fname: | ||
return fname | ||
aname = '' | ||
while fname is None: | ||
aname = '-' + ttype[-1] + aname | ||
ttype = ttype.parent | ||
fname = STANDARD_TYPES.get(ttype) | ||
return fname + aname | ||
|
||
|
||
class GitlabFormatter(Formatter): | ||
r""" | ||
GitLab specific formatter for HTML output. | ||
Additional options accepted: | ||
`show_line_numbers` | ||
Determines whether the line number column should be shown (default: | ||
``True``). | ||
`first_line_number` | ||
The line number for the first line (default: ``1``). | ||
""" | ||
|
||
name = 'GitLab' | ||
aliases = ['gitlab'] | ||
filenames = [] | ||
|
||
def __init__(self, **options): | ||
Formatter.__init__(self, **options) | ||
self.show_line_numbers = get_bool_opt(options, 'show_line_numbers', True) | ||
self.first_line_number = abs(get_int_opt(options, 'first_line_number', 1)) | ||
|
||
def _wrap_table(self, inner): | ||
""" | ||
Wrap the whole thing into a table and add line numbers | ||
""" | ||
dummyoutfile = StringIO.StringIO() | ||
lncount = 0 | ||
for line in inner: | ||
lncount += 1 | ||
dummyoutfile.write(line) | ||
|
||
sln = self.show_line_numbers | ||
if sln: | ||
fl = self.first_line_number | ||
mw = len(str(lncount + fl - 1)) | ||
|
||
lines = [] | ||
for i in range(fl, fl+lncount): | ||
lines.append('<a id="L%d" href="#L%d" rel="#L%d">' % (i, i, i) + | ||
'<i class="icon-link"></i> %*d' % (mw, i) + | ||
'</a>') | ||
ls = '\n'.join(lines) | ||
|
||
yield '<table class="lines"><tr>' | ||
if sln: | ||
yield '<td><pre class="line_numbers">' + ls + '</pre></td>' | ||
yield '<td><div class="highlight"><pre>' | ||
yield dummyoutfile.getvalue() | ||
yield '</pre></div></td></tr></table>' | ||
|
||
def _wrap_code_lines(self, inner): | ||
""" | ||
Wrap each line in a <div class="line"> | ||
""" | ||
# subtract 1 since we have to increment i *before* yielding | ||
i = self.first_line_number - 1 | ||
|
||
for line in inner: | ||
i += 1 | ||
yield '<div id="LC%d" class="line">%s</div>' % (i, line) | ||
|
||
def _format_code_lines(self, tokensource): | ||
""" | ||
Just format the tokens, without any wrapping tags. | ||
Yield individual lines. | ||
""" | ||
# for <span style=""> lookup only | ||
escape_table = _escape_html_table | ||
|
||
lspan = '' | ||
line = '' | ||
for ttype, value in tokensource: | ||
cls = _get_ttype_class(ttype) | ||
cspan = cls and '<span class="%s">' % cls or '' | ||
|
||
parts = escape_html(value).split('\n') | ||
|
||
# for all but the last line | ||
for part in parts[:-1]: | ||
if line: | ||
if lspan != cspan: | ||
line += (lspan and '</span>') + cspan + part + \ | ||
(cspan and '</span>') | ||
else: # both are the same | ||
line += part + (lspan and '</span>') | ||
yield line | ||
line = '' | ||
elif part: | ||
yield cspan + part + (cspan and '</span>') | ||
else: | ||
yield '<br/>' | ||
# for the last line | ||
if line and parts[-1]: | ||
if lspan != cspan: | ||
line += (lspan and '</span>') + cspan + parts[-1] | ||
lspan = cspan | ||
else: | ||
line += parts[-1] | ||
elif parts[-1]: | ||
line = cspan + parts[-1] | ||
lspan = cspan | ||
# else we neither have to open a new span nor set lspan | ||
|
||
if line: | ||
yield line + (lspan and '</span>') | ||
|
||
def format_unencoded(self, tokensource, outfile): | ||
""" | ||
The formatting process uses several nested generators; which of | ||
them are used is determined by the user's options. | ||
Each generator should take at least one argument, ``inner``, | ||
and wrap the pieces of text generated by this. | ||
""" | ||
source = self._format_code_lines(tokensource) | ||
source = self._wrap_code_lines(source) | ||
source = self._wrap_table(source) | ||
|
||
for piece in source: | ||
outfile.write(piece) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
pygments.formatters.gitlab | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
GitLab specific formatter for HTML output. | ||
Based on the standard HTML formatter. | ||
:copyright: Copyright 2012 by the GitLab team (http://www.gitlab.org). | ||
:license: BSD, see LICENSE for details. | ||
""" | ||
|
||
import os | ||
import sys | ||
import StringIO | ||
|
||
from pygments.formatter import Formatter | ||
from pygments.token import Token, Text, STANDARD_TYPES | ||
from pygments.util import get_bool_opt, get_int_opt | ||
|
||
|
||
__all__ = ['GitlabFormatter'] | ||
|
||
|
||
_escape_html_table = { | ||
ord('&'): u'&', | ||
ord('<'): u'<', | ||
ord('>'): u'>', | ||
ord('"'): u'"', | ||
ord("'"): u''', | ||
} | ||
|
||
def escape_html(text, table=_escape_html_table): | ||
"""Escape &, <, > as well as single and double quotes for HTML.""" | ||
return text.translate(table) | ||
|
||
|
||
def _get_ttype_class(ttype): | ||
fname = STANDARD_TYPES.get(ttype) | ||
if fname: | ||
return fname | ||
aname = '' | ||
while fname is None: | ||
aname = '-' + ttype[-1] + aname | ||
ttype = ttype.parent | ||
fname = STANDARD_TYPES.get(ttype) | ||
return fname + aname | ||
|
||
|
||
class GitlabFormatter(Formatter): | ||
r""" | ||
GitLab specific formatter for HTML output. | ||
Additional options accepted: | ||
`show_line_numbers` | ||
Determines whether the line number column should be shown (default: | ||
``True``). | ||
`first_line_number` | ||
The line number for the first line (default: ``1``). | ||
""" | ||
|
||
name = 'GitLab' | ||
aliases = ['gitlab'] | ||
filenames = [] | ||
|
||
def __init__(self, **options): | ||
Formatter.__init__(self, **options) | ||
self.show_line_numbers = get_bool_opt(options, 'show_line_numbers', True) | ||
self.first_line_number = abs(get_int_opt(options, 'first_line_number', 1)) | ||
|
||
def _wrap_table(self, inner): | ||
""" | ||
Wrap the whole thing into a table and add line numbers | ||
""" | ||
dummyoutfile = StringIO.StringIO() | ||
lncount = 0 | ||
for line in inner: | ||
lncount += 1 | ||
dummyoutfile.write(line) | ||
|
||
sln = self.show_line_numbers | ||
if sln: | ||
fl = self.first_line_number | ||
mw = len(str(lncount + fl - 1)) | ||
|
||
lines = [] | ||
for i in range(fl, fl+lncount): | ||
lines.append('<a id="L%d" href="#L%d" rel="#L%d">' % (i, i, i) + | ||
'<i class="icon-link"></i> %*d' % (mw, i) + | ||
'</a>') | ||
ls = '\n'.join(lines) | ||
|
||
yield '<table class="lines"><tr>' | ||
if sln: | ||
yield '<td><pre class="line_numbers">' + ls + '</pre></td>' | ||
yield '<td><div class="highlight"><pre>' | ||
yield dummyoutfile.getvalue() | ||
yield '</pre></div></td></tr></table>' | ||
|
||
def _wrap_code_lines(self, inner): | ||
""" | ||
Wrap each line in a <div class="line"> | ||
""" | ||
# subtract 1 since we have to increment i *before* yielding | ||
i = self.first_line_number - 1 | ||
|
||
for line in inner: | ||
i += 1 | ||
yield '<div id="LC%d" class="line">%s</div>' % (i, line) | ||
|
||
def _format_code_lines(self, tokensource): | ||
""" | ||
Just format the tokens, without any wrapping tags. | ||
Yield individual lines. | ||
""" | ||
# for <span style=""> lookup only | ||
escape_table = _escape_html_table | ||
|
||
lspan = '' | ||
line = '' | ||
for ttype, value in tokensource: | ||
cls = _get_ttype_class(ttype) | ||
cspan = cls and '<span class="%s">' % cls or '' | ||
|
||
parts = escape_html(value).split('\n') | ||
|
||
# for all but the last line | ||
for part in parts[:-1]: | ||
if line: | ||
if lspan != cspan: | ||
line += (lspan and '</span>') + cspan + part + \ | ||
(cspan and '</span>') | ||
else: # both are the same | ||
line += part + (lspan and '</span>') | ||
yield line | ||
line = '' | ||
elif part: | ||
yield cspan + part + (cspan and '</span>') | ||
else: | ||
yield '<br/>' | ||
# for the last line | ||
if line and parts[-1]: | ||
if lspan != cspan: | ||
line += (lspan and '</span>') + cspan + parts[-1] | ||
lspan = cspan | ||
else: | ||
line += parts[-1] | ||
elif parts[-1]: | ||
line = cspan + parts[-1] | ||
lspan = cspan | ||
# else we neither have to open a new span nor set lspan | ||
|
||
if line: | ||
yield line + (lspan and '</span>') | ||
|
||
def format_unencoded(self, tokensource, outfile): | ||
""" | ||
The formatting process uses several nested generators; which of | ||
them are used is determined by the user's options. | ||
Each generator should take at least one argument, ``inner``, | ||
and wrap the pieces of text generated by this. | ||
""" | ||
source = self._format_code_lines(tokensource) | ||
source = self._wrap_code_lines(source) | ||
source = self._wrap_table(source) | ||
|
||
for piece in source: | ||
outfile.write(piece) |
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a glance this seems to be the only change from upstream (except lagging behind). Is it so?
Why not just make a pull request for this and remove the fork?
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, the reference in the file headers to a BSD LICENSE file is wrong. No such file exists.
Why would you want to change license in your fork from the MIT/Expat license to BSD?
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avtobiff There are basically two deviations in this fork. The use of
python2
for calling Python (see gitlabhq/gitlabhq#2214) and the custom GitLab formatter (see #1).d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@riyad
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avtobiff what's so special with pygments upstream?
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@riyad
Well, generally a proliferation of a codebase should be avoided.
The Debian Ruby team is working with packaging GitLab and it's
dependencies. We don't want to package all custom forks of
different gems. This is why I suggest to pull request this change
to pygment.rb upstream.
Furthermore, Debian takes licensing seriously. It is a tad unclear
what the license of these additions are. (Code says BSD License
but references a file with the MIT License.)
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you point please? As I see all custom lexers have BSD LIcense but Pygments.rb itself has MIT
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pygments#74 seems to have made it upstream so we can drop the
python2
hack. This only leaves the custom formatter.d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avtobiff @randx please support pygments#77 😄
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, I did not realize that
vendor/pygments-main/
is actually a copy of upstream pygments itself.So the changes should be pushed there and not to pygments.rb. (We rip pygments-main out in the
Debian package and use python-pygments.)
I only checked the pygments.rb root for the LICENSE file.
Do you want to push this to pygments bitbucket? Otherwise I volunteer!
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet!
d946a60
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@avtobiff go ahead 😄