branch: externals/hyperbole commit 64ce04dc4aaf85375838e61d75c7da07b933a918 Author: bw <r...@gnu.org> Commit: bw <r...@gnu.org>
hywiki.el - Enable hywiki-mode on hywiki pages and highlight Extend hywiki characters that highlight wiki words to symbol chars. Fix hpath:find and anchor handling for dired and other non-file modes. --- ChangeLog | 22 +++++++++ hpath.el | 9 ++-- hywiki.el | 126 +++++++++++++++++++++++++++++---------------------- test/hyrolo-tests.el | 14 +++--- 4 files changed, 106 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4596b25827..859b025468 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,27 @@ 2024-05-18 Bob Weiner <r...@gnu.org> +* test/hyrolo-tests.el (hyrolo-tests--goto-kotl-header-with-slash-match): Start + to try to fix this test. + +* hpath.el (hpath:find, hpath:to-markup-anchor): Fix for directory pathnames so + properly handles anchors, line numbers, column numbers and 'hpath-find' returns + the buffer found. Also, make 'hpath:to-markup-anchor' handle any special buffer + types without attached buffers. + +* hywiki.el (hywiki-get-org-insertion-punctuation-keys): Allow for symbol syntax + chars and rename to 'hywiki-get-buttonize-characters'. + (hywiki-remap-org-insertion-punctuation-keys): Rename to + 'hywiki-remap-buttonize-characters'. + (hywiki--buttonize-characters): Add as a computed string of single + characters that each trigger prior hywiki word highlighting when it is enabled. + (hywiki-highlight-page-name, hywiki-highlight-page-names): Don't skip + back over symbol chars. + (hywiki-find-page): Use this function as the 'find-file-hook' instead + of 'hywiki-highlight-page-names'; make 'page-name' optional for this use since + the current buffer will be the page, so the page name can be derived. If calling + this function creates the page buffer, then enable hywiki-mode and call + 'hywiki-highlight-page-names'. + * hui-em-but.el (hproperty:but-clear-all-in-list, hproperty:but-get-all-in-region): Add. diff --git a/hpath.el b/hpath.el index 3ee53c65bf..d4abba08ae 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: 5-May-24 at 23:48:12 by Bob Weiner +;; Last-Mod: 18-May-24 at 19:06:22 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1571,9 +1571,10 @@ but locational suffixes within the file are utilized." ;; matching of path is likely to be wrong in ;; certain cases, e.g. with mount point or os path ;; alterations. - (when (and buffer-file-name + (when (or (null buffer-file-name) + (and buffer-file-name (equal (file-name-nondirectory path) - (file-name-nondirectory buffer-file-name))) + (file-name-nondirectory buffer-file-name)))) (cond ((and anchor kotl-flag) (klink:act path-with-anchor anchor-start-pos)) ((or hash anchor) @@ -1637,7 +1638,7 @@ of the buffer." (and buffer-file-name (string-match-p "\\`[A-Z][A-Z0-9]+\\'" buffer-file-name))) hpath:outline-section-pattern) - (prog-mode + ((or prog-mode (null buffer-file-name)) "%s") ((or (and buffer-file-name (string-match-p hpath:markdown-suffix-regexp buffer-file-name)) diff --git a/hywiki.el b/hywiki.el index 103df390e7..833a263b38 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: 18-May-24 at 11:22:07 by Bob Weiner +;; Last-Mod: 18-May-24 at 20:00:23 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -40,7 +40,7 @@ ;; for any delimiters. Simply type them out, e.g. Emacs and if a ;; page exists for the word, it is automatically highlighted when: ;; - a HyWiki page file is read in -;; - a whitespace character, ')', '}', or Org-mode punctuation +;; - a whitespace character, ')', '}', or Org-mode punctuation/symbol ;; character is inserted following a HyWiki word ;; - the Action Key is pressed to activate a HyWiki word button. ;; @@ -86,9 +86,13 @@ (defvar hywiki-file-suffix ".org" "File suffix (including period) to use when creating HyWiki pages.") -(defconst hywiki-directory '"~/hywiki/" +(defvar hywiki-directory '"~/hywiki/" "Directory in which to find HyWiki page files.") +;; Define the keymap for hywiki-mode. +(defvar hywiki-mode-map nil + "Keymap for `hywiki-mode'.") + (defconst hywiki-org-link-type "hy" "HyWiki string prefix type for Org links. Excludes trailing colon.") @@ -147,24 +151,43 @@ the HyWiki word and grouping 2 is the #section with the # included.") (hywiki-highlight-page-name t) (hact 'hywiki-find-page page-name)))) -(defun hywiki-find-page (page-name &optional prompt-flag) +(defun hywiki-find-page (&optional page-name prompt-flag) "Display HyWiki PAGE-NAME. By default, create any non-existent page. With optional PROMPT-FLAG t, prompt to create if non-existent. If PROMPT-FLAG is 'exists, return nil unless the page already exists." (interactive (list (completing-read "Find HyWiki page: " (hywiki-get-page-list)))) - (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) - (if prompt-flag - (unless (eq prompt-flag 'exists) - (when (y-or-n-p (concat "Create new `" page-name "' page? ")) - (hywiki-add-page page-name))) - (hywiki-add-page page-name))))) - (when page-file - (hpath:find (concat page-file section))))) + + (let ((in-page-flag (null page-name)) + (in-hywiki-directory-flag (string-prefix-p (expand-file-name hywiki-directory) + (or buffer-file-name "")))) + ;; If called from `find-file-hook' without a page-name and outside + ;; hywiki-directory, do nothing (just finding a regular file). + (when (or (stringp page-name) in-hywiki-directory-flag) + (when in-page-flag + ;; Current buffer must be the desired page (called from 'find-file-hook') + (unless in-hywiki-directory-flag + (error "(hywiki-find-page): No `page-name'; buffer file must be in `hywiki-directory', not %s" + default-directory)) + (when (null buffer-file-name) + (error "(hywiki-find-page): No `page-name' given in a buffer without an attached file")) + (setq page-name (file-name-sans-extension (file-name-nondirectory buffer-file-name)))) + + (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) + (if prompt-flag + (unless (eq prompt-flag 'exists) + (when (y-or-n-p (concat "Create new `" page-name "' page? ")) + (hywiki-add-page page-name))) + (hywiki-add-page page-name)))) + (page-buffer (and page-file (get-file-buffer page-file)))) + (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 @@ -184,15 +207,16 @@ Do this only if the expression is an implicit button of hywiki type." ;; (let ((key (concat "<" char ">"))) ;; (when (bound-and-true-p org-mode-map)))))) -(defun hywiki-get-org-insertion-punctuation-keys () - "Return a string of Org self-insert keys that have punctuation syntax." +(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-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. + ;; 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) @@ -200,37 +224,27 @@ Do this only if the expression is an implicit button of hywiki type." (when (eq cmd 'self-insert-command) (cond ((and (characterp key) (= (char-syntax key) ?.)) - ;; char with punctuation syntax + ;; 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 syntax + ;; 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 (= (char-syntax k) ?.) + (when (memq (char-syntax k) '(?. ?_)) (setq result (cons k result))))))))))) -(defun hywiki-remap-org-insertion-punctuation-keys () - "Remap Org self-insert punct. keys in `hywiki-mode` to `hywiki-buttonize`." +(defun hywiki-remap-remap-buttonize-characters () + "Remap Org self-insert punct/sym keys in `hywiki-mode` to `hywiki-buttonize`." (mapc (lambda (c) (define-key hywiki-mode-map (char-to-string c) 'hywiki-buttonize)) - (hywiki-get-org-insertion-punctuation-keys))) - -;; Define the keymap for hywiki-mode. -(defvar hywiki-mode-map nil - "Keymap for `hywiki-mode'.") + hywiki--buttonize-characters)) ;; Initialize hywiki-mode-map when null. (defun hywiki-initialize-mode-map () (setq hywiki-mode-map (make-sparse-keymap)) - (hywiki-remap-org-insertion-punctuation-keys) - (define-key hywiki-mode-map ")" 'hywiki-buttonize) - (define-key hywiki-mode-map "]" 'hywiki-buttonize) - (define-key hywiki-mode-map ">" 'hywiki-buttonize) - (define-key hywiki-mode-map "}" 'hywiki-buttonize) - (define-key hywiki-mode-map (kbd "SPC") 'hywiki-buttonize) - (define-key hywiki-mode-map (kbd "RET") 'hywiki-buttonize)) + (hywiki-remap-org-insertion-non-word-keys)) (unless hywiki-mode-map (hywiki-initialize-mode-map)) @@ -316,9 +330,7 @@ Use `hywiki-get-page' to determine whether a HyWiki page exists." (defun hywiki-highlight-page-names () "Highlight all non-Org link HyWiki page names in a HyWiki buffer. Use `hywiki-word-face' to highlight. Does not highlight references to -the current page unless they have sections attached. - -Automatically called as a `find-file-hook'." +the current page unless they have sections attached." (interactive) ;; Avoid doing any lets for efficiency. ;; Highlight HyWiki words in buffers where `hywiki-mode' is enabled @@ -344,11 +356,11 @@ Automatically called as a `find-file-hook'." (goto-char hywiki--start) (when (hywiki-maybe-at-wikiword-beginning) ;; Include any #section. - (skip-syntax-forward "^-\)$\>.\"\'") + (skip-syntax-forward "^-\)$\>._\"\'") (skip-chars-forward "-#[:alnum:]") (setq hywiki--end (point)) - ;; Don't highlight current-page matches unless - ;; they include a #section. + ;; Don't highlight current-page matches unless they + ;; include a #section. (unless (string-equal hywiki--current-page (buffer-substring-no-properties hywiki--start hywiki--end)) (hproperty:but-add hywiki--start hywiki--end hywiki-word-face))))))) @@ -376,17 +388,18 @@ the current page unless they have sections attached." ;; of a larger balanced delimiter text with multiple words. ;; If there is just a single HyWikiWord, it will be ;; re-highlighted later in this function. - (ignore-errors - (let* ((sexp-end (point)) - (sexp-start (scan-sexps sexp-end -1))) - (when sexp-start - (hproperty:but-clear-all-in-list - (hproperty:but-get-all-in-region sexp-start sexp-end 'face hywiki-word-face)))))) + ;; (ignore-errors + ;; (let* ((sexp-end (point)) + ;; (sexp-start (scan-sexps sexp-end -1))) + ;; (when sexp-start + ;; (hproperty:but-clear-all-in-list + ;; (hproperty:but-get-all-in-region sexp-start sexp-end 'face hywiki-word-face))))) + ) (unless on-page-name ;; after page name (goto-char (max (1- (point)) (point-min)))) - (skip-syntax-backward "^-$().\"\'") + (skip-syntax-backward "^-$()._\"\'") (skip-chars-backward "#[:alpha:]") (setq hywiki--save-case-fold-search case-fold-search @@ -419,7 +432,7 @@ the current page unless they have sections attached." (hproperty:but-add hywiki--start hywiki--end hywiki-word-face)))) ;; Remove any potential earlier highlighting since the ;; previous word may have changed. - (skip-syntax-backward "^-$().\"\'") + (skip-syntax-backward "^-$()._\"\'") (hproperty:but-clear (point) 'face hywiki-word-face))))) (defun hywiki-is-wikiword (word) @@ -544,12 +557,17 @@ Use `hywiki-get-page' to determine whether a HyWiki page exists." (add-hook 'org-mode-hook (lambda () - (add-hook 'find-file-hook #'hywiki-highlight-page-names t))) + (add-hook 'find-file-hook #'hywiki-find-page t))) ;;; ************************************************************************ ;;; Private variables ;;; ************************************************************************ +(defvar hywiki--buttonize-characters + (concat " \r\n\)\]\>\}'" (hywiki-get-buttonize-characters)) + "String of single character keys bound to `hywiki-buttonize'. +Each such key self-inserts before highlighting any prior HyWiki word.") + (defvar hywiki--pages-hasht nil) (provide 'hywiki) diff --git a/test/hyrolo-tests.el b/test/hyrolo-tests.el index d2655e297c..13444faf8b 100644 --- a/test/hyrolo-tests.el +++ b/test/hyrolo-tests.el @@ -3,7 +3,7 @@ ;; Author: Mats Lidell <ma...@gnu.org> ;; ;; Orig-Date: 19-Jun-21 at 22:42:00 -;; Last-Mod: 31-Mar-24 at 22:29:58 by Mats Lidell +;; Last-Mod: 18-May-24 at 20:14:05 by Bob Weiner ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;; @@ -1613,21 +1613,21 @@ body (ert-deftest hyrolo-tests--goto-kotl-header-with-slash-match () "Move from heading match to target line with a slash in kotl file." :expected-result :failed - (let* ((kotl-file1 (hyrolo-tests--gen-kotl-outline "h1 / h2" "body" 1)) + (let* ((kotl-file1 (hyrolo-tests--gen-kotl-outline "h1" "body" 1)) (hyrolo-file-list (list kotl-file1))) (unwind-protect (progn - (hyrolo-grep "h2") - (hyrolo-next-match) + (kotl-mode:beginning-of-buffer) + (hyrolo-grep "h1/h1 1") (action-key) (should (string= (buffer-file-name) kotl-file1)) - (should (looking-at-p "h2$")) + (should (looking-at-p "h1 1$")) (should (string= (buffer-substring-no-properties (point-min) (point-max)) "\ - 1. h1 / h2 + 1. h1 body - 1a. h1 / h2 1 + 1a. h2 body 1 " )))