branch: externals/hyperbole commit 8a8367189c10598d81b57908887aa5925e0cfc38 Merge: d4aaee59fe 0c019d9b8f Author: Robert Weiner <r...@gnu.org> Commit: GitHub <nore...@github.com>
Merge pull request #550 from rswgnu/rsw hynote.el - Add initial HyNote link support for Org and Org Roam --- ChangeLog | 47 ++++++++++++--- MANIFEST | 11 ++-- Makefile | 10 +-- hbut.el | 11 +++- hibtypes.el | 8 ++- hmouse-drv.el | 10 ++- hui-em-but.el => hproperty.el | 80 ++++++++++++++++++++++-- hsettings.el | 8 +-- hsys-org.el | 44 +++++--------- hynote.el | 137 ++++++++++++++++++++++++++++++++++++++++++ hypb.el | 6 ++ hywiki.el | 55 +++-------------- test/hsys-org-tests.el | 5 +- test/hui-tests.el | 6 +- 14 files changed, 319 insertions(+), 119 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8f6c08d40..77a0d444e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,42 @@ +2024-06-29 Bob Weiner <r...@gnu.org> + +* test/hui-tests.el (hui-ebut-create-link-to-info-index-using-completion): + When finished, kill all *info*<#> buffers. + +* hui-em-but.el: Rename to "hproperty.el". + +* hui-em-but.el (hproperty:char-property-start, hproperty:char-property-end, + hproperty:char-property-range, hproperty:overlay-range) + hproperty:char-property-contains-p): + Add char-property and overlay utility functions and use in "hsys-org.el" + and "hsys-org-tests.el"; adds compatibility with Org mode 9.7 and earlier. + +2024-06-25 Bob Weiner <r...@gnu.org> + +* hibtypes.el (hynote): Add for Org and Org Roam links by name. + MANIFEST (hynote.el): Add. + Makefile (EL_COMPILE): Add hynote.el. + +* hynote.el (hynote-directory-list, hynote-find-file-stem): Add. + +* hbut.el (ibut:create): Add debugging to show the type name if an ibtype + evaluation fails. + hmouse-drv.el (hkey-execute, hkey-help): Change 'eval' to 'hypb:eval-debug' + to show a backtrace whenever an error occurs. + 2024-06-23 Bob Weiner <r...@gnu.org> -* Makefile: (dockerized-run): Add to intweractively run dockerized versions - of Emacs with Hyperbole. Update Commentary to summarize dockerized +* hynote.el (hynote-get-files, hynote-get-file-stem-list, hynote-find-file, + hynote-file-stem-start-end-at): + Add these functions to find non-HyWikiWord files in `hywiki-directory' when + referenced by stem name, e.g. Action key on Non-Wiki-Word displays + Non-Wiki-Word.org. + (hynote-file): Add ibtype to display non-HyWikiWord files in + hywiki-directory'. + + +* Makefile: (docker-run): Add to intweractively run docker versions + of Emacs with Hyperbole. Update Commentary to summarize docker targets that build, byte-compile and run Hyperbole. 2024-06-22 Mats Lidell <ma...@gnu.org> @@ -12,7 +47,7 @@ * Makefile (dockerized-update): Target to update (pull) the Emacs docker image. - (dockerized): Copy source to docker so not local workspace is affected + (dockererized): Copy source to docker so not local workspace is affected when running targets in the docker environment. 2024-06-22 Bob Weiner <r...@gnu.org> @@ -31,12 +66,6 @@ * hywiki.el (hywiki-word-at): Fix to use 'hywiki-word-with-optional-section-regexp' instead of 'hywiki-word-regexp' so handles sections properly. (hywiki-word-highlight-flag): Improve documentation. - (hywiki-get-files, hywiki-get-file-stem-list, hywiki-find-file): - Add these functions to find non-HyWikiWord files in `hywiki-directory' when - referenced by stem name, e.g. Action key on Non-Wiki-Word displays - Non-Wiki-Word.org. - (hywiki-file): Add ibtype to display non-HyWikiWord files in - hywiki-directory'. (hywiki-get-page-file): Allow name to include 'hywiki-file-suffix' for non-HyWikiWord files. Also, rename to 'hywiki-get-file'. diff --git a/MANIFEST b/MANIFEST index f2ded012f9..99d3a9ed0c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -36,10 +36,8 @@ hmouse-key.el - Setup Smart Key mouse bindings hmouse-mod.el - Action Key acts as CONTROL modifier and Assist Key as META modifier (Unused) hmouse-sh.el - System-dependent Smart Mouse Key bindings hmouse-tag.el - Smart Key support of programming language tags location -hycontrol.el - Interactive sizing, moving, replicating and deleting of windows and frames -hyrolo-menu.el - Pulldown and popup menus of HyRolo commands +hproperty.el - GNU Emacs button highlighting and flashing support hui-dired-sidebar.el - Smart Key support for dired sidebar -hui-em-but.el - GNU Emacs button highlighting and flashing support hui-jmenu.el - Popup menus for jumping to and managing buffers, frames, and windows hui-menu.el - Menubar menu of GNU Hyperbole commands hui-mini.el - Single line command menus for GNU Hyperbole @@ -48,6 +46,8 @@ hui-select.el - Select delimited or larger and larger syntax-driven regio hui-treemacs.el - GNU Hyperbole Smart Key support for the Treemacs file manager package hui-window.el - Smart Mouse Key window and modeline depress/release actions hui.el - GNU Hyperbole button and hyperlink user interface +hycontrol.el - Interactive sizing, moving, replicating and deleting of windows and frames +hyrolo-menu.el - Pulldown and popup menus of HyRolo commands * --- APPLICATION PROGRAMMING INTERFACE --- hact.el - GNU Hyperbole button action handling @@ -78,9 +78,10 @@ hyrolo.el - Hierarchical, multi-file, easy-to-use record management s hyrolo.py - Output file header and matching entries from HyRolo files via the command-line hyrolo-logic.el - Logic functions for GNU Hyperbole Rolo files -* --- HYPERBOLE WIKI --- -hywiki.el - Hyperbole's auto-wikiword note-taking system +* --- HYPERBOLE NOTES AND WIKI --- hasht.el - Create hash tables from lists and operate on them. +hynote.el - Link to Org and Org Roam notes by name +hywiki.el - Hyperbole's auto-wikiword note-taking system * --- USENET NEWS SUPPORT --- hgnus.el - GNU Hyperbole buttons in news reader/poster: GNUS diff --git a/Makefile b/Makefile index 7cc0b848a1..fc840442c6 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Author: Bob Weiner # # Orig-Date: 15-Jun-94 at 03:42:38 -# Last-Mod: 23-Jun-24 at 00:16:22 by Bob Weiner +# Last-Mod: 29-Jun-24 at 18:59:38 by Bob Weiner # # Copyright (C) 1994-2023 Free Software Foundation, Inc. # See the file HY-COPY for license information. @@ -195,12 +195,12 @@ EL_COMPILE = hact.el hactypes.el hargs.el hbdata.el hbmap.el hbut.el \ hib-social.el hibtypes.el \ hinit.el hload-path.el hmail.el hmh.el hmoccur.el hmouse-info.el \ hmouse-drv.el hmouse-key.el hmouse-mod.el hmouse-sh.el hmouse-tag.el \ - hpath.el hrmail.el hsettings.el hsmail.el hsys-flymake.el hsys-org.el \ - hsys-org-roam.el hsys-www.el hsys-xref.el hsys-youtube.el htz.el \ + hpath.el hproperty.el hrmail.el hsettings.el hsmail.el hsys-flymake.el \ + hsys-org.el hsys-org-roam.el hsys-www.el hsys-xref.el hsys-youtube.el htz.el \ hycontrol.el hui-jmenu.el hui-menu.el hui-mini.el hui-mouse.el hui-select.el \ - hui-treemacs.el hui-window.el hui.el hvar.el hversion.el hypb.el hyperbole.el \ + hui-treemacs.el hui-window.el hui.el hvar.el hversion.el hynote.el hypb.el hyperbole.el \ hyrolo-demo.el hyrolo-logic.el hyrolo-menu.el hyrolo.el hywconfig.el hywiki.el \ - hasht.el set.el hypb-ert.el hui-dired-sidebar.el hypb-maintenance.el hui-em-but.el \ + hasht.el set.el hypb-ert.el hui-dired-sidebar.el hypb-maintenance.el \ hui-register.el EL_SRC = $(EL_COMPILE) diff --git a/hbut.el b/hbut.el index 501d92a11d..958db847ee 100644 --- a/hbut.el +++ b/hbut.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 18-Sep-91 at 02:57:09 -;; Last-Mod: 23-Jun-24 at 00:11:37 by Mats Lidell +;; Last-Mod: 25-Jun-24 at 01:03:43 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1957,7 +1957,14 @@ If a new button is created, store its attributes in the symbol, (setq ibtype-point (point)) (while (and (not is-type) types) (setq itype (car types)) - (when (and itype (setq args (funcall itype))) + (when (condition-case () + (and itype (setq args (funcall itype))) + ;; Purposely trigger another error + ;; here by sending a symbol + ;; argument to the message call + ;; below so can see the value of + ;; itype whose funcall failed above. + (error (message itype))) (setq is-type itype) ;; Any implicit button type check should leave point ;; unchanged. Trigger an error if not. diff --git a/hibtypes.el b/hibtypes.el index ed2156f614..c4b11e4467 100644 --- a/hibtypes.el +++ b/hibtypes.el @@ -91,7 +91,13 @@ ;; ibtype priorities. ;;; ======================================================================== -;;; Creates and display personal wiki pages with auto-wikiword links +;;; Displays Org and Org Roam files and sections by name link +;;; ======================================================================== + +(load "hynote") + +;;; ======================================================================== +;;; Creates and displays personal wiki pages and sections with auto-wikiword links ;;; ======================================================================== (load "hywiki") diff --git a/hmouse-drv.el b/hmouse-drv.el index 59b2b43f4a..c748fced8b 100644 --- a/hmouse-drv.el +++ b/hmouse-drv.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 04-Feb-90 -;; Last-Mod: 8-Mar-24 at 11:06:21 by Mats Lidell +;; Last-Mod: 25-Jun-24 at 02:13:58 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1029,7 +1029,7 @@ predicate is found." (while (and (null pred-value) (setq hkey-form (car hkey-forms))) (if (setq hkey-action (if assisting (cddr hkey-form) (cadr hkey-form)) pred (car hkey-form) - pred-value (eval pred)) + pred-value (hypb:eval-debug pred)) (progn ;; Any Smart Key predicate should leave point unchanged. ;; Trigger an error if not. @@ -1041,9 +1041,7 @@ predicate is found." (when hkey-debug (hkey-debug pred pred-value hkey-action)) (if hkey-debug - (let ((debug-on-error t) - (debug-on-quit t)) - (eval hkey-action)) + (hypb:eval-debug hkey-action) (eval hkey-action))) (setq hkey-forms (cdr hkey-forms)))) pred-value)) @@ -1062,7 +1060,7 @@ documentation is found." (assist-flag assisting) hkey-form pred-value call calls cmd-sym doc) (while (and (null pred-value) (setq hkey-form (car hkey-forms))) - (or (setq pred-value (eval (car hkey-form))) + (or (setq pred-value (hypb:eval-debug (car hkey-form))) (setq hkey-forms (cdr hkey-forms)))) (if pred-value (setq call (if assisting (cdr (cdr hkey-form)) diff --git a/hui-em-but.el b/hproperty.el similarity index 80% rename from hui-em-but.el rename to hproperty.el index 7bce522728..2a34918c23 100644 --- a/hui-em-but.el +++ b/hproperty.el @@ -1,9 +1,9 @@ -;;; hui-em-but.el --- GNU Emacs button highlighting and flashing support -*- lexical-binding: t; -*- +;;; hproperty.el --- GNU Emacs button highlighting and flashing support -*- lexical-binding: t; -*- ;; ;; Author: Bob Weiner ;; ;; Orig-Date: 21-Aug-92 -;; Last-Mod: 26-May-24 at 17:24:25 by Bob Weiner +;; Last-Mod: 29-Jun-24 at 18:57:42 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -261,6 +261,78 @@ See `hproperty:but-get'." (add-to-list 'yank-handled-properties '(hproperty:but-face . hproperty:but-create-on-yank)) +;;; char-property and overlay utility functions + +(defun hproperty:char-property-contains-p (pos property value) + "At POS if PROPERTY contains VALUE (a symbol), return VALUE, else nil." + (let ((val (get-char-property pos property))) + (when (or (eq val value) + ;; `val' may be a list of property values + (and (listp val) (memq value val))) + value))) + +(defun hproperty:char-property-start (pos property value) + "From POS, return the start of text PROPERTY with VALUE overlapping POS. +Otherwise, return nil. Value must be a symbol." + (when-let ((val (hproperty:char-property-contains-p pos property value)) + (prev pos)) + ;; Can't use `previous-single-char-property-change' below + ;; because it checks for any change in the property value, not + ;; just if the property contains the value desired. + (while (and (setq prev (1- prev)) + (>= prev (point-min)) + (hproperty:char-property-contains-p prev property value))) + (max (1+ prev) (point-min)))) + +(defun hproperty:char-property-end (pos property value) + "From POS, return the end of text PROPERTY with VALUE overlapping POS. +Otherwise, return nil. Value must be a symbol." + (when-let ((val (hproperty:char-property-contains-p pos property value)) + (next pos)) + ;; Can't use `next-single-char-property-change' below + ;; because it checks for any change in the property value, not + ;; just if the property contains the value desired. + (while (and (setq next (1+ next)) + (<= next (point-max)) + (hproperty:char-property-contains-p next property value))) + (min next (point-max)))) + +(defun hproperty:char-property-range (pos property &optional value) + "Return a char-property range (start . end) at POS where PROPERTY = VALUE. +Return nil if no such range. If POS is nil, use point. +VALUE is optional; if omitted, use the first char-property at POS with PROPERTY." + (unless pos (setq pos (point))) + (let ((start pos) + (end pos) + val) + (when (or (null value) + (eq value (setq val (hproperty:char-property-contains-p pos property value)))) + (setq start (hproperty:char-property-start pos property val) + end (hproperty:char-property-end pos property val))) + (unless (or (null start) (null end) (= start end)) + (cons start end)))) + +(defun hproperty:overlay-range (pos property &optional value) + "Return the first overlay range (start . end) at POS where PROPERTY = VALUE. +Return nil if no such overlay range. If POS is nil, use point. +VALUE is optional; if omitted, use the first overlay at POS with PROPERTY. + +Use `hproperty:char-property-range' for the same capability but for +both text-properties and overlays." + (unless pos (setq pos (point))) + (let ((start pos) + (end pos) + val) + (catch 'end + (dolist (overlay (overlays-at pos t)) + (when (and (setq val (overlay-get overlay property)) + (or (null value) (eq val value))) + (setq start (overlay-start overlay) + end (overlay-end overlay)) + (throw 'end nil)))) + (unless (= start end) + (cons start end)))) + ;;; ************************************************************************ ;;; Private functions ;;; ************************************************************************ @@ -375,6 +447,6 @@ hproperty:color-ptr." "Button used to highlight an item in a listing buffer.") (make-variable-buffer-local 'hproperty:item-button) -(provide 'hui-em-but) +(provide 'hproperty) -;;; hui-em-but.el ends here +;;; hproperty.el ends here diff --git a/hsettings.el b/hsettings.el index 7e1994fdaa..cac10afe16 100644 --- a/hsettings.el +++ b/hsettings.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 15-Apr-91 at 00:48:49 -;; Last-Mod: 13-Apr-24 at 11:22:31 by Bob Weiner +;; Last-Mod: 29-Jun-24 at 18:57:18 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -38,8 +38,8 @@ (defvar helm-allow-mouse) (defvar htz:local) ; "htz.el" -(declare-function hproperty:but-create "hui-em-but") -(declare-function hproperty:but-flash "hui-em-but") +(declare-function hproperty:but-create "hproperty") +(declare-function hproperty:but-flash "hproperty") (declare-function hyperbole-minibuffer-menu "hui-mini") (declare-function hyperbole-menubar-menu "hui-menu") @@ -298,7 +298,7 @@ then runs the search." "Button flash No-op.") (cond ((not noninteractive) - (require 'hui-em-but) + (require 'hproperty) ;; Highlight explicit buttons whenever a file is read in. (add-hook 'find-file-hook #'hproperty:but-create t) (defalias 'hui:but-flash #'hproperty:but-flash))) diff --git a/hsys-org.el b/hsys-org.el index 11dbde4471..259aa93760 100644 --- a/hsys-org.el +++ b/hsys-org.el @@ -3,7 +3,7 @@ ;; Author: Bob Weiner ;; ;; Orig-Date: 2-Jul-16 at 14:54:14 -;; Last-Mod: 22-Jun-24 at 23:43:08 by Mats Lidell +;; Last-Mod: 29-Jun-24 at 18:55:30 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -31,7 +31,7 @@ ;;; ************************************************************************ (eval-when-compile (require 'hmouse-drv)) -(require 'hbut) +(require 'hproperty) ;; requires 'hbut (require 'org) (require 'org-element) (require 'org-fold nil t) @@ -368,21 +368,6 @@ Match to all todos if `keyword' is nil or the empty string." (org-occur (concat "^" org-outline-regexp " *" (regexp-quote keyword))) keyword)) -(defun hsys-org-region-with-text-property-value (pos property) - "Return region around POS that shares its text PROPERTY value, else nil. -Return the (start . end) buffer positions of the region." - (when (null pos) (setq pos (point))) - (let ((property-value (get-text-property pos property)) - (start-point pos)) - (when property-value - ;; Can't use previous-single-property-change here because it - ;; ignores characters that lack the property, i.e. have nil values. - (if (bobp) - (setq start-point (point-min)) - (while (equal (get-text-property (1- start-point) property) property-value) - (setq start-point (1- start-point)))) - (cons start-point (next-single-property-change start-point property))))) - (defun hsys-org-agenda-item-at-p () "Return non-nil if point is on an Org Agenda view item line, else nil." (and (apply #'derived-mode-p '(org-agenda-mode)) @@ -453,7 +438,7 @@ Assume caller has already checked that the current buffer is in `org-mode'." Link region is (start . end) and includes delimiters, else nil." (and (hsys-org-face-at-p 'org-link) (equal (get-text-property (point) 'help-echo) "Radio target link") - (hsys-org-region-with-text-property-value (point) 'face))) + (hproperty:char-property-range (point) 'face 'org-link))) (defun hsys-org-radio-target-def-at-p () "Return target region iff point is on a <<<radio target>>> definition. @@ -461,18 +446,19 @@ Target region is (start . end) and includes any delimiters, else nil." (when (hsys-org-target-at-p) (save-excursion (unless (looking-at org-radio-target-regexp) - (goto-char (or (previous-single-property-change (point) 'face) (point-min)))) + (goto-char (or (hproperty:char-property-start (point) 'face 'org-target) + (point-min)))) (when (looking-at "<<<") (goto-char (match-end 0))) (and (hsys-org-face-at-p 'org-target) - (hsys-org-region-with-text-property-value (point) 'face))))) + (hproperty:char-property-range (point) 'face 'org-target))))) (defun hsys-org-radio-target-at-p () "Return region iff point is on a <<<radio target>>> or a link to one. The region is (start . end) and includes any delimiters, else nil." (and (or (hsys-org-radio-target-def-at-p) (hsys-org-radio-target-link-at-p)) - (hsys-org-region-with-text-property-value (point) 'face))) + (hproperty:char-property-range (point) 'face 'org-target))) (defun hsys-org-internal-target-link-at-p () "Return link text region iff point is on an Org mode internal target link. @@ -480,7 +466,7 @@ Link region is (start . end) and includes delimiters, else nil." (and (hsys-org-face-at-p 'org-link) (not (equal (get-text-property (point) 'help-echo) "Radio target link")) (hsys-org-link-at-p) - (hsys-org-region-with-text-property-value (point) 'face))) + (hproperty:char-property-range (point) 'face 'org-link))) (defun hsys-org-internal-target-def-at-p () "Return target region iff point is on <<internal target>> definition. @@ -488,26 +474,24 @@ Target region is (start . end) and includes any delimiters, else nil." (when (hsys-org-target-at-p) (save-excursion (unless (looking-at org-target-regexp) - (goto-char (or (previous-single-property-change (point) 'face) (point-min)))) + (goto-char (or (hproperty:char-property-start (point) 'face 'org-target) + (point-min)))) (when (looking-at "<<") (goto-char (match-end 0))) (and (hsys-org-face-at-p 'org-target) - (hsys-org-region-with-text-property-value (point) 'face))))) + (hproperty:char-property-range (point) 'face 'org-target))))) (defun hsys-org-internal-target-at-p () - "Return region iff point is on an <<internal target>> or a link to one. + "Return target region iff point is on an <<internal target>> or a link to one. The region is (start . end) and includes any delimiters, else nil." (and (or (hsys-org-internal-target-def-at-p) (hsys-org-internal-target-link-at-p)) - (hsys-org-region-with-text-property-value (point) 'face))) + (hproperty:char-property-range (point) 'face 'org-target))) (defun hsys-org-face-at-p (org-face-type) "Return ORG-FACE-TYPE iff point is on a character with that face, else nil. ORG-FACE-TYPE must be a symbol, not a symbol name." - (let ((face-prop (get-text-property (point) 'face))) - (when (or (eq face-prop org-face-type) - (and (listp face-prop) (memq org-face-type face-prop))) - org-face-type))) + (hproperty:char-property-contains-p (point) 'face org-face-type)) ;; Adapted from Org code (defun hsys-org-search-internal-link-p (target) diff --git a/hynote.el b/hynote.el new file mode 100644 index 0000000000..8f16206fd5 --- /dev/null +++ b/hynote.el @@ -0,0 +1,137 @@ +;;; hynote.el --- Link to Org and Org Roam notes by name -*- lexical-binding: t; -*- +;; +;; Author: Bob Weiner +;; +;; Orig-Date: 23-Jun-24 at 12:50:37 +;; Last-Mod: 25-Jun-24 at 02:39:05 by Bob Weiner +;; +;; SPDX-License-Identifier: GPL-3.0-or-later +;; +;; Copyright (C) 2024 Free Software Foundation, Inc. +;; See the "HY-COPY" file for license information. +;; +;; This file is part of GNU Hyperbole. + +;;; Commentary: +;; +;; This is Hyperbole's note taking system, HyNote. It utilizes the +;; Org mode or the Koutliner file format plus UUIds and HyRolo for note lookups. +;; +;; See all the autoloaded functions herein for interactive commands. +;; See the Info manual entry "(hyperbole)HyNote" for usage information. + +;;; Code: +;;; ************************************************************************ +;;; Other required Elisp libraries +;;; ************************************************************************ + +(require 'hyrolo) +(require 'hywiki) + +;;; ************************************************************************ +;;; Public Implicit Button and Action Types +;;; ************************************************************************ + +(defun hynote-file-stem-start-end-at () + "Return (file-stem start end) if on a `hynote-directory-list' file stem. +Otherwise, return (nil nil nil)." + (or (hpath:delimited-possible-path nil t) + (list nil nil nil))) + +(defib hynote-file () + "When on a HyNote file name stem, display the file and its optional section. +This type is active only in buffers where `hywiki-active-in-current-buffer-p' +is true. This may require that (hywiki-mode) has been enabled." + (when (hywiki-active-in-current-buffer-p) + (cl-destructuring-bind (file-stem-name start end) + (hynote-file-stem-start-end-at) + (when file-stem-name + (let ((file (hynote-get-file file-stem-name)) + section) + (when (and file (file-readable-p file)) + (setq section (when (string-match "#" file-stem-name) + (substring file-stem-name (match-beginning 0)))) + (ibut:label-set file-stem-name start end) + (hact 'hynote-find-file file section))))))) + +(defun hynote-find-file (file &optional section) + "Display an existing FILE starting at SECTION. +SECTION must be the name of a heading from the FILE and should begin +with \"#\", though this function will add \"#\" if missing. + +Return the absolute path to any file successfully found, else nil. +After successfully finding a file and reading it into a buffer, run +`hynote-find-file-hook'." + (interactive (list (completing-read "Find HyNote file: " + (hynote-get-files)))) + (when (and (stringp file) (file-readable-p file)) + (when (and (stringp section) (not (string-prefix-p "#" section))) + (setq section (concat "#" section))) + (hpath:find (concat file section)) + (hywiki-maybe-highlight-page-names) + (run-hooks 'hynote-find-file-hook) + file)) + +(defun hynote-find-file-stem (file-stem-name) + "Display an existing FILE-STEM-NAME from `hynote-directory-list'. +Return the absolute path to any file successfully found, else nil. + +After successfully finding a file and reading it into a buffer, run +`hynote-find-file-hook'." + (interactive (list (completing-read "Find HyNote file: " + (hynote-get-file-stems)))) + (when (stringp file-stem-name) + (let ((file (hynote-get-file file-stem-name)) + section) + (when (file-readable-p file) + (setq section (when (string-match "#" file-stem-name) + (substring file-stem-name (match-beginning 0)))) + (when file + (hpath:find (concat file section)) + (hywiki-maybe-highlight-page-names) + (run-hooks 'hynote-find-file-hook) + file))))) + +;;; ************************************************************************ +;;; Public variables +;;; ************************************************************************ + +(defvar hynote-directory-list '("~/org/" "~/org-roam/") + "Directories in which to find HyNote Org files.") + +;;; ************************************************************************ +;;; Public functions +;;; ************************************************************************ + +(defun hynote-get-file (file-stem-name) + "Return existing file path in `hynote-directory-list' from FILE-STEM-NAME. +File name must end with `hyrolo-file-suffix-regexp'. No +validation of FILE-STEM-NAME is done." + ;; Remove any #section from `file-stem-name' + (setq file-stem-name (if (string-match "#" file-stem-name) + (substring file-stem-name 0 (match-beginning 0)) + file-stem-name)) + (locate-file file-stem-name hynote-directory-list + '(".org" ".md" ".kotl" ".kot"))) + +(defun hynote-get-files () + "Return `hynote-directory-list' files ending with `hyrolo-file-suffix-regexp'. +File names returned are relative to `hynote-directory-list'." + (mapcan + (lambda (dir) + (make-directory dir t) + (when (file-readable-p dir) + (directory-files dir nil (concat "^[^#]+" hyrolo-file-suffix-regexp)))) + hynote-directory-list)) + +(defun hynote-get-file-stems () + "Return the list of existing HyWiki files sans their `hynote-file-suffixes'. +This includes both Hynote page files and others. Stems returned are +relative to `hynote-directory-list'." + (mapcar #'file-name-sans-extension (hynote-get-files))) + +;;; ************************************************************************ +;;; Private functions +;;; ************************************************************************ + +(provide 'hynote) diff --git a/hypb.el b/hypb.el index 34a67d26a9..d804b5e064 100644 --- a/hypb.el +++ b/hypb.el @@ -476,6 +476,12 @@ the `format' function." (put 'error 'error-message msg) (error msg))) +(defun hypb:eval-debug (sexp) + "Eval SEXP and on error show a debug backtrace of the problem." + (let ((debug-on-error t) + (debug-on-quit t)) + (eval sexp))) + (defun hypb:fgrep-git-log (string) "List git log entries whose changesets include STRING for selection and display. Listing is asynchronous. A press of RET, the Action Key or the diff --git a/hywiki.el b/hywiki.el index 89ca51790c..d0fdda29fd 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: 23-Jun-24 at 00:12:37 by Mats Lidell +;; Last-Mod: 29-Jun-24 at 18:56:47 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -105,7 +105,7 @@ (require 'hasht) (require 'hpath) (require 'hypb) -(require 'hui-em-but) +(require 'hproperty) (require 'outline) ;; For `outline-mode-syntax-table' (eval-and-compile @@ -381,21 +381,6 @@ See the Info documentation at \"(hyperbole)HyWiki\". ;;; Public Implicit Button and Action Types ;;; ************************************************************************ -(defun hywiki-file-stem-start-end-at () - "Return (file-stem start-pos end-pos) if on a `hywiki-directory' file stem. -Otherwise, return (nil nil nil)." - (or (hpath:delimited-possible-path nil t) - (list nil nil nil))) - -(defib hywiki-file () - "When on a HyWiki file name stem, display the file and its optional section." - (cl-destructuring-bind (file-stem-name start end) - (hywiki-file-stem-start-end-at) - (when (and file-stem-name - (file-readable-p (hywiki-get-file file-stem-name))) - (ibut:label-set file-stem-name start end) - (hact 'hywiki-find-file file-stem-name)))) - (defib hywiki-word () "When on a HyWiki word, display its page and optional section." (let ((page-name (hywiki-word-at))) @@ -403,26 +388,6 @@ Otherwise, return (nil nil nil)." (ibut:label-set page-name (match-beginning 0) (match-end 0)) (hact 'hywiki-find-page page-name)))) -(defun hywiki-find-file (file-stem-name) - "Display an existing non-HyWikiWord FILE-STEM-NAME from `hywiki-directory'. -Return the absolute path to any file successfully found, else nil. - -After successfully finding a file and reading it into a buffer, run -`hywiki-find-file-hook'." - (interactive (list (completing-read "Find HyWiki file: " - (hywiki-get-file-stem-list)))) - (when (stringp file-stem-name) - (let ((file (hywiki-get-file file-stem-name)) - section) - (when (file-readable-p file) - (setq section (when (string-match "#" file-stem-name) - (substring file-stem-name (match-beginning 0)))) - (when file - (hpath:find (concat file section)) - (hywiki-maybe-highlight-page-names) - (run-hooks 'hywiki-find-file-hook) - file))))) - (defun hywiki-find-page (&optional page-name prompt-flag) "Display HyWiki PAGE-NAME or a regular file with PAGE-NAME nil. Return the absolute path to any page successfully found; nil if @@ -440,7 +405,7 @@ successfully finding a page and reading it into a buffer, run (if (or (stringp page-name) in-hywiki-directory-flag) (progn (when in-page-flag - ;; Current buffer must be the desired page (called from 'find-file-hook') + ;; Current buffer must be the desired page (unless in-hywiki-directory-flag (error "(hywiki-find-page): No `page-name' given; buffer file must be in `hywiki-directory', not %s" default-directory)) @@ -467,10 +432,10 @@ successfully finding a page and reading it into a buffer, run (hywiki-maybe-highlight-page-names) (run-hooks 'hywiki-find-page-hook) page-file))) - ;; When called from `find-file-hook' without a page-name and outside - ;; hywiki-directory, just find as a regular file and use next line - ;; to highlight HyWikiWords only if buffer was not previously - ;; highlighted. + ;; When called from without a page-name and outside + ;; hywiki-directory, just find as a regular file and use next + ;; line to highlight HyWikiWords only if buffer was not + ;; previously highlighted. (hywiki-maybe-highlight-page-names)))) ;;; ************************************************************************ @@ -896,12 +861,6 @@ relative to `hywiki-directory'." hywiki-directory nil (concat "^[^#]+" (regexp-quote hywiki-file-suffix) "$"))))) -(defun hywiki-get-file-stem-list () - "Return the list of existing HyWiki files sans their `hywiki-file-suffix'. -This includes both HyWiki page files and others. Stems returned are -relative to `hywiki-directory'." - (mapcar #'file-name-sans-extension (hywiki-get-files))) - (defun hywiki-get-page (page-name) "Return the absolute path of HyWiki PAGE-NAME or nil if it does not exist." (if (and (stringp page-name) (not (string-empty-p page-name)) diff --git a/test/hsys-org-tests.el b/test/hsys-org-tests.el index 9b905d066c..2c7258d58b 100644 --- a/test/hsys-org-tests.el +++ b/test/hsys-org-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 23-Apr-21 at 20:55:00 -;; Last-Mod: 9-Apr-24 at 09:32:53 by Mats Lidell +;; Last-Mod: 29-Jun-24 at 15:13:29 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -41,7 +41,8 @@ (insert "* 1\n** 2\n*** 3\n") (goto-char 1) (font-lock-ensure) - (should (equal (hsys-org-region-with-text-property-value 1 'face) '(1 . 4))))) + (should (equal (hproperty:char-property-range 1 'face 'org-level-1) + '(1 . 4))))) ;; TODO: org-agenda-item-at-p diff --git a/test/hui-tests.el b/test/hui-tests.el index 39c08efc5c..6c5d11fa0d 100644 --- a/test/hui-tests.el +++ b/test/hui-tests.el @@ -253,9 +253,9 @@ Ensure modifying the button but keeping the label does not create a double label (hy-test-helpers:consume-input-events) (hy-test-helpers-verify-hattr-at-p :actype 'actypes::link-to-Info-index-item :args '("(emacs)Package") :loc file :lbl-key "emacs-package-button")) - (progn - (kill-buffer "*info*") - (hy-delete-file-and-buffer file))))) + ;; There may be multiple *info* buffers, e.g. *info*<2> + (kill-matching-buffers "^\\*info\\*" nil t) + (hy-delete-file-and-buffer file)))) (ert-deftest hui-gibut-create-link-to-file () "Programatically create implicit button link to file."