summary refs log tree commit diff stats
path: root/tools/atlas/packagesjson.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tools/atlas/packagesjson.nim')
-rw-r--r--tools/atlas/packagesjson.nim117
1 files changed, 117 insertions, 0 deletions
diff --git a/tools/atlas/packagesjson.nim b/tools/atlas/packagesjson.nim
new file mode 100644
index 000000000..e1e23ee29
--- /dev/null
+++ b/tools/atlas/packagesjson.nim
@@ -0,0 +1,117 @@
+
+import std / [json, os, sets, strutils]
+import osutils
+
+type
+  Package* = ref object
+    # Required fields in a package.
+    name*: string
+    url*: string # Download location.
+    license*: string
+    downloadMethod*: string
+    description*: string
+    tags*: seq[string] # \
+    # From here on, optional fields set to the empty string if not available.
+    version*: string
+    dvcsTag*: string
+    web*: string # Info url for humans.
+
+proc optionalField(obj: JsonNode, name: string, default = ""): string =
+  if hasKey(obj, name) and obj[name].kind == JString:
+    result = obj[name].str
+  else:
+    result = default
+
+proc requiredField(obj: JsonNode, name: string): string =
+  result = optionalField(obj, name, "")
+
+proc fromJson*(obj: JSonNode): Package =
+  result = Package()
+  result.name = obj.requiredField("name")
+  if result.name.len == 0: return nil
+  result.version = obj.optionalField("version")
+  result.url = obj.requiredField("url")
+  if result.url.len == 0: return nil
+  result.downloadMethod = obj.requiredField("method")
+  if result.downloadMethod.len == 0: return nil
+  result.dvcsTag = obj.optionalField("dvcs-tag")
+  result.license = obj.optionalField("license")
+  result.tags = @[]
+  for t in obj["tags"]:
+    result.tags.add(t.str)
+  result.description = obj.requiredField("description")
+  result.web = obj.optionalField("web")
+
+const PackagesDir* = "packages"
+
+proc getPackages*(workspaceDir: string): seq[Package] =
+  result = @[]
+  var uniqueNames = initHashSet[string]()
+  var jsonFiles = 0
+  for kind, path in walkDir(workspaceDir / PackagesDir):
+    if kind == pcFile and path.endsWith(".json"):
+      inc jsonFiles
+      let packages = json.parseFile(path)
+      for p in packages:
+        let pkg = p.fromJson()
+        if pkg != nil and not uniqueNames.containsOrIncl(pkg.name):
+          result.add(pkg)
+
+proc `$`*(pkg: Package): string =
+  result = pkg.name & ":\n"
+  result &= "  url:         " & pkg.url & " (" & pkg.downloadMethod & ")\n"
+  result &= "  tags:        " & pkg.tags.join(", ") & "\n"
+  result &= "  description: " & pkg.description & "\n"
+  result &= "  license:     " & pkg.license & "\n"
+  if pkg.web.len > 0:
+    result &= "  website:     " & pkg.web & "\n"
+
+proc search*(pkgList: seq[Package]; terms: seq[string]) =
+  var found = false
+  template onFound =
+    echo pkg
+    echo("")
+    found = true
+    break forPackage
+
+  for pkg in pkgList:
+    if terms.len > 0:
+      block forPackage:
+        for term in terms:
+          let word = term.toLower
+          # Search by name.
+          if word in pkg.name.toLower:
+            onFound()
+          # Search by tag.
+          for tag in pkg.tags:
+            if word in tag.toLower:
+              onFound()
+    else:
+      echo(pkg)
+      echo(" ")
+
+  if not found and terms.len > 0:
+    echo("No package found.")
+
+type PkgCandidates* = array[3, seq[Package]]
+
+proc determineCandidates*(pkgList: seq[Package];
+                         terms: seq[string]): PkgCandidates =
+  result[0] = @[]
+  result[1] = @[]
+  result[2] = @[]
+  for pkg in pkgList:
+    block termLoop:
+      for term in terms:
+        let word = term.toLower
+        if word == pkg.name.toLower:
+          result[0].add pkg
+          break termLoop
+        elif word in pkg.name.toLower:
+          result[1].add pkg
+          break termLoop
+        else:
+          for tag in pkg.tags:
+            if word in tag.toLower:
+              result[2].add pkg
+              break termLoop