From 57650131c63a95fee8312eda078ced844fde9765 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Wed, 8 Dec 2021 13:17:28 +0300 Subject: [PATCH] feat: fix persp-set-buffer & perspective-exwm-assign-window --- README.org | 35 ++++++++++++++++++++----- perspective-exwm.el | 64 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/README.org b/README.org index 4e24e96..ca11b73 100644 --- a/README.org +++ b/README.org @@ -20,12 +20,13 @@ The package provides a minor mode, =perspective-exwm-mode=, which is meant to be #+end_src * Usage and details -- =perspective-exwm-mode= +- =perspective-exwm-mode=\\ The mode does a couple of things: - advises away a bug with half-killing the current perspective when closing a floating window. I haven't tested this as thoroughly, so run =M-x perspective-exwm-revive-perspectives= if the problem arises anyway. - - adjusts the name of the inital perspective in the new workspace. It tries to get the name from the =perspective-exwm-override-initial-name= variable and falls back to `main-`. + - fixes a bug with running =persp-set-buffer= on an EXWM buffer that was moved between workspaces by advising =persp-buffer-in-other-p=. + - adjusts the name of the inital perspective in the new workspace. It tries to get the name from the =perspective-exwm-override-initial-name= variable and fallbacks to =main-=. - I have the following in my configuration: + For the last point, I have the following in my configuration: #+begin_src emacs-lisp (setq perspective-exwm-override-initial-name '((0 . "misc") @@ -36,7 +37,7 @@ The package provides a minor mode, =perspective-exwm-mode=, which is meant to be #+end_src This also serves a purpose, because otherwise there are issues with multiple perspectives sharing the same scratch buffer. -- =M-x perspective-exwm-cycle-exwm-buffers-forward=, =perspective-exwm-cycle-exwm-buffers-backward= +- =M-x perspective-exwm-cycle-exwm-buffers-forward=, =perspective-exwm-cycle-exwm-buffers-backward=\\ Cycles EXWM buffers in the current perspective. [[./img/cycle-buffers.png]] @@ -45,11 +46,31 @@ The package provides a minor mode, =perspective-exwm-mode=, which is meant to be Set =perspective-exwm-get-exwm-buffer-name= to customize the displayed name, by default it's =exwm-class-name=. -- =M-x perspective-exwm-switch-perspective= +- =M-x perspective-exwm-switch-perspective=\\ Select a perspective from the list of all perspectives on all workspaces. [[./img/switch-perspective.png]] -- =M-x perspective-exwm-copy-to-workspace= +- =M-x perspective-exwm-copy-to-workspace=\\ Copy the current perspective to another EXWM workspace. -- =M-x perspective-exwm-move-to-workspace= +- =M-x perspective-exwm-move-to-workspace=\\ Move the current perspective to another EXWM workspace. +- =perspective-exwm-assign-windows=\\ + A handy function to move the current window to a given workspace and/or perspective. Example usage: + #+begin_src emacs-lisp + (defun my/exwm-configure-window () + (interactive) + (pcase exwm-class-name + ((or "Firefox" "Nightly") + (perspective-exwm-assign-window + :workspace-index 2 + :persp-name "browser")) + ("Alacritty" + (perspective-exwm-assign-window + :persp-name "term")) + ((or "VK" "Slack" "Discord" "TelegramDesktop") + (perspective-exwm-assign-window + :workspace-index 3 + :persp-name "comms")))) + + (add-hook 'exwm-manage-finish-hook #'my/exwm-configure-window) + #+end_src diff --git a/perspective-exwm.el b/perspective-exwm.el index 8fedc06..89f6a56 100644 --- a/perspective-exwm.el +++ b/perspective-exwm.el @@ -1,6 +1,7 @@ ;;; perspective-exwm.el --- Better integration for perspective.el and EXWM -*- lexical-binding: t -*- ;; Copyright (C) 2021 Korytov Pavel +;; Copyright (C) 2008-2020 Natalie Weizenbaum ;; Author: Korytov Pavel ;; Maintainer: Korytov Pavel @@ -234,7 +235,8 @@ Overrides `persp-initial-frame-name' according to (apply fun args))) (defun perspective-exwm--after-exwm-init () - "Create perspectives in workspaces in accordance with `perspective-exwm-override-initial-name'. + "Create perspectives in workspaces in accordance with + `perspective-exwm-override-initial-name'. This is meant to be run from `exwm-init-hook'." (cl-loop for workspace-index from 0 to (exwm-workspace--count) @@ -248,6 +250,31 @@ This is meant to be run from `exwm-init-hook'." (unless (string-equal current-name target-name) (persp-switch target-name) (persp-kill current-name)))))) + + +(cl-defun perspective-exwm--persp-buffer-in-other-p (buffer) + "Returns nil if BUFFER is only in the current perspective. +Otherwise, returns (FRAME . NAME), the frame and name of another +perspective that has the buffer. + +Prefers perspectives in the selected frame. + +This version of the function also excludes EXWM buffers from +appearing to be in other frames, because an EXWM buffer can be +only in one frame." + (cl-loop for frame in + (sort (frame-list) + (lambda (_frame1 frame2) (not (eq frame2 (selected-frame))))) + do (cl-loop for persp being the hash-values of (perspectives-hash frame) + if (and (not (and (equal frame (selected-frame)) + (equal (persp-name persp) (persp-name (persp-curr frame))))) + (not (and (not (equal frame (selected-frame))) + (eq (buffer-local-value 'major-mode buffer) 'exwm-mode))) + (memq buffer (persp-buffers persp))) + do (cl-return-from perspective-exwm--persp-buffer-in-other-p + (cons frame (persp-name persp))))) + nil) + ;;;###autoload (defun perspective-exwm-revive-perspectives () "Make perspectives in the current frame not killed." @@ -262,6 +289,35 @@ This is meant to be run from `exwm-init-hook'." (when to-switch (persp-switch (persp-name to-switch))))) +;;;###autoload +(cl-defun perspective-exwm-assign-window (&key workspace-index persp-name) + "Move current the buffer to another workspace and/or perspective. + +WORKSPACE-INDEX is index of the workspace as in +`exwm-workspace--list'. PERSP-NAME is the name of the target +perspective. + +The function is useful to be ran from `exwm-manage-finish-hook', +e.g. like this: +(defun my/exwm-configure-window () + (interactive) + (pcase exwm-class-name + ((or \"Firefox\" \"Nightly\") (perspective-exwm-assign-window + :workspace-index 2 + :persp-name \"browser\")))) +" + (let ((buffer-name (buffer-name)) + (buffer (current-buffer))) + (when (and workspace-index (not (= workspace-index exwm-workspace-current-index))) + (exwm-workspace-move-window workspace-index)) + (when persp-name + (with-selected-frame (nth (or workspace-index + exwm-workspace-current-index) + exwm-workspace--list) + (with-perspective persp-name + (persp-set-buffer buffer)) + (persp-switch-to-buffer buffer))))) + ;;;###autoload (define-minor-mode perspective-exwm-mode "A minor mode for intergrating perspective.el and EXWM. @@ -271,6 +327,8 @@ The mode does a couple of things: a floating window. I haven't tested this as thoroughly, so run `perspective-exwm-revive-perspectives' if the problem arises anyway. + - fixes a bug with running `persp-set-buffer' on an EXWM buffer that + was moved between workspaces by advising `persp-buffer-in-other-p'. - adjusts the name of the inital perspective in the new workspace. It tries to get the name from the `perspective-exwm-override-initial-name' variable and falls back to @@ -293,6 +351,8 @@ inital workspaces are created with the new perspective names." :around #'perspective-exwm--init-frame-around) (advice-add #'exwm-workspace-switch-create :around #'perspective-exwm--workspace-switch-create-around) + (advice-add #'persp-buffer-in-other-p + :override #'perspective-exwm--persp-buffer-in-other-p) (add-hook 'exwm-init-hook #'perspective-exwm--after-exwm-init)) (advice-remove #'persp-delete-frame #'perspective-exwm--delete-frame-around) @@ -300,6 +360,8 @@ inital workspaces are created with the new perspective names." #'perspective-exwm--init-frame-around) (advice-remove #'exwm-workspace-switch-create #'perspective-exwm--workspace-switch-create-around) + (advice-remove #'persp-buffer-in-other-p + #'perspective-exwm--persp-buffer-in-other-p) (remove-hook 'exwm-init-hook #'perspective-exwm--after-exwm-init)))) (provide 'perspective-exwm)