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 diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index f515f9a4..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,35 +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 - (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]*$" "" - ;; get text of current entry - (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." diff --git a/src/interface/emacs/tests/khoj-tests.el b/src/interface/emacs/tests/khoj-tests.el new file mode 100644 index 00000000..9325a61c --- /dev/null +++ b/src/interface/emacs/tests/khoj-tests.el @@ -0,0 +1,251 @@ +;;; 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\ +")))) + + + +;; ------------------------------------- +;; 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