238 lines
10 KiB
EmacsLisp
238 lines
10 KiB
EmacsLisp
|
;;; transpose-frame.el --- Transpose windows arrangement in a frame
|
||
|
|
||
|
;; Copyright (c) 2011 S. Irie
|
||
|
|
||
|
;; Author: S. Irie
|
||
|
;; Keywords: window
|
||
|
;; Package-Version: 20200307.2119
|
||
|
;; Package-Commit: 12e523d70ff78cc8868097b56120848befab5dbc
|
||
|
|
||
|
;; This program is free software.
|
||
|
|
||
|
;; Redistribution and use in source and binary forms, with or without
|
||
|
;; modification, are permitted provided that the following conditions
|
||
|
;; are met:
|
||
|
|
||
|
;; 1. Redistributions of source code must retain the above copyright
|
||
|
;; notice, this list of conditions and the following disclaimer.
|
||
|
;; 2. Redistributions in binary form must reproduce the above copyright
|
||
|
;; notice, this list of conditions and the following disclaimer in the
|
||
|
;; documentation and/or other materials provided with the distribution.
|
||
|
|
||
|
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||
|
;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||
|
;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||
|
;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
|
;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
|
;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
;;; Commentary:
|
||
|
|
||
|
;; This program provides some interactive functions which allows users
|
||
|
;; to transpose windows arrangement in currently selected frame:
|
||
|
;;
|
||
|
;; `transpose-frame' ... Swap x-direction and y-direction
|
||
|
;;
|
||
|
;; +------------+------------+ +----------------+--------+
|
||
|
;; | | B | | A | |
|
||
|
;; | A +------------+ | | |
|
||
|
;; | | C | => +--------+-------+ D |
|
||
|
;; +------------+------------+ | B | C | |
|
||
|
;; | D | | | | |
|
||
|
;; +-------------------------+ +--------+-------+--------+
|
||
|
;;
|
||
|
;; `flip-frame' ... Flip vertically
|
||
|
;;
|
||
|
;; +------------+------------+ +------------+------------+
|
||
|
;; | | B | | D |
|
||
|
;; | A +------------+ +------------+------------+
|
||
|
;; | | C | => | | C |
|
||
|
;; +------------+------------+ | A +------------+
|
||
|
;; | D | | | B |
|
||
|
;; +-------------------------+ +------------+------------+
|
||
|
;;
|
||
|
;; `flop-frame' ... Flop horizontally
|
||
|
;;
|
||
|
;; +------------+------------+ +------------+------------+
|
||
|
;; | | B | | B | |
|
||
|
;; | A +------------+ +------------+ A |
|
||
|
;; | | C | => | C | |
|
||
|
;; +------------+------------+ +------------+------------+
|
||
|
;; | D | | D |
|
||
|
;; +-------------------------+ +-------------------------+
|
||
|
;;
|
||
|
;; `rotate-frame' ... Rotate 180 degrees
|
||
|
;;
|
||
|
;; +------------+------------+ +-------------------------+
|
||
|
;; | | B | | D |
|
||
|
;; | A +------------+ +------------+------------+
|
||
|
;; | | C | => | C | |
|
||
|
;; +------------+------------+ +------------+ A |
|
||
|
;; | D | | B | |
|
||
|
;; +-------------------------+ +------------+------------+
|
||
|
;;
|
||
|
;; `rotate-frame-clockwise' ... Rotate 90 degrees clockwise
|
||
|
;;
|
||
|
;; +------------+------------+ +-------+-----------------+
|
||
|
;; | | B | | | A |
|
||
|
;; | A +------------+ | | |
|
||
|
;; | | C | => | D +--------+--------+
|
||
|
;; +------------+------------+ | | B | C |
|
||
|
;; | D | | | | |
|
||
|
;; +-------------------------+ +-------+--------+--------+
|
||
|
;;
|
||
|
;; `rotate-frame-anticlockwise' ... Rotate 90 degrees anti-clockwise
|
||
|
;;
|
||
|
;; +------------+------------+ +--------+--------+-------+
|
||
|
;; | | B | | B | C | |
|
||
|
;; | A +------------+ | | | |
|
||
|
;; | | C | => +--------+--------+ D |
|
||
|
;; +------------+------------+ | A | |
|
||
|
;; | D | | | |
|
||
|
;; +-------------------------+ +-----------------+-------+
|
||
|
;;
|
||
|
;; This program is tested on GNU Emacs 22, 23.
|
||
|
|
||
|
;;; Code:
|
||
|
;;; Internal functions
|
||
|
|
||
|
(defun transpose-frame-get-arrangement (&optional frame subtree)
|
||
|
(let ((tree (or subtree
|
||
|
(car (window-tree frame)))))
|
||
|
(if (windowp tree)
|
||
|
(list (window-buffer tree)
|
||
|
(window-start tree)
|
||
|
(window-point tree)
|
||
|
(window-hscroll tree)
|
||
|
(window-margins tree)
|
||
|
(window-fringes tree)
|
||
|
(window-dedicated-p tree)
|
||
|
(window-redisplay-end-trigger tree)
|
||
|
tree
|
||
|
(eq tree (frame-selected-window frame)))
|
||
|
(let* ((vertical (car tree))
|
||
|
(edges (cadr tree))
|
||
|
(length (float (if vertical
|
||
|
(- (nth 3 edges) (cadr edges))
|
||
|
(- (nth 2 edges) (car edges))))))
|
||
|
(cons vertical
|
||
|
(mapcar (lambda (subtree)
|
||
|
(cons (transpose-frame-get-arrangement frame subtree)
|
||
|
(/ (let ((edges (if (windowp subtree)
|
||
|
(window-edges subtree)
|
||
|
(cadr subtree))))
|
||
|
(if vertical
|
||
|
(- (nth 3 edges) (cadr edges))
|
||
|
(- (nth 2 edges) (car edges))))
|
||
|
length)))
|
||
|
(cddr tree)))))))
|
||
|
|
||
|
(defun transpose-frame-set-arrangement (config &optional window-or-frame &rest how)
|
||
|
(let ((window (if (windowp window-or-frame)
|
||
|
window-or-frame
|
||
|
(frame-selected-window window-or-frame))))
|
||
|
(unless (windowp window-or-frame)
|
||
|
(delete-other-windows window))
|
||
|
(if (bufferp (car config))
|
||
|
(let ((buffer (pop config)))
|
||
|
(set-window-buffer window buffer)
|
||
|
(set-window-start window (pop config))
|
||
|
(set-window-point window (pop config))
|
||
|
(set-window-hscroll window (pop config))
|
||
|
(set-window-margins window (caar config) (cdr (pop config)))
|
||
|
(apply 'set-window-fringes window (pop config))
|
||
|
(set-window-dedicated-p window (pop config))
|
||
|
(set-window-redisplay-end-trigger window (pop config))
|
||
|
(let* ((orig-window (pop config))
|
||
|
(ol-func (lambda (ol)
|
||
|
(when (eq (overlay-get ol 'window) orig-window)
|
||
|
(overlay-put ol 'window window))))
|
||
|
(ol-lists (with-current-buffer buffer
|
||
|
(overlay-lists))))
|
||
|
(mapc ol-func (car ol-lists))
|
||
|
(mapc ol-func (cdr ol-lists)))
|
||
|
(if (car config) (select-window window)))
|
||
|
(let* ((horizontal (if (memq 'transpose how)
|
||
|
(pop config)
|
||
|
(not (pop config))))
|
||
|
(edges (window-edges window))
|
||
|
(length (if horizontal
|
||
|
(- (nth 2 edges) (car edges))
|
||
|
(- (nth 3 edges) (cadr edges)))))
|
||
|
(if (memq (if horizontal 'flop 'flip) how)
|
||
|
(setq config (reverse config)))
|
||
|
(while (cdr config)
|
||
|
(setq window (prog1
|
||
|
(split-window window (round (* length (cdar config)))
|
||
|
horizontal)
|
||
|
(apply 'transpose-frame-set-arrangement
|
||
|
(caar config) window how))
|
||
|
config (cdr config)))
|
||
|
(apply 'transpose-frame-set-arrangement
|
||
|
(caar config) window how)))))
|
||
|
|
||
|
;;; User commands
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun transpose-frame (&optional frame)
|
||
|
"Transpose windows arrangement at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'transpose)
|
||
|
(when (called-interactively-p 'any) (recenter)))
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun flip-frame (&optional frame)
|
||
|
"Flip windows arrangement vertically at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'flip))
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun flop-frame (&optional frame)
|
||
|
"Flop windows arrangement horizontally at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'flop))
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun rotate-frame (&optional frame)
|
||
|
"Rotate windows arrangement 180 degrees at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'flip 'flop))
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun rotate-frame-clockwise (&optional frame)
|
||
|
"Rotate windows arrangement 90 degrees clockwise at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'transpose 'flop)
|
||
|
(when (called-interactively-p 'any) (recenter)))
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun rotate-frame-anticlockwise (&optional frame)
|
||
|
"Rotate windows arrangement 90 degrees anti-clockwise at FRAME.
|
||
|
Omitting FRAME means currently selected frame."
|
||
|
(interactive)
|
||
|
(transpose-frame-set-arrangement (transpose-frame-get-arrangement frame) frame
|
||
|
'transpose 'flip)
|
||
|
(when (called-interactively-p 'any) (recenter)))
|
||
|
|
||
|
;;; _
|
||
|
;; Local Variables:
|
||
|
;; indent-tabs-mode: nil
|
||
|
;; End:
|
||
|
(provide 'transpose-frame)
|
||
|
;;; transpose-frame.el ends here
|