"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
op@omarpolo.com
Subject:
gotwebd: wip: side-by-side diffs
To:
gameoftrees@openbsd.org
Date:
Sun, 23 Feb 2025 18:53:59 +0100

Download raw body.

Thread
  • op@omarpolo.com:

    gotwebd: wip: side-by-side diffs

Hello,

This is an attempt at rendering diffs side-by-side in gotwebd.  I've
found that, sometimes, they're useful to read some kinds of diffs
(it's a matter of preference, some people seems to really like and want
them always.)

To keep it simple, I'm not using cookies or whatnot; in the diff page
there is now an extra link "Diff side by side" which will re-render the
diff in the different format.  I'm using an extra query parameter for
this.

Also, the side-by-side view won't work on text browsers.  The way to
maybe have them working on w3m would require a table, but i'm not sure
it's semantically the right thing to do, so w3m users will have to keep
reading unified diffs :)

What do you think?

P.S.: remember to install the new css file and clear the browse cache
      when testing this diff.

diff /home/op/w/got
path + /home/op/w/got
commit - d07b17ba19c434be14cc50b320ca154fa92a100f
blob - ea4cdedb51cb3f930bbc483b0f82bc9590a180b6
file + gotwebd/files/htdocs/gotwebd/gotweb.css
--- gotwebd/files/htdocs/gotwebd/gotweb.css
+++ gotwebd/files/htdocs/gotwebd/gotweb.css
@@ -41,6 +41,26 @@ pre {
 	margin: 0;
 }
 
+.diff.side-by-side {
+	margin: 1rem;
+}
+
+.diff.side-by-side p {
+	margin: 0;
+	display: flex;
+}
+
+.diff.side-by-side code {
+	flex: 1;
+	white-space: pre-wrap;
+}
+
+.diff.side-by-side code + code {
+	border-left-width: 1px;
+	border-left-color: LightSlateGray;
+	border-left-style: solid;
+}
+
 .diff_minus, .diff_submodule {
 	color: magenta;
 }
commit - d07b17ba19c434be14cc50b320ca154fa92a100f
blob - 1a1a8770b26108d09399eb43a781fa0e4d63c1b9
file + gotwebd/gotweb.c
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -63,6 +63,7 @@ static const struct querystring_keys querystring_keys[
 	{ "headref",		HEADREF },
 	{ "index_page",		INDEX_PAGE },
 	{ "path",		PATH },
+	{ "sidebyside",		SIDEBYSIDE },
 };
 
 static const struct action_keys action_keys[] = {
@@ -690,6 +691,9 @@ qa_found:
 				goto done;
 			}
 			break;
+		case SIDEBYSIDE:
+			qs->sidebyside = !strcmp(value, "true");
+			break;
 		}
 
 		/* entry found */
@@ -1079,6 +1083,12 @@ gotweb_render_url(struct request *c, struct gotweb_url
 		sep = "&";
 	}
 
+	if (url->sidebyside) {
+		if (tp_writef(c->tp, "%ssidebyside=true", sep) == -1)
+			return -1;
+		sep = "&";
+	}
+
 	return 0;
 }
 
commit - d07b17ba19c434be14cc50b320ca154fa92a100f
blob - f6a54900f231bcf8db79e76bbea47944ab3a713a
file + gotwebd/gotwebd.h
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -368,6 +368,7 @@ struct gotwebd {
 struct gotweb_url {
 	int		 action;
 	int		 index_page;
+	int		 sidebyside;
 	const char	*commit;
 	const char	*file;
 	const char	*folder;
@@ -383,6 +384,7 @@ struct querystring {
 	char		*headref;
 	int		 index_page;
 	char		*path;
+	int		 sidebyside;
 };
 
 struct querystring_keys {
@@ -403,6 +405,7 @@ enum querystring_elements {
 	HEADREF,
 	INDEX_PAGE,
 	PATH,
+	SIDEBYSIDE,
 };
 
 enum query_actions {
commit - d07b17ba19c434be14cc50b320ca154fa92a100f
blob - cd49228ec99471205e216489a687095f309e2ee8
file + gotwebd/pages.tmpl
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
@@ -939,6 +939,13 @@ nextsep(char *s, char **t)
 		.index_page = -1,
 		.path = qs->path,
 		.commit = rc->commit_id,
+	}, diff_sidebyside_url = {
+		.action = DIFF,
+		.index_page = -1,
+		.path = qs->path,
+		.commit = qs->commit,
+		.sidebyside = 1,
+		.headref = qs->headref,
 	};
 
 	memcpy(&patch_url, &tree_url, sizeof(patch_url));
@@ -973,15 +980,31 @@ nextsep(char *s, char **t)
         <a href="{{ render gotweb_render_url(c, &tree_url) }}">
           Tree
         </a>
+        {{" | "}}
+        <a href="{{ render gotweb_render_url(c, &diff_sidebyside_url) }}">
+          Diff side by side
+        </a>
       </dd>
     </dl>
   </div>
   <hr />
-  <pre id="diff">
-    {{ while (linelen = getline(&line, &linesize, fp)) != -1 }}
-      {{ render diff_line(tp, line) }}
-    {{ end }}
-  </pre>
+
+  {{ if qs->sidebyside }}
+    <section class="diff side-by-side">
+  {{ else }}
+    <pre id="diff">
+  {{ end }}
+
+  {{ while (linelen = getline(&line, &linesize, fp)) != -1 }}
+    {{ render diff_line(tp, line) }}
+  {{ end }}
+
+  {{ if qs->sidebyside }}
+    </section>
+  {{ else }}
+    </pre>
+  {{ end }}
+
 </div>
 {{ finally }}
 {! free(line); !}
@@ -989,6 +1012,8 @@ nextsep(char *s, char **t)
 
 {{ define diff_line(struct template *tp, char *line )}}
 {!
+	struct request		*c = tp->tp_arg;
+	struct querystring	*qs = c->t->qs;
 	const char		*color = NULL;
 	char			*nl;
 
@@ -1014,7 +1039,22 @@ nextsep(char *s, char **t)
 	if (nl)
 		*nl = '\0';
 !}
-<span class="diff_line {{ color }}">{{ line }}</span>{{"\n"}}
+  {{ if qs->sidebyside }}
+    <p class="diff_line {{ color }}">
+      {{ if *line == '+' && strncmp(line, "+++ ", 4) /* XXX */ }}
+        <code class="diff_empty"></code><code>{{ line }}</code>
+      {{ else if *line == '-' && strncmp(line, "--- ", 4) /* XXX */ }}
+        <code>{{ line }}</code><code class="diff_empty"></code>
+      {{ else if *line == ' ' }}
+        <code>{{ line }}</code><code>{{ line }}</code>
+      {{ else }}
+        <code>{{ line }}</code>
+      {{ end }}
+    </p>
+  {{ else }}
+    <span class="diff_line {{ color }}">{{ line }}</span>
+  {{ end }}
+  {{"\n"}}
 {{ end }}
 
 {{ define gotweb_render_branches(struct template *tp,