Skip to content

Commit a88feab

Browse files
authored
Rollup merge of rust-lang#56332 - GuillaumeGomez:specifi-crate-search, r=QuietMisdreavus
[rustdoc] Specific crate search Reopening of rust-lang#54706. Fixes rust-lang#54616. <img width="1440" alt="screenshot 2018-11-29 at 01 29 11" src="https://user-images.githubusercontent.com/3050060/49191372-979adf80-f376-11e8-963e-e4feb927c1da.png"> r? @QuietMisdreavus
2 parents 3073c7a + 3f253f5 commit a88feab

File tree

10 files changed

+164
-26
lines changed

10 files changed

+164
-26
lines changed

src/librustdoc/html/layout.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
5757
{css_extension}\
5858
{favicon}\
5959
{in_header}\
60+
<style type=\"text/css\">\
61+
#crate-search{{background-image:url(\"{root_path}down-arrow{suffix}.svg\");}}\
62+
</style>\
6063
</head>\
6164
<body class=\"rustdoc {css_class}\">\
6265
<!--[if lte IE 8]>\
@@ -81,11 +84,16 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
8184
<nav class=\"sub\">\
8285
<form class=\"search-form js-only\">\
8386
<div class=\"search-container\">\
84-
<input class=\"search-input\" name=\"search\" \
85-
autocomplete=\"off\" \
86-
spellcheck=\"false\" \
87-
placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
88-
type=\"search\">\
87+
<div>\
88+
<select id=\"crate-search\">\
89+
<option value=\"All crates\">All crates</option>\
90+
</select>\
91+
<input class=\"search-input\" name=\"search\" \
92+
autocomplete=\"off\" \
93+
spellcheck=\"false\" \
94+
placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
95+
type=\"search\">\
96+
</div>\
8997
<a id=\"settings-menu\" href=\"{root_path}settings.html\">\
9098
<img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
9199
</a>\

src/librustdoc/html/render.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,8 @@ fn write_shared(
793793
static_files::BRUSH_SVG)?;
794794
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
795795
static_files::WHEEL_SVG)?;
796+
write(cx.dst.join(&format!("down-arrow{}.svg", cx.shared.resource_suffix)),
797+
static_files::DOWN_ARROW_SVG)?;
796798
write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
797799
static_files::themes::LIGHT,
798800
options.enable_minification)?;
@@ -1066,7 +1068,7 @@ themePicker.onblur = handleThemeButtonsBlur;
10661068
&[(minifier::js::Keyword::Null, "N")]),
10671069
&dst);
10681070
}
1069-
try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
1071+
try_err!(writeln!(&mut w, "initSearch(searchIndex);addSearchOptions(searchIndex);"), &dst);
10701072

