124 lines
5.1 KiB
EmacsLisp
124 lines
5.1 KiB
EmacsLisp
;;; treemacs.el --- A tree style file viewer package -*- lexical-binding: t -*-
|
|
|
|
;; Copyright (C) 2024 Alexander Miller
|
|
|
|
;; This program is free software; you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;; Follow mode definition.
|
|
|
|
;;; Code:
|
|
|
|
(require 'hl-line)
|
|
(require 'dash)
|
|
(require 's)
|
|
(require 'treemacs-customization)
|
|
(require 'treemacs-rendering)
|
|
(require 'treemacs-dom)
|
|
(require 'treemacs-async)
|
|
(require 'treemacs-core-utils)
|
|
|
|
(eval-when-compile
|
|
(require 'treemacs-macros))
|
|
|
|
(treemacs-import-functions-from "dired"
|
|
dired-current-directory)
|
|
|
|
(defvar treemacs--ready-to-follow nil
|
|
"Signals to `treemacs-follow-mode' if a follow action may be run.
|
|
Must be set to nil when no following should be triggered, e.g. when the
|
|
treemacs buffer is being rebuilt or during treemacs' own window selection
|
|
functions.")
|
|
|
|
(defvar treemacs--follow-timer nil
|
|
"Idle timer for `treemacs--follow' to run.")
|
|
|
|
(defun treemacs--follow ()
|
|
"Move point to the current file in the treemacs buffer.
|
|
Expand directories if needed. Do nothing if current file does not exist in the
|
|
file system or is not below current treemacs root or if the treemacs buffer is
|
|
not visible."
|
|
;; Treemacs selecting files with `ace-window' results in a large amount of
|
|
;; window selections, so we should be breaking out as soon as possbile
|
|
(setq treemacs--follow-timer nil)
|
|
(when treemacs--ready-to-follow
|
|
(treemacs-without-following
|
|
(let* ((treemacs-window (treemacs-get-local-window))
|
|
(current-buffer (current-buffer))
|
|
(buffer-name (buffer-name current-buffer))
|
|
(current-file (or (buffer-file-name current-buffer)
|
|
(when (eq major-mode 'dired-mode)
|
|
(treemacs-canonical-path (dired-current-directory))))))
|
|
(when (and treemacs-window
|
|
current-file
|
|
(not (s-starts-with? treemacs--buffer-name-prefix buffer-name))
|
|
(file-exists-p current-file)
|
|
(not (string= buffer-name "COMMIT_EDITMSG"))
|
|
(--none?
|
|
(funcall it current-file)
|
|
treemacs-file-follow-ignore-functions))
|
|
(-when-let (project-for-file (treemacs--find-project-for-buffer current-file))
|
|
(with-selected-window treemacs-window
|
|
(-let [selected-file (--if-let (treemacs-current-button)
|
|
(treemacs--nearest-path it)
|
|
(treemacs-project->path project-for-file))]
|
|
(unless (treemacs-is-path selected-file :same-as current-file)
|
|
(when (treemacs-goto-file-node current-file project-for-file)
|
|
(when treemacs-project-follow-cleanup
|
|
(dolist (project (treemacs-workspace->projects (treemacs-current-workspace)))
|
|
(unless (or (not (treemacs-project->is-expanded? project))
|
|
(eq project project-for-file))
|
|
(-when-let (project-pos (treemacs-project->position project))
|
|
(goto-char project-pos)
|
|
(treemacs--collapse-root-node project-pos)))))
|
|
(when treemacs-recenter-after-file-follow
|
|
(treemacs--maybe-recenter treemacs-recenter-after-file-follow))))))))))))
|
|
|
|
(defun treemacs--follow-after-buffer-list-update ()
|
|
"Debounced call to `treemacs--follow'."
|
|
(when treemacs--ready-to-follow
|
|
(unless treemacs--follow-timer
|
|
(setq treemacs--follow-timer
|
|
(run-with-idle-timer treemacs-file-follow-delay nil #'treemacs--follow)))))
|
|
|
|
(defun treemacs--setup-follow-mode ()
|
|
"Setup all the hooks needed for `treemacs-follow-mode'."
|
|
(add-hook 'buffer-list-update-hook #'treemacs--follow-after-buffer-list-update)
|
|
(treemacs--follow))
|
|
|
|
(defun treemacs--tear-down-follow-mode ()
|
|
"Remove the hooks added by `treemacs--setup-follow-mode'."
|
|
(remove-hook 'buffer-list-update-hook #'treemacs--follow-after-buffer-list-update))
|
|
|
|
(define-minor-mode treemacs-follow-mode
|
|
"Toggle `treemacs-follow-mode'.
|
|
When enabled treemacs will keep track of and focus the currently selected
|
|
buffer's file. This only applies if the file is within the treemacs root
|
|
directory.
|
|
This functionality can also be manually invoked with `treemacs-find-file'."
|
|
:init-value nil
|
|
:global t
|
|
:lighter nil
|
|
:group 'treemacs
|
|
(if treemacs-follow-mode
|
|
(treemacs--setup-follow-mode)
|
|
(treemacs--tear-down-follow-mode)))
|
|
|
|
(treemacs-only-during-init (treemacs-follow-mode))
|
|
|
|
(provide 'treemacs-follow-mode)
|
|
|
|
;;; treemacs-follow-mode.el ends here
|