diff --git a/ChangeLog b/ChangeLog index cd77ec87..8dc5d02c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2026-07-23 Bob Weiner + +* hywiki.el (hywiki-get-entry): Strip file header when returning + definition as a string, as that is all should be desired. + (hywiki-get-definition, hywiki-get-entry): Change so just + returns nil if first arg is sent as a non-string or an empty string + rather than triggering an error. + (hywiki-display-glossary-entry): Don't display the entry if in + the middle of a 'hywiki-create-referent-and-display' call since that + displays the entry source buffer already. + +* hmouse-drv.el (hkey-help): Conditionalize HyWikiWord glossary entry + definition output on a non-nil 'lbl-key', i.e. non-nil reference. + +2026-07-22 Bob Weiner + +* test/hy-string-tests.el: Add to start 'hypb:in-string-p' testing. + +* man/hyperbole.texi (HyWiki Menu, HyWiki Glossary): Document the ways + to use HyWiki glossary entries. + +* hywiki.el (hywiki-get-term-variant-regexp): Allow the term to be + surrounded by Org emphasis characters. + (hywiki-get-term-variant-regexp): Fix to make case sensitive + so wikiwords are always split on capital letters properly. + hpath.el (hpath:org-normalize-title): Strip any Org emphasis characters. + (hywiki-get-entry): Obey 'regexp-flag' when calling + 'hyrolo-grep-file'. + (hydef): Add macro to use as an Action Button to display HyWiki + glossary definitions. + 2026-07-22 Mats Lidell * test/hywiki-tests.el (hywiki-tests--potential-buffer-p): New test. diff --git a/hmouse-drv.el b/hmouse-drv.el index cfe0de44..a200733c 100644 --- a/hmouse-drv.el +++ b/hmouse-drv.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-90 -;; Last-Mod: 20-Jul-26 at 01:47:30 by Bob Weiner +;; Last-Mod: 23-Jul-26 at 00:17:46 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1185,15 +1185,15 @@ documentation is found." ;; Print Hyperbole button attributes (when (memq cmd-sym '(hui:hbut-act hui:hbut-help)) - (let* ;; (lbl-key (hattr:get 'hbut:current 'lbl-key)) - ((categ (hattr:get 'hbut:current 'categ)) - (attributes (nthcdr 2 (hattr:list 'hbut:current))) - (but-def-symbol (htype:def-symbol - (if (eq categ 'explicit) actype categ))) - (wikiword-referent - (when (eq (htype:def-symbol actype) 'link-to-wikiword) - (hywiki-get-referent - (hattr:get 'hbut:current 'lbl-key))))) + (let* ((lbl-key (hattr:get 'hbut:current 'lbl-key)) + (categ (hattr:get 'hbut:current 'categ)) + (attributes (nthcdr 2 (hattr:list 'hbut:current))) + (but-def-symbol (htype:def-symbol + (if (eq categ 'explicit) actype categ))) + (wikiword-referent + (when (eq (htype:def-symbol actype) 'link-to-wikiword) + (hywiki-get-referent + (hattr:get 'hbut:current 'lbl-key))))) (when wikiword-referent (hattr:set 'hbut:current 'referent-type @@ -1219,16 +1219,17 @@ documentation is found." ;; (hypb:remove-from-plist attributes 'action)) (hattr:report attributes) - ;; Need to save and restore 'hbut:current here since - ;; hywiki-get-definition overwrites it - (unwind-protect - (progn (hattr:copy 'hbut:current 'saved-but) - (setq def (hywiki-get-definition - (ibut:key-to-label (hattr:get 'hbut:current 'lbl-key)))) - (when def - (terpri) - (princ def))) - (hattr:copy 'saved-but 'hbut:current)) + (when lbl-key + (unwind-protect + ;; Need to save and restore 'hbut:current here + ;; since hywiki-get-definition overwrites it + (progn (hattr:copy 'hbut:current 'saved-but) + (setq def (hywiki-get-definition + (ibut:key-to-label lbl-key))) + (when (stringp def) + (terpri) + (princ def))) + (hattr:copy 'saved-but 'hbut:current))) (unless (or assisting (eq categ 'explicit) diff --git a/hpath.el b/hpath.el index 399f2f62..a22b5121 100644 --- a/hpath.el +++ b/hpath.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 1-Nov-91 at 00:44:23 -;; Last-Mod: 16-Jul-26 at 16:57:49 by Bob Weiner +;; Last-Mod: 22-Jul-26 at 15:13:47 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1754,7 +1754,9 @@ but locational suffixes within the file are utilized." "Ignore HASH when ANCHOR is non-null and move point to ANCHOR string if found. Move point to beginning of buffer if HASH is non-nil and ANCHOR is null. With optional INSTANCE-NUM, go to that instance of ANCHOR from the start -of the buffer." +of the buffer. + +Trigger an error if the instance of the non-null anchor requested is not found." (let ((omin (point-min)) (omax (point-max))) (unwind-protect @@ -2026,7 +2028,8 @@ form is what is returned for PATH." (defun hpath:org-normalize-title (title) "Return title in normalized form. -Strip all priority, leading ':' or '-' separators, and stats from TITLE." +Strip all priority, leading ':' or '-' separators, stats and Org emphasis +characters from TITLE." (when title (let ((clean (copy-sequence title))) ;; Strip leading priority: [#B] or [#2} followed by ':' or '-' surrounded by any whitespace @@ -2035,7 +2038,11 @@ Strip all priority, leading ':' or '-' separators, and stats from TITLE." ;; Matches: "- Title", ": Title", " - Title" (setq clean (string-trim (replace-regexp-in-string "\\`[ \t]*[-:][ \t]+" "" clean))) ;; Strip trailing statistics cookies [1/2] or [50%] - (setq clean (replace-regexp-in-string "\\(?: +\\[[0-9%+/]+\\]\\)+\\'" "" clean))))) + (setq clean (replace-regexp-in-string "\\(?: +\\[[0-9%+/]+\\]\\)+\\'" "" clean)) + ;; Strip *bold*’, ‘/italic/’, ‘_underlined_’, ‘=verbatim=’ and ‘~code~’ + ;; Org emphasis characters + (setq clean (replace-regexp-in-string "\\`[ \t]*[*/_=~]\\(.+\\)[*/_=~]" + "\\1" clean))))) (defun hpath:org-normalize-titles () "Get all buffer Org titles in normalized form. diff --git a/hyperbole.el b/hyperbole.el index 92343f9d..9a3cee20 100644 --- a/hyperbole.el +++ b/hyperbole.el @@ -9,7 +9,7 @@ ;; Maintainer: Robert Weiner ;; Maintainers: Robert Weiner , Mats Lidell ;; Created: 06-Oct-92 at 11:52:51 -;; Last-Mod: 14-Jul-26 at 10:01:48 by Bob Weiner +;; Last-Mod: 22-Jul-26 at 11:15:05 by Bob Weiner ;; Released: 10-Mar-24 ;; Version: 9.0.2pre ;; Keywords: comm, convenience, files, frames, hypermedia, languages, mail, matching, mouse, multimedia, outlines, tools, wp @@ -354,20 +354,21 @@ of the commands." ;; f = SELECTED_FRAME (); ;; XSETFRAME (lispy_dummy, f); ;; -;; It seems like the XSETFRAME macro is not properly copying the value of f on initial frame selection under the macOS window system. -;; The problem occurs on other systems as well, e.g. Emacs 25.2 under Windows 7. +;; It seems like the XSETFRAME macro is not properly copying the value of f +;; on initial frame selection under the macOS window system. The problem +;; occurs on other systems as well, e.g. Emacs 25.2 under Windows 7. ;; ;; Hyperbole resolves this problem by setting the ;; `mouse-position-function' variable below to properly set the ;; newly selected frame. -(if (boundp 'mouse-position-function) - (setq mouse-position-function - (lambda (frame-x-dot-y) - "Make `mouse-position' and `mouse-pixel-position' return the selected frame. +(when (boundp 'mouse-position-function) + (setq mouse-position-function + (lambda (frame-x-dot-y) + "Make `mouse-position' and `mouse-pixel-position' return the selected frame. Under macOS and Windows 7 at least, upon initial selection of a new frame, those functions by default still return the prior frame." - (if (consp frame-x-dot-y) (setcar frame-x-dot-y (selected-frame))) - frame-x-dot-y))) + (if (consp frame-x-dot-y) (setcar frame-x-dot-y (selected-frame))) + frame-x-dot-y))) ;; hmouse-drv will load hui-mouse and hmouse-key (mapc #'require '(hsettings hmouse-drv hmouse-sh)) diff --git a/hywiki.el b/hywiki.el index ac2cd9cb..f964176a 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: 21-Jul-26 at 01:46:11 by Bob Weiner +;; Last-Mod: 23-Jul-26 at 11:38:51 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1449,7 +1449,7 @@ calling this function." (gbut:act gbut-name)) (defun hywiki-add-glossary-entry (term) - "Add TERM as a new HyWiki glossary entry to be defined." + "Add/edit TERM as a HyWiki glossary entry with a definition." (let ((glossary (hywiki-get-glossary-file)) (hyrolo-date-format "")) ;; don't add a date (if (= 1 (hyrolo-grep (hywiki-get-term-variant-regexp term) @@ -1461,14 +1461,20 @@ calling this function." ;; Skip past file header (hyrolo-to-next-entry) (hyrolo-edit-entry)) - ;; add a new entry + ;; add a new definition entry using the original term, not any + ;; wikiword transformed version (hyrolo-add term glossary))) + ;; Connect wikiword version of term to the glossary definition (hywiki-add-referent (hywiki-string-to-wikiword term) (cons 'glossary-entry term))) (defun hywiki-display-glossary-entry (_wikiword term) "Display any HyWiki glossary definition for TERM." - (hywiki-get-definition term t)) + ;; Don't display the entry if in the middle of a + ;; `hywiki-create-referent-and-display' call since that displays the entry + ;; source buffer already. + (unless (hyperb:stack-frame '(hywiki-create-referent-and-display)) + (hywiki-get-definition term t))) (defun hywiki-add-hyrolo (wikiword) "Make WIKIWORD search and display `hyrolo-file-list' matches. @@ -2413,8 +2419,12 @@ therein is invalid, trigger an error." (defun hywiki-get-term-variant-regexp (term) "Return a grouped regexp of the allowed glossary variants for TERM string." - (let (str) - (format "\\(%s\\|%s\\|%s\\|%s\\)" + ;; Allow for term downcased, and/or with spaces between capitalized words + ;; or the whole term capitalized. Also allow the term to be surrounded by + ;; Org emphasis characters. + (let ((str) + (case-fold-search nil)) + (format "[*/_=~]?\\(%s\\|%s\\|%s\\|%s\\)[*/_=~]?" (regexp-quote term) (regexp-quote (downcase term)) (regexp-quote (setq str (hywiki-wikiword-to-string term " "))) @@ -2423,12 +2433,13 @@ therein is invalid, trigger an error." ;;;###autoload (defun hywiki-get-definition (term &optional display-flag file) "Return or display the HyWiki glossary definition string for TERM. -Return nil if no match is found. +Return nil if TERM is not a string, if TERM is the empty string or no match +is found. If called interactively or with optional DISPLAY-FLAG non-nil, display a buffer with TERM's definition but don't return it. Get definition from HyWiki's Glossary.org or optional FILE. If the file is not readable or no -matching TERM entry is found, return nil. +matching TERM entry is found, return nil; othewise, return t. If the `consult' package is installed, interactively select and complete the entry to be inserted. @@ -2448,35 +2459,46 @@ top-level headlines are searched. (interactive (list (hywiki-completing-read-glossary-term "HyWiki glossary definition of: ") nil t)) - (when (or (not (stringp term)) (string-empty-p term)) - (error "(hywiki-get-definition): Invalid `term': `%s'" term)) - (let ((glossary (hywiki-get-glossary-file file)) - (term-regexp (hywiki-get-term-variant-regexp term)) - entry) - (setq entry - (cond ((cl-find ?# term) - ;; WikiWord#section or #section - (hywiki-get-entry term-regexp display-flag nil t)) - ((or (hywiki-word-is-p term t) (null file)) - ;; Is a WikiWord or phrase only; match to any of several - ;; forms: WikiWord, wikiword, Wiki Word, wiki word - (when (file-readable-p glossary) - (hywiki-get-entry (concat (if file "" "Glossary#") term-regexp) - display-flag file t))) - (t - (cond ((or (not (stringp file)) (string-empty-p file)) - (error "(hywiki-get-definition): \"%s\" is invalid" file)) - (t - ;; phrase with a file to search - (hywiki-get-entry term-regexp display-flag file t)))))) - (when (stringp entry) - ;; Remove * or # prefix from def entry before returning, so can be - ;; embedded in other doc - (setq entry (substring entry (if (string-match "\\`[*#]+[ \t\n\f]*" - entry) - (match-end 0) - 0))) - (if display-flag t entry)))) + (when (and (stringp term) (not (string-empty-p term))) + (let ((glossary (hywiki-get-glossary-file file)) + entry + index + term-regexp + wikiword) + (cond ((setq index (seq-position term ?#)) + ;; WikiWord#section or #section + (setq wikiword (substring term 0 index) + term (substring term (1+ index)) + term-regexp (hywiki-get-term-variant-regexp term) + file (if (zerop index) + buffer-file-name + (hywiki-get-page-file wikiword)))) + ((or (hywiki-word-is-p term t) (null file)) + ;; Is a WikiWord or phrase only; match to any of several + ;; forms: WikiWord, wikiword, Wiki Word, wiki word -- in + ;; file when given or the Glossary file when not + (when (file-readable-p glossary) + (setq term-regexp (hywiki-get-term-variant-regexp term)) + (unless (and (stringp file) (not (string-empty-p file))) + (setq file glossary)))) + (t + ;; `file' is non-null so try to use that or trigger an error + (when (or (not (stringp file)) (string-empty-p file) + (not (file-readable-p file))) + (error "(hywiki-get-definition): \"%s\" is invalid" file)) + (setq term-regexp (hywiki-get-term-variant-regexp term)))) + + ;; Return and possibly display matching definition + (setq entry (hywiki-get-entry term-regexp display-flag file t)) + + (when (stringp entry) + ;; Remove * or # prefix from def entry before returning, so can be + ;; embedded in other doc + (setq entry (substring entry (if (string-match "\\`[*#]+[ \t\n\f]*" + entry) + (match-end 0) + 0)))) + entry))) (defun hywiki-get-delimited-region () "Immediately before or after a balanced delimiter, return the delimited range. @@ -2526,14 +2548,20 @@ This includes the delimiters: (), {}, <>, [] and \"\" (double quotes)." ;;;###autoload (defun hywiki-get-entry (reference &optional display-flag file regexp-flag) "Return a string of the first HyWiki entry headline containing REFERENCE. -Return nil if no match is found. +Return nil if REFERENCE is not a string, if REFERENCE is the empty string or +no match is found. If called interactively or with optional DISPLAY-FLAG non-nil, display a -buffer with REFERENCE's definition but don't return it. Get definition from -HyWiki's Glossary.org, optional FILE, or the current buffer for #in-file -references. If the file is not readable or no matching REFERENCE entry is -found, return nil. With optional prefix arg, REGEXP-FLAG, treat REFERENCE -as a regular expression instead of a string. +buffer with REFERENCE's definition but don't return it. If the file is not +readable or no matching REFERENCE entry is found, return nil; othewise, +return t. + +Get definition from HyWiki's Glossary.org, optional FILE, or the current +buffer for #in-file references. Trigger an error if an invalid non-nil FILE +argument is sent. + +With optional prefix arg, REGEXP-FLAG, treat REFERENCE as a regular +expression instead of a string. If the `consult' package is installed, interactively select and complete the entry to be inserted. @@ -2551,22 +2579,18 @@ top-level headlines are searched. |------------------+------+---------------+----------------------------------|" (interactive (list (hywiki-read-headline-regexp "Return") current-prefix-arg)) - (when (and (stringp reference) (string-empty-p reference)) - (setq reference nil)) - (when (or (null reference) (not (stringp reference))) - (error "(hywiki-get-entry): Invalid reference: `%s'" reference)) - - (let ((buf (current-buffer)) - (buf-file buffer-file-name) - (found 0) - (word-end (hywiki-word-is-p reference t)) - (consult-flag (and (called-interactively-p 'interactive) (hsys-consult-active-p))) - (phrase "") - entry-to-match - path-list) - (save-window-excursion - (with-current-buffer (get-buffer-create hywiki-glossary-display-buffer) - (let ((hyrolo-display-buffer hywiki-glossary-display-buffer)) + (when (and (stringp reference) (not (string-empty-p reference))) + (let ((hyrolo-display-buffer hywiki-glossary-display-buffer) + (buf-file buffer-file-name) + (found 0) + (word-end (hywiki-word-is-p reference t)) + (consult-flag (and (called-interactively-p 'interactive) (hsys-consult-active-p))) + (phrase "") + entry-to-match + path-list) + (save-window-excursion + (with-current-buffer (get-buffer-create hywiki-glossary-display-buffer) + (setq hyrolo-display-buffer hywiki-glossary-display-buffer) ;; (hyrolo--cache-initialize) (cond ((or consult-flag (not (string-match-p "#" reference)) @@ -2587,7 +2611,7 @@ top-level headlines are searched. path-list (if buf-file (list buf-file) (user-error "(hywiki-get-entry): #section not allowed in non-file buffer: reference = %s; buffer = %S" - reference buf)))) + reference (get-buffer buf-file))))) ((not (string-empty-p phrase)) ;; The phrase is a WikiWord; use this as the file to search (setq path-list (list (expand-file-name @@ -2609,27 +2633,57 @@ top-level headlines are searched. (string-match "\\([^ \t\n\r\"'`]*[^ \t\n\r:\"'`0-9]\\): ?\\([1-9][0-9]*\\)[ :]" reference))) (hyrolo-grep-file (if path-list (car path-list) (match-string-no-properties 1 reference)) - (regexp-quote (if path-list - entry-to-match - (substring reference (match-end 0)))) + (funcall (if regexp-flag #'identity #'regexp-quote) + (if path-list + entry-to-match + (substring reference (match-end 0)))) -1 nil t) (hyrolo-grep (if regexp-flag entry-to-match (regexp-quote entry-to-match)) -1 (hyrolo-expand-path-list (or path-list (list hywiki-directory))) - nil t (not display-flag)))))))) - (if display-flag - (progn - (hyrolo-display-matches) - ;; skip past header to the entry - (unless (zerop found) - (hyrolo-to-next-entry))) - (unless (zerop found) - (with-current-buffer hyrolo-display-buffer - (buffer-string)))))) + nil t (not display-flag))))))) + (if display-flag + (if (zerop found) + (progn (beep) + (message "(hywiki-get-entry): No match for `%s' found in `%s'" + reference + (or path-list hywiki-directory)) + nil) + ;; Display even if no entries are found + (hyrolo-display-matches) + ;; skip past header to the entry + (hyrolo-to-next-entry) + t) + (unless (zerop found) + (with-current-buffer hyrolo-display-buffer + (save-excursion + (goto-char (point-min)) + ;; skip past header to the entry + (hyrolo-to-next-entry) + (buffer-substring (point) (point-max))))))))) + +;;;###autoload +(defmacro hydef (&rest term) + "Display TERM's definition, which may be given as multiple strings or symbols. +All of the following represent the same TERM: ActionKey, \"ActionKey\", +Action Key, action key, and \"action key\", i.e. (hydef action key). + +Use this as a Hyperbole Action Button to hyperlink to an individual HyWiki +definition from ${hywiki-directory}/Glossary.org), i.e. " + `(let ((term-str (mapconcat (lambda (word) + (cond ((symbolp word) (symbol-name word)) + ((stringp word) word) + (t (format "%s" word)))) + ',term " "))) + (when (or (null term-str) (member term-str '("" "t" "nil"))) + (error "(hydef): No term given; must give a term to lookup the definition")) + (hywiki-get-definition term-str t))) (defun hywiki-get-glossary-file (&optional file) "Return the glossary file for the current HyWiki." - (expand-file-name (or file (concat "Glossary" hywiki-file-suffix)) + (expand-file-name (if (and (stringp file) (not (string-empty-p file))) + file + (concat "Glossary" hywiki-file-suffix)) hywiki-directory)) (defun hywiki-get-glossary-terms () @@ -3881,8 +3935,8 @@ When NO-STATS is non-nil, don't include statistics in square brackets." "\\(?:[ \t]*\\(\\[#.\\]\\)\\)?" ;; title and optional stats "\\(?:[ \t]*\\(%s\\)\\)") - ;; exact title - (regexp-quote title))) + ;; exact title in diff formats + (hywiki-get-term-variant-regexp title))) (defun hywiki-org-get-publish-project () "Return the HyWiki Org publish project, a named set of properties. diff --git a/man/hyperbole.texi b/man/hyperbole.texi index 8ba6bd47..7812c45a 100644 --- a/man/hyperbole.texi +++ b/man/hyperbole.texi @@ -7,7 +7,7 @@ @c Author: Bob Weiner @c @c Orig-Date: 6-Nov-91 at 11:18:03 -@c Last-Mod: 20-Jul-26 at 01:29:18 by Bob Weiner +@c Last-Mod: 22-Jul-26 at 23:56:16 by Bob Weiner @c %**start of header (This is for running Texinfo on a region.) @setfilename hyperbole.info @@ -30,7 +30,7 @@ @set txicodequoteundirected @set txicodequotebacktick -@set UPDATED July 20, 2026 +@set UPDATED July 22, 2026 @set UPDATED-MONTH July 2026 @set EDITION 9.0.2pre @set VERSION 9.0.2pre @@ -171,7 +171,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

 Edition 9.0.2pre
-Printed July 20, 2026.
+Printed July 22, 2026.
 
   Published by the Free Software Foundation, Inc.
   Author:    Bob Weiner
@@ -213,7 +213,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 @example
 Edition 9.0.2pre
-July 20, 2026 @c AUTO-REPLACE-ON-SAVE
+July 22, 2026 @c AUTO-REPLACE-ON-SAVE
 
 
   Published by the Free Software Foundation, Inc.
@@ -5155,15 +5155,37 @@ reference is highlighted but no referent is displayed).  Defer
 referent creation until the first activation of the HyWikiWord, at
 which point the HyWiki RefType menu is displayed for selection.
 
-@cindex menu item, HyWiki Glossary
+@cindex menu item, HyWiki glossarY
 @cindex HyWiki Glossary reftype
 @cindex HyWikiWord definition
 @cindex definition, HyWikiWord
 @findex hywiki-get-definition
+@anchor{HyWiki Glossary}
 @item Glossary
-Add a HyWikiWord that displays its own definition from the HyWiki's
-Glossary.org file.  See the documentation string for
-@code{hywiki-get-definition} for more detail.
+Add or edit the definition of a HyWikiWord that displays its own
+definition from the HyWiki's Glossary.org file.
+
+A HyWiki can contain a Glossary.org file with heading titles that
+represent terms associated with the HyWiki.  The body of each heading
+section is the definition of the term.  Terms can consist of multiple
+words and do not have to be HyWikiWords but may be.
+
+@noindent
+There are three ways to work with HyWiki glossary terms:
+
+@enumerate
+@item Use a @dfn{hydef} Action Button to display the term's definition.
+For example, @samp{} or @samp{}
+
+@item Create a HyWikiWord with a glossary referent type.
+With @code{hywiki-mode} active, @bkbd{M-0 M-RET y} or @bkbd{C-h h h c
+y} will turn the wikiword at point into or will prompt you for a
+wikiword name whose referent displays the definition for the wikiword.
+
+@item Programmatically display a glossary entry.
+Call @code{(hywiki-get-definition "term" t)} to display the entry.
+@end enumerate
+
 @end table
 
 @vindex hywiki-directory
@@ -8833,12 +8855,23 @@ publishes/exports an entire HyWiki to HTML for display on the web.
 See the documentation for its implicit button types,
 @code{hywiki-word} and @code{hywiki-existing-word}.
 
+@cindex glossary, HyWiki
+@cindex definition, HyWikiWord
+@cindex HyWikiWord definition
+@item HyWiki Glossary
+A HyWiki can contain a Glossary.org file with heading titles that
+represent terms associated with the HyWiki.  The body of each heading
+section is the definition of the term.  Terms can consist of multiple
+words and do not have to be HyWikiWords but may be.
+
+@xref{HyWiki Glossary}, for more details.
+
 @item HyWikiWord
 A @dfn{HyWikiWord}, or just wikiword, is a PascalCase word that starts
 with a capital letter and contains upper and lowercase letters only
 and has an associated referent (a link or an action).  The default,
-most common referent type, is a @dfn{HyWiki Page}, an Org file with the
-wikiword's name and a @file{.org} suffix that lives in
+most common referent type, is a @dfn{HyWiki Page}, an Org file with
+the wikiword's name and a @file{.org} suffix that lives in
 @code{hywiki-directory}.
 
 HyWikiWords are automatically highlighted and turned into hyperlinks
diff --git a/test/MANIFEST b/test/MANIFEST
index 444cd43d..12da5c0f 100644
--- a/test/MANIFEST
+++ b/test/MANIFEST
@@ -19,6 +19,7 @@ hui-mouse-tests.el      - hui-mouse and hkey-alist Action Key tests
 hui-register-tests.el   - test for hui-register
 hui-select-tests.el     - hui-select tests
 hui-tests.el            - tests for hui.el Hyperbole UI
+hy-string-tests.el      - test whether point is inside or outside of a string
 hy-test-coverage.el     - provide test coverage information
 hy-test-dependencies.el - Hyperbole test dependencies
 hy-test-helpers.el      - unit test helpers
diff --git a/test/demo-tests.el b/test/demo-tests.el
index 7587e246..8c5f0c88 100644
--- a/test/demo-tests.el
+++ b/test/demo-tests.el
@@ -1,9 +1,9 @@
 ;;; demo-tests.el --- unit tests from examples in the DEMO         -*- lexical-binding: t; -*-
-
+;;
 ;; Author:       Mats Lidell 
 ;;
 ;; Orig-Date:    30-Jan-21 at 12:00:00
-;; Last-Mod:     16-Jun-26 at 22:09:58 by Bob Weiner
+;; Last-Mod:     22-Jul-26 at 23:49:19 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
diff --git a/test/hy-string-tests.el b/test/hy-string-tests.el
new file mode 100644
index 00000000..a24dce5b
--- /dev/null
+++ b/test/hy-string-tests.el
@@ -0,0 +1,97 @@
+;;; hy-string-tests.el --- test whether point is inside or outside of a string    -*- lexical-binding: t; -*-
+;;
+;; Author:       Bob Weiner
+;;
+;; Orig-Date:    22-Jul-26 at 23:41:29
+;; Last-Mod:     22-Jul-26 at 23:49:34 by Bob Weiner
+;;
+;; SPDX-License-Identifier: GPL-3.0-or-later
+;;
+;; Copyright (C) 2026  Free Software Foundation, Inc.
+;; See the "HY-COPY" file for license information.
+;;
+;; This file is part of GNU Hyperbole.
+
+;;; Commentary:
+
+;; Test point location relative to string start and end locations.
+
+;;; Code:
+
+;;; ************************************************************************
+;;; Other required Elisp libraries
+;;; ************************************************************************
+
+(require 'cl-lib) ;; For `cl-incf'
+(require 'hypb)   ;; For `hypb:in-string-p'
+
+;; Sample use of next function
+;; (debug-in-string "double-quotes" "str")
+;; (debug-in-string "double-with-single" "' st' 'r' ")
+;; (debug-in-string "python-triple-multi-line" "\"\"\"\n str\n\"\"\"" 'python-mode)
+
+;;; ************************************************************************
+;;; Public functions
+;;; ************************************************************************
+
+(defun debug-in-string (test-name str &optional mode)
+  "With TEST-NAME for each char in STR, print results of whether in the string.
+STR, including delimiters, is inserted into a blank buffer for testing.
+With optional major MODE, a function, that mode is enabled prior to testing the string."
+  (interactive sStr to test: \")
+  (with-temp-buffer
+    (when mode (funcall mode))
+    (insert "\"" str "\"")
+    (with-help-window (format "*%s Results*" (capitalize test-name))
+      (prin1 str)
+      (when mode
+        (princ " - ")
+        (princ (cond ((symbolp mode) (symbol-name mode))
+                     ((stringp mode) mode))))
+      (terpri)
+      (terpri)
+      (goto-char (point-min))
+      (let ((len (+ (length str) 2))
+            (i 1)
+            hypb-in-str
+            ppss-in-str
+            str-start
+            foll-quote)
+        (while (/= i (point-max))
+          (goto-char i)
+          (setq hypb-in-str (hypb:in-string-p)     ;; Hyperbole in-string test
+                ppss-in-str (nth 3 (syntax-ppss))  ;; Emacs in-string test
+                str-start   (nth 8 (syntax-ppss))  ;; Char that starts this string, if any
+                foll-quote  (nth 5 (syntax-ppss))) ;; t if following a quote char
+          (princ
+           (format "%s Pos %2d, char '%c', in-str hypb=%3S %3S=ppss, str-start=%3S, following-quote=%3S"
+                   (if (or (and hypb-in-str ppss-in-str)
+                           (and (not hypb-in-str) (not ppss-in-str)))
+                       "."
+                     "F")
+                   i (following-char)
+                   hypb-in-str ppss-in-str str-start foll-quote
+                   ;; Hyperbole in-string test
+                   (hypb:in-string-p)
+                   ;; Emacs in-string test; any non-nil value is the
+                   ;; character that will terminate the string, or t if the
+                   ;; string should be terminated by a generic string
+                   ;; delimiter
+                   (nth 3 (syntax-ppss))
+                   ;; Character address of start of comment or string;
+                   ;; nil if not in one
+                   (nth 8 (syntax-ppss))
+                   ;; t if following a quote char
+                   (nth 5 (syntax-ppss))
+                   ;; Sixth arg COMMENTSTOP non-nil means stop after the
+                   ;; start of a comment. If it is the symbol
+                   ;; ‘syntax-table’, stop after the start of a comment or a
+                   ;; string, or after end of a comment or a string.
+                   ))
+          (terpri)
+          (cl-incf i))))))
+
+
+(provide 'hy-string-tests)
+
+;;; hy-string-tests.el ends here
diff --git a/test/hywiki-tests.el b/test/hywiki-tests.el
index 19f80dba..c219ba5c 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:     21-Jul-26 at 22:30:31 by Mats Lidell
+;; Last-Mod:     23-Jul-26 at 11:38:53 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;