Commit a5a6604

HPCesia <me@hpcesia.com>
2026-05-19 05:19:53
feat: packages list generator script
NOTE: The script is generated by LLM agent
1 parent c5797a9
Changed files (3)
pkgs
helix-plugins
helix-file-watcher
scripts
pkgs/helix-plugins/helix-file-watcher/default.nix
@@ -28,6 +28,6 @@ buildHelixPlugin {
   meta = {
     description = "Helix file watcher plugin";
     homepage = "https://github.com/mattwparas/helix-file-watcher";
-    license = lib.licenses.unfree; # Unclear licensing status. Marked as unfree.
+    # license = lib.licenses.unfree; # Unclear licensing status. Marked as unfree.
   };
 }
scripts/gen-readme.sh
@@ -0,0 +1,173 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
+README="$REPO_DIR/README.md"
+TEMP_TABLE="/tmp/nur-packages-readme-table.md"
+SYSTEM="${NIX_SYSTEM:-x86_64-linux}"
+
+echo "==> Evaluating package metadata via nix..."
+
+json=$(nix eval --impure --expr "
+let
+  flake = builtins.getFlake (toString $REPO_DIR);
+  pkgs = flake.legacyPackages.\"${SYSTEM}\";
+
+  reserved = [
+    \"lib\" \"nixosModules\" \"overlays\"
+    \"homeModules\" \"darwinModules\" \"flakeModules\"
+    \"callPackage\" \"newScope\" \"overrideScope\" \"packages\"
+    \"override\" \"overrideDerivation\"
+  ];
+
+  resolveLic = lic:
+    let
+      go = l:
+        if l == null then { shortName = null; spdxId = null; url = null; }
+        else if builtins.isList l then go (builtins.head l)
+        else if builtins.isString l then { shortName = l; spdxId = null; url = null; }
+        else {
+          shortName = l.shortName or null;
+          spdxId = l.spdxId or null;
+          url = l.url or null;
+        };
+    in go lic;
+
+  getLic = meta:
+    resolveLic (meta.license or meta.licence or null);
+
+  isDer = x: builtins.isAttrs x && x ? type && x.type == \"derivation\";
+  isScope = x: builtins.isAttrs x && x ? callPackage && x ? newScope && !isDer x;
+
+  reservedSet = builtins.listToAttrs (builtins.map (n: { name = n; value = true; }) reserved);
+
+  collect = prefix: attrs:
+    let
+      names = builtins.filter (n: !(reservedSet.\${n} or false)) (builtins.attrNames attrs);
+    in
+      builtins.concatMap (name:
+        let
+          v = attrs.\${name};
+          fullPrefix = if prefix == \"\" then name else \"\${prefix}.\${name}\";
+          pkgInfo = {
+            path = fullPrefix;
+            pname = v.pname or v.name or \"\";
+            version = v.version or \"\";
+            homepage = v.meta.homepage or \"\";
+            description = v.meta.description or \"\";
+            license = getLic v.meta;
+          };
+        in
+          if isDer v then [ pkgInfo ]
+          else if isScope v then collect fullPrefix v
+          else []
+      ) names;
+in
+  collect \"\" pkgs
+" --json 2>/dev/null)
+
+echo "==> Found $(echo "$json" | jq length) derivations"
+
+echo "==> Generating markdown tables..."
+
+echo "$json" | jq -r '
+
+  def fmt_license:
+    if .spdxId then
+      if .url and (.url | length > 0) then "[\(.spdxId)](\(.url))"
+      else .spdxId end
+    elif .shortName then
+      if .shortName == "unfree" then "**Unfree**"
+      elif .url and (.url | length > 0) then "[\(.shortName)](\(.url))"
+      else .shortName end
+    else "Not specified"
+    end;
+
+  def fmt_name($pname; $homepage):
+    if ($pname | length > 0) and ($homepage | length > 0) then "[\($pname)](\($homepage))"
+    else $pname end;
+
+  def fmt_version:
+    if . and (. | length > 0) then "`\(.)`" else "-" end;
+
+  def fmt_row($item):
+    "| `\($item.path)` | \(fmt_name($item.pname; $item.homepage)) | \($item.version | fmt_version) | \($item.license | fmt_license) | \($item.description) |";
+
+  def mk_table($items):
+    "| Path | Name | Version | License | Description |",
+    "| --- | --- | --- | --- | --- |",
+    ($items[] | fmt_row(.)),
+    "";
+
+  # Group by first path segment
+  (reduce .[] as $item ({}; .[$item.path | split(".")[0]] += [$item])
+  | to_entries
+  | map(
+      .key as $group_key
+      | .value as $items
+      | ($items | length) as $count
+      | ($items | map(.description) | unique | length) as $desc_count
+      | if $count == 1 then
+          { section: "Common", items: $items }
+        elif $desc_count <= 1 then
+          {
+            section: "Common",
+            items: [{
+              path: $group_key,
+              pname: $group_key,
+              version: "-",
+              homepage: $items[0].homepage,
+              description: $items[0].description,
+              license: $items[0].license
+            }]
+          }
+        else
+          { section: $group_key, items: $items }
+        end
+      )
+  ) as $groups
+
+  # Combine all Common items
+  | ($groups | map(select(.section == "Common") | .items[]) ) as $common
+  | ($groups | map(select(.section != "Common"))) as $named
+
+  # Generate output
+  | (if ($common | length > 0) then
+       "### Common\n", mk_table($common)
+     else empty end),
+    ($named[] |
+       "### \(.section)\n", mk_table(.items))
+' > "$TEMP_TABLE"
+
+echo "==> Injecting table into README..."
+
+if grep -q '<!-- BEGIN_PACKAGE_TABLE -->' "$README" 2>/dev/null; then
+  awk -v tmp="$TEMP_TABLE" '
+    BEGIN          { printing = 1 }
+    /<!-- BEGIN_PACKAGE_TABLE -->/ {
+      print
+      while ((getline line < tmp) > 0) print line
+      close(tmp)
+      printing = 0
+      next
+    }
+    /<!-- END_PACKAGE_TABLE -->/ {
+      printing = 1
+      print
+      next
+    }
+    printing       { print }
+  ' "$README" > "${README}.tmp" && mv "${README}.tmp" "$README"
+else
+  {
+    head -n -0 "$README"
+    echo ""
+    echo "<!-- BEGIN_PACKAGE_TABLE -->"
+    cat "$TEMP_TABLE"
+    echo "<!-- END_PACKAGE_TABLE -->"
+  } > "${README}.tmp" && mv "${README}.tmp" "$README"
+fi
+
+rm -f "$TEMP_TABLE"
+
+echo "==> Done. README updated at $README"
README.md
@@ -4,36 +4,27 @@
 
 ## Packages List
 
+<!-- BEGIN_PACKAGE_TABLE -->
 ### Common
 
-| **Path**             | **Name**                         | **Version**             | **License**     | **Description**                     |
-| -------------------- | -------------------------------- | ----------------------- | --------------- | ----------------------------------- |
-| `dwproton-bin`       | [dwproton-bin][dwproton]         | `11.0-2`                | BSD-3-Clause    | Modifed Proton builds               |
-| `harmonoid`          | [harmonoid][harmonoid]           | `0.3.22`                | **Unfree**      | Music player                        |
-| `localbooru-bin`     | [localbooru-bin][localbooru]     | `1.6.1`                 | GPL-3.0         | Local booru collection              |
-| `mo2-lint`           | [mo2-lint][mo2-lint]             | `0-unstable-2026-03-24` | GPL-3.0         | Mod Organizer 2 installer for Linux |
-| `musly-player`       | [musly-player][musly]            | `1.0.13`                | CC-BY-NC-SA 4.0 | Subsonic-compatible music client    |
-| `particle-music`     | [particle-music][particle-music] | `2.2.1`                 | Apache-2.0      | Music player                        |
-| `shimmie2`           | [shimmie2][shimmie2]             | `2.12.2`                | GPL-2.0         | Image gallery (aka booru)           |
-| `shimmie2-unwrapped` | [shimmie2-unwrapped][shimmie2]   | `2.12.2`                | GPL-2.0         | Image gallery (aka booru)           |
-| `spritz-wine-bin`    | [spritiz-wine-bin][spritz-wine]  | -                       | MIT             | Spritz-Wine builds for some games   |
+| Path | Name | Version | License | Description |
+| --- | --- | --- | --- | --- |
+| `dwproton-bin` | [dwproton](https://dawn.wine/dawn-winery/dwproton) | `11.0-2` | [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) | Dawn Winery's custom Proton fork with fixes for various games |
+| `harmonoid` | [harmonoid](https://harmonoid.com/) | `0.3.22` | **Unfree** | Plays & manages your music library. Looks beautiful & juicy. |
+| `localbooru-bin` | [localbooru-bin](https://github.com/resucutie/localbooru) | `1.6.1` | [GPL-3.0-or-later](https://spdx.org/licenses/GPL-3.0-or-later.html) | Cross platform local booru collection that exclusively works on local storage, without selfhosting |
+| `mo2-lint` | [mo2-lint](https://github.com/Furglitch/modorganizer2-linux-installer/tree/rewrite) | `0-unstable-2026-03-24` | [GPL-3.0](https://spdx.org/licenses/GPL-3.0.html) | An easy-to-use Mod Organizer 2 installer for Linux, rewrited in Python. |
+| `musly-player` | [musly-player](https://github.com/dddevid/Musly) | `1.0.13` | [CC-BY-NC-SA-4.0](https://spdx.org/licenses/CC-BY-NC-SA-4.0.html) | A beautiful Flutter music streaming client for Subsonic-compatible servers with a modern Apple Music-inspired UI. |
+| `particle-music` | [particle-music](https://github.com/AfalpHy/ParticleMusic) | `2.2.1` | [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) | A cross-platform local music player based on Flutter |
+| `shimmie2` | [shimmie2](https://github.com/shish/shimmie2) | `2.12.2` | [GPL-2.0](https://spdx.org/licenses/GPL-2.0.html) | An easy-to-install community image gallery (aka booru) |
+| `shimmie2-unwrapped` | [shimmie2-unwrapped](https://github.com/shish/shimmie2) | `2.12.2` | [GPL-2.0](https://spdx.org/licenses/GPL-2.0.html) | An easy-to-install community image gallery (aka booru) |
+| `spritz-wine-bin` | [spritz-wine-bin](https://github.com/NelloKudo/spritz-wine) | `-` | [MIT](https://spdx.org/licenses/MIT.html) | Spritz-Wine builds for some games  |
 
-### Helix Plugins
+### helixPlugins
 
-| **Path**                          | **Name**                                              | **Version**           | **License**   |
-| --------------------------------- | ----------------------------------------------------- | --------------------- | ------------- |
-| `helixPlugins.helix-file-watcher` | [helix-file-watcher][helixPlugins/helix-file-watcher] | `unstable-2026-03-08` | Not specified |
-| `helixPlugins.wakatime-hx`        | [wakatime.hx][helixPlugins/wakatime.hx]               | `unstable-2026-05-01` | MIT           |
-| `helixPlugins.scooter-hx`         | [sooter.hx][helixPlugins/scooter.hx]                  | `unstable-2026-03-15` | MIT           |
+| Path | Name | Version | License | Description |
+| --- | --- | --- | --- | --- |
+| `helixPlugins.helix-file-watcher` | [helix-file-watcher](https://github.com/mattwparas/helix-file-watcher) | `unstable-2026-03-08` | Not specified | Helix file watcher plugin |
+| `helixPlugins.scooter-hx` | [scooter.hx](https://github.com/thomasschafer/scooter.hx) | `unstable-2026-03-15` | [MIT](https://spdx.org/licenses/MIT.html) | Interactive find-and-replace Helix plugin |
+| `helixPlugins.wakatime-hx` | [wakatime.hx](https://github.com/Xerxes-2/wakatime.hx) | `unstable-2026-05-01` | [MIT](https://spdx.org/licenses/MIT.html) | Wakatime plugin for Helix Steel |
 
-[dwproton]: https://dawn.wine/dawn-winery/dwproton
-[harmonoid]: https://harmonoid.com/
-[helixPlugins/helix-file-watcher]: https://github.com/mattwparas/helix-file-watcher
-[helixPlugins/scooter.hx]: https://github.com/thomasschafer/scooter.hx
-[helixPlugins/wakatime.hx]: https://github.com/Xerxes-2/wakatime.hx
-[localbooru]: https://github.com/resucutie/localbooru
-[mo2-lint]: https://github.com/Furglitch/modorganizer2-linux-installer
-[musly]: https://github.com/dddevid/Musly
-[particle-music]: https://github.com/AfalpHy/ParticleMusic
-[shimmie2]: https://github.com/shish/shimmie2
-[spritz-wine]: https://github.com/NelloKudo/spritz-wine
+<!-- END_PACKAGE_TABLE -->