10711073
if options.enable_index_page {
10721074
if let Some(index_page) = options.index_page.clone() {
Loading

src/librustdoc/html/static/main.js

+83-16
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,14 @@ if (!String.prototype.endsWith) {
218218
//
219219
// So I guess you could say things are getting pretty interoperable.
220220
function getVirtualKey(ev) {
221-
if ("key" in ev && typeof ev.key != "undefined")
221+
if ("key" in ev && typeof ev.key != "undefined") {
222222
return ev.key;
223+
}
223224

224225
var c = ev.charCode || ev.keyCode;
225-
if (c == 27)
226+
if (c == 27) {
226227
return "Escape";
228+
}
227229
return String.fromCharCode(c);
228230
}
229231

@@ -431,12 +433,13 @@ if (!String.prototype.endsWith) {
431433

432434
/**
433435
* Executes the query and builds an index of results
434-
* @param {[Object]} query [The user query]
435-
* @param {[type]} searchWords [The list of search words to query
436-
* against]
437-
* @return {[type]} [A search index of results]
436+
* @param {[Object]} query [The user query]
437+
* @param {[type]} searchWords [The list of search words to query
438+
* against]
439+
* @param {[type]} filterCrates [Crate to search in if defined]
440+
* @return {[type]} [A search index of results]
438441
*/
439-
function execQuery(query, searchWords) {
442+
function execQuery(query, searchWords, filterCrates) {
440443
function itemTypeFromName(typename) {
441444
for (var i = 0; i < itemTypes.length; ++i) {
442445
if (itemTypes[i] === typename) {
@@ -812,6 +815,9 @@ if (!String.prototype.endsWith) {
812815
{
813816
val = extractGenerics(val.substr(1, val.length - 2));
814817
for (var i = 0; i < nSearchWords; ++i) {
818+
if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
819+
continue;
820+
}
815821
var in_args = findArg(searchIndex[i], val, true);
816822
var returned = checkReturned(searchIndex[i], val, true);
817823
var ty = searchIndex[i];
@@ -866,6 +872,9 @@ if (!String.prototype.endsWith) {
866872
var output = extractGenerics(parts[1]);
867873

868874
for (var i = 0; i < nSearchWords; ++i) {
875+
if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
876+
continue;
877+
}
869878
var type = searchIndex[i].type;
870879
var ty = searchIndex[i];
871880
if (!type) {
@@ -937,11 +946,11 @@ if (!String.prototype.endsWith) {
937946
var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
938947

939948
for (j = 0; j < nSearchWords; ++j) {
940-
var lev_distance;
941949
var ty = searchIndex[j];
942-
if (!ty) {
950+
if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
943951
continue;
944952
}
953+
var lev_distance;
945954
var lev_add = 0;
946955
if (paths.length > 1) {
947956
var lev = checkPath(contains, paths[paths.length - 1], ty);
@@ -1326,7 +1335,7 @@ if (!String.prototype.endsWith) {
13261335
return '<div>' + text + ' <div class="count">(' + nbElems + ')</div></div>';
13271336
}
13281337

1329-
function showResults(results) {
1338+
function showResults(results, filterCrates) {
13301339
if (results['others'].length === 1 &&
13311340
getCurrentValue('rustdoc-go-to-only-result') === "true") {
13321341
var elem = document.createElement('a');
@@ -1344,8 +1353,13 @@ if (!String.prototype.endsWith) {
13441353
var ret_in_args = addTab(results['in_args'], query, false);
13451354
var ret_returned = addTab(results['returned'], query, false);
13461355

1356+
var filter = "";
1357+
if (filterCrates !== undefined) {
1358+
filter = " (in <b>" + filterCrates + "</b> crate)";
1359+
}
1360+
13471361
var output = '<h1>Results for ' + escape(query.query) +
1348-
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
1362+
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + filter + '</h1>' +
13491363
'<div id="titles">' +
13501364
makeTabHeader(0, "In Names", ret_others[1]) +
13511365
makeTabHeader(1, "In Parameters", ret_in_args[1]) +
@@ -1374,7 +1388,7 @@ if (!String.prototype.endsWith) {
13741388
printTab(currentTab);
13751389
}
13761390

1377-
function execSearch(query, searchWords) {
1391+
function execSearch(query, searchWords, filterCrates) {
13781392
var queries = query.raw.split(",");
13791393
var results = {
13801394
'in_args': [],
@@ -1385,7 +1399,7 @@ if (!String.prototype.endsWith) {
13851399
for (var i = 0; i < queries.length; ++i) {
13861400
var query = queries[i].trim();
13871401
if (query.length !== 0) {
1388-
var tmp = execQuery(getQuery(query), searchWords);
1402+
var tmp = execQuery(getQuery(query), searchWords, filterCrates);
13891403

13901404
results['in_args'].push(tmp['in_args']);
13911405
results['returned'].push(tmp['returned']);
@@ -1447,15 +1461,27 @@ if (!String.prototype.endsWith) {
14471461
}
14481462
}
14491463

1450-
function search(e) {
1464+
function getFilterCrates() {
1465+
var elem = document.getElementById("crate-search");
1466+
1467+
if (elem && elem.value !== "All crates" && rawSearchIndex.hasOwnProperty(elem.value)) {
1468+
return elem.value;
1469+
}
1470+
return undefined;
1471+
}
1472+
1473+
function search(e, forced) {
14511474
var params = getQueryStringParams();
14521475
var query = getQuery(search_input.value.trim());
14531476

14541477
if (e) {
14551478
e.preventDefault();
14561479
}
14571480

1458-
if (query.query.length === 0 || query.id === currentResults) {
1481+
if (query.query.length === 0) {
1482+
return;
1483+
}
1484+
if (forced !== true && query.id === currentResults) {
14591485
if (query.query.length > 0) {
14601486
putBackSearch(search_input);
14611487
}
@@ -1475,7 +1501,8 @@ if (!String.prototype.endsWith) {
14751501
}
14761502
}
14771503

1478-
showResults(execSearch(query, index));
1504+
var filterCrates = getFilterCrates();
1505+
showResults(execSearch(query, index, filterCrates), filterCrates);
14791506
}
14801507

14811508
function buildIndex(rawSearchIndex) {
@@ -1575,6 +1602,13 @@ if (!String.prototype.endsWith) {
15751602
};
15761603
search_input.onpaste = search_input.onchange;
15771604

1605+
var selectCrate = document.getElementById('crate-search');
1606+
if (selectCrate) {
1607+
selectCrate.onchange = function() {
1608+
search(undefined, true);
1609+
};
1610+
}
1611+
15781612
// Push and pop states are used to add search results to the browser
15791613
// history.
15801614
if (browserSupportsHistoryApi()) {
@@ -2323,6 +2357,39 @@ if (!String.prototype.endsWith) {
23232357
if (window.location.hash && window.location.hash.length > 0) {
23242358
expandSection(window.location.hash.replace(/^#/, ''));
23252359
}
2360+
2361+
function addSearchOptions(crates) {
2362+
var elem = document.getElementById('crate-search');
2363+
2364+
if (!elem) {
2365+
return;
2366+
}
2367+
var crates_text = [];
2368+
for (var crate in crates) {
2369+
if (crates.hasOwnProperty(crate)) {
2370+
crates_text.push(crate);
2371+
}
2372+
}
2373+
crates_text.sort(function(a, b) {
2374+
var lower_a = a.toLowerCase();
2375+
var lower_b = b.toLowerCase();
2376+
2377+
if (lower_a < lower_b) {
2378+
return -1;
2379+
} else if (lower_a > lower_b) {
2380+
return 1;
2381+
}
2382+
return 0;
2383+
});
2384+
for (var i = 0; i < crates_text.length; ++i) {
2385+
var option = document.createElement("option");
2386+
option.value = crates_text[i];
2387+
option.innerText = crates_text[i];
2388+
elem.appendChild(option);
2389+
}
2390+
}
2391+
2392+
window.addSearchOptions = addSearchOptions;
23262393
}());
23272394

23282395
// Sets the focus on the search bar at the top of the page

src/librustdoc/html/static/rustdoc.css

+26-2
Original file line numberDiff line numberDiff line change
@@ -620,27 +620,51 @@ a {
620620
.search-container {
621621
position: relative;
622622
}
623+
.search-container > div {
624+
display: inline-flex;
625+
width: calc(100% - 34px);
626+
}
627+
#crate-search {
628+
margin-top: 5px;
629+
padding: 6px;
630+
padding-right: 19px;
631+
border: 0;
632+
border-right: 0;
633+
border-radius: 4px 0 0 4px;
634+
outline: none;
635+
cursor: pointer;
636+
border-right: 1px solid;
637+
-moz-appearance: none;
638+
-webkit-appearance: none;
639+
/* Removes default arrow from firefox */
640+
text-indent: 0.01px;
641+
text-overflow: "";
642+
background-repeat: no-repeat;
643+
background-color: transparent;
644+
background-size: 16%;
645+
background-position: calc(100% - 1px) 56%;
646+
}
623647
.search-container > .top-button {
624648
position: absolute;
625649
right: 0;
626650
top: 10px;
627651
}
628652
.search-input {
629-
width: calc(100% - 34px);
630653
/* Override Normalize.css: we have margins and do
631654
not want to overflow - the `moz` attribute is necessary
632655
until Firefox 29, too early to drop at this point */
633656
-moz-box-sizing: border-box !important;
634657
box-sizing: border-box !important;
635658
outline: none;
636659
border: none;
637-
border-radius: 1px;
660+
border-radius: 0 1px 1px 0;
638661
margin-top: 5px;
639662
padding: 10px 16px;
640663
font-size: 17px;
641664
transition: border-color 300ms ease;
642665
transition: border-radius 300ms ease-in-out;
643666
transition: box-shadow 300ms ease-in-out;
667+
width: 100%;
644668
}
645669

646670
.search-input:focus {

src/librustdoc/html/static/themes/dark.css

+7-1
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,15 @@ a.test-arrow {
182182
color: #999;
183183
}
184184

185+
#crate-search {
186+
color: #111;
187+
background-color: #f0f0f0;
188+
border-color: #000;
189+
}
190+
185191
.search-input {
186192
color: #111;
187-
box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
193+
box-shadow: 1px 0 0 1px #000, 0 0 0 2px transparent;
188194
background-color: #f0f0f0;
189195
}
190196

src/librustdoc/html/static/themes/light.css

+8-1
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,16 @@ a.test-arrow {
182182
color: #999;
183183
}
184184

185+
#crate-search {
186+
color: #555;
187+
background-color: white;
188+
border-color: #e0e0e0;
189+
box-shadow: 0px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
190+
}
191+
185192
.search-input {
186193
color: #555;
187-
box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
194+
box-shadow: 1px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
188195
background-color: white;
189196
}
190197

src/librustdoc/html/static_files.rs

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
4545
/// The file contents of `wheel.svg`, the icon used for the settings button.
4646
pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
4747

48+
/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
49+
pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg");
50+
4851
/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
4952
/// output.
5053
pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");

src/test/rustdoc-js/filter-crate.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// exact-check
12+
13+
const QUERY = 'hashmap';
14+
const FILTER_CRATE = 'core';
15+
16+
const EXPECTED = {
17+
'others': [
18+
],
19+
};

src/tools/rustdoc-js/tester.js

+1
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ function main(argv) {
259259
'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
260260
const expected = loadedFile.EXPECTED;
261261
const query = loadedFile.QUERY;
262+
const filter_crate = loadedFile.FILTER_CRATE;
262263
const ignore_order = loadedFile.ignore_order;
263264
const exact_check = loadedFile.exact_check;
264265
const should_fail = loadedFile.should_fail;

0 commit comments

Comments
 (0)