Emacs 如何根据文本高度自动添加/删除滚动条

Emacs 如何根据文本高度自动添加/删除滚动条,emacs,scrollbar,elisp,Emacs,Scrollbar,Elisp,许多商业文字处理器都有一个默认行为,即当文档中的文本行小于可见窗口时,自动隐藏垂直滚动条;并且,当文档中的文本行大于可见窗口时,滚动条会自动显示。Emacs缺少这种能力,我希望这是各种不同模式下的默认行为 有人知道如何随着文档大小(文本行数)的增加或减少而动态地删除或添加滚动条吗 我正在考虑使用@phils之前在相关线程中的一个示例将其编织到行号函数中: 即使我不使用linum模式,我也希望它能正常工作。但是,我不认为滚动条功能应该在每个命令之后运行——它应该只在添加或减去新行时运行,考虑到可视

许多商业文字处理器都有一个默认行为,即当文档中的文本行小于可见窗口时,自动隐藏垂直滚动条;并且,当文档中的文本行大于可见窗口时,滚动条会自动显示。Emacs缺少这种能力,我希望这是各种不同模式下的默认行为

有人知道如何随着文档大小(文本行数)的增加或减少而动态地删除或添加滚动条吗

我正在考虑使用@phils之前在相关线程中的一个示例将其编织到行号函数中:

即使我不使用
linum模式
,我也希望它能正常工作。但是,我不认为滚动条功能应该在每个命令之后运行——它应该只在添加或减去新行时运行,考虑到
可视行模式
(即包装处于活动状态)可能处于活动状态

以下片段的灵感来源于@abo abo之前在相关线程中的回答:


编辑(2014年1月17日):工作草案基于@Drew对此主题的有用答案

EDIT(2014年1月19日):添加了一个函数,使用
垂直运动对每个单词包装行进行计数。设置
初始帧默认值
似乎是在创建初始帧后由Emacs读取的,因此滚动条在一瞬间可见——为了避免看到这一点,修改初始帧的帧参数似乎可以解决此视觉问题。现在使用
窗口文本高度
而不是
窗口高度
——返回的高度不包括分隔符、模式行、任何标题行,也不包括文本区域底部的任何部分高度行。复制了
linum模式
在使用方面使用的方法--
post-command钩子
更改主模式钩子
,以及
窗口配置更改钩子
)。添加了
window-live-p
条件,以避免在各种缓冲区加载时启动Emacs时出现
post-command-hook
错误。添加了处理
窄到区域的条件
——仍然不确定为什么这种情况会导致Emacs冻结在循环中或其他东西中——现在需要解决方法。2014年1月19日推出的最新版本Emacs Trunk似乎解决了以前版本中遇到的视觉显示问题,因此,
重新绘制帧
不再是必要的。添加了
(重新显示t)
到功能
计算垂直线
,该功能在切换缓冲区时加快显示新缓冲区。为始终具有滚动条或从不具有滚动条的缓冲区添加了regexp

EDIT(2014年1月20日):只添加了一个主要条件,即存在实时窗口,并从
法律列表滚动条功能的各个分支中删除了相同的条件。为
缩小到区域
的情况添加了附加条件,以便仅当缩小之前存在滚动条时,才需要移除滚动条

编辑(2014年1月21日):使用此修订版,不再需要计算行数(这会导致大缓冲区的速度减慢)。新方法是基于四(4)个点的简单数学计算,这些点仅在几分之一秒内确定,即
最小点
最大点
窗口开始
窗口结束
。如果
point min
从屏幕上移开,就会添加滚动条——我认为这种行为是有意义的——尽管,我停下来思考滚动条是否也应该作为一种视觉表示,显示
point min
point max
参数内的字符是否可以实际放入窗口,而不管
point min
是否已移到窗口之外。本例中没有一个钩子能够处理
显示缓冲区
情况(针对同一帧的同一窗口,这两个窗口都已经有焦点)——因此,我创建了自己的
显示缓冲区钩子
(这超出了本例的范围)


不清楚你说的“在飞”是什么意思。为什么不举一个你正在寻找的行为和你看到的行为的例子呢

如果您只想以交互方式打开/关闭滚动条,或者在钩子上,或者从代码中切换滚动条,那么您只需要
滚动条模式
。但我只是疯狂地猜测你到底在寻找什么

