2016-07-01 18:20:28 +00:00
|
|
|
;;; centered-buffer-mode.el --- Minor mode for centering buffers.
|
|
|
|
|
|
|
|
;; Copyright (C) 2012-2016 Sylvain Benner & Contributors
|
|
|
|
;;
|
2016-07-05 21:23:36 +00:00
|
|
|
;; Author: Eugene "JAremko" Yaremenko <w3techplayground@gmail.com>
|
|
|
|
;; Keywords: centering buffer minor-mode
|
2016-07-01 18:20:28 +00:00
|
|
|
;; Created: 1 July 2016
|
2016-07-07 17:55:19 +00:00
|
|
|
;; Version: 1.01
|
2016-07-01 18:20:28 +00:00
|
|
|
;; Package-Requires: ((emacs "24.4"))
|
|
|
|
;; URL: https://github.com/syl20bnr/spacemacs
|
|
|
|
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
|
|
|
|
;; 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/>.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
(require 'face-remap)
|
|
|
|
|
2016-07-15 14:15:14 +00:00
|
|
|
(defgroup spacemacs-centered-buffer-mode nil "Minor mode to center buffer in its window."
|
|
|
|
:group 'convenience)
|
|
|
|
|
2016-07-05 21:23:36 +00:00
|
|
|
(defcustom spacemacs-centered-buffer-mode-min-fringe-width 50
|
|
|
|
"Minimal fringe width."
|
|
|
|
:type 'integer
|
2016-07-15 14:15:14 +00:00
|
|
|
:group 'spacemacs-centered-buffer-mode)
|
2016-07-05 21:23:36 +00:00
|
|
|
|
|
|
|
(defcustom spacemacs-centered-buffer-mode-safety-gap-width 20
|
|
|
|
"Add extra width to the modified buffer to make sure
|
|
|
|
that differed modifications won't cause an overflow."
|
|
|
|
:type 'integer
|
2016-07-15 14:15:14 +00:00
|
|
|
:group 'spacemacs-centered-buffer-mode)
|
2016-07-05 21:23:36 +00:00
|
|
|
|
2016-07-05 23:36:15 +00:00
|
|
|
(defcustom spacemacs-centered-buffer-mode-fringe-color "black"
|
2016-07-05 21:23:36 +00:00
|
|
|
"Color of the fringes."
|
2016-07-05 23:36:15 +00:00
|
|
|
:type 'color
|
2016-07-15 14:15:14 +00:00
|
|
|
:group 'spacemacs-centered-buffer-mode)
|
2016-07-05 21:23:36 +00:00
|
|
|
|
2016-07-01 18:20:28 +00:00
|
|
|
(defvar-local spacemacs--centered-buffer-mode-origin-buffer nil)
|
|
|
|
(defvar-local spacemacs--centered-buffer-mode-indirect-buffer nil)
|
|
|
|
(defvar-local spacemacs--centered-buffer-mode-text-pixel-size nil)
|
2016-07-07 17:55:19 +00:00
|
|
|
(defvar spacemacs-centered-buffer-mode-default-fringe-color (face-background 'fringe))
|
2016-07-05 21:23:36 +00:00
|
|
|
(defvar spacemacs--centered-buffer-mode-indirect-buffers (list))
|
2016-07-01 18:20:28 +00:00
|
|
|
|
|
|
|
(define-minor-mode spacemacs-centered-buffer-mode
|
2016-07-05 21:23:36 +00:00
|
|
|
"Minor mode to center buffer in its window."
|
2016-07-01 18:20:28 +00:00
|
|
|
:init-value nil
|
2016-07-15 14:15:14 +00:00
|
|
|
:group 'spacemacs-centered-buffer-mode
|
2016-07-01 18:20:28 +00:00
|
|
|
(if spacemacs-centered-buffer-mode
|
2016-07-07 17:55:19 +00:00
|
|
|
(if (not (window-dedicated-p))
|
|
|
|
(spacemacs//centered-buffer-mode-enable-branch (called-interactively-p 'any))
|
|
|
|
(setq spacemacs-centered-buffer-mode nil)
|
|
|
|
(when (called-interactively-p 'any)
|
|
|
|
(message "Can't center in dedicated window!")))
|
|
|
|
(spacemacs//centered-buffer-mode-disable-branch)))
|
|
|
|
|
|
|
|
(defun spacemacs//centered-buffer-mode-enable-branch (interact)
|
2016-07-15 08:52:54 +00:00
|
|
|
"Used it `spacemacs-centered-buffer-mode'.
|
|
|
|
Assume to be called interactively when INTERACT has non nil value."
|
2016-07-07 17:55:19 +00:00
|
|
|
;; Mode will be applied to the indirect buffer.
|
|
|
|
(setq spacemacs-centered-buffer-mode nil)
|
2016-07-15 08:52:54 +00:00
|
|
|
;; Don't run if the mode is enabled(we are in the indirect buffer).
|
2016-07-07 17:55:19 +00:00
|
|
|
(unless spacemacs--centered-buffer-mode-origin-buffer
|
|
|
|
(let* ((window (selected-window))
|
|
|
|
(origin-buffer (window-buffer window))
|
|
|
|
(indirect-buffer
|
|
|
|
(if (buffer-live-p
|
|
|
|
spacemacs--centered-buffer-mode-indirect-buffer)
|
|
|
|
spacemacs--centered-buffer-mode-indirect-buffer
|
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffer
|
|
|
|
(make-indirect-buffer origin-buffer
|
|
|
|
(format "%s(centered)"
|
|
|
|
origin-buffer)
|
|
|
|
t)))))
|
|
|
|
(spacemacs//centered-buffer-mode-buffer-fringr-color-toggle origin-buffer t)
|
2016-07-15 14:15:14 +00:00
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffer
|
|
|
|
indirect-buffer
|
|
|
|
spacemacs-centered-buffer-mode-default-fringe-color
|
|
|
|
(face-background 'fringe))
|
2016-07-07 17:55:19 +00:00
|
|
|
(when (derived-mode-p 'org-mode)
|
|
|
|
(setq-local org-startup-folded nil)
|
|
|
|
(outline-show-all))
|
|
|
|
(switch-to-buffer indirect-buffer nil t)
|
|
|
|
(with-mode-disabled
|
|
|
|
page-break-lines-mode
|
|
|
|
(let* ((fringe-w (spacemacs//centered-buffer-calc-fringe
|
|
|
|
window)))
|
|
|
|
(if (> fringe-w spacemacs-centered-buffer-mode-min-fringe-width)
|
|
|
|
(progn
|
|
|
|
;; Fix visual glitch.
|
|
|
|
(spacemacs/toggle-line-numbers)
|
|
|
|
(spacemacs/toggle-line-numbers)
|
|
|
|
;;
|
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffers
|
|
|
|
(append (list indirect-buffer)
|
|
|
|
spacemacs--centered-buffer-mode-indirect-buffers)
|
|
|
|
spacemacs--centered-buffer-mode-origin-buffer origin-buffer
|
|
|
|
spacemacs-centered-buffer-mode t
|
|
|
|
indicate-empty-lines nil
|
|
|
|
fringes-outside-margins t
|
|
|
|
left-fringe-width fringe-w
|
|
|
|
right-fringe-width fringe-w
|
|
|
|
;; looks better with some margin.
|
|
|
|
left-margin-width (if (or (not left-margin-width)
|
|
|
|
(= left-margin-width 0))
|
|
|
|
1
|
|
|
|
left-margin-width)
|
|
|
|
spacemacs--centered-buffer-mode-text-pixel-size
|
|
|
|
(car (window-text-pixel-size window)))
|
|
|
|
(face-remap-add-relative 'fringe :background
|
|
|
|
spacemacs-centered-buffer-mode-fringe-color)
|
|
|
|
(set-window-buffer window indirect-buffer)
|
2016-08-16 16:18:56 +00:00
|
|
|
(advice-add 'previous-buffer
|
2016-07-07 17:55:19 +00:00
|
|
|
:before
|
2016-08-16 16:18:56 +00:00
|
|
|
#'spacemacs//centered-buffer-mode-prev-next-buffer-advice)
|
|
|
|
(advice-add 'next-buffer
|
2016-07-07 17:55:19 +00:00
|
|
|
:before
|
2016-08-16 16:18:56 +00:00
|
|
|
#'spacemacs//centered-buffer-mode-prev-next-buffer-advice)
|
2016-08-30 09:05:05 +00:00
|
|
|
(add-hook 'after-change-functions
|
|
|
|
#'spacemacs//centered-buffer-after-change-function
|
|
|
|
nil
|
|
|
|
t)
|
2016-07-07 17:55:19 +00:00
|
|
|
(add-hook 'buffer-list-update-hook
|
|
|
|
'spacemacs//centered-buffer-buffer-list-update-fringes)
|
|
|
|
(add-hook 'window-configuration-change-hook
|
|
|
|
'spacemacs//centered-buffer-buffer-list-update-fringes))
|
|
|
|
(setq spacemacs--centered-buffer-mode-origin-buffer nil)
|
|
|
|
(set-buffer origin-buffer)
|
|
|
|
(spacemacs//centered-buffer-mode-buffer-fringr-color-toggle origin-buffer nil)
|
|
|
|
(kill-buffer indirect-buffer)
|
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffer nil)
|
|
|
|
(when interact
|
|
|
|
(message "Not enough space to center the buffer!"))))))))
|
|
|
|
|
2016-08-16 16:18:56 +00:00
|
|
|
(defun spacemacs//centered-buffer-mode-prev-next-buffer-advice ()
|
|
|
|
"Disables `spacemacs-centered-buffer-mode' when `spacemacs/previous-buffer'
|
|
|
|
or `spacemacs/next-buffer' is called."
|
2016-07-07 17:55:19 +00:00
|
|
|
(when (bound-and-true-p spacemacs-centered-buffer-mode)
|
|
|
|
(spacemacs-centered-buffer-mode -1)))
|
|
|
|
|
|
|
|
(defun spacemacs//centered-buffer-mode-disable-branch ()
|
2016-07-15 08:52:54 +00:00
|
|
|
"Used in `spacemacs-centered-buffer-mode'."
|
2016-08-16 16:18:56 +00:00
|
|
|
;; Don't run if the mode is disabled(we are not in the indirect buffer).
|
2016-07-07 17:55:19 +00:00
|
|
|
(when spacemacs--centered-buffer-mode-origin-buffer
|
2016-07-01 18:20:28 +00:00
|
|
|
(let* ((window (selected-window))
|
|
|
|
(origin-buffer spacemacs--centered-buffer-mode-origin-buffer)
|
|
|
|
(indirect-buffer (window-buffer window)))
|
|
|
|
(setq spacemacs--centered-buffer-mode-origin-buffer nil)
|
2016-07-07 17:55:19 +00:00
|
|
|
(switch-to-buffer origin-buffer nil t)
|
|
|
|
(spacemacs//centered-buffer-mode-buffer-fringr-color-toggle origin-buffer nil)
|
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffer nil)
|
2016-07-05 21:23:36 +00:00
|
|
|
(when (buffer-live-p indirect-buffer)
|
|
|
|
(dolist (window (get-buffer-window-list indirect-buffer 2))
|
|
|
|
(set-window-buffer window origin-buffer))
|
|
|
|
(kill-buffer indirect-buffer)))))
|
2016-07-01 18:20:28 +00:00
|
|
|
|
2016-07-07 17:55:19 +00:00
|
|
|
(defun spacemacs//centered-buffer-mode-buffer-fringr-color-toggle (buffer flag)
|
|
|
|
"Change fringe color of the BUFFER if FLAG has non-nil value.
|
|
|
|
Revert changes Otherwise."
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(if flag
|
|
|
|
(face-remap-add-relative 'fringe :background
|
|
|
|
spacemacs-centered-buffer-mode-fringe-color)
|
|
|
|
(face-remap-reset-base 'fringe)
|
|
|
|
(face-remap-add-relative 'fringe
|
|
|
|
:background
|
|
|
|
spacemacs-centered-buffer-mode-default-fringe-color))))
|
|
|
|
|
2016-07-01 18:20:28 +00:00
|
|
|
(defun spacemacs//centered-buffer-calc-fringe (&optional window text-pixel-size)
|
|
|
|
"Calculate fringe width for `spacemacs-centered-buffer-mode'.
|
|
|
|
Uses text-pixel-size if provided, otherwise calculates it with `window-pixel-width'."
|
|
|
|
(-(/ (- (window-pixel-width window)
|
|
|
|
(or text-pixel-size
|
|
|
|
(car (window-text-pixel-size window))))
|
|
|
|
2)
|
2016-07-05 21:23:36 +00:00
|
|
|
(if (bound-and-true-p org-indent-mode) 40
|
|
|
|
spacemacs-centered-buffer-mode-safety-gap-width)))
|
2016-07-01 18:20:28 +00:00
|
|
|
|
2016-08-30 09:05:05 +00:00
|
|
|
(defun spacemacs//centered-buffer-buffer-update-window-fringes (window)
|
|
|
|
"Update fringe width of WINDOW if it displays `centered-buffer-mode' buffer."
|
|
|
|
(when (and (buffer-local-value 'spacemacs--centered-buffer-mode-origin-buffer
|
|
|
|
(window-buffer window))
|
|
|
|
;; Might be needed because
|
|
|
|
;; (spacemacs-centered-buffer-mode -1) kills buffers.
|
|
|
|
(buffer-live-p (window-buffer window)))
|
|
|
|
(let ((fringe-w (spacemacs//centered-buffer-calc-fringe
|
|
|
|
window
|
|
|
|
spacemacs--centered-buffer-mode-text-pixel-size)))
|
|
|
|
(if (> fringe-w spacemacs-centered-buffer-mode-min-fringe-width)
|
|
|
|
(set-window-fringes window fringe-w fringe-w t)
|
|
|
|
(spacemacs-centered-buffer-mode -1)
|
|
|
|
(when spacemacs--centered-buffer-mode-indirect-buffers
|
|
|
|
(spacemacs//centered-buffer-prune-indirect-buffer-list))))))
|
|
|
|
|
2016-07-01 18:20:28 +00:00
|
|
|
(defun spacemacs//centered-buffer-buffer-list-update-fringes ()
|
2016-08-30 09:05:05 +00:00
|
|
|
"Update fringe width of all `centered-buffer-mode' fringes."
|
2016-07-05 21:23:36 +00:00
|
|
|
(dolist (frame (frame-list))
|
|
|
|
(when (frame-live-p frame)
|
|
|
|
(dolist (window (window-list frame 2))
|
2016-08-30 09:05:05 +00:00
|
|
|
(spacemacs//centered-buffer-buffer-update-window-fringes window)))))
|
|
|
|
|
|
|
|
(defun spacemacs//centered-buffer-after-change-function (begin end length)
|
|
|
|
"Reduce `centered-buffer-mode' fringe width in case of buffer content overflow."
|
|
|
|
(dolist (window (get-buffer-window-list (current-buffer) 2 t))
|
|
|
|
(save-excursion
|
|
|
|
(let* ((min-pos (progn (goto-char begin)
|
|
|
|
(point-at-bol)))
|
|
|
|
(max-pos (progn (goto-char end)
|
|
|
|
(point-at-eol)))
|
|
|
|
(updated-segment-max-width (car (window-text-pixel-size window min-pos max-pos))))
|
|
|
|
(when (> updated-segment-max-width
|
|
|
|
spacemacs--centered-buffer-mode-text-pixel-size)
|
|
|
|
(setq spacemacs--centered-buffer-mode-text-pixel-size updated-segment-max-width)
|
|
|
|
(spacemacs//centered-buffer-buffer-update-window-fringes window))))))
|
2016-07-05 21:23:36 +00:00
|
|
|
|
|
|
|
(defun spacemacs//centered-buffer-prune-indirect-buffer-list ()
|
|
|
|
"Remove indirect buffer from the `spacemacs--centered-buffer-mode-indirect-buffers'
|
2016-07-15 08:52:54 +00:00
|
|
|
if the buffer hasn't at least one live window. Disables `centered-buffer-mode' hooks
|
|
|
|
and advices if `spacemacs--centered-buffer-mode-indirect-buffers' has no elements left to
|
|
|
|
minimize the performance hit when the mode isn't used."
|
2016-07-05 21:23:36 +00:00
|
|
|
(dolist (buffer spacemacs--centered-buffer-mode-indirect-buffers)
|
2016-07-15 14:15:14 +00:00
|
|
|
(unless (or (and (buffer-live-p buffer)
|
|
|
|
(window-live-p (get-buffer-window buffer t)))
|
|
|
|
(not spacemacs--centered-buffer-mode-indirect-buffers))
|
2016-07-05 21:23:36 +00:00
|
|
|
(let ((origin-buffer (buffer-local-value
|
|
|
|
'spacemacs--centered-buffer-mode-origin-buffer
|
|
|
|
buffer)))
|
2016-07-15 14:15:14 +00:00
|
|
|
(when (ignore-errors (kill-buffer buffer))
|
2016-08-29 15:52:06 +00:00
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffers
|
|
|
|
(delete buffer spacemacs--centered-buffer-mode-indirect-buffers))
|
2016-07-15 14:15:14 +00:00
|
|
|
(when (buffer-live-p origin-buffer)
|
|
|
|
(spacemacs//centered-buffer-mode-buffer-fringr-color-toggle origin-buffer nil)
|
|
|
|
(with-current-buffer origin-buffer
|
|
|
|
(setq spacemacs--centered-buffer-mode-indirect-buffers nil)))))))
|
|
|
|
;; Remove hooks and advices when they are not needed anymore.
|
2016-07-05 21:23:36 +00:00
|
|
|
(unless spacemacs--centered-buffer-mode-indirect-buffers
|
2016-08-16 16:18:56 +00:00
|
|
|
(advice-remove 'previous-buffer
|
|
|
|
#'spacemacs//centered-buffer-mode-prev-next-buffer-advice)
|
|
|
|
(advice-remove 'next-buffer
|
|
|
|
#'spacemacs//centered-buffer-mode-prev-next-buffer-advice)
|
2016-08-30 09:05:05 +00:00
|
|
|
(remove-hook 'after-change-functions
|
|
|
|
#'spacemacs//centered-buffer-after-change-function)
|
2016-07-05 21:23:36 +00:00
|
|
|
(remove-hook 'buffer-list-update-hook
|
|
|
|
'spacemacs//centered-buffer-buffer-list-update-fringes)
|
|
|
|
(remove-hook 'window-configuration-change-hook
|
|
|
|
'spacemacs//centered-buffer-buffer-list-update-fringes)))
|
|
|
|
|
|
|
|
(defmacro with-mode-disabled (mode &rest body)
|
|
|
|
"Evaluate BODY with MODE disabled."
|
|
|
|
(declare (indent 1) (debug t))
|
|
|
|
`(if (not (bound-and-true-p ,mode))
|
|
|
|
(progn ,@body)
|
|
|
|
(,mode -1)
|
|
|
|
,@body
|
|
|
|
(,mode +1)))
|
2016-07-01 18:20:28 +00:00
|
|
|
|
|
|
|
(provide 'centered-buffer-mode)
|
|
|
|
|
|
|
|
;;; centered-buffer-mode.el ends here
|