diff --git a/collects/scribblings/main/private/make-search.ss b/collects/scribblings/main/private/make-search.ss index 337bb562b1..0622a3e5f6 100644 --- a/collects/scribblings/main/private/make-search.ss +++ b/collects/scribblings/main/private/make-search.ss @@ -2,9 +2,10 @@ #lang scheme/base (require scribble/decode + scribble/decode-struct + scribble/basic scribble/struct scribble/manual-struct - scribble/basic scheme/list scheme/string scheme/match @@ -62,8 +63,9 @@ (if (= 1 (length body)) (car body) (string-append* `("[" ,@(add-between body ",") "]"))))))) + (define manual-refs (make-hash)) (define l - (for/list ([i (get-index-entries sec ri)]) + (for/list ([i (get-index-entries sec ri)] [idx (in-naturals)]) ;; i is (list tag (text ...) (element ...) index-desc) (define-values (tag texts elts desc) (apply values i)) (define text (string-downcase (string-join texts " "))) @@ -73,6 +75,9 @@ [e (send renderer render-element e sec ri)]) (match e ; should always render to a single `a' [`((a ([href ,href] [class "indexlink"]) . ,body)) + (cond [(and (part-index-desc? desc) + (regexp-match #rx"(?:^|/)([^/]+)/index\\.html$" href)) + => (lambda (man) (hash-set! manual-refs (cadr man) idx))]) (let (;; throw away tooltips, we don't need them [body (match body [`((span ((title ,label)) . ,body)) @@ -122,14 +127,24 @@ // or the string "module" for a module entry plt_search_data = [ @(add-between l ",\n")]; + // array of pointers to the previous array, for items that are manuals + plt_manual_ptrs = { + @(let* ([ms (hash-map manual-refs cons)] + [ms (sort ms < #:key cdr)] + [ms (map (lambda (x) (format "~s: ~a" (car x) (cdr x))) ms)]) + (add-between ms ",\n "))}; // Globally visible bindings var key_handler, toggle_help_pref, hide_prefs, new_query, - set_results_num, set_type_delay, set_highlight_color; + set_show_manuals, set_show_manual_titles, set_results_num, + set_type_delay, set_highlight_color; (function(){ - // Configuration options (use || in case the cookie exists but empty) + // Configuration options (use || in case a cookie exists but is empty) + var manual_settings = parseInt(GetCookie("PLT_ManualSettings",1)); + var show_manuals = manual_settings % 10; + var show_manual_titles = ((manual_settings - show_manuals) / 10) > 0; var results_num = (parseInt(GetCookie("PLT_ResultsNum", false)) || 20); var type_delay = (parseInt(GetCookie("PLT_TypeDelay", false)) || 300); var highlight_color = (GetCookie("PLT_HighlightColor", false) || "#ffd"); @@ -138,6 +153,13 @@ var query, status, results_container, result_links, prev_page_link, next_page_link, panel; + // tabIndex fields are set: + // 1 query + // 2 index links + // 3 help/pref toggle + // 4 pref widgets + // -1 prev/next page (un-tab-able) + function InitializeSearch() { var n; n = document.getElementById("plt_search_container").parentNode; @@ -149,14 +171,14 @@ +'' +'' - +'[?]' +'' - +'' @@ -164,25 +186,45 @@ +'
  • Hit PageUp/PageDown and Enter to' +' scroll through the results.
  • ' +'
  • Use “M:str” to match only' - +' idenifiers from modles that match ' - +'“str”; “M:” by' - +' itself will restrict results to bound names only
  • ' + +' idenifiers from modles that match' + +' “str”; “M:”' + +' by itself will restrict results to bound names only' +'
  • L:str” is similar to' +' “L:str”, but' +' “str” should match the module name' +' exactly
  • ' + +'
  • T:str” restricts results to ones' + +' in the “str” manual (naming the' + +' directory where the manual is found)
  • ' + +'
  • Entries that correspond to bindings have module links that' + +' create a query restricted to bindings in that module (using' + +' “L:”), other entries have a similar' + +' manual links (using “T:”); you can' + +' control whether manual links appear (and how) below
  • ' +'
    ' +'Preferences:
    ' + +'Show manuals:' + +' ' + +' ' + +' use titles
    ' +'Results per page:' - +'
    ' +'Type delay:' - +'
    ' +'Exact matches color:' - +'
    ' +'
    ' @@ -247,9 +289,14 @@ } } + // constants for Compare(() results; // `rexact' is for an actual exact match, so we know that we matched - // *something* and can show exact matches as such + // *something* and can show exact matches as such, in other words: + // - < exact => this match is inexact + // - = exact => does not affect the exactness of this match + // - > exact => this is an exact match as far as this predicate goes var C_fail = 0, C_match = 1, C_prefix = 2, C_exact = 3, C_rexact = 4; + function Compare(pat, str) { var i = str.indexOf(pat); if (i < 0) return C_fail; @@ -264,26 +311,35 @@ return r; } + function UrlToManual(url) { + return url.replace(/\/[^\/]*$/, "").replace(/^(.*\/|>)/, ""); + } + function CompileTerm(term) { - var flag = ((term.search(/^[LM]:/)==0) && term.substring(0,1)); + var flag = ((term.search(/^[LMT]:/)==0) && term.substring(0,1)); if (flag) term = term.substring(2); term = term.toLowerCase(); switch(flag) { - case "L": return function(text,info) { - if (!info) return C_fail; - if (info == "module") return Compare(term,text); // rexact allowed! - return (MaxCompares(term,info) >= C_exact) ? C_exact : C_fail; + case "L": return function(x) { + if (!x[3]) return C_fail; + if (x[3] == "module") return Compare(term,x[0]); // rexact allowed! + return (MaxCompares(term,x[3]) >= C_exact) ? C_exact : C_fail; } - case "M": return function(text,info) { - if (!info) return C_fail; - if (info == "module") return Compare(term,text); // rexact allowed! - return (MaxCompares(term,info) >= C_match) ? C_exact : C_fail; + case "M": return function(x) { + if (!x[3]) return C_fail; + if (x[3] == "module") return Compare(term,x[0]); // rexact allowed! + return (MaxCompares(term,x[3]) >= C_match) ? C_exact : C_fail; } - default: return function(text,info) { - switch (Compare(term,text)) { + case "T": return function(x) { + if (Compare(term,UrlToManual(x[1])) < C_exact) return C_fail; + else if (x[1].search(/\/index\.html$/) > 0) return C_rexact; + else return C_exact; + } + default: return function(x) { + switch (Compare(term,x[0])) { case C_fail: return C_fail; case C_match: case C_prefix: return C_match; - case C_exact: case C_rexact: return (info ? C_rexact : C_match); + case C_exact: case C_rexact: return (x[3] ? C_rexact : C_match); } } } @@ -310,8 +366,7 @@ for (var i=0@";" i= C_rexact) exact_results.push(plt_search_data[i]); else if (r > C_fail) search_results.push(plt_search_data[i]); } @@ -352,26 +407,39 @@ for (var i=0@";" i 0)) { note = 'provided from '; for (var j=0@";" j' + desc[j] + ''; } else if (desc == "module") { note = 'module'; } + if (show_manuals == 2 || (show_manuals == 1 && !desc)) { + var manual = UrlToManual(res[1]), + idx = (show_manual_titles && plt_manual_ptrs[manual]); + note = (note ? (note + " ") : ""); + note += 'in ' + + '' + + ((typeof idx == "number") + ? (''+UncompactHtml(plt_search_data[idx][2])+'') + : manual) + + ''; + } if (note) note = '  ' + note + ''; result_links[i].innerHTML = - '' - + UncompactHtml(search_results[n][2]) + '' + (note || ""); + '' + + UncompactHtml(res[2]) + '' + (note || ""); result_links[i].style.backgroundColor = (n < exact_results_num) ? highlight_color : background_color; result_links[i].style.display = "block"; @@ -454,6 +522,7 @@ if (m < 0) return true; else { query.value = decodeURIComponent(node.href.substring(m+3)); + query.focus(); DoSearch(); return false; } @@ -464,8 +533,12 @@ function TogglePanel() { panel_shown = !panel_shown; if (panel_shown) { - document.getElementById("results_num_pref").value = results_num; - document.getElementById("type_delay_pref").value = type_delay; + document.getElementById("show_manuals_pref").selectedIndex + = show_manuals; + document.getElementById("show_manual_titles_pref").checked + = show_manual_titles; + document.getElementById("results_num_pref").value = results_num; + document.getElementById("type_delay_pref").value = type_delay; document.getElementById("highlight_color_pref").value = highlight_color; } panel.style.display = panel_shown ? "table-cell" : "none"; @@ -481,12 +554,30 @@ } hide_prefs = HidePanel; + function SetShowManuals(inp) { + if (inp.selectedIndex != show_manuals) { + show_manuals = inp.selectedIndex; + SetCookie("PLT_ManualSettings", show_manuals+(show_manual_titles?10:0)); + UpdateResults(); + } + } + set_show_manuals = SetShowManuals; + + function SetShowManualTitles(inp) { + if (inp.checked != show_manual_titles) { + show_manual_titles = inp.checked; + SetCookie("PLT_ManualSettings", show_manuals+(show_manual_titles?10:0)); + UpdateResults(); + } + } + set_show_manual_titles = SetShowManualTitles; + function SetResultsNum(inp) { var n = (parseInt(inp.value.replace(/[^0-9]+/g,"")) || results_num); inp.value = n; if (n != results_num) { results_num = n; - SetCookie("PLT_ResultsNum", n); + SetCookie("PLT_ResultsNum", results_num); AdjustResultsNum(); UpdateResults(); } @@ -498,7 +589,7 @@ inp.value = n; if (n != type_delay) { type_delay = n; - SetCookie("PLT_TypeDelay", n); + SetCookie("PLT_TypeDelay", type_delay); } } set_type_delay = SetTypeDelay; @@ -508,7 +599,7 @@ inp.value = c; if (c != highlight_color) { highlight_color = c; - SetCookie("PLT_HighlightColor", c); + SetCookie("PLT_HighlightColor", highlight_color); UpdateResults(); } }