(car (elquery-$ ".book__list" html)))))))
(elquery-children (first (elquery-$ ".book__list" html)))))))
:error (cl-function
(lambda (&rest args &key error-thrown &allow-other-keys)
(message "Function kiwix-get-libraries error.")))
:success (cl-function
(lambda (&key _data &allow-other-keys)
_data))
:status-code '((404 . (lambda (&rest _) (message (format "Endpoint %s does not exist." url))))
(500 . (lambda (&rest _) (message (format "Error from %s." url))))))))
;; ZIM library files on local host, parse directory files.
((or (eq kiwix-server-type 'kiwix-serve-local)
(eq kiwix-server-type 'docker-local))
(when (and (file-directory-p kiwix-zim-dir) (file-readable-p kiwix-zim-dir))
(setq kiwix-libraries
(mapcar #'kiwix--get-library-name
(directory-files kiwix-zim-dir nil ".*\\.zim\\'")))))))
(defun kiwix-select-library (&optional filter)
"Select Kiwix library name."
(kiwix-get-libraries)
(completing-read "Kiwix library: " kiwix-libraries nil t filter))
(defcustom kiwix-mode-prefix nil
"Specify kiwix-mode keybinding prefix before loading."
:type 'kbd)
(defvar kiwix--server-process nil
"Local server process launched by ‘kiwix-launch-server’.")
;; launch Kiwix server
;;;###autoload
(defun kiwix-launch-server ()
"Launch Kiwix server."
(interactive)
(let ((library-path kiwix-zim-dir))
(cl-case kiwix-server-type
('docker-remote
(message "kiwix-serve service is started by user manually at other place."))
('docker-local (start-process
"kiwix-server"
" *kiwix server*"
"docker"
"container" "run" "-d"
"--name" "kiwix-serve"
"-v" (concat (file-name-directory library-path) ":" "/data")
"-p" (format "%s:80" kiwix-server-port)
"kiwix/kiwix-serve"
"--library" "library.xml"))
('kiwix-serve-local
(setq kiwix--server-process
(start-process
"kiwix-server"
" *kiwix server*"
kiwix-server-command
"--port" (number-to-string kiwix-server-port)
"--library" (concat kiwix-zim-dir "/library.xml")))))))
(defun kiwix-stop-local-server ()
"Stops a Kiwix server started by ‘kiwix-launch-server’."
(interactive)
(when kiwix--server-process
(kill-process kiwix--server-process)
(setq kiwix--server-process nil)))
(defun kiwix-capitalize-first (string)
"Only capitalize the first word of STRING."
(concat (string (upcase (aref string 0))) (substring string 1)))
(defun kiwix-query (query &optional selected-library)
"Search `QUERY' in `LIBRARY' with Kiwix."
(let* ((library (or selected-library (kiwix--get-library-name selected-library)))
(url (concat (format "%s:%s" kiwix-server-url kiwix-server-port)
"/search?content=" library "&pattern=" (url-hexify-string query)))
(browse-url-browser-function kiwix-default-browser-function))
(browse-url url)))
(defun kiwix-docker-check ()
"Make sure Docker image 'kiwix/kiwix-server' is available."
(let ((docker-image (replace-regexp-in-string
"\n" ""
(shell-command-to-string
"docker image ls kiwix/kiwix-serve | sed -n '2p' | cut -d ' ' -f 1"))))
(string-equal docker-image "kiwix/kiwix-serve")))
(defvar kiwix-server-available? nil
"The kiwix-server current available?")
;;;###autoload
(defun kiwix-ping-server ()
"Ping Kiwix server to set `kiwix-server-available?' global state variable."
(and (eq kiwix-server-type 'docker-local)
(or (kiwix-docker-check)
(async-shell-command "docker pull kiwix/kiwix-serve")))
(let ((inhibit-message t))
(request (format "%s:%s" kiwix-server-url kiwix-server-port)
:type "GET"
:sync t
:parser (lambda () (libxml-parse-html-region (point-min) (point-max)))
:error (cl-function
(lambda (&rest args &key error-thrown &allow-other-keys)
(setq kiwix-server-available? nil)
(when (string-equal (cdr error-thrown) "exited abnormally with code 7\n")
(warn "kiwix.el failed to connect to host. exited abnormally with status code: 7."))))
:success (cl-function
(lambda (&key _data &allow-other-keys)
(setq kiwix-server-available? t)))
:status-code '((404 . (lambda (&rest _) (message (format "Endpoint %s does not exist." url))))
(500 . (lambda (&rest _) (message (format "Error from %s." url))))))))
(defun kiwix--ajax-search-hints (input &optional selected-library)
"Instantly AJAX request to get available Kiwix entry keywords
list and return a list result."
(kiwix-ping-server)
(when (and input kiwix-server-available?)
(let* ((library (or selected-library
(kiwix--get-library-name selected-library)))
(ajax-api (format "%s:%s/suggest?content=%s&term="
kiwix-server-url kiwix-server-port
library))
(ajax-url (concat ajax-api input))
(data (request-response-data
(let ((inhibit-message t))
(request ajax-url
:type "GET"
:sync t
:headers '(("Content-Type" . "application/json"))
:parser #'json-read
:success (cl-function
(lambda (&key data &allow-other-keys)
data)))))))
(if (vectorp data) (mapcar #'cdar data)))))
(defun kiwix--get-thing-at-point ()
"Get region select text or symbol at point."
(if (use-region-p)
(buffer-substring
(region-beginning) (region-end))
(thing-at-point 'symbol)))
(defun kiwix--ajax-select-available-hints (zim-library)
"AJAX search hints on the selected library and select one term from available hints."
(pcase kiwix-default-completing-read
('selectrum
(require 'selectrum)
(require 'consult)
(consult--read
(lambda (input)
(apply #'kiwix--ajax-search-hints
input `(,zim-library)))
:prompt "Kiwix related entries: "
:require-match nil))
('ivy
(require 'ivy)
(ivy-read
"Kiwix related entries: "
(lambda (input)
(apply #'kiwix--ajax-search-hints
input `(,zim-library)))
:predicate nil
:require-match nil
:initial-input (kiwix--get-thing-at-point)
:preselect nil
:def nil
:history nil
:keymap nil
:update-fn 'auto
:sort t
:dynamic-collection t
:caller 'ivy-done))
('helm
(require 'helm)
(helm
:source (helm-build-async-source "kiwix-helm-search-hints"
:candidates-process
(lambda (input)
(apply #'kiwix--ajax-search-hints
input `(,zim-library))))
:input (kiwix--get-thing-at-point)
:buffer "*helm kiwix completion candidates*"))
(_
(completing-read
"Kiwix related entries: "
;; FIXME: This needs work!
(completion-table-dynamic
(lambda (input)
(apply #'kiwix--ajax-search-hints
input `(,zim-library))))
nil nil
(kiwix--get-thing-at-point)))))
;;;###autoload
(defun kiwix-search-at-library (zim-library query)
"Search QUERY in selected ZIM library."
(interactive (let ((zim-library (kiwix-select-library)))
(list zim-library (kiwix--ajax-select-available-hints zim-library))))
(message (format "library: %s, query: %s" zim-library query))
(if (or (null zim-library)
(string-empty-p zim-library)
(null query)
(string-empty-p query))
(error "Your query is invalid")
(kiwix-query query zim-library)))
;;;###autoload
(defun kiwix-search-full-context (query)
"Full context search QUERY in all kiwix ZIM libraries. It's very slow."
(interactive
(list (read-string "kiwix full context search in all libraries: ")))
(browse-url (format "%s:%s/search?pattern=%s" kiwix-server-url kiwix-server-port query)))
;;;###autoload
(defun kiwix-at-point ()
"Search for the symbol at point with `kiwix-search-at-library'."
(interactive)
(unless (kiwix-ping-server)
(kiwix-launch-server))
(if kiwix-server-available?
(call-interactively 'kiwix-search-at-library)
(warn "kiwix-serve is not available, please start it at first."))
(setq kiwix-server-available? nil))
;;===============================================================================
(defun kiwix-mode-enable ()
"Enable kiwix-mode."
)
(defun kiwix-mode-disable ()
"Disable kiwix-mode."
)
(defvar kiwix-mode-map
(let ((map (make-sparse-keymap)))
map)
"kiwix-mode map.")
;;;###autoload
(define-minor-mode kiwix-mode
"Kiwix global minor mode for searching Kiwix serve."
:global t
:lighter " Kiwix"
(if kiwix-mode (kiwix-mode-enable) (kiwix-mode-disable)))
(provide 'kiwix)
;;; kiwix.el ends here
kiwix-1.1.5/org-kiwix.el 0000644 0001752 0001753 00000013753 14105035336 013555 0 ustar elpa elpa ;;; org-kiwix.el --- Org Mode link support -*- lexical-binding: t; -*-
;;; Time-stamp: <2021-01-14 02:33:56 stardiviner>
;; Author: stardiviner
;; Maintainer: stardiviner
;; Keywords: kiwix wikipedia
;; Homepage: https://github.com/stardiviner/kiwix.el
;; Created: 23th July 2016
;; Version: 1.0.3
;; Package-Requires: ((emacs "26.1"))
;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see .
;;; Commentary:
;; Support Org-mode
;;
;; - [[wikipedia:(library):query]]
;; - [[wikipedia:query]]
;;
;; links:
;; - wikipedia:(zh):%E7%A6%85%E5%AE%97
;; - wikipedia:(en):linux
;; - wikipedia:linux
;;
;; - parameter `link' will be (en):linux" or linux".
;;
;; elisp regexp: "\\(?:(\\(.*\\)):\\)?\\([^] \n\t\r]*\\)"
;; - non capturing group (\(?:...\)) for optional library
;; - group 1: library (en or zh)
;; - group 2: link? (match everything but ], space, tab, carriage return, linefeed by using [^] \n\t\r]*)
;; for open wiki search query with local application database.
;; Usage:
;;
;; (add-hook 'org-load-hook #'org-kiwix-setup-link)
;;; Code:
(require 'kiwix)
(autoload 'org-link-set-parameters "org")
(autoload 'org-store-link-props "org")
(defun org-kiwix--chinese-string-p (string)
"Return t if STRING is a Chinese string."
(if (string-match (format "\\cC\\{%s\\}" (length string)) string)
t
nil))
(defun org-kiwix-get-library (link)
"Get library from Org-mode `LINK'."
(let ((library (catch 'args-out-of-range
(when (string-match "(\\([^)].*\\)):\\(.*\\)" link)
(match-string 1 link)))))
(or library
(cond
((org-kiwix--chinese-string-p link)
(kiwix-select-library "zh"))
((string-match-p "[a-zA-Z\ ]+" link)
;; convert between libraries full name and abbrev.
(kiwix-select-library "en"))
(t (kiwix-select-library))))))
(defun org-kiwix-open-link (link)
"Open LINK in external Wikipedia program."
;; The regexp: (library):query
;; - query : should not exclude space
;; match link spec: "(library):query" with regexp "([^).]*):?:.*"
;; (string-match "\\(?:(\\(.*\\)):\\)?\\([^]\n\t\r]*\\)" link)
(string-match "(\\([^)].*\\)):\\(.*\\)" link)
(let* ((library (org-kiwix-get-library link))
(query (cond
((org-kiwix--chinese-string-p link) link)
((string-match-p "(\\([^)].*\\)):\\(.*\\)" link)
(match-string 2 link))
(t link)))
(url (concat
kiwix-server-url
"/" library "/A/"
;; query need to be convert to URL encoding: "禅宗" https://zh.wikipedia.org/wiki/%E7%A6%85%E5%AE%97
(url-encode-url
;; convert space to underline: "Beta distribution" "Beta_distribution"
(replace-regexp-in-string
" " "_"
;; only capitalize the first word. like: "meta-circular interpreter" -> "Meta-circular interpreter"
(kiwix-capitalize-first query)
nil nil))
".html")))
;; (prin1 (format "library: %s, query: %s, url: %s" library query url))
(browse-url url)))
(defun org-kiwix-export-link (link description format)
"Export the Wikipedia LINK with DESCRIPTION for FORMAT from Org files."
(when (string-match "\\(?:(\\(.*\\)):\\)?\\([^] \n\t\r]*\\)" link)
(let* ((library (org-kiwix-get-library link))
(query (url-encode-url (or (match-string 2 link) description)))
;; "http://en.wikipedia.org/wiki/Linux"
;; --
;; ^- library: en, zh
(path (concat "http://" library ".wikipedia.org/wiki/" query))
(desc (or (match-string 2 link) description)))
(when (stringp path)
(cond
((eq format 'html) (format "%s" path desc))
((eq format 'latex) (format "\\href{%s}{%s}" path desc))
(t path))))))
(defun org-kiwix-store-link ()
"Store a link to a Wikipedia link."
;; [C-c o C-l l] `org-store-link'
;; remove those interactive functions. use normal function instead.
(when (eq major-mode 'wiki-mode)
(let* ((query (read-string "Wikipedia Query with Kiwix: "))
(library (kiwix-select-library))
(link (concat "wikipedia:" "(" library "):" query)))
(org-store-link-props :type "wikipedia"
:link link
:description query)
link)))
(defun org-kiwix-complete-link (&optional arg)
"Use kiwix AJAX request to provide available completion keywords."
(let* ((query (or arg (read-from-minibuffer "Search keyword: ")))
(library (kiwix-select-library))
(keywords (kiwix--ajax-search-hints query library)))
(concat "wikipedia:"
"(" library "):"
(completing-read "Available keywords: " keywords))))
;;;###autoload
(defun org-kiwix-setup-link ()
"Setup Org link for org-kiwix."
(org-link-set-parameters "wikipedia" ; NOTE: use `wikipedia' for future backend changing.
:follow #'org-kiwix-open-link
:store #'org-kiwix-store-link
:export #'org-kiwix-export-link
:complete #'org-kiwix-complete-link)
(add-hook 'org-store-link-functions 'org-kiwix-store-link))
(provide 'org-kiwix)
;;; org-kiwix.el ends here
kiwix-1.1.5/kiwix-pkg.el 0000644 0001752 0001753 00000000566 14165537106 013555 0 ustar elpa elpa ;; Generated package description from kiwix.el -*- no-byte-compile: t -*-
(define-package "kiwix" "1.1.5" "Searching offline Wikipedia through Kiwix." '((emacs "25.1") (request "0.3.0")) :authors '(("stardiviner" . "numbchild@gmail.com")) :maintainer '("stardiviner" . "numbchild@gmail.com") :keywords '("kiwix" "wikipedia") :url "https://github.com/stardiviner/kiwix.el")