branch: elpa/org-superstar commit f1e26c29bfe9c5612f363125e6cebd2a4e828455 Author: D. Williams <d.willi...@posteo.net> Commit: D. Williams <d.willi...@posteo.net>
Permit cycling through the last N bullets rather than the first. See Issue #59. --- README.org | 3 ++- org-superstar.el | 47 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/README.org b/README.org index 9db2cf41fef..c74ed201005 100644 --- a/README.org +++ b/README.org @@ -146,7 +146,8 @@ used, allowing the user to inherit the level-dependent default look. * ~nil~ :: Go through the list, then repeat the last entry indefinitely. - * any integer /k/ :: Cycle through the first /k/ elements of the list. + * any positive integer /k/ :: Cycle through the first /k/ elements of the list. + * any negative integer /k/ :: Cycle through the last -/k/ elements of the list. *** ~org-superstar-leading-bullet~ Maybe you actually /like/ that Org's heading lines are connected to diff --git a/org-superstar.el b/org-superstar.el index b59f604ed87..4d1cdeab587 100644 --- a/org-superstar.el +++ b/org-superstar.el @@ -339,8 +339,9 @@ variable for your changes to take effect." The following values are meaningful: -An integer value of N cycles through the first N entries of the -list instead of the whole list. +An integer value of N cycles through the first N entries of the list +instead of the whole list. If N is negative, cycle through the last -N +entries instead. If otherwise non-nil, cycle through the entirety of the list. This is the default behavior inherited from org-bullets. @@ -357,22 +358,34 @@ variable for your changes to take effect." :format "Repeat the first %v entries exclusively.\n" :size 8 :value 1 - :validate org-superstar--validate-hcycle))) + :match (lambda (_ x) (and (integerp x) (> x 0))) + :validate org-superstar--validate-hcycle) + (integer :tag "Repeat the last -<integer> elements only." + :format "Repeat the last -(%v) entries exclusively.\n" + :size 8 + :value -1 + :match (lambda (_ x) (and (integerp x) (< x 0))) + :validate (lambda (x) (org-superstar--validate-hcycle x t))))) -(defun org-superstar--validate-hcycle (text-field) +(defun org-superstar--validate-hcycle (text-field &optional negative) "Raise an error if TEXT-FIELD’s value is an invalid hbullet number. + +If the optional argument NEGATIVE is given, flip the sign of the value +read from TEXT-FIELD. + This function is used for ‘org-superstar-cycle-headline-bullets’. If the integer exceeds the length of ‘org-superstar-headline-bullets-list’, set it to the length and raise an error." - (let ((ncycle (widget-value text-field)) - (maxcycle (org-superstar--hbullets-length))) + (let* ((sign (if negative -1 1)) + (ncycle (* sign (widget-value text-field))) + (maxcycle (org-superstar--hbullets-length))) (unless (<= 1 ncycle maxcycle) (widget-put text-field - :error (format "Value must be between 1 and %i" - maxcycle)) - (widget-value-set text-field maxcycle) + :error (format "Value must be between %i and %i" + sign (* sign maxcycle))) + (widget-value-set text-field (* sign maxcycle)) text-field))) (defcustom org-superstar-prettify-item-bullets t @@ -595,16 +608,24 @@ See also ‘org-superstar-cycle-headline-bullets’." ;; However, allowing for fallback means the list may contain ;; strings, chars or conses. The cons must be resolved. ;; Hence, a new funtion is needed to keep the complexity to a minimum. - (let ((max-bullets org-superstar-cycle-headline-bullets) + (let ((ncycle org-superstar-cycle-headline-bullets) (n (if org-odd-levels-only (/ (1- level) 2) (1- level))) (todo-bullet (when org-superstar-special-todo-items (org-superstar--todo-bullet)))) (cond (todo-bullet (unless (eq todo-bullet 'hide) todo-bullet)) - ((integerp max-bullets) - (org-superstar--nth-headline-bullet (% n max-bullets))) - (max-bullets + ((and (integerp ncycle) (> ncycle 0)) + (org-superstar--nth-headline-bullet (% n ncycle))) + ((and (integerp ncycle) (< ncycle 0)) + ;; Remember, ncycle is negative. + (let* ((loop-start (+ (org-superstar--hbullets-length) ncycle)) + (k (- n loop-start))) + (org-superstar--nth-headline-bullet + (if (< n loop-start) + n + (+ loop-start (% k (- ncycle))))))) + (ncycle (org-superstar--nth-headline-bullet (% n (org-superstar--hbullets-length)))) (t