diff --git a/ChangeLog b/ChangeLog index 812622bc..d5efd454 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2024-12-22 Bob Weiner + +* test/hywiki-tests.el (hywiki-tests--add-org-id): Fix so :type + argument is a list as required, not a symbol. + +* hact.el (action:param-count): Add and use in 'hywiki-add-org-id'. + hywiki.el (hywiki-add-org-id): Pre-9.7 versions of org-id-get + did not accept the 4th optional INHERIT arg, so fix by + conditionally sending this argument. + +* hui-mouse.el (smart-magit-tab): Change 'if-let' (now obsolete) + to 'if-let*'. + +* test/hywiki-tests.el (hywiki-tests--add-org-id): Fix final test + to just look for prefix of "ID: ". + +* hywiki.el (hywiki-clear-pages-hasht): Also clear + 'hywiki--any-page-regexp-list'. + (hywiki-add-org-id): Fix first two lines of doc string. + +* test/hywiki-tests.el (hywiki-tests--add-org-id): Fix to not compare + error string values since when compiled may not be a string but + just a pair of indexes into one. + +* hywiki.el (hywiki-let-directory, hywiki-set-directory, + hywiki-directory-changed): Add to support 'let' changes of + 'hywiki-directory'. + (hywiki-clear-pages-hasht): Simplify to nullify hywiki + hash table and not try to reuse a previously build table. + +2024-12-16 Mats Lidell + +* test/hywiki-tests.el (hywiki-tests--sections-with-dash-space) + (hywiki-tests--get-singular-wikiword) + (hywiki-tests--get-plural-wikiword, hywiki-tests--add-referent) + (hywiki-tests--add-bookmark, hywiki-tests--add-command) + (hywiki-tests--add-find, hywiki-tests--add-global-button) + (hywiki-tests--add-hyrolo, hywiki-tests--add-info-index) + (hywiki-tests--add-info-node, hywiki-tests--add-key-series) + (hywiki-tests--add-link, hywiki-tests--add-org-id) + (hywiki-tests--get-page-list-for-new-wiki-directory-after-added-referent): + Tests. + 2024-12-16 Mats Lidell * Makefile (docker-all-tests, docker-batch-tests): No byte compiling to @@ -100,7 +143,7 @@ 2024-11-25 Mats Lidell -* kotl/kmenu.el (kotl-menu-common-body): Use kotl-kview. +* kotl/kmenu.el (kotl-menu-common-body): Use kotl-kview. * .github/workflows/static.yaml: Static workflow for publishing the manual to a static site using GitHub Pages. diff --git a/hact.el b/hact.el index 58019bf3..13c02fae 100644 --- a/hact.el +++ b/hact.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 18-Sep-91 at 02:57:09 -;; Last-Mod: 17-Aug-24 at 15:09:52 by Bob Weiner +;; Last-Mod: 22-Dec-24 at 16:03:11 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -333,6 +333,14 @@ TYPE and TYPE-CATEGORY are both symbols. TYPE-CATEGORY must be one of "Return Hyperbole action that execute a keyboard MACRO REPEAT-COUNT times." (list 'execute-kbd-macro macro repeat-count)) +(defun action:param-count (action) + "Return the number of args in ACTION's arg list. +Keywords and special symbols like &optional and &key are excluded." + (length (seq-filter (lambda (sym) + (not (or (keywordp sym) + (string-match "^&" (symbol-name sym))))) + (action:params action)))) + (defun action:params-emacs (def) "Return the argument list for the function DEF. DEF may be a symbol or a function body." diff --git a/hui-mouse.el b/hui-mouse.el index e6759461..aa3fd202 100644 --- a/hui-mouse.el +++ b/hui-mouse.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-89 -;; Last-Mod: 15-Dec-24 at 13:17:27 by Bob Weiner +;; Last-Mod: 22-Dec-24 at 13:22:26 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1635,7 +1635,7 @@ If assist key is pressed: (magit-section-show section) (magit-section-hide section))) (t - (if-let ((command (key-binding (kbd "RET")))) + (if-let* ((command (key-binding (kbd "RET")))) (progn (setq last-command-event ?\() (setq this-command command) (smart-magit-display-file command)) diff --git a/hyrolo.el b/hyrolo.el index 1a84c1bd..5b0f238e 100644 --- a/hyrolo.el +++ b/hyrolo.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 7-Jun-89 at 22:08:29 -;; Last-Mod: 13-Nov-24 at 13:17:36 by Mats Lidell +;; Last-Mod: 22-Dec-24 at 11:02:15 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -220,7 +220,7 @@ Function is called with 4 arguments: (SYMBOL SET-TO-VALUE OPERATION WHERE)." (hyrolo-set-file-list symbol set-to-value))) ;; This next line is needed to invoke `hyrolo-set-file-list' when -;; `hyrolo-file-list' is changed via `setq' rather than +;; `hyrolo-file-list' is changed via `setq' or `let' rather than ;; `customize-set-variable'. (add-variable-watcher 'hyrolo-file-list #'hyrolo-file-list-changed) diff --git a/hywiki.el b/hywiki.el index 242101f0..9108ce58 100644 --- a/hywiki.el +++ b/hywiki.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 21-Apr-24 at 22:41:13 -;; Last-Mod: 16-Dec-24 at 01:03:45 by Bob Weiner +;; Last-Mod: 22-Dec-24 at 16:31:10 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -254,20 +254,41 @@ Use nil for no HyWiki mode indicator." (defvar hywiki-file-suffix ".org" "File suffix (including period) to use when creating HyWiki pages.") +;;;###autoload +(defun hywiki-let-directory (option value) + (set option value) + (hywiki-clear-pages-hasht) + (hywiki-make-pages-hasht)) + +;;;###autoload +(defun hywiki-set-directory (option value) + (unless (and (boundp 'hywiki-directory) + (equal hywiki-directory (file-name-as-directory value))) + (set-default option (file-name-as-directory value)) + (hywiki-clear-pages-hasht) + (hywiki-make-pages-hasht)) + (hywiki-org-set-publish-project)) + (defcustom hywiki-directory "~/hywiki/" "Directory that holds all HyWiki pages in Org format. See `hywiki-org-publishing-directory' for exported pages in html format." :initialize #'custom-initialize-default - :set (lambda (option value) - (unless (and (boundp 'hywiki-directory) - (equal hywiki-directory (file-name-as-directory value))) - (set option (file-name-as-directory value)) - (hywiki-clear-pages-hasht) - (hywiki-make-pages-hasht)) - (hywiki-org-set-publish-project)) + :set #'hywiki-set-directory :type 'string :group 'hyperbole-hywiki) +(defun hywiki-directory-changed (option set-to-value operation _where) + "Watch function for variable `hywiki-directory'. +Function is called with 4 arguments: (SYMBOL SET-TO-VALUE OPERATION WHERE)." + (if (memq operation '(let unlet)) ;; not setting global value + (hywiki-let-directory option set-to-value) + (hywiki-set-directory option set-to-value))) + +;; This next line is needed to invoke `hywiki-set-directory' when +;; `hywiki-directory' is changed via `setq' or `let' rather than +;; `customize-set-variable'. +(add-variable-watcher 'hywiki-directory #'hywiki-directory-changed) + (defvar-local hywiki-buffer-highlighted-state nil "State of HyWikiWords highlighting in the associated buffer. \\='h means the buffer was already highlighted; @@ -952,7 +973,8 @@ calling this function." (hywiki-add-referent wikiword referent))) (defun hywiki-add-org-id (wikiword) - "Make WIKIWORD evaluate a prompted for sexpression and return it. + "Make WIKIWORD display an Org file or headline with an Org id. +If no id exists, it is created. Return the string \"ID: org-id-string\". If WIKIWORD is invalid, trigger a `user-error' if called interactively or return nil if not. @@ -970,7 +992,9 @@ calling this function." (user-error "(hywiki-add-org-id): Referent buffer <%s> must be in org-mode, not %s" (buffer-name) major-mode)) - (let ((org-id (org-id-get nil nil nil t))) + (let ((org-id (if (>= (action:param-count #'org-id-get) 4) + (org-id-get nil nil nil t) + (org-id-get)))) (when (and (null org-id) buffer-read-only) (user-error "(hywiki-add-org-id): Referent buffer <%s> point has no Org ID and buffer is read-only" (buffer-name))) @@ -2059,11 +2083,8 @@ If deleted, update HyWikiWord highlighting across all frames." (defun hywiki-clear-pages-hasht () "Clear all elements from the HyWiki referent hash table and return it." - (if (hashp hywiki--pages-hasht) - (progn (hash-map (lambda (key) (hash-delete key hywiki--pages-hasht)) - (hash-map #'cdr hywiki--pages-hasht)) - hywiki--pages-hasht) - (hash-make (length (hywiki-get-page-files))))) + (setq hywiki--pages-hasht nil + hywiki--any-page-regexp-list nil)) (eval-and-compile '(when (featurep 'company) diff --git a/test/hywiki-tests.el b/test/hywiki-tests.el index 9d9020b6..ed925c99 100644 --- a/test/hywiki-tests.el +++ b/test/hywiki-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell ;; ;; Orig-Date: 18-May-24 at 23:59:48 -;; Last-Mod: 16-Dec-24 at 00:07:45 by Bob Weiner +;; Last-Mod: 22-Dec-24 at 16:22:44 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -19,6 +19,7 @@ (require 'ert) (require 'el-mock) +(require 'with-simulated-input) (require 'hy-test-helpers) (require 'hywiki) (require 'ox-publish) @@ -120,6 +121,31 @@ (hywiki-mode -1) (hy-delete-dir-and-buffer hywiki-directory)))) +(ert-deftest hywiki-tests--sections-with-dash-space () + "Verify `hywiki-word-at' finds sections with dash and space." + (let ((hywiki-directory (make-temp-file "hywiki" t))) + (unwind-protect + (progn + (with-temp-buffer + (hywiki-mode) + (insert "WikiWord#section rest is ignored") + (goto-char 4) + (should (string= "WikiWord#section" (hywiki-word-at)))) + + (with-temp-buffer + (hywiki-mode) + (insert "WikiWord#section-with-dash") + (goto-char 4) + (should (string= "WikiWord#section-with-dash" (hywiki-word-at)))) + + (with-temp-buffer + (hywiki-mode) + (insert "WikiWord#\"section-within-quotes\"") + (goto-char 4) + (should (string= "WikiWord#\"section-within-quotes\"" (hywiki-word-at))))) + (hywiki-mode -1) + (hy-delete-dir-and-buffer hywiki-directory)))) + (ert-deftest hywiki-tests--word-is-p () "Verify `hywiki-word-is-p' identifies WikiWords." (should (hywiki-word-is-p "WikiWord")) @@ -272,6 +298,22 @@ Both mod-time and checksum must be changed for a test to return true." (hy-delete-file-and-buffer wikipage) (hy-delete-dir-and-buffer hywiki-directory)))) +(ert-deftest hywiki-tests--get-page-list-for-new-wiki-directory-after-added-referent () + "Verify `hywiki-get-page-list' is empty for new `hywiki-directory'." + (defvar hywiki-add-referent-hook) + (let ((hywiki-directory (make-temp-file "hywiki" t)) + (hywiki-add-referent-hook 'test-func)) + (unwind-protect + (progn + (mocklet (((test-func) => t)) + (should (eq 'referent (hywiki-add-referent "WikiWord" 'referent)))) + (should (= 1 (length (hywiki-get-page-list)))) + (let ((hywiki-directory (make-temp-file "hywiki" t))) + (unwind-protect + (should (= 0 (length (hywiki-get-page-list)))) + (hy-delete-dir-and-buffer hywiki-directory)))) + (hy-delete-dir-and-buffer hywiki-directory)))) + ;; Following three test cases for verifying proper face is some what ;; experimental. They need to be run in interactive mode. @@ -523,5 +565,135 @@ Both mod-time and checksum must be changed for a test to return true." (hy-delete-file-and-buffer wikipage) (hy-delete-dir-and-buffer hywiki-directory)))) +(ert-deftest hywiki-tests--get-singular-wikiword () + "Verify plural WikiWord is converted to singular. +Note special meaning of `hywiki-allow-plurals-flag'." + (let ((hywiki-allow-plurals-flag t)) + (should (string= "WikiWord" (hywiki-get-singular-wikiword "WikiWord"))) + (should (string= "WikiWord" (hywiki-get-singular-wikiword "WikiWords")))) + (let ((hywiki-allow-plurals-flag nil)) + (should (string= "WikiWord" (hywiki-get-singular-wikiword "WikiWord"))) + (should (string= "WikiWords" (hywiki-get-singular-wikiword "WikiWords"))))) + +(ert-deftest hywiki-tests--get-plural-wikiword () + "Verify singular WikiWord is converted to plural." + ;; Note: Should not this also respect `hywiki-allow-plurals-flag' so + ;; this can be disabled completely? + (should (string= "WikiWords" (hywiki-get-plural-wikiword "WikiWord"))) + (should (string= "Taxes" (hywiki-get-plural-wikiword "Tax"))) + ;; Exceptions + (should (string= "Monarchs" (hywiki-get-plural-wikiword "Monarchs")))) + +(ert-deftest hywiki-tests--add-referent () + "Verify `hywiki-add-referent'." + (defvar hywiki-add-referent-hook) + (let ((hywiki-directory (make-temp-file "hywiki" t)) + (hywiki-add-referent-hook 'test-func)) + (unwind-protect + (progn + (should-not (hywiki-add-referent "notawikiword" 'referent)) + (mocklet (((test-func) => t)) + (should (eq 'referent (hywiki-add-referent "WikiWord" 'referent)))) + (should (eq 'referent (hywiki-get-referent "WikiWord")))) + (hy-delete-dir-and-buffer hywiki-directory)))) + +;; hywiki-add-activity -- Requires activities + +(ert-deftest hywiki-tests--add-bookmark () + "Verify `hywiki-add-bookmark'." + (let ((hywiki-directory (make-temp-file "hywiki" t))) + (unwind-protect + (progn + (mocklet ((bookmark-completing-read => "")) + (should-error (hywiki-add-bookmark "WikiWord")))) + (mocklet ((bookmark-completing-read => 'bkmark)) + (should (equal '(bookmark-jump bkmark) (caddr (hywiki-add-bookmark "WikiWord"))))) + (hy-delete-dir-and-buffer hywiki-directory)))) + +(ert-deftest hywiki-tests--add-command () + "Verify `hywiki-add-command'." + (mocklet ((hui:actype => 'command) + ((hywiki-add-referent "WikiWord" 'command) => 'command)) + (should (eq 'command (hywiki-add-command "WikiWord"))))) + +(ert-deftest hywiki-tests--add-find () + "Verify `hywiki-add-find'." + (mocklet (((hywiki-add-referent "WikiWord" #'hywiki-word-grep) => 'word-grep)) + (should (eq 'word-grep (hywiki-add-find "WikiWord"))))) + +(ert-deftest hywiki-tests--add-global-button () + "Verify `hywiki-add-global-button'." + (mocklet ((hargs:read-match => "gbtn") + ((hywiki-add-referent "WikiWord" '(gbut:act "gbtn")) => 'gbut-referent)) + (should (equal 'gbut-referent (hywiki-add-global-button "WikiWord"))))) + +(ert-deftest hywiki-tests--add-hyrolo () + "Verify `hywiki-add-hyrolo'." + (mocklet (((hywiki-add-referent "WikiWord" '(hyrolo-fgrep "WikiWord")) => 'hyrolo-referent)) + (should (equal 'hyrolo-referent (hywiki-add-hyrolo "WikiWord"))))) + +(ert-deftest hywiki-tests--add-info-index () + "Verify `hywiki-add-info-index'." + (mocklet (((info) => t) + ((Info-read-index-item-name "Info index item: ") => "index-name") + ((Info-current-filename-sans-extension) => "info") + ((hywiki-add-referent "WikiWord" '(Info-goto-node "(info)index-name")) => 'info-referent)) + (should (equal 'info-referent (hywiki-add-info-index "WikiWord"))))) + +(ert-deftest hywiki-tests--add-info-node () + "Verify `hywiki-add-info-node'." + (mocklet (((info) => t) + ((Info-read-node-name "Info node: ") => "node-name") + ((Info-current-filename-sans-extension) => "info") + ((hywiki-add-referent "WikiWord" '(Info-goto-node "(info)node-name")) => 'info-referent)) + (should (equal 'info-referent (hywiki-add-info-node "WikiWord"))))) + +(ert-deftest hywiki-tests--add-key-series () + "Verify `hywiki-add-key-series'." + (mocklet (((hywiki-add-referent "WikiWord" "{ABC}") => 'key-series-referent)) + (with-simulated-input "ABC RET" + (should (equal 'key-series-referent (hywiki-add-key-series "WikiWord")))) + (with-simulated-input "{ABC} RET" + (should (equal 'key-series-referent (hywiki-add-key-series "WikiWord")))))) + +(ert-deftest hywiki-tests--add-link () + "Verify `hywiki-add-link'." + (mocklet (((hactypes:link-to-file-interactively) => '("file" 20)) + ((hpath:file-position-to-line-and-column "file" 20) => "file:L2:C3") + ((hywiki-add-referent "WikiWord" "file:L2:C3") => 'path-referent)) + (should (equal 'path-referent (hywiki-add-link "WikiWord"))))) + +(ert-deftest hywiki-tests--add-org-id () + "Verify `hywiki-add-org-id'." + ;; Error case - Non org-mode buffer + (let ((filea (make-temp-file "hypb" nil ".txt"))) + (unwind-protect + (with-current-buffer (find-file filea) + (mocklet (((hmouse-choose-link-and-referent-windows) => (list nil (get-buffer-window)))) + (should-error (hywiki-add-org-id "WikiWord") :type '(error)))) + (hy-delete-file-and-buffer filea))) + + (let ((filea (make-temp-file "hypb" nil ".org"))) + (unwind-protect + (with-current-buffer (find-file filea) + (insert "* header\n") + + ;; Error-case - No Org ID and read only + (setq buffer-read-only t) + (mocklet (((hmouse-choose-link-and-referent-windows) => (list nil (get-buffer-window)))) + (should-error (hywiki-add-org-id "WikiWord") :type '(error)) + + ;; Normal case - Org-mode with Org ID + (goto-char (point-max)) + (setq buffer-read-only nil) + (defvar hywiki-test--org-id) + (let ((result (hywiki-add-org-id "WikiWord"))) + (if (stringp result) + (should (string-prefix-p "ID: " result)) + (error "(hywiki-tests--add-org-id): result value is a non-string: %s" result))))) + (hy-delete-file-and-buffer filea)))) + +;; hywiki-add-org-roam-node -- Requires org-roam + (provide 'hywiki-tests) ;;; hywiki-tests.el ends here