Skip to content

Commit

Permalink
hywiki.el - Persistent loading and saving of all referent types
Browse files Browse the repository at this point in the history
  • Loading branch information
rswgnu committed Jan 26, 2025
1 parent 5ebcc83 commit c3d8636
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 40 deletions.
26 changes: 26 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,37 @@
hywiki-tests--action-key-on-wikiword-and-line-column-displays-page):
Fix both of these so they no longer fail.

* test/hy-test-helpers.el (hy-delete-dir-and-buffer): Add support for
deleting automatically created HyWiki cache .hywiki.eld file
before trying to delete directory.

* hui-select.el (hui-select-at-delimited-sexp-p): Correct doc.

* hywiki.el (hywiki-get-referent-hasht): Load/build referent hash table
t if invalid or empty.

* hasht.el (hash-prin1): Add 'reverse' arg and use in 'hywiki-cache-save'.

* hywiki.el (hywiki-maybe-highlight-page-names,
hywiki-maybe-highlight-wikiwords-in-frame, hywiki-add-page):
Replace calls to 'hywiki-directory-set-mod-time' and
'hywiki-directory-set-checksum' with 'hywiki-env-save'.
(hywiki--referent-alist): Add.
(hywiki-cache-default-file, hywiki-cache-file, hywiki-cache-default-file,
hywiki-cache-edit, hywiki-cache-save): Add to save HyWikiWord referent
relations in a persistent cache. This makes HyWikis with multiple referent
types work across Emacs sessions.
(hywiki-make-referent-hasht): Add load from persistent cache.

* README.md: Update to show HTML, Info and PDF links to the Hyperbole Manual
as the first section in this file for easy reference.

* hmouse-tag.el (smart-emacs-lisp-mode-p): Add 'lisp-data-mode' support for
.eld files.

* hywiki.el (hywiki-set-directory): Ensure hash table has been created if
skip call 'hywiki-make-referent-hasht'.

* hasht.el: Change to use lexical scope.
(hash-make): Speed up by referencing 'reverse' value only once.
(hashp): Remove, use builtin 'hash-table-p' instead.
Expand Down
4 changes: 2 additions & 2 deletions hmouse-tag.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 24-Aug-91
;; Last-Mod: 16-Dec-24 at 00:34:24 by Bob Weiner
;; Last-Mod: 26-Jan-25 at 10:33:32 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
Expand Down Expand Up @@ -416,7 +416,7 @@ When optional NO-FLASH, do not flash."
;; Beyond Lisp files, Emacs Lisp symbols appear frequently in Byte-Compiled
;; buffers, debugger buffers, program ChangeLog buffers, Help buffers,
;; *Warnings*, *Flymake log* and *Flymake diagnostics buffers.
(or (apply #'derived-mode-p '(emacs-lisp-mode lisp-interaction-mode
(or (apply #'derived-mode-p '(emacs-lisp-mode lisp-data-mode lisp-interaction-mode
debugger-mode ert-results-mode))
(string-match-p (concat "\\`\\*\\(Warnings\\|Flymake log\\|Compile-Log\\(-Show\\)?\\)\\*"
"\\|\\`\\*Flymake diagnostics")
Expand Down
5 changes: 3 additions & 2 deletions hui-select.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 19-Oct-96 at 02:25:27
;; Last-Mod: 19-Jan-25 at 10:04:03 by Bob Weiner
;; Last-Mod: 26-Jan-25 at 17:04:55 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
Expand Down Expand Up @@ -894,7 +894,8 @@ Return t if selected, else nil."
(goto-char (match-end 0)))))))

