mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-09 13:25:11 +00:00
Make khoj.el pass checkdoc, package-lint, flycheck checks
- Add docstrings, mention args in them. Make docstring crisper - prefix funcs, variables with khoj-- - Require emacs >27.1 for json-parse-buffer - Use lexical binding - Add quickstart docs to elisp file itself - Bump version of khoj.el
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
;;; khoj.el --- Natural, Incremental Search via Emacs
|
;;; khoj.el --- Natural, Incremental Search for your Second Brain -*- lexical-binding: t -*-
|
||||||
|
|
||||||
;; Copyright (C) 2021-2022 Debanjum Singh Solanky
|
;; Copyright (C) 2021-2022 Debanjum Singh Solanky
|
||||||
|
|
||||||
;; Author: Debanjum Singh Solanky <debanjum@gmail.com>
|
;; Author: Debanjum Singh Solanky <debanjum@gmail.com>
|
||||||
;; Version: 2.0
|
;; Description: Natural, Incremental Search for your Second Brain
|
||||||
;; Keywords: search, org-mode, outlines, markdown, image
|
;; Keywords: search, org-mode, outlines, markdown, beancount, ledger, image
|
||||||
|
;; Version: 2.1
|
||||||
|
;; Package-Requires: ((emacs "27.1"))
|
||||||
;; URL: http://github.com/debanjum/khoj/interface/emacs
|
;; URL: http://github.com/debanjum/khoj/interface/emacs
|
||||||
|
|
||||||
;; This file is NOT part of GNU Emacs.
|
;; This file is NOT part of GNU Emacs.
|
||||||
@@ -27,9 +29,20 @@
|
|||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; This package provides a natural, incremental search interface to your
|
;; This package provides a natural, incremental search interface to your
|
||||||
;; org-mode notes, markdown files, beancount transactions and images.
|
;; `org-mode' notes, `markdown' files, `beancount' transactions and images.
|
||||||
;; It is a wrapper that interfaces with transformer based ML models.
|
;; It is a wrapper that interfaces with the Khoj server.
|
||||||
;; The models search capabilities are exposed via the Khoj HTTP API.
|
;; The server exposes an API for advanced search using transformer ML models.
|
||||||
|
;; The Khoj server needs to be running to use this package.
|
||||||
|
;; See the repository docs for detailed setup of the Khoj server.
|
||||||
|
;;
|
||||||
|
;; Quickstart
|
||||||
|
;; -------------
|
||||||
|
;; 1. Install Khoj Server
|
||||||
|
;; pip install khoj-assistant
|
||||||
|
;; 2. Start, Configure Khoj Server
|
||||||
|
;; khoj
|
||||||
|
;; 3. Install khoj.el
|
||||||
|
;; (use-package khoj :bind ("C-c s" . 'khoj))
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
@@ -52,7 +65,7 @@
|
|||||||
:type 'integer)
|
:type 'integer)
|
||||||
|
|
||||||
(defcustom khoj-rerank-after-idle-time 2.0
|
(defcustom khoj-rerank-after-idle-time 2.0
|
||||||
"Idle time (in seconds) to trigger cross-encoder to rerank incremental search results."
|
"Idle time (in seconds) to rerank incremental search results."
|
||||||
:group 'khoj
|
:group 'khoj
|
||||||
:type 'float)
|
:type 'float)
|
||||||
|
|
||||||
@@ -70,7 +83,7 @@
|
|||||||
(const "music")))
|
(const "music")))
|
||||||
|
|
||||||
(defvar khoj--rerank-timer nil
|
(defvar khoj--rerank-timer nil
|
||||||
"Idle timer to make cross-encoder re-rank incremental search results if user idle.")
|
"Idle timer to re-rank incremental search results if user idle.")
|
||||||
|
|
||||||
(defvar khoj--minibuffer-window nil
|
(defvar khoj--minibuffer-window nil
|
||||||
"Minibuffer window being used by user to enter query.")
|
"Minibuffer window being used by user to enter query.")
|
||||||
@@ -85,6 +98,7 @@
|
|||||||
"The type of content to perform search on.")
|
"The type of content to perform search on.")
|
||||||
|
|
||||||
(defun khoj--keybindings-info-message ()
|
(defun khoj--keybindings-info-message ()
|
||||||
|
"Show available khoj keybindings in-context, when user invokes Khoj."
|
||||||
(let ((enabled-content-types (khoj--get-enabled-content-types)))
|
(let ((enabled-content-types (khoj--get-enabled-content-types)))
|
||||||
(concat
|
(concat
|
||||||
"
|
"
|
||||||
@@ -101,13 +115,13 @@
|
|||||||
(when (member 'music enabled-content-types)
|
(when (member 'music enabled-content-types)
|
||||||
"C-x M | music\n"))))
|
"C-x M | music\n"))))
|
||||||
|
|
||||||
(defun khoj--search-markdown () (interactive) (setq khoj--search-type "markdown"))
|
(defun khoj--search-markdown () "Set search-type to 'markdown'." (interactive) (setq khoj--search-type "markdown"))
|
||||||
(defun khoj--search-org () (interactive) (setq khoj--search-type "org"))
|
(defun khoj--search-org () "Set search-type to 'org-mode'." (interactive) (setq khoj--search-type "org"))
|
||||||
(defun khoj--search-ledger () (interactive) (setq khoj--search-type "ledger"))
|
(defun khoj--search-ledger () "Set search-type to 'ledger'." (interactive) (setq khoj--search-type "ledger"))
|
||||||
(defun khoj--search-images () (interactive) (setq khoj--search-type "image"))
|
(defun khoj--search-images () "Set search-type to image." (interactive) (setq khoj--search-type "image"))
|
||||||
(defun khoj--search-music () (interactive) (setq khoj--search-type "music"))
|
(defun khoj--search-music () "Set search-type to music." (interactive) (setq khoj--search-type "music"))
|
||||||
(defun khoj--make-search-keymap (&optional existing-keymap)
|
(defun khoj--make-search-keymap (&optional existing-keymap)
|
||||||
"Setup keymap to configure Khoj search"
|
"Setup keymap to configure Khoj search. Build of EXISTING-KEYMAP when passed."
|
||||||
(let ((enabled-content-types (khoj--get-enabled-content-types))
|
(let ((enabled-content-types (khoj--get-enabled-content-types))
|
||||||
(kmap (or existing-keymap (make-sparse-keymap))))
|
(kmap (or existing-keymap (make-sparse-keymap))))
|
||||||
(when (member 'markdown enabled-content-types)
|
(when (member 'markdown enabled-content-types)
|
||||||
@@ -121,6 +135,8 @@
|
|||||||
(when (member 'music enabled-content-types)
|
(when (member 'music enabled-content-types)
|
||||||
(define-key kmap (kbd "C-x M") #'khoj--search-music))
|
(define-key kmap (kbd "C-x M") #'khoj--search-music))
|
||||||
kmap))
|
kmap))
|
||||||
|
|
||||||
|
(defvar khoj--keymap nil "Track Khoj keymap in this variable.")
|
||||||
(defun khoj--display-keybinding-info ()
|
(defun khoj--display-keybinding-info ()
|
||||||
"Display information on keybindings to customize khoj search.
|
"Display information on keybindings to customize khoj search.
|
||||||
Use `which-key` if available, else display simple message in echo area"
|
Use `which-key` if available, else display simple message in echo area"
|
||||||
@@ -132,7 +148,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
(message "%s" (khoj--keybindings-info-message))))
|
(message "%s" (khoj--keybindings-info-message))))
|
||||||
|
|
||||||
(defun khoj--extract-entries-as-markdown (json-response query)
|
(defun khoj--extract-entries-as-markdown (json-response query)
|
||||||
"Convert json response from API to markdown entries"
|
"Convert JSON-RESPONSE, QUERY from API to markdown entries."
|
||||||
;; remove leading (, ) or SPC from extracted entries string
|
;; remove leading (, ) or SPC from extracted entries string
|
||||||
(replace-regexp-in-string
|
(replace-regexp-in-string
|
||||||
"^[\(\) ]" ""
|
"^[\(\) ]" ""
|
||||||
@@ -147,7 +163,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
json-response))))
|
json-response))))
|
||||||
|
|
||||||
(defun khoj--extract-entries-as-org (json-response query)
|
(defun khoj--extract-entries-as-org (json-response query)
|
||||||
"Convert json response from API to org-mode entries"
|
"Convert JSON-RESPONSE, QUERY from API to 'org-mode' entries."
|
||||||
;; remove leading (, ) or SPC from extracted entries string
|
;; remove leading (, ) or SPC from extracted entries string
|
||||||
(replace-regexp-in-string
|
(replace-regexp-in-string
|
||||||
"^[\(\) ]" ""
|
"^[\(\) ]" ""
|
||||||
@@ -162,7 +178,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
json-response))))
|
json-response))))
|
||||||
|
|
||||||
(defun khoj--extract-entries-as-images (json-response query)
|
(defun khoj--extract-entries-as-images (json-response query)
|
||||||
"Convert json response from API to html with images"
|
"Convert JSON-RESPONSE, QUERY from API to html with images."
|
||||||
;; remove leading (, ) or SPC from extracted entries string
|
;; remove leading (, ) or SPC from extracted entries string
|
||||||
(replace-regexp-in-string
|
(replace-regexp-in-string
|
||||||
"[\(\) ]$" ""
|
"[\(\) ]$" ""
|
||||||
@@ -188,7 +204,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
json-response)))))
|
json-response)))))
|
||||||
|
|
||||||
(defun khoj--extract-entries-as-ledger (json-response query)
|
(defun khoj--extract-entries-as-ledger (json-response query)
|
||||||
"Convert json response from API to ledger entries"
|
"Convert JSON-RESPONSE, QUERY from API to ledger entries."
|
||||||
;; remove leading (, ) or SPC from extracted entries string
|
;; remove leading (, ) or SPC from extracted entries string
|
||||||
(replace-regexp-in-string
|
(replace-regexp-in-string
|
||||||
"[\(\) ]$" ""
|
"[\(\) ]$" ""
|
||||||
@@ -203,6 +219,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
json-response)))))
|
json-response)))))
|
||||||
|
|
||||||
(defun khoj--buffer-name-to-search-type (buffer-name)
|
(defun khoj--buffer-name-to-search-type (buffer-name)
|
||||||
|
"Infer search type based on BUFFER-NAME."
|
||||||
(let ((enabled-content-types (khoj--get-enabled-content-types))
|
(let ((enabled-content-types (khoj--get-enabled-content-types))
|
||||||
(file-extension (file-name-extension buffer-name)))
|
(file-extension (file-name-extension buffer-name)))
|
||||||
(cond
|
(cond
|
||||||
@@ -213,7 +230,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
(t khoj-default-search-type))))
|
(t khoj-default-search-type))))
|
||||||
|
|
||||||
(defun khoj--get-enabled-content-types ()
|
(defun khoj--get-enabled-content-types ()
|
||||||
"Get content types enabled for search from API"
|
"Get content types enabled for search from API."
|
||||||
(let ((config-url (format "%s/config/data" khoj-server-url)))
|
(let ((config-url (format "%s/config/data" khoj-server-url)))
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
@@ -228,11 +245,14 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
content-type))))))
|
content-type))))))
|
||||||
|
|
||||||
(defun khoj--construct-api-query (query search-type &optional rerank)
|
(defun khoj--construct-api-query (query search-type &optional rerank)
|
||||||
|
"Construct API Query from QUERY, SEARCH-TYPE and (optional) RERANK params."
|
||||||
(let ((rerank (or rerank "false"))
|
(let ((rerank (or rerank "false"))
|
||||||
(encoded-query (url-hexify-string query)))
|
(encoded-query (url-hexify-string query)))
|
||||||
(format "%s/search?q=%s&t=%s&r=%s&n=%s" khoj-server-url encoded-query search-type rerank khoj-results-count)))
|
(format "%s/search?q=%s&t=%s&r=%s&n=%s" khoj-server-url encoded-query search-type rerank khoj-results-count)))
|
||||||
|
|
||||||
(defun khoj--query-api-and-render-results (query search-type query-url buffer-name)
|
(defun khoj--query-api-and-render-results (query search-type query-url buffer-name)
|
||||||
|
"Query Khoj API using QUERY, SEARCH-TYPE, QUERY-URL.
|
||||||
|
Render results in BUFFER-NAME."
|
||||||
;; get json response from api
|
;; get json response from api
|
||||||
(with-current-buffer buffer-name
|
(with-current-buffer buffer-name
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
@@ -260,8 +280,8 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
(read-only-mode t)))
|
(read-only-mode t)))
|
||||||
|
|
||||||
|
|
||||||
;; Incremental Search on Khoj
|
|
||||||
(defun khoj--incremental-search (&optional rerank)
|
(defun khoj--incremental-search (&optional rerank)
|
||||||
|
"Perform Incremental Search on Khoj. Allow optional RERANK of results."
|
||||||
(let* ((rerank-str (cond (rerank "true") (t "false")))
|
(let* ((rerank-str (cond (rerank "true") (t "false")))
|
||||||
(khoj-buffer-name (get-buffer-create khoj--buffer-name))
|
(khoj-buffer-name (get-buffer-create khoj--buffer-name))
|
||||||
(query (minibuffer-contents-no-properties))
|
(query (minibuffer-contents-no-properties))
|
||||||
@@ -281,8 +301,8 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
query-url
|
query-url
|
||||||
khoj-buffer-name)))))
|
khoj-buffer-name)))))
|
||||||
|
|
||||||
(defun delete-open-network-connections-to-khoj ()
|
(defun khoj--delete-open-network-connections-to-server ()
|
||||||
"Delete all network connections to khoj server"
|
"Delete all network connections to khoj server."
|
||||||
(dolist (proc (process-list))
|
(dolist (proc (process-list))
|
||||||
(let ((proc-buf (buffer-name (process-buffer proc)))
|
(let ((proc-buf (buffer-name (process-buffer proc)))
|
||||||
(khoj-network-proc-buf (string-join (split-string khoj-server-url "://") " ")))
|
(khoj-network-proc-buf (string-join (split-string khoj-server-url "://") " ")))
|
||||||
@@ -290,6 +310,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
(delete-process proc)))))
|
(delete-process proc)))))
|
||||||
|
|
||||||
(defun khoj--teardown-incremental-search ()
|
(defun khoj--teardown-incremental-search ()
|
||||||
|
"Teardown timers and hooks used for incremental search."
|
||||||
(message "Khoj: Teardown Incremental Search")
|
(message "Khoj: Teardown Incremental Search")
|
||||||
;; remove advice to rerank results on normal exit from minibuffer
|
;; remove advice to rerank results on normal exit from minibuffer
|
||||||
(advice-remove 'exit-minibuffer #'khoj--minibuffer-exit-advice)
|
(advice-remove 'exit-minibuffer #'khoj--minibuffer-exit-advice)
|
||||||
@@ -298,19 +319,20 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
;; cancel rerank timer
|
;; cancel rerank timer
|
||||||
(when (timerp khoj--rerank-timer)
|
(when (timerp khoj--rerank-timer)
|
||||||
(cancel-timer khoj--rerank-timer))
|
(cancel-timer khoj--rerank-timer))
|
||||||
;; delete open connections to khoj
|
;; delete open connections to khoj server
|
||||||
(delete-open-network-connections-to-khoj)
|
(khoj--delete-open-network-connections-to-server)
|
||||||
;; remove hooks for khoj incremental query and self
|
;; remove hooks for khoj incremental query and self
|
||||||
(remove-hook 'post-command-hook #'khoj--incremental-search)
|
(remove-hook 'post-command-hook #'khoj--incremental-search)
|
||||||
(remove-hook 'minibuffer-exit-hook #'khoj--teardown-incremental-search))
|
(remove-hook 'minibuffer-exit-hook #'khoj--teardown-incremental-search))
|
||||||
|
|
||||||
(defun khoj--minibuffer-exit-advice (&rest _args)
|
(defun khoj--minibuffer-exit-advice (&rest _args)
|
||||||
|
"Rerank results of incremental search on exiting minibuffer."
|
||||||
(khoj--incremental-search t))
|
(khoj--incremental-search t))
|
||||||
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun khoj ()
|
(defun khoj ()
|
||||||
"Natural, Incremental Search for your personal notes, transactions and music using Khoj"
|
"Natural, Incremental Search for your personal notes, transactions and music."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((khoj-buffer-name (get-buffer-create khoj--buffer-name)))
|
(let* ((khoj-buffer-name (get-buffer-create khoj--buffer-name)))
|
||||||
;; set khoj search type to last used or based on current buffer
|
;; set khoj search type to last used or based on current buffer
|
||||||
@@ -337,7 +359,7 @@ Use `which-key` if available, else display simple message in echo area"
|
|||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun khoj-simple (query)
|
(defun khoj-simple (query)
|
||||||
"Natural Search for QUERY in your personal notes, transactions, music and images using Khoj"
|
"Natural Search for QUERY on your personal notes, transactions, music and images."
|
||||||
(interactive "s🦅Khoj: ")
|
(interactive "s🦅Khoj: ")
|
||||||
(let* ((rerank "true")
|
(let* ((rerank "true")
|
||||||
(default-type (khoj--buffer-name-to-search-type (buffer-name)))
|
(default-type (khoj--buffer-name-to-search-type (buffer-name)))
|
||||||
|
|||||||
Reference in New Issue
Block a user