Remove `exwm-worspace-number'

No longer fill initial workspace list, nor limit the number of
workspaces to `exwm-worspace-number'.

Users are free to create as many as they like by hitting 'C-x 5 2' or
running `make-frame'.

The initial workspace list can be set up by creating frames in a
configuration file.  For example, to start up with 4 workspaces:

    (dolist (i 3)
      (make-frame))

The interactive workspace switcher is improved to support selecting
workspaces with a many-digits position.

	* exwm-workspace.el (exwm-workspace-number): Remove variable, as
	we no longer have a fixed number of workspaces.
	(exwm-workspace--switch-map)
	(exwm-workspace--switch-map-nth-prefix)
	(exwm-workspace--switch-map-select-nth): Improve support for
	selecting workspaces with multiple-digit positions (e.g. workspace
	number 12).
	(exwm-workspace--add-frame-as-workspace, exwm-workspace--init):
	Remove limit on number of workspaces.
	(exwm-workspace--init): Stop creating workspaces at startup.
	* exwm-config.el (exwm-config-default): Bind keys to namespaces
	0-9 in the default configuration.
This commit is contained in:
Adrián Medraño Calvo 2016-07-17 12:00:00 +00:00
parent 0fbc725de1
commit d0797d03de
2 changed files with 64 additions and 37 deletions

View file

@ -39,7 +39,7 @@
;; 's-w': Switch workspace ;; 's-w': Switch workspace
(exwm-input-set-key (kbd "s-w") #'exwm-workspace-switch) (exwm-input-set-key (kbd "s-w") #'exwm-workspace-switch)
;; 's-N': Switch to certain workspace ;; 's-N': Switch to certain workspace
(dotimes (i exwm-workspace-number) (dotimes (i 10)
(exwm-input-set-key (kbd (format "s-%d" i)) (exwm-input-set-key (kbd (format "s-%d" i))
`(lambda () (interactive) (exwm-workspace-switch ,i)))) `(lambda () (interactive) (exwm-workspace-switch ,i))))
;; 's-&': Launch application ;; 's-&': Launch application

View file

@ -27,7 +27,6 @@
(require 'exwm-core) (require 'exwm-core)
(defvar exwm-workspace-number 4 "Number of workspaces (1 ~ 10).")
(defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).") (defvar exwm-workspace--list nil "List of all workspaces (Emacs frames).")
(defvar exwm-workspace--current nil "Current active workspace.") (defvar exwm-workspace--current nil "Current active workspace.")
(defvar exwm-workspace-current-index 0 "Index of current active workspace.") (defvar exwm-workspace-current-index 0 "Index of current active workspace.")
@ -63,12 +62,7 @@ NIL if FRAME is not a workspace"
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map [t] (lambda () (interactive))) (define-key map [t] (lambda () (interactive)))
(dotimes (i 10) (dotimes (i 10)
(define-key map (int-to-string i) (define-key map (int-to-string i) #'exwm-workspace--switch-map-nth-prefix))
`(lambda ()
(interactive)
(when (< ,i (exwm-workspace--count))
(goto-history-element ,(1+ i))
(exit-minibuffer)))))
(define-key map "\C-a" (lambda () (interactive) (goto-history-element 1))) (define-key map "\C-a" (lambda () (interactive) (goto-history-element 1)))
(define-key map "\C-e" (lambda () (define-key map "\C-e" (lambda ()
(interactive) (interactive)
@ -318,6 +312,48 @@ Value nil means to use the default position which is fixed at bottom, while
:stack-mode xcb:StackMode:Above)) :stack-mode xcb:StackMode:Above))
(set-frame-width exwm-workspace--minibuffer width nil t))) (set-frame-width exwm-workspace--minibuffer width nil t)))
(defun exwm-workspace--switch-map-nth-prefix (&optional prefix-digits)
"Allow selecting a workspace by number.
PREFIX-DIGITS is a list of the digits introduced so far."
(interactive)
(let* ((ev (this-command-keys-vector))
(off (1- (length ev)))
(k (elt ev off))
;; 0 is ASCII 48.
(d (- k 48))
;; Convert prefix-digits to number. For example, '(2 1) to 120.
(o 1)
(pn (apply #'+ (mapcar (lambda (x)
(setq o (* 10 o))
(* o x))
prefix-digits)))
(n (+ pn d))
(num-workspaces (exwm-workspace--count)))
(if (= (length prefix-digits) ; Go ahead if there are enough
(floor (log num-workspaces 10))) ; digits to select any workspace.
(exwm-workspace--switch-map-select-nth n)
(set-transient-map
(let ((map (make-sparse-keymap))
(cmd `(lambda ()
(interactive)
(exwm-workspace--switch-map-nth-prefix ',(cons d prefix-digits))
)))
(dotimes (i 10)
(define-key map (int-to-string i) cmd))
;; Accept
(define-key map [return]
`(lambda ()
(interactive)
(exwm-workspace--switch-map-select-nth ,n)))
map)))))
(defun exwm-workspace--switch-map-select-nth (n)
"Select Nth workspace."
(interactive)
(goto-history-element (1+ n))
(exit-minibuffer))
(defvar exwm-workspace-switch-hook nil (defvar exwm-workspace-switch-hook nil
"Normal hook run after switching workspace.") "Normal hook run after switching workspace.")
@ -854,9 +890,6 @@ before it."
(defun exwm-workspace--add-frame-as-workspace (frame) (defun exwm-workspace--add-frame-as-workspace (frame)
"Configure frame FRAME to be treated as a workspace." "Configure frame FRAME to be treated as a workspace."
(cond (cond
((>= (exwm-workspace--count) exwm-workspace-number)
(delete-frame frame)
(user-error "[EXWM] Too many workspaces: maximum is %d" exwm-workspace-number))
((exwm-workspace--workspace-p frame) ((exwm-workspace--workspace-p frame)
(exwm--log "Frame `%s' is already a workspace" frame)) (exwm--log "Frame `%s' is already a workspace" frame))
((not (display-graphic-p frame)) ((not (display-graphic-p frame))
@ -1010,31 +1043,23 @@ applied to all subsequently created X frames."
(defun exwm-workspace--init () (defun exwm-workspace--init ()
"Initialize workspace module." "Initialize workspace module."
(cl-assert (and (< 0 exwm-workspace-number) (>= 10 exwm-workspace-number)))
;; Prevent unexpected exit ;; Prevent unexpected exit
(setq confirm-kill-emacs #'exwm-workspace--confirm-kill-emacs) (setq confirm-kill-emacs #'exwm-workspace--confirm-kill-emacs)
(let ((initial-workspaces (frame-list))) (let ((initial-workspaces (frame-list)))
(if (not (exwm-workspace--minibuffer-own-frame-p)) (if (not (exwm-workspace--minibuffer-own-frame-p))
;; Initialize workspaces with minibuffers. ;; Initialize workspaces with minibuffers.
(progn (when (< 1 (length initial-workspaces))
(when (< 1 (exwm-workspace--count)) ;; Exclude the initial frame.
;; Exclude the initial frame. (dolist (i initial-workspaces)
(dolist (i initial-workspaces) (unless (frame-parameter i 'window-id)
(unless (frame-parameter i 'window-id) (setq initial-workspaces (delq i initial-workspaces))))
(setq initial-workspaces (delq i initial-workspaces)))) (setq exwm-workspace--client
(cl-assert (= 1 (length initial-workspaces))) (frame-parameter (car exwm-workspace--list) 'client))
(setq exwm-workspace--client (let ((f (car initial-workspaces)))
(frame-parameter (car exwm-workspace--list) 'client)) ;; Remove the possible internal border.
(let ((f (car initial-workspaces))) (set-frame-parameter f 'internal-border-width 0)
;; Remove the possible internal border. ;; Prevent user from deleting the first frame by accident.
(set-frame-parameter f 'internal-border-width 0) (set-frame-parameter f 'client nil)))
;; Prevent user from deleting this frame by accident.
(set-frame-parameter f 'client nil)))
;; Create remaining frames.
(dotimes (_ (1- exwm-workspace-number))
(nconc initial-workspaces
(list (make-frame '((window-system . x)
(internal-border-width . 0)))))))
;; Initialize workspaces without minibuffers. ;; Initialize workspaces without minibuffers.
(setq exwm-workspace--minibuffer (setq exwm-workspace--minibuffer
(make-frame '((window-system . x) (minibuffer . only) (make-frame '((window-system . x) (minibuffer . only)
@ -1092,12 +1117,14 @@ applied to all subsequently created X frames."
(setq exwm-workspace--timer (setq exwm-workspace--timer
(run-with-idle-timer 0 t #'exwm-workspace--on-echo-area-dirty)) (run-with-idle-timer 0 t #'exwm-workspace--on-echo-area-dirty))
(add-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear) (add-hook 'echo-area-clear-hook #'exwm-workspace--on-echo-area-clear)
;; Create workspace frames. ;; Recreate frames with the external minibuffer set.
(dotimes (_ exwm-workspace-number) (setq initial-workspaces
(push (make-frame `((window-system . x) (mapcar
(internal-border-width . 0) (lambda (_)
(client . nil))) (make-frame `((window-system . x)
exwm-workspace--list)) (internal-border-width . 0)
(client . nil))))
initial-workspaces))
;; The default behavior of `display-buffer' (indirectly called by ;; The default behavior of `display-buffer' (indirectly called by
;; `minibuffer-completion-help') is not correct here. ;; `minibuffer-completion-help') is not correct here.
(cl-pushnew '(exwm-workspace--display-buffer) display-buffer-alist (cl-pushnew '(exwm-workspace--display-buffer) display-buffer-alist