bookshelf-doc/DocGen4/Process/Hierarchy.lean

139 lines
4.6 KiB
Plaintext
Raw Permalink Normal View History

2021-12-12 12:28:52 +00:00
/-
Copyright (c) 2021 Henrik Böving. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Henrik Böving
-/
2021-12-12 12:20:44 +00:00
import Lean
import Lean.Data.HashMap
2021-12-12 12:20:44 +00:00
import DocGen4.Process.NameExt
def Lean.HashSet.fromArray [BEq α] [Hashable α] (xs : Array α) : Lean.HashSet α :=
xs.foldr (flip .insert) .empty
2021-12-12 12:20:44 +00:00
namespace DocGen4
open Lean Name
2021-12-12 12:20:44 +00:00
def getNLevels (name : Name) (levels: Nat) : Name :=
2022-10-20 17:51:26 +00:00
let components := name.componentsRev
2022-01-15 14:35:52 +00:00
(components.drop (components.length - levels)).reverse.foldl (· ++ ·) Name.anonymous
2021-12-12 12:20:44 +00:00
inductive Hierarchy where
| node (name : NameExt) (isFile : Bool) (children : RBNode NameExt (fun _ => Hierarchy)) : Hierarchy
2021-12-12 12:20:44 +00:00
instance : Inhabited Hierarchy := ⟨Hierarchy.node ⟨anonymous, .html⟩ false RBNode.leaf⟩
2021-12-12 12:20:44 +00:00
abbrev HierarchyMap := RBNode NameExt (fun _ => Hierarchy)
2021-12-12 12:20:44 +00:00
-- Everything in this namespace is adapted from stdlib's RBNode
namespace HierarchyMap
def toList : HierarchyMap → List (NameExt × Hierarchy)
2021-12-12 12:20:44 +00:00
| t => t.revFold (fun ps k v => (k, v)::ps) []
def toArray : HierarchyMap → Array (NameExt × Hierarchy)
| t => t.fold (fun ps k v => ps ++ #[(k, v)] ) #[]
def hForIn [Monad m] (t : HierarchyMap) (init : σ) (f : (NameExt × Hierarchy) → σ → m (ForInStep σ)) : m σ :=
2021-12-12 12:20:44 +00:00
t.forIn init (fun a b acc => f (a, b) acc)
instance : ForIn m HierarchyMap (NameExt × Hierarchy) where
2021-12-12 12:20:44 +00:00
forIn := HierarchyMap.hForIn
end HierarchyMap
namespace Hierarchy
def empty (n : NameExt) (isFile : Bool) : Hierarchy :=
node n isFile RBNode.leaf
2021-12-12 12:20:44 +00:00
def getName : Hierarchy → Name
| node n _ _ => n.name
def getNameExt : Hierarchy → NameExt
| node n _ _ => n
2021-12-12 12:20:44 +00:00
def getChildren : Hierarchy → HierarchyMap
| node _ _ c => c
def isFile : Hierarchy → Bool
| node _ f _ => f
2021-12-12 12:20:44 +00:00
partial def insert! (h : Hierarchy) (n : NameExt) : Hierarchy := Id.run do
let hn := h.getNameExt
2021-12-12 12:20:44 +00:00
let mut cs := h.getChildren
if getNumParts hn.name + 1 == getNumParts n.name then
match cs.find NameExt.cmp n with
2021-12-12 12:20:44 +00:00
| none =>
node hn h.isFile (cs.insert NameExt.cmp n <| empty n true)
| some (node _ true _) => h
| some (node _ false ccs) =>
cs := cs.erase NameExt.cmp n
node hn h.isFile (cs.insert NameExt.cmp n <| node n true ccs)
2021-12-12 12:20:44 +00:00
else
let leveledName := ⟨getNLevels n.name (getNumParts hn.name + 1), .html⟩
match cs.find NameExt.cmp leveledName with
2021-12-12 12:20:44 +00:00
| some nextLevel =>
cs := cs.erase NameExt.cmp leveledName
-- BUG?
node hn h.isFile <| cs.insert NameExt.cmp leveledName (nextLevel.insert! n)
2021-12-12 12:20:44 +00:00
| none =>
let child := (insert! (empty leveledName false) n)
node hn h.isFile <| cs.insert NameExt.cmp leveledName child
2021-12-12 12:20:44 +00:00
partial def fromArray (names : Array Name) : Hierarchy :=
(names.map (fun n => NameExt.mk n .html)).foldl insert! (empty ⟨anonymous, .html⟩ false)
partial def fromArrayExt (names : Array NameExt) : Hierarchy :=
names.foldl insert! (empty ⟨anonymous, .html⟩ false)
2021-12-12 12:20:44 +00:00
def baseDirBlackList : HashSet String :=
HashSet.fromArray #[
"404.html",
2023-06-08 05:52:51 +00:00
"color-scheme.js",
"declaration-data.js",
"declarations",
2023-09-21 09:27:33 +00:00
"expand-nav.js",
"find",
2023-09-21 09:27:33 +00:00
"foundational_types.html",
"how-about.js",
"index.html",
2023-09-21 09:27:33 +00:00
"jump-src.js",
"mathjax-config.js",
"navbar.html",
"nav.js",
2023-09-21 09:27:33 +00:00
"search.html",
"search.js",
"src",
"style.css"
]
partial def fromDirectoryAux (dir : System.FilePath) (previous : Name) : IO (Array NameExt) := do
let mut children := #[]
for entry in ← System.FilePath.readDir dir do
if ← entry.path.isDir then
children := children ++ (← fromDirectoryAux entry.path (.str previous entry.fileName))
else if entry.path.extension = some "html" then
children := children.push <| ⟨.str previous (entry.fileName.dropRight ".html".length), .html⟩
else if entry.path.extension = some "pdf" then
children := children.push <| ⟨.str previous (entry.fileName.dropRight ".pdf".length), .pdf⟩
return children
def fromDirectory (dir : System.FilePath) : IO Hierarchy := do
let mut children := #[]
for entry in ← System.FilePath.readDir dir do
if baseDirBlackList.contains entry.fileName then
continue
else if ← entry.path.isDir then
children := children ++ (← fromDirectoryAux entry.path (.mkSimple entry.fileName))
else if entry.path.extension = some "html" then
children := children.push <| ⟨.mkSimple (entry.fileName.dropRight ".html".length), .html⟩
else if entry.path.extension = some "pdf" then
children := children.push <| ⟨.mkSimple (entry.fileName.dropRight ".pdf".length), .pdf⟩
return Hierarchy.fromArrayExt children
2021-12-12 12:20:44 +00:00
end Hierarchy
end DocGen4