From a0b03c8bb185a157400fdc7205bce2471fd63d10 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 10:01:25 -0300 Subject: [PATCH 1/6] Get current entry text when point at heading for Find Similar in khoj.el Previously if cursor was at heading of current entry, it would find entries similar to the previous outline heading, instead of the current one --- src/interface/emacs/khoj.el | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index f515f9a4..a138c4ac 100644 --- a/src/interface/emacs/khoj.el +++ b/src/interface/emacs/khoj.el @@ -395,9 +395,16 @@ Use `which-key` if available, else display simple message in echo area" (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))))))) + (cond + ;; when at heading of entry + ((looking-at outline-regexp) + (buffer-substring-no-properties + (point) + (save-excursion (outline-next-heading) (point)))) + ;; when within entry + (t (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." From 07e9e4ecc3561a8c02e264e88e65f07c89b1710d Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 18:02:47 -0300 Subject: [PATCH 2/6] Get current paragraph text when point at start of paragraph in khoj.el Previously if cursor was at start of current paragraph, it would get text for the current and next paragraph, instead of just the current one --- src/interface/emacs/khoj.el | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index a138c4ac..3a75cf36 100644 --- a/src/interface/emacs/khoj.el +++ b/src/interface/emacs/khoj.el @@ -417,10 +417,16 @@ Use `which-key` if available, else display simple message in echo area" ;; 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))))))) + (cond + ;; when at beginning of a middle paragraph + ((and (looking-at paragraph-start) (not (equal (point) (point-min)))) + (buffer-substring-no-properties + (save-excursion (backward-paragraph) (point)) + (point))) + ;; else + (t (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." From 0d0bf3b5aac7b6fa487bb3914773650ab97cea55 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 18:41:58 -0300 Subject: [PATCH 3/6] Simplify get-current-text functions for Find Similar in khoj.el Use existing functions like `string-trim', `thing-at-point' and remove unneeded code from the two functions --- src/interface/emacs/khoj.el | 65 ++++++++++++++----------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index 3a75cf36..109cdfc2 100644 --- a/src/interface/emacs/khoj.el +++ b/src/interface/emacs/khoj.el @@ -50,6 +50,7 @@ (require 'json) (require 'transient) (require 'outline) +(eval-when-compile (require 'subr-x)) ;; for string-trim before Emacs 28.2 ;; ------------------------- @@ -385,48 +386,32 @@ Use `which-key` if available, else display simple message in echo area" (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 - (cond - ;; when at heading of entry - ((looking-at outline-regexp) - (buffer-substring-no-properties - (point) - (save-excursion (outline-next-heading) (point)))) - ;; when within entry - (t (buffer-substring-no-properties - (save-excursion (outline-previous-heading) (point)) - (save-excursion (outline-next-heading) (point))))))))) + (string-trim + ;; get text of current outline entry + (cond + ;; when at heading of entry + ((looking-at outline-regexp) + (buffer-substring-no-properties + (point) + (save-excursion (outline-next-heading) (point)))) + ;; when within entry + (t (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]*$" "" - (cond - ;; when at beginning of a middle paragraph - ((and (looking-at paragraph-start) (not (equal (point) (point-min)))) - (buffer-substring-no-properties - (save-excursion (backward-paragraph) (point)) - (point))) - ;; else - (t (buffer-substring-no-properties - (save-excursion (backward-paragraph) (point)) - (save-excursion (forward-paragraph) (point))))))))) + "Get trimmed text in current paragraph at point. +Paragraph only starts at first text after blank line." + (string-trim + (cond + ;; when at end of a middle paragraph + ((and (looking-at paragraph-start) (not (equal (point) (point-min)))) + (buffer-substring-no-properties + (save-excursion (backward-paragraph) (point)) + (point))) + ;; else + (t (thing-at-point 'paragraph t))))) + (defun khoj--find-similar (&optional content-type) "Find items of CONTENT-TYPE in khoj index similar to text surrounding point." From be6acda21277603d9e768a8870a041cb9bb8f4ae Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 14:55:20 -0300 Subject: [PATCH 4/6] Create khoj.el tests. Test rendering results of each content types --- src/interface/emacs/tests/khoj-tests.el | 155 ++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/interface/emacs/tests/khoj-tests.el diff --git a/src/interface/emacs/tests/khoj-tests.el b/src/interface/emacs/tests/khoj-tests.el new file mode 100644 index 00000000..75cfad7c --- /dev/null +++ b/src/interface/emacs/tests/khoj-tests.el @@ -0,0 +1,155 @@ +;;; khoj-tests.el --- Test suite for khoj.el -*- lexical-binding: t -*- + +;; Copyright (C) 2023 Debanjum Singh Solanky + +;; Author: Debanjum Singh Solanky +;; Version: 0.0.0 +;; Package-Requires: ((emacs "27.1") (transient "0.3.0")) +;; URL: https://github.com/debanjum/khoj/tree/master/src/interface/emacs + +;;; License: + +;; This program 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. + +;; This program 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 this program. If not, see . + +;;; Commentary: + +;; This file contains the test suite for khoj.el. + +;;; Code: + +(require 'ert) +(require 'khoj) + + + +;; ---------------------------------------------------- +;; Test Extract and Render Entries of each Content Type +;; ---------------------------------------------------- + +(ert-deftest khoj-tests--extract-entries-as-markdown () + "Test `json-response', `query' from API formatted as markdown." + (let ((user-query "Become God") + (json-response-from-khoj-backend + (json-read-from-string + "[\ +{\ + \"entry\": \"## Upgrade\\n\\n Penance to Immortality\\n\",\ + \"score\": \"0.376\",\ + \"additional\": {\ + \"file\": \"/home/ravan/upgrade.md\",\ + \"compiled\": \"## Upgrade Penance to Immortality\"\ + }\ +},\ +{\ + \"entry\": \"## Act\\n\\n Rule everything\\n\",\ + \"score\": \"0.153\",\ + \"additional\": {\ + \"file\": \"/home/ravan/act.md\",\ + \"compiled\": \"## Act Rule everything\"\ + }\ +}]\ +"))) + (should + (equal + (khoj--extract-entries-as-markdown json-response-from-khoj-backend user-query) + "\ +# Become God\n\ +## Upgrade\n\ +\n\ +Penance to Immortality\n\ +## Act\n\ +\n\ +Rule everything\n")))) + + +(ert-deftest khoj-tests--extract-entries-as-org () + "Test `json-response', `query' from API formatted as org." + (let ((user-query "Become God") + (json-response-from-khoj-backend + (json-read-from-string + "[\ +{\ + \"entry\": \"** Upgrade\\n\\n Penance to Immortality\\n\",\ + \"score\": \"0.42\",\ + \"additional\": {\ + \"file\": \"/home/ravan/upgrade.md\",\ + \"compiled\": \"** Upgrade Penance to Immortality\"\ + }\ +},\ +{\ + \"entry\": \"** Act\\n\\n Rule everything\\n\",\ + \"score\": \"0.42\",\ + \"additional\": {\ + \"file\": \"/home/ravan/act.md\",\ + \"compiled\": \"** Act Rule everything\"\ + }\ +}]\ +"))) + (should + (equal + (khoj--extract-entries-as-org json-response-from-khoj-backend user-query) + "\ +* Become God\n\ +** Upgrade\n\ +\n\ +Penance to Immortality\n\ +** Act\n\ +\n\ +Rule everything\n\ +\n\ +#+STARTUP: showall hidestars inlineimages")))) + + +(ert-deftest khoj-tests--extract-entries-as-ledger () + "Test `json-response', `query' from API formatted as beancount ledger." + (let ((user-query "Become God") + (json-response-from-khoj-backend + (json-read-from-string + "[\ +{\ + \"entry\": \"4242-04-01 * \\\"Penance Center\\\" \\\"Book Stay for 10,000 Years\\\"\\n Expenses:Health:Mental 15 GOLD\\n Assets:Commodities:Gold\",\ + \"score\": \"0.42\",\ + \"additional\": {\ + \"file\": \"/home/ravan/ledger.beancount\",\ + \"compiled\": \"4242-04-01 * \\\"Penance Center\\\" \\\"Book Stay for 10,000 Years\\\" Expenses:Health:Mental 15 GOLD Assets:Commodities:Gold\"\ + }\ +},\ +{\ + \"entry\": \"14242-04-01 * \\\"Brahma\\\" \\\"Boon for Invincibility from Higher Beings\\\"\\n Income:Health -1,00,00,000 LIFE\\n Assets:Commodities:Life\",\ + \"score\": \"0.42\",\ + \"additional\": {\ + \"file\": \"/home/ravan/ledger.beancount\",\ + \"compiled\": \"4242-04-01 * \\\"Brahma\\\" \\\"Boon for Invincibility from Higher Beings\\\" Income:Health -1,00,00,000 LIFE Assets:Commodities:Life\"\ + }\ +}]\ +"))) + (should + (equal + (khoj--extract-entries-as-ledger json-response-from-khoj-backend user-query) + ";; Become God\n\ +\n\ +4242-04-01 * \"Penance Center\" \"Book Stay for 10,000 Years\"\n\ + Expenses:Health:Mental 15 GOLD\n\ + Assets:Commodities:Gold\n\ +\n\ +14242-04-01 * \"Brahma\" \"Boon for Invincibility from Higher Beings\"\n\ + Income:Health -1,00,00,000 LIFE\n\ + Assets:Commodities:Life\n\ +\n\ +\n\ +")))) + +(provide 'khoj-tests) + +;;; khoj-tests.el ends here From 86e808abfbe9010e6cd5e242a2f9b0cc926d602d Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 18:15:23 -0300 Subject: [PATCH 5/6] Test get-current-text helpers for Find Similar feature in khoj.el --- src/interface/emacs/tests/khoj-tests.el | 96 +++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/interface/emacs/tests/khoj-tests.el b/src/interface/emacs/tests/khoj-tests.el index 75cfad7c..9325a61c 100644 --- a/src/interface/emacs/tests/khoj-tests.el +++ b/src/interface/emacs/tests/khoj-tests.el @@ -150,6 +150,102 @@ Rule everything\n\ \n\ ")))) + + +;; ------------------------------------- +;; Test Helpers for Find Similar Feature +;; ------------------------------------- + +(ert-deftest khoj-tests--get-current-outline-entry-text () + "Test get current outline-mode entry text'." + (with-temp-buffer + (insert "\ +* Become God\n\ +** Upgrade\n\ +\n\ +Penance to Immortality\n\ +** Act\n\ +\n\ +Rule everything\\n") + (goto-char (point-min)) + + ;; Test getting current entry text from cursor at start of outline heading + (outline-next-visible-heading 1) + (should + (equal + (khoj--get-current-outline-entry-text) + "\ +** Upgrade\n\ +\n\ +Penance to Immortality")) + + ;; Test getting current entry text from cursor within outline entry + (forward-line) + (should + (equal + (khoj--get-current-outline-entry-text) + "\ +** Upgrade\n\ +\n\ +Penance to Immortality")) + )) + + +(ert-deftest khoj-tests--get-current-paragraph-text () + "Test get current paragraph text'." + (with-temp-buffer + (insert "\ +* Become God\n\ +** Upgrade\n\ +\n\ +Penance to Immortality\n\ +** Act\n\ +\n\ +Rule everything\n") + ;; Test getting current paragraph text from cursor at start of buffer + (goto-char (point-min)) + (should + (equal + (khoj--get-current-paragraph-text) + "* Become God\n\ +** Upgrade")) + + ;; Test getting current paragraph text from cursor within paragraph + (goto-char (point-min)) + (forward-line 1) + (should + (equal + (khoj--get-current-paragraph-text) + "* Become God\n\ +** Upgrade")) + + ;; Test getting current paragraph text from cursor at paragraph end + (goto-char (point-min)) + (forward-line 2) + (should + (equal + (khoj--get-current-paragraph-text) + "* Become God\n\ +** Upgrade")) + + ;; Test getting current paragraph text from cursor at start of middle paragraph + (goto-char (point-min)) + (forward-line 3) + (should + (equal + (khoj--get-current-paragraph-text) + "Penance to Immortality\n\ +** Act")) + + ;; Test getting current paragraph text from cursor at end of buffer + (goto-char (point-max)) + (should + (equal + (khoj--get-current-paragraph-text) + "Rule everything")) + )) + + (provide 'khoj-tests) ;;; khoj-tests.el ends here From f9fb58aec3f4deacf847651c055e00aee8b861a8 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 23 Jan 2023 19:42:46 -0300 Subject: [PATCH 6/6] Automate khoj.el testing using Github workflow Install transient.el dependency as it is not available by default before Emacs 28.1 --- .github/workflows/test_khoj_el.yml | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/test_khoj_el.yml diff --git a/.github/workflows/test_khoj_el.yml b/.github/workflows/test_khoj_el.yml new file mode 100644 index 00000000..eb1803c1 --- /dev/null +++ b/.github/workflows/test_khoj_el.yml @@ -0,0 +1,49 @@ +name: test khoj.el + +on: + push: + branches: + - 'master' + paths: + - src/interface/emacs/*.el + - src/interface/emacs/tests/*.el + - .github/workflows/test_khoj_el.yml + pull_request: + branches: + - 'master' + paths: + - src/interface/emacs/*.el + - src/interface/emacs/tests/*.el + - .github/workflows/test_khoj_el.yml + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + emacs_version: + - 27.1 + - 27.2 + - 28.1 + - 28.2 + - snapshot + steps: + - uses: purcell/setup-emacs@master + with: + version: ${{ matrix.emacs_version }} + - uses: actions/checkout@v3 + - name: Test Khoj.el + run: | + # Run ERT tests on khoj.el + emacs -batch \ + --eval "(progn \ + (require 'package) \ + (push '(\"melpa\" . \"https://melpa.org/packages/\") package-archives) \ + (package-initialize) \ + (unless package-archive-contents (package-refresh-contents)) \ + (unless (package-installed-p 'transient) (package-install 'transient)))" \ + -l ert \ + -l ./src/interface/emacs/khoj.el \ + -l ./src/interface/emacs/tests/khoj-tests.el \ + -f ert-run-tests-batch-and-exit