cgit

commit dbaee2672be14374acb17266477c19294c6155f3

Author: Jeff Smith <whydoubt@gmail.com>

ui-blame: Allow syntax highlighting

Place file contents into a single block so that syntax highlighting can
be applied in the usual fashion.  Place the alternating color bars
behind the file contents.  Force the default syntax highlighting
background to transparent.

Signed-off-by: Jeff Smith <whydoubt@gmail.com>
Reviewed-by: John Keeping <john@keeping.me.uk>

 cgit.css | 10 +++++
 filters/syntax-highlighting.py | 2 
 ui-blame.c | 63 +++++++++++++++++++++++++++++------


diff --git a/cgit.css b/cgit.css
index 20b7e869cca4c7087e36e3a010039566fc9a5286..217a05a557d7d806006946810efbdb47437d37bb 100644
--- a/cgit.css
+++ b/cgit.css
@@ -353,6 +353,16 @@ div#cgit table.blame div.alt:nth-child(odd) {
 	background: white;
 }
 
+div#cgit table.blame td.lines > div {
+	position: relative;
+}
+
+div#cgit table.blame td.lines > div > pre {
+	padding: 0 0 0 0.5em;
+	position: absolute;
+	top: 0;
+}
+
 div#cgit table.bin-blob {
 	margin-top: 0.5em;
 	border: solid 1px black;




diff --git a/filters/syntax-highlighting.py b/filters/syntax-highlighting.py
index 5888b507863f020dddf7f5f7606c6bfcb304869e..e912594c48a71fce1baffb11149ab9b72cc223d4 100755
--- a/filters/syntax-highlighting.py
+++ b/filters/syntax-highlighting.py
@@ -34,7 +34,7 @@ sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors='replace')
 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
 data = sys.stdin.read()
 filename = sys.argv[1]
-formatter = HtmlFormatter(style='pastie')
+formatter = HtmlFormatter(style='pastie', nobackground=True)
 
 try:
 	lexer = guess_lexer_for_filename(filename, data)




diff --git a/ui-blame.c b/ui-blame.c
index d565fffa697914391d3cdc9cad5b40291307db36..17e2d60dc6981d486cd8bde05a081eb80d74578c 100644
--- a/ui-blame.c
+++ b/ui-blame.c
@@ -67,15 +67,29 @@ 	while (lineno < ent->lno + ent->num_lines)
 		htmlf(numberfmt, ++lineno);
 }
 
-static void emit_blame_entry_line(struct blame_scoreboard *sb,
-				  struct blame_entry *ent)
+static void emit_blame_entry_line_background(struct blame_scoreboard *sb,
+					     struct blame_entry *ent)
 {
-	const char *cp, *cpend;
+	unsigned long line;
+	size_t len, maxlen = 2;
+	const char* pos, *endpos;
 
-	cp = blame_nth_line(sb, ent->lno);
-	cpend = blame_nth_line(sb, ent->lno + ent->num_lines);
+	for (line = ent->lno; line < ent->lno + ent->num_lines; line++) {
+		html("\n");
+		pos = blame_nth_line(sb, line);
+		endpos = blame_nth_line(sb, line + 1);
+		len = 0;
+		while (pos < endpos) {
+			len++;
+			if (*pos++ == '\t')
+				len = (len + 7) & ~7;
+		}
+		if (len > maxlen)
+			maxlen = len;
+	}
 
-	html_ntxt(cp, cpend - cp);
+	for (len = 0; len < maxlen - 1; len++)
+		html(" ");
 }
 
 struct walk_tree_context {
@@ -88,6 +102,7 @@ static void print_object(const unsigned char *sha1, const char *path,
 			 const char *basename, const char *rev)
 {
 	enum object_type type;
+	char *buf;
 	unsigned long size;
 	struct argv_array rev_argv = ARGV_ARRAY_INIT;
 	struct rev_info revs;
@@ -102,6 +117,13 @@ 				      sha1_to_hex(sha1));
 		return;
 	}
 
+	buf = read_sha1_file(sha1, &type, &size);
+	if (!buf) {
+		cgit_print_error_page(500, "Internal server error",
+			"Error reading object %s", sha1_to_hex(sha1));
+		return;
+	}
+
 	argv_array_push(&rev_argv, "blame");
 	argv_array_push(&rev_argv, rev);
 	init_revisions(&revs, NULL);
@@ -157,19 +179,36 @@ 		}
 		html("</td>\n");
 	}
 
-	/* Lines */
-	html("<td class='lines'>");
+	html("<td class='lines'><div>");
+
+	/* Colored bars behind lines */
+	html("<div>");
 	for (ent = sb.ent; ent; ) {
 		struct blame_entry *e = ent->next;
-		html("<div class='alt'><pre><code>");
-		emit_blame_entry_line(&sb, ent);
-		html("</code></pre></div>");
+		html("<div class='alt'><pre>");
+		emit_blame_entry_line_background(&sb, ent);
+		html("</pre></div>");
 		free(ent);
 		ent = e;
 	}
-	html("</td>\n");
+	html("</div>");
 
 	free((void *)sb.final_buf);
+
+	/* Lines */
+	html("<pre><code>");
+	if (ctx.repo->source_filter) {
+		char *filter_arg = xstrdup(basename);
+		cgit_open_filter(ctx.repo->source_filter, filter_arg);
+		html_raw(buf, size);
+		cgit_close_filter(ctx.repo->source_filter);
+		free(filter_arg);
+	} else {
+		html_txt(buf);
+	}
+	html("</code></pre>");
+
+	html("</div></td>\n");
 
 	html("</tr>\n</table>\n");