From 978148d6b5bc8d9bbb247117de8d1131a4ae94ba Mon Sep 17 00:00:00 2001 From: Zelong Kuang Date: Sun, 21 Dec 2025 12:54:49 +1100 Subject: [PATCH] Update --- init.el | 2 +- lisp/init-treemacs.el | 21 +-- lisp/init-workspace.el | 55 ++---- lisp/packages/persp-mode-project-bridge.el | 192 +++++++++++++++++++++ 4 files changed, 211 insertions(+), 59 deletions(-) create mode 100644 lisp/packages/persp-mode-project-bridge.el diff --git a/init.el b/init.el index 1b3b450..10812e8 100644 --- a/init.el +++ b/init.el @@ -8,7 +8,7 @@ (require 'init-ui) (require 'init-bindings) -(require 'init-workspace) +;; (require 'init-workspace) (require 'init-dired) ;; (require 'init-treemacs) diff --git a/lisp/init-treemacs.el b/lisp/init-treemacs.el index fbe72de..4caae4d 100644 --- a/lisp/init-treemacs.el +++ b/lisp/init-treemacs.el @@ -1,10 +1,5 @@ ;; -*- lexical-binding: t; -*- (use-package treemacs - :commands (treemacs-follow-mode - treemacs-filewatch-mode - treemacs-git-mode - treemacs-project-follow-mode - treemacs-hide-gitignored-files-mode) :custom-face (cfrs-border-color ((t (:inherit posframe-border)))) :init @@ -24,14 +19,9 @@ treemacs-sorting 'alphabetic-asc treemacs-follow-after-init t treemacs-width 30 - treemacs-show-hidden-files nil - treemacs-silent-refresh t - treemacs-no-png-images 1) - - (treemacs-follow-mode t) - (treemacs-project-follow-mode t) - (treemacs-filewatch-mode t) - (treemacs-hide-gitignored-files-mode t) + treemacs-show-hidden-files nil + treemacs-silent-refresh t + treemacs-no-png-images 1) :bind (:map global-map ("M-0" . treemacs-select-window) @@ -59,9 +49,12 @@ :config (treemacs-nerd-icons-config)) (use-package treemacs-persp - :after persp-mode + :after (treemacs persp-mode) :demand t :functions treemacs-set-scope-type :config (treemacs-set-scope-type 'Perspectives)) +(use-package treemacs-projectile + :after (treemacs projectile-mode)) + (provide 'init-treemacs) diff --git a/lisp/init-workspace.el b/lisp/init-workspace.el index 9022199..eb5314b 100644 --- a/lisp/init-workspace.el +++ b/lisp/init-workspace.el @@ -1,51 +1,18 @@ ;; -*- lexical-binding: t; -*- -(use-package tabspaces - :functions tabspaces-mode - :hook (elpaca-after-init . tabspaces-mode) +(use-package persp-mode + :hook (elpaca-after-init . persp-mode) :custom - (tab-bar-show nil) - - (tabspaces-use-filtered-buffers-as-default t) - (tabspaces-default-tab "Default") - (tabspaces-remove-to-default t) - (tabspaces-include-buffers '("*scratch*" "*Messages*")) - (tabspaces-exclude-buffers '("*eat*" "*vterm*" "*shell*" "*eshell*")) - ;; sessions - (tabspaces-session t) - (tabspaces-session-auto-restore t) - (tabspaces-keymap-prefix "C-c w") + (persp-keymap-prefix "w") :config - (with-no-warnings - ;; Filter Buffers for Consult-Buffer - (with-eval-after-load 'consult - ;; hide full buffer list (still available with "b" prefix) - (consult-customize consult--source-buffer :hidden t :default nil) - ;; set consult-workspace buffer list - (defvar consult--source-workspace - (list :name "Workspace Buffer" - :narrow ?w - :history 'buffer-name-history - :category 'buffer - :state #'consult--buffer-state - :default t - :items (lambda () (consult--buffer-query - :predicate #'tabspaces--local-buffer-p - :sort 'visibility - :as #'buffer-name))) - "Set workspace buffer list for consult-buffer.") - (add-to-list 'consult-buffer-sources 'consult--source-workspace)) + (setq wg-morph-on nil) + (setq persp-autokill-buffer-on-remove 'kill-weak) + (add-hook 'window-setup-hook #'(lambda () (persp-mode 1)))) - (defun my-tabspaces-delete-childframe (&rest _) - "Delete all child frames." - (ignore-errors - (posframe-delete-all))) - (advice-add #'tabspaces-save-session :before #'my-tabspaces-delete-childframe) - - (defun my-tabspaces-burry-window (&rest _) - "Burry *Messages* buffer." - (ignore-errors - (quit-windows-on messages-buffer-name))) - (advice-add #'tabspaces-restore-session :after #'my-tabspaces-burry-window))) +(use-package projectile + :hook (elpaca-after-init . projectile-mode) + :config + ;; Recommended keymap prefix on Windows/Linux + (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)) (provide 'init-workspace) diff --git a/lisp/packages/persp-mode-project-bridge.el b/lisp/packages/persp-mode-project-bridge.el new file mode 100644 index 0000000..76f511d --- /dev/null +++ b/lisp/packages/persp-mode-project-bridge.el @@ -0,0 +1,192 @@ +;;; persp-mode-project-bridge.el --- Integration of persp-mode + project.el -*- lexical-binding: t -*- + +;; Copyright (C) 2017 Constantin Kulikov +;; Copyright (C) 2021 Siavash Askari Nasr +;; +;; Author: Constantin Kulikov (Bad_ptr) +;; Siavash Askari Nasr +;; Maintainer: Siavash Askari Nasr +;; Version: 0.1 +;; Package-Requires: ((emacs "27.1") (persp-mode "2.9")) +;; SPDX-License-Identifier: GPL-3.0-or-later +;; Keywords: vc, persp-mode, perspective, project, project.el +;; URL: https://github.com/CIAvash/persp-mode-project-bridge + +;;; License: + +;; This file is not part of GNU Emacs. + +;; 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, 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, write to the Free Software +;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +;;; Commentary: + +;; Creates a perspective for each project.el project. (Based on the persp-mode-projectile-bridge) + +;;; Usage: + +;; Installation: + +;; M-x package-install-file RET persp-mode-project-bridge RET + +;; Example configuration: + +;; (with-eval-after-load "persp-mode-project-bridge-autoloads" +;; (add-hook 'persp-mode-project-bridge-mode-hook +;; (lambda () +;; (if persp-mode-project-bridge-mode +;; (persp-mode-project-bridge-find-perspectives-for-all-buffers) +;; (persp-mode-project-bridge-kill-perspectives)))) +;; (add-hook 'after-init-hook +;; (lambda () +;; (persp-mode-project-bridge-mode 1)) +;; t)) +;; +;; With use-package: +;; (use-package persp-mode-project-bridge +;; :hook +;; (persp-mode-project-bridge-mode . (lambda () +;; (if persp-mode-project-bridge-mode +;; (persp-mode-project-bridge-find-perspectives-for-all-buffers) +;; (persp-mode-project-bridge-kill-perspectives)))) +;; (persp-mode . persp-mode-project-bridge-mode)) + +;;; Code: + + +(require 'persp-mode) +(require 'project) +(require 'cl-lib) + +(declare-function project-root "project") + +(defvar persp-mode-project-bridge-mode nil) + +(defgroup persp-mode-project-bridge nil + "persp-mode project.el integration." + :group 'persp-mode + :group 'project + :prefix "persp-mode-project-bridge-" + :link + '(url-link + :tag "Github" "https://github.com/CIAvash/persp-mode-project-bridge")) + +(defcustom persp-mode-project-bridge-persp-name-prefix "[p] " + "Prefix to use for project perspective names." + :group 'persp-mode-project-bridge + :type 'string + :set (lambda (sym val) + (if persp-mode-project-bridge-mode + (let ((old-prefix (symbol-value sym))) + (custom-set-default sym val) + (let (old-name) + (mapc (lambda (p) + (when (and + p (persp-parameter + 'persp-mode-project-bridge p)) + (setq old-name + (substring (persp-name p) + (string-width old-prefix))) + (persp-rename (concat val old-name) p))) + (persp-persps)))) + (custom-set-default sym val)))) + + +(defun persp-mode-project-bridge-add-new-persp (name) + "Create a new perspective NAME." + (let ((persp (persp-get-by-name name *persp-hash* :nil))) + (if (eq :nil persp) + (prog1 + (setq persp (persp-add-new name)) + (when persp + (set-persp-parameter 'persp-mode-project-bridge t persp) + (set-persp-parameter 'dont-save-to-file t persp) + (persp-add-buffer (cl-remove-if-not #'get-file-buffer (project-files (project-current))) + persp nil nil))) + persp))) + +(defun persp-mode-project-bridge-find-perspective-for-buffer (b) + "Find a perspective for buffer B." + (when (buffer-live-p b) + (with-current-buffer b + (when (and persp-mode-project-bridge-mode + (buffer-name b) (project-current)) + (let ((persp (persp-mode-project-bridge-add-new-persp + (concat persp-mode-project-bridge-persp-name-prefix + (file-name-nondirectory + (directory-file-name + (if (fboundp 'project-root) + (project-root (project-current)) + (car (project-roots (project-current)))))))))) + (when persp + (persp-add-buffer b persp nil nil) + persp)))))) + +(defun persp-mode-project-bridge-hook-switch (&rest _args) + "Switch to a perspective when hook is activated." + (let ((persp + (persp-mode-project-bridge-find-perspective-for-buffer + (current-buffer)))) + (when persp + (persp-frame-switch (persp-name persp))))) + +(defun persp-mode-project-bridge-find-perspectives-for-all-buffers () + "Find perspectives for all buffers." + (when persp-mode-project-bridge-mode + (mapc #'persp-mode-project-bridge-find-perspective-for-buffer + (buffer-list)))) + +(defun persp-mode-project-bridge-kill-perspectives () + "Kill all bridge perspectives." + (when persp-mode + (mapc #'persp-kill + (mapcar #'persp-name + (cl-delete-if-not + (apply-partially + #'persp-parameter + 'persp-mode-project-bridge) + (persp-persps)))))) + +(defvar persp-mode-project-bridge-switch-hooks + (list 'find-file-hook 'dired-mode-hook 'vc-dir-mode-hook 'eshell-mode-hook)) + +;;;###autoload +(define-minor-mode persp-mode-project-bridge-mode + "`persp-mode' and `project.el' integration. +Creates perspectives for project.el projects." + :require 'persp-mode-project-bridge + :group 'persp-mode-project-bridge + :init-value nil + :global t + + (if persp-mode-project-bridge-mode + (if persp-mode + (progn + ;; Add hooks + (add-hook 'persp-mode-hook + (lambda () + (unless persp-mode + (persp-mode-project-bridge-mode -1)))) + (dolist (hook persp-mode-project-bridge-switch-hooks) + (add-hook hook #'persp-mode-project-bridge-hook-switch))) + (message "You can not enable persp-mode-project-bridge-mode \ +unless persp-mode is active.") + (setq persp-mode-project-bridge-mode nil)) + ;; Remove hooks + (dolist (hook persp-mode-project-bridge-switch-hooks) + (remove-hook hook #'persp-mode-project-bridge-hook-switch)))) + +(provide 'persp-mode-project-bridge) + +;;; persp-mode-project-bridge.el ends here