Find Similar Notes, Transactions, Images from Khoj in Emacs

### Overview
Find items of specified type similar to current text item at point

### Capabilities
- Support querying with text surrounding point in any text buffer
- Find similar items of specified content type indexed on Khoj

### Details
- Query using text in current section if in a `outline-mode` buffer (i.e markdown heading, org-mode entry text)
- Query using text in current paragraph if in non `outline-mode` buffer
- Search for items of `content-type` set in khoj transient menu
- Update last used khoj content-type and results from the
  *find-similar* and *update* functions for later reuse

### Related
- Recently added [Find Similar Notes in Khoj Obsidian](https://github.com/debanjum/khoj/pull/122) as well
This commit is contained in:
Debanjum
2023-01-20 22:44:28 -03:00
committed by GitHub

View File

@@ -49,8 +49,9 @@
(require 'url)
(require 'json)
(require 'transient)
(require 'outline)
;; -------------------------
;; Khoj Static Configuration
;; -------------------------
@@ -84,7 +85,7 @@
(const "image")
(const "music")))
;; --------------------------
;; Khoj Dynamic Configuration
;; --------------------------
@@ -160,7 +161,7 @@ Use `which-key` if available, else display simple message in echo area"
nil t t))
(message "%s" (khoj--keybindings-info-message))))
;; -----------------------------------------------
;; Extract and Render Entries of each Content Type
;; -----------------------------------------------
@@ -247,7 +248,7 @@ Use `which-key` if available, else display simple message in echo area"
((and (member 'markdown enabled-content-types) (or (equal file-extension "markdown") (equal file-extension "md"))) "markdown")
(t khoj-default-content-type))))
;; --------------
;; Query Khoj API
;; --------------
@@ -274,9 +275,8 @@ Use `which-key` if available, else display simple message in echo area"
(encoded-query (url-hexify-string query)))
(format "%s/api/search?q=%s&t=%s&r=%s&n=%s" khoj-server-url encoded-query content-type rerank khoj-results-count)))
(defun khoj--query-api-and-render-results (query content-type query-url buffer-name)
"Query Khoj API using QUERY, CONTENT-TYPE, QUERY-URL.
Render results in BUFFER-NAME."
(defun khoj--query-api-and-render-results (query-url content-type query buffer-name)
"Query Khoj QUERY-URL. Render results in BUFFER-NAME using QUERY, CONTENT-TYPE."
;; get json response from api
(with-current-buffer buffer-name
(let ((inhibit-read-only t)
@@ -304,7 +304,7 @@ Render results in BUFFER-NAME."
(t (fundamental-mode))))
(read-only-mode t)))
;; ------------------
;; Incremental Search
;; ------------------
@@ -334,9 +334,9 @@ Render results in BUFFER-NAME."
(setq khoj--rerank t)
(message "Khoj: Rerank Results"))
(khoj--query-api-and-render-results
query
khoj--content-type
query-url
khoj--content-type
query
khoj-buffer-name))))))
(defun khoj--delete-open-network-connections-to-server ()
@@ -378,7 +378,73 @@ Render results in BUFFER-NAME."
(add-hook 'minibuffer-exit-hook #'khoj--teardown-incremental-search)) ; teardown khoj incremental search on minibuffer exit
(read-string khoj--query-prompt))))
;; --------------
;; Similar Search
;; --------------
(defun khoj--get-current-outline-entry-text ()
"Get text under current outline section."
(with-current-buffer (current-buffer)
;; jump to cursor in current buffer
(goto-char (point))
;; trim leading whitespaces from text
(replace-regexp-in-string
"^[ \t\n]*" ""
;; trim trailing whitespaces from text
(replace-regexp-in-string
"[ \t\n]*$" ""
;; get text of current outline entry
(buffer-substring-no-properties
(save-excursion (outline-previous-heading) (point))
(save-excursion (outline-next-heading) (point)))))))
(defun khoj--get-current-paragraph-text ()
"Get text in current paragraph at point."
(with-current-buffer (current-buffer)
;; jump to cursor in current buffer
(goto-char (point))
;; trim leading whitespaces from text
(replace-regexp-in-string
"^[ \t\n]*" ""
;; trim trailing whitespaces from text
(replace-regexp-in-string
"[ \t\n]*$" ""
;; get text of current entry
(buffer-substring-no-properties
(save-excursion (backward-paragraph) (point))
(save-excursion (forward-paragraph) (point)))))))
(defun khoj--find-similar (&optional content-type)
"Find items of CONTENT-TYPE in khoj index similar to text surrounding point."
(interactive)
(let* ((rerank "true")
;; set content type to: specified > based on current buffer > default type
(content-type (or content-type (khoj--buffer-name-to-content-type (buffer-name))))
;; get text surrounding current point based on the major mode context
(query (cond
;; get section outline derived mode like org or markdown
((or (derived-mode-p 'outline-mode) (equal major-mode 'markdown-mode))
(khoj--get-current-outline-entry-text))
;; get paragraph, if in text mode
(t
(khoj--get-current-paragraph-text))))
(query-url (khoj--construct-api-query query content-type rerank))
;; extract heading to show in result buffer from query
(query-title
(format "Similar to: %s"
(replace-regexp-in-string "^[#\\*]* " "" (car (split-string query "\n")))))
(buffer-name (get-buffer-create khoj--buffer-name)))
(progn
(khoj--query-api-and-render-results
query-url
content-type
query-title
buffer-name)
(switch-to-buffer buffer-name)
(goto-char (point-min)))))
;; ---------
;; Khoj Menu
;; ---------
@@ -387,7 +453,7 @@ Render results in BUFFER-NAME."
:class 'transient-switches
:argument-format "--content-type=%s"
:argument-regexp ".+"
;; set content type to last used or based on current buffer or to default
;; set content type to: last used > based on current buffer > default type
:init-value (lambda (obj) (oset obj value (format "--content-type=%s" (or khoj--content-type (khoj--buffer-name-to-content-type (buffer-name))))))
;; dynamically set choices to content types enabled on khoj backend
:choices (or (ignore-errors (mapcar #'symbol-name (khoj--get-enabled-content-types))) '("org" "markdown" "ledger" "music" "image")))
@@ -395,21 +461,34 @@ Render results in BUFFER-NAME."
(transient-define-suffix khoj--search-command (&optional args)
(interactive (list (transient-args transient-current-command)))
(progn
;; set content type to last used or based on current buffer or to default
;; set content type to: specified > last used > based on current buffer > default type
(setq khoj--content-type (or (transient-arg-value "--content-type=" args) (khoj--buffer-name-to-content-type (buffer-name))))
;; set results count to last used or to default
;; set results count to: specified > last used > to default
(setq khoj-results-count (or (transient-arg-value "--results-count=" args) khoj-results-count))
;; trigger incremental search
(call-interactively #'khoj-incremental)))
(transient-define-suffix khoj--find-similar-command (&optional args)
"Find items similar to current item at point."
(interactive (list (transient-args transient-current-command)))
(progn
;; set content type to: specified > last used > based on current buffer > default type
(setq khoj--content-type (or (transient-arg-value "--content-type=" args) (khoj--buffer-name-to-content-type (buffer-name))))
;; set results count to: specified > last used > to default
(setq khoj-results-count (or (transient-arg-value "--results-count=" args) khoj-results-count))
(khoj--find-similar khoj--content-type)))
(transient-define-suffix khoj--update-command (&optional args)
"Call khoj API to update index of specified content type."
(interactive (list (transient-args transient-current-command)))
(let* ((force-update (if (member "--force-update" args) "true" "false"))
;; set content type to: specified > last used > based on current buffer > default type
(content-type (or (transient-arg-value "--content-type=" args) (khoj--buffer-name-to-content-type (buffer-name))))
(update-url (format "%s/api/update?t=%s&force=%s" khoj-server-url content-type force-update))
(url-request-method "GET"))
(url-retrieve update-url (lambda (_) (message "Khoj %s index %supdated!" content-type (if (member "--force-update" args) "force " ""))))))
(progn
(setq khoj--content-type content-type)
(url-retrieve update-url (lambda (_) (message "Khoj %s index %supdated!" content-type (if (member "--force-update" args) "force " "")))))))
(transient-define-prefix khoj-menu ()
"Create Khoj Menu to Configure and Execute Commands."
@@ -421,10 +500,11 @@ Render results in BUFFER-NAME."
("-f" "Force Update" "--force-update")]]
[["Act"
("s" "Search" khoj--search-command)
("f" "Find Similar" khoj--find-similar-command)
("u" "Update" khoj--update-command)
("q" "Quit" transient-quit-one)]])
;; ----------
;; Entrypoint
;; ----------