mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-06 21:29:12 +00:00
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:
@@ -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
|
||||
;; ----------
|
||||
|
||||
Reference in New Issue
Block a user