aboutsummaryrefslogtreecommitdiff
path: root/dottydoc/js
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-06-01 17:23:37 +0200
committerFelix Mulder <felix.mulder@gmail.com>2016-08-19 15:37:25 +0200
commita099344f81ddb0463bbc6da99c376df9f70667df (patch)
tree73bbb72d67086db7d6c5eadda6fbf3a7122f763e /dottydoc/js
parent756861ed32207b5e1ab7964bcfdbe4165b68723e (diff)
downloaddotty-a099344f81ddb0463bbc6da99c376df9f70667df.tar.gz
dotty-a099344f81ddb0463bbc6da99c376df9f70667df.tar.bz2
dotty-a099344f81ddb0463bbc6da99c376df9f70667df.zip
Add basic implementation of toplevel entity search
Diffstat (limited to 'dottydoc/js')
-rw-r--r--dottydoc/js/src/DottyDoc.scala2
-rw-r--r--dottydoc/js/src/Search.scala115
-rw-r--r--dottydoc/js/src/html/EntityLayout.scala2
-rw-r--r--dottydoc/js/src/html/Member.scala4
-rw-r--r--dottydoc/js/src/model/entities.scala50
5 files changed, 134 insertions, 39 deletions
diff --git a/dottydoc/js/src/DottyDoc.scala b/dottydoc/js/src/DottyDoc.scala
index 5773e6a19..d33648e49 100644
--- a/dottydoc/js/src/DottyDoc.scala
+++ b/dottydoc/js/src/DottyDoc.scala
@@ -18,7 +18,7 @@ import html.EntityLayout
hljs.initHighlightingOnLoad()
val searchInput = document.getElementById("search").asInstanceOf[dom.html.Input]
- searchInput.onkeyup = Search(searchInput)
+ searchInput.onkeyup = new Search(searchInput).search()
}
}
diff --git a/dottydoc/js/src/Search.scala b/dottydoc/js/src/Search.scala
index 0683c5d95..6625e3c78 100644
--- a/dottydoc/js/src/Search.scala
+++ b/dottydoc/js/src/Search.scala
@@ -2,33 +2,120 @@ package dotty.tools.dottydoc
package js
import scala.scalajs.{ js => sjs }
-import sjs.timers._
-import org.scalajs.dom
+import sjs.timers.setTimeout
+import scalatags.JsDom.all._
+import org.scalajs.dom.html.{ Input, Div }
+import org.scalajs.dom.{ document, Event }
+import scala.concurrent.ExecutionContext.Implicits.global
+import scala.concurrent.Future
-object Search {
+import js.model._
+import js.model.ops._
+
+class Search(val input: Input) {
private var isSearching = false
- def apply(input: dom.html.Input) = considerSearch(input)
+ private val mainDiv = document
+ .getElementById("entity-container")
+ .asInstanceOf[Div]
+ private val resultsDiv = document
+ .getElementById("search-results")
+ .asInstanceOf[Div]
+
+ /** Search result ADTs */
+ private case class PackageResults(matching: Stream[Package], nonMatching: Stream[Package])
+ private object PackageResults {
+ def empty = PackageResults(Stream.empty, Stream.empty)
+ }
- def considerSearch(input: dom.html.Input): dom.Event => Unit = { e =>
- val query = input.value
+ /** Entry point into search, will consider whether to start searching or not,
+ * then call `performSearch`
+ */
+ def search(): Event => Unit = { e =>
+ val query = input.value.trim
if (query.length > 2) setTimeout(200) {
if (!isSearching) {
isSearching = true
- performSearch(query)
+ performSearch(query.toLowerCase).map { _ => isSearching = false }
}
}
+ else if (query.length == 0)
+ hideSearchDiv()
}
- def performSearch(query: String): Unit = {
- println(s"searching for $query...")
+ private def performSearch(query: String): Future[Unit] =
+ for (PackageResults(matching, nonMatching) <- searchPackages(query)) yield {
+ // Clear old results, add new result categories add close button
+ resultsDiv.innerHTML = ""
+ val toplevelRes = div(id := "toplevel-results").render
+ val methodRes = div(id := "method-results").render
+ val closeButton = button(
+ id := "close-button",
+ onclick := { _: Event =>
+ resetInput()
+ hideSearchDiv()
+ },
+ cls := "mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored",
+ i(cls := "material-icons", "clear")
+ ).render
+
+ resultsDiv.appendChild(toplevelRes)
+ resultsDiv.appendChild(methodRes)
+ resultsDiv.appendChild(closeButton)
+
+ // Add all matching toplevel entities
+ matching
+ .toStream
+ .sortBy(_.name)
+ .map(createPackageCard)
+ .foreach(toplevelRes.appendChild)
+
+ // Hide entity and show results instead
+ showSearchDiv()
+ }
+
+ private def searchPackages(query: String): Future[PackageResults] = Future {
+ EntityIndex.packages.values.foldLeft(PackageResults.empty) { (acc, p) =>
+ val matchingMembers = p.members.collect {
+ case x if (x.name.toLowerCase.contains(query) && x.kind != "package") => x
+ }
+
+ println("We found all matching members maybe")
+ sjs.Dynamic.global.console.log(p)
- val matchingPackages = EntityIndex.packages.values.collect {
- case x if x.name.startsWith(query) => x
+ if (p.name.toLowerCase.contains(query) || matchingMembers.nonEmpty)
+ acc.copy(matching = p.withMembers(matchingMembers) #:: acc.matching)
+ else acc
}
+ }
+
+ private def createPackageCard(pack: Package): Div = div(
+ cls := "mdl-card mdl-shadow--2dp package-result",
+ div(cls := "mdl-card__title", h2(cls := "mdl-card__title-text", pack.name)),
+ ul(pack.members.map(createEntityLi).toList)
+ ).render
+
+ private def createEntityLi(e: Entity) = li(
+ a(
+ href := toRoot + e.path.mkString("", "/", ".html"),
+ e.kind + " " + e.name
+ )
+ )
+
+ private def toRoot = "../" * (EntityIndex.currentEntity.path.length - 1)
+
+ private def resetInput() = {
+ input.value = ""
+ input.parentElement.className = input.parentElement.className.replaceAll("is-dirty", "")
+ }
+
+ private def showSearchDiv() = {
+ mainDiv.style.display = "none"
+ resultsDiv.style.display = "block"
+ }
- println("Found matching packages: ")
- matchingPackages.map(_.name).foreach(println)
- isSearching = false
+ private def hideSearchDiv() = {
+ resultsDiv.style.display = "none"
+ mainDiv.style.display = "block"
}
}
diff --git a/dottydoc/js/src/html/EntityLayout.scala b/dottydoc/js/src/html/EntityLayout.scala
index fcb0cd5e0..9a1076a16 100644
--- a/dottydoc/js/src/html/EntityLayout.scala
+++ b/dottydoc/js/src/html/EntityLayout.scala
@@ -5,7 +5,7 @@ package html
import scalatags.JsDom.all._
import org.scalajs.dom
import org.scalajs.dom.html.{Anchor, Div}
-import model._
+import dotty.tools.dottydoc.model._
case class EntityLayout(entity: Entity) extends MemberLayout {
def html = div(
diff --git a/dottydoc/js/src/html/Member.scala b/dottydoc/js/src/html/Member.scala
index ff16631c5..c4989e762 100644
--- a/dottydoc/js/src/html/Member.scala
+++ b/dottydoc/js/src/html/Member.scala
@@ -8,8 +8,8 @@ import org.scalajs.dom
import org.scalajs.dom.html.{Anchor, Div}
trait MemberLayout {
- import model._
- import comment._
+ import dotty.tools.dottydoc.model._
+ import dotty.tools.dottydoc.model.comment._
def member(m: Entity, parent: Entity) = {
def toggleBetween(short: Div, and: Div): Unit =
diff --git a/dottydoc/js/src/model/entities.scala b/dottydoc/js/src/model/entities.scala
index 2710a5392..4a4984a34 100644
--- a/dottydoc/js/src/model/entities.scala
+++ b/dottydoc/js/src/model/entities.scala
@@ -4,6 +4,7 @@ package js
package model
import scala.scalajs.{ js => sjs }
+import sjs.annotation.ScalaJSDefined
/** This file defines the interface for which to interact with the searchable
* index. To use the normal operations available on the traits on the JVM:
@@ -17,47 +18,47 @@ import scala.scalajs.{ js => sjs }
* interface, this is simply due to the fact that they're not necessary for
* search - YET. They could be added, for instance `comment` is missing.
*/
-@sjs.native
-trait Entity extends sjs.Any {
- val kind: String = sjs.native
+@ScalaJSDefined
+trait Entity extends sjs.Object {
+ val kind: String
- val name: String = sjs.native
+ val name: String
- val path: sjs.Array[String] = sjs.native
+ val path: sjs.Array[String]
}
-@sjs.native
-trait Members extends sjs.Any {
- val members: sjs.Array[Entity] = sjs.native
+@ScalaJSDefined
+trait Members extends sjs.Object {
+ val members: sjs.Array[Entity]
}
-@sjs.native
-trait Modifiers extends sjs.Any {
- val modifiers: sjs.Array[String] = sjs.native
+@ScalaJSDefined
+trait Modifiers extends sjs.Object {
+ val modifiers: sjs.Array[String]
}
-@sjs.native
+@ScalaJSDefined
trait Package extends Entity with Members
-@sjs.native
+@ScalaJSDefined
trait Class extends Entity with Members with Modifiers
-@sjs.native
-trait CaseClass extends Entity with Members with Modifiers
+@ScalaJSDefined
+trait CaseClass extends Class
-@sjs.native
-trait Object extends Class with Modifiers
+@ScalaJSDefined
+trait Object extends Class
-@sjs.native
+@ScalaJSDefined
trait Trait extends Class
-@sjs.native
+@ScalaJSDefined
trait Def extends Entity with Modifiers
-@sjs.native
+@ScalaJSDefined
trait Val extends Def
-@sjs.native
+@ScalaJSDefined
trait Var extends Def
object ops {
@@ -70,5 +71,12 @@ object ops {
case x if EntitiesWithMembers contains x.kind =>
x.asInstanceOf[Entity with Members]
}
+
+ def withMembers(mbrs: sjs.Array[Entity]): Package = new Package {
+ val kind = p.kind
+ val name = p.name
+ val path = p.path
+ val members = mbrs
+ }
}
}