[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/topspace 3e24bc6657 003/181: Initial code commit
From: |
ELPA Syncer |
Subject: |
[elpa] externals/topspace 3e24bc6657 003/181: Initial code commit |
Date: |
Tue, 23 Aug 2022 12:58:27 -0400 (EDT) |
branch: externals/topspace
commit 3e24bc66570fc553d53132a32a95835fabc3b3e9
Author: Trevor Pogue <poguete@mcmaster.ca>
Commit: Trevor Pogue <poguete@mcmaster.ca>
Initial code commit
---
README.md | 37 ++++++++-
vertical-center-mode.el | 211 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 247 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index a128b00e83..9ad6424d00 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,36 @@
-# vertical-center-mode
\ No newline at end of file
+# vertical-center-mode
+### An Emacs minor-mode
+Automatically center buffers vertically in the window after opening files and
during editing. Users can also adjust the centering offset with scrolling to
further scroll up or down by any amount **above** the top lines in a buffer.
+
+Scrolling is currently supported when using the
`scroll-down-line`/`scroll-up-line`, or
`evil-scroll-line-up`/`evil-scroll-line-down`.
+
+Scrolling also integrates well with `centered-cursor-mode`, allowing the
cursor to stay centered all the way to the top line when moving the cursor with
`previous-line` and `next-line`.
+
+# Installation
+Save the file from this repository named `"vertical-center-mode.el"` into a
directory of your choice, then add the following lines to your [`.emacs`][1]
file if not using Spacemacs:
+
+ (setq load-path (append load-path "<directory>"))
+ (require 'use-package)
+
+If using Spacemacs, add the following to your `dotspacemacs/user-config`:
+
+```
+(eval-when-compile
+ (add-to-list 'load-path "<directory>")
+ (require 'use-package))
+(use-package vertical-center-mode)
+```
+
+Above, `<directory>` should be the path to the directory in which you saved
the `"vertical-center-mode.el"` file.
+
+# Usage
+After restarting Emacs, you can now activate or deactivate the mode by typing
<kbd>M-x vertical-center-mode</kbd>.
+
+You can also globally enable the minor mode either manually by typing <kbd>M-x
global-vertical-center-mode</kbd>, or on init by adding the following to your
init file.
+
+`(global-vertical-center-mode 1)`
+
+# Contributions
+The initial implementation ideas and name for this minor-mode originated from
[this answer](https://stackoverflow.com/a/66678124/3705784) in a Stack Overflow
thread.
+
+ [1]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html
diff --git a/vertical-center-mode.el b/vertical-center-mode.el
new file mode 100644
index 0000000000..650cd7e158
--- /dev/null
+++ b/vertical-center-mode.el
@@ -0,0 +1,211 @@
+;;; vertical-center-mode.el --- Center buffers vertically in their window and
scroll above the top line -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Trevor Pogue, ...
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; Automatically center buffers vertically in the window after opening files
and
+;; during editing. Users can also adjust the centering offset with scrolling to
+;; further scroll up or down by any amount above the top lines in a buffer.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; TODO:
+;; - support scrolling above top line with page scrolling as well
+;; - cannot scroll above top line if buffer open in multiple windows and
+;; one or more windows is scrolled above beginning of buffer
+;; - centering is a bit lower than dead center
+;; - support recentering on window resize
+;; - submit to MELPA? (after optimizing/cleaning up code more)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Mode definition and setup
+
+;;;###autoload
+(define-global-minor-mode global-vertical-center-mode vertical-center-mode
+ vcm--turn-on-from-global)
+
+(defun vcm--turn-on-from-global ()
+ "Try to turn on vertical-center-mode from global call.
+Called when calling command `global-vertical-center-mode'.
+vertical-center-mode will not start in minibuffer or hidden buffers, or helm."
+ (unless (or (bound-and-true-p vcm-on)
+ (string-match " \\*.*\\*" (buffer-name))
+ (string-match "helm" (buffer-name))
+ (minibufferp))
+ (vertical-center-mode 1)))
+
+;;;###autoload
+(define-minor-mode vertical-center-mode
+ "Allows vertical padding or scrolling above the top line of a buffer.
+When opening a buffer, the contents are initially vertically centered with
+respect to the window height. The user can also scroll as well to adjust the
+centering offset. The buffer also recenters if transfered to
+another window unless user has previously adjusted its height with scrolling.
+"
+ :init-value nil
+ :ligher " vc"
+ :keymap nil
+ ;; only turn on if mode was previously off
+ (if (and vertical-center-mode (not (bound-and-true-p vcm-on)))
+ (vcm--turn-on))
+ ;; only turn off if mode was previously on
+ (if (and (not vertical-center-mode) (bound-and-true-p vcm-on))
+ (vcm--turn-off)))
+
+(defun vcm--turn-on ()
+ (setq-local vcm-on t)
+ (setq-local vcm-overlay (make-overlay (point-min) (point-max)))
+ (setq-local vcm-scroll-offset 0)
+ (setq-local vcm-user-scrolled nil)
+ (vcm--add-hooks)
+ (if (not (boundp 'vcm-first-recenter-done))
+ (setq-local vcm-first-recenter-done nil))
+ (if vcm-first-recenter-done
+ (vcm--recenter-reset-scroll)))
+
+(defun vcm--turn-off ()
+ "Delete/unset data structures when the mode is turned off."
+ (vcm--remove-hooks)
+ (makunbound 'vcm-on)
+ (delete-overlay vcm-overlay)
+ (makunbound 'vcm-overlay)
+ (makunbound 'vcm-scroll-offset)
+ (makunbound 'vcm-user-scrolled))
+
+;; handle insertions into the buffer
+(defun vcm--kill-buffer ()
+ (makunbound 'vcm-first-recenter-done)
+ (vcm--turn-off))
+
+(provide 'vertical-center-mode)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Hooks
+
+(defvar vcm--hook-alist
+ '(
+ (window-configuration-change-hook . vcm--recenter-reset-scroll-conditional)
+ (kill-buffer-hook . vcm--kill-buffer)
+ (before-change-functions . vcm--recenter-keep-scroll)
+ (after-change-functions . vcm--recenter-keep-scroll)
+ (pre-command-hook . vcm--scroll-increase-overlay)
+ (post-command-hook . vcm--scroll-decrease-overlay))
+ "A list of hooks so they only need to be written in one spot.
+List of cons cells in format (hook-variable . function).")
+
+(defun vcm--add-hooks ()
+ "Add hooks defined in variable `vcm-hook-alist'."
+ (mapc (lambda (entry) (add-hook (car entry) (cdr entry) t t))
+ vcm--hook-alist))
+
+(defun vcm--remove-hooks ()
+ "Remove hooks defined in variable `vcm-hook-alist'."
+ (mapc (lambda (entry) (remove-hook (car entry) (cdr entry) t))
+ vcm--hook-alist))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Scrolling
+
+(defun vcm--scroll (scroll-list ccm-list scroll-direction)
+ "Emulate scrolling if user command was a scrolling command."
+ (when (member this-command '(comment-line))
+ ;; this resolves a bug with the overlay changing size when commenting code
+ (vcm--recenter-keep-scroll))
+ (let ((user-is-scrolling (member this-command scroll-list))
+ (centering-cursor (member this-command ccm-list)))
+ ;; shouldn't scroll from moving cursor unless in centered-cursor-mode
+ (unless (bound-and-true-p centered-cursor-mode) (setq centering-cursor
nil))
+ (when (and (or user-is-scrolling centering-cursor))
+ (vcm--add-to-scroll-offset scroll-direction)
+ (setq vcm-user-scrolled t)
+ (vcm--recenter-keep-scroll))))
+
+(defun vcm--scroll-increase-overlay ()
+ "Check if user command should initiate scrolling down."
+ (vcm--scroll '(scroll-down-line evil-scroll-line-up)
+ '(previous-line evil-previous-visual-line) 1))
+
+(defun vcm--scroll-decrease-overlay ()
+ "Check if user command should initiate scrolling up."
+ (vcm--scroll '(scroll-up-line evil-scroll-line-down)
+ '(next-line evil-next-visual-line) -1))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Overlay dislaying and recentering
+
+(defun vcm--recenter-keep-scroll (&optional arg0 arg1 arg2)
+ "Use an overlay to display empty lines at the beginning of the buffer.
+This emulates the ability to scroll above the top line."
+ (let ((overlay-size (vcm--overlay-size)))
+ (overlay-put vcm-overlay 'before-string
+ (when (> overlay-size 0) (make-string overlay-size ?\n))))
+ (setq vcm-first-recenter-done t))
+
+(defun vcm--recenter-reset-scroll (&optional arg0 arg1 arg2)
+ (vcm--reset-scroll)
+ (vcm--recenter-keep-scroll))
+
+(defun vcm--recenter-reset-scroll-conditional (&optional arg0 arg1 arg2)
+ (unless (and vcm-user-scrolled)
+ (vcm--recenter-reset-scroll)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Properties
+
+(defun vcm--center-offset ()
+ "Portion of the overlay that makes small buffer centered."
+ (let ((center-offset
+ (/ (- (window-height) (vcm--buf-size)) 2)))
+ (when (< center-offset 0) (setq center-offset 0))
+ center-offset)) ; return center-offset
+
+(defun vcm--scroll-offset ()
+ "Portion of the overlay the user adjusts with scrolling."
+ (let ((top-line (vcm--top-line)))
+ (if (> top-line 2)
+ (setq vcm-scroll-offset (- (*(vcm--center-offset) -1) 1))))
+ vcm-scroll-offset) ; return vcm-scroll-offset
+
+(defun vcm--add-to-scroll-offset (direction)
+ (let ((pos (+ (- (line-number-at-pos) (vcm--top-line)) (vcm--overlay-size)))
+ (bottom (- (window-height) 5)))
+ ;; avoids a bug with cursor suddenly scrolling up
+ (when (> pos bottom) (previous-line)))
+ ;; only put overlay when top line is 1
+ (when (= (vcm--top-line) 1)
+ ;; block scrolling text fully below bottom of window
+ (unless (and (> direction 0)
+ (>= (vcm--overlay-size) (- (window-height) 5)))
+ (setq vcm-scroll-offset (+ (vcm--scroll-offset) direction)))))
+
+(defun vcm--reset-scroll () (setq vcm-scroll-offset 0))
+
+(defun vcm--overlay-size ()
+ "The total overlay size."
+ (+ (vcm--scroll-offset) (vcm--center-offset)))
+
+(defun vcm--buf-size ()
+ "Size of the buffer text in lines."
+ (count-lines (point-min) (point-max)))
+
+(defun vcm--top-line ()
+ "Line number of the top line of text shown in the window."
+ (line-number-at-pos (window-start)))
- [elpa] externals/topspace 7d384d0568 120/181: Add mouse-scrolling test, (continued)
- [elpa] externals/topspace 7d384d0568 120/181: Add mouse-scrolling test, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 74ba25eee4 117/181: Update HISTORY.md format to match CHANGELOG.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 97334a2089 122/181: Bump version: 0.2.0 → 0.2.1, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace c78ac7edd9 137/181: Update README.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 8c2b1e4391 146/181: Increase test coverage, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace cbd1f7e8da 154/181: Remove cl-lib dependency in Cask, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 6ed32d2426 162/181: Update NEWS.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 97c2216b72 167/181: Update .elpaignore, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 28f3792bf3 159/181: Internal refactoring, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 8d44371ff0 002/181: Create LICENSE, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 3e24bc6657 003/181: Initial code commit,
ELPA Syncer <=
- [elpa] externals/topspace 903f45bb4a 056/181: Update issue templates, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace dbcbf2c25a 059/181: Update bug_report.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 334fecd4c4 068/181: Update description in topspace.el and readme.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace c1e4621a11 067/181: Update description in topspace.el and readme.md, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace ac2e2c2cdb 072/181: Mention to follow Elisp style guides, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace a0aa7b9b07 066/181: Remove checkdoc warnings, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace b305bb56be 078/181: Add HISTORY.md containing legacy changelog, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 270b4ace51 069/181: Update changelog for v0.1.2, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 9d3125c0ec 081/181: Test automatic changelog generation action, ELPA Syncer, 2022/08/23
- [elpa] externals/topspace 45b44cf17c 084/181: Add automatic changelog generation action, ELPA Syncer, 2022/08/23