Diff between cf87bb3e294fc839418e8e6f68570a6ced214990 and 0a3c1255202c7657b8a39ce0232648d6289dca6d

Changed Files

File Additions Deletions Status
app.py +2 -2 modified
git/blame.py +6 -3 modified
highlight.py +25 -2 modified
static/styles.css +7 -1 modified
templates/blame.html +8 -28 modified

Full Patch

diff --git a/app.py b/app.py
index d483772..2564732 100644
--- a/app.py
+++ b/app.py
@@ -122,8 +122,8 @@ def repo_blob_path(repo_name, path):
 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
@@ -1,4 +1,5 @@
 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
@@ -61,7 +62,9 @@ def get_blame(repo_path, ref="HEAD", file_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
@@ -8,8 +8,7 @@ from pygments.formatters import HtmlFormatter
 
 # 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:
@@ -25,6 +24,30 @@ def highlight_code(data, filename):
     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
@@ -117,7 +117,13 @@ table.commits-table .message-col {
 }
 
 .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
@@ -1,36 +1,16 @@
 {% 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 %}