diff --git a/emacs/.emacs.d/wpc/cycle.el b/emacs/.emacs.d/wpc/cycle.el index f876cf705..9ec6ecd2f 100644 --- a/emacs/.emacs.d/wpc/cycle.el +++ b/emacs/.emacs.d/wpc/cycle.el @@ -150,6 +150,46 @@ ITEM is the first item in XS that t for `equal'." "Return t if cycle XS has a non-nil value for current-index." (maybe/some? (cycle-current-index xs))) +(defun cycle/append (x xs) + "Add X to the left of the focused element in XS. +If there is no currently focused item, add X to the beginning of XS." + (if (cycle/empty? xs) + (progn + (struct/set! cycle xs (list x) xs) + (struct/set! cycle current-index 0 xs) + (struct/set! cycle previous-index nil xs)) + (let ((curr-i (cycle-current-index xs)) + (prev-i (cycle-previous-index xs))) + (if curr-i + (progn + (struct/set! cycle xs (-insert-at curr-i x (cycle-xs xs)) xs) + (when (>= prev-i curr-i) (struct/set! cycle previous-index (1+ prev-i) xs)) + (when curr-i (struct/set! cycle current-index (1+ curr-i) xs))) + (progn + (struct/set! cycle xs (cons x (cycle-xs xs)) xs) + (when prev-i (struct/set! cycle previous-index (1+ prev-i) xs)))) + xs))) + +(defun cycle/remove (x xs) + "Attempt to remove X from XS. + +X is found using `equal'. + +If X is the currently focused value, after it's deleted, current-index will be + nil. If X is the previously value, after it's deleted, previous-index will be + nil." + (let ((curr-i (cycle-current-index xs)) + (prev-i (cycle-previous-index xs)) + (rm-i (-elem-index x (cycle-xs xs)))) + (struct/set! cycle xs (-remove-at rm-i (cycle-xs xs)) xs) + (when prev-i + (when (> prev-i rm-i) (struct/set! cycle previous-index (1- prev-i) xs)) + (when (= prev-i rm-i) (struct/set! cycle previous-index nil xs))) + (when curr-i + (when (> curr-i rm-i) (struct/set! cycle current-index (1- curr-i) xs)) + (when (= curr-i rm-i) (struct/set! cycle current-index nil xs))) + xs)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Tests ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -164,7 +204,15 @@ ITEM is the first item in XS that t for `equal'." (prelude/assert (= 2 (->> xs (cycle/jump 1) cycle/current))) (prelude/assert (= 3 (->> xs (cycle/jump 2) cycle/current))) (prelude/assert (= 2 (cycle/previous-focus xs))) - (prelude/assert (= 2 (cycle/focus-previous! xs))))) + (prelude/assert (= 2 (cycle/focus-previous! xs))) + (prelude/assert (equal '(1 4 2 3) (cycle-xs (cycle/append 4 xs)))) + (prelude/assert (equal '(1 2 3) (cycle-xs (cycle/remove 4 xs)))) + (progn + (cycle/focus-item 3 xs) + (cycle/focus-item 2 xs) + (cycle/remove 1 xs) + (prelude/assert (= 2 (cycle/current xs))) + (prelude/assert (= 3 (cycle/previous-focus xs)))))) (provide 'cycle) ;;; cycle.el ends here