Added javac compiler message highlighting.

This commit is contained in:
mitsuhiko 2008-12-14 17:35:07 +01:00
parent eb1aef1b67
commit 80c7b57717
6 changed files with 135 additions and 23 deletions

View File

@ -15,7 +15,7 @@ from lodgeit.lib import antispam
from lodgeit.i18n import list_languages, _
from lodgeit.utils import render_to_response
from lodgeit.database import session, Paste
from lodgeit.lib.highlighting import LANGUAGES, STYLES, get_style
from lodgeit.lib.highlighting import list_languages, STYLES, get_style
from lodgeit.lib.pagination import generate_pagination
from lodgeit.lib.captcha import check_hashed_solution, Captcha
@ -71,7 +71,7 @@ class PasteController(object):
private = parent.private
return render_to_response('new_paste.html',
languages=LANGUAGES,
languages=list_languages(),
parent=parent,
code=code,
language=language,

View File

@ -22,15 +22,35 @@ _gcc_message_re = re.compile(r'''(?ux)
$
''')
_javac_message_re = re.compile(r'''(?ux)
^\s*
(?P<filename>[^:]*)
:(?P<line>\d*)
(:(?P<column>\d*))?
\s(?P<message>.*)
$
''')
_javac_prefix_re = re.compile(r'^\s*\[javac\]\s')
_javac_junk_re = re.compile(r'^((Note:\s+.*?)|(\d+)\s+errors\s*)$')
class Message(object):
class Raw(object):
is_raw = True
def __init__(self, raw):
self.raw = raw
class Message(Raw):
is_raw = False
def __init__(self, raw, filename, lineno, column, message):
self.raw = raw
Raw.__init__(self, raw)
self.filename = filename
self.lineno = lineno
self.column = column
self.message = message
self.context = ''
@property
def level(self):
@ -65,3 +85,46 @@ def parse_gcc_messages(data):
if match is not None:
result.append(make_message(line, **match.groupdict()))
return result
def parse_javac_messages(data):
"""Parse javac messages."""
result = []
linebuffer = []
def _remove_prefix(line):
match = _javac_prefix_re.match(line)
if match is not None:
line = line[match.end():]
return line
def _append_buffered_lines():
if not linebuffer:
return
if not result:
result.append(Raw('\n'.join(linebuffer)))
else:
last = result[-1]
last.raw = '\n'.join([last.raw] + linebuffer)
if not last.is_raw:
before = last.context and [last.context] or []
last.context = '\n'.join(before + linebuffer)
del linebuffer[:]
lineiter = iter(data.splitlines())
for line in lineiter:
line = _remove_prefix(line)
match = _javac_junk_re.match(line)
if match is not None:
_append_buffered_lines()
result.append(Raw(line))
continue
match = _javac_message_re.match(line)
if match is None:
linebuffer.append(line)
else:
_append_buffered_lines()
result.append(make_message(line, **match.groupdict()))
_append_buffered_lines()
return result

View File

@ -13,7 +13,7 @@ import pygments
import csv
from pygments.util import ClassNotFound
from pygments.lexers import get_lexer_by_name, get_lexer_for_filename, \
get_lexer_for_mimetype, PhpLexer
get_lexer_for_mimetype, PhpLexer, TextLexer
from pygments.styles import get_all_styles
from pygments.formatters import HtmlFormatter
@ -21,7 +21,8 @@ from lodgeit import local
from lodgeit.i18n import lazy_gettext as _
from lodgeit.utils import render_template
from lodgeit.lib.diff import prepare_udiff
from lodgeit.lib.compilerparser import parse_gcc_messages
from lodgeit.lib.compilerparser import parse_gcc_messages, \
parse_javac_messages
from werkzeug import escape
@ -55,6 +56,7 @@ LANGUAGES = {
'html+genshi': _('Genshi Templates'),
'js': _('JavaScript'),
'java': _('Java'),
'javac-messages': _('javac Messages'),
'jsp': _('JSP'),
'lua': _('Lua'),
'haskell': _('Haskell'),
@ -109,20 +111,26 @@ _escaped_marker = re.compile(r'^\\(?=###)(?m)')
def highlight(code, language, _preview=False):
"""Highlight a given code to HTML"""
if not _preview and language == 'diff':
return highlight_diff(code)
if language == 'creole':
return format_creole(code)
elif language == 'multi':
if not _preview:
if language == 'diff':
return highlight_diff(code)
elif language == 'creole':
return format_creole(code)
elif language == 'csv':
return format_csv(code)
elif language == 'gcc-messages':
return format_compiler_messages(parse_gcc_messages(code), 'gcc')
elif language == 'javac-messages':
return format_compiler_messages(parse_javac_messages(code), 'javac')
if language == 'multi':
return highlight_multifile(code)
elif language == 'csv':
return format_csv(code)
elif language == 'gcc-messages':
return format_compiler_messages(parse_gcc_messages(code))
elif language == 'php':
lexer = PhpLexer(startinline=True)
else:
lexer = get_lexer_by_name(language)
try:
lexer = get_lexer_by_name(language)
except ClassNotFound:
lexer = TextLexer()
style = get_style(name_only=True)
formatter = HtmlFormatter(linenos=True, cssclass='syntax', style=style)
return u'<div class="code">%s</div>' % \
@ -180,9 +188,10 @@ def format_csv(code):
return ''.join(result).decode('utf-8')
def format_compiler_messages(lines):
def format_compiler_messages(lines, compiler):
"""Highlights compiler messages."""
return render_template('utils/compiler-messages.html', lines=lines)
return render_template('utils/compiler-messages.html',
lines=lines, compiler=compiler)
def highlight_multifile(code):
@ -271,3 +280,10 @@ def get_known_alias(lexer, default='text'):
if alias in LANGUAGES:
return alias
return default
def list_languages():
"""List all languages."""
languages = LANGUAGES.items()
languages.sort(key=lambda x: x[1].lstrip(' _-.').lower())
return languages

View File

@ -586,6 +586,7 @@ div.compiler-messages table {
div.compiler-messages table td {
padding: 3px 7px;
vertical-align: top;
}
div.compiler-messages table td.level {
@ -597,8 +598,30 @@ div.compiler-messages table tr.error td.level {
}
div.compiler-messages table td.message {
line-height: 1.5;
}
div.compiler-messages table tr.raw pre {
font-family: 'Bitstream Vera Sans Mono', monospace;
font-size: 12px;
font-size: 12px!important;
padding: 0!important;
}
div.compiler-messages table td.message {
font-family: 'Bitstream Vera Sans Mono', monospace;
font-size: 12px!important;
}
div.compiler-messages table tr.context pre {
border: 1px solid #C8DADA;
background: #EDF6F7;
padding: 2px!important;
font-family: 'Bitstream Vera Sans Mono', monospace;
font-size: 12px!important;
}
div.compiler-javac table tr.context pre {
padding-top: 7px!important; /* to balance the closing "^" */
}
div.compiler-messages table td.location span.filename {

View File

@ -23,7 +23,7 @@
{%- endif %}
<textarea name="code" rows="10" cols="80">{{ code|e }}</textarea>
<select name="language">
{%- for key, caption in languages|dictsort(true, 'value') %}
{%- for key, caption in languages %}
<option value="{{ key }}"{% if language == key
%} selected="selected"{% endif %}>{{ caption|e }}</option>
{%- endfor %}

View File

@ -1,6 +1,9 @@
<div class="compiler-messages">
<div class="compiler-messages compiler-{{ compiler }}">
<table class="formatted">
{% for line in lines %}
{%- for line in lines %}
{%- if line.is_raw %}
<tr class="raw"><td colspan="3"><pre>{{ line.raw|e }}</pre></td></tr>
{%- else %}
<tr class="{{ line.level }}">
<td class="level">{{ line.level }}</td>
<td class="location">
@ -16,6 +19,13 @@
</td>
<td class="message">{{ line.message|e }}</td>
</tr>
{% endfor %}
{% if line.context %}
<tr class="context">
<td>&nbsp;</td>
<td colspan="2"><pre>{{ line.context|e }}</pre></td>
</tr>
{% endif %}
{%- endif %}
{%- endfor %}
</table>
</div>