diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index b64b4e72..2c2f4172 100644 --- a/src/interface/emacs/khoj.el +++ b/src/interface/emacs/khoj.el @@ -49,6 +49,7 @@ (require 'url) (require 'json) (require 'transient) +(require 'outline) ;; ------------------------- @@ -383,38 +384,66 @@ Render results in BUFFER-NAME." ;; Similar Search ;; -------------- -(defun khoj--get-current-org-entry-text () - "Get text in org entry at point." +(defun khoj--get-current-outline-entry-text () + "Get text under current outline section." (with-current-buffer (current-buffer) - (org-with-wide-buffer - ;; jump to cursor in current buffer - (goto-char (point)) + ;; 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 - (save-excursion - ;; jump to heading of current entry - (org-back-to-heading t) - ;; get text of current entry using org-element-at-point - (buffer-substring-no-properties - (org-element-property :begin (org-element-at-point)) - (org-element-property :end (org-element-at-point)))))))) + ;; get text of current outline entry + (buffer-substring-no-properties + (save-excursion (outline-previous-heading) (point)) + (save-excursion (outline-next-heading) (point))))))) -(defun khoj--find-similar-notes () - "Search for org entries similar to entry at 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") - (content-type (khoj--buffer-name-to-content-type (buffer-name))) - (query (khoj--get-current-org-entry-text)) + ;; 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))) - (khoj--query-api-and-render-results - ;; extract headline from query string containing org-entry - (replace-regexp-in-string "^\\** " "" (car (split-string query "\n"))) - content-type - query-url - buffer-name) - (switch-to-buffer buffer-name))) + (progn + (khoj--query-api-and-render-results + query-title + content-type + query-url + buffer-name) + (switch-to-buffer buffer-name) + (goto-char (point-min))))) ;; --------- @@ -425,7 +454,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"))) @@ -433,26 +462,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 _) - "Find other notes similar to current note at point." - (interactive) - (khoj--find-similar-notes)) +(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." @@ -464,7 +501,7 @@ Render results in BUFFER-NAME." ("-f" "Force Update" "--force-update")]] [["Act" ("s" "Search" khoj--search-command) - ("f" "Find Similar Notes" khoj--find-similar-command) + ("f" "Find Similar" khoj--find-similar-command) ("u" "Update" khoj--update-command) ("q" "Quit" transient-quit-one)]])