This repository has been archived on 2022-11-18. You can view files and clone it, but cannot push or open issues or pull requests.
emacs/external/zoom-window.el

142 lines
4.8 KiB
EmacsLisp

;;; zoom-window.el --- Zoom window like tmux -*- lexical-binding: t; -*-
;; Copyright (C) 2019 by Wojciech Kozlowski
;; Author: Wojciech Kozlowski <wk@wojciechkozlowski.eu>
;; based on `github.com/syohex/emacs-zoom-window'
;; by Syohei YOSHIDA <syohex@gmail.com>
;; 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:
;; zoom-window.el provides functions which zooms specific window in frame and
;; restore original window configuration. This is like tmux's zoom/unzoom
;; features.
;;; Code:
(require 'cl-lib)
(defgroup zoom-window nil
"Zoom window like tmux"
:group 'windows)
(defcustom zoom-window-mode-line-bg (face-background 'mode-line)
"The face of the modeline when zoom-window is enabled."
:type 'string)
(cl-defstruct zoom-window-
(enabled nil)
(mode-line-bg (face-background 'mode-line))
(buffers nil)
(window-configuration nil))
(defvar zoom-window--cb (make-zoom-window-))
(defun zoom-window--save-mode-line-color ()
"Save the original mode line color."
(setf (zoom-window--mode-line-bg zoom-window--cb)
(face-background 'mode-line)))
(defun zoom-window--save-buffers ()
"Save the current buffer list."
(let ((buffers (cl-loop for window in (window-list)
collect (window-buffer window))))
(setf (zoom-window--buffers zoom-window--cb) buffers)))
(defun zoom-window--get-buffers ()
"Get the saved buffer list."
(zoom-window--buffers zoom-window--cb))
(defun zoom-window--restore-mode-line-face ()
"Restore the original mode line face."
(set-face-background 'mode-line (zoom-window--mode-line-bg zoom-window--cb)))
(defun zoom-window--save-window-configuration ()
"Save the window configuration."
(setf (zoom-window--window-configuration zoom-window--cb)
(list (current-window-configuration) (point-marker))))
(defun zoom-window--restore-window-configuration ()
"Restore the window configuration."
(let* ((window-context (zoom-window--window-configuration zoom-window--cb)))
(let ((window-conf (cl-first window-context))
(marker (cl-second window-context)))
(set-window-configuration window-conf)
(when (marker-buffer marker)
(goto-char marker))
(setf (zoom-window--window-configuration zoom-window--cb) nil))))
(defun zoom-window--toggle-enabled ()
"Toggle the enabled flag."
(let ((status (zoom-window--enabled zoom-window--cb)))
(setf (zoom-window--enabled zoom-window--cb) (not status))))
(defun zoom-window--enable-p ()
"Return t if zoom is enabled."
(zoom-window--enabled zoom-window--cb))
(defsubst zoom-window--goto-line (line)
"Go to the given LINE in the current buffer."
(goto-char (point-min))
(forward-line (1- line)))
(defun zoom-window--do-unzoom ()
"Unzoom window."
(let ((current-line (line-number-at-pos))
(current-column (current-column))
(current-buf (current-buffer)))
(zoom-window--restore-mode-line-face)
(zoom-window--restore-window-configuration)
(unless (string= (buffer-name current-buf) (buffer-name))
(switch-to-buffer current-buf))
(zoom-window--goto-line current-line)
(move-to-column current-column)))
(defun zoom-window--do-zoom ()
"Zoom window."
(zoom-window--save-mode-line-color)
(zoom-window--save-buffers)
(zoom-window--save-window-configuration)
(delete-other-windows)
(set-face-background 'mode-line zoom-window-mode-line-bg))
;;;###autoload
(defun zoom-window-zoom ()
"Zoom/un-zoom window."
(interactive)
(let ((enabled (zoom-window--enable-p)))
(if (and (one-window-p) (not enabled))
(message "There is only one window!!")
(if enabled
(with-demoted-errors "Warning: %S"
(zoom-window--do-unzoom))
(zoom-window--do-zoom))
(force-mode-line-update)
(zoom-window--toggle-enabled))))
(defun zoom-window-next ()
"Switch to next buffer which is in zoomed workspace."
(interactive)
(let* ((buffers (zoom-window--get-buffers))
(targets (member (current-buffer) buffers)))
(if targets
(if (cdr targets)
(switch-to-buffer (cadr targets))
(switch-to-buffer (car buffers)))
(switch-to-buffer (car buffers)))))
(provide 'zoom-window)
;;; zoom-window.el ends here