I wanted to get an overview of the nimble packages but there isn't a browse function, so I wrote the nim program below. To use it you need to download `packages.json` from [nimble.packages](https://github.com/nim-lang/packages/). {.experimental: "codeReordering".} # TODO download the JSON file if mtime is older than today import algorithm import json import os import sequtils import strformat import strutils except escape import sugar import unicode import xmltree const Outfile = "nimble-packages.html" type Entry = object name: string url: string tags: seq[string] description: string license: string web: string main() proc main() = let filename = getFilename() # May not return let entries = entryItems(filename) writeHtmlTable(entries) proc getFilename(): string = let args = commandLineParams() if len(args) == 0 or args[0] == "-h" or args[0] == "--help": echo("usage: ", lastPathPart(getAppFilename()), " /path/to/nimble.packages.json") quit() args[0] proc entryItems(filename: string): seq[Entry] = for item in parseJson(readFile(filename)): var entry: Entry try: entry = to(item, Entry) except KeyError: for tag in ["name", "url", "description", "license", "web"]: try: let node = item[tag] let text = node.getStr() case tag of "name": entry.name = text of "url": entry.url = text of "description": entry.description = text of "license": entry.license = text of "web": entry.web = text except KeyError: discard # ignore missing for now try: let node = item["tags"] if node.kind == JArray: var tags = newSeq[string]() for element in node.getElems(): tags.add(element.getStr()) entry.tags = tags except KeyError: discard # no tags if entry.name == "": continue entry.tags = sorted(entry.tags.mapIt(it.toLower())) result.add(entry) if entry.url == "": entry.url = entry.web result.sort((a, b) => cmpIgnoreCase(a.name, b.name)) proc writeHtmlTable(entries: seq[Entry]) = var file = open(Outfile, fmWrite) defer: close(file) file.write("<table>\n") file.write("<tr><th>Name/Link</th><th>Description</th><th>Tags</th>" & "<th>License</th></tr>\n") for entry in entries: let name = &"<a href=\"{entry.url}\">{escape(entry.name)}</a>" let description = escape(entry.description) let tags = escape(join(entry.tags, ", ")) let license = escape(entry.license) file.write(&"<tr><td>{name}</td><td>{description}</td>" & &"<td>{tags}</td><td>{license}</td></tr>\n") file.write("</table>\n") file.write(&"<p>{len(entries)} packages.</p>\n") Run