[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/hyperbole 6cd7a45434 1/9: hywiki.el - Add global HyWiki
From: |
ELPA Syncer |
Subject: |
[elpa] externals/hyperbole 6cd7a45434 1/9: hywiki.el - Add global HyWiki page override & custom referent types |
Date: |
Mon, 16 Dec 2024 15:58:30 -0500 (EST) |
branch: externals/hyperbole
commit 6cd7a45434e7bc7b8d076a134e5b32eb6be263e4
Author: bw <rsw@gnu.org>
Commit: bw <rsw@gnu.org>
hywiki.el - Add global HyWiki page override & custom referent types
defcustom hywiki-display-page-function #'hpath:find
Hyperbole function to display HyWiki pages.
defcustom hywiki-allow-plurals-flag t
Non-nil means plural HyWikiWords have the same referent as the singular
form.
Minibuffer menu prompt for per wikiword referent type overrides looks
like this:
HyWiki TestAdds Type> Bookmark Command Find Gbut HyRolo Keys
InfoIndex infoNode OrgID orgRoamNode Path Sexp
---
ChangeLog | 66 ++++++-
hactypes.el | 7 +-
hib-kbd.el | 4 +-
hibtypes.el | 13 +-
hui-menu.el | 4 +-
hui.el | 6 +-
hywiki.el | 569 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
7 files changed, 581 insertions(+), 88 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1324ae46e7..e1bb43b512 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,67 @@
+2024-11-24 Bob Weiner <rsw@gnu.org>
+
+* hibtypes.el (hywiki-word:help): Add so Assist Key on a HyWikiWord
+ customizes its referent type and link.
+ hywiki.el its referent type and link.
+
+2024-11-23 Bob Weiner <rsw@gnu.org>
+
+* hui.el (hui:link-possible-types): Allow for :CUSTOM_ID: in
+ addition to :ID: matches for Org IDs.
+
+* hib-kbd.el (kbd-key:normalize): Fix interactive expr to read
+ a string rather than a single key sequence.
+
+* hywiki.el (hywiki-get-wikiwords-obarray): Add.
+ (hywiki-read-new-page-name, hywiki-read-page-name):
+ Replace 'hywiki-get-page-list' completion table with
+ 'hywiki-get-wikiwords-obarray' which is more efficient.
+ (hywiki-find-page): Rename to 'hywiki-find-referent'.
+ Rename 'hywiki-find-page-hook' to 'hywiki-find-referent-hook'.
+ (hywiki-word-activate): Change so automatically creates
+ pages that do not exist, except for the first HyWiki page, in
+ which case, prompts before creation.
+ (hywiki-display-page-function): Add this customization
+ function that displays HyWiki pages.
+ (hywiki-display-page): Add to use above variable to
+ display HyWiki pages.
+ (hywiki-word): Update doc with first page prompting.
+ (hywiki-maybe-highlight-page-names): Return nil so
+ 'hywiki-display-referent' returns nil when this is called.
+ (hywiki-get-file, hywiki-display-referent): Improve
+ #section matching to ignore #autosave# file names.
+ (hywiki-allow-plurals-flag): Add new customization,
+ defaults to t to treat plural HyWikiWords the same as singular
+ ones.
+ (hywiki-get-page): Handle HyWikiWord plurals based on
+ the above flag.
+
+* hactypes.el: Document potential second arg of referent (point)
+ when referent is already read into a buffer and user wants
+ to link to the current point.
+
+* hywiki.el (hywiki-add-*): Add to allow each HyWikiWord to have
+ a custom referent when created with a prefix argument. Referent
+ type is prompted for, similar to when creating other Hyperbole
+ buttons.
+ (hywiki-add-prompted-referent): Add to prompt for and
+ link a HyWikiWord to a custom referent or action type.
+ (hywiki-referent-menu): New minibuffer menu used by the
+ above function.
+ (hywiki-get-page): Expand to return all new possible
+ referent types.
+ (hywiki-display-referent): Add to display all of the
+ new referent types.
+ (hywiki-read-new-page-name): Use any potential WikiWord at
+ point as the default.
+
+2024-11-22 Bob Weiner <rsw@gnu.org>
+
+* hywiki.el (hywiki-find-page): Add missing second interactive
+ arg value, current-prefix-arg. Rewrite to allow for
+ different actions per HyWikiWord or a single overriding
+ function.
+
2024-11-19 Bob Weiner <rsw@gnu.org>
* hywiki.el (hywiki-maybe-highlight-page-name): Fix that adding
@@ -10,8 +74,6 @@
man-show where needed. This may allow CI/CD build of docker Emacs
master branch that lacks 'man' package.
-2024-11-18 bw <bw@norlinux>
-
* hui-tests.el (hui--ibut-link-directly-to-org-header-first-column):
Remove dir from fileb when comparing to in-buffer filename and
do the same for other tests in this file.
diff --git a/hactypes.el b/hactypes.el
index 9c8bf7b1a7..12f609a72d 100644
--- a/hactypes.el
+++ b/hactypes.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 23-Sep-91 at 20:34:36
-;; Last-Mod: 18-Nov-24 at 23:27:33 by Bob Weiner
+;; Last-Mod: 23-Nov-24 at 12:27:01 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -347,7 +347,10 @@ Interactively, KEY-FILE defaults to the current buffer's
file name."
(describe-symbol symbol)))))
(defun hactypes:link-to-file-interactively ()
- "Get a path to link to and return it as a one item list."
+ "Get a path to link to and return it as a one item list.
+If the path is already read into a buffer, prompt the user whether to
+also include its current (point) and if so, include that as the second
+list item returned."
(let ((prev-reading-p hargs:reading-type)
(existing-buf t)
path-buf)
diff --git a/hib-kbd.el b/hib-kbd.el
index 8dd80b222b..53cb6a2d3d 100644
--- a/hib-kbd.el
+++ b/hib-kbd.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 22-Nov-91 at 01:37:57
-;; Last-Mod: 30-Jun-24 at 02:19:16 by Bob Weiner
+;; Last-Mod: 23-Nov-24 at 21:15:04 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -298,7 +298,7 @@ The KEY-SERIES is without any surrounding {}. Return the
normalized but still human-readable format. Use
`kbd-key:key-series-to-events' to add the key series to Emacs'
keyboad input queue, as if they had been typed by the user."
- (interactive "kKeyboard key sequence to normalize (no {}): ")
+ (interactive "sKeyboard key sequence to normalize (no {}): ")
;;
;; Hyperbole developers: see `edmacro-parse-keys' in "edmacro.el"
;; for further details on key formats.
diff --git a/hibtypes.el b/hibtypes.el
index fda2bdf1f6..0f4d311303 100644
--- a/hibtypes.el
+++ b/hibtypes.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 19-Sep-91 at 20:45:31
-;; Last-Mod: 13-Nov-24 at 13:08:00 by Mats Lidell
+;; Last-Mod: 24-Nov-24 at 01:52:18 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -1696,7 +1696,16 @@ If a boolean function or variable, display its value."
(if (and start end)
(ibut:label-set page-name start end)
(ibut:label-set page-name))
- (hact 'hywiki-find-page (hywiki-get-singular-page-name page-name)))))
+ (hact 'hywiki-find-referent page-name))))
+
+(defun hywiki-existing-word:help (wikiword)
+ "When on a HyWikiWord, customize its referent type and link."
+ (interactive (list (hywiki-word-at)))
+ (unless (stringp wikiword)
+ (setq wikiword (hywiki-word-at)))
+ (when wikiword
+ (ibut:label-set wikiword (match-beginning 0) (match-end 0))
+ (hywiki-find-referent wikiword t)))
;;; ========================================================================
;;; Inserts completion into minibuffer or other window.
diff --git a/hui-menu.el b/hui-menu.el
index 6687033cb0..38a99585a8 100644
--- a/hui-menu.el
+++ b/hui-menu.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 28-Oct-94 at 10:59:44
-;; Last-Mod: 27-Oct-24 at 17:59:52 by Bob Weiner
+;; Last-Mod: 23-Nov-24 at 21:14:02 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -309,7 +309,7 @@ Return t if cutoff, else nil."
["Activate-HyWiki-Word" hywiki-word-activate t]
["Create-HyWiki-Page" hywiki-add-page-and-display t]
["Edit-HyWiki-Pages" hywiki-directory-edit t]
- ["Find-HyWiki-Page" hywiki-find-page t]
+ ["Find-HyWiki-Referent" hywiki-find-referent t]
(when (fboundp 'consult-grep) ;; allow for autoloading
["Grep-Consult-Pages" hywiki-consult-grep t])
["Help" hkey-help t]
diff --git a/hui.el b/hui.el
index 0d060b0928..608012261b 100644
--- a/hui.el
+++ b/hui.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 19-Sep-91 at 21:42:03
-;; Last-Mod: 18-Nov-24 at 20:05:31 by Bob Weiner
+;; Last-Mod: 23-Nov-24 at 20:35:50 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -1848,9 +1848,9 @@ Buffer without File link-to-buffer-tmp"
(list (cond ((and (featurep 'org-id)
(cond ((save-excursion
(beginning-of-line)
- (when (looking-at "[ \t]*:ID:[
\t]+\\([^ \t\r\n\f]+\\)")
+ (when (looking-at "[
\t]*:\\(CUSTOM_\\)?ID:[ \t]+\\([^ \t\r\n\f]+\\)")
;; Org ID definition
- (list 'link-to-org-id
(match-string 1)))))
+ (list 'link-to-org-id
(match-string 2)))))
(t (let* ((id (thing-at-point 'symbol
t)) ;; Could be a uuid or some other form of id
(bounds (when id
(bounds-of-thing-at-point 'symbol)))
(start (when bounds (car
bounds)))
diff --git a/hywiki.el b/hywiki.el
index 0d4572489b..4e3474ad16 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: 19-Nov-24 at 00:21:19 by Bob Weiner
+;; Last-Mod: 24-Nov-24 at 03:24:57 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
@@ -137,10 +137,14 @@
;;; ************************************************************************
(defvar action-key-modeline-buffer-id-function) ;; "hui-mouse"
-(defvar org-agenda-buffer-tmp-name) ;; "org-agenda.el"
-(defvar org-export-with-broken-links);; "ox.el"
-(defvar org-publish-project-alist) ;; "ox-publish.el"
-
+(defvar hywiki-referent-menu nil) ;; "hywiki.el"
+(defvar org-agenda-buffer-tmp-name) ;; "org-agenda.el"
+(defvar org-export-with-broken-links) ;; "ox.el"
+(defvar org-publish-project-alist) ;; "ox-publish.el"
+
+(declare-function activities-completing-read "activities" (:prompt prompt
:default default))
+(declare-function activities-new "activities" (name))
+(declare-function activities-resume "activities" (activity :resetp resetp))
(declare-function hsys-org-at-tags-p "hsys-org")
(declare-function org-link-store-props "ol" (&rest plist))
(declare-function org-publish-property "ox-publish" (property project
&optional default))
@@ -314,7 +318,7 @@ where PATH is the un-resolvable reference."
:with-toc nil)))
(defvar-local hywiki-page-flag nil
- "Set to t after a `find-file' of a HyWiki page file, else nil.
+ "Set to t after finding a HyWiki page file, else nil.
The file must be below `hywiki-directory'.
For reference, this is set when `window-buffer-change-functions' calls
@@ -355,8 +359,21 @@ the HyWiki word and grouping 2 is the #section with the #
included.")
(defcustom hywiki-word-face 'hywiki--word-face
"Hyperbole face for HyWiki word highlighting."
+ :initialize #'custom-initialize-default
:type 'face
+ :group 'hyperbole-hywiki)
+
+(defcustom hywiki-display-page-function #'hpath:find
+ "Hyperbole function to display HyWiki pages.
+Only argument is the page name concatenated with optional #section."
+ :initialize #'custom-initialize-default
+ :type 'string
+ :group 'hyperbole-hywiki)
+
+(defcustom hywiki-allow-plurals-flag t
+ "Non-nil means plural HyWikiWords have the same referent as the singular
form."
:initialize #'custom-initialize-default
+ :type 'boolean
:group 'hyperbole-hywiki)
;;; ************************************************************************
@@ -537,30 +554,66 @@ See the Info documentation at \"(hyperbole)HyWiki\".
;;; ************************************************************************
(defib hywiki-word ()
- "When on a HyWiki word, display its page and optional section.
-If the associated HyWiki page does not exist, create it automatically."
- (let ((page-name (hywiki-word-at)))
- (when page-name
- (ibut:label-set page-name (match-beginning 0) (match-end 0))
- (hact 'hywiki-find-page page-name))))
+ "When on a HyWikiWord, display its referent.
+If the associated HyWiki referent is a page and it does not exist,
+create it automatically unless it is the first HyWiki page to be
+created, in which case, prompt the user whether to create it to
+prevent any unexpected HyWiki use."
+ (let ((wikiword (hywiki-word-at)))
+ (when wikiword
+ (ibut:label-set wikiword (match-beginning 0) (match-end 0))
+ (hact 'hywiki-find-referent wikiword))))
+
+(defalias 'hywiki-word:help 'hywiki-existing-word:help)
;;;###autoload
-(defun hywiki-find-page (&optional page-name prompt-flag)
+(defun hywiki-find-referent (&optional wikiword prompt-flag)
+ "Display optional HyWiki WIKIWORD referent or if nil, use current buffer.
+If called interactively, prompt for a new or existing WIKIWORD
+and use any prefix argument as PROMPT-FLAG.
+
+Return the referent if successfully found or nil otherwise.
+See `hywiki-referent-menu' for valid referent types.
+
+If the referent is a HyWiki page:
+ Return the absolute path to any page successfully found; nil
+ if failed or if displaying a regular file (read in via a
+ `find-file' call).
+
+ By default, create any non-existent page. When not in batch
+ mode, with optional PROMPT-FLAG t or if this is the first
+ HyWiki page in `hywiki-directory', prompt to create if
+ non-existent. If PROMPT-FLAG is :existing or with a prefix
+ argument when called interactively, return nil unless the
+ page already exists. After successfully finding a page and
+ reading it into a buffer, run `hywiki-display-referent-hook'.
+
+After successfully finding any kind of referent, run
+`hywiki-find-referent-hook'."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")
+ (when current-prefix-arg t)))
+ (prog1 (hywiki-display-referent wikiword prompt-flag)
+ (run-hooks 'hywiki-find-referent-hook)))
+
+(defun hywiki-display-page (&optional wikiword)
+ "Display an optional WIKIWORD page.
+Use `hywiki-display-page-function' to display the page.
+
+If WIKIWORD is omitted or nil and `hywiki-display-page-function'
+is an interactive function, it is called interactively and prompts for
+an existing or new HyWikiWord."
+ (if (and (null wikiword) (commandp hywiki-display-page-function))
+ (call-interactively hywiki-display-page-function)
+ (when (null wikiword)
+ (setq wikiword (hywiki-read-new-page-name "Find HyWiki page: ")))
+ (funcall hywiki-display-page-function wikiword)))
+
+(defun hywiki-display-referent (&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
-failed or if displaying a regular file (read in via a `find-file'
-call).
-By default, create any non-existent page. When not in batch mode,
-with optional PROMPT-FLAG t or if this is the first HyWiki page in
-`hywiki-directory', prompt to create if non-existent. If
-PROMPT-FLAG is :existing or with a prefix argument when called
-interactively, return nil unless the page already exists. After
-successfully finding a page and reading it into a buffer, run
-`hywiki-find-page-hook'."
- (interactive (list (if current-prefix-arg
- (hywiki-read-page-name "Find existing HyWiki page: ")
- (hywiki-read-new-page-name "Find HyWiki page: "))))
+For details, see documentation for `hywiki-find-referent'.
+After successfully finding a page and reading it into a buffer, run
+`hywiki-display-referent-hook'."
(let ((in-page-flag (null page-name))
(in-hywiki-directory-flag (hywiki-in-page-p)))
(if (or (stringp page-name) in-hywiki-directory-flag)
@@ -568,32 +621,138 @@ successfully finding a page and reading it into a
buffer, run
(when in-page-flag
;; 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"
+ (error "(hywiki-display-referent): No `page-name' given; buffer
file must be in `hywiki-directory', not %s"
default-directory))
- (when (null buffer-file-name)
- (error "(hywiki-find-page): No `page-name' given; buffer must
have an attached file"))
+ (unless buffer-file-name
+ (error "(hywiki-display-referent): No `page-name' given; buffer
must have an attached file"))
(setq page-name (file-name-sans-extension (file-name-nondirectory
buffer-file-name))))
-
- (let* ((section (when (string-match "#" page-name)
+ (when (string-match "#[^#]+$" page-name)
+ (setq page-name (substring page-name 0 (match-beginning 0))))
+ (let* ((section (when (string-match "#[^#]+$" page-name)
(substring page-name (match-beginning 0))))
- (page-name (if (string-match "#" page-name)
- (substring page-name 0 (match-beginning 0))
- page-name))
- (page-file (or (hywiki-get-page page-name)
- (hywiki-add-page page-name prompt-flag))))
- (when page-file
+ (referent (if prompt-flag
+ (hywiki-add-prompted-referent page-name)
+ (hywiki-add-page page-name prompt-flag))))
+ (when referent
;; Ensure highlight any page name at point in case called as a
;; Hyperbole action type
(hywiki-maybe-highlight-page-name t)
- (unless in-page-flag (hpath:find (concat page-file section)))
+ (cond ((or (symbolp referent) (functionp referent))
+ ;; function or actype symbol
+ (hact referent page-name prompt-flag))
+ ((and (consp referent) (fboundp (car referent)))
+ ;; e.g. (kbd "key sequence")
+ (hact #'eval referent))
+ ((and (null referent) (stringp section)
+ (string-match-p "^\\(#[^#]+\\)$" section))
+ ;; "#in-buffer-section"
+ (hywiki-display-page section))
+ ((stringp referent)
+ (let ((case-fold-search t))
+ (cond
+ ((string-match-p "^\\({.+}\\)$" referent)
+ ;; "{key series}"
+ (hact 'kbd-key referent))
+ ((and (featurep 'org-id)
+ (string-match "^\\(CUSTOM_\\)?ID:[ \t]+\\(.*[^
\t]\\)" referent))
+ ;; "ID: org-id"
+ (setq referent (match-string 2 referent))
+ (hact 'link-to-org-id referent))
+ ((string-match-p "^\\(<\\[.+\\]>\\|<(.+)>\\)$" referent)
+ ;; "<(global explicit button name)>"
+ ;; "<[global implicit button name]>"
+ (gbut:act (string-trim (substring referent 2 -2))))
+ (t
+ ;; page path, the default
+ (unless in-page-flag
+ (hywiki-display-page (concat referent section))))))))
(hywiki-maybe-highlight-page-names)
- (run-hooks 'hywiki-find-page-hook)
- page-file)))
+ (run-hooks 'hywiki-display-referent-hook)
+ referent)))
;; When called 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))))
+;;; ************************************************************************
+;;; Public referent menus and utility functions
+;;; ************************************************************************
+
+(unless hywiki-referent-menu
+ (makunbound 'hywiki-referent-menu))
+(defcustom hywiki-referent-menu
+ (delq nil
+ (list
+ '("HyWiki Add>")
+ (when (fboundp #'activities-new)
+ '("Activity" (hywiki-add-activity wikiword)
+ "Add a HyWikiWord that activates a saved activity from the
Activities package."))
+ '("Bookmark" (hywiki-add-bookmark wikiword)
+ "Add a HyWikiWord that jumps to an Emacs bookmark.")
+ '("Command" (hywiki-add-command wikiword)
+ "Add a HyWikiWord that runs an Emacs command or Hyperbole action
type.")
+ '("Find" (hywiki-add-find wikiword)
+ "Add a HyWikiWord that greps through `hywiki-directory' for its
matches.")
+ ;; "<(global explicit button name)>"
+ ;; "<[global implicit button name]>"
+ '("Gbut" (hywiki-add-global-button wikiword)
+ "Add a HyWikiWord that activates a named Hyperbole global button.")
+ '("HyRolo" (hywiki-add-hyrolo wikiword)
+ "Add a HyWikiWord that searches `hyrolo-file-list' for matches.")
+ ;; "{key series}" wikiword)
+ '("Keys" (hywiki-add-key-series wikiword)
+ "Add a HyWikiWord that executes a key series.")
+ '("InfoIndex" (hywiki-add-info-index wikiword)
+ "Add a HyWikiWord that displays an Info index item.")
+ '("infoNode" (hywiki-add-info-node wikiword)
+ "Add a HyWikiWord that displays an Info node.")
+ ;; "ID: org-id"
+ '("OrgID" (hywiki-add-org-id wikiword)
+ "Add a HyWikiWord that displays an Org section given its Org ID.")
+ '("orgRoamNode" (hywiki-add-org-roam-node wikiword)
+ "Add a HyWikiWord that displays an Org Roam node given its title.")
+ ;; "pathname:line:col"
+ ;; "#in-buffer-section"
+ '("Path" (hywiki-add-path wikiword)
+ "Add a HyWikiWord that links to a path and possible position.")
+ ;; e.g. (kbd "key sequence")
+ '("Sexp" (hywiki-add-sexpresion wikiword)
+ "Add a HyWikiWord that evaluates an Elisp sexpression.")))
+ "*Menu of HyWikiWord custom referent types of the form:
+\(LABEL-STRING ACTION-SEXP DOC-STR)."
+ :set (lambda (var value) (set-default var value))
+ :type '(cons (list string) (repeat (list string sexp string)))
+ :group 'hyperbole-buttons)
+
+(defun hywiki-add-prompted-referent (wikiword)
+ "Prompt for, add to HyWiki lookups and return a WIKIWORD custom referent."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (unless (stringp wikiword)
+ (setq wikiword (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((referent
+ (hui:menu-act 'hywiki-referent-menu
+ (list (cons 'hywiki-referent-menu
+ (cons (list (format "HyWiki %s Type>"
+ wikiword))
+ (cdr hywiki-referent-menu)))))))
+ (or referent
+ (when (called-interactively-p 'interactive)
+ (user-error "(hywiki-add-referent): Invalid HyWikiWord: '%s'; must be
capitalized, all alpha" wikiword)))))
+
+(defun hywiki-add-referent (wikiword referent)
+ (when (hywiki-word-is-p wikiword)
+ (when (match-string-no-properties 2 wikiword)
+ ;; Remove any #section suffix in PAGE-NAME.
+ (setq wikiword (match-string-no-properties 1 wikiword)))
+ (hash-add referent (hywiki-get-singular-page-name wikiword)
+ (hywiki-get-page-hasht))
+ (setq hywiki--any-page-regexp-list nil)
+ (unless (hyperb:stack-frame '(hywiki-maybe-highlight-page-names-in-frame))
+ (hywiki-directory-set-mod-time)
+ (hywiki-directory-set-checksum))
+ (run-hooks 'hywiki-add-referent-hook)
+ referent))
+
;;; ************************************************************************
;;; Public functions
;;; ************************************************************************
@@ -608,6 +767,165 @@ Exclude the minibuffer if selected and return nil."
(not (apply #'derived-mode-p hywiki-exclude-major-modes))
(or hywiki-mode (hywiki-in-page-p))))
+(defun hywiki-add-activity (wikiword)
+ "Make WIKIWORD resume a prompted for activity.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the activity, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (require 'activities)
+ (let ((activity (activities-completing-read :prompt "Resume activity"
:default nil)))
+ (hywiki-add-referent wikiword `(activities-resume ,activity :resetp nil))))
+
+(defun hywiki-add-bookmark (wikiword)
+ "Make WIKIWORD display a bookmark and return the action.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the bookmark, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (require 'bookmark)
+ (let* ((bookmark (bookmark-completing-read "Bookmark: "
+ bookmark-current-bookmark))
+ (loc (bookmark-location bookmark))
+ ;; Use Hyperbole-specified display location
+ (bkm-display `(progn
+ (cond ((bufferp ,loc)
+ (hpath:display-buffer ,loc))
+ ((get-buffer ,loc)
+ (hpath:display-buffer (get-buffer ,loc)))
+ ((stringp ,loc)
+ (hywiki-display-page ,loc)))
+ (bookmark-jump ,bookmark))))
+ (hywiki-add-referent wikiword bkm-display)))
+
+(defun hywiki-add-command (wikiword)
+ "Set a custom command symbol for WIKIWORD and return it.
+Command is the symbol used in the definition expression, which
+may be an Emacs command or a Hyperbole action type.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the actype, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((command (hui:actype nil (format "Command for %s: " wikiword))))
+ (hywiki-add-referent wikiword command)))
+
+(defun hywiki-add-find (wikiword)
+ "Make WIKIWORD grep across `hywiki-directory' for matches to itself.
+Return the command to invoke.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the grep, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((grep-cmd (if (fboundp 'consult-grep) ;; allow for autoloading
+ #'hywiki-word-consult-grep
+ #'grep)))
+ (hywiki-add-referent wikiword (list grep-cmd wikiword))))
+
+(defun hywiki-add-global-button (wikiword)
+ "Make WIKIWORD evaluate a prompted for global button.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the button link, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((gbut-name (hargs:read-match "Global button: "
+ (mapcar #'list (gbut:label-list))
+ nil t nil 'gbut)))
+ (hywiki-add-referent wikiword `(gbut:act ,gbut-name))))
+
+(defun hywiki-add-hyrolo (wikiword)
+ "Make WIKIWORD search and display `hyrolo-file-list' matches.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the hyrolo search, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (require 'hyrolo)
+ ;; !! TODO: Change PaulAllenWinter to search for "Winter, Paul Allen".
+ (hywiki-add-referent wikiword `(hyrolo-fgrep ,wikiword)))
+
+(defun hywiki-add-info-index (wikiword)
+ "Make WIKIWORD display an Info manual index item and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the Info index item, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((item (save-window-excursion
+ (info)
+ (Info-read-index-item-name "Info index item: "))))
+ (when (stringp item)
+ (unless (= (aref item 0) ?\()
+ (setq item (format "(%s)%s" (Info-current-filename-sans-extension)
item)))
+ (hywiki-add-referent wikiword item))))
+
+(defun hywiki-add-info-node (wikiword)
+ "Make WIKIWORD display an Info manual node and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the Info node, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((node (save-window-excursion
+ (info)
+ (Info-read-node-name "Info node: "))))
+ (when (stringp node)
+ (unless (= (aref node 0) ?\()
+ (setq node (format "(%s)%s" (Info-current-filename-sans-extension)
node)))
+ (hywiki-add-referent wikiword node))))
+
+(defun hywiki-add-key-series (wikiword)
+ "Make WIKIWORD invoke a prompted for key series and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the key series, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((key-series (read-string "Key series (with or without {}): ")))
+ (unless (string-match-p "\\`{.+}\\'" key-series)
+ (setq key-series (concat "{" (string-trim key-series) "}")))
+ (hywiki-add-referent wikiword key-series)))
+
;;;###autoload
(defun hywiki-add-link ()
"Insert at point a link to a HyWiki page."
@@ -615,6 +933,67 @@ Exclude the minibuffer if selected and return nil."
(insert (hywiki-read-page-name "Link to HyWiki page: "))
(hywiki-maybe-highlight-page-name))
+(defun hywiki-add-org-id (wikiword)
+ "Make WIKIWORD evaluate a prompted for sexpression and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the sexpression, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (cl-destructuring-bind (_src-window referent-window)
+ (hmouse-choose-link-and-referent-windows)
+ (with-selected-window referent-window
+ (unless (hsys-org-mode-p)
+ (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)))
+ (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)))
+ (unless org-id
+ (setq org-id (org-id-get-create)))
+ (hywiki-add-referent wikiword (concat "ID: " org-id))))))
+
+(defun hywiki-add-org-roam-node (wikiword)
+ "Make WIKIWORD display an Org Roam Node and return the action.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the action, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (require 'org-roam)
+ (let* ((org-roam-node (org-roam-node-read))
+ (referent `(org-roam-node-open ,org-roam-node
+ (or (alist-get 'file
org-link-frame-setup)
+ (alist-get hpath:display-where
hpath:display-where-alist)))))
+ (hywiki-add-referent wikiword referent)))
+
+(defun hywiki-add-path (wikiword)
+ "Set a path link and possible position for WIKIWORD and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the path link, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (let ((referent (hactypes:link-to-file-interactively)))
+ (when (= (length referent) 2)
+ (setq referent (hpath:file-position-to-line-and-column
+ (car referent) (cadr referent))))
+ (hywiki-add-referent wikiword referent)))
+
(defun hywiki-add-page (page-name &optional prompt-flag)
"Add or edit the HyWiki page for PAGE-NAME and return its file.
If file exists already, just return it. If PAGE-NAME is invalid,
@@ -666,9 +1045,22 @@ Use `hywiki-get-page' to determine whether a HyWiki page
exists."
(interactive (list (hywiki-read-new-page-name "Add and display HyWiki page:
")))
(let ((page-file (hywiki-add-page page-name)))
(if page-file
- (hywiki-find-page (file-name-base page-file))
+ (hywiki-find-referent (file-name-base page-file))
(user-error "(hywiki-add-page-and-display): Invalid page name: '%s';
must be capitalized, all alpha" page-name))))
+(defun hywiki-add-sexpression (wikiword)
+ "Make WIKIWORD evaluate a prompted for sexpression and return it.
+
+If WIKIWORD is invalid, trigger a `user-error' if called interactively
+or return nil if not.
+
+After successfully adding the sexpression, run `hywiki-add-referent-hook'.
+
+Use `hywiki-get-page' to determine whether WIKIWORD exists prior to
+calling this function."
+ (interactive (list (hywiki-read-new-page-name "Add/Edit HyWikiWord: ")))
+ (hywiki-add-referent wikiword (read--expression "Sexpression: ")))
+
(defun hywiki-add-to-page (page-name text start-flag)
"Add to PAGE-NAME TEXT at page start with START-FLAG non-nil, else end.
Create page if it does not exist. If PAGE-NAME is invalid, return
@@ -740,18 +1132,19 @@ Use `hywiki-get-page' to determine whether a HyWiki page
exists."
t))
(defun hywiki-word-activate (&optional arg)
- "Display HyWiki page for wiki word at point, creating the page if needed.
-If found, return the full path of the page.
+ "Display HyWiki referent for wikiword at point.
+If referent is a non-existent HyWiki page, create it. When this
+is the first HyWiki page, prompt before creating in case this is
+not what was intended.
-If on a HyWikiWord without a wiki page, then prompt before creating
-the page.
+If found, return the referent.
If not on a HyWikiWord and optional prefix ARG is null, emulate an
Action Key press; with a prefix ARG, emulate an Assist Key press."
(interactive "P")
(let ((word (hywiki-word-at)))
(if word
- (hywiki-find-page word t)
+ (hywiki-find-referent word)
(hkey-either arg))))
(defun hywiki-word-at ()
@@ -1519,7 +1912,8 @@ value of `hywiki-word-highlight-flag' is changed."
(hywiki-maybe-dehighlight-page-names region-start region-end))
(unless (hyperb:stack-frame '(hywiki-maybe-highlight-page-names-in-frame))
(hywiki-directory-set-mod-time)
- (hywiki-directory-set-checksum)))
+ (hywiki-directory-set-checksum))
+ nil)
(defun hywiki-maybe-highlight-page-names-in-frame (frame &optional
skip-lookups-update-flag)
"Highlight all non-Org link HyWiki page names displayed in FRAME.
@@ -1564,7 +1958,7 @@ value returns nil."
;; Remove any #section from `file-stem-name' and make it singular
(setq file-stem-name
(hywiki-get-singular-page-name
- (if (string-match "#" file-stem-name)
+ (if (string-match "#[^#]+$" file-stem-name)
(substring file-stem-name 0 (match-beginning 0))
file-stem-name)))
(if (string-suffix-p hywiki-file-suffix file-stem-name)
@@ -1573,23 +1967,37 @@ value returns nil."
file-stem-name hywiki-directory) hywiki-file-suffix))))
(defun hywiki-get-page (page-name)
- "Return the absolute path of HyWiki PAGE-NAME or nil if it does not exist."
+ "Return the referent of HyWiki PAGE-NAME or nil if it does not exist.
+If it is a pathname, expand it relative to `hywiki-directory'."
(when (and (stringp page-name) (not (string-empty-p page-name))
(string-match hywiki-word-with-optional-section-exact-regexp
page-name))
- (when (match-string-no-properties 2 page-name)
- ;; Remove any #section suffix in PAGE-NAME.
- (setq page-name (match-string-no-properties 1 page-name)))
-
- (let ((relative-page-file
- (or (hash-get page-name (hywiki-get-page-hasht))
- ;; Handle typical pluralized words ending in 's' (not preceded
- ;; by an 's') or 'es'
- (when (string-match "[eE][sS]$" page-name)
- (hash-get (substring page-name 0 -2) (hywiki-get-page-hasht)))
- (when (string-match ".[^eEsS]s$" page-name)
- (hash-get (substring page-name 0 -1)
(hywiki-get-page-hasht))))))
- (when (stringp relative-page-file)
- (expand-file-name relative-page-file hywiki-directory)))))
+ (let* ((section (when (match-string-no-properties 2 page-name)
+ (prog1 (substring page-name (match-beginning 2))
+ ;; Remove any #section suffix in PAGE-NAME.
+ (setq page-name (match-string-no-properties 1
page-name)))))
+ (referent (hash-get (hywiki-get-singular-page-name page-name)
+ (hywiki-get-page-hasht))))
+ (cond ((or (symbolp referent) (functionp referent)
+ (and (consp referent) (fboundp (car referent))))
+ ;; function or actype symbol
+ ;; e.g. (kbd "key sequence")
+ referent)
+ ((stringp referent)
+ (let ((case-fold-search t))
+ (cond ((and (null referent) (stringp section)
+ (string-match-p "^\\(#[^#]+\\)$" section))
+ ;; "#in-buffer-section"
+ section)
+ ((string-match-p "^\\({.+}\\|\\(CUSTOM_\\)?ID:[
\t]+.+\\|<\\[.+\\]>\\|<(.+)>\\)$"
+ referent)
+ ;; "{key series}"
+ ;; "ID: org-id"
+ ;; "<(global explicit button name)>"
+ ;; "<[global implicit button name]>"
+ referent)
+ ;; path, expand to absolute
+ (t (expand-file-name referent hywiki-directory)))))
+ (t nil)))))
(defun hywiki-get-page-files ()
"Return the list of existing HyWiki page file names.
@@ -1634,6 +2042,10 @@ regexps of page names."
"Return a list of the HyWiki page names."
(hash-map #'cdr (hywiki-get-page-hasht)))
+(defun hywiki-get-wikiwords-obarray ()
+ "Return an obarray of existing HyWikiWords."
+ (cdr (hywiki-get-page-hasht)))
+
(defun hywiki-get-plural-page-name (page-name)
"Return the pluralized version of the given PAGE-NAME."
;; You add "-es" to make a noun plural when the singular noun ends
@@ -1654,15 +2066,20 @@ regexps of page names."
"S")))))
(defun hywiki-get-singular-page-name (page-name)
- "Return the singular version of the given PAGE-NAME."
- (or (when (let ((case-fold-search t))
- (string-match-p "\\(ch\\|sh\\|[sxz]\\)es$" page-name))
- (substring page-name 0 -2))
- (when (let ((case-fold-search t))
- (and (string-match-p ".[^s]s$" page-name)
- (not (string-match-p "emacs$" page-name))))
- (substring page-name 0 -1))
- page-name))
+ "Return the singular version of the given PAGE-NAME.
+If `hywiki-allow-plurals-flag' is nil, return PAGE-NAME unchanged."
+ (if hywiki-allow-plurals-flag
+ (or (when (let ((case-fold-search t))
+ ;; Handle typical pluralized words ending in 's' (not preceded
+ ;; by an 's') or 'es'
+ (string-match-p "\\(ch\\|sh\\|[sxz]\\)es$" page-name))
+ (substring page-name 0 -2))
+ (when (let ((case-fold-search t))
+ (and (string-match-p ".[^eEsS]s$" page-name)
+ (not (string-match-p "emacs$" page-name))))
+ (substring page-name 0 -1))
+ page-name)
+ page-name))
(defun hywiki-kill-buffer-hook ()
"Delete file attached to HyWiki buffer if the file is zero-sized.
@@ -1825,7 +2242,7 @@ variables."
'(org-link-set-parameters hywiki-org-link-type
:complete #'hywiki-org-link-complete
:export #'hywiki-org-link-export
- :follow #'hywiki-find-page
+ :follow #'hywiki-find-referent
:store #'hywiki-org-link-store))
(defun hywiki-page-exists-p (&optional word start end)
@@ -1893,14 +2310,16 @@ Customize this directory with:
"Prompt with completion for and return a new HyWiki page name."
(let ((completion-ignore-case t))
(completing-read (if (stringp prompt) prompt "HyWiki Page Name: ")
- (hywiki-get-page-list))))
+ (hywiki-get-wikiwords-obarray)
+ nil nil nil nil (hywiki-word-at))))
(defun hywiki-read-page-name (&optional prompt)
"Prompt with completion for and return an existing HyWiki page name.
If on a page name, immediately pressing RET will use that name as the default."
(let ((completion-ignore-case t))
(completing-read (if (stringp prompt) prompt "HyWiki Page Name: ")
- (hywiki-get-page-list) nil t nil nil (hywiki-word-at))))
+ (hywiki-get-wikiwords-obarray)
+ nil t nil nil (hywiki-word-at))))
;;;###autoload
(defun hywiki-tags-view (&optional todo-only match view-buffer-name)
- [elpa] externals/hyperbole updated (e2749c6348 -> c4c5daaa08), ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole 6cd7a45434 1/9: hywiki.el - Add global HyWiki page override & custom referent types,
ELPA Syncer <=
- [elpa] externals/hyperbole a335b73d0f 3/9: hywiki.el - Fix custom HyWikiWord referents for single session use, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole f9df63b217 5/9: hywiki.el - Add require, defvar and declare-function for warnings, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole 5a91e7abaa 4/9: hywiki.el - Redo hywiki-add-page-and-display and hywiki-referent-menu, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole ebad245f63 2/9: Merge branch 'master' into rsw, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole 4eb1d46dbc 6/9: Merge branch 'master' into rsw, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole c4c5daaa08 9/9: Merge pull request #615 from rswgnu/rsw, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole 4bff008242 7/9: hywiki.el - Many fixes and updates plus Smart Key fixes, ELPA Syncer, 2024/12/16
- [elpa] externals/hyperbole 93874b2ec3 8/9: test/hbut-tests.el: Change most "/tmp" to "/tmp/", ELPA Syncer, 2024/12/16