emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/swsw c5f85632d9 3/3: Rework display functions


From: ELPA Syncer
Subject: [nongnu] elpa/swsw c5f85632d9 3/3: Rework display functions
Date: Sat, 17 Sep 2022 12:59:09 -0400 (EDT)

branch: elpa/swsw
commit c5f85632d970b67a7f4790e02c1c8b2177165a54
Author: Daniel Semyonov <daniel@dsemy.com>
Commit: Daniel Semyonov <daniel@dsemy.com>

    Rework display functions
    
    * swsw.el (swsw-minimum): New user option.
    (swsw-define-window-command): New macro.
    (swsw-select, swsw-delete): Redefine using 'swsw-define-window-command'.
    (swsw-display-buffer-selected-window): New action function for buffer
    display.
    (swsw-delete-other, swsw-split-window-below, swsw-split-window-right):
    (swsw-selected-window-prefix, swsw-swap): New window command.
    (swsw-select-minibuffer): Simplify slightly.
    (swsw-command-map): Add bindings for new commands.
    * README (Usage):
    * swsw.texi (Usage): Document new commands.
    (Window commands): Reword the opening paragraph.  Document new option
    and macro.  Slightly modify documentation for 'swsw-run-window-command'.
    * NEWS: Document changes.
---
 NEWS      |  12 +++++
 README    |  19 +++++--
 swsw.el   | 178 +++++++++++++++++++++++++++++++++++++++++++++++---------------
 swsw.texi | 113 +++++++++++++++++++++++++++------------
 4 files changed, 244 insertions(+), 78 deletions(-)

diff --git a/NEWS b/NEWS
index b129b4dbdb..ba5ad9074b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,18 @@
 swsw NEWS -- history of user-visible changes. -*- mode: outline -*-
 See the end of the file for an explanation of the versioning scheme.
 
+* 2.3
+
+** Rework window commands
+A new macro has been added ('swsw-define-window-command') which
+greatly simplifies the creation of window commands; existing commands
+now use it and 5 new window commands have been added:
+'swsw-delete-other', 'swsw-split-window-below' and
+'swsw-split-window-right', which correspond to the built-in commands,
+'swsw-selected-window-prefix', which displays the buffer of the next
+command in the selected window, and 'swsw-swap' which swaps the state
+of the current window and the selected window.
+
 * 2.2
 
 ** Rework display functions
diff --git a/README b/README
index 64d01da321..3c95819b21 100644
--- a/README
+++ b/README
@@ -43,12 +43,25 @@ When swsw-mode is active:
 - Window IDs are assigned to all windows on all frames except for
   the minibuffer (by default, see ‘swsw-scope’).
 
-C-x o ID switches focus to the window which corresponds to ID.
-
-C-x o m switches focus to the minibuffer if it's active.
+C-x o ID   switches focus to the window which corresponds to ID.
 
 C-x o 0 ID deletes the window which corresponds to ID.
 
