{"id":13653295,"url":"https://github.com/hrs/engine-mode","last_synced_at":"2025-04-09T08:07:36.813Z","repository":{"id":16746393,"uuid":"19503921","full_name":"hrs/engine-mode","owner":"hrs","description":"Minor mode for defining and querying search engines through Emacs.","archived":false,"fork":false,"pushed_at":"2024-09-25T01:22:19.000Z","size":642,"stargazers_count":275,"open_issues_count":3,"forks_count":23,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-02T06:17:18.728Z","etag":null,"topics":["emacs","search"],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hrs.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-05-06T17:35:00.000Z","updated_at":"2025-01-28T16:06:08.000Z","dependencies_parsed_at":"2023-01-11T19:25:48.585Z","dependency_job_id":"a321e71c-1e45-477d-9df8-faad686d363f","html_url":"https://github.com/hrs/engine-mode","commit_stats":{"total_commits":92,"total_committers":17,"mean_commits":5.411764705882353,"dds":0.3586956521739131,"last_synced_commit":"e7f317f1b284853b6df4dfd37ab7715b248e0ebd"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Fengine-mode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Fengine-mode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Fengine-mode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrs%2Fengine-mode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hrs","download_url":"https://codeload.github.com/hrs/engine-mode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247999859,"owners_count":21031046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","search"],"created_at":"2024-08-02T02:01:08.357Z","updated_at":"2025-04-09T08:07:36.788Z","avatar_url":"https://github.com/hrs.png","language":"Emacs Lisp","funding_links":[],"categories":["Emacs Lisp"],"sub_categories":[],"readme":"#+title: =engine-mode=\n#+options: toc:nil num:nil\n\n[[https://melpa.org/#/engine-mode][https://melpa.org/packages/engine-mode-badge.svg]]\n[[https://stable.melpa.org/#/engine-mode][https://stable.melpa.org/packages/engine-mode-badge.svg]]\n[[https://www.gnu.org/licenses/gpl-3.0][https://img.shields.io/badge/License-GPL%20v3-blue.svg]]\n[[https://github.com/hrs/engine-mode/actions/workflows/test.yml][https://github.com/hrs/engine-mode/actions/workflows/test.yml/badge.svg?branch=main]]\n\n~engine-mode~ is a global minor mode for Emacs. It enables you to easily define\nsearch engines, bind them to keybindings, and query them from the comfort of\nyour editor.\n\n#+ATTR_HTML: :alt Demo searching for a term, with the results opening in a browser window.\n#+ATTR_HTML: :width 100%\n[[file:./doc/demo.gif]]\n\nFor example, suppose we want to be able to easily search GitHub:\n\n#+begin_src emacs-lisp\n  (defengine github\n    \"https://github.com/search?ref=simplesearch\u0026q=%s\")\n#+end_src\n\nThis defines an interactive function ~engine/search-github~. When executed it will\ntake the selected region (or prompt for input, if no region is selected) and\nsearch GitHub for it, displaying the results in your default browser.\n\nThe ~defengine~ macro can also take an optional key combination, prefixed with\n~engine/keymap-prefix~ (which defaults to =C-x /=). That keybinding will be wrapped\nin a call to ~kbd~.\n\n#+begin_src emacs-lisp\n  (defengine duckduckgo\n    \"https://duckduckgo.com/?q=%s\"\n    :keybinding \"d\")\n#+end_src\n\n=C-x / d= is now bound to the new function ~engine/search-duckduckgo~! Nifty.\n\nIf you'd like to see a video on the whys and wherefores of this mode, check out\n[[https://www.youtube.com/watch?v=MBhJBMYfWUo][the talk @hrs gave at EmacsNYC]].\n\n** Installation\n\n~engine-mode~ is available on MELPA.\n\nUsing ~use-package~:\n\n#+begin_src emacs-lisp\n  (use-package engine-mode\n    :ensure t\n\n    :config\n    (engine-mode t))\n#+end_src\n\nYou can also install it like any other elisp file by adding it to your load path\nand globally enabling it:\n\n#+begin_src emacs-lisp\n  (require 'engine-mode)\n  (engine-mode t)\n#+end_src\n\n** Changing your default browser\n\n~engine-mode~ uses the ~engine/browser-function~ variable to determine which browser\nit should use to open the URL it constructs. To change the default browser,\nredefine ~engine/browser-function~. For example, to always use Emacs' built-in ~eww~\nbrowser:\n\n#+begin_src emacs-lisp\n  (setq engine/browser-function 'eww-browse-url)\n#+end_src\n\n~engine/browser-function~ defaults to ~browse-url-browser-function~, which Emacs\nuses globally to open links.\n\nThe implementation of the ~browse-url-browser-function~ variable contains a\ncomprehensive list of possible browser functions. You can get to that by hitting\n=C-h v browse-url-browser-function \u003cRETURN\u003e= and following the link to\n=browse-url.el=.\n\n** Changing your browser on a per-engine basis\n\nTo only change the browser for a single engine, use the ~:browser~ keyword\nargument when you define the engine. For example, to use ~eww~ only for your\nGitHub search results, try:\n\n#+begin_src emacs-lisp\n  (defengine github\n    \"https://github.com/search?ref=simplesearch\u0026q=%s\"\n    :browser 'eww-browse-url)\n#+end_src\n\nAs mentioned about, see the implementation of the ~browse-url-browser-function~\nfor a definitive list of browsers.\n\n** Changing the keymap prefix\n\nThe default keymap prefix for ~engine-mode~ is =C-x /=. If you'd like to bind\nthe keymap to an additional prefix (say, =C-c s=), you totally can:\n\n#+begin_src emacs-lisp\n  (engine/set-keymap-prefix (kbd \"C-c s\"))\n#+end_src\n\nIf you use ~use-package~, you can achieve the same thing with:\n\n#+begin_src emacs-lisp\n  :bind-keymap (\"C-c s\" . engine-mode-prefixed-map)\n#+end_src\n\n** Custom docstrings\n\n~defengine~ assigns each engine a reasonable default docstring, but you can\noverride that on a case-by-case basis with the ~:docstring~ keyword argument:\n\n#+begin_src emacs-lisp\n  (defengine ctan\n    \"https://www.ctan.org/search/?x=1\u0026PORTAL=on\u0026phrase=%s\"\n    :docstring \"Search the Comprehensive TeX Archive Network (ctan.org)\")\n#+end_src\n\n** Modifying the search term before sending it\n\nAn engine might want to transform a search term in some way before it\ninterpolates the term into the URL. Maybe the term should have a different\nencoding, or be capitalized differently, or, uh, be passed through [[https://en.wikipedia.org/wiki/ROT13][ROT13]].\nWhatever the reason, you can apply a custom transformation to a search term by\npassing a function to ~defengine~ through the ~:term-transformation-hook~ keyword\nargument.\n\nFor example, to UPCASE all of your DuckDuckGo searches:\n\n#+begin_src emacs-lisp\n  (defengine duckduckgo\n    \"https://duckduckgo.com/?q=%s\"\n    :term-transformation-hook upcase)\n#+end_src\n\nOr, to ensure that all your queries are encoded as latin-1:\n\n#+begin_src emacs-lisp\n  (defengine diec2\n    \"dlc.iec.cat/results.asp?txtEntrada=%s\"\n    :term-transformation-hook (lambda (term) (encode-coding-string term latin-1))\n    :keybinding \"c\")\n#+end_src\n\nYou could also use a ~:term-transformation-hook~ to make an engine behave\ndifferently when given a [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Prefix-Command-Arguments.html][prefix argument]] (i.e. typing =C-u= before invoking the\nengine).\n\nSome search engines support querying for exact phrases by enclosing the search\nstring with double quotes. Transformations could be useful in this case to\nperform a literal search instead if the universal argument is present:\n\n#+begin_src emacs-lisp\n  (defengine duckduckgo\n    \"https://duckduckgo.com/?q=%s\"\n    :term-transformation-hook (lambda (term) (if current-prefix-arg\n                                            (concat \"\\\"\" term \"\\\"\")\n                                          term))\n    :keybinding \"d\")\n#+end_src\n\nTyping =C-x / d= will perform a regular search, but typing =C-u C-x / d= will\nwrap your query in quotes before searching for it. That's especially useful when\nsearching for the contents of the region.\n\n** Importing keyword searches from other browsers\n\nSince many browsers save keyword searches using the same format as engine-mode\n(that is, by using ~%s~ in a url to indicate a search term), it's not too hard to\nimport them into Emacs.\n\n[[https://github.com/sshaw][@sshaw]] has written a script to [[https://gist.github.com/sshaw/9b635eabde582ebec442][import from Chrome on OS X]]. Thanks for that!\n\n** Comparison with =webjump=\n\nEmacs has a perfectly lovely built-in =webjump= package which allows the user to\ndefine a set of URLs, interpolate search terms into them, and visit them in the\nbrowser.\n\nWhy might you use =engine-mode= instead of =webjump=?\n\n- You want to bind specific searches to keybindings. Because =engine-mode= defines\n  a function for each engine, keybindings in =engine-mode= can be associated\n  directly with specific searches.\n- You'd like to associate browser functions with engines on a case-by-case\n  basis. For example, if you want to perform some searches in Firefox, and other\n  searches in =eww=, that's trivial in =engine-mode=.\n- You like some of =engine-mode='s minor UI conveniences. If you've got a region\n  selected, for example, =engine-mode= will use that as the search query, while\n  =webjump= will ignore it and offer an empty prompt.\n\nIf you're not interested in these features, =webjump= is a great choice! Honestly,\nthe author of =engine-mode= probably wouldn't have bothered writing it if they'd\nknown =webjump= existed at the time. :sweat_smile:\n\n** Engine examples\n\n#+begin_src emacs-lisp\n  (defengine amazon\n    \"https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps\u0026field-keywords=%s\")\n\n  (defengine duckduckgo\n    \"https://duckduckgo.com/?q=%s\"\n    :keybinding \"d\")\n\n  (defengine github\n    \"https://github.com/search?ref=simplesearch\u0026q=%s\")\n\n  (defengine google\n    \"https://www.google.com/search?ie=utf-8\u0026oe=utf-8\u0026q=%s\"\n    :keybinding \"g\")\n\n  (defengine google-images\n    \"https://www.google.com/images?hl=en\u0026source=hp\u0026biw=1440\u0026bih=795\u0026gbv=2\u0026aq=f\u0026aqi=\u0026aql=\u0026oq=\u0026q=%s\")\n\n  (defengine google-maps\n    \"https://maps.google.com/maps?q=%s\"\n    :docstring \"Mappin' it up.\")\n\n  (defengine project-gutenberg\n    \"https://www.gutenberg.org/ebooks/search/?query=%s\")\n\n  (defengine qwant\n    \"https://www.qwant.com/?q=%s\")\n\n  (defengine stack-overflow\n    \"https://stackoverflow.com/search?q=%s\")\n\n  (defengine twitter\n    \"https://twitter.com/search?q=%s\")\n\n  (defengine wikipedia\n    \"https://www.wikipedia.org/search-redirect.php?language=en\u0026go=Go\u0026search=%s\"\n    :keybinding \"w\"\n    :docstring \"Searchin' the wikis.\")\n\n  (defengine wiktionary\n    \"https://www.wikipedia.org/search-redirect.php?family=wiktionary\u0026language=en\u0026go=Go\u0026search=%s\")\n\n  (defengine wolfram-alpha\n    \"https://www.wolframalpha.com/input/?i=%s\")\n\n  (defengine youtube\n    \"https://www.youtube.com/results?aq=f\u0026oq=\u0026search_query=%s\")\n#+end_src\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrs%2Fengine-mode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhrs%2Fengine-mode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrs%2Fengine-mode/lists"}