(defun hui-select-at-delimited-sexp-p ()
"Select a delimited sexp."
"Return non-nil if at the start or on the end char of an sexpression.
Use `hui-select-mark-delimited-sexp' to select it."
(unless (eolp)
(let ((syn-before (if (char-before) (char-syntax (char-before)) 0))
(syn-after (if (char-after) (char-syntax (char-after)) 0)))
Expand Down
161 changes: 127 additions & 34 deletions hywiki.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 21-Apr-24 at 22:41:13
;; Last-Mod: 21-Jan-25 at 00:20:28 by Mats Lidell
;; Last-Mod: 26-Jan-25 at 18:01:00 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
;; Copyright (C) 2024 Free Software Foundation, Inc.
;; Copyright (C) 2024-2025 Free Software Foundation, Inc.
;; See the "HY-COPY" file for license information.
;;
;; This file is part of GNU Hyperbole.
Expand Down Expand Up @@ -210,7 +210,11 @@ See `current-time' function for the mod time format.")
"Standard syntax table for Org mode buffers with HyWiki support.")

(defvar hywiki--pages-directory nil)
(defvar hywiki--referent-hasht nil)
(defvar hywiki--referent-alist nil
"HyWiki alist generated from `hywiki--referent-hasht' for storage in cache.
Each element is of the form: (wikiword . (referent-type . referent-value)).")
(defvar hywiki--referent-hasht nil
"HyWiki hash table for fast WikiWord referent lookup.")

;; Globally set these values to avoid using 'let' with stack allocations
;; within `hywiki-maybe-highlight-page-name' frequently.
Expand Down Expand Up @@ -282,7 +286,8 @@ Use nil for no HyWiki mode indicator."
;;;###autoload
(defun hywiki-set-directory (option value)
(unless (and (boundp 'hywiki-directory)
(equal hywiki-directory (file-name-as-directory value)))
(equal hywiki-directory (file-name-as-directory value))
(hash-table-p hywiki--referent-hasht))
(set-default option (file-name-as-directory value))
(hywiki-clear-referent-hasht)
(hywiki-make-referent-hasht))
Expand Down Expand Up @@ -825,8 +830,7 @@ an error is triggered."
(hywiki-get-referent-hasht)))
(setq hywiki--any-wikiword-regexp-list nil)
(unless (hyperb:stack-frame '(hywiki-maybe-highlight-wikiwords-in-frame))
(hywiki-directory-set-mod-time)
(hywiki-directory-set-checksum))
(hywiki-cache-save))
(run-hooks 'hywiki-add-referent-hook)
referent))

Expand Down Expand Up @@ -1182,8 +1186,7 @@ Use `hywiki-get-referent' to determine whether a HyWiki page exists."
(message "HyWikiWord page exists: \"%s\"" page-file)))
(unless (or (hyperb:stack-frame '(hywiki-maybe-highlight-wikiwords-in-frame))
(and (not force-flag) page-file-readable page-in-hasht))
(hywiki-directory-set-mod-time)
(hywiki-directory-set-checksum))
(hywiki-cache-save))
(run-hooks 'hywiki-add-page-hook)
(when page-file (cons 'page page-file))))
(when (called-interactively-p 'interactive)
Expand Down Expand Up @@ -1465,9 +1468,16 @@ Use `dired' unless `action-key-modeline-buffer-id-function' is set to
(setq hywiki--directory-checksum (hywiki-directory-get-checksum)))

(defun hywiki-directory-set-mod-time ()
"Store the last page mod time for `hywiki-directory' as an integer."
"Store the last page mod time for `hywiki-directory'.
Use `time-since' to see the time in seconds since this modification time."
(setq hywiki--directory-mod-time (hywiki-directory-get-mod-time)))

(defun hywiki-maybe-directory-updated ()
"When a HyWiki directory is modified, reset its modified time and checksum."
(hywiki-directory-set-mod-time)
(hywiki-directory-set-checksum))


;;;###autoload
(defun hywiki-find-referent (&optional wikiword prompt-flag)
"Display optional HyWiki WIKIWORD referent or if nil, use current buffer.
Expand Down Expand Up @@ -2136,8 +2146,7 @@ value of `hywiki-word-highlight-flag' is changed."
;; when `hywiki-word-highlight-flag' is nil.
(hywiki-maybe-dehighlight-page-names region-start region-end))
(unless (hyperb:stack-frame '(hywiki-maybe-highlight-wikiwords-in-frame))
(hywiki-directory-set-mod-time)
(hywiki-directory-set-checksum))
(hywiki-maybe-directory-updated))
nil)

(defun hywiki-maybe-highlight-wikiwords-in-frame (frame &optional skip-lookups-update-flag)
Expand All @@ -2156,8 +2165,7 @@ the current page unless they have sections attached."
(sit-for 0)
(hywiki-maybe-highlight-page-names nil nil skip-lookups-update-flag)))
nil frame)
(hywiki-directory-set-mod-time)
(hywiki-directory-set-checksum))
(hywiki-maybe-directory-updated))

(defun hywiki-in-page-p ()
"Return non-nil if the current buffer is a HyWiki page.
Expand Down Expand Up @@ -2232,9 +2240,9 @@ regexps of wikiwords, if the hash table is out-of-date."
(if (and (equal hywiki--pages-directory hywiki-directory)
;; If page files changed, have to rebuild referent hash table
(not (hywiki-directory-modified-p))
hywiki--referent-hasht)
(hash-table-p hywiki--referent-hasht)
(not (hash-empty-p hywiki--referent-hasht)))
hywiki--referent-hasht
(setq hywiki--any-wikiword-regexp-list nil)
;; Rebuild referent hash table
(hywiki-make-referent-hasht))
(unless hywiki--any-wikiword-regexp-list
Expand Down Expand Up @@ -2335,27 +2343,112 @@ If deleted, update HyWikiWord highlighting across all frames."
collect key))))
('sorted t))))))

(defvar hywiki-cache-default-file ".hywiki.eld"
"Standard file name for storing cached data for a HyWiki.")

(defvar hywiki-cache-file nil
"Current HyWiki cache file, if any.
If nil, use: (expand-file-name hywiki-cache-default-file hywiki-directory).")

(defun hywiki-cache-default-file (&optional directory)
"Return a HyWiki cache file for optional DIRECTORY or `hywiki-directory'.
The filename is either the string value of `hywiki-cache-file', or else the
value of `hywiki-cache-default-file'. The filename returned is an
absolute path."
(expand-file-name (or hywiki-cache-file hywiki-cache-default-file)
(or directory hywiki-directory)))

(defun hywiki-cache-edit (cache-file)
"Read in CACHE-FILE for editing and disable undo and backups within it."
(prog1 (set-buffer (find-file-noselect cache-file))
(buffer-disable-undo (current-buffer))
(make-local-variable 'make-backup-files)
(make-local-variable 'backup-inhibited)
(setq make-backup-files nil
backup-inhibited t
buffer-read-only nil)))

(defun hywiki-cache-save (&optional save-file)
"Save the modified Environment to a file given by optional SAVE-FILE or `hywiki-cache-file'.
Also saves and potentially sets `hywiki--directory-mod-time' and
hywiki--directory-checksum'."
(when (or (not (stringp save-file)) (equal save-file ""))
(setq save-file (hywiki-cache-default-file)))
(setq save-file (expand-file-name save-file hywiki-directory))
(or (file-writable-p save-file)
(error "(hywiki-cache-save): Non-writable Environment file, \"%s\"" save-file))
(let ((buf (get-file-buffer save-file)))
(and buf (kill-buffer buf)))
(let ((dir (or (file-name-directory save-file)
default-directory)))
(or (file-writable-p dir)
(error "(hywiki-cache-save): Non-writable Environment directory, \"%s\"" dir)))
(save-window-excursion
(let ((standard-output (hywiki-cache-edit save-file)))
(with-current-buffer standard-output
(erase-buffer)
(princ ";; -*- mode:lisp-data; coding: utf-8-emacs; -*-\n")

(princ (format "\n(setq\nhyperb:version %S\n" hyperb:version))

(princ (format "\nhywiki-directory %S\n" hywiki-directory))

;; Save last `hywiki-directory' mod time and checksum, nil if none.
(princ (format "\nhywiki--directory-mod-time '%S\n" (hywiki-directory-set-mod-time)))

(princ (format "\nhywiki--directory-checksum %S\n"
(hywiki-directory-set-checksum)))

(princ "\nhywiki--referent-alist\n'")
(hash-prin1 (hywiki-get-referent-hasht) nil t)
(princ ")\n")

(save-buffer)
(set-buffer-modified-p nil)
(kill-buffer standard-output)))))

(defun hywiki-make-referent-hasht ()
"Rebuld referent hasht from list of HyWiki page files and non-page entries."
(let* ((page-files (hywiki-get-page-files))
(non-page-elts (when (hashp hywiki--referent-hasht)
(delq nil
(hash-map 'hywiki-non-page-elt
hywiki--referent-hasht))))
(non-page-hasht (hash-make non-page-elts))
(key)
(page-elts (delq nil (mapcar (lambda (file)
(setq key (file-name-sans-extension file))
(unless (hash-get key non-page-hasht)
(cons (cons 'page file) key)))
page-files))))
(setq hywiki--any-wikiword-regexp-list nil
hywiki--pages-directory hywiki-directory
hywiki--referent-hasht
(if non-page-elts
(hash-merge non-page-hasht
(hash-make page-elts))
(hash-make page-elts)))))
(setq hywiki--any-wikiword-regexp-list nil
hywiki--pages-directory hywiki-directory)
;; Try to load from a .hywiki.eld cache file if up-to-date
(let* ((cache-file (hywiki-cache-default-file))
(cache-buffer (when (file-readable-p cache-file)
(find-file-noselect cache-file)))
(hywiki-loaded-flag (when cache-buffer
(with-current-buffer cache-buffer
(widen)
(goto-char (point-min))
;; Skip past initial comments
(when (re-search-forward "^(" nil t)
(goto-char (1- (point)))
(condition-case ()
(progn (eval (read (buffer-string)))
t)
(error nil)))))))
(if (and hywiki-loaded-flag (not (hywiki-directory-modified-p)))
;; Rebuild from loaded data
(setq hywiki--referent-hasht (hash-make hywiki--referent-alist t)
hywiki--referent-alist nil)
;; Read `hywiki-directory' for current page files and merge with
;; non-page referents
(let* ((page-files (hywiki-get-page-files))
(non-page-elts (when (hash-table-p hywiki--referent-hasht)
(delq nil
(hash-map 'hywiki-non-page-elt
hywiki--referent-hasht))))
(non-page-hasht (hash-make non-page-elts))
(key)
(page-elts (delq nil (mapcar (lambda (file)
(setq key (file-name-sans-extension file))
(unless (hash-get key non-page-hasht)
(cons (cons 'page file) key)))
page-files))))
(setq hywiki--referent-hasht
(if non-page-elts
(hash-merge non-page-hasht
(hash-make page-elts))
(hash-make page-elts)))))))

(defun hywiki-non-page-elt (val-key)
(unless (eq (caar val-key) 'page) val-key))
Expand Down
11 changes: 9 additions & 2 deletions test/hy-test-helpers.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
;; Author: Mats Lidell <[email protected]>
;;
;; Orig-Date: 30-Jan-21 at 12:00:00
;; Last-Mod: 21-Jan-25 at 17:02:36 by Mats Lidell
;; Last-Mod: 26-Jan-25 at 18:24:56 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
Expand Down Expand Up @@ -95,9 +95,16 @@ Checks ACTYPE, ARGS, LOC, LBL-KEY and NAME."

(defun hy-delete-dir-and-buffer (dir)
"Delete DIR and buffer visiting directory."
(let ((buf (find-buffer-visiting dir)))
(let ((buf (find-buffer-visiting dir))
(hywiki-cache (when (featurep 'hywiki)
(expand-file-name hywiki-cache-default-file
dir))))
(when buf
(kill-buffer buf))
(when (and hywiki-cache
(file-readable-p hywiki-cache)
(file-writable-p hywiki-cache))
(delete-file hywiki-cache))
(delete-directory dir)))

(defun hy-make-random-wikiword (&optional length word-length)
Expand Down

0 comments on commit c3d8636

Please sign in to comment.