Skip to content

Hugo-Heagren/easi

Repository files navigation

EASI: the Emacs Advanced Searching Interface

⚠️ THIS PROJECT IS IN A VERY EARLY STATE ⚠️

Overview

Easi lets you search multiple information sources at once—it is a federated search system in Emacs. Search engines or other sources of information are declared once in the init file and arbitrary groups can be used together. After searching, the results are collected together, sorted, and presented in Emacs. They can be viewed as a whole collection or individually, or both. Configurable and user-defined actions can be run on the results. Every aspect of Easi’s operation is meant to be highly configurable.

Installation

The project is not currently on MELPA or Gnu ELPA. You can install it manually, or with a helper like straight. A pure straight form might look like this:

(straight-use-package
 '(easi :type git :host github :repo "Hugo-Heagren/easi"))

Basic Configuration

Easi aggregates (‘federates’) results obtained by sending the same query to multiple search engines. When called interactively, it prompts for search engines to use from a customisable list easi-searchables. A searchable is any of:

  • an easi-search-engine object (the most basic searchable type)
  • an easi-search-engine-group object (when certain combinations of searchables are used together often, a group can be defined. The group is effectively an alias for just using them all as usual)
  • a list of searchables
  • a symbol whose value is a searchable

So if engine-foo and engine-bar are easi-search-engine s, and group-foo and group-bar are easi-search-engine-group s, all the following are valid searchables:

  • engine-foo
  • (engine-foo engine-bar)
  • (group-foo (engine-foo group-bar))
  • (engine-foo ((engine-foo) engine-bar) (group-foo group-bar))

The most important configuration is to populate ~easi-searchables~.

Easi is designed so that searchables can be defined and shared as Emacs packages. Eventually I might get round to doing that, but for now there aren’t any. As an example though, you might define a searchable like this:

 (require 'url)
 (require 'easi-result)

 (defun my/ddg-get-result-from-divs (divs)
   (cl-loop for div in divs
	     collect
	     (let* ((raw (easi--structured-object-get-field '(cdr 2 cdr) div))
		    (title (easi--structured-object-get-field
			    '(4 3 2) raw))
		    (url (easi--structured-object-get-field
			  '(8 1 "href" url-generic-parse-url url-path-and-query
			      cdr url-parse-query-string "uddg" car)
			  raw)))
	       `(("title" . ,title)
		 ("url" . ,url)))))

 (setq my/duckduckgo-search-engine
	(easi-search-engine-create
	 :name "DuckDuckGo"
	 :suggestions-getter "https://duckduckgo.com/ac/?q=%s&client=opensearch&type=list"
	 :suggestion-post-processor
	 '(easi-utils-get-http-body easi-utils-json-parse-with-lists 1)
	 :queryable-results-getter "https://html.duckduckgo.com/html/?q=%s&client=opensearch&type=list"
	 :results-post-processor
	 '(easi-utils-parse-html-body
	   2 20 9 3 3
	   cddr
	   (lambda (ls) (cl-delete-if #'stringp ls))
	   (lambda (ls) (butlast ls 3))
	   my/ddg-get-result-from-divs)
	 :field-aliases '(("id" . "url"))))

 (add-to-list 'easi-searchables 'my/duckduckgo-search-engine)

Usage

Easi’s main entry point is easi-search. Once easi-searchables is configured, call this function, select some search engines, and enter a query.

Prior art

This package was largely inspired by engine mode, and the search facilities in w3m. I am also indebted to the frankly astonishing documentation of SWIRL, the only other generic federated searching package I have found so far.

Releases

No releases published

Packages

No packages published