[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/window-commander c5f85632d9 156/170: Rework display fun
From: |
ELPA Syncer |
Subject: |
[elpa] externals/window-commander c5f85632d9 156/170: Rework display functions |
Date: |
Wed, 28 Jun 2023 19:00:36 -0400 (EDT) |
branch: externals/window-commander
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
- [elpa] externals/window-commander 95c25ee03c 022/170: ; Bump version to 1.0 and update README, (continued)
- [elpa] externals/window-commander 95c25ee03c 022/170: ; Bump version to 1.0 and update README, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 51b8c1eb7c 080/170: ; Update documentation according to latest changes, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander c378be9bae 130/170: ; Load 'subr-x' when compiling, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 444873d9bd 114/170: Fix names of some internal and some external functions, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 8a9686e0fe 111/170: ; Change required Emacs version according to package-lint, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 85d9c690b1 102/170: ; Add key binding to swsw-mode's docstring, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander b5ebc9e08a 106/170: Use lambdas for ':set' functions, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander b2dcc60dab 136/170: ; Explain 'swsw--id-counter' more thoroughly, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander bbe31e347c 146/170: ; Bump version to 2.1.1, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 0d361df85e 148/170: ; Use 'kbd' notation in the README, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander c5f85632d9 156/170: Rework display functions,
ELPA Syncer <=
- [elpa] externals/window-commander ae9876b2c6 163/170: Rename to Window Commander and simplify project, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 43d93402a8 167/170: ; Small fix, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander ff30079d41 075/170: ; Remove trailing period in a tag string of 'swsw-scope', ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 07f26210e8 086/170: ; Add 'swsw-delete' fix to the NEWS file, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 8b74678bcf 028/170: * swsw.el (swsw-display-function): Avoid byte compilation warning, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 54ca1baa14 030/170: ; Restructure README and commentary, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander ebaa85abdd 031/170: ; Add a missing word to a comment, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander 6695f8858e 034/170: ; Use '; ' for inline comment instead of '; ; ', ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander b5b05358a3 035/170: ; Add a news file containing a detailed change log, ELPA Syncer, 2023/06/28
- [elpa] externals/window-commander b6277eb31f 037/170: ; Indicate that version 1.1 is still in development in the NEWS file, ELPA Syncer, 2023/06/28