2020-08-05 20:19:14 +00:00
|
|
|
package tree
|
|
|
|
|
|
|
|
import (
|
2022-08-06 08:45:10 +00:00
|
|
|
"github.com/bouncepaw/mycorrhiza/hyphae"
|
2020-08-05 20:19:14 +00:00
|
|
|
"path"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2022-08-06 08:45:10 +00:00
|
|
|
// Tree returns the subhypha matrix as HTML and names of the next and previous hyphae (or empty strings).
|
|
|
|
func Tree(hyphaName string) (childrenHTML, prev, next string) {
|
2021-04-06 18:47:35 +00:00
|
|
|
var (
|
2022-08-06 08:45:10 +00:00
|
|
|
root = child{hyphaName, true, make([]child, 0)}
|
|
|
|
descendantPrefix = hyphaName + "/"
|
|
|
|
parent = path.Dir(hyphaName) // Beware, it might be . and whatnot.
|
|
|
|
slashCount = strings.Count(hyphaName, "/")
|
2021-04-06 18:47:35 +00:00
|
|
|
)
|
2022-08-06 08:45:10 +00:00
|
|
|
for h := range hyphae.YieldExistingHyphae() {
|
|
|
|
name := h.CanonicalName()
|
|
|
|
if strings.HasPrefix(name, descendantPrefix) {
|
|
|
|
var subPath = strings.TrimPrefix(name, descendantPrefix)
|
|
|
|
addHyphaToChild(name, subPath, &root)
|
|
|
|
// A child is not a sibling, so we skip the rest.
|
|
|
|
continue
|
2021-04-06 18:47:35 +00:00
|
|
|
}
|
|
|
|
|
2022-08-06 08:45:10 +00:00
|
|
|
// Skipping non-siblings.
|
|
|
|
if !(path.Dir(name) == parent && slashCount == strings.Count(name, "/")) {
|
|
|
|
continue
|
|
|
|
}
|
2021-04-06 18:47:35 +00:00
|
|
|
|
2022-08-06 08:45:10 +00:00
|
|
|
if (name < hyphaName) && (name > prev) {
|
|
|
|
prev = name
|
|
|
|
} else if (name > hyphaName) && (name < next || next == "") {
|
|
|
|
next = name
|
2021-04-06 18:47:35 +00:00
|
|
|
}
|
2020-08-05 20:19:14 +00:00
|
|
|
}
|
2022-08-06 08:45:10 +00:00
|
|
|
return subhyphaeMatrix(root.children), prev, next
|
2021-04-06 18:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type child struct {
|
|
|
|
name string
|
2021-10-01 09:18:11 +00:00
|
|
|
exists bool
|
2021-04-06 18:47:35 +00:00
|
|
|
children []child
|
|
|
|
}
|
|
|
|
|
2021-10-17 02:48:35 +00:00
|
|
|
func addHyphaToChild(hyphaName, subPath string, child *child) {
|
|
|
|
// when hyphaName = "root/a/b", subPath = "a/b", and child.name = "root"
|
|
|
|
// addHyphaToChild("root/a/b", "b", child{"root/a"})
|
|
|
|
// when hyphaName = "root/a/b", subPath = "b", and child.name = "root/a"
|
|
|
|
// set .exists=true for "root/a/b", and create it if it isn't there already
|
|
|
|
var exists = !strings.Contains(subPath, "/")
|
|
|
|
if exists {
|
|
|
|
var subchild = findOrCreateSubchild(subPath, child)
|
|
|
|
subchild.exists = true
|
|
|
|
} else {
|
|
|
|
var (
|
|
|
|
firstSlash = strings.IndexRune(subPath, '/')
|
2021-10-17 18:30:19 +00:00
|
|
|
firstDir = subPath[:firstSlash]
|
|
|
|
restOfPath = subPath[firstSlash+1:]
|
|
|
|
subchild = findOrCreateSubchild(firstDir, child)
|
2021-10-17 02:48:35 +00:00
|
|
|
)
|
|
|
|
addHyphaToChild(hyphaName, restOfPath, subchild)
|
2021-10-01 09:18:11 +00:00
|
|
|
}
|
2021-10-17 02:48:35 +00:00
|
|
|
}
|
2021-10-01 09:18:11 +00:00
|
|
|
|
2021-10-17 02:48:35 +00:00
|
|
|
func findOrCreateSubchild(name string, baseChild *child) *child {
|
|
|
|
// when name = "a", and baseChild.name = "root"
|
|
|
|
// if baseChild.children contains "root/a", return it
|
|
|
|
// else create it and return that
|
|
|
|
var fullName = baseChild.name + "/" + name
|
|
|
|
for i := range baseChild.children {
|
|
|
|
if baseChild.children[i].name == fullName {
|
|
|
|
return &baseChild.children[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
baseChild.children = append(baseChild.children, child{fullName, false, make([]child, 0)})
|
2021-10-17 18:30:19 +00:00
|
|
|
return &baseChild.children[len(baseChild.children)-1]
|
2021-04-06 18:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func subhyphaeMatrix(children []child) (html string) {
|
2021-02-19 18:12:36 +00:00
|
|
|
sort.Slice(children, func(i, j int) bool {
|
|
|
|
return children[i].name < children[j].name
|
|
|
|
})
|
|
|
|
for _, child := range children {
|
2021-04-07 17:49:56 +00:00
|
|
|
html += childHTML(&child)
|
2021-02-19 18:12:36 +00:00
|
|
|
}
|
|
|
|
return html
|
|
|
|
}
|