~jakob/exwm-buffer-groups

exwm-buffer-groups/exwm-buffer-groups.el -rw-r--r-- 5.2 KiB
853de6d3 — Jakob L. Kreuze Implement #'exwm-buffer-groups-kill-buffer 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
;;; exwm-buffer-groups.el --- Buffer grouping for EXWM workspaces. -*- lexical-binding: t; -*-

;; Copyright (C) 2019 Jakob L. Kreuze

;; Author: Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
;; Version: 1.0
;; Package-Requires (cl-lib exwm)
;; Keywords: frames
;; URL: https://git.sr.ht/~jakob/exwm-buffer-groups

;; 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 <http://www.gnu.org/licenses/>.

;;; Commentary:

;; The default behavior of EXWM is to make buffers containing X windows
;; accessible only from the workspace they were created in. This is a useful
;; feature, but introduces some level of inconsistency as this does not apply to
;; normal buffers. exwm-buffer-groups aims to change this by associating all
;; buffers with a workspace.

;;; Code:

(require 'cl-lib)
(require 'exwm)

(defun exwm-buffer-groups-default-buffers ()
  "Initial list of buffers for a workspace."
  (if (get-buffer "*scratch*")
      (list (get-buffer "*scratch*"))
    nil))

(defvar exwm-buffer-groups-buffers
  (make-vector exwm-workspace-number (exwm-buffer-groups-default-buffers))
  "Vector containing lists of associated buffers for each workspace.")

(defun exwm-buffer-groups--buffer-seen-p (buffer)
  "Whether or not BUFFER is contained in `exwm-buffer-groups-buffers'."
  (reduce #'(lambda (x y) (or x y))
          (map 'list
               #'(lambda (workspace)
                   (memq buffer workspace))
               exwm-buffer-groups-buffers)))

(defun exwm-buffer-groups--remove-buffers ()
  "Removes dead buffers from `exwm-buffer-groups-buffers'."
  (setq exwm-buffer-groups-buffers
        (map 'vector
             #'(lambda (buffers) (cl-remove-if-not #'buffer-live-p buffers))
             exwm-buffer-groups-buffers)))

(defun exwm-buffer-groups--add-buffers ()
  "Adds unseen buffers to `exwm-buffer-groups-buffers'.
Any unseen buffers are added to the entry corresponding to the
current workspace."
  (dolist (buffer (buffer-list))
    (unless (exwm-buffer-groups--buffer-seen-p buffer)
      (push buffer (elt exwm-buffer-groups-buffers exwm-workspace-current-index)))))

(defun exwm-buffer-groups-update ()
  "Updates `exwm-buffer-groups-buffers' to reflect the buffer list."
  (exwm-buffer-groups--remove-buffers)
  (exwm-buffer-groups--add-buffers))

(defun exwm-buffer-groups-switch-buffer (buffer-or-name)
  "Display buffer BUFFER-OR-NAME in the selected window.
If called interactively, read the buffer name using
`completing-read', completing only on buffers in the current
workspace."
  (interactive
   (list
    (let ((buffers-in-workspace (map 'list
                                     #'buffer-name
                                     (elt exwm-buffer-groups-buffers
                                          exwm-workspace-current-index)))
          (current-buffer (buffer-name (other-buffer (current-buffer)))))
      ;; Clean up so that "nil" isn't showing up in the list.
      (exwm-buffer-groups--remove-buffers)
      (completing-read "Switch to buffer: " buffers-in-workspace
                       nil nil nil nil current-buffer))))
  (switch-to-buffer buffer-or-name))

(defun exwm-buffer-groups-kill-buffer (buffer-or-name)
  "Kill the buffer specified by BUFFER-OR-NAME.
If called interactively, read the buffer name using
`completing-read', completing only on buffers in the current
workspace."
  (interactive
   (list
    (let ((buffers-in-workspace (map 'list
                                     #'buffer-name
                                     (elt exwm-buffer-groups-buffers
                                          exwm-workspace-current-index)))
          (current-buffer (buffer-name (other-buffer (current-buffer)))))
      ;; Clean up so that "nil" isn't showing up in the list.
      (exwm-buffer-groups--remove-buffers)
      (completing-read "Switch to buffer: " buffers-in-workspace
                       nil nil nil nil current-buffer))))
  (kill-buffer buffer-or-name))

(defun exwm-buffer-groups-move (nth)
  "Moves the current buffer to the NTH workspace."
  (interactive
   (list
    (exwm-workspace--position
     (exwm-workspace--prompt-for-workspace "Move workspace to: "))))
  ;; Remove the buffer from the current workspace.
  (setf (elt exwm-buffer-groups-buffers exwm-workspace-current-index)
        (remove (current-buffer)
                (elt exwm-buffer-groups-buffers exwm-workspace-current-index)))
  ;; Add it to the NTH workspace.
  (push (current-buffer) (elt exwm-buffer-groups-buffers nth))
  ;; Switch out of the buffer.
  (set-window-dedicated-p nil nil)
  (switch-to-prev-buffer nil 'bury))

(add-hook 'after-change-major-mode-hook #'exwm-buffer-groups-update)

(provide 'exwm-buffer-groups)
;;; exwm-buffer-groups.el ends here