diff --git a/README.md b/README.md index ba31d74..67121c2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ space-tree is a library for managing spaces (workspaces) in Emacs. It is inspire (use-package space-tree :ensure (:host github :repo "chiply/space-tree") :config - (space-tree-init)) + (space-tree-init) + (space-tree-init-frames)) ``` ### With straight.el (use-package) @@ -32,7 +33,8 @@ space-tree is a library for managing spaces (workspaces) in Emacs. It is inspire (use-package space-tree :straight (:host github :repo "chiply/space-tree") :config - (space-tree-init)) + (space-tree-init) + (space-tree-init-frames)) ``` ### Manual @@ -43,6 +45,7 @@ Clone the repository and add it to your `load-path`: (add-to-list 'load-path "/path/to/space-tree") (require 'space-tree) (space-tree-init) +(space-tree-init-frames) ``` ## Usage diff --git a/space-tree.el b/space-tree.el index 96db74d..c9da0b0 100644 --- a/space-tree.el +++ b/space-tree.el @@ -93,45 +93,103 @@ does not affect the underlying tree structure." ;; (for keybindings, custom modeline elements, etc.). Do not mutate ;; them directly; use the commands and helpers in this file. -(defvar space-tree-tree (make-hash-table :test 'equal) - "Root hash table holding the structural layout of all spaces. + +;; (defvar space-tree-tree (make-hash-table :test 'equal) +;; "Root hash table holding the structural layout of all spaces. + +;; Each node is a hash table whose keys are integer space numbers and +;; whose values are the child node hash tables. The variable itself is +;; the root. Reset by `space-tree-init'.") + +(defun space-tree--get-tree (&optional frame) + "Get current FRAME's root hash table for spaces. + +Each node is a hash table whose keys are integer space numbers and +whose values are the child node hash tables. The variable itself is +the root. Reset by `space-tree-init'." + (frame-parameter frame 'space-tree-tree)) + +(defun space-tree--set-tree (val &optional frame) + "Set current FRAME's root hash table for spaces to VAL. Each node is a hash table whose keys are integer space numbers and whose values are the child node hash tables. The variable itself is -the root. Reset by `space-tree-init'.") +the root. Reset by `space-tree-init'." + (set-frame-parameter frame 'space-tree-tree val)) -(defvar space-tree-current-address nil - "Address of the currently selected space, as a list of integers. +(defun space-tree--get-current-address (&optional frame) + "Get address of the current space for FRAME, as integer list. For example, (2 1 3) refers to the third space at depth 3, nested under space 1 at depth 2, which is nested under top-level space 2. The empty list indicates no space is selected (initial state before -`space-tree-init' is called).") +`space-tree-init' is called)." + (frame-parameter frame 'space-tree-current-address)) + +(defun space-tree--set-current-address (val &optional frame) + "Set address of the current space for FRAME as VAL. + +For example, (2 1 3) refers to the third space at depth 3, nested +under space 1 at depth 2, which is nested under top-level space 2. +The empty list indicates no space is selected (initial state before +`space-tree-init' is called)." + (set-frame-parameter frame 'space-tree-current-address val)) + +(defun space-tree--get-address-wconf-tbl (&optional frame) + "Get FRAME's hash table with each space's window state. + +Keys are address lists (see `space-tree--get-current-address') and +values are objects produced by `window-state-get'. When you switch +to a space, the corresponding window state is restored via +`window-state-put'." + (frame-parameter frame 'space-tree-address-wconf-tbl)) -(defvar space-tree-address-wconf-tbl (make-hash-table :test 'equal) - "Hash table mapping each space's address to its saved window state. +(defun space-tree--set-address-wconf-tbl (val &optional frame) + "Set FRAME's hash table with each space's window state to VAL. -Keys are address lists (see `space-tree-current-address') and values -are objects produced by `window-state-get'. When you switch to a -space, the corresponding window state is restored via -`window-state-put'.") +Keys are address lists (see `space-tree--get-current-address') and +values are objects produced by `window-state-get'. When you switch +to a space, the corresponding window state is restored via +`window-state-put'." + (set-frame-parameter frame 'space-tree-address-wconf-tbl val)) -(defvar space-tree-recent-space-list nil - "List of recently visited space addresses, most recent first. +(defun space-tree--get-recent-space-list (&optional frame) + "Get FRAME's list of recently visited addresses, most recent first. Used by `space-tree-switch-or-create' to resolve a partial address to its most recently visited descendant - e.g. asking for (2) when \(2 1) was last visited resolves to (2 1). Adjacent duplicates and pure prefixes of later entries are compacted by -`space-tree--process-history'.") +`space-tree--process-history'." + (frame-parameter frame 'space-tree-recent-space-list)) -(defvar space-tree-space-name-tbl (make-hash-table :test 'equal) - "Hash table mapping space addresses to user-supplied display names. +(defun space-tree--set-recent-space-list (val &optional frame) + "Set FRAME's list of recently visited space addresses to VAL. + +Used by `space-tree-switch-or-create' to resolve a partial address +to its most recently visited descendant - e.g. asking for (2) when +\(2 1) was last visited resolves to (2 1). Adjacent duplicates and +pure prefixes of later entries are compacted by +`space-tree--process-history'." + (set-frame-parameter frame 'space-tree-recent-space-list val)) + +(defun space-tree--get-space-name-tbl () + "Get hash table mapping space addresses to display names. Set by `space-tree-name-current-space' and `space-tree-name-space-by-digit-arg'. Named spaces appear in the modeline by name instead of number and can be reached directly with -`space-tree-switch-space-by-name'.") +`space-tree-switch-space-by-name'." + (frame-parameter nil 'space-tree-space-name-tbl)) + +(defun space-tree--set-space-name-tbl (val &optional frame) + "Set FRAME's hash table mapping space addresses to VAL. + +Set by `space-tree-name-current-space' and +`space-tree-name-space-by-digit-arg'. Named spaces appear in the +modeline by name instead of number and can be reached directly with +`space-tree-switch-space-by-name'." + (set-frame-parameter frame 'space-tree-space-name-tbl val)) (defvar space-tree-copied-space nil "Window state captured by `space-tree-copy-workspace', or nil. @@ -242,36 +300,39 @@ invoked from a shallower depth than it expects)." ;;; Analyzing State -(defun space-tree--get (address) - "Return the tree node at ADDRESS in `space-tree-tree', or nil if absent. +(defun space-tree--get (address &optional frame) + "Return the FRAME's node at ADDRESS, or nil if absent. ADDRESS is a list of integer space numbers. An empty list returns the root. The returned value is the child-hash-table at that node." - (let ((node space-tree-tree)) + (let ((node (space-tree--get-tree frame))) (dolist (k address node) (setq node (and node (gethash k node)))))) (defun space-tree--space-exists-p (address) "Return non-nil if a space exists at ADDRESS." - (and (gethash address space-tree-address-wconf-tbl) t)) + (and (gethash address (space-tree--get-address-wconf-tbl)) t)) (defun space-tree--current-depth () "Return the depth (number of levels) of the current space." - (length space-tree-current-address)) + (length (space-tree--get-current-address))) (defun space-tree--current-parent () "Return the address of the parent of the current space. Returns the empty list when the current space is at the top level." - (butlast space-tree-current-address)) + (butlast (space-tree--get-current-address))) -(defun space-tree--siblings-of (address) - "Return the sorted list of space numbers at the level of ADDRESS. +(defun space-tree--siblings-of (address &optional frame) + "Return the FRAME's list of space numbers at the level of ADDRESS. That is, the keys of ADDRESS's parent node, in ascending order." - (sort (hash-table-keys (space-tree--get (butlast address))) #'<)) + (sort (hash-table-keys + (space-tree--get (butlast address) frame)) + #'<)) -(defun space-tree--number-of-spaces-current-level () - "Return the count of spaces at the current address's level." - (length (space-tree--siblings-of space-tree-current-address))) +(defun space-tree--number-of-spaces-current-level (&optional frame) + "Return the FRAME's count of spaces at the current address's level." + (length (space-tree--siblings-of + (space-tree--get-current-address frame) frame))) (defun space-tree--recent-space-on-path (sublist) "Return the most recently visited address that starts with SUBLIST. @@ -280,35 +341,36 @@ Returns nil if no recent space has SUBLIST as a prefix. Used to resolve a partial navigation like \"go to space 1\" into the most recently visited descendant of that parent." (cl-find-if (lambda (x) (space-tree--prefix-p sublist x)) - space-tree-recent-space-list)) + (space-tree--get-recent-space-list))) ;;; State Mutation -(defun space-tree--set (address) - "Create an empty child node at ADDRESS. +(defun space-tree--set (address &optional frame) + "Create an empty child node at FRAME's ADDRESS. ADDRESS must be non-empty and its parent must already exist. Overwrites any existing node at that address." (puthash (car (last address)) (space-tree--ht) - (space-tree--get (butlast address)))) + (space-tree--get (butlast address) frame))) -(defun space-tree--process-history () - "Compact `space-tree-recent-space-list'. +(defun space-tree--process-history (&optional frame) + "Compact FRAME's `space-tree-recent-space-list'. Removes addresses that are pure prefixes of a deeper address already in the list (since the deeper address already captures the parent context) and collapses adjacent duplicates." - (setq space-tree-recent-space-list - (space-tree--remove-adjacent-duplicates - (seq-remove - (lambda (a) - (cl-some (lambda (b) - (and (> (length b) (length a)) - (space-tree--prefix-p a b))) - space-tree-recent-space-list)) - space-tree-recent-space-list)))) + (space-tree--set-recent-space-list + (space-tree--remove-adjacent-duplicates + (seq-remove + (lambda (a) + (cl-some (lambda (b) + (and (> (length b) (length a)) + (space-tree--prefix-p a b))) + (space-tree--get-recent-space-list frame))) + (space-tree--get-recent-space-list frame))) + frame)) (defun space-tree--remove (address) "Delete the space at ADDRESS from all state. @@ -317,16 +379,16 @@ Removes the tree node, the saved window state, the user-defined name (if any), and all references in the recent-space history. Refreshes the modeline." (remhash (car (last address)) (space-tree--get (butlast address))) - (remhash address space-tree-space-name-tbl) - (remhash address space-tree-address-wconf-tbl) - (setq space-tree-recent-space-list - (seq-remove (lambda (x) (equal x address)) - space-tree-recent-space-list)) + (remhash address (space-tree--get-space-name-tbl)) + (remhash address (space-tree--get-address-wconf-tbl)) + (space-tree--set-recent-space-list + (seq-remove (lambda (x) (equal x address)) + (space-tree--get-recent-space-list))) (space-tree--process-history) (force-mode-line-update)) -(defun space-tree--create-space-at (address) - "Create a new space at ADDRESS and switch to it. +(defun space-tree--create-space-at (address &optional frame) + "Create a new space at FRAME's ADDRESS and switch to it. Establishes the tree node, captures the current window state as the new space's starting layout, and clears the frame to a single @@ -334,22 +396,26 @@ new space's starting layout, and clears the frame to a single which case the user's existing frame layout is preserved, e.g. for the very first space created by `space-tree-init')." (space-tree--select-non-side-window) - (space-tree--set address) - (setq space-tree-current-address address) - (puthash address (window-state-get) space-tree-address-wconf-tbl) - (push space-tree-current-address space-tree-recent-space-list) - (space-tree--process-history) - (when (> (space-tree--number-of-spaces-current-level) 1) + (space-tree--set address frame) + (space-tree--set-current-address address frame) + (puthash address (window-state-get) + (space-tree--get-address-wconf-tbl frame)) + (space-tree--set-recent-space-list + (cons (space-tree--get-current-address frame) + (space-tree--get-recent-space-list frame)) + frame) + (space-tree--process-history frame) + (when (> (space-tree--number-of-spaces-current-level frame) 1) (space-tree--delete-other-windows-and-switch-to-scratch))) (defun space-tree--save-wconf () "Snapshot the current window state into the current space. No-op when no space is currently selected, so callers can invoke this unconditionally without first checking initialisation state." - (when space-tree-current-address - (puthash space-tree-current-address + (when (space-tree--get-current-address) + (puthash (space-tree--get-current-address) (window-state-get) - space-tree-address-wconf-tbl))) + (space-tree--get-address-wconf-tbl)))) (defun space-tree--switch (address &optional no-update-wconf) "Switch to the existing space at ADDRESS. @@ -359,11 +425,13 @@ state - used when the caller will redraw the frame separately, for example when deleting the current space and switching to its parent in one operation." (space-tree--select-non-side-window) - (let ((wconf (gethash address space-tree-address-wconf-tbl))) + (let ((wconf (gethash address (space-tree--get-address-wconf-tbl)))) (unless no-update-wconf (space-tree--window-state-put-safely wconf)) - (setq space-tree-current-address address) - (push space-tree-current-address space-tree-recent-space-list))) + (space-tree--set-current-address address) + (space-tree--set-recent-space-list + (cons (space-tree--get-current-address) + (space-tree--get-recent-space-list))))) ;;; Modeline @@ -380,7 +448,7 @@ sibling nodes at this level." (mapconcat (lambda (n) (let ((label (or (gethash (append parent-address (list n)) - space-tree-space-name-tbl) + (space-tree--get-space-name-tbl)) (number-to-string n)))) (if (equal n selected-space-number) (propertize (concat label "' ") 'face 'bold) @@ -398,8 +466,8 @@ marked with a trailing apostrophe; levels are separated by `|'. Named spaces appear by name instead of number." (let (parts) (dotimes (i (space-tree--current-depth)) - (let* ((parent (seq-take space-tree-current-address i)) - (selected (nth i space-tree-current-address)) + (let* ((parent (seq-take (space-tree--get-current-address) i)) + (selected (nth i (space-tree--get-current-address))) (level-ht (space-tree--get parent))) (push (space-tree--modeline-string-for-level parent selected level-ht) parts))) @@ -409,8 +477,8 @@ Named spaces appear by name instead of number." ;;; Public API - Lifecycle ;;;###autoload -(defun space-tree-init () - "Initialise space-tree, replacing any existing state. +(defun space-tree-init (&optional frame) + "Initialise space-tree for FRAME, replacing any existing state. Resets the entire tree and creates a single top-level space. The first space is numbered 1 by default, or 0 if `space-tree-start-at-0' @@ -420,14 +488,19 @@ WARNING: any previously created spaces and their saved window states are discarded. The internal copy/paste clipboard \(`space-tree-copied-space') is preserved." (interactive) - (setq space-tree-tree (space-tree--ht) - space-tree-current-address nil - space-tree-address-wconf-tbl (space-tree--ht) - space-tree-space-name-tbl (space-tree--ht) - space-tree-recent-space-list nil) - (space-tree--create-space-at (list (if space-tree-start-at-0 0 1))) + (space-tree--set-tree (space-tree--ht) frame) + (space-tree--set-current-address nil frame) + (space-tree--set-address-wconf-tbl (space-tree--ht) frame) + (space-tree--set-recent-space-list nil frame) + (space-tree--set-space-name-tbl (space-tree--ht) frame) + (space-tree--create-space-at (list (if space-tree-start-at-0 0 1)) frame) (force-mode-line-update)) +;;;###autoload +(defun space-tree-init-frames () + "Initialise `space-tree-init' after each frame." + (unless (member 'space-tree-init after-make-frame-functions) + (add-hook 'after-make-frame-functions #'space-tree-init))) ;;; Public API - Navigation @@ -447,7 +520,8 @@ including the convenience wrappers `space-tree-to-1' .. `-to-9' and `space-tree-sub-1' .. `-sub-5'. It is not directly interactive; bind a wrapper lambda or use a digit-encoded command instead." (space-tree--validate-address new-address) - (let* ((existing (gethash new-address space-tree-address-wconf-tbl)) + (let* ((existing (gethash new-address + (space-tree--get-address-wconf-tbl))) (recent (space-tree--recent-space-on-path new-address))) (space-tree--save-wconf) (cond @@ -476,7 +550,7 @@ The new space is numbered one higher than the current largest top-level space. Its window layout starts as a single `*scratch*' buffer." (interactive) - (let ((next (1+ (apply #'max (hash-table-keys space-tree-tree))))) + (let ((next (1+ (apply #'max (hash-table-keys (space-tree--get-tree)))))) (space-tree--create-space-at (list next)))) ;;;###autoload @@ -492,7 +566,7 @@ an error. Deletion also removes the saved window state, the user-defined name \(if any), and all history references." - (interactive (list space-tree-current-address)) + (interactive (list (space-tree--get-current-address))) (let ((n (space-tree--number-of-spaces-current-level))) (cond ((> n 1) (space-tree-go-left) (space-tree--remove address)) ((and (= n 1) (= (space-tree--current-depth) 1)) @@ -578,7 +652,7 @@ requires a match - arbitrary input is rejected." (let* ((entries (let (acc) (maphash (lambda (addr name) (push (cons name addr) acc)) - space-tree-space-name-tbl) + (space-tree--get-space-name-tbl)) acc)) (name (completing-read "Named space: " entries nil t))) (space-tree-switch-or-create (cdr (assoc name entries))))) @@ -588,7 +662,7 @@ requires a match - arbitrary input is rejected." "Switch back to the most recently visited space. Signals a `user-error' if there is no prior space in the history." (interactive) - (if-let* ((prev (nth 1 space-tree-recent-space-list))) + (if-let* ((prev (nth 1 (space-tree--get-recent-space-list)))) (space-tree-switch-or-create prev) (user-error "No previous space"))) @@ -596,9 +670,11 @@ Signals a `user-error' if there is no prior space in the history." "Move DELTA positions among the current level's sorted siblings. Wraps around at both ends, so going right from the rightmost lands on the leftmost and vice versa." - (space-tree--validate-address space-tree-current-address) - (let* ((siblings (space-tree--siblings-of space-tree-current-address)) - (i (seq-position siblings (car (last space-tree-current-address)))) + (space-tree--validate-address (space-tree--get-current-address)) + (let* ((siblings (space-tree--siblings-of + (space-tree--get-current-address))) + (i (seq-position + siblings (car (last (space-tree--get-current-address))))) (j (mod (+ i delta) (length siblings)))) (space-tree-switch-current-level (nth j siblings)))) @@ -627,7 +703,9 @@ The name replaces the numeric label in the modeline lighter and can be used as a target for `space-tree-switch-space-by-name'. Names are not required to be unique." (interactive "sName: ") - (puthash space-tree-current-address name space-tree-space-name-tbl) + (puthash + (space-tree--get-current-address) name + (space-tree--get-space-name-tbl)) (force-mode-line-update)) ;;;###autoload @@ -640,7 +718,7 @@ prompted in the minibuffer for the name." (interactive "p") (let* ((address (space-tree--parse-digit-address (number-to-string arg))) (name (read-from-minibuffer "Name: "))) - (puthash address name space-tree-space-name-tbl)) + (puthash address name (space-tree--get-space-name-tbl))) (force-mode-line-update)) @@ -672,12 +750,12 @@ is used as the docstring of each generated command." (space-tree--def-level-commands "space-tree-sub" "Switch to second-level space %d under the current top-level." 5 - (list (nth 0 space-tree-current-address) n)) + (list (nth 0 (space-tree--get-current-address)) n)) (space-tree--def-level-commands "space-tree-sub-sub" "Switch to third-level space %d under the current path." 5 - (list (nth 0 space-tree-current-address) - (nth 1 space-tree-current-address) n)) + (list (nth 0 (space-tree--get-current-address)) + (nth 1 (space-tree--get-current-address)) n)) (provide 'space-tree) diff --git a/test/space-tree-test.el b/test/space-tree-test.el index c2eceda..05b5fd4 100644 --- a/test/space-tree-test.el +++ b/test/space-tree-test.el @@ -19,12 +19,12 @@ (defmacro space-tree-test-with-clean-state (&rest body) "Execute BODY with all space-tree global state saved and restored." (declare (indent 0) (debug t)) - `(let ((space-tree-tree (make-hash-table :test 'equal)) - (space-tree-current-address '()) - (space-tree-address-wconf-tbl (make-hash-table :test 'equal)) - (space-tree-recent-space-list '()) - (space-tree-space-name-tbl (make-hash-table :test 'equal)) - (space-tree-copied-space nil)) + `(cl-letf (((frame-parameter nil 'space-tree-tree) (make-hash-table :test 'equal)) + ((frame-parameter nil 'space-tree-current-address) '()) + ((frame-parameter nil 'space-tree-address-wconf-tbl) (make-hash-table :test 'equal)) + ((frame-parameter nil 'space-tree-recent-space-list) '()) + ((frame-parameter nil 'space-tree-space-name-tbl) (make-hash-table :test 'equal)) + ((frame-parameter nil 'space-tree-copied-space) nil)) ,@body)) (defmacro space-tree-test-with-mock-windows (&rest body) @@ -50,11 +50,11 @@ table entries, current-address (last in list), and recent-space-list." (unless (space-tree--get path) (space-tree--set path)))) ;; Store a placeholder wconf - (puthash addr (list 'mock-wconf addr) space-tree-address-wconf-tbl)) + (puthash addr (list 'mock-wconf addr) (space-tree--get-address-wconf-tbl))) ;; Current address is the last one given - (setq space-tree-current-address (car (last addresses))) + (space-tree--set-current-address (car (last addresses))) ;; Recent list is addresses in reverse order - (setq space-tree-recent-space-list (reverse addresses))) + (space-tree--set-recent-space-list (reverse addresses))) ;;; A. Pure Functions @@ -214,17 +214,17 @@ table entries, current-address (last in list), and recent-space-list." (ert-deftest space-tree-test-recent-space-on-path/found () (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2 3) (1 2) (2 1))) + (space-tree--set-recent-space-list '((1 2 3) (1 2) (2 1))) (should (equal (space-tree--recent-space-on-path '(1 2)) '(1 2 3))))) (ert-deftest space-tree-test-recent-space-on-path/not-found () (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2 3) (2 1))) + (space-tree--set-recent-space-list '((1 2 3) (2 1))) (should-not (space-tree--recent-space-on-path '(3))))) (ert-deftest space-tree-test-recent-space-on-path/exact-match () (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2) (3 4))) + (space-tree--set-recent-space-list '((1 2) (3 4))) (should (equal (space-tree--recent-space-on-path '(1 2)) '(1 2))))) ;; space-tree--get @@ -290,13 +290,13 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-build-tree '((1) (2))) (space-tree--remove '(2)) (should-not (space-tree--get '(2))) - (should-not (gethash '(2) space-tree-address-wconf-tbl))))) + (should-not (gethash '(2) (space-tree--get-address-wconf-tbl)))))) (ert-deftest space-tree-test-remove/nested () (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (1 1) (1 2))) - (setq space-tree-current-address '(1 2)) + (space-tree--set-current-address '(1 2)) (space-tree--remove '(1 1)) (should-not (space-tree--get '(1 1))) ;; Parent still has remaining child @@ -306,38 +306,38 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (puthash '(2) "work" space-tree-space-name-tbl) + (puthash '(2) "work" (space-tree--get-space-name-tbl)) (space-tree--remove '(2)) - (should-not (gethash '(2) space-tree-space-name-tbl))))) + (should-not (gethash '(2) (space-tree--get-space-name-tbl)))))) (ert-deftest space-tree-test-remove/cleans-history () (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (setq space-tree-recent-space-list '((2) (1))) + (space-tree--set-recent-space-list '((2) (1))) (space-tree--remove '(2)) - (should-not (member '(2) space-tree-recent-space-list))))) + (should-not (member '(2) (space-tree--get-recent-space-list)))))) ;; space-tree--process-history (ert-deftest space-tree-test-process-history/removes-prefix () "Parent addresses are removed when a child is in the list." (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2 3) (1 2) (1))) + (space-tree--set-recent-space-list '((1 2 3) (1 2) (1))) (space-tree--process-history) - (should (equal space-tree-recent-space-list '((1 2 3)))))) + (should (equal (space-tree--get-recent-space-list) '((1 2 3)))))) (ert-deftest space-tree-test-process-history/keeps-non-prefix () (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2) (3 4))) + (space-tree--set-recent-space-list '((1 2) (3 4))) (space-tree--process-history) - (should (equal space-tree-recent-space-list '((1 2) (3 4)))))) + (should (equal (space-tree--get-recent-space-list) '((1 2) (3 4)))))) (ert-deftest space-tree-test-process-history/removes-adj-dups () (space-tree-test-with-clean-state - (setq space-tree-recent-space-list '((1 2) (1 2) (3 4))) + (space-tree--set-recent-space-list '((1 2) (1 2) (3 4))) (space-tree--process-history) - (should (equal space-tree-recent-space-list '((1 2) (3 4)))))) + (should (equal (space-tree--get-recent-space-list) '((1 2) (3 4)))))) ;; space-tree-init @@ -347,8 +347,8 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-mock-windows (let ((space-tree-start-at-0 nil)) (space-tree-init) - (should (equal space-tree-current-address '(1))) - (should (gethash '(1) space-tree-address-wconf-tbl)) + (should (equal (space-tree--get-current-address) '(1))) + (should (gethash '(1) (space-tree--get-address-wconf-tbl))) (should (hash-table-p (space-tree--get '(1)))))))) (ert-deftest space-tree-test-init/start-at-0 () @@ -356,22 +356,22 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-mock-windows (let ((space-tree-start-at-0 t)) (space-tree-init) - (should (equal space-tree-current-address '(0))) - (should (gethash '(0) space-tree-address-wconf-tbl)))))) + (should (equal (space-tree--get-current-address) '(0))) + (should (gethash '(0) (space-tree--get-address-wconf-tbl))))))) (ert-deftest space-tree-test-init/resets-state () "Init clears any pre-existing state." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2) (3))) - (puthash '(1) "old" space-tree-space-name-tbl) + (puthash '(1) "old" (space-tree--get-space-name-tbl)) (let ((space-tree-start-at-0 nil)) (space-tree-init) ;; Old spaces gone - (should-not (gethash '(2) space-tree-address-wconf-tbl)) - (should-not (gethash '(3) space-tree-address-wconf-tbl)) + (should-not (gethash '(2) (space-tree--get-address-wconf-tbl))) + (should-not (gethash '(3) (space-tree--get-address-wconf-tbl))) ;; Name table cleared - (should (= (hash-table-count space-tree-space-name-tbl) 0)))))) + (should (= (hash-table-count (space-tree--get-space-name-tbl)) 0)))))) ;; space-tree--switch @@ -379,18 +379,18 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (setq space-tree-current-address '(1)) + (space-tree--set-current-address '(1)) (space-tree--switch '(2)) - (should (equal space-tree-current-address '(2)))))) + (should (equal (space-tree--get-current-address) '(2)))))) (ert-deftest space-tree-test-switch/history-updated () (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (setq space-tree-current-address '(1)) - (setq space-tree-recent-space-list '((1))) + (space-tree--set-current-address '(1)) + (space-tree--set-recent-space-list '((1))) (space-tree--switch '(2)) - (should (equal (car space-tree-recent-space-list) '(2)))))) + (should (equal (car (space-tree--get-recent-space-list)) '(2)))))) ;; space-tree-switch-or-create @@ -399,31 +399,31 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (setq space-tree-current-address '(1)) - (setq space-tree-recent-space-list '((1) (2))) + (space-tree--set-current-address '(1)) + (space-tree--set-recent-space-list '((1) (2))) (space-tree-switch-or-create '(2)) - (should (equal space-tree-current-address '(2)))))) + (should (equal (space-tree--get-current-address) '(2)))))) (ert-deftest space-tree-test-switch-or-create/new-space () "Switching to non-existent address creates it." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1))) - (setq space-tree-current-address '(1)) + (space-tree--set-current-address '(1)) (space-tree-switch-or-create '(2)) - (should (equal space-tree-current-address '(2))) - (should (gethash '(2) space-tree-address-wconf-tbl))))) + (should (equal (space-tree--get-current-address) '(2))) + (should (gethash '(2) (space-tree--get-address-wconf-tbl)))))) (ert-deftest space-tree-test-switch-or-create/via-recent () "Navigating to a parent address resolves via recent list." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (1 1) (1 2))) - (setq space-tree-current-address '(1)) - (setq space-tree-recent-space-list '((1 2) (1 1) (1))) + (space-tree--set-current-address '(1)) + (space-tree--set-recent-space-list '((1 2) (1 1) (1))) (space-tree-switch-or-create '(1)) ;; Should resolve to (1 2) - first recent space on path (1) - (should (equal space-tree-current-address '(1 2)))))) + (should (equal (space-tree--get-current-address) '(1 2)))))) ;;; D. Modeline Rendering @@ -464,7 +464,7 @@ table entries, current-address (last in list), and recent-space-list." (space-tree-test-with-clean-state (space-tree-test-with-mock-windows (space-tree-test-build-tree '((1) (2))) - (puthash '(2) "work" space-tree-space-name-tbl) + (puthash '(2) "work" (space-tree--get-space-name-tbl)) (let ((result (space-tree-modeline-lighter))) (should (string-match-p "work" result))))))