aboutsummaryrefslogtreecommitdiff
path: root/wiki-engine.el
diff options
context:
space:
mode:
authorYuchen Pei <id@ypei.org>2023-07-24 13:58:09 +1000
committerYuchen Pei <id@ypei.org>2023-07-24 13:58:09 +1000
commit7cea566a9616f1300cfc2728acf664ac5bd89bd8 (patch)
treeae65e5d7d160bca38a6783f791a3ac8dbc620aa0 /wiki-engine.el
parent78672bd3ccd71e36cd99d57b244213a37a8bf32e (diff)
Add search.
- For mediawiki sites, use API search. - For non-mediawiki sites, use eww. - Now it depends on a new library `generic-search.el'.
Diffstat (limited to 'wiki-engine.el')
-rw-r--r--wiki-engine.el97
1 files changed, 82 insertions, 15 deletions
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
+ "<span class=\"searchmatch\">\\(.*?\\)</span>" 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.