diff --git a/app.py b/app.py
index d483772..2564732 100644
--- a/app.py
+++ b/app.py
def repo_blame_path(repo_name, path):
ref = request.args.get('ref', 'HEAD')
refs = get_refs(f"{repo_path}/{repo_name}")
- blame = get_blame(f"{repo_path}/{repo_name}", ref, path)
- return render_template("blame.html", repo_name=repo_name, ref=ref, path=path, blame=blame, refs=refs)
+ blame, style = get_blame(f"{repo_path}/{repo_name}", ref, path)
+ return render_template("blame.html", repo_name=repo_name, ref=ref, path=path, blame=blame, refs=refs, style=style)
@app.route("/<repo_name>/diff")
def repo_diff(repo_name):
diff --git a/git/blame.py b/git/blame.py
index 8ec663d..6d391de 100644
--- a/git/blame.py
+++ b/git/blame.py
import pygit2 as git
+from highlight import get_highlight_blame_style, highlight_line
# discourage using blame because its very expensive, especially on repos with long commits history
# retrieves blame information for a file at given ref and path
result.append({
'line_num': i + 1,
'content': line,
- 'blame': blame_lines[i]
+ 'blame': blame_lines[i],
+ # highlight every line individually
+ 'highlighted': highlight_line(line, file_path)
})
-
- return result
\ No newline at end of file
+
+ return result, get_highlight_blame_style()
\ No newline at end of file
diff --git a/highlight.py b/highlight.py
index 626c617..afd7796 100644
--- a/highlight.py
+++ b/highlight.py
# server-side syntax highlighting
-# https://git.kernel.org/pub/scm/infra/cgit.git/tree/filters/syntax-highlighting.py?id=dbaee2672be14374acb17266477c19294c6155f3
-
+# reference: https://git.kernel.org/pub/scm/infra/cgit.git/tree/filters/syntax-highlighting.py?id=dbaee2672be14374acb17266477c19294c6155f3
def highlight_code(data, filename):
formatter = HtmlFormatter(style='sas', nobackground=True, linenos=True)
try:
highlighted = highlight(data, lexer, formatter)
return f'<style>{css}</style>{highlighted}'
+def get_highlight_blame_style():
+ formatter = HtmlFormatter(style='sas', nobackground=True, cssclass='blame-code')
+ return formatter.get_style_defs('.blame-code')
+
+# highlight a single line (for blame)
+def highlight_line(line, filename):
+ formatter = HtmlFormatter(style='sas', nobackground=True, cssclass='blame-code')
+ try:
+ lexer = guess_lexer_for_filename(filename, line)
+ except ClassNotFound:
+ if line.startswith('#!'):
+ lexer = guess_lexer(line)
+ else:
+ lexer = TextLexer()
+ except TypeError:
+ lexer = TextLexer()
+ highlighted = highlight(line, lexer, formatter)
+ # remove the outer div and pre
+ # highlighted is <div class="blame-code"><pre>mirri</pre></div>
+ # extract inner
+ start = highlighted.find('<pre>') + 5 # length of <pre>, very hacky i know
+ end = highlighted.find('</pre>')
+ return highlighted[start:end]
+
# bare diff highlighting
def highlight_diff(data):
formatter = HtmlFormatter(style='sas', nobackground=True)
diff --git a/static/styles.css b/static/styles.css
index 19d285c..90526f3 100644
--- a/static/styles.css
+++ b/static/styles.css
}
.deletions {
- color: red;
+ color: red;
+}
+
+.blame-code {
+ background-color: #f9f9f9;
+ border: 1px solid lightgray;
+ overflow-x: auto;
}
diff --git a/templates/blame.html b/templates/blame.html
index 26cc641..ba4b8e7 100644
--- a/templates/blame.html
+++ b/templates/blame.html
{% extends "base.html" %}
{% block content %}
+<style>{{ style }}</style>
+<style>.blame-code pre { line-height: 0.7; }</style>
<h1>Blame: {{ path }}</h1>
{% if blame %}
-<table class="list"> <!-- temp default styling --->
- <thead>
- <tr>
- <th>Line</th>
- <th>Commit</th>
- <th>Author</th>
- <th>Date</th>
- <th>Content</th>
- </tr>
- </thead>
- <tbody>
- {% for line in blame %}
- <tr>
- <td>{{ line.line_num }}</td>
- {% if line.blame %}
- <td><a href="{{ url_for('commit_detail', repo_name=repo_name, commit_id=line.blame.commit_id) }}">{{ line.blame.commit_id[:8] }}</a></td>
- <td>{{ line.blame.author.name }}</td>
- <td>{{ line.blame.author.time | datetime }}</td>
- {% else %}
- <td></td>
- <td></td>
- <td></td>
- {% endif %}
- <td><pre>{{ line.content }}</pre></td>
- </tr>
- {% endfor %}
- </tbody>
-</table>
+<div class="blame-code"><pre>
+<!-- first 4 chars are for line number -->
+<!-- next part is for commit id (8 chars), then author (15 chars, cutoff if over), date/time -->
+<!-- this is just to keep the alignment -->
+{% for line in blame %}{{ "%4s" % line.line_num }} {% if line.blame %}<a href="{{ url_for('commit_detail', repo_name=repo_name, commit_id=line.blame.commit_id) }}">{{ line.blame.commit_id[:8] }}</a> {{ "%-15s" % line.blame.author.name[:15] }} {{ line.blame.author.time | datetime }}{% endif %} | {{ line.highlighted | safe }}
+{% endfor %}</pre></div>
{% else %}
<p>No blame info</p>
{% endif %}