Function: treemacs--follow-each-dir

treemacs--follow-each-dir is a byte-compiled function defined in treemacs-core-utils.el.

Signature

(treemacs--follow-each-dir BTN DIR-PARTS PROJECT)

Documentation

Starting at BTN follow (goto and open) every single dir in DIR-PARTS.

Return the button that is found or the symbol follow-failed if the search failed. PROJECT is used for determining whether Git actions are appropriate.

Source Code

;; Defined in ~/.emacs.d/elpa/treemacs-20251226.1307/treemacs-core-utils.el
(define-inline treemacs--follow-each-dir (btn dir-parts project)
  "Starting at BTN follow (goto and open) every single dir in DIR-PARTS.
Return the button that is found or the symbol `follow-failed' if the search
failed.  PROJECT is used for determining whether Git actions are appropriate."
  (inline-letevals (btn dir-parts project)
    (inline-quote
     (let* ((root       (treemacs-button-get ,btn :path))
            (git-future (treemacs--git-status-process root ,project))
            (last-index (- (length ,dir-parts) 1))
            (depth      (treemacs-button-get ,btn :depth)))
       (goto-char ,btn)
       ;; point is currently on the next closest dir to the followed file we could get
       ;; from the dom, so we expand it to keep going
       (pcase (treemacs-button-get ,btn :state)
         ('dir-node-closed (treemacs--expand-dir-node ,btn :git-future git-future))
         ('root-node-closed (treemacs--expand-root-node ,btn)))
       (catch 'follow-failed
         (let ((index 0)
               (dir-part nil))
           ;; for every item in dir-parts append it to the already found path for a new
           ;; 'root' to follow, so for root = /x/ and dir-parts = [src, config, foo.el]
           ;; consecutively try to move to /x/src, /x/src/confg and finally /x/src/config/foo.el
           (while ,dir-parts
             (setq dir-part (pop ,dir-parts)
                   root (treemacs-join-path root dir-part)
                   ,btn
                   (let (current-btn)
                     (cl-block search
                       ;; first a plain text-based search for the current dir-part string
                       ;; then we grab the node we landed at and see what's going on
                       ;; there's a couple ways this can go
                       (while (progn (goto-char (line-end-position)) (search-forward dir-part nil :no-error))
                         (setq current-btn (treemacs-current-button))
                         (cond
                          ;; somehow we landed on a line where there isn't even anything to look at
                          ;; technically this should never happen, but better safe than sorry
                          ((null current-btn)
                           (cl-return-from search))
                          ;; the search matched a custom button - skip those, as they cannot match
                          ;; and their :paths are not strings, which would cause the following checks
                          ;; to crash
                          ((treemacs-button-get current-btn :custom))
                          ;; perfect match - return the node we're at
                          ((treemacs-is-path root :same-as (treemacs-button-get current-btn :path))
                           (cl-return-from search current-btn))
                          ;; perfect match - taking collapsed dirs into account
                          ;; return the node, but make sure to advance the loop variables an
                          ;; appropriate nuber of times, since a collapsed directory is basically
                          ;; multiple search iterations bundled as one
                          ((and (treemacs-button-get current-btn :collapsed)
                                (treemacs-is-path (treemacs-button-get current-btn :path) :parent-of root))
                           (dotimes (_ (car (treemacs-button-get current-btn :collapsed)))
                             (setq root (concat root "/" (pop ,dir-parts)))
                             (cl-incf index))
                           (cl-return-from search current-btn))
                          ;; node we're at has a smaller depth than the one we started from
                          ;; that means we overshot our target and there's nothing to be found here
                          ((>= depth (treemacs-button-get current-btn :depth))
                           (cl-return-from search)))))))
             (unless ,btn (throw 'follow-failed 'follow-failed))
             (goto-char ,btn)
             ;; don't open dir at the very end of the list since we only want to put
             ;; point in its line
             (when (and (eq 'dir-node-closed (treemacs-button-get ,btn :state))
                        (< index last-index))
               (treemacs--expand-dir-node ,btn :git-future git-future))
             (setq index (1+ index))))
         ,btn)))))