summaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-03-27 14:27:19 -0300
committerGabriel Schneider <[email protected]>2026-03-27 15:16:44 -0300
commiteeb2d880626c72b1f94e6d84838d8a0342bb99c7 (patch)
tree510a7030fcbf29f49c6b313fe9602648de928e4f /build
parent5d935263f828f8be1037484f22f9181aa9f734c5 (diff)
download0x4200.cafe-eeb2d880626c72b1f94e6d84838d8a0342bb99c7.tar.gz
0x4200.cafe-eeb2d880626c72b1f94e6d84838d8a0342bb99c7.zip
Added jj metadata to page build, orchestrated with nushell and mise
Diffstat (limited to 'build')
-rw-r--r--build/jj-log.nu34
-rw-r--r--build/jj-log.tmpl1
-rw-r--r--build/jj-log.typ158
3 files changed, 193 insertions, 0 deletions
diff --git a/build/jj-log.nu b/build/jj-log.nu
new file mode 100644
index 0000000..7d2aa92
--- /dev/null
+++ b/build/jj-log.nu
@@ -0,0 +1,34 @@
+#!/usr/bin/env nu
+
+# Generate JSON from jj log and compile a Typst document
+# Usage: nu build/jj-log.nu [--revset '::@'] [--output build/jj-log.pdf]
+
+def main [
+ --revset (-r): string = "::@" # jj revset expression
+ --output (-o): string = "build/jj-log.pdf" # output PDF path
+ --json-only (-j) # only generate JSON, skip typst compile
+] {
+ let build_dir = ($env.FILE_PWD? | default ("build" | path expand))
+ let tmpl = (open ([$build_dir "jj-log.tmpl"] | path join))
+ let json_path = ($output | path parse | update extension "json" | path join)
+
+ let trees_json = "trees/_data/jj-log.json"
+ mkdir trees/_data
+
+ print $"generating log for revset: ($revset)"
+ let log_output = (jj log -r $revset --no-graph -T $tmpl)
+ $log_output | save -f $json_path
+ $log_output | save -f $trees_json
+
+ let n = (open --raw $json_path | lines | where $it != "" | length)
+ print $"wrote ($n) entries to ($json_path), ($trees_json)"
+
+ if not $json_only {
+ let typ_path = ([$build_dir "jj-log.typ"] | path join)
+ let json_abs = ($json_path | path expand)
+ let out_abs = ($output | path expand)
+ print $"compiling ($output)..."
+ typst compile $typ_path --root / --input $"data=($json_abs)" $out_abs
+ print $"done → ($output)"
+ }
+}
diff --git a/build/jj-log.tmpl b/build/jj-log.tmpl
new file mode 100644
index 0000000..2119648
--- /dev/null
+++ b/build/jj-log.tmpl
@@ -0,0 +1 @@
+"{\"commit\": " ++ json(self) ++ ", \"bookmarks\": " ++ json(local_bookmarks) ++ ", \"empty\": " ++ if(empty, "true", "false") ++ ", \"conflict\": " ++ if(conflict, "true", "false") ++ ", \"root\": " ++ if(root, "true", "false") ++ ", \"short_change\": \"" ++ change_id.shortest() ++ "\", \"short_commit\": \"" ++ commit_id.shortest() ++ "\"}\n"
diff --git a/build/jj-log.typ b/build/jj-log.typ
new file mode 100644
index 0000000..a1b36a9
--- /dev/null
+++ b/build/jj-log.typ
@@ -0,0 +1,158 @@
+// jj-log.typ — Typst document that renders jj log JSON output
+//
+// Usage:
+// jj log -r '::@' --no-graph \
+// -T '{"commit": ' ++ json(self) ++ ', "bookmarks": ' ++ json(local_bookmarks) ++ ', "empty": ' ++ if(empty, "true", "false") ++ ', "conflict": ' ++ if(conflict, "true", "false") ++ ', "root": ' ++ if(root, "true", "false") ++ '}\n' \
+// > log.json
+// typst compile jj-log.typ --input data=log.json
+
+#let data-path = sys.inputs.at("data", default: "log.json")
+#let raw-text = read(data-path)
+#let lines = raw-text.split("\n").filter(l => l.trim() != "")
+#let commits = lines.map(l => json(bytes(l)))
+
+// Filter out root commit
+#let commits = commits.filter(c => not c.root)
+
+// --- Helpers ---
+
+#let mono(body) = text(font: "DejaVu Sans Mono", size: 0.85em, body)
+#let short(hash) = hash.slice(0, 8)
+#let tag-pill(name, color: rgb("#4a6fa5")) = {
+ box(
+ fill: color.lighten(75%),
+ stroke: 0.5pt + color,
+ radius: 3pt,
+ inset: (x: 4pt, y: 2pt),
+ text(size: 0.8em, font: "DejaVu Sans Mono", fill: color, weight: "bold", name),
+ )
+}
+
+#let format-date(ts) = {
+ // timestamp is ISO 8601, e.g. "2026-03-27T14:22:35-03:00"
+ // extract date + time portion
+ let date-part = ts.slice(0, 10)
+ let time-part = ts.slice(11, 16)
+ date-part + " " + time-part
+}
+
+// Collect all bookmarks across commits
+#let all-bookmarks = commits.map(c => {
+ c.bookmarks.map(b => (name: b.name, commit: short(c.commit.commit_id), change: short(c.commit.change_id), desc: c.commit.description.trim()))
+}).flatten()
+
+// --- Page setup ---
+
+#set page(paper: "a4", margin: 2cm)
+#set text(font: "DejaVu Sans", size: 10pt)
+#set par(leading: 0.6em)
+
+// --- Title ---
+
+#align(center)[
+ #text(size: 18pt, weight: "bold")[jj ancestor log]
+ #v(0.3em)
+ #text(size: 9pt, fill: gray)[
+ #commits.len() commits #h(1em)
+ #all-bookmarks.len() bookmarks #h(1em)
+ newest → oldest
+ ]
+]
+
+#v(1em)
+
+// --- Bookmarks index ---
+
+#if all-bookmarks.len() > 0 [
+ == Bookmarks
+
+ #for bm in all-bookmarks [
+ - #tag-pill(bm.name) #h(0.5em) at #mono(bm.commit) — #emph(bm.desc)
+ ]
+
+ #v(1em)
+]
+
+// --- Commit log table ---
+
+== Commit History
+
+#table(
+ columns: (auto, auto, 1fr, auto),
+ align: (center, center, left, right),
+ stroke: 0.4pt + luma(200),
+ inset: 6pt,
+
+ // Header
+ table.header(
+ text(weight: "bold")[Change],
+ text(weight: "bold")[Commit],
+ text(weight: "bold")[Description],
+ text(weight: "bold")[Date],
+ ),
+
+ // Rows — newest to oldest (jj log default order with ::@)
+ ..commits.map(c => {
+ let bookmarks = c.bookmarks.map(b => tag-pill(b.name))
+ let is-empty = c.empty
+ let has-conflict = c.conflict
+ let desc = c.commit.description.trim()
+ if desc == "" { desc = "(no description)" }
+
+ let badges = {
+ if is-empty { tag-pill("empty", color: rgb("#999")) }
+ if has-conflict { tag-pill("conflict", color: rgb("#c44")) }
+ }
+
+ (
+ mono(short(c.commit.change_id)),
+ mono(short(c.commit.commit_id)),
+ [
+ #desc
+ #if bookmarks.len() > 0 { h(0.5em); bookmarks.join(h(0.3em)) }
+ #badges
+ ],
+ text(size: 0.85em, fill: luma(100), format-date(c.commit.author.timestamp)),
+ )
+ }).flatten(),
+)
+
+// --- Detailed list ---
+
+#v(1.5em)
+
+== Commit Details
+
+#for (i, c) in commits.enumerate() [
+ #let desc = c.commit.description.trim()
+ #if desc == "" { desc = "(no description)" }
+ #let bookmarks = c.bookmarks.map(b => tag-pill(b.name))
+
+ #block(
+ width: 100%,
+ inset: 8pt,
+ radius: 4pt,
+ stroke: 0.3pt + luma(200),
+ fill: if calc.even(i) { luma(252) } else { white },
+ )[
+ #grid(
+ columns: (auto, 1fr),
+ column-gutter: 1em,
+ row-gutter: 0.4em,
+ text(fill: luma(120), size: 0.85em)[change:], mono(short(c.commit.change_id)),
+ text(fill: luma(120), size: 0.85em)[commit:], mono(short(c.commit.commit_id)),
+ text(fill: luma(120), size: 0.85em)[author:], [#c.commit.author.name #text(fill: luma(120))[\<#c.commit.author.email\>]],
+ text(fill: luma(120), size: 0.85em)[date:], format-date(c.commit.author.timestamp),
+ ..if bookmarks.len() > 0 {(
+ text(fill: luma(120), size: 0.85em)[bookmarks:],
+ bookmarks.join(h(0.3em)),
+ )},
+ )
+ #v(0.3em)
+ #text(weight: "bold", size: 1.05em, desc)
+ #if c.empty [ #text(fill: luma(150), size: 0.85em)[\[empty\]] ]
+ #if c.conflict [ #text(fill: rgb("#c44"), size: 0.85em)[\[conflict\]] ]
+ ]
+
+ #v(0.5em)
+]