branch: externals/hyperbole
commit eaf031aa6f660c6dec424a0dfc6ac3a43dc8a91e
Author: Bob Weiner <[email protected]>
Commit: Bob Weiner <[email protected]>
Redo Koutine idstamp handling for increased efficiency/smaller files
---
ChangeLog | 50 +++++++++++++++++++
kotl/EXAMPLE.kotl | 130 ++++++++++++++++++++++++------------------------
kotl/kcell.el | 70 ++++++++++----------------
kotl/kfile.el | 36 ++++++++++----
kotl/kotl-mode.el | 35 +++++++------
kotl/kproperty.el | 9 +++-
kotl/kview.el | 99 +++++++++++++++++++++---------------
test/kotl-mode-tests.el | 20 ++++----
8 files changed, 263 insertions(+), 186 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7feb66db8a..b3c444e198 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+2022-04-03 Kathy <[email protected]>
+
+* test/kotl-mode-tests.el (setup-kotl-mode-example-test): Fix so handles
multiple buffers with same
+ buffer name prefix.
+
+* kotl/kproperty.el (kproperty:remove-properties): Add and use in
kcell-view:remove-attr.
+
+* test/kotl-mode-tests.el
(kotl-mode-copy-kotl-file-updates-root-id-attributes): Change from 'file attr
+ test to 'label-type.
+
+* kotl/kview.el (kcell-view:idstamp-integer): Add to return idstamp as int
instead of string.
+
+* kotl/kcell.el (kcell-data:create): Add idstamp as 2nd parameter.
+ kotl/kfile.el (kfile:update): Call kcell-data:create with 2nd parameter.
+
+* kotl/kotl-mode.el (kotl-mode:exchange-cells): Give idstamp as second arg to
kcell-view:set-cell calls.
+ (kotl-mode:cell-help, kotl-mode:print-attributes,
kotl-mode:get-cell-attribute):
+ Handle separate idstamp attribute.
+ kotl/kview.el (kcell-view:set-cell, kotl-mode:copy-after,
kotl-mode:copy-before): Set kcell and
+ idstamp as separate text properties.
+
+* kotl/kview.el (kcell-view:idstamp, kcell-view:get-attr, kcell-view:set-attr,
+ kcell-view:remove-attr, kcell-view:create): Always move to point with
cell's text properties
+ and handle text property idstamp.
+ (kcell-view:create): Pass idstamp as a parameter.
+ (kview:add-cell):
+ kotl/kcell.el (kcell:create):
+ kotl/kfile.el (kfile:insert-attributes-v2, kfile:insert-attributes-v3):
Store idstamp as a
+ koutline text property outside the kcell, for efficiency.
+* kotl/kcell.el (kcell:set-idstamp): Remove, use kcell-view:set-attr instead.
+ (kcell:idstamp): Remove, use kcell-view:idstamp instead.
+ (kcell-data:to-kcell-v2, kcell-data:to-kcell-v3): Remove use
of view-based idstamp.
+
+* kotl/kcell.el (kcell-data:create): idstamp is no longer stored in a kcell's
property list, so
+ don't try to delete it from the plist when creating the persistent
representation keyed
+ by the numeric value of the idstamp.
+
+* kotl/kfile.el (kfile:insert-attributes-v2, kfile:insert-attributes-v3): In
Koutline buffer,
+ store kcell properties as a single 'kcell text property, as previously in
Hyperbole 7.1.3.
+ This allows other text properties to be stored at the same position
without being written
+ out as kcell properties.
+ kotl/kcell.el (kcell:create): Stop writing 'kcell attr out to save space.
+ (kcell:is-p): Test for 'creator attr rather than 'kcell since
no longer
+ writing that attr.
+ kotl/kview.el (kcell-view:cell): Update to use 'kcell text property.
+
+* kotl/kview.el (kview:create):
+ kotl/kfile.el (kfile:write, file:update): Remove read/write of Koutline
'file attribute;
+ just use buffer-file-name.
+
2022-04-02 Mats Lidell <[email protected]>
* test/kotl-mode-tests.el (kotl-mode-move-tree-forward)
diff --git a/kotl/EXAMPLE.kotl b/kotl/EXAMPLE.kotl
index 7b6efacf50..7af7d5e8ef 100644
--- a/kotl/EXAMPLE.kotl
+++ b/kotl/EXAMPLE.kotl
@@ -413,133 +413,133 @@ alpha ;; label-type
[[0
(idstamp 0 creator "[email protected]" create-time "20220117:22:23:52" id-counter
82 file "/Users/bk/Dropbox/emacs/hyperbole/kotl/EXAMPLE.kotl")]
[20
- (creator "[email protected]" create-time "19940104:17:38:28" no-fill t
rear-nonsticky t idstamp 20 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:28" no-fill t)]
[2
- (creator "[email protected]" create-time "19940104:17:38:28" no-fill t
rear-nonsticky t idstamp 2 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:28" no-fill t)]
[34
- (creator "[email protected]" create-time "19940610:16:43:55" rear-nonsticky t
idstamp 34 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:43:55")]
[35
- (creator "[email protected]" create-time "19940610:16:44:03" rear-nonsticky t
idstamp 35 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:44:03")]
[4
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 4 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[5
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 5 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[6
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 6 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[14
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 14 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[67
- (creator "[email protected]" create-time "19951028:04:29:13" no-fill t
rear-nonsticky t idstamp 67 kcell t)]
+ (creator "[email protected]" create-time "19951028:04:29:13" no-fill t)]
[15
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 15 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[31
- (creator "[email protected]" create-time "19940306:18:11:43" rear-nonsticky t
idstamp 31 kcell t)]
+ (creator "[email protected]" create-time "19940306:18:11:43")]
[7
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 7 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[46
- (creator "[email protected]" create-time "19950614:21:35:17" rear-nonsticky t
idstamp 46 kcell t)]
+ (creator "[email protected]" create-time "19950614:21:35:17")]
[43
- (creator "[email protected]" create-time "19940610:22:00:46" rear-nonsticky t
idstamp 43 kcell t)]
+ (creator "[email protected]" create-time "19940610:22:00:46")]
[22
- (creator "[email protected]" create-time "19940127:22:41:42" rear-nonsticky t
idstamp 22 kcell t)]
+ (creator "[email protected]" create-time "19940127:22:41:42")]
[82
- (no-fill t create-time "20220126:04:52:26" creator "[email protected]" idstamp 82
kcell t fontified t)]
+ (creator "[email protected]" create-time "20220126:04:52:26" no-fill t fontified
t)]
[32
- (creator "[email protected]" create-time "19940610:16:31:28" rear-nonsticky t
idstamp 32 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:31:28")]
[41
- (creator "[email protected]" create-time "19940610:18:55:09" rear-nonsticky t
idstamp 41 kcell t)]
+ (creator "[email protected]" create-time "19940610:18:55:09")]
[42
- (creator "[email protected]" create-time "19940610:18:55:57" rear-nonsticky t
idstamp 42 kcell t)]
+ (creator "[email protected]" create-time "19940610:18:55:57")]
[33
- (creator "[email protected]" create-time "19940610:16:31:29" rear-nonsticky t
idstamp 33 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:31:29")]
[47
- (creator "[email protected]" create-time "19951022:22:59:26" no-fill t
rear-nonsticky t idstamp 47 kcell t)]
+ (creator "[email protected]" create-time "19951022:22:59:26")]
[8
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 8 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[28
- (creator "[email protected]" create-time "19940128:22:50:44" rear-nonsticky t
idstamp 28 kcell t)]
+ (creator "[email protected]" create-time "19940128:22:50:44")]
[29
- (creator "[email protected]" create-time "19940128:22:50:54" rear-nonsticky t
idstamp 29 kcell t)]
+ (creator "[email protected]" create-time "19940128:22:50:54")]
[10
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 10 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[30
- (creator "[email protected]" create-time "19940129:00:27:59" rear-nonsticky t
idstamp 30 kcell t)]
+ (creator "[email protected]" create-time "19940129:00:27:59")]
[62
- (creator "[email protected]" create-time "19951026:08:32:57" no-fill t
rear-nonsticky t idstamp 62 kcell t)]
+ (creator "[email protected]" create-time "19951026:08:32:57" no-fill t)]
[70
- (creator "[email protected]" create-time "19951030:19:18:49" no-fill t
rear-nonsticky t idstamp 70 kcell t)]
+ (creator "[email protected]" create-time "19951030:19:18:49" no-fill t)]
[71
- (creator "[email protected]" create-time "19951030:19:19:40" no-fill t
rear-nonsticky t idstamp 71 kcell t)]
+ (creator "[email protected]" create-time "19951030:19:19:40" no-fill t)]
[73
- (creator "[email protected]" create-time "19951030:19:23:09" no-fill t
rear-nonsticky t idstamp 73 kcell t)]
+ (creator "[email protected]" create-time "19951030:19:23:09" no-fill t)]
[63
- (creator "[email protected]" create-time "19951026:19:31:34" no-fill t
rear-nonsticky t idstamp 63 kcell t)]
+ (creator "[email protected]" create-time "19951026:19:31:34" no-fill t)]
[64
- (creator "[email protected]" create-time "19951026:19:33:01" no-fill t
rear-nonsticky t idstamp 64 kcell t)]
+ (creator "[email protected]" create-time "19951026:19:33:01" no-fill t)]
[69
- (creator "[email protected]" create-time "19951029:06:24:35" no-fill t
rear-nonsticky t idstamp 69 kcell t)]
+ (creator "[email protected]" create-time "19951029:06:24:35" no-fill t)]
[68
- (creator "[email protected]" create-time "19951029:06:24:27" no-fill t
rear-nonsticky t idstamp 68 kcell t)]
+ (creator "[email protected]" create-time "19951029:06:24:27" no-fill t)]
[65
- (creator "[email protected]" create-time "19951026:19:33:08" no-fill t
rear-nonsticky t idstamp 65 kcell t)]
+ (creator "[email protected]" create-time "19951026:19:33:08" no-fill t)]
[66
- (creator "[email protected]" create-time "19951026:19:33:15" no-fill t
rear-nonsticky t idstamp 66 kcell t)]
+ (creator "[email protected]" create-time "19951026:19:33:15" no-fill t)]
[77
- (creator "[email protected]" create-time "19980226:19:54:44" no-fill t
rear-nonsticky t idstamp 77 kcell t)]
+ (creator "[email protected]" create-time "19980226:19:54:44" no-fill t)]
[48
- (creator "[email protected]" create-time "19951023:05:55:19" no-fill t
rear-nonsticky t idstamp 48 kcell t)]
+ (creator "[email protected]" create-time "19951023:05:55:19" no-fill t)]
[57
- (creator "[email protected]" create-time "19951023:10:07:06" no-fill t
rear-nonsticky t idstamp 57 kcell t)]
+ (creator "[email protected]" create-time "19951023:10:07:06" no-fill t)]
[58
- (creator "[email protected]" create-time "19951023:10:07:26" no-fill t
rear-nonsticky t idstamp 58 kcell t)]
+ (creator "[email protected]" create-time "19951023:10:07:26" no-fill t)]
[49
- (creator "[email protected]" create-time "19951023:05:55:55" no-fill t
rear-nonsticky t idstamp 49 kcell t)]
+ (creator "[email protected]" create-time "19951023:05:55:55" no-fill t)]
[55
- (creator "[email protected]" create-time "19951023:08:56:41" no-fill t
rear-nonsticky t idstamp 55 kcell t)]
+ (creator "[email protected]" create-time "19951023:08:56:41" no-fill t)]
[50
- (creator "[email protected]" create-time "19951023:05:57:26" no-fill t
rear-nonsticky t idstamp 50 kcell t)]
+ (creator "[email protected]" create-time "19951023:05:57:26" no-fill t)]
[51
- (creator "[email protected]" create-time "19951023:05:58:31" no-fill t
rear-nonsticky t idstamp 51 kcell t)]
+ (creator "[email protected]" create-time "19951023:05:58:31" no-fill t)]
[56
- (creator "[email protected]" create-time "19951023:08:57:09" no-fill t
rear-nonsticky t idstamp 56 kcell t)]
+ (creator "[email protected]" create-time "19951023:08:57:09" no-fill t)]
[52
- (creator "[email protected]" create-time "19951023:05:59:59" no-fill t
rear-nonsticky t idstamp 52 kcell t)]
+ (creator "[email protected]" create-time "19951023:05:59:59" no-fill t)]
[53
- (creator "[email protected]" create-time "19951023:06:00:48" no-fill t
rear-nonsticky t idstamp 53 kcell t)]
+ (creator "[email protected]" create-time "19951023:06:00:48" no-fill t)]
[54
- (creator "[email protected]" create-time "19951023:06:05:50" no-fill t
rear-nonsticky t idstamp 54 kcell t)]
+ (creator "[email protected]" create-time "19951023:06:05:50" no-fill t)]
[26
- (creator "[email protected]" create-time "19940128:03:56:23" rear-nonsticky t
idstamp 26 kcell t)]
+ (creator "[email protected]" create-time "19940128:03:56:23")]
[27
- (creator "[email protected]" create-time "19940128:22:36:54" rear-nonsticky t
idstamp 27 kcell t)]
+ (creator "[email protected]" create-time "19940128:22:36:54")]
[59
- (creator "[email protected]" create-time "19951024:03:40:05" no-fill t
rear-nonsticky t idstamp 59 kcell t)]
+ (creator "[email protected]" create-time "19951024:03:40:05" no-fill t)]
[60
- (creator "[email protected]" create-time "19951024:03:40:13" no-fill t
rear-nonsticky t idstamp 60 kcell t)]
+ (creator "[email protected]" create-time "19951024:03:40:13" no-fill t)]
[61
- (creator "[email protected]" create-time "19951024:03:40:42" no-fill t
rear-nonsticky t idstamp 61 kcell t)]
+ (creator "[email protected]" create-time "19951024:03:40:42" no-fill t)]
[1
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 1 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[11
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 11 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[80
- (no-fill t create-time "20220117:22:26:40" creator "[email protected]" idstamp 80
kcell t fontified t)]
+ (no-fill t create-time "20220117:22:26:40" creator "[email protected]")]
[81
- (no-fill t create-time "20220117:22:26:47" creator "[email protected]" idstamp 81
kcell t fontified t)]
+ (no-fill t create-time "20220117:22:26:47" creator "[email protected]")]
[78
- (no-fill t create-time "20220117:22:26:33" creator "[email protected]" idstamp 78
kcell t fontified t)]
+ (no-fill t create-time "20220117:22:26:33" creator "[email protected]")]
[12
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 12 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[44
- (creator "[email protected]" create-time "19940728:21:56:49" rear-nonsticky t
idstamp 44 kcell t)]
+ (creator "[email protected]" create-time "19940728:21:56:49")]
[36
- (creator "[email protected]" create-time "19940610:16:49:34" rear-nonsticky t
idstamp 36 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:49:34")]
[37
- (creator "[email protected]" create-time "19940610:16:50:02" rear-nonsticky t
idstamp 37 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:50:02")]
[38
- (creator "[email protected]" create-time "19940610:16:50:13" rear-nonsticky t
idstamp 38 kcell t)]
+ (creator "[email protected]" create-time "19940610:16:50:13")]
[13
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 13 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
[16
- (creator "[email protected]" create-time "19940104:17:38:29" rear-nonsticky t
idstamp 16 kcell t)]
+ (creator "[email protected]" create-time "19940104:17:38:29")]
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil]
diff --git a/kotl/kcell.el b/kotl/kcell.el
index be35508882..95b721797f 100644
--- a/kotl/kcell.el
+++ b/kotl/kcell.el
@@ -2,8 +2,8 @@
;;
;; Author: Bob Weiner
;;
-;; Orig-Date: 5/1/1993
-;; Last-Mod: 12-Feb-22 at 19:02:00 by Bob Weiner
+;; Orig-Date: 1-May-93
+;; Last-Mod: 3-Apr-22 at 16:23:56 by Bob Weiner
;;
;; Copyright (C) 1993-2021 Free Software Foundation, Inc.
;; See the "../HY-COPY" file for license information.
@@ -12,9 +12,13 @@
;;; Commentary:
;;
-;; Defines kcells, nodes in Koutlines, along with a persistent representation
-;; called kcell-data for writing to files. Node text content is stored
-;; separately in kview for efficiency.
+;; Defines kcells, in-memory, individually addressable elements of Koutlines,
+;; along with a persistent representation called kcell-data for writing to
+;; files. Node text content is stored separately in the kview for
efficiency.
+;;
+;; For compatibility between kcell and kcell-data representations,
+;; the unique per Koutline permanent idstamp for each kcell is also stored
+;; separately. This also allows fast retrieval.
;;; Code:
;;; ************************************************************************
@@ -37,42 +41,33 @@ Add to this list but don't remove any of the default
elements.")
;;; ************************************************************************
;;;
-;;; kcell
+;;; kcell - In-memory representation of Koutline cells
;;;
(defun kcell:copy (kcell)
"Return a copy of KCELL."
(copy-tree kcell))
-(defun kcell:create (idstamp &optional plist)
- "Return a new kcell which has permanent IDSTAMP (an integer) and optional
additional property list, PLIST.
+(defun kcell:create (&optional plist)
+ "Return a new kcell with optional property list, PLIST.
User id of `creator' of cell and `create-time' are added to cell's PLIST if
not already there."
- (unless (klabel:idstamp-p idstamp)
- (error "(kcell:create): Invalid `idstamp' argument: '%s'" idstamp))
(nconc
- (unless (memq 'kcell plist)
- (list 'kcell t))
- (unless (memq 'idstamp plist)
- (list 'idstamp idstamp))
(unless (memq 'creator plist)
(list 'creator hyperb:user-email
'create-time (htz:date-sortable-gmt)))
plist))
(defun kcell:create-top (&optional top-cell-attributes)
- "Return a new koutline top cell optionally attached to FILE with current
idstamp COUNTER."
- (kcell:create 0 top-cell-attributes))
+ "Return a new koutline top cell with optional property list of
TOP-CELL-ATTRIBUTES.
+The idstamp of the top cell is always 0 and this cell stores the
idstamp-counter."
+ (kcell:create top-cell-attributes))
(defalias 'kcell:get-attr 'plist-get)
-(defun kcell:idstamp (kcell)
- "Return permanent idstamp of KCELL as an integer."
- (kcell:get-attr kcell 'idstamp))
-
(defun kcell:is-p (object)
"Is OBJECT a kcell?"
- (and (listp object) (plist-get object 'kcell)))
+ (and (listp object) (plist-get object 'creator)))
(defalias 'kcell:plist 'identity)
@@ -183,25 +178,20 @@ Augment capabilities not yet implemented and ignored for
now:
"Store the current user's id as the creator of KCELL."
(kcell:set-attr kcell 'creator hyperb:user-email))
-(defun kcell:set-idstamp (kcell idstamp)
- "Set KCELL's permanent IDSTAMP (an integer) and return IDSTAMP."
- (kcell:set-attr kcell 'idstamp idstamp)
- (kcell:idstamp kcell))
-
;;;
-;;; kcell-data - Persistent representation of kotl cells (written to files).
+;;; kcell-data - Persistent representation of Koutline cells (written to files)
;;;
-(defun kcell-data:create (cell)
- "Given a kotl CELL, return a kcell-data structure to write to a file.
+(defun kcell-data:create (cell idstamp)
+ "Given a kotl CELL and IDSTAMP (an integer), return a kcell-data structure
to write to a file.
If CELL, its idstamp, or its property list are nil, this repairs the cell by
assuming it is the cell at point and filling in the missing information."
- (let ((idstamp (kcell:idstamp cell))
- (plist (nthcdr 2 (kcell:plist cell))))
+ (let ((plist (kcell:plist cell)))
(if (and cell idstamp plist)
(vector idstamp plist)
(kcell-data:create
- (kcell:create (or idstamp (kview:id-increment kview)) plist)))))
+ (kcell:create plist)
+ (or idstamp (kview:id-increment kview))))))
(defun kcell-data:idstamp (kcell-data)
(aref kcell-data 0))
@@ -214,21 +204,13 @@ assuming it is the cell at point and filling in the
missing information."
(defun kcell-data:to-kcell-v2 (kcell-data)
(if (vectorp kcell-data)
- (kcell:create
- ;; Repair invalid idstamps on the fly.
- (or (kcell-data:idstamp kcell-data) (kview:id-increment kview))
- (kcell-data:plist-v2 kcell-data))
- ;; Repair invalid cells on the fly.
- (kcell:create (kview:id-increment kview))))
+ (kcell:create (kcell-data:plist-v2 kcell-data))
+ (kcell:create)))
(defun kcell-data:to-kcell-v3 (kcell-data)
(if (vectorp kcell-data)
- (kcell:create
- ;; Repair invalid idstamps on the fly.
- (or (kcell-data:idstamp kcell-data) (kview:id-increment kview))
- (kcell-data:plist-v3 kcell-data))
- ;; Repair invalid cells on the fly.
- (kcell:create (kview:id-increment kview))))
+ (kcell:create (kcell-data:plist-v3 kcell-data))
+ (kcell:create)))
(provide 'kcell)
diff --git a/kotl/kfile.el b/kotl/kfile.el
index 4c906f7bb2..ba7a80fd4b 100644
--- a/kotl/kfile.el
+++ b/kotl/kfile.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 10/31/93
-;; Last-Mod: 12-Feb-22 at 10:42:20 by Mats Lidell
+;; Last-Mod: 3-Apr-22 at 16:17:53 by Bob Weiner
;;
;; Copyright (C) 1993-2021 Free Software Foundation, Inc.
;; See the "../HY-COPY" file for license information.
@@ -258,7 +258,7 @@ If V3-FLAG is true, read as a version-3 buffer."
Leave outline file expanded with structure data showing unless optional
VISIBLE-ONLY-P is non-nil. Signal an error if kotl is not attached to a file."
(let* ((top (kview:top-cell kview))
- (file (kcell:get-attr top 'file))
+ (file buffer-file-name)
(label-type (kview:label-type kview))
(label-min-width (kview:label-min-width kview))
(label-separator (kview:label-separator kview))
@@ -285,13 +285,13 @@ VISIBLE-ONLY-P is non-nil. Signal an error if kotl is
not attached to a file."
(setq cell (kcell-view:cell))
(aset kcell-data
kcell-num
- (kcell-data:create cell))
+ (kcell-data:create cell (kcell-view:idstamp-integer)))
(setq kcell-num (1+ kcell-num)))
kview t)
;; Save top cell, 0, last since above loop may increment the total
;; number of cells counter stored in it, if any invalid cells are
;; encountered.
- (aset kcell-data 0 (kcell-data:create top))
+ (aset kcell-data 0 (kcell-data:create top 0))
(setq id-counter (kcell:get-attr top 'id-counter))
;;
(widen)
@@ -342,7 +342,6 @@ VISIBLE-ONLY-P is non-nil. Signal an error if kotl is not
attached to a file."
(when (and (file-directory-p file) buffer-file-name)
(setq file (concat (file-name-as-directory file)
(file-name-nondirectory buffer-file-name))))
- (kcell:set-attr (kview:top-cell kview) 'file file)
(set-visited-file-name file)
;; Set-visited-file-name clears local-write-file-hooks that we use to save
;; koutlines properly, so reinitialize local variables.
@@ -390,7 +389,9 @@ included in the list."
"Set cell attributes within KVIEW for each element in KCELL-LIST.
Assume all cell contents are already in kview and that no cells are
hidden."
- (let (buffer-read-only)
+ (let (buffer-read-only
+ idstamp
+ kcell-data)
(while
(progn
(skip-chars-forward "\n")
@@ -399,16 +400,24 @@ hidden."
;; for the location at which to place cell properties.
;; Be sure not to skip past a period which may terminate the label.
(when (re-search-forward "[A-Za-z0-9]\\(\\.?[A-Za-z0-9]\\)*" nil t)
- (kproperty:add-properties (car kcell-list))
+ (setq kcell-data (car kcell-list)
+ ;; Repair invalid idstamps on the fly.
+ idstamp (if (vectorp kcell-data)
+ (or (kcell-data:idstamp kcell-data)
(kview:id-increment kview))
+ (kview:id-increment kview)))
+ (kproperty:set 'idstamp idstamp)
+ (kproperty:set 'kcell (car kcell-list))
(setq kcell-list (cdr kcell-list)))
(search-forward "\n\n" nil t)))))
(defun kfile:insert-attributes-v3 (_kview kcell-vector)
- "Set cell attributes within KVIEW for each element in KCELL-VECTOR.
+ "Set cell attributes within _KVIEW for each element in KCELL-VECTOR.
Assume all cell contents are already in kview and that no cells are
hidden."
(let ((kcell-num 1)
- (buffer-read-only))
+ buffer-read-only
+ idstamp
+ kcell-data)
(while
(progn
(skip-chars-forward "\n")
@@ -417,8 +426,13 @@ hidden."
;; for the location at which to place cell properties.
;; Be sure not to skip past a period which may terminate the label.
(when (re-search-forward "[A-Za-z0-9]\\(\\.?[A-Za-z0-9]\\)*" nil t)
- (kproperty:add-properties
- (kcell-data:to-kcell-v3 (aref kcell-vector kcell-num)))
+ (setq kcell-data (aref kcell-vector kcell-num)
+ ;; Repair invalid idstamps on the fly.
+ idstamp (if (vectorp kcell-data)
+ (or (kcell-data:idstamp kcell-data)
(kview:id-increment kview))
+ (kview:id-increment kview)))
+ (kproperty:set 'idstamp idstamp)
+ (kproperty:set 'kcell (kcell-data:to-kcell-v3 kcell-data))
(setq kcell-num (1+ kcell-num)))
(search-forward "\n\n" nil t)))))
diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el
index 7b61253ce2..33b8aa04ad 100644
--- a/kotl/kotl-mode.el
+++ b/kotl/kotl-mode.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 6/30/93
-;; Last-Mod: 20-Mar-22 at 22:34:26 by Bob Weiner
+;; Last-Mod: 3-Apr-22 at 23:08:47 by Bob Weiner
;;
;; Copyright (C) 1993-2021 Free Software Foundation, Inc.
;; See the "../HY-COPY" file for license information.
@@ -1033,8 +1033,7 @@ Leave point at the start of the root cell of the new
tree."
;; Alter the copied tree so each cell appears to be newly created.
(kview:map-tree
(lambda (view)
- (kcell-view:set-cell
- (kcell:create (kview:id-increment view))))
+ (kcell-view:set-cell (kcell:create) (kview:id-increment view)))
kview))
(defun kotl-mode:copy-before (from-cell-ref to-cell-ref parent-p)
@@ -1059,8 +1058,7 @@ Leave point at the start of the root cell of the new
tree."
;; Alter the copied tree so each cell appears to be newly created.
(kview:map-tree
(lambda (view)
- (kcell-view:set-cell
- (kcell:create (kview:id-increment view))))
+ (kcell-view:set-cell (kcell:create) (kview:id-increment view)))
kview))
(defun kotl-mode:move-after (from-cell-ref to-cell-ref child-p
@@ -2309,13 +2307,13 @@ to one level and kotl-mode:refill-flag is treated as
true."
;; Save cell-1 attributes
(kotl-mode:goto-cell cell-ref-1 t)
(setq kcell-1 (kcell-view:cell)
- idstamp-1 (kcell-view:idstamp)
+ idstamp-1 (kcell-view:idstamp-integer)
contents-1 (kcell-view:contents))
;;
;; Save cell-2 attributes
(kotl-mode:goto-cell cell-ref-2 t)
(setq kcell-2 (cl-copy-list (kcell-view:cell))
- idstamp-2 (kcell-view:idstamp)
+ idstamp-2 (kcell-view:idstamp-integer)
contents-2 (kcell-view:contents))
;; Substitute cell-1 contents into cell-2 location.
@@ -2345,19 +2343,19 @@ to one level and kotl-mode:refill-flag is treated as
true."
;;
(kotl-mode:goto-cell cell-ref-2 t)
;; Set kcell properties.
- (kcell-view:set-cell kcell-1)
+ (kcell-view:set-cell kcell-1 idstamp-1)
;; If idstamp labels are on, then must exchange labels in view.
(when (eq (kview:label-type kview) 'id)
- (klabel:set idstamp-1)))
+ (klabel:set (format "0%d" idstamp-1))))
;;
;; Substitute cell-2 attributes into cell-1 location.
;;
;; Set kcell properties.
- (kcell-view:set-cell kcell-2)
+ (kcell-view:set-cell kcell-2 idstamp-2)
;; If idstamp labels are on, then must exchange labels in view.
(when (eq (kview:label-type kview) 'id)
- (klabel:set idstamp-2)))))
+ (klabel:set (format "0%d" idstamp-2))))))
(defun kotl-mode:kill-contents (arg)
"Kill contents of cell from point to cell end.
@@ -2937,7 +2935,8 @@ See also the documentation for
`kotl-mode:cell-attributes'."
(if (or (member cell-ref '("0" 0))
(<= cells-flag 0))
(progn
- (hattr:report (kcell:plist (kview:top-cell kview)))
+ (hattr:report (append '(idstamp 0)
+ (kcell:plist (kview:top-cell kview))))
(terpri)
(cond ((= cells-flag 1) nil)
((> cells-flag 1)
@@ -2959,9 +2958,13 @@ ATTRIBUTE and ignore any value of POS.
When called interactively, it displays the value in the minibuffer."
(interactive "SCurrent cell attribute to get: ")
(let ((value
- (if top-cell-flag
+ (if (eq attribute 'idstamp)
+ (if top-cell-flag
+ 0
+ (kproperty:get (kcell-view:plist-point pos) attribute))
+ (if top-cell-flag
(kcell:get-attr (kview:top-cell kview) attribute)
- (kcell-view:get-attr attribute pos))))
+ (kcell-view:get-attr attribute pos)))))
(when (called-interactively-p 'interactive)
(message "Attribute \"%s\" = `%s' in cell <%s>."
attribute value (if top-cell-flag
@@ -3204,7 +3207,9 @@ upon the current view."
(progn (kview:end-of-actual-line)
(point)))))
(terpri)
- (hattr:report (kcell:plist (kcell-view:cell)))
+ (hattr:report
+ (append (list 'idstamp (kcell-view:idstamp-integer))
+ (kcell:plist (kcell-view:cell))))
(terpri))
(put 'outline 'reveal-toggle-invisible 'kotl-mode:reveal-toggle-invisible)
diff --git a/kotl/kproperty.el b/kotl/kproperty.el
index 3c0e395898..272b5b9135 100644
--- a/kotl/kproperty.el
+++ b/kotl/kproperty.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 7/27/93
-;; Last-Mod: 12-Feb-22 at 10:42:20 by Mats Lidell
+;; Last-Mod: 3-Apr-22 at 18:33:09 by Bob Weiner
;;
;; Copyright (C) 1993-2021 Free Software Foundation, Inc.
;; See the "../HY-COPY" file for license information.
@@ -31,6 +31,11 @@
(kproperty:put (point) (min (+ 2 (point)) (point-max))
plist))
+(defun kproperty:remove-properties (plist)
+ "Remove properties at point and the following character from PLIST."
+ (kproperty:remove (point) (min (+ 2 (point)) (point-max))
+ plist))
+
(defun kproperty:all-positions (property value)
"Return a list of all non-narrowed buffer positions of kcells with PROPERTY
set to VALUE, else nil.
Use (kcell-view:start <position>) on each returned <position> to get
@@ -80,7 +85,7 @@ properties."
The optional fourth argument, OBJECT, is the string or buffer containing the
text. PROPERTY-LIST should be a plist; if the value of a property is
non-nil, then only a property with a matching value will be removed.
-Returns t if any property was changed, nil otherwise."
+Return t if any property was changed, nil otherwise."
(let ((changed) plist property value next)
(while property-list
(setq property (car property-list)
diff --git a/kotl/kview.el b/kotl/kview.el
index b14d656502..8b665acea5 100644
--- a/kotl/kview.el
+++ b/kotl/kview.el
@@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 6/30/93
-;; Last-Mod: 13-Feb-22 at 19:50:05 by Mats Lidell
+;; Last-Mod: 3-Apr-22 at 19:00:16 by Bob Weiner
;;
;; Copyright (C) 1993-2021 Free Software Foundation, Inc.
;; See the "../HY-COPY" file for license information.
@@ -113,7 +113,7 @@ Return t unless no such cell."
(defun kcell-view:cell (&optional pos)
"Return kcell at optional POS or point."
- (kproperty:properties (kcell-view:plist-point pos)))
+ (kproperty:get (kcell-view:plist-point pos) 'kcell))
(defun kcell-view:cell-from-ref (cell-ref)
"Return a kcell referenced by CELL-REF, a cell label, id string or integer
idstamp.
@@ -217,11 +217,14 @@ Any cell that is invisible is also collapsed as indicated
by a call to
(concat "\\([\n\r]\\)" (make-string indent ?\ ))
(buffer-substring start end) "\\1"))))
-(defun kcell-view:create (kview cell contents level klabel &optional no-fill)
- "Insert into KVIEW at point, CELL with CONTENTS at LEVEL (1 = first level)
with KLABEL.
+(defun kcell-view:create (kview cell contents level idstamp klabel &optional
no-fill)
+ "Insert into KVIEW at point, CELL with CONTENTS at LEVEL (1 = first level)
with IDSTAMP and KLABEL.
+If the current view displays klabels, then KLABEL should be inserted
+prior to this call, with point following it.
+
Optional NO-FILL non-nil suppresses filling of cell's contents upon insertion
or movement."
- (unless (zerop (kcell:idstamp cell))
+ (unless (zerop idstamp)
(unless no-fill
(setq no-fill (kcell:get-attr cell 'no-fill)))
(let* ((label-min-width (kview:label-min-width kview))
@@ -264,7 +267,8 @@ or movement."
(insert label-separator)
(goto-char old-point)
;; Add cell's attributes to the text property list at point.
- (kproperty:add-properties cell)
+ (kproperty:set 'idstamp idstamp)
+ (kproperty:set 'kcell cell)
(goto-char new-point))))
(defun kcell-view:end (&optional pos)
@@ -321,18 +325,29 @@ Return t unless no such cell."
found))
(defun kcell-view:get-attr (attribute &optional pos)
- "Return ATTRIBUTE's value for current cell or cell at optional POS."
+ "Return ATTRIBUTE's value for current cell or cell at optional POS
+Use 0 for POS to retrieve top cell's attributes."
+ (if (eq pos 0)
+ (if (eq attribute 'idstamp)
+ 0
+ (kcell:get-attr (kview:top-cell kview) attribute))
+ (save-excursion
+ (goto-char (or pos (kcell-view:plist-point)))
+ (if (eq attribute 'idstamp)
+ (kproperty:get (point) attribute)
+ (kcell:get-attr (kcell-view:cell) attribute)))))
+
+(defun kcell-view:idstamp-integer (&optional pos)
+ "Return idstamp integer >= 0 of cell at optional POS or point."
(save-excursion
- (when pos
- (goto-char pos))
- (kcell:get-attr (kcell-view:cell) attribute)))
+ (goto-char (or pos (kcell-view:plist-point)))
+ (kproperty:get (point) 'idstamp)))
(defun kcell-view:idstamp (&optional pos)
"Return idstamp string of cell at optional POS or point."
(save-excursion
- (when pos
- (goto-char pos))
- (format "0%s" (or (kcell:idstamp (kcell-view:cell)) ""))))
+ (goto-char (or pos (kcell-view:plist-point)))
+ (format "0%s" (or (kproperty:get (point) 'idstamp) ""))))
(defun kcell-view:indent (&optional pos label-sep-len)
"Return indentation of cell at optional POS or point.
@@ -485,31 +500,40 @@ or is nil), before it is returned."
(kcell-view:label pos) (kcell-view:idstamp pos)))
(defun kcell-view:remove-attr (attribute &optional pos)
- "Remove ATTRIBUTE, if any, for current cell or cell at optional POS."
+ "Remove ATTRIBUTE, if any, for current cell or cell at optional POS. Return
the modified cell."
(interactive "*SAttribute to remove: ")
- (save-excursion
- (when pos
- (goto-char pos))
-
- (let ((kcell (kcell:remove-attr (kcell-view:cell) attribute)))
- (when (called-interactively-p 'interactive)
- (message "Cell <%s> now has no %s attribute."
- (kcell-view:label) attribute))
+ (unless (eq attribute 'idstamp) ;; Can't remove idstamp
+ (let (mod-cell)
+ (save-excursion
+ (goto-char (or pos (kcell-view:plist-point)))
+ (setq mod-cell (kcell:remove-attr (kcell-view:cell) attribute))
+ (kproperty:add-properties (list 'kcell mod-cell))
+ (when (called-interactively-p 'interactive)
+ (message "Cell <%s> now has no %s attribute."
+ (kcell-view:label) attribute)))
kcell)))
(defun kcell-view:set-attr (attribute value &optional pos)
- "Set ATTRIBUTE's VALUE for current cell or cell at optional POS and return
the cell."
- (save-excursion
- (when pos
- (goto-char pos))
- ;; Returns kcell.
- (kcell:set-attr (kcell-view:cell) attribute value)))
-
-(defun kcell-view:set-cell (kcell)
- "Attach KCELL property to cell at point."
+ "Set ATTRIBUTE's VALUE for current cell or cell at optional POS and return
the modified cell.
+Use 0 for POS to set top cell's attributes."
+ (unless (and (eq pos 0) (eq attribute 'idstamp)) ;; top cell idstamp set
when Koutline is created
+ (save-excursion
+ (goto-char (or pos (kcell-view:plist-point)))
+ (if (eq attribute 'idstamp)
+ (progn (kproperty:set attribute value)
+ (kcell-view:cell))
+ ;; Returns kcell
+ (let ((mod-cell (kcell:set-attr (if (eq pos 0) (kview:top-cell kview)
(kcell-view:cell))
+ attribute value)))
+ (kproperty:add-properties (list 'kcell mod-cell))
+ mod-cell)))))
+
+(defun kcell-view:set-cell (kcell idstamp)
+ "Attach KCELL and IDSTAMP (an integer) properties to cell at point."
(save-excursion
(kcell-view:to-label-end)
- (kproperty:add-properties kcell)))
+ (kproperty:add-properties
+ (list 'idstamp idstamp 'kcell kcell))))
(defun kcell-view:sibling-p (&optional pos visible-p label-sep-len)
"Return t if cell at optional POS or point has a successor.
@@ -561,8 +585,8 @@ level."
(let* ((idstamp (if (klabel:idstamp-p klabel)
(if (stringp klabel) (string-to-number klabel) klabel)
(kview:id-increment kview)))
- (new-cell (kcell:create idstamp prop-list)))
- (kcell-view:create kview new-cell contents level klabel no-fill)
+ (new-cell (kcell:create prop-list)))
+ (kcell-view:create kview new-cell contents level idstamp klabel no-fill)
new-cell))
(defun kview:beginning-of-actual-line ()
@@ -620,11 +644,8 @@ BLANK-LINES, LEVELS-TO-SHOW, and LINES-TO-SHOW may also be
given, otherwise defa
;; Don't recreate view if it exists.
(unless (and (boundp 'kview) (kview:is-p kview) (eq (kview:buffer kview)
buf))
(make-local-variable 'kview)
- ;; File location may have changed since saved, so always inject the
- ;; current file name here and update cell count id-counter.
- (setq top-cell-attributes
- (plist-put (plist-put top-cell-attributes 'id-counter id-counter)
- 'file buffer-file-name))
+ ;; Update cell count id-counter.
+ (setq top-cell-attributes (plist-put top-cell-attributes 'id-counter
id-counter))
(setq kview
(list 'kview 'plist
(list 'view-buffer (current-buffer)
diff --git a/test/kotl-mode-tests.el b/test/kotl-mode-tests.el
index bc234fd201..8bb18bc515 100644
--- a/test/kotl-mode-tests.el
+++ b/test/kotl-mode-tests.el
@@ -28,8 +28,8 @@
(progn
,@body
(should (equal major-mode 'kotl-mode))
- (should (string= (buffer-name (current-buffer)) "EXAMPLE.kotl")))
- (kill-buffer "EXAMPLE.kotl")))
+ (should (string-prefix-p "EXAMPLE.kotl" (buffer-name
(current-buffer)))))
+ (kill-buffer (current-buffer))))
(ert-deftest smart-menu-loads-kotl-example ()
"Loading kotl-mode example file works."
@@ -43,7 +43,7 @@
(ert-deftest kotl-mode-example-loads-kotl-example ()
"Loading kotl-mode example file works."
(setup-kotl-mode-example-test
- (kotl-mode:example)))
+ (kotl-mode:example nil t)))
(ert-deftest kotl-mode-move-between-cells ()
"Loading kotl-mode example file works."
@@ -462,21 +462,21 @@
(ert-deftest kotl-mode-copy-kotl-file-updates-root-id-attributes ()
"Verify root id-attribute is updated when kotl mode is copied."
- (let ((kotl-file (make-temp-file "hypb" nil ".kotl"))
- (new-name (concat (make-temp-name (concat temporary-file-directory
"hypb")) ".kotl")))
+ (let* ((kotl-file (make-temp-file "hypb" nil ".kotl"))
+ (indent (kcell:get-attr (kcell-view:cell-from-ref 0) 'level-indent))
+ (new-name (concat (make-temp-name (concat temporary-file-directory
"hypb")) ".kotl")))
(unwind-protect
(progn
(find-file kotl-file)
(insert "a cell")
(save-buffer)
- (should (string= (kcell:get-attr (kcell-view:cell-from-ref 0) 'file)
kotl-file))
+ (should (string= (kcell:get-attr (kcell-view:cell-from-ref 0)
'level-indent) indent))
(copy-file kotl-file new-name)
(find-file new-name)
- (should (string= (kcell:get-attr (kcell-view:cell-from-ref 0) 'file)
new-name)))
- (progn
- (delete-file kotl-file)
- (delete-file new-name)))))
+ (should (string= (kcell:get-attr (kcell-view:cell-from-ref 0)
'level-indent) indent)))
+ (delete-file kotl-file)
+ (delete-file new-name))))
(ert-deftest kotl-mode-hide-cell ()
"Verify cell is hidden and unhidden on `action-key' press."