From 7cea566a9616f1300cfc2728acf664ac5bd89bd8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 24 Jul 2023 13:58:09 +1000 Subject: Add search. - For mediawiki sites, use API search. - For non-mediawiki sites, use eww. - Now it depends on a new library `generic-search.el'. --- wiki-engine.el | 97 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) (limited to 'wiki-engine.el') diff --git a/wiki-engine.el b/wiki-engine.el index 242c6d4..b69f7ed 100644 --- a/wiki-engine.el +++ b/wiki-engine.el @@ -28,6 +28,7 @@ ;;; Code: (require 'wiki-utils) (require 'wiki-markup) +(require 'generic-search) ;; TODO: make this a defcustom (defvar wiki-default-engine 'mediawiki @@ -122,6 +123,10 @@ And switch to the corresponding buffer." ('oddmuse (error "API not supported for engine: %s" engine)) (_ (error "Unknown engine: %s" engine)))))) +(defun wiki-engine-compute-fetcher (site-info) + "Return :fetcher of SITE-INFO, or default." + (or (plist-get site-info :fetcher) 'wiki-engine-simple-fetch)) + (defun wiki-engine-wiki-url (site title) "Construct the url to fetch wiki of TITLE from SITE." (let* ((site-info (alist-get site wiki-sites)) @@ -165,12 +170,6 @@ API-BASE-URL is the base url for the api request." "%s/api.php?action=query&format=json&titles=%s&prop=revisions&rvprop=content&rvslots=main" api-base-url title))) -(defun wiki-engine-mediawiki-api-search (api-base-url query) - (wiki-url-fetch-json - (format - "%s/api.php?action=query&format=json&list=search&srsearch=%s" - api-base-url query))) - (defun wiki-engine-mediawiki-api-fetch (site-id title) "Fetch TITLE from site with SITE-ID using mediawiki api." (when (string-empty-p title) (setq title "Main Page")) @@ -227,24 +226,92 @@ DIR defaults to `default-directory'." (wiki-mode) (buffer-name))))) -(defmacro defun-wiki-fetchers () +(defmacro define-wiki-site-commands () "Defines all wiki fetcher functions." (cons 'progn (mapcar (lambda (pair) (pcase-let ((`(,id . ,info) pair)) (let ((engine-fetcher - (or (plist-get info :fetcher) - 'wiki-engine-simple-fetch))) - `(defun ,(wiki-site-fetcher id) (title) - (interactive ,(format "sFetch title for %s: " - (wiki-engine-compute-display-name - id info))) - (,engine-fetcher ',id title))))) + (wiki-engine-compute-fetcher info))) + `(progn + (defun ,(wiki-site-fetcher id) (title) + (interactive ,(format "sFetch title for %s: " + (wiki-engine-compute-display-name + id info))) + (,engine-fetcher ',id title)) + (defun ,(wiki-site-searcher id) (title) + (interactive ,(format "sSearch %s for: " + (wiki-engine-compute-display-name + id info))) + (wiki-engine-simple-search ',id title)))))) (seq-filter #'cdr wiki-sites) ))) -(defun-wiki-fetchers) +(define-wiki-site-commands) + +;; FIXME: make this work with local wiki, by using say grep-based +;; search. +(defun wiki-engine-simple-search (site-id query) + "Simple search of QUERY using eww with its default search. + +SITE-ID is the id of the site." + (let ((site-info (alist-get site-id wiki-sites))) + (pcase (wiki-engine-compute-engine site-info) + ('mediawiki (wiki-engine-mediawiki-search site-id query)) + ('local (error "Search not implemented for local engine yet" )) + (_ + (eww (format "%s site:%s" query + (plist-get (alist-get site-id wiki-sites) :host))))))) + +(defun wiki-engine-mediawiki-api-search (api-base-url query) + "Make an API call searching for QUERY. + +API-BASE-URL is the base url for the api request." + (wiki-url-fetch-json + (format + "%s/api.php?action=query&format=json&list=search&srsearch=%s" + api-base-url query))) + +(defun wiki-engine-mediawiki-search-action (site-id) + (lambda (info) + (interactive) + (funcall (wiki-site-fetcher site-id) (alist-get 'title info)))) + +(defun wiki-engine-mediawiki-search (site-id query) + (let ((api-base-url (wiki-engine-compute-api-base-url + (alist-get site-id wiki-sites)))) + (generic-search-open + (alist-get 'search + (alist-get 'query + (wiki-engine-mediawiki-api-search + api-base-url query))) + (format "%s-query:%s" site-id query) + `((formatter . wiki-engine-mediawiki-format-query-result) + (default-action . ,(wiki-engine-mediawiki-search-action + site-id)) + (keymap . ,my-wikipedia-button-keymap))))) + +(defun wiki-engine-mediawiki-format-query-result (result) + (concat + (format "%s (%d words)" + (alist-get 'title result) + (alist-get 'wordcount result)) + (propertize + (format "\n\n%s" + (wiki-mediawiki-highlight-snippet-matches + (alist-get 'snippet result))) + 'face 'default))) + +(defun wiki-mediawiki-highlight-snippet-matches (snippet) + (with-temp-buffer + (insert snippet) + (goto-char (point-min)) + (while (re-search-forward + "\\(.*?\\)" nil t) + (replace-match + (propertize (match-string 1) 'face 'match))) + (buffer-string))) (defun wiki-open-url (url) "Open the raw wiki corresponding to the URL of a html wiki page. -- cgit v1.2.3