您还可以使用
菜单栏无滚动条
菜单栏左滚动条
,以及
菜单栏右滚动条
。或者只需执行这些命令中的每个命令即可:
(自定义设置变量“滚动条模式”,无论什么)
。或者使用
设置滚动条模式
设置窗口滚动条
,类似地。这取决于你在寻找什么样的行为

我推荐
M-x apropos滚动条
。(或者如果使用,只需
C-h f滚动条S-TAB
,然后重复
C-M-down
。)


更新(回复评论后)

您可以将其添加到
模式行位置
,这样模式行的更新会自动触发滚动条的打开/关闭。这很有效,例如:

(setq-default
 mode-line-position
 '(:eval
   (progn
     (if (> (count-lines (point-min) (point-max)) (window-height))
         (set-window-scroll-bars nil 20 t)
       (set-window-scroll-bars nil 0 t))
     `((-3 ,(propertize
             "%p"
             'local-map mode-line-column-line-number-mode-map
             'mouse-face 'mode-line-highlight
             'help-echo "Buffer position, mouse-1: Line/col menu"))
       (line-number-mode
        ((column-number-mode
          (10 ,(propertize
                " (%l,%c)"
                'face (and (> (current-column)
                              modelinepos-column-limit)
                           'modelinepos-column-warning)
                'local-map mode-line-column-line-number-mode-map
                'mouse-face 'mode-line-highlight
                'help-echo "Line and column, mouse-1: Line/col menu"))
          (6 ,(propertize
               " L%l"
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Line number, mouse-1: Line/col menu"))))
        ((column-number-mode
          (5 ,(propertize
               " C%c"
               'face (and (> (current-column)
                             modelinepos-column-limit)
                          'modelinepos-column-warning)
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Column number, mouse-1: Line/col menu")))))))))
您也可以使用以下方法,使用Stefan的 为了更好地处理缩放文本、
视觉线条模式、图像等。但是,在这种情况下,每当某些文本由于滚动而超出窗口时,滚动条就会启动,而不管该文本是否适合该窗口。这是否是一项功能由您决定。;-)

(设置默认值
模式
;;;;;;;;;;;;;;;;;;;;;;;;;; LAWLIST SCROLL BAR MODE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defvar regexp-always-scroll-bar '("\\.yes" "\\*Scroll-Bar\\*")
  "Regexp matching buffer names that will always have scroll bars.")

(defvar regexp-never-scroll-bar '("\\.off" "\\.not")
  "Regexp matching buffer names that will never have scroll bars.")

(add-to-list 'default-frame-alist '(vertical-scroll-bars . nil))

(modify-all-frames-parameters (list (cons 'vertical-scroll-bars nil)))

(defun lawlist-scroll-bar ()
  (when (window-live-p (get-buffer-window (current-buffer)))
    (redisplay t)
    (cond
      ;; not regexp matches | not narrow-to-region
      ((and
          (not (regexp-match-p regexp-always-scroll-bar (buffer-name)))
          (not (regexp-match-p regexp-never-scroll-bar (buffer-name)))
          (equal (- (point-max) (point-min)) (buffer-size)))
        (cond
          ;; Lines of text are less-than or equal-to window height,
          ;; and scroll bars are present (which need to be removed).
          ((and
              (<= (- (point-max) (point-min)) (- (window-end) (window-start)))
              (equal (window-scroll-bars) `(15 2 right nil)))
            (set-window-scroll-bars (selected-window) 0 'right nil))
          ;; Lines of text are greater-than window height, and
          ;; scroll bars are not present and need to be added.
          ((and
              (> (- (point-max) (point-min)) (- (window-end) (window-start)))
              (not (equal (window-scroll-bars) `(15 2 right nil))))
            (set-window-scroll-bars (selected-window) 15 'right nil))))
      ;; Narrow-to-region is active, and scroll bars are present
      ;; (which need to be removed).
      ((and
          (not (equal (- (point-max) (point-min)) (buffer-size)))
          (equal (window-scroll-bars) `(15 2 right nil)))
        (set-window-scroll-bars (selected-window) 0 'right nil))
      ;; not narrow-to-region | regexp always scroll-bars
      ((and
          (equal (- (point-max) (point-min)) (buffer-size))
          (regexp-match-p regexp-always-scroll-bar (buffer-name)))
        (set-window-scroll-bars (selected-window) 15 'right nil))
      ;; not narrow-to-region | regexp never scroll-bars
      ((and
          (equal (- (point-max) (point-min)) (buffer-size))
          (regexp-match-p regexp-never-scroll-bar (buffer-name)))
        (set-window-scroll-bars (selected-window) 0 'right nil)))))

(define-minor-mode lawlist-scroll-bar-mode
  "This is a custom scroll bar mode."
  :lighter " sc"
  (if lawlist-scroll-bar-mode
    (progn
      (add-hook 'post-command-hook 'lawlist-scroll-bar nil t)
      ;; (add-hook 'change-major-mode-hook 'lawlist-scroll-bar nil t)
      ;; (add-hook 'window-configuration-change-hook 'lawlist-scroll-bar nil t)
       )
    (remove-hook 'post-command-hook 'lawlist-scroll-bar t)
    (remove-hook 'change-major-mode-hook 'lawlist-scroll-bar t)
    (remove-hook 'window-configuration-change-hook 'lawlist-scroll-bar t)))

(define-globalized-minor-mode global-lawlist-scroll-bar-mode
  lawlist-scroll-bar-mode lawlist-scroll-bar-on)

(defun lawlist-scroll-bar-on ()
  (unless (minibufferp)
    (lawlist-scroll-bar-mode 1)))

(global-lawlist-scroll-bar-mode)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; https://github.com/kentaro/auto-save-buffers-enhanced
;; `regexp-match-p` function modified by @sds on stackoverflow
;; https://stackoverflow.com/questions/20343048/distinguishing-files-with-extensions-from-hidden-files-and-no-extensions
(defun regexp-match-p (regexps string)
  (and string
       (catch 'matched
         (let ((inhibit-changing-match-data t)) ; small optimization
           (dolist (regexp regexps)
             (when (string-match regexp string)
               (throw 'matched t)))))))
(setq-default
 mode-line-position
 '(:eval
   (progn
     (if (> (count-lines (point-min) (point-max)) (window-height))
         (set-window-scroll-bars nil 20 t)
       (set-window-scroll-bars nil 0 t))
     `((-3 ,(propertize
             "%p"
             'local-map mode-line-column-line-number-mode-map
             'mouse-face 'mode-line-highlight
             'help-echo "Buffer position, mouse-1: Line/col menu"))
       (line-number-mode
        ((column-number-mode
          (10 ,(propertize
                " (%l,%c)"
                'face (and (> (current-column)
                              modelinepos-column-limit)
                           'modelinepos-column-warning)
                'local-map mode-line-column-line-number-mode-map
                'mouse-face 'mode-line-highlight
                'help-echo "Line and column, mouse-1: Line/col menu"))
          (6 ,(propertize
               " L%l"
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Line number, mouse-1: Line/col menu"))))
        ((column-number-mode
          (5 ,(propertize
               " C%c"
               'face (and (> (current-column)
                             modelinepos-column-limit)
                          'modelinepos-column-warning)
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Column number, mouse-1: Line/col menu")))))))))
(setq-default
 mode-line-position
 '(:eval
   (let ((scroll-bars  (nth 2 (window-scroll-bars))))
     (if (or (> (point-max) (window-end))  (< (point-min) (window-start)))
         (unless scroll-bars (set-window-scroll-bars nil 20 t))
       (when scroll-bars (set-window-scroll-bars nil 0 t)))
     (unless (equal scroll-bars (nth 2 (window-scroll-bars))) (redraw-frame))
     `((-3 ,(propertize
             "%p"
             'local-map mode-line-column-line-number-mode-map
             'mouse-face 'mode-line-highlight
             'help-echo "Buffer position, mouse-1: Line/col menu"))
       (line-number-mode
        ((column-number-mode
          (10 ,(propertize
                " (%l,%c)"
                'face (and (> (current-column)
                              modelinepos-column-limit)
                           'modelinepos-column-warning)
                'local-map mode-line-column-line-number-mode-map
                'mouse-face 'mode-line-highlight
                'help-echo "Line and column, mouse-1: Line/col menu"))
          (6 ,(propertize
               " L%l"
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Line number, mouse-1: Line/col menu"))))
        ((column-number-mode
          (5 ,(propertize
               " C%c"
               'face (and (> (current-column)
                             modelinepos-column-limit)
                          'modelinepos-column-warning)
               'local-map mode-line-column-line-number-mode-map
               'mouse-face 'mode-line-highlight
               'help-echo "Column number, mouse-1: Line/col menu")))))))))