diff options
Diffstat (limited to 'web/todolist')
-rw-r--r-- | web/todolist/default.nix | 116 | ||||
-rw-r--r-- | web/todolist/extract-todos.jq | 30 |
2 files changed, 146 insertions, 0 deletions
diff --git a/web/todolist/default.nix b/web/todolist/default.nix new file mode 100644 index 000000000000..c37a65555956 --- /dev/null +++ b/web/todolist/default.nix @@ -0,0 +1,116 @@ +# Generates a simple web view of open TODOs in the depot. +# +# Only TODOs that match the form 'TODO($username)' are considered, and +# only for users that are known to us. +{ depot, lib, pkgs, ... }: + +let + inherit (pkgs) + jq + ripgrep + runCommandNoCC + writeTextFile + ; + + inherit (builtins) + elem + filter + fromJSON + head + readFile + map + ; + + inherit (lib) concatStringsSep; + + inherit (depot.nix.yants) + defun + int + string + struct + ; + + knownUsers = map (u: u.username) depot.ops.users; + + todo = struct { + file = string; + line = int; + todo = string; + user = string; + }; + + allTodos = fromJSON (readFile (runCommandNoCC "depot-todos.json" { } '' + ${ripgrep}/bin/rg --json 'TODO\(\w+\):.*$' ${depot.path} | \ + ${jq}/bin/jq -s -f ${./extract-todos.jq} > $out + '')); + + knownUserTodos = filter (todos: elem (head todos).user knownUsers) allTodos; + + fileLink = defun [ todo string ] (t: + ''<a style="color: inherit;" + href="https://cs.tvl.fyi/depot/-/blob/${t.file}#L${toString t.line}"> + //${t.file}:${toString t.line}</a>''); + + todoElement = defun [ todo string ] (t: '' + <p>${fileLink t}:</p> + <blockquote>${t.todo}</blockquote> + + ''); + + userParagraph = todos: + let user = (head todos).user; + in '' + <p> + <h3> + <a style="color:inherit; text-decoration: none;" + name="${user}" + href="#${user}">${user}</a> + </h3> + ${concatStringsSep "\n" (map todoElement todos)} + </p> + <hr> + ''; + + staticUrl = "https://static.tvl.fyi/${depot.web.static.drvHash}"; + +in +writeTextFile { + name = "tvl-todos"; + destination = "/index.html"; + text = '' + <!DOCTYPE html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content="TVL's todo-list"> + <link rel="stylesheet" type="text/css" media="all" href="${staticUrl}/tvl.css"> + <link rel="icon" type="image/webp" href="${staticUrl}/favicon.webp"> + <title>TVL's todo-list</title> + <style> + svg { + max-width: inherit; + height: auto; + } + </style> + </head> + <body class="dark"> + <header> + <h1><a class="blog-title" href="/">The Virus Lounge's todo-list</a> </h1> + <hr> + </header> + <main> + ${concatStringsSep "\n" (map userParagraph knownUserTodos)} + </main> + <footer> + <p class="footer"> + <a class="uncoloured-link" href="https://tvl.fyi">homepage</a> + | + <a class="uncoloured-link" href="https://cs.tvl.fyi/depot/-/blob/README.md">code</a> + | + <a class="uncoloured-link" href="https://cl.tvl.fyi">reviews</a> + </p> + <p class="lod">ಠ_ಠ</p> + </footer> + </body> + ''; +} diff --git a/web/todolist/extract-todos.jq b/web/todolist/extract-todos.jq new file mode 100644 index 000000000000..d4e0476c403a --- /dev/null +++ b/web/todolist/extract-todos.jq @@ -0,0 +1,30 @@ +# Simple jq script to extract all TODO comments in the code base from +# ripgrep's JSON output. +# +# This assumes that the filter used is something like 'TODO\(\w+\):' + +# Capture the username and todo entry from an input string. +def capture_todo: + capture("TODO\\((?<user>\\w+)\\):\\s+(?<todo>.*)$"); + +# Construct a structure with only the fields we need to populate the +# page. +def simplify_match: + .data as $data + | (.data.submatches[0].match.text | capture_todo) as $capture + | { + file: ($data | .path.text | sub("/nix/store/.+-depot/"; "")), + line: ($data | .line_number), + todo: ($capture | .todo), + user: ($capture | .user), + }; + +# Group all matches first by the user and return them in sorted order +# by the file in which they appear. This matches the presentation +# order on the website. +def group_by_user: . + | group_by(.user) + | map(sort_by(.file)); + +# main: +map(select(.type == "match") | simplify_match) | group_by_user |