Source code for zelfred.gallery.e04_google_search_with_suggestion

# -*- coding: utf-8 -*-

"""
Feature:

The user types a query and receives a dropdown list of Google search suggestions.
The user can then tap "Enter" to perform a Google search in their web browser.

Difficulty: Medium

Dependencies:

.. code-block:: bash

    pip install requests

Demo: https://asciinema.org/a/616014
"""

import typing as T
import dataclasses

# we need this to parse google search API response
import xml.etree.ElementTree as ET

# we need this to send HTTP request
import requests
import zelfred.api as zf


[docs]@dataclasses.dataclass class Item(zf.Item):
[docs] def enter_handler(self, ui: zf.UI): """ Open the url in default web browser. """ zf.open_url(self.arg)
[docs]def encode_query(query: str) -> str: """ Encode the query to be used in the url. """ return query.replace(" ", "+")
[docs]class GoogleComplete: """ Google complete API caller and parser. """ google_complete_endpoint = ( "https://www.google.com/complete/search?output=toolbar&q={query}" ) def _encode_endpoint(self, query: str) -> str: """ :return: full api url. """ query = "+".join([s for s in query.split(" ") if s.strip()]) return self.google_complete_endpoint.format(query=query) def _parse_response(self, html: str) -> T.List[str]: """ :return: list of suggestions. """ root = ET.fromstring(html) suggestion_list = list() for suggestion in root.iter("suggestion"): suggestion_list.append(suggestion.attrib["data"]) return suggestion_list
[docs] def get(self, query: str) -> T.List[str]: """ :return: list of suggestions. """ url = self._encode_endpoint(query) html = requests.get(url).text suggestion_list = self._parse_response(html) return suggestion_list
google_complete = GoogleComplete()
[docs]def handler(query: str, ui: zf.UI): """ The handler is the core of a Zelfred App. It's a user-defined function that takes the entered query and the UI object as inputs and returns a list of items to render. """ # if query is empty, return the full list in the original order if bool(query) is False: return [ Item( title="type something to search in google", ) ] # if query is not empty else: suggestion_list = google_complete.get(query) return [ Item( title=s, subtitle=f"hit 'Enter' to Google search {s!r} in web browser", uid=s, autocomplete=s, # store google search url in arg, so we can access it in enter_handler arg=f"https://www.google.com/search?q={encode_query(s)}", ) for s in suggestion_list ]
if __name__ == "__main__": # reset the debugger and enable it zf.debugger.reset() zf.debugger.enable() # create the UI and run it ui = zf.UI(handler=handler, capture_error=True) ui.run()