+C-x o 1 ID makes the window which corresponds to ID the sole window of
+           its frame.
+
+C-x o 2 ID splits the window which corresponds to ID from below.
+
+C-x o 3 ID splits the window which corresponds to ID from the right.
+
+C-x 0 4 ID displays the buffer of the next command in the window which
+           corresponds to ID.
+
+C-x 0 t ID swaps the states of the current window and the window which
+           corresponds to ID.
+
+C-x o m    switches focus to the minibuffer if it's active.
+
 More commands can be added through ‘swsw-command-map’:
 
 (define-key swsw-command-map (kbd "z") #'my-command)
diff --git a/swsw.el b/swsw.el
index d12f350a91..c7f5ce9ac7 100644
--- a/swsw.el
+++ b/swsw.el
@@ -48,12 +48,25 @@
 ;;   the minibuffer (by default, see `swsw-scope').
 ;; - `other-window' (C-x o by default) is remapped to `swsw-select'.
 ;;
-;; C-x o ID switches focus to the window which corresponds to ID.
-;;
-;; C-x o m switches focus to the minibuffer if it's active.
+;; C-x o ID   switches focus to the window which corresponds to ID.
 ;;
 ;; C-x o 0 ID deletes the window which corresponds to ID.
 ;;
+;; C-x o 1 ID makes the window which corresponds to ID the sole window of
+;;            its frame.
+;;
+;; C-x o 2 ID splits the window which corresponds to ID from below.
+;;
+;; C-x o 3 ID splits the window which corresponds to ID from the right.
+;;
+;; C-x 0 4 ID displays the buffer of the next command in the window which
+;;            corresponds to ID.
+;;
+;; C-x 0 t ID swaps the states of the current window and the window which
+;;            corresponds to ID.
+;;
+;; C-x o m    switches focus to the minibuffer if it's active.
+;;
 ;; More commands can be added through `swsw-command-map':
 ;;
 ;; (define-key swsw-command-map (kbd "z") #'my-command)
@@ -117,6 +130,13 @@ This list should contain at least two characters."
   :risky t
   :package-version '(swsw . 1.1))
 
+(defcustom swsw-minimum 3
+  "Minimum number of tracked windows for which interactive selection occurs."
+  :link '(info-link "(swsw) Window Commands")
+  :type 'integer
+  :risky t
+  :package-version '(swsw . 2.3))
+
 (define-obsolete-variable-alias 'swsw-display-function
   'swsw-display-lighter "version 2.2 of the swsw package"
   "Function used to display the ID of each window.
@@ -327,52 +347,128 @@ exit."
                      (lambda ()
                        (run-hooks 'swsw-after-command-hook))))
 
-(defun swsw-select ()
-  "Start window selection.
-If less than three windows have been assigned an ID, switch to the
-window returned by `next-window'.
-Otherwise, window selection allows either choosing a window by its ID
-\(switching to it), or using a window manipulation command.
-This command is intended to be used only when swsw mode is enabled."
-  (declare (modes swsw-mode)
-           (interactive-only t))
-  (interactive)
-  (if (< swsw-window-count 3)
-      (select-window (next-window nil nil (swsw--get-scope)))
-    (swsw-run-window-command #'select-window)))
+(defmacro swsw-define-window-command (name args &rest body)
+  "Define NAME as a window command with DOCSTRING as its documentation string.
+
+Inside BODY, WINDOW and PREFIX (symbols) are bound to the selected
+window and the raw prefix argument, respectively.
+If PREFIX is omitted or nil, the resulting command will not accept a
+prefix argument.
+
+If MINIBUFFER is non-nil, allow the minibuffer to be selected by
+`next-window' (when there are less than `swsw-minimum' tracked windows).
+
+For more information, see info node `(swsw) Window Commands'.
+
+\(fn NAME (WINDOW [PREFIX] [MINIBUFFER]) [DOCSTRING] BODY...)"
+  (declare (debug (&define [&name symbolp] listp [&optional stringp] def-body))
+           (doc-string 3) (indent defun))
+  (let* ((docstring (car body)) (window (car args))
+         (prefix (cadr args)) (minibuffer (caddr args)))
+    `(defun ,name ,(and prefix `(,prefix))
+       ,(when (stringp docstring) (format "%s
+
+If less than `swsw-minimum' windows have been assigned an ID,
+use the window returned by `next-window' (according to the
+value of `swsw-scope'%s).
+Otherwise, either a window is selected using its ID or a separate
+window command is chosen.
+
+  This is a window command, intended to be used only when simple
+  window switching is enabled; for more information, see info node
+  `(swsw) Window Commands'.
+" docstring (if minibuffer "" ", excluding the minibuffer")))
+       (declare (modes swsw-mode)
+                (interactive-only t))
+       (interactive ,(and prefix "P"))
+       (if-let ((f (lambda (,window)
+                     ,@body))
+                ((>= swsw-window-count swsw-minimum)))
+           (swsw-run-window-command f)
+         (funcall f (next-window nil (unless ,minibuffer 'exclude)
+                                 (swsw--get-scope)))))))
+
+(swsw-define-window-command swsw-select (window nil t)
+  "Select a window."
+  (select-window window))
+
+(swsw-define-window-command swsw-delete (window)
+  "Delete a window."
+  (delete-window window))
+
+(swsw-define-window-command swsw-delete-other (window)
+  "Make a window the sole window of its frame."
+  (delete-other-windows window))
+
+(swsw-define-window-command swsw-split-window-below (window size)
+  "Split a window from below.
+If optional argument SIZE is omitted or nil, both windows get the same
+height, or close to it.  If SIZE is positive, the upper window gets
+SIZE lines.  If SIZE is negative, the lower window gets -SIZE lines."
+  (split-window-below (and size (prefix-numeric-value size)) window))
+
+(swsw-define-window-command swsw-split-window-right (window size)
+  "Split a window from the right.
+If optional argument SIZE is omitted or nil, both windows get the same
+width, or close to it.  If SIZE is positive, the left-hand window gets
+SIZE columns.  If SIZE is negative, the right-hand window gets -SIZE
+columns.  Here, SIZE includes the width of the window’s scroll bar; if
+there are no scroll bars, it includes the width of the divider column
+to the window’s right, if any."
+  (split-window-right (and size (prefix-numeric-value size)) window))
+
+(defun swsw-display-buffer-selected-window (buffer alist)
+  "Display BUFFER in the selected (through swsw) window.
+ALIST is an association list of action symbols and values.  See
+Info node `(elisp) Buffer Display Action Alists' for details of
+such alists.
+
+The function fails if ALIST has no `window' element or its value isn't a
+live window, or if it is a minibuffer window or is dedicated to another
+buffer; in that case return nil.
+Otherwise, return the value of the `window' element.
+
+This is an action function for buffer display, see Info
+node ‘(elisp) Buffer Display Action Functions’.  It should be
+called only by ‘display-buffer’ or a function directly or
+indirectly called by the latter."
+  (let ((window (cdr (assq 'window alist))))
+    (unless (or (not (windowp window))
+                (window-minibuffer-p window)
+                (window-dedicated-p window))
+      (window--display-buffer buffer window 'reuse alist))))
+
+(swsw-define-window-command swsw-selected-window-prefix (window)
+  "Display the buffer of the next command in a window."
+  (display-buffer-override-next-command
+   (lambda (buffer alist)
+     (setq alist (append `((window . ,window)) alist))
+     (cons (swsw-display-buffer-selected-window buffer alist) 'reuse))
+   nil (format "[swsw-window-%s]" (window-parameter window 'swsw-id)))
+  (message "Display next command buffer in the selected window..."))
+
+(swsw-define-window-command swsw-swap (window)
+  "Swap the states of a window and the currently selected window."
+  (window-swap-states nil window)
+  (and (eq (current-buffer) (window-buffer window)) (swsw--update)))
 
 (defun swsw-select-minibuffer ()
-  "Select the active minibuffer window (if it exists).
-This command is intended to be used only when swsw mode is enabled."
-  (declare (modes swsw-mode)
-           (interactive-only t))
+  "Select the active minibuffer window (if it exists)."
+  (declare (modes swsw-mode))
   (interactive)
-  (if-let ((window (active-minibuffer-window)))
-      (select-window window)
-    (user-error "There is no active minibuffer window")))
-
-(defun swsw-delete ()
-  "Start window deletion.
-If less than three windows have been assigned an ID, delete the window
-returned by `next-window'.
-Otherwise, window deletion allows either choosing a window by its ID
-\(deleting it), or using a window manipulation command.
-This command is intended to be used only when swsw mode is enabled."
-  (declare (modes swsw-mode)
-           (interactive-only t))
-  (interactive)
-  (if-let (((< swsw-window-count 3))
-           (window (next-window nil nil (swsw--get-scope))))
-      (unless (or (minibufferp (window-buffer window))
-                  (minibufferp)) ; Selected window.
-        (delete-window window))
-    (swsw-run-window-command #'delete-window)))
+  (select-window (or (active-minibuffer-window)
+                     (user-error "There is no active minibuffer window"))))
 
 (defvar swsw-command-map
   (let ((map (make-sparse-keymap)))
     (define-key map [?o] #'swsw-select)
-    (define-key map [?m] #'swsw-select-minibuffer)
     (define-key map [?0] #'swsw-delete)
+    (define-key map [?1] #'swsw-delete-other)
+    (define-key map [?2] #'swsw-split-window-below)
+    (define-key map [?3] #'swsw-split-window-right)
+    (define-key map [?4] #'swsw-selected-window-prefix)
+    (define-key map [?t] #'swsw-swap)
+    (define-key map [?m] #'swsw-select-minibuffer)
     map)
   "Key map for window commands.
 This key map is set as the parent of `swsw--id-map' during ID
diff --git a/swsw.texi b/swsw.texi
index b6720058f8..7ed876c76c 100644
--- a/swsw.texi
+++ b/swsw.texi
@@ -142,28 +142,53 @@ lighters of the form @code{<ID>} (by default, @xref{ID 
display}), and
 
 @table @asis
 @kindex C-x o
+@kindex C-x o o
 @cindex swsw-select
-@item @kbd{C-x o}
-Start window selection (@code{swsw-select}).
-This command sets a transient key map in which several window
-commands are defined, and window IDs can be selected.
-Selecting a window ID (by pressing @kbd{ID}) will switch to the window
-corresponding to it.
+@item @kbd{C-x o ID}, @kbd{C-x o o ID}
+Select the window corresponding to ID in the current scope
+(@xref{Customization}) (@code{swsw-select}).
+
+@kindex C-x o 0
+@cindex swsw-delete
+@item @kbd{C-x o 0 ID}
+Delete the window corresponding to ID in the current scope 
(@code{swsw-delete}).
+
+@kindex C-x o 1
+@cindex swsw-delete-other
+@item @kbd{C-x o 1 ID}
+Make the window corresponding to ID the in the current scope the sole
+window of its frame (@code{swsw-delete-other}).
+
+@kindex C-x o 2
+@cindex swsw-split-window-below
+@item @kbd{C-x o 2 ID}
+Split the window corresponding to ID in the current scope from below
+(@code{swsw-split-window-below}).  This window command accepts a
+prefix argument (with the same semantics as @code{split-window-below}).
+
+@kindex C-x o 3
+@cindex swsw-split-window-right
+@item @kbd{C-x o 3 ID}
+Split the window corresponding to ID in the current scope from the right
+(@code{swsw-split-window-right}).  This window command accepts a
+prefix argument (with the same semantics as @code{split-window-right}).
+
+@kindex C-x o 4
+@cindex swsw-selected-window-prefix
+@item @kbd{C-x o 4 ID}
+Display the buffer of the next command in the window corresponding to
+ID in the current scope (@code{swsw-delete}).
+
+@kindex C-x o t
+@cindex swsw-swap
+@item @kbd{C-x o t ID}
+Swap the states of the current window and the window corresponding to
+ID in the current scope (@code{swsw-delete}).
 
 @kindex C-x o m
 @cindex swsw-select-minibuffer
 @item @kbd{C-x o m}
-Switch focus the minibuffer if it's active
-(@code{swsw-select-minibuffer}).
-
-@kindex C-x o 0
-@cindex swsw-delete
-@item @kbd{C-x o 0}
-Start window deletion (@code{swsw-delete}).
-This command sets a transient key map in which several window
-commands are defined, and window IDs can be selected.
-Selecting a window ID (by pressing @kbd{ID}) will delete the window
-corresponding to it.
+Switch to the minibuffer if it's active (@code{swsw-select-minibuffer}).
 @end table
 
 @xref{Window commands} for information regarding defining new commands.
@@ -262,18 +287,24 @@ display function respects @code{swsw-id-format}.
 @node Window commands
 @section Window commands
 
-Window commands are used to perform operations on specific
-windows. They are normal commands (interactive functions) which are
-bound to a key sequence in @code{swsw-command-map}. @code{swsw-select},
-@code{swsw-select-minibuffer} and @code{swsw-delete} are implemented
-as window commands (@xref{Usage}).
-
-@code{swsw-run-window-command} should be used to define window
-commands which require window selection. Alternatively, ensure
-@code{swsw-before-command-hook} runs before window selection, and
-@code{swsw-after-command-hook} runs after window selection. Window
-selection can be started by setting @code{swsw--id-map} as a transient
-map.
+Window commands are used to perform operations on specific windows,
+chosen by their ID (or the next window, if less than
+@code{swsw-minimum} (3 by default) windows are currently in scope).
+Alternatively, other commands available in @code{swsw-command-map} can
+be chosen. Not all commands in @code{swsw-command-map} are window
+commands (by default).  For more information about included window
+commands, @xref{Usage}.
+
+Window commands can easily be defined using
+@code{swsw-define-window-command}.  For more complex use cases,
+the lower level @code{swsw-run-window-command} can be used.
+
+@defopt swsw-minimum
+Minimum number of tracked windows for which interactive selection
+occurs when using window commands.  In practice, only window commands
+defined using @code{swsw-define-window-command} automatically adhere
+to this rule.
+@end defopt
 
 @defvar swsw--id-map
 Key map which is populated automatically with elements corresponding
@@ -296,14 +327,28 @@ active). It can be used to change the behavior of window 
commands (or
 display functions, @xref{ID display}).
 @end defvar
 
+@defmac swsw-define-window-command name (window [prefix] [minibuffer]) 
docstring body...
+Define NAME as a window command with DOCSTRING as its documentation
+string.  PREFIX (a symbol) is passed as an argument to the command
+(when not omitted or nil), with it's value being the raw prefix
+argument.
+
+BODY is used as the body of an anonymous function which receives
+WINDOW (a symbol) as an argument, with its value being a selected
+window.  If there are less than @code{swsw-minimum} (3 by default)
+windows in the current scope (@xref{Customization}), the function is
+called with the window returned by @code{next-window}.  In this case,
+if MINIBUFFER is non-nil, it can be selected if it's active.
+Otherwise, the function is run using @code{swsw-run-window-command}.
+@end defmac
+
 @defun swsw-run-window-command fun
 Run FUN as a window command. Run @code{swsw-before-command-hook}, set
 @code{this-command} to FUN, and set @code{swsw--id-map} as a transient
-map which runs @code{swsw-after-command-hook} on exit. This function
-can be used to easily define new window commands. The hooks ran by
-this function are expected by swsw to run for any window command which
-requires ID selection; they should be manually added even if this
-function isn't used when defining a new window command.
+map which runs @code{swsw-after-command-hook} on exit.  The hooks run
+by this function are expected by swsw to run for any window command
+which requires ID selection; they should be manually added even if
+this function isn't used when defining a new window command.
 @end defun
 
 @node Keystroke Index



reply via email to

[Prev in Thread] Current Thread [Next in Thread]