bpo-34398: Allow glossary results to show up on search page (GH-8773)

diff --git a/Doc/conf.py b/Doc/conf.py
index 079d177..6b88c23 100644
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -15,8 +15,7 @@
 
 extensions = ['sphinx.ext.coverage', 'sphinx.ext.doctest',
               'pyspecific', 'c_annotations', 'escape4chm',
-              'asdl_highlight', 'peg_highlight']
-
+              'asdl_highlight', 'peg_highlight', 'glossary_search']
 
 doctest_global_setup = '''
 try:
diff --git a/Doc/tools/extensions/glossary_search.py b/Doc/tools/extensions/glossary_search.py
new file mode 100644
index 0000000..34d227d
--- /dev/null
+++ b/Doc/tools/extensions/glossary_search.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+    glossary_search.py
+    ~~~~~~~~~~~~~~~~
+
+    Feature search results for glossary items prominently.
+
+    :license: Python license.
+"""
+from os import path
+from sphinx.addnodes import glossary
+from sphinx.util import logging
+from docutils.nodes import definition_list_item
+import json
+
+
+logger = logging.getLogger(__name__)
+
+
+def process_glossary_nodes(app, doctree, fromdocname):
+    if app.builder.format != 'html':
+        return
+
+    terms = {}
+
+    for node in doctree.traverse(glossary):
+        for glossary_item in node.traverse(definition_list_item):
+            term = glossary_item[0].astext().lower()
+            definition = glossary_item[1]
+
+            rendered = app.builder.render_partial(definition)
+            terms[term] = {
+                'title': glossary_item[0].astext(),
+                'body': rendered['html_body']
+            }
+
+    if hasattr(app.env, 'glossary_terms'):
+        app.env.glossary_terms.update(terms)
+    else:
+        app.env.glossary_terms = terms
+
+def on_build_finish(app, exc):
+    if not hasattr(app.env, 'glossary_terms'):
+        return
+    if not app.env.glossary_terms:
+        return
+
+    logger.info('Writing glossary.json', color='green')
+    with open(path.join(app.outdir, '_static', 'glossary.json'), 'w') as f:
+        json.dump(app.env.glossary_terms, f)
+
+
+def setup(app):
+    app.connect('doctree-resolved', process_glossary_nodes)
+    app.connect('build-finished', on_build_finish)
+
+    return {'version': '0.1', 'parallel_read_safe': True}
diff --git a/Doc/tools/templates/search.html b/Doc/tools/templates/search.html
new file mode 100644
index 0000000..cf20c2e
--- /dev/null
+++ b/Doc/tools/templates/search.html
@@ -0,0 +1,48 @@
+{% extends "!search.html" %}
+{% block extrahead %}
+    {{ super() }}
+    <script type="text/javascript">
+        var GLOSSARY_PAGE = 'glossary.html';
+
+        jQuery(function() {
+            $.getJSON("_static/glossary.json", function(glossary) {
+                var RESULT_TEMPLATE = '<div style="display: none" class="admonition seealso" id="glossary-result">' + 
+                                      '  <p class="topic-title">' +
+                                      '    <a class="glossary-title" href="#"></a>' +
+                                      '  </p>' +
+                                      '  <div class="glossary-body"></div>' +
+                                      '</div>';
+                $("#search-results").prepend(RESULT_TEMPLATE);
+
+                var params = $.getQueryParameters();
+                if (params.q) {
+                    var search_param = params.q[0].toLowerCase();
+                    var glossary_item = glossary[search_param];
+                    if (glossary_item) {
+                        var resultDiv = $("#glossary-result");
+                        
+                        // set up the title text with a link to the glossary page
+                        resultDiv.find(".glossary-title").text('Glossary: ' + glossary_item.title);
+                        var link_target = search_param.replace(/ /g, '-');
+                        resultDiv.find(".glossary-title").attr(
+                            'href', GLOSSARY_PAGE + '#term-' + link_target
+                        );
+
+                        // rewrite any anchor links (to other glossary terms)
+                        // to have a full reference to the glossary page
+                        var body = $(glossary_item.body).children();
+                        body.find("a[href^='#']").each(function() {
+                            var current_url = $(this).attr('href');
+                            $(this).attr('href', GLOSSARY_PAGE + current_url);
+                        });
+                        resultDiv.find(".glossary-body").html(body);
+
+                        resultDiv.show();
+                    } else {
+                        $("#glossary-result").hide('');
+                    }
+                }
+            });
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/Misc/NEWS.d/next/Documentation/2019-03-04-18-51-21.bpo-34398.YedUqW.rst b/Misc/NEWS.d/next/Documentation/2019-03-04-18-51-21.bpo-34398.YedUqW.rst
new file mode 100644
index 0000000..4693cec
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2019-03-04-18-51-21.bpo-34398.YedUqW.rst
@@ -0,0 +1,2 @@
+Prominently feature listings from the glossary in documentation search
+results. Patch by Ammar Askar.