branch: externals/hyperbole
commit 893b778fccb48a2c41d34d7a8402fd7a63d0bc16
Author: bw <r...@gnu.org>
Commit: bw <r...@gnu.org>

    Add first release of HyWiki to merge
---
 ChangeLog   |  21 ++++++
 hibtypes.el |  23 +++---
 hsys-org.el |   4 +-
 hywiki.el   | 238 +++++++++++++++++++++++++++++++++---------------------------
 4 files changed, 168 insertions(+), 118 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a64af91041..386af52a05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,12 +2,30 @@
 
 * hbut.el (ibtype:delete): Fix interactive call.
 
+* hywiki.el (hywiki-remap-buttonize-characters): Add <tab>.
+            (hywiki-highlight-page-name): Fix to highlight page
+    name regardless of how much whitespace comes after the name.
+            (hywiki-mode): Expand doc and add/remove 'post-self-insert-hook'
+    call of 'hywiki-buttonize'.
+            (hywiki-remap-buttonize-characters, hywiki-initialize-mode-map):
+    Remove these and move keymap init into 'hywiki-mode' definition.
+            (hywiki-buttonize): Rewrite to highlight hywiki word to the left of
+    point iff last inserted char is in the set of 
'hywiki--buttonize-characters'.
+    Rename to 'hywiki-buttonize-character-commands'.
+           (hywiki-buttonize-non-character-commands): Add.
+
 * hbut.el (gbut:act): Set 'loc to current-buffer, not the gbut's
     source buffer.
           (hbut:key-src-set-buffer): Clarify doc.
           (hbut:funcall): Change to use 'hbut:key-src-set-buffer' to
     temporarily set current-buffer to button's loc attribute.
 
+* hywiki.el (hywiki-get-page-files): Check that 'hywiki-directory'
+    exists and is readable.
+           (hywiki-is-wikiword): Make case-sensitive.
+          (hywiki-at-wikiword): Remove optional 'org-link-flag' arg
+    use 'ibut:label-p' to get HyWikiWord.
+
 2024-05-23  Bob Weiner  <r...@gnu.org>
 
 * hact.el (actype:delete): Fix interactive spec, eliminating use of
@@ -20,6 +38,9 @@
 * hywiki.el (hywiki-remap-buttonize-characters): Move initialization of
     'hywiki--buttonize-characters' here instead of at variable definition
     to eliminate circular load dependency.
+           (find-file-hook): Remove add-hook on 'org-mode-hook'.
+          (hywiki-find-page): Add post 'hywiki-find-page-hook' and return
+    absolute path to the found page.
 
 * hibtypes.el (grep-msg): Fix that when no source-loc, file path was not
     expanded.
