nimpkgs/src/nimpkgs.nim

251 lines
7.6 KiB
Nim

import std/[strutils, sets, sequtils, random]
include karax / prelude
import packages, button
type
Query = object
all, name, tag, license = "".kstring
randomize()
var
filteredPackages: seq[Package] = allPackages
searchInput: kstring = "".kstring
const
packagesGitUrl = "https://github.com/nim-lang/packages/blob/" & packagesHash & "/packages.json"
numPackages = allPackages.len
numTags = allTags.len
colors = [
"flamingo",
"pink",
"mauve",
"red",
"maroon",
"peach",
"yellow",
"green",
"teal",
"sky",
"sapphire",
"blue",
"lavender"
]
let
accent = (" " & colors.sample() & " ").kstring
textStyle = (" text-ctp-" & accent & " ").kstring
borderStyle = (" b-ctp-" & accent & " ").kstring
randomPkgIndices = [
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
rand(numPackages-1), rand(numPackages-1), rand(numPackages-1),
rand(numPackages-1)]
randomTagIndices = [
rand(numTags-1), rand(numTags-1), rand(numTags-1),
rand(numTags-1), rand(numTags-1), rand(numTags-1)
]
proc parseQuery(s: kstring): Query =
result = Query()
if ":" notin s:
result.all = s; return
let parts = s.split(" ")
for part in parts:
if ":" in part:
let
subparts = part.split(":")
k = subparts[0]
v = subparts[1]
case k:
of "name":
result.name = v
of "tag":
result.tag = v
of "license":
result.license = v
else: discard
else:
result.all &= part
proc searchPackages(q: Query) =
filteredPackages = @[]
if q == Query():
filteredPackages = allPackages
return
for pkg in allPackages:
let searchStr = ((pkg.name & " " & pkg.description & " " & (pkg.tags).join(" ").kstring))
if (q.name notin pkg.name) or
(q.license notin pkg.license) or
(q.tag != "".kstring and (q.tag notin pkg.tags)): continue
if q.all in searchStr:
filteredPackages.add pkg
proc setSearch(v: kstring): proc () =
result = proc() =
searchInput = v
searchPackages(parseQuery(v))
redraw()
proc fieldToDom(s: kstring): VNode =
result = buildHtml(tdiv(class = "font-black basis-1/4 sm:basis-1/6 shrink-0")):
text s & ":"
proc noProtocol(s: kstring): kstring = kstring(($s).replace("http://",
"").replace("https://", ""))
proc toDom(pkg: Package): VNode =
result = buildHtml(tdiv(class = "flex flex-col bg-ctp-crust rounded-xl my-5 p-5")):
h2(class = (textStyle & "font-black md:text-2xl text-lg font-casual").kstring):
text ("# " & pkg.name).kstring
if pkg.alias != "":
tdiv:
text "alias for: "
span(onClick = setSearch("name:" & pkg.alias),
class = "hover:text-ctp-mauve"):
text pkg.alias
else:
text pkg.description
tdiv(class = "flex flex-col text-xs md:text-lg overflow-x-scroll"):
tdiv(class = "flex flex-row"):
fieldToDom("project")
a(href = pkg.url):
text pkg.url.noProtocol
tdiv(class = "flex flex-row"):
fieldToDom("web")
a(href = pkg.web): text pkg.web.noProtocol
if pkg.doc != "":
tdiv(class = "flex flex-row"):
fieldToDom("doc")
a(href = pkg.doc): text pkg.doc.noProtocol
tdiv(class = "flex flex-row"):
fieldToDom("license")
span: text pkg.license
tdiv(class = "flex flex-row"):
fieldToDom("tags")
tdiv():
for t in pkg.tags:
span(onClick = setSearch("tag:" & t),
class = "hover:text-ctp-mauve"):
text t
text "; "
# tdiv(class="bg-ctp-mantle rounded my-2 p-2"):
# text "nimble install " & p.name
# br()
# text "atlas use " & p.name
proc startChar(p: Package): char = p.name[0].toLowerAscii
proc toDom(pkgs: seq[Package]): VNode =
var l = 'a'
result = buildHtml(tdiv):
if pkgs[0].startChar == l: tdiv(id = ($l).kstring)
for pkg in pkgs:
let startC = pkg.name[0].toLowerAscii
if l != startC:
while l != startC: inc l
tdiv(id = ($l).kstring)
pkg.toDom
proc getSearchInput() =
searchInput = getVNodeById("search").getInputText
searchPackages(parseQuery(searchInput))
proc render(t: Tag): VNode =
result = buildHtml(tdiv(class = "bg-ctp-mantle m-1 p-1 rounded hover:text-ctp-mauve")):
tdiv(onClick = setSearch("tag:" & t.name)):
text t.name & "|" & kstring($t.packages)
proc searchBar(): Vnode =
result = buildHtml(tdiv(class = "flex flex-col md:flex-row md:items-center md:my-5")):
tdiv(class = "flex flex-row my-2"):
input(`type` = "text", class = "border-1 bg-ctp-crust rounded mx-3 p-2".kstring & borderStyle, `id` = "search",
placeholder = "query", value = searchInput,
onChange = getSearchInput)
button(`type` = "button", class = "border-1 rounded p-2".kstring &
borderStyle, onClick = getSearchInput):
text "search"
#[
tdiv(class = "md:mx-5 flex flex-col items-center"):
tdiv: text "examples: "
tdiv(class="flex flex-col"):
for msg in ["tag:database sqlite","license:MIT javascript"]:
span(class = "bg-ctp-mantle rounded text-ctp-subtextone m-1 p-1 text-xs"):
text msg
]#
tdiv(class = "flex flex-col mx-5"):
tdiv: text "explore tags:"
tdiv(class = "flex flex-wrap text-sm"):
for idx in randomTagIndices:
allTags[idx].render
proc headerBar(): VNode =
result = buildHtml(tdiv(class = "mt-5 mx-5 flex flex-wrap")):
tdiv(class = "flex items-center my-3 grow"):
img(src = "img/logo.svg", class = "inline h-1em md:h-2em px-1")
span(class = "font-bold md:text-4xl text-lg font-casual"):
text "pkgs"
label(`for` = "menu-toggle",
class = "cursor-pointer lg:hidden flex items-center px-3 py-2"
):
text "menu"
input(class = "hidden", type = "checkbox", `id` = "menu-toggle")
tdiv(class = "lg:flex lg:items-center justify-between hidden w-full lg:w-auto",
`id` = "menu"):
nav:
ul(class = "md:flex items-center"):
for (url, msg) in [
(packagesGitUrl, "nim-lang/packages:" & packagesHashAbbr),
("http://github.com/daylinmorgan/nimpkgs", "source")
]:
li(class = "p-2 hover:bg-ctp-mantle rounded text-sm"):
a(href = url.kstring, class = accent):
text msg
proc includedLinks(pkgs: seq[Package]): HashSet[char] =
pkgs.mapIt(it.startChar).toHashSet
proc letterlink(): VNode =
let activeLinks = includedLinks(filteredPackages)
result = buildHtml(tdiv(class = "flex flex-wrap md:text-xl text-lg capitalize w-full justify-evenly gap-x-2 md:gap-x-auto")):
for l in LowercaseLetters:
tdiv(class = "w-5"):
if l in activeLinks:
a(href = "#" & ($l).kstring):
text $l
else:
span(class = "text-ctp-crust"):
text $l
proc filteredPackagesDom(): VNode =
if filteredPackages.len > 0:
result = filteredPackages.toDom
else:
result = buildHtml():
text "no match...try a different query"
proc createDom(): VNode =
result = buildHtml(tdiv(class = "md:w-3/4 max-w-[95%] md:mx-auto mx-5 md:text-lg text-sm")):
headerBar()
searchBar()
letterlink()
tdiv(class = "text-ctp-surfacetwo"):
text ($filteredPackages.len & "/" & $allPackages.len) & " packages"
if searchInput == "":
tdiv():
for idx in randomPkgIndices:
allPackages[idx].toDom
hr()
filteredPackagesDom()
scrollToTopButton()
setRenderer createDom