emacs - 滚动到缓冲区顶部?

emacs - scroll past top of buffer?

Emacs(和所有其他文本编辑器)默认在缓冲区底行下方显示空白 space。我希望 emacs 也能够滚动 above/show 空白 space 像这样 上方 缓冲区中的顶行,以便顶行可以在小文件的屏幕中心。

我已经启动了一个小的次要模式来完成这个。然而,作为第一个版本,它可能有问题,不能处理所有边缘情况(例如缩小),而且效率不是特别高。

因此,我很乐意接受改进:如果您可以改进或扩展此代码,请随时直接编辑此答案。

(defvar vertical-center-num-buffers 0
  "The number of buffers in which `vertical-center-mode' is activated.")

(define-minor-mode vertical-center-mode
  "This minor mode displays the contents of a buffer vertically
centered with respect to the window height. This, of course, only
makes sense for buffers whose content is shorter than the window
height."
  nil
  " vc"
  nil

  ;; is the mode being turned on or off?
  (if vertical-center-mode
  ;; on
  (progn
    ;; keep track of the number of lines in the buffer
    (setq-local vertical-center-num-lines (count-lines (point-min) (point-max)))
    ;; use an overlay to display empty lines at the beginning of the buffer
    (setq-local vertical-center-overlay (make-overlay (point-min) (point-max)))
    ;; initial call to the function that centers the buffer contents
    (vertical-center--lines-changed 0)

    ;; react to changes to the buffer or the window
    (add-hook 'kill-buffer-hook 'vertical-center--kill-buffer)
    (add-hook 'window-size-change-functions 'vertical-center--window-size-changed)
    (when (= vertical-center-num-buffers 0)
      (add-hook 'before-change-functions 'vertical-center--before-change)
      (add-hook 'after-change-functions 'vertical-center--after-change))

    ;; this is just to play nice and remove the above hook
    ;; functions when they're no longer needed. Let's keep our
    ;; fingers crossed that we'll always stay in sync.
    (setq vertical-center-num-buffers (1+ vertical-center-num-buffers)))

;; off
;; delete/unset data structures when the mode is turned off
(delete-overlay vertical-center-overlay)
(makunbound 'vertical-center-num-lines)
(makunbound 'vertical-center-overlay)
(setq vertical-center-num-buffers (1- vertical-center-num-buffers))

;; remove hook functions when they're no longer needed
(when (= vertical-center-num-buffers 0)
  (remove-hook 'kill-buffer-hook 'vertical-center--kill-buffer)
  (remove-hook 'window-size-change-functions 'vertical-center--window-size-changed)
  (remove-hook 'before-change-functions 'vertical-center--before-change)
  (remove-hook 'after-change-functions 'vertical-center--after-change))))

;; handle killing of buffers
(defun vertical-center--kill-buffer ()
  (when vertical-center-mode
(setq vertical-center-num-buffers (1- vertical-center-num-buffers))))    

;; react to changes in the window height
(defun vertical-center--window-size-changed (arg)
  (vertical-center--lines-changed 0))

;; handle deletions of buffer text
(defun vertical-center--before-change (beginning end)
  (when (boundp 'vertical-center-num-lines)
(let ((num-lines 0))
  (while (< beginning end)
    (when (= (char-after beginning) ?\n)
      (setq num-lines (1- num-lines)))
    (setq beginning (1+ beginning)))
  (when (< num-lines 0)
    (vertical-center--lines-changed num-lines)))))

;; handle insertions into the buffer
(defun vertical-center--after-change (beginning end previous-length)
  (when (boundp 'vertical-center-num-lines)
(let ((num-lines 0))
  (while (< beginning end)
    (when (= (char-after beginning) ?\n)
      (setq num-lines (1+ num-lines)))
    (setq beginning (1+ beginning)))
  (when (> num-lines 0)
    (vertical-center--lines-changed num-lines)))))

;; update the display when either the buffer content or the window
;; height has changed
(defun vertical-center--lines-changed (num-lines)
  (setq vertical-center-num-lines (+ vertical-center-num-lines num-lines))
  (let ((top-margin (/ (- (window-height) vertical-center-num-lines) 2)))
    ;; set the top margin
    (overlay-put vertical-center-overlay 'before-string 
             (when (> top-margin 0)
               (make-string top-margin ?\n)))))

将以上代码保存在您选择的目录中名为 "vertical-center.el" 的文件中,然后将以下行添加到您的 .emacs 文件中:

(setq load-path (append load-path "<directory>"))
(autoload 'vertical-center-mode "vertical-center")

此处,<directory> 应该是您保存 "vertical-center.el" 文件的目录路径。

重新启动 Emacs 后,您现在可以通过键入 M-x vertical-center-mode.

来激活或停用该模式

根据 Thomas 在这里的回答的指导,我为此创建了一个次要模式,现在可以在 MELPA 上使用:

TopSpace - 在 Emacs 中向下滚动并重新居中顶部行/获取上部 margins/padding