diff options
-rw-r--r-- | README.org | 6 | ||||
-rw-r--r-- | wiki-engine.el | 97 | ||||
-rw-r--r-- | wiki-utils.el | 21 | ||||
-rw-r--r-- | wiki.el | 2 |
4 files changed, 105 insertions, 21 deletions
@@ -47,18 +47,20 @@ Currently supported features: * Install and use :PROPERTIES: - :UPDATED: [2023-07-23 Sun 22:25] + :UPDATED: [2023-07-24 Mon 13:57] :END: Clone, require, M-x: #+begin_src shell +git clone https://g.ypei.me/generic-search.el.git git clone https://g.ypei.me/wiki.el.git #+end_src -Assuming you have cloned into =~/.emacs.d/lisp/wiki.el=, then +Assuming you have cloned into dirs under =~/.emacs.d/lisp=, then #+begin_src emacs-lisp +(add-to-list 'load-path "~/.emacs.d/lisp/generic-search.el") (add-to-list 'load-path "~/.emacs.d/lisp/wiki.el") (require 'wiki) #+end_src 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. diff --git a/wiki-utils.el b/wiki-utils.el index fd5a0bc..043602b 100644 --- a/wiki-utils.el +++ b/wiki-utils.el @@ -110,15 +110,30 @@ Assuming the current buffer to be a `url-retrieve' response buffer." "Alist of wiki sites. Each item is in the form of (identifier . properties), where -identifier is a symbol, and properties is a plist of the site. -One of the sites is (local), meaning a local filesystem.") - +identifier is a symbol, and properties is a plist of site +properties. One of the sites is (local), meaning a local +filesystem. + +The only mandatory field is `:host'. All other fields, i.e. +`:engine', `:base-url', `:api-base-url', `display-name' may be +computed from `wiki-engine-compute-engine', +`wiki-engine-compute-base-url', +`wiki-engine-compute-api-base-url', or +`wiki-engine-compute-display-name'.") + +;; FIXME: does it make sense to fallback to wiki-find-file here? (defun wiki-site-fetcher (site-id) "Return the fetcher function for wiki site with SITE-ID." (if site-id (intern (format "wiki-%s-fetch" site-id)) 'wiki-find-file)) +(defun wiki-site-searcher (site-id) + "Return the fetcher function for wiki site with SITE-ID." + (if site-id + (intern (format "wiki-%s-search" site-id)) + (error "Unknown site id: %s" site-id))) + (defvar wiki-client-buffer-name "*wiki api*" "Name of the buffer recording wiki API calls.") @@ -7,7 +7,7 @@ ;; Created: 2023 ;; Version: 0 ;; Keywords: wiki, markup -;; Package-Requires: ((emacs "28")) +;; Package-Requires: ((emacs "28") (generic-search "0")) ;; Package-Type: multi ;; Homepage: https://g.ypei.me/wiki.el.git |