diff --git a/collects/scribblings/main/private/make-search.ss b/collects/scribblings/main/private/make-search.ss
new file mode 100644
index 0000000000..9582481c62
--- /dev/null
+++ b/collects/scribblings/main/private/make-search.ss
@@ -0,0 +1,236 @@
+#reader scribble/reader
+#lang scheme/base
+
+(require scribble/decode
+ scribble/struct
+ ;; scribble/manual-struct
+ scheme/list
+ scheme/string
+ scheme/match
+ (only-in scheme/class send)
+ (only-in xml xexpr->string)
+ "utils.ss")
+
+(provide make-search)
+
+(define (cadr-string-lists a b)
+ (let loop ([a (cadr a)] [b (cadr b)])
+ (cond [(null? b) #f]
+ [(null? a) #t]
+ [(string-ci=? (car a) (car b))
+ (or (loop (cdr a) (cdr b))
+ ;; Try string so "Foo" still precedes "foo"
+ (string (car a) (car b)))]
+ [else (string-ci (car a) (car b))])))
+
+(define (make-script renderer sec ri)
+ (define l null)
+ (hash-for-each
+ (let ([parent (collected-info-parent (part-collected-info sec ri))])
+ (if parent
+ (collected-info-info (part-collected-info parent ri))
+ (collect-info-ext-ht (resolve-info-ci ri))))
+ (lambda (k v)
+ (when (and (pair? k) (eq? 'index-entry (car k)))
+ (set! l (cons (cons (cadr k) v) l)))))
+ (set! l (sort l cadr-string-lists))
+ (set! l
+ (for/list ([i l])
+ ;; i is (list tag (text ...) (element ...) index-desc)
+ (define-values (tag texts elts desc) (apply values i))
+ (define-values (href html)
+ (let* ([e (add-between elts ", ")]
+ [e (make-link-element "indexlink" e tag)]
+ [e (send renderer render-element e sec ri)])
+ (match e ; should always render to a single `a'
+ [`((a ([href ,href] [class "indexlink"]) . ,body))
+ (values href (string-append* (map xexpr->string body)))]
+ [else (error 'zzz "something bad happened ~s" e)])))
+ ;; (and (exported-index-desc? desc)
+ ;; (list (exported-index-desc-name desc)
+ ;; (exported-index-desc-from-libs desc)))
+ (format "~a[~s, ~s, ~s]"
+ (if (eq? i (car l)) "" ",\n")
+ (string-join texts " ")
+ href
+ html)))
+ @script[#:noscript @list{Sorry, you must have JavaScript to use this page.}]{
+ // this vector has an entry for each index link: [text, url, html]
+ plt_search_data = [
+ @l];
+
+ // Globally visible bindings
+ var search_handler, page_up_handler, page_dn_handler;
+
+ (function(){
+
+ // Configuration options
+ var results_num = 20;
+
+ var query, status, results_container, result_links;
+
+ function InitializeSearch() {
+ var n;
+ n = document.getElementById("plt_search_container").parentNode;
+ // hack the table in
+ n.innerHTML = ''
+ +'
';
+ // get the query box
+ query = document.getElementById("search_box");
+ // status should point to the text object
+ status = document.getElementById("search_status");
+ if (status.childNodes.length == 1) status = status.firstChild;
+ // result_links is the array of result link pairs
+ result_links = new Array();
+ n = document.getElementById("search_result");
+ results_container = n.parentNode;
+ results_container.normalize();
+ result_links.push(n);
+ AdjustResultsNum();
+ // get search string
+ if (location.search.length > 0) {
+ var paramstrs = location.search.substring(1).split(/[@";"&]/);
+ for (var i=0@";" i results_num)
+ results_container.removeChild(result_links.pop());
+ while (result_links.length < results_num) {
+ var n = result_links[0].cloneNode(true);
+ result_links.push(n);
+ results_container.appendChild(n);
+ }
+ }
+
+ var last_search_terms;
+ var search_results, first_search_result;
+ function DoSearch() {
+ var terms = query.value.toLowerCase()
+ .replace(/\s\s*/g," ") // single spaces
+ .replace(/^\s/g,"").replace(/\s$/g,""); // trim edge spaces
+ if (terms == last_search_terms) return;
+ last_search_terms = terms;
+ status.nodeValue = "Searching " + plt_search_data.length + " entries";
+ terms = (terms=="") ? [] : terms.split(/ /);
+ if (terms.length == 0) {
+ search_results = plt_search_data;
+ } else {
+ search_results = new Array();
+ for (var i=0@";" i= search_results.length)
+ first_search_result = 0;
+ for (var i=0@";" i'
+ + search_results[n][2] + '';
+ result_links[i].style.display = "block";
+ } else {
+ result_links[i].style.display = "none";
+ }
+ }
+ if (search_results.length == 0)
+ status.nodeValue = "No matches found";
+ else if (search_results.length <= results_num)
+ status.nodeValue = "Showing all " + search_results.length + " matches";
+ else
+ status.nodeValue =
+ "Showing "
+ + (first_search_result+1) + "--"
+ + Math.min(first_search_result+results_num,search_results.length)
+ + " of " + search_results.length + " matches";
+ }
+
+ var search_timer = null;
+ function DelayedSearch(event) {
+ if (search_timer != null) {
+ var t = search_timer;
+ search_timer = null;
+ clearTimeout(t);
+ }
+ var key = event && event.keyCode;
+ if (key == 13) DoSearch();
+ else if (key == 33) PageUp();
+ else if (key == 34) PageDn();
+ else search_timer = setTimeout(DoSearch, 1000);
+ }
+
+ search_handler = DelayedSearch;
+ page_up_handler = PageUp;
+ page_dn_handler = PageDn;
+
+ window.onload = InitializeSearch;
+
+ })();
+ })
+
+(define (make-search)
+ (make-splice
+ (list
+ (make-delayed-block
+ (lambda (r s i) (make-paragraph (list (make-script r s i)))))
+ (make-element (make-with-attributes #f '((id . "plt_search_container")))
+ null))))
diff --git a/collects/scribblings/main/private/utils.ss b/collects/scribblings/main/private/utils.ss
index 608dbd9a82..911a7be639 100644
--- a/collects/scribblings/main/private/utils.ss
+++ b/collects/scribblings/main/private/utils.ss
@@ -5,9 +5,10 @@
scribble/manual
scribble/struct
scribble/decode
+ scheme/list
setup/dirs)
-(provide main-page)
+(provide main-page script)
(define page-info
(let ([links (filter pair? links)])
@@ -15,8 +16,8 @@
(cond [(assq id links) => cdr]
[else (error 'main-page "page id not found: ~e" id)]))))
-(define (script . body)
- (make-script-element #f null "text/javascript" body))
+(define (script #:noscript [noscript null] . body)
+ (make-script-element #f noscript "text/javascript" (flatten body)))
;; the second argument specifies installation/user specific, and if
;; it's missing, then it's a page with a single version
diff --git a/collects/scribblings/main/search.scrbl b/collects/scribblings/main/search.scrbl
index d8db0c1d22..1a5a96192d 100644
--- a/collects/scribblings/main/search.scrbl
+++ b/collects/scribblings/main/search.scrbl
@@ -1,8 +1,7 @@
#lang scribble/doc
-@(require scribble/basic
- scribble/decode
- "private/utils.ss")
+@(require "private/utils.ss"
+ "private/make-search.ss")
@main-page['search #t]
-Search page not implemented yet.
+@make-search[]
diff --git a/collects/scribblings/main/user/search.scrbl b/collects/scribblings/main/user/search.scrbl
index ed604316df..ee5089921d 100644
--- a/collects/scribblings/main/user/search.scrbl
+++ b/collects/scribblings/main/user/search.scrbl
@@ -1,8 +1,7 @@
#lang scribble/doc
-@(require scribble/basic
- scribble/decode
- "../private/utils.ss")
+@(require "../private/utils.ss"
+ "../private/make-search.ss")
@main-page['search #f]
-Search page not implemented yet.
+@make-search[]