diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index aac5d0d2601de..583c9f2b67144 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -37,128 +37,116 @@ pub fn render<T: fmt::Display, S: fmt::Display>( -> io::Result<()> { write!(dst, -r##"<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="generator" content="rustdoc"> - <meta name="description" content="{description}"> - <meta name="keywords" content="{keywords}"> - - <title>{title}</title> - - <link rel="stylesheet" type="text/css" href="{root_path}normalize{suffix}.css"> - <link rel="stylesheet" type="text/css" href="{root_path}rustdoc{suffix}.css" - id="mainThemeStyle"> - {themes} - <link rel="stylesheet" type="text/css" href="{root_path}dark{suffix}.css"> - <link rel="stylesheet" type="text/css" href="{root_path}light{suffix}.css" id="themeStyle"> - <script src="{root_path}storage{suffix}.js"></script> - {css_extension} - - {favicon} - {in_header} -</head> -<body class="rustdoc {css_class}"> - <!--[if lte IE 8]> - <div class="warning"> - This old browser is unsupported and will most likely display funky - things. - </div> - <![endif]--> - - {before_content} - - <nav class="sidebar"> - <div class="sidebar-menu">☰</div> - {logo} - {sidebar} - </nav> - - <div class="theme-picker"> - <button id="theme-picker" aria-label="Pick another theme!"> - <img src="{root_path}brush{suffix}.svg" width="18" alt="Pick another theme!"> - </button> - <div id="theme-choices"></div> - </div> - <script src="{root_path}theme{suffix}.js"></script> - <nav class="sub"> - <form class="search-form js-only"> - <div class="search-container"> - <input class="search-input" name="search" - autocomplete="off" - placeholder="Click or press ‘S’ to search, ‘?’ for more options…" - type="search"> - </div> - </form> - </nav> - - <section id='main' class="content">{content}</section> - <section id='search' class="content hidden"></section> - - <section class="footer"></section> - - <aside id="help" class="hidden"> - <div> - <h1 class="hidden">Help</h1> - - <div class="shortcuts"> - <h2>Keyboard Shortcuts</h2> - - <dl> - <dt><kbd>?</kbd></dt> - <dd>Show this help dialog</dd> - <dt><kbd>S</kbd></dt> - <dd>Focus the search field</dd> - <dt><kbd>↑</kbd></dt> - <dd>Move up in search results</dd> - <dt><kbd>↓</kbd></dt> - <dd>Move down in search results</dd> - <dt><kbd>↹</kbd></dt> - <dd>Switch tab</dd> - <dt><kbd>⏎</kbd></dt> - <dd>Go to active search result</dd> - <dt><kbd>+</kbd></dt> - <dd>Expand all sections</dd> - <dt><kbd>-</kbd></dt> - <dd>Collapse all sections</dd> - </dl> - </div> - - <div class="infos"> - <h2>Search Tricks</h2> - - <p> - Prefix searches with a type followed by a colon (e.g. - <code>fn:</code>) to restrict the search to a given type. - </p> - - <p> - Accepted types are: <code>fn</code>, <code>mod</code>, - <code>struct</code>, <code>enum</code>, - <code>trait</code>, <code>type</code>, <code>macro</code>, - and <code>const</code>. - </p> - - <p> - Search functions by type signature (e.g. - <code>vec -> usize</code> or <code>* -> vec</code>) - </p> - </div> - </div> - </aside> - - {after_content} - - <script> - window.rootPath = "{root_path}"; - window.currentCrate = "{krate}"; - </script> - <script src="{root_path}main{suffix}.js"></script> - <script defer src="{root_path}search-index.js"></script> -</body> -</html>"##, +"<!DOCTYPE html>\ +<html lang=\"en\">\ +<head>\ + <meta charset=\"utf-8\">\ + <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\ + <meta name=\"generator\" content=\"rustdoc\">\ + <meta name=\"description\" content=\"{description}\">\ + <meta name=\"keywords\" content=\"{keywords}\">\ + <title>{title}</title>\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}normalize{suffix}.css\">\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}rustdoc{suffix}.css\" \ + id=\"mainThemeStyle\">\ + {themes}\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}dark{suffix}.css\">\ + <link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \ + id=\"themeStyle\">\ + <script src=\"{root_path}storage{suffix}.js\"></script>\ + {css_extension}\ + {favicon}\ + {in_header}\ +</head>\ +<body class=\"rustdoc {css_class}\">\ + <!--[if lte IE 8]>\ + <div class=\"warning\">\ + This old browser is unsupported and will most likely display funky \ + things.\ + </div>\ + <![endif]-->\ + {before_content}\ + <nav class=\"sidebar\">\ + <div class=\"sidebar-menu\">☰</div>\ + {logo}\ + {sidebar}\ + </nav>\ + <div class=\"theme-picker\">\ + <button id=\"theme-picker\" aria-label=\"Pick another theme!\">\ + <img src=\"{root_path}brush{suffix}.svg\" width=\"18\" alt=\"Pick another theme!\">\ + </button>\ + <div id=\"theme-choices\"></div>\ + </div>\ + <script src=\"{root_path}theme{suffix}.js\"></script>\ + <nav class=\"sub\">\ + <form class=\"search-form js-only\">\ + <div class=\"search-container\">\ + <input class=\"search-input\" name=\"search\" \ + autocomplete=\"off\" \ + placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \ + type=\"search\">\ + </div>\ + </form>\ + </nav>\ + <section id=\"main\" class=\"content\">{content}</section>\ + <section id=\"search\" class=\"content hidden\"></section>\ + <section class=\"footer\"></section>\ + <aside id=\"help\" class=\"hidden\">\ + <div>\ + <h1 class=\"hidden\">Help</h1>\ + <div class=\"shortcuts\">\ + <h2>Keyboard Shortcuts</h2>\ + <dl>\ + <dt><kbd>?</kbd></dt>\ + <dd>Show this help dialog</dd>\ + <dt><kbd>S</kbd></dt>\ + <dd>Focus the search field</dd>\ + <dt><kbd>↑</kbd></dt>\ + <dd>Move up in search results</dd>\ + <dt><kbd>↓</kbd></dt>\ + <dd>Move down in search results</dd>\ + <dt><kbd>↹</kbd></dt>\ + <dd>Switch tab</dd>\ + <dt><kbd>⏎</kbd></dt>\ + <dd>Go to active search result</dd>\ + <dt><kbd>+</kbd></dt>\ + <dd>Expand all sections</dd>\ + <dt><kbd>-</kbd></dt>\ + <dd>Collapse all sections</dd>\ + </dl>\ + </div>\ + <div class=\"infos\">\ + <h2>Search Tricks</h2>\ + <p>\ + Prefix searches with a type followed by a colon (e.g. \ + <code>fn:</code>) to restrict the search to a given type.\ + </p>\ + <p>\ + Accepted types are: <code>fn</code>, <code>mod</code>, \ + <code>struct</code>, <code>enum</code>, \ + <code>trait</code>, <code>type</code>, <code>macro</code>, \ + and <code>const</code>.\ + </p>\ + <p>\ + Search functions by type signature (e.g. \ + <code>vec -> usize</code> or <code>* -> vec</code>)\ + </p>\ + <p>\ + Search multiple things at once by splitting your query with comma (e.g. \ + <code>str,u8</code> or <code>String,struct:Vec,test</code>)\ + </p>\ + </div>\ + </div>\ + </aside>\ + {after_content}\ + <script>\ + window.rootPath = \"{root_path}\";\ + window.currentCrate = \"{krate}\";\ + </script>\ + <script src=\"{root_path}main{suffix}.js\"></script>\ + <script defer src=\"{root_path}search-index.js\"></script>\ +</body>\ +</html>", css_extension = if css_file_extension { format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme{suffix}.css\">", root_path = page.root_path, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 3a3fa833c238b..2546a9410a9f6 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1299,14 +1299,78 @@ printTab(currentTab); } + function execSearch(query, searchWords) { + var queries = query.raw.split(","); + var results = { + 'in_args': [], + 'returned': [], + 'others': [], + }; + + for (var i = 0; i < queries.length; ++i) { + var query = queries[i].trim(); + if (query.length !== 0) { + var tmp = execQuery(getQuery(query), searchWords); + + results['in_args'].push(tmp['in_args']); + results['returned'].push(tmp['returned']); + results['others'].push(tmp['others']); + } + } + if (queries.length > 1) { + function getSmallest(arrays, positions) { + var start = null; + + for (var it = 0; it < positions.length; ++it) { + if (arrays[it].length > positions[it] && + (start === null || start > arrays[it][positions[it]].lev)) { + start = arrays[it][positions[it]].lev; + } + } + return start; + } + + function mergeArrays(arrays) { + var ret = []; + var positions = []; + + for (var x = 0; x < arrays.length; ++x) { + positions.push(0); + } + while (ret.length < MAX_RESULTS) { + var smallest = getSmallest(arrays, positions); + if (smallest === null) { + break; + } + for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) { + if (arrays[x].length > positions[x] && + arrays[x][positions[x]].lev === smallest) { + ret.push(arrays[x][positions[x]]); + positions[x] += 1; + } + } + } + return ret; + } + + return { + 'in_args': mergeArrays(results['in_args']), + 'returned': mergeArrays(results['returned']), + 'others': mergeArrays(results['others']), + }; + } else { + return { + 'in_args': results['in_args'][0], + 'returned': results['returned'][0], + 'others': results['others'][0], + }; + } + } + function search(e) { - var query, - obj, i, len, - results = {"in_args": [], "returned": [], "others": []}, - resultIndex; var params = getQueryStringParams(); + var query = getQuery(document.getElementsByClassName('search-input')[0].value); - query = getQuery(document.getElementsByClassName('search-input')[0].value); if (e) { e.preventDefault(); } @@ -1328,8 +1392,7 @@ } } - results = execQuery(query, index); - showResults(results); + showResults(execSearch(query, index)); } function buildIndex(rawSearchIndex) { diff --git a/src/test/rustdoc-js/multi-query.js b/src/test/rustdoc-js/multi-query.js new file mode 100644 index 0000000000000..3793ca6599c5f --- /dev/null +++ b/src/test/rustdoc-js/multi-query.js @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const QUERY = 'str,u8'; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'str' }, + { 'path': 'std', 'name': 'u8' }, + { 'path': 'std::ffi', 'name': 'CStr' }, + { 'path': 'std::simd', 'name': 'u8x2' }, + ], +}; diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 7c9ee2a49430b..1e6c4336a9e99 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -157,7 +157,8 @@ function main(argv) { // execQuery first parameter is built in getQuery (which takes in the search input). // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index. - var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery"]; + var functionsToLoad = ["levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery", + "execSearch"]; finalJS += 'window = { "currentCrate": "std" };\n'; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); @@ -174,7 +175,7 @@ function main(argv) { 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; - var results = loaded.execQuery(loaded.getQuery(query), index); + var results = loaded.execSearch(loaded.getQuery(query), index); process.stdout.write('Checking "' + file + '" ... '); var error_text = []; for (var key in expected) {