diff --git a/hibtypes.el b/hibtypes.el
index 532ac80fe7..ed2156f614 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:     19-May-24 at 03:52:05 by Bob Weiner
+;; Last-Mod:     25-May-24 at 10:11:05 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -366,16 +366,17 @@ attached file."
        (let ((chr (aref (buffer-name) 0)))
          (not (or (eq chr ?\ ) (eq chr ?*))))
        (not (apply #'derived-mode-p '(prog-mode c-mode objc-mode c++-mode 
java-mode markdown-mode org-mode)))
-       (let ((ref (hattr:get 'hbut:current 'lbl-key))
-            (lbl-start (hattr:get 'hbut:current 'lbl-start)))
-         (and ref
-             lbl-start
-             (eq ?w (char-syntax (aref ref 0)))
-              (not (string-match "[#@]" ref))
-             (save-excursion
-               (goto-char lbl-start)
-               (ibut:label-p t "[" "]" t))
-              (hact 'annot-bib ref)))))
+       (unless (ibut:label-p t "[[" "]]" t) ;; Org link
+        (let ((ref (hattr:get 'hbut:current 'lbl-key))
+              (lbl-start (hattr:get 'hbut:current 'lbl-start)))
+           (and ref
+               lbl-start
+               (eq ?w (char-syntax (aref ref 0)))
+               (not (string-match "[#@]" ref))
+               (save-excursion
+                 (goto-char lbl-start)
+                 (ibut:label-p t "[" "]" t))
+               (hact 'annot-bib ref))))))
 
 ;;; ========================================================================
 ;;; Follows Org links that are in non-Org mode buffers
diff --git a/hsys-org.el b/hsys-org.el
index 6d7f6f9882..853a88aeb6 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:     21-Apr-24 at 12:17:44 by Bob Weiner
+;; Last-Mod:     25-May-24 at 10:22:57 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -411,7 +411,7 @@ or is looking for an Org link in another buffer type."
            ;; return nil from this function and let ibtypes handle this
            ;; as a HyWiki word.
            (if (fboundp 'hywiki-at-wikiword)
-               (if (hywiki-at-wikiword t)
+               (if (hywiki-at-wikiword)
                    (when (or hywiki-org-link-type-required
                              (hyperb:stack-frame '(hywiki-at-wikiword)))
                      in-org-link)
diff --git a/hywiki.el b/hywiki.el
index a12584a900..a9bfe1f8db 100644
--- a/hywiki.el
+++ b/hywiki.el
@@ -2,8 +2,8 @@
 ;;
 ;; Author:       Bob Weiner
 ;;
-;; Orig-Date:     21-Apr-24 at 22:41:13
-;; Last-Mod:     19-May-24 at 04:18:40 by Bob Weiner
+;; Orig-Date:    21-Apr-24 at 22:41:13
+;; Last-Mod:     25-May-24 at 16:54:09 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -65,13 +65,13 @@
 ;;; ************************************************************************
 
 (require 'hasht)
+(require 'hpath)
 (require 'hui-em-but)
 (require 'ol)
 
-(when (package-installed-p 'company)
-  (package-activate 'company)
-  (require 'company)
-  (add-to-list 'company-backends 'hywiki-company-hasht-backend))
+(eval-and-compile
+  '(when (require 'company nil t)
+     (add-to-list 'company-backends 'hywiki-company-hasht-backend)))
 
 ;;; ************************************************************************
 ;;; Public variables
@@ -89,6 +89,23 @@
 (defvar hywiki-directory '"~/hywiki/"
   "Directory in which to find HyWiki page files.")
 
+(defvar hywiki-non-character-commands
+  '(;; Org mode
+    org-cycle                         ;; TAB
+    org-return                        ;; RET, \r
+    org-return-and-maybe-indent       ;; C-j, \n
+    ;; Markdown mode
+    markdown-cycle                    ;; TAB
+    markdown-enter-key                ;; RET, \r
+    electric-newline-and-maybe-indent ;; C-j, \n
+    ;; Global
+    newline                           ;; RET, \r
+    newline-and-indent                ;; RET, \r
+    quoted-insert                     ;; C-q
+    )
+  "Commands that insert characters but whose input events do not
+  arrive as characters or that quote another character for input.")
+
 ;; Define the keymap for hywiki-mode.
 (defvar hywiki-mode-map nil
   "Keymap for `hywiki-mode'.")
@@ -144,11 +161,86 @@ the HyWiki word and grouping 2 is the #section with the # 
included.")
 ;;; ************************************************************************
 
 (defvar hywiki--buttonize-characters nil
-  "String of single character keys bound to `hywiki-buttonize'.
+  "String of single character keys bound to 
`hywiki-buttonize-character-commands'.
 Each such key self-inserts before highlighting any prior HyWiki word.")
 
 (defvar hywiki--pages-hasht nil)
 
+;;; ************************************************************************
+;;; hywiki minor mode
+;;; ************************************************************************
+
+(defun hywiki-buttonize-character-commands ()
+  "Turn any HyWikiWord before point into a highlighted Hyperbole button.
+Triggered by `post-self-insert-hook' for self-inserting characters."
+  (when (and (characterp last-command-event)
+            (seq-find (lambda (c) (= c last-command-event)) 
hywiki--buttonize-characters))
+    (hywiki-highlight-page-name)))
+
+(defun hywiki-buttonize-non-character-commands ()
+  "Turn any HyWikiWord before point into a highlighted Hyperbole button.
+Triggered by `pre-command-hook' for non-character-commands, e.g. return."
+  (when (memq this-command hywiki-non-character-commands)
+    (hywiki-highlight-page-name)))
+
+(defun hywiki-get-buttonize-characters ()
+  "Return a string of Org self-insert keys that have punctuation/symbol 
syntax."
+  (let (key
+       cmd
+       key-cmds
+       result)
+    ;; Org and other text mode self-insert-command bindings are just
+    ;; remaps inherited from global-map.  Create key-cmds list of
+    ;; parsable (key . cmd) combinations where key may be a
+    ;; (start-key . end-key) range of keys.
+    (map-keymap (lambda (key cmd) (setq key-cmds (cons (cons key cmd) 
key-cmds))) (current-global-map))
+    (dolist (key-cmd key-cmds (concat (nreverse result)))
+      (setq key (car key-cmd)
+           cmd (cdr key-cmd))
+      (when (eq cmd 'self-insert-command)
+       (cond ((and (characterp key)
+                   (= (char-syntax key) ?.))
+              ;; char with punctuation/symbol syntax
+              (setq result (cons key result)))
+             ((and (consp key)
+                   (characterp (car key))
+                   (characterp (cdr key))
+                   (<= (cdr key) 256))
+              ;; ASCII char range, some of which has punctuation/symbol syntax
+              (with-syntax-table org-mode-syntax-table
+                (dolist (k (number-sequence (car key) (cdr key)))
+                  (when (memq (char-syntax k) '(?. ?_))
+                    (setq result (cons k result)))))))))))
+
+(define-minor-mode hywiki-mode
+  "Toggle HyWiki minor mode with \\[hywiki-mode].
+
+The hywiki-mode minor mode auto-highlights and creates implicit
+buttons from wiki words.  Any such button jumps to the associated
+HyWiki page or associated section when HyWikiWord#section is used.
+
+When hywiki-mode is enabled, the `hywiki-mode' variable is
+non-nil.
+
+See the Info documentation at \"(hyperbole)HyWiki\".
+
+\\{hywiki-mode-map}"
+
+  :lighter " HyWiki"
+  :keymap hywiki-mode-map
+  (if hywiki-mode
+      (progn (unless hywiki-mode-map
+               (setq hywiki-mode-map (make-sparse-keymap)))
+            ;; Self-insert punct/sym keys that trigger wiki-word
+            ;; highlighting via `hywiki-buttonize-character-commands' in 
`hywiki-mode'.
+            (unless hywiki--buttonize-characters
+              (setq hywiki--buttonize-characters
+                    (concat " \t\r\n\)\]\>\}'" 
(hywiki-get-buttonize-characters))))
+            (add-hook 'post-self-insert-hook 
'hywiki-buttonize-character-commands)
+            (add-hook 'pre-command-hook 
'hywiki-buttonize-non-character-commands 95))
+    (remove-hook 'post-self-insert-hook 'hywiki-buttonize-character-commands)
+    (remove-hook 'pre-command-hook 'hywiki-buttonize-character-commands)))
+
 ;;; ************************************************************************
 ;;; Public Implicit Button and Action Types
 ;;; ************************************************************************
@@ -196,75 +288,9 @@ PROMPT-FLAG is 'exists, return nil unless the page already 
exists."
        (when page-file
          (unless in-page-flag (hpath:find (concat page-file section)))
          (unless hywiki-mode (hywiki-mode 1))
-         (hywiki-highlight-page-names))))))
-
-;;; ************************************************************************
-;;; hywiki minor mode
-;;; ************************************************************************
-
-(defun hywiki-buttonize ()
-  "Turn expression one character before point into a highlighted Hyperbole 
button.
-Do this only if the expression is an implicit button of hywiki type."
-  (interactive "*")
-  (insert last-input-event)
-  (hywiki-highlight-page-name))
-
-;; (defun hywiki-setup-org-mode-punctuation-remaps ()
-;;   "Remap punctuation keys in `org-mode` to `hywiki-buttonize`."
-;;   (let ((punctuation-chars ",.;:'\"-/\\?!()[]{}"))
-;;     (dolist (char punctuation-chars)
-;;       (let ((key (concat "<" char ">")))
-;;         (when (bound-and-true-p org-mode-map))))))
-
-(defun hywiki-get-buttonize-characters ()
-  "Return a string of Org self-insert keys that have punctuation/symbol 
syntax."
-  (let (key
-       cmd
-       key-cmds
-       result)
-    ;; Org and other text mode self-insert-command bindings are just
-    ;; remaps inherited from global-map.  Create key-cmds list of
-    ;; parsable (key . cmd) combinations where key may be a
-    ;; (start-key . end-key) range of keys.
-    (map-keymap (lambda (key cmd) (setq key-cmds (cons (cons key cmd) 
key-cmds))) (current-global-map))
-    (dolist (key-cmd key-cmds (concat (nreverse result)))
-      (setq key (car key-cmd)
-           cmd (cdr key-cmd))
-      (when (eq cmd 'self-insert-command)
-       (cond ((and (characterp key)
-                   (= (char-syntax key) ?.))
-              ;; char with punctuation/symbol syntax
-              (setq result (cons key result)))
-             ((and (consp key)
-                   (characterp (car key))
-                   (characterp (cdr key))
-                   (<= (cdr key) 256))
-              ;; ASCII char range, some of which has punctuation/symbol syntax
-              (with-syntax-table org-mode-syntax-table
-                (dolist (k (number-sequence (car key) (cdr key)))
-                  (when (memq (char-syntax k) '(?. ?_))
-                    (setq result (cons k result)))))))))))
-
-(defun hywiki-remap-buttonize-characters ()
-  "Remap Org self-insert punct/sym keys in `hywiki-mode` to 
`hywiki-buttonize`."
-  (unless hywiki--buttonize-characters
-    (setq hywiki--buttonize-characters
-         (concat " \r\n\)\]\>\}'" (hywiki-get-buttonize-characters))))
-  (mapc (lambda (c) (define-key hywiki-mode-map (char-to-string c) 
'hywiki-buttonize))
-       hywiki--buttonize-characters))
-
-;; Initialize hywiki-mode-map when null.
-(defun hywiki-initialize-mode-map ()
-  (setq hywiki-mode-map (make-sparse-keymap))
-  (hywiki-remap-buttonize-characters))
-
-(unless hywiki-mode-map
-  (hywiki-initialize-mode-map))
-
-(define-minor-mode hywiki-mode
-  "A minor mode for HyWiki."
-  :lighter " HyWiki"
-  :keymap hywiki-mode-map)
+         (hywiki-highlight-page-names)
+         (run-hooks 'hywiki-find-page-hook)
+         page-file)))))
 
 ;;; ************************************************************************
 ;;; Public functions
@@ -299,20 +325,18 @@ Use `hywiki-get-page' to determine whether a HyWiki page 
exists."
            (memq (char-before) '(?\( ?\{ ?\" ?\' ?\` ?\  ?\t ?\n ?\r ?\f)))
     t))
 
-(defun hywiki-at-wikiword (&optional org-link-flag)
+(defun hywiki-at-wikiword ()
   "Return HyWiki word and optional #section at point or nil if not on one.
 Does not test whether or not a page exists for the HyWiki word.
 Use `hywiki-get-page' to determine whether a HyWiki page exists."
   (when hywiki-mode
-    (let (wikiword)
-      (if (or org-link-flag (hsys-org-link-at-p))
-         ;; Handle an Org link [[HyWiki word]] [[hy:HyWiki word]] or [[HyWiki 
word#section]].
+    (let ((wikiword (ibut:label-p t "[[" "]]")))
+      (if wikiword
+         ;; Handle an Org link [[HyWikiWord]] [[hy:HyWikiWord]] or 
[[HyWikiWord#section]].
          (progn
            (setq wikiword
-                 (org-link-expand-abbrev
-                  (org-link-unescape
-                   (string-trim (match-string-no-properties 1)))))
-           ;; Ignore hy:word hywiki:word since Org mode will display those.
+                 (org-link-expand-abbrev (org-link-unescape (string-trim 
wikiword))))
+           ;; Ignore prefixed, typed hy:HyWikiWord since Org mode will display 
those.
            (when (hywiki-is-wikiword wikiword)
              wikiword))
        ;; Handle a HyWiki word with optional #section; if it is an Org
@@ -328,16 +352,16 @@ Use `hywiki-get-page' to determine whether a HyWiki page 
exists."
 
 ;; Globally set these values to avoid using 'let' with stack allocations
 ;; within `hywiki-highlight-page-name' frequently.
-(setq hywiki--any-page-regexp nil
-      hywiki--but nil
-      hywiki--but-end nil
-      hywiki--but-start nil
-      hywiki--current-page nil
-      hywiki--end nil
-      hywiki--page-name nil
-      hywiki--save-case-fold-search nil
-      hywiki--save-org-link-type-required nil
-      hywiki--start nil)
+(defvar hywiki--any-page-regexp nil)
+(defvar hywiki--but nil)
+(defvar hywiki--but-end nil)
+(defvar hywiki--but-start nil)
+(defvar hywiki--current-page nil)
+(defvar hywiki--end nil)
+(defvar hywiki--page-name nil)
+(defvar hywiki--save-case-fold-search nil)
+(defvar hywiki--save-org-link-type-required nil)
+(defvar hywiki--start nil)
 
 (defun hywiki-highlight-page-names ()
   "Highlight all non-Org link HyWiki page names in a HyWiki buffer.
@@ -409,7 +433,10 @@ the current page unless they have sections attached."
 
       (unless on-page-name
        ;; after page name
-       (goto-char (max (1- (point)) (point-min))))
+       (skip-syntax-backward "-"))
+      ;; May be a closing delimiter that we have to skip past
+      (skip-chars-backward (regexp-quote hywiki--buttonize-characters))
+      ;; Skip pass HyWikiWord or section
       (skip-syntax-backward "^-$()._\"\'")
       (skip-chars-backward "#[:alpha:]")
 
@@ -451,10 +478,11 @@ the current page unless they have sections attached."
 The page for the word may not yet exist.  Use `hywiki-get-page'
 to determine whether a HyWiki word page exists."
   (and (stringp word)
-       (or (eq (string-match (concat "\\`" hywiki-word-org-link-regexp "\\'") 
word)
-              0)
-          (eq (string-match (concat "\\`" hywiki-word-optional-section-regexp 
"\\'") word)
-              0))))
+       (let (case-fold-search)
+        (or (eq (string-match (concat "\\`" hywiki-word-org-link-regexp "\\'") 
word)
+                0)
+            (eq (string-match (concat "\\`" 
hywiki-word-optional-section-regexp "\\'") word)
+                0)))))
 
 (defun hywiki-get-buffer-page-name ()
   "Extract the page name from the buffer file name or else buffer name."
@@ -484,7 +512,8 @@ No validation of PAGE-NAME is done."
 (defun hywiki-get-page-files ()
   "Return the list of existing HyWiki page file names.
 These may have any alphanumeric file suffix, if files were added manually."
-  (directory-files-recursively hywiki-directory (concat "^" hywiki-word-regexp 
"\\.[A-Za-z0-9]+$")))
+  (when (and (stringp hywiki-directory) (file-readable-p hywiki-directory))
+    (directory-files-recursively hywiki-directory (concat "^" 
hywiki-word-regexp "\\.[A-Za-z0-9]+$"))))
 
 (defun hywiki-get-page-hasht ()
   "Return hash table of existing HyWiki pages."
@@ -523,7 +552,8 @@ Use `hywiki-get-page' to determine whether a HyWiki page 
exists."
                            page-files)))
     (setq hywiki--pages-hasht (hash-make page-elts))))
 
-(when (featurep 'company)
+(eval-and-compile
+'(when (featurep 'company)
 (defun hywiki-company-hasht-backend (command &optional _arg &rest ignored)
  "A `company-mode` backend that completes from the keys of a hash table."
  (interactive (list 'interactive))
@@ -537,7 +567,7 @@ Use `hywiki-get-page' to determine whether a HyWiki page 
exists."
           (cl-loop for key being the hash-keys in (hywiki-get-page-list)
                    when (string-prefix-p prefix key)
                    collect key))))
-     ('sorted t)))))
+     ('sorted t))))))
 
 (defun hywiki-org-link-complete (&optional _arg)
   "Complete HyWiki page names for `org-insert-link'."
@@ -566,8 +596,6 @@ Use `hywiki-get-page' to determine whether a HyWiki page 
exists."
                         :follow #'hywiki-find-page
                         :store #'hywiki-org-link-store)
 
-(add-hook 'org-mode-hook
-         (lambda ()
-           (add-hook 'find-file-hook #'hywiki-find-page t)))
+(add-hook 'find-file-hook #'hywiki-find-page t)
 
 (provide 'hywiki)

Reply via email to