summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArto Jantunen <viiru@debian.org>2024-01-28 09:02:41 +0200
committerArto Jantunen <viiru@debian.org>2024-01-28 09:02:41 +0200
commit16910cc25e38d584a0bb627ed4a9e35b6bdfd856 (patch)
treef35a730ed558f3932fa49b2e376d3ef50ac7518d
parent984bea0406fc97c28ce2875763578514c83662f8 (diff)
parent9d79793edaa98a8a06674723ad5a53ebc4fc237c (diff)
Merge tag 'taxy-magit-section-0.13'
Release: v0.13
-rw-r--r--README.org11
-rw-r--r--taxy-magit-section.el283
-rw-r--r--taxy-magit-section.info121
3 files changed, 227 insertions, 188 deletions
diff --git a/README.org b/README.org
index 1b15f4b..c001ffd 100644
--- a/README.org
+++ b/README.org
@@ -36,6 +36,17 @@ This library renders [[https://github.com/alphapapa/taxy.el][Taxy]] structs with
:TOC: :depth 0
:END:
+** 0.13
+
+*Additions*
+
++ Function ~taxy-magit-section-insert~ takes a ~:section-class~ argument, which is passed to ~magit-insert-section~ as its ~class~ argument. This allows a custom subclass of ~magit-section~ to be passed, which, with a custom method on ~magit-section-ident-value~, allows section visibility to be cached concisely.
+
+** 0.12.2
+
+*Fixes*
++ Header alignment.
+
** 0.12.1
*Fixes*
diff --git a/taxy-magit-section.el b/taxy-magit-section.el
index 45e9d48..d1d7588 100644
--- a/taxy-magit-section.el
+++ b/taxy-magit-section.el
@@ -5,7 +5,7 @@
;; Author: Adam Porter <adam@alphapapa.net>
;; Maintainer: Adam Porter <adam@alphapapa.net>
;; URL: https://github.com/alphapapa/taxy.el
-;; Version: 0.12.1
+;; Version: 0.13
;; Package-Requires: ((emacs "26.3") (magit-section "3.2.1") (taxy "0.10"))
;; Keywords: lisp
@@ -96,8 +96,20 @@ this does not disable indentation of section headings.")
;; hierarchical path, but since the taxys aren't doubly linked, that isn't easily done.
;; Could probably be worked around by binding a special variable around the creation of
;; the taxy hierarchy that would allow the path to be saved into each taxy.
- (when-let ((taxy (oref section value)))
- (taxy-name taxy)))
+
+ ;; NOTE: This method seems to slightly conflate a couple of things: the section class
+ ;; and the value of the section instance. In the case of `taxy-magit-section', the
+ ;; non-leaf nodes will have a `taxy' as their value, but the leaves will be whatever
+ ;; type of object the `taxy' contains, and we can't account for that in the method
+ ;; specializer (or could we define our own specializer? I guess we could, but the
+ ;; implications of that aren't obvious). It's not clear that calling the next method
+ ;; (i.e. probably falling back on just the `magit-section' class) would produce a useful
+ ;; or "correct" value for visibility caching purposes, but at least it works, so it will
+ ;; do for now.
+ (let ((value (oref section value)))
+ (cl-typecase value
+ (taxy (taxy-name value))
+ (otherwise (cl-call-next-method)))))
;;;; Commands
@@ -105,82 +117,85 @@ this does not disable indentation of section headings.")
;;;; Functions
(cl-defun taxy-magit-section-insert
- (taxy &key (items 'first) (initial-depth 0) (blank-between-depth 1))
+ (taxy &key (items 'first) (initial-depth 0) (blank-between-depth 1)
+ (section-class 'taxy-magit-section-section))
"Insert a `magit-section' for TAXY into current buffer.
If ITEMS is `first', insert a taxy's items before its descendant
taxys; if `last', insert them after descendants. INITIAL-DEPTH
is the initial indentation depth; it may be, e.g. -1 to make the
second level unindented. BLANK-BETWEEN-DEPTH is the level up to
-which blank lines are inserted between sections at that level."
+which blank lines are inserted between sections at that level.
+SECTION-CLASS is passed to `magit-insert-section', which
+see (this may be set to a custom subclass of `magit-section' in
+order to define a custom `magit-section-ident-value' method so
+that section visibility may be cached concisely)."
(declare (indent defun))
(let* ((magit-section-set-visibility-hook
(cons #'taxy-magit-section-visibility magit-section-set-visibility-hook)))
- (cl-labels ((insert-item
- (item taxy depth)
- (magit-insert-section (magit-section item)
- (magit-insert-section-body
- ;; This is a tedious way to give the indent
- ;; string the same text properties as the start
- ;; of the formatted string, but no matter where I
- ;; left point after using `insert-and-inherit',
- ;; something was wrong about the properties, and
- ;; `magit-section' didn't navigate the sections
- ;; properly anymore.
- (let* ((formatted (funcall (taxy-magit-section-format-fn taxy) item))
- (indent-size (if (or (not taxy-magit-section-insert-indent-items)
- (< depth 0))
- 0
- (+ (* depth (taxy-magit-section-level-indent taxy))
- (taxy-magit-section-item-indent taxy))))
- (indent-string (make-string indent-size ? )))
- (add-text-properties 0 (length indent-string)
- (text-properties-at 0 formatted)
- indent-string)
- (insert indent-string formatted "\n")))))
- (insert-taxy
- (taxy depth)
- (let ((magit-section-set-visibility-hook magit-section-set-visibility-hook)
- (taxy-magit-section-level-indent (taxy-magit-section-level-indent taxy))
- (taxy-magit-section-item-indent (taxy-magit-section-item-indent taxy))
- (taxy-name (copy-sequence (taxy-name taxy))))
- (add-face-text-property
- 0 (length taxy-name)
- (funcall (taxy-magit-section-heading-face-fn taxy) depth)
- t taxy-name)
- (cl-typecase taxy
- (taxy-magit-section
- (when (taxy-magit-section-visibility-fn taxy)
- (push (taxy-magit-section-visibility-fn taxy)
- magit-section-set-visibility-hook))))
- ;; HACK: We set the section's washer to nil to prevent
- ;; `magit-section--maybe-wash' from trying to wash the section when its
- ;; visibility is toggled back on. I'm not sure why this is necessary
- ;; (maybe an issue in magit-section?).
- (oset (magit-insert-section (taxy-magit-section-section taxy)
- (magit-insert-heading
- (make-string (* (if (< depth 0) 0 depth)
- (taxy-magit-section-level-indent taxy))
- ? )
- taxy-name
- (format " (%s%s)"
- (if (taxy-description taxy)
- (concat (taxy-description taxy) " ")
- "")
- (taxy-size taxy)))
- (magit-insert-section-body
- (when (eq 'first items)
- (dolist (item (taxy-items taxy))
- (insert-item item taxy depth)))
- (dolist (taxy (taxy-taxys taxy))
- (insert-taxy taxy (1+ depth)))
- (when (eq 'last items)
- (dolist (item (taxy-items taxy))
- (insert-item item taxy depth))))
- (when (<= depth blank-between-depth)
- (insert "\n")))
- washer nil))))
+ (cl-labels ((insert-item (item taxy depth)
+ (magit-insert-section ((eval section-class) item)
+ (magit-insert-section-body
+ ;; This is a tedious way to give the indent
+ ;; string the same text properties as the start
+ ;; of the formatted string, but no matter where I
+ ;; left point after using `insert-and-inherit',
+ ;; something was wrong about the properties, and
+ ;; `magit-section' didn't navigate the sections
+ ;; properly anymore.
+ (let* ((formatted (funcall (taxy-magit-section-format-fn taxy) item))
+ (indent-size (if (or (not taxy-magit-section-insert-indent-items)
+ (< depth 0))
+ 0
+ (+ (* depth (taxy-magit-section-level-indent taxy))
+ (taxy-magit-section-item-indent taxy))))
+ (indent-string (make-string indent-size ? )))
+ (add-text-properties 0 (length indent-string)
+ (text-properties-at 0 formatted)
+ indent-string)
+ (insert indent-string formatted "\n")))))
+ (insert-taxy (taxy depth)
+ (let ((magit-section-set-visibility-hook magit-section-set-visibility-hook)
+ (taxy-magit-section-level-indent (taxy-magit-section-level-indent taxy))
+ (taxy-magit-section-item-indent (taxy-magit-section-item-indent taxy))
+ (taxy-name (copy-sequence (taxy-name taxy))))
+ (add-face-text-property
+ 0 (length taxy-name)
+ (funcall (taxy-magit-section-heading-face-fn taxy) depth)
+ t taxy-name)
+ (cl-typecase taxy
+ (taxy-magit-section
+ (when (taxy-magit-section-visibility-fn taxy)
+ (push (taxy-magit-section-visibility-fn taxy)
+ magit-section-set-visibility-hook))))
+ ;; HACK: We set the section's washer to nil to prevent
+ ;; `magit-section--maybe-wash' from trying to wash the section when its
+ ;; visibility is toggled back on. I'm not sure why this is necessary
+ ;; (maybe an issue in magit-section?).
+ (oset (magit-insert-section ((eval section-class) taxy)
+ (magit-insert-heading
+ (make-string (* (if (< depth 0) 0 depth)
+ (taxy-magit-section-level-indent taxy))
+ ? )
+ taxy-name
+ (format " (%s%s)"
+ (if (taxy-description taxy)
+ (concat (taxy-description taxy) " ")
+ "")
+ (taxy-size taxy)))
+ (magit-insert-section-body
+ (when (eq 'first items)
+ (dolist (item (taxy-items taxy))
+ (insert-item item taxy depth)))
+ (dolist (taxy (taxy-taxys taxy))
+ (insert-taxy taxy (1+ depth)))
+ (when (eq 'last items)
+ (dolist (item (taxy-items taxy))
+ (insert-item item taxy depth))))
+ (when (<= depth blank-between-depth)
+ (insert "\n")))
+ washer nil))))
;; HACK: See earlier note about washer.
- (oset (magit-insert-section (taxy-magit-section-section)
+ (oset (magit-insert-section ((eval section-class))
(insert-taxy taxy initial-depth))
washer nil))))
@@ -359,70 +374,69 @@ according to `columns' and takes into account the width of all
the items' values for each column."
(let ((table (make-hash-table))
column-aligns column-sizes image-p)
- (cl-labels ((string-width*
- (string) (if-let (pos (text-property-not-all 0 (length string)
- 'display nil string))
- ;; Text has a display property: check for an image.
- (pcase (get-text-property pos 'display string)
- ((and `(image . ,_rest) spec)
- ;; An image: try to calcuate the display width. (See also:
- ;; `org-string-width'.)
-
- ;; FIXME: The entire string may not be an image, so the
- ;; image part needs to be handled separately from any
- ;; non-image part.
-
- ;; TODO: Do we need to specify the frame? What if the
- ;; buffer isn't currently displayed?
- (setf image-p t)
- (floor (car (image-size spec))))
- (_
- ;; No image: just use `string-width'.
- (setf image-p nil)
- (string-width string)))
- ;; No display property.
- (setf image-p nil)
- (string-width string)))
- (resize-image-string
- (string width) (let ((image
- (get-text-property
- (text-property-not-all 0 (length string)
- 'display nil string)
- 'display string)))
- (propertize (make-string width ? ) 'display image)))
-
- (format-column
- (item depth column-name)
- (let* ((column-alist (alist-get column-name formatters nil nil #'equal))
- (fn (alist-get 'formatter column-alist))
- (value (funcall fn item depth))
- (current-column-size (or (map-elt column-sizes column-name) (string-width column-name))))
- (setf (map-elt column-sizes column-name)
- (max current-column-size (string-width* value)))
- (setf (map-elt column-aligns column-name)
- (or (alist-get 'align column-alist)
- 'left))
- (when image-p
- ;; String probably is an image: set its non-image string value to a
- ;; number of matching spaces. It's not always pixel-perfect, but
- ;; this is probably as good as we can do without using pixel-based
- ;; :align-to's for everything (which might be worth doing in the
- ;; future).
-
- ;; FIXME: This only works properly if the entire string has an image
- ;; display property (but this is good enough for now).
- (setf value (resize-image-string value (string-width* value))))
- value))
- (format-item
- (depth item) (puthash item
- (cl-loop for column in columns
- collect (format-column item depth column))
- table))
+ (cl-labels ((string-width* (string)
+ (if-let (pos (text-property-not-all 0 (length string)
+ 'display nil string))
+ ;; Text has a display property: check for an image.
+ (pcase (get-text-property pos 'display string)
+ ((and `(image . ,_rest) spec)
+ ;; An image: try to calcuate the display width. (See also:
+ ;; `org-string-width'.)
+
+ ;; FIXME: The entire string may not be an image, so the
+ ;; image part needs to be handled separately from any
+ ;; non-image part.
+
+ ;; TODO: Do we need to specify the frame? What if the
+ ;; buffer isn't currently displayed?
+ (setf image-p t)
+ (floor (car (image-size spec))))
+ (_
+ ;; No image: just use `string-width'.
+ (setf image-p nil)
+ (string-width string)))
+ ;; No display property.
+ (setf image-p nil)
+ (string-width string)))
+ (resize-image-string (string width)
+ (let ((image
+ (get-text-property
+ (text-property-not-all 0 (length string)
+ 'display nil string)
+ 'display string)))
+ (propertize (make-string width ? ) 'display image)))
+
+ (format-column (item depth column-name)
+ (let* ((column-alist (alist-get column-name formatters nil nil #'equal))
+ (fn (alist-get 'formatter column-alist))
+ (value (funcall fn item depth))
+ (current-column-size (or (map-elt column-sizes column-name) (string-width column-name))))
+ (setf (map-elt column-sizes column-name)
+ (max current-column-size (string-width* value)))
+ (setf (map-elt column-aligns column-name)
+ (or (alist-get 'align column-alist)
+ 'left))
+ (when image-p
+ ;; String probably is an image: set its non-image string value to a
+ ;; number of matching spaces. It's not always pixel-perfect, but
+ ;; this is probably as good as we can do without using pixel-based
+ ;; :align-to's for everything (which might be worth doing in the
+ ;; future).
+
+ ;; FIXME: This only works properly if the entire string has an image
+ ;; display property (but this is good enough for now).
+ (setf value (resize-image-string value (string-width* value))))
+ value))
+ (format-item (depth item)
+ (puthash item
+ (cl-loop for column in columns
+ collect (format-column item depth column))
+ table))
(format-taxy (depth taxy)
- (dolist (item (taxy-items taxy))
- (format-item depth item))
- (dolist (taxy (taxy-taxys taxy))
- (format-taxy (1+ depth) taxy))))
+ (dolist (item (taxy-items taxy))
+ (format-item depth item))
+ (dolist (taxy (taxy-taxys taxy))
+ (format-taxy (1+ depth) taxy))))
(format-taxy 0 taxy)
;; Now format each item's string using the column sizes.
(let* ((column-sizes (nreverse column-sizes))
@@ -452,7 +466,8 @@ variable passed to that function, which see."
((or `nil 'left) "-")
('right ""))))
(concat (format (format " %%%s%ss"
- first-column-align (cdar column-sizes))
+ ;; FIXME: Why is this 1+ necessary for proper alignment?
+ first-column-align (1+ (cdar column-sizes)))
(caar column-sizes))
(cl-loop for (name . size) in (cdr column-sizes)
for column-alist = (alist-get name formatters nil nil #'equal)
diff --git a/taxy-magit-section.info b/taxy-magit-section.info
index be59bef..d41dd27 100644
--- a/taxy-magit-section.info
+++ b/taxy-magit-section.info
@@ -1,4 +1,4 @@
-This is README.info, produced by makeinfo version 5.2 from README.texi.
+This is README.info, produced by makeinfo version 6.7 from README.texi.
INFO-DIR-SECTION Emacs
START-INFO-DIR-ENTRY
@@ -6,7 +6,7 @@ START-INFO-DIR-ENTRY
END-INFO-DIR-ENTRY

-File: README.info, Node: Top, Next: COMMENT Examples, Up: (dir)
+File: README.info, Node: Top, Next: Installation, Up: (dir)
taxy-magit-section.el
*********************
@@ -19,9 +19,7 @@ structs with magit-section (https://melpa.org/#/magit-section).
* Menu:
-* COMMENT Examples::
* Installation::
-* COMMENT Usage::
* Changelog::
* Development::
* Credits::
@@ -31,24 +29,20 @@ structs with magit-section (https://melpa.org/#/magit-section).
Changelog
-* 0.12.1: 0121.
-* 0.12: 012.
-* 0.11: 011.
-* 0.10: 010.
-* 0.9.1: 091.
-* 0.9: 09.
+* 0.13: 013.
+* 0.12.2: 0122.
+* 0.12.1: 0121.
+* 0.12: 012.
+* 0.11: 011.
+* 0.10: 010.
+* 0.9.1: 091.
+* 0.9: 09.

-File: README.info, Node: COMMENT Examples, Next: Installation, Prev: Top, Up: Top
+File: README.info, Node: Installation, Next: Changelog, Prev: Top, Up: Top
-1 COMMENT Examples
-******************
-
-
-File: README.info, Node: Installation, Next: COMMENT Usage, Prev: COMMENT Examples, Up: Top
-
-2 Installation
+1 Installation
**************
‘taxy-magit-section’ is distributed in GNU ELPA (https://elpa.gnu.org/),
@@ -57,30 +51,49 @@ taxy-magit-section RET’, then ‘(require 'taxy-magit-section)’ in your
Elisp project.

-File: README.info, Node: COMMENT Usage, Next: Changelog, Prev: Installation, Up: Top
+File: README.info, Node: Changelog, Next: Development, Prev: Installation, Up: Top
-3 COMMENT Usage
-***************
+2 Changelog
+***********
+
+* Menu:
+
+* 0.13: 013.
+* 0.12.2: 0122.
+* 0.12.1: 0121.
+* 0.12: 012.
+* 0.11: 011.
+* 0.10: 010.
+* 0.9.1: 091.
+* 0.9: 09.

-File: README.info, Node: Changelog, Next: Development, Prev: COMMENT Usage, Up: Top
+File: README.info, Node: 013, Next: 0122, Up: Changelog
-4 Changelog
-***********
+2.1 0.13
+========
-* Menu:
+*Additions*
+
+ • Function ‘taxy-magit-section-insert’ takes a ‘:section-class’
+ argument, which is passed to ‘magit-insert-section’ as its ‘class’
+ argument. This allows a custom subclass of ‘magit-section’ to be
+ passed, which, with a custom method on ‘magit-section-ident-value’,
+ allows section visibility to be cached concisely.
+
+
+File: README.info, Node: 0122, Next: 0121, Prev: 013, Up: Changelog
+
+2.2 0.12.2
+==========
-* 0.12.1: 0121.
-* 0.12: 012.
-* 0.11: 011.
-* 0.10: 010.
-* 0.9.1: 091.
-* 0.9: 09.
+*Fixes*
+ • Header alignment.

-File: README.info, Node: 0121, Next: 012, Up: Changelog
+File: README.info, Node: 0121, Next: 012, Prev: 0122, Up: Changelog
-4.1 0.12.1
+2.3 0.12.1
==========
*Fixes*
@@ -89,7 +102,7 @@ File: README.info, Node: 0121, Next: 012, Up: Changelog

File: README.info, Node: 012, Next: 011, Prev: 0121, Up: Changelog
-4.2 0.12
+2.4 0.12
========
*Fixes*
@@ -98,7 +111,7 @@ File: README.info, Node: 012, Next: 011, Prev: 0121, Up: Changelog

File: README.info, Node: 011, Next: 010, Prev: 012, Up: Changelog
-4.3 0.11
+2.5 0.11
========
*Additions*
@@ -108,7 +121,7 @@ File: README.info, Node: 011, Next: 010, Prev: 012, Up: Changelog

File: README.info, Node: 010, Next: 091, Prev: 011, Up: Changelog
-4.4 0.10
+2.6 0.10
========
*Fixes*
@@ -117,7 +130,7 @@ File: README.info, Node: 010, Next: 091, Prev: 011, Up: Changelog

File: README.info, Node: 091, Next: 09, Prev: 010, Up: Changelog
-4.5 0.9.1
+2.7 0.9.1
=========
*Fixes*
@@ -130,7 +143,7 @@ File: README.info, Node: 091, Next: 09, Prev: 010, Up: Changelog

File: README.info, Node: 09, Prev: 091, Up: Changelog
-4.6 0.9
+2.8 0.9
=======
• ‘taxy-magit-section’ moved to separate package.
@@ -139,7 +152,7 @@ File: README.info, Node: 09, Prev: 091, Up: Changelog

File: README.info, Node: Development, Next: Credits, Prev: Changelog, Up: Top
-5 Development
+3 Development
*************
‘taxy-magit-section’ is developed in a branch of the main Taxy repo
@@ -148,7 +161,7 @@ File: README.info, Node: Development, Next: Credits, Prev: Changelog, Up: To

File: README.info, Node: Credits, Next: License, Prev: Development, Up: Top
-6 Credits
+4 Credits
*********
• Thanks to Stefan Monnier for his feedback, and for maintaining GNU
@@ -157,7 +170,7 @@ File: README.info, Node: Credits, Next: License, Prev: Development, Up: Top

File: README.info, Node: License, Prev: Credits, Up: Top
-7 License
+5 License
*********
GPLv3
@@ -166,19 +179,19 @@ GPLv3

Tag Table:
Node: Top221
-Node: COMMENT Examples833
-Node: Installation961
-Node: COMMENT Usage1332
-Node: Changelog1457
-Node: 01211669
-Node: 0121789
-Node: 0111926
-Node: 0102127
-Node: 0912282
-Node: 092674
-Node: Development2864
-Node: Credits3091
-Node: License3281
+Node: Installation813
+Node: Changelog1167
+Node: 0131401
+Node: 01221860
+Node: 01211992
+Node: 0122125
+Node: 0112262
+Node: 0102463
+Node: 0912618
+Node: 093010
+Node: Development3200
+Node: Credits3427
+Node: License3617

End Tag Table