123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- import std / [json, os, sets, strutils]
- 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
- 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)
- 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
|