【问题标题】:Emacs -- calculating new window-start/end without redisplayEmacs - 计算新窗口开始/结束而不重新显示
【发布时间】:2014-05-28 23:16:51
【问题描述】:

是否可以计算 new 窗口开始/结束 不发生重新显示?如果是这样,那么一个例子将不胜感激。如果不是,那么近似它的最佳方法是什么?

示例:我们想要移动到屏幕外某处缓冲区的新区域,并在到达那里时放置叠加层。我们可能正在使用向下翻页或向下滚动或向下段落或缓冲区结束。当我们到达那个 new 点时,我们想要计算 new window-startnew window-end。但是,我们希望避免出现没有任何覆盖的瞬间裸露的缓冲区。理想情况下,一旦添加了这些叠加层,就会重新显示。我想根据 new window-start/end 将新的叠加层限制在新区域。

  • Point-Min:点 = 1

  • 旧窗口开始:点 = 1000

  • 旧窗口结束:点 = 1500

  • 新窗口开始:点 = 3500

  • 新窗口结束:point = 4000

  • 点-最大值:点 = 6000

问题:当使用post-command-hook尝试并计算window-start window-end,正在使用之前的显示位置 - 即 old window-startold window-end


这是我正在进行的项目的示例。没有修复 window-start \ window-end 问题,我收到以下错误:

Error in post-command-hook (my-eol-ruler-function):
  (error "Invalid search bound (wrong side of point)")`.

使用交互函数end-of-buffer(point-min) 到缓冲区末尾时会发生错误。在此错误的上下文中,(point-max) 超出了 window-end


编辑:更新代码以包含一条消息:(message "point: %s | window-start: %s | window-end: %s | point-max: %s" (point) (window-start) (window-end) (point-max) )。该消息用于证明 new window-startnew window-end 未在 post-command-hook 内计算,因为尚未发生重新显示。但是,我试图避免重新显示,直到放置新的叠加层之后——否则,一个没有叠加层的裸缓冲区会在瞬间可见。


(defvar my-eol-ruler nil
"A horizontal ruler stretching from eol (end of line) to the window edge.")
(make-variable-buffer-local 'my-eol-ruler)

(defvar my-eol-pilcrow nil
"A pilcrow symbol placed at the end of every line except the current line.")
(make-variable-buffer-local 'my-eol-pilcrow)

(defun my-eol-ruler-function ()
  (let* (
    (opoint (point))
    (window-width (window-width))
    (window-start (window-start))
    (window-end (window-end))
    (col-eovl
      (save-excursion
        (vertical-motion 1)
        (skip-chars-backward " \r\n" (- (point) 1))
        (- (current-column) (progn (vertical-motion 0) (current-column)))))
    (my-current-line-length (- (- window-width col-eovl) 3))
    (pilcrow
      (propertize (char-to-string ?\u00B6)
        'face '(:foreground "white")
        'cursor t))
    (pilcrow-underlined
      (propertize (char-to-string ?\u00B6)
        'face '(:foreground "white" :underline "yellow")
        'cursor t))
    (underline (propertize (char-to-string ?\u2009)
          'display `(space :width ,my-current-line-length)
          'face '(:underline "yellow")
          'cursor t)))
  (when (or my-eol-ruler my-eol-pilcrow)
    (dolist (description `(
        ,my-eol-ruler
        ,my-eol-pilcrow ))
      (remove-overlays (point-min) (point-max)
        'after-string description)) )
  (setq my-eol-ruler (concat pilcrow-underlined underline))
  (setq my-eol-pilcrow pilcrow)
  (save-excursion
    (end-of-line)
    (overlay-put (make-overlay (point) (point))
      'after-string my-eol-ruler ) )
  (message "point:  %s | window-start:  %s | window-end:  %s | point-max:  %s"
    (point)
    (window-start)
    (window-end)
    (point-max) )
  (save-excursion
    (goto-char window-end)
    (while (re-search-backward "\n" window-start t)
      (let* (
          (pbol (point-at-bol))
          (pbovl (save-excursion (vertical-motion 0) (point)))
          (peol (point))
          (peol-pbol-region-p
            (if (region-active-p)
              (= peol pbol)))
          (eol-inside-region-p
            (if (region-active-p)
              (and
                (<= reg-beg peol)
                (> reg-end peol))))
          (col-eovl
            (save-excursion
              (vertical-motion 1)
              (skip-chars-backward " \r\n" (- (point) 1))
              (- (current-column) (progn (vertical-motion 0) (current-column)))))
          (my-last-column (current-column))
          (window-width-bug-p (= my-last-column (- window-width 1)))
          (shazbot-pbol
            (save-excursion
              (end-of-line)
              (re-search-backward "\s\\|\t" pbol t) (+ (point) 1)))
          (wrapped-window-width-bug-p (= col-eovl (- window-width 1))) )
        (when
          (or
            (< opoint pbol)
            (> opoint peol))
        (overlay-put (make-overlay peol peol) 'after-string my-eol-pilcrow))))) ))

(add-hook 'post-command-hook 'my-eol-ruler-function)

缓冲区的开始,在错误发生之前。


缓冲区结束--从缓冲区开始处执行交互函数end-of-buffer时发生错误。

Error in post-command-hook (my-eol-ruler-function):
  (error "Invalid search bound (wrong side of point)")

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    另请参阅 Emacs 错误跟踪器功能请求 #22404(尚未实现,但邮件存档包含一个粗略的基本补丁草稿,该补丁为此特定问题创建了一个新钩子):https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22404

    • 在视觉重新显示之前测试 window-startwindow-end 的次要模式。
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; test-mode
    ;; A minor-mode for testing `window-start` / `window-end` BEFORE visual redisplay.
    
    (defvar test-this-command nil
    "This local variable is set within the `post-command-hook`; and,
    is also used by the `window-scroll-functions` hook.")
    (make-variable-buffer-local 'test-this-command)
    
    (defun test-post-command-hook-fn ()
    "A function attached to the `post-command-hook`."
      (setq test-this-command this-command)
      (test-demo-fn))
    
    (defun test-window-scroll-functions-fn (win _start)
    "A function attached to the `window-scroll-functions` hook."
      (test-demo-fn))
    
    (defun test-demo-fn ()
    "This is a test-mode demonstration function."
      (when
          (and
            test-mode
            test-this-command
            (window-live-p (get-buffer-window (current-buffer)))
            (not (minibufferp))
            (pos-visible-in-window-p (point)
              (get-buffer-window (current-buffer) (selected-frame)) t))
        (let* (
            (selected-window (selected-window))
            (window-start (window-start selected-window))
            (window-end (window-end selected-window t)) )
          (message "window-start: %s | window-end: %s" window-start window-end)
          (setq test-this-command nil) )))
    
    (define-minor-mode test-mode
    "A minor-mode for testing `window-start` / `window-end` BEFORE visual redisplay."
      :init-value nil
      :lighter " TEST"
      :keymap nil
      :global nil
      :group nil
      (cond
        (test-mode
          (set (make-local-variable 'scroll-conservatively) 101)
          (add-hook 'post-command-hook 'test-post-command-hook-fn nil t)
          (add-hook 'window-scroll-functions 'test-window-scroll-functions-fn nil t)
          (when (called-interactively-p 'any)
            (message "Turned ON `test-mode`.")))
        (t
          (kill-local-variable 'scroll-conservatively)
          (kill-local-variable 'test-this-command)
          (remove-hook 'post-command-hook 'test-post-command-hook-fn t)
          (remove-hook 'window-scroll-functions 'test-window-scroll-functions-fn t)
          (when (called-interactively-p 'any)
            (message "Turned OFF `test-mode`.") ))))
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    

    【讨论】:

      【解决方案2】:

      顺便说一句,我会说引发错误是因为您将 BOUND arg 传递给搜索函数。例如:

      (re-search-backward "\n" window-start t)
      
      (re-search-backward "\s\\|\t" pbol t)
      

      检查window-startpbol 的值。请记住,当您向后搜索时,边界不得大于当前位置(点)。

      【讨论】:

      • 感谢您查看此线程。我设置了一些消息来测试发生了什么,并尝试使用实际功能 (window-end)(window-start) 来查看发生了什么。我认为无法获得新的(window-start) 和新的(window-end),因为在新的缓冲区位置还没有发生重新显示。在post-command-hook 中使用(window-start)(window-end) 时,不考虑新的缓冲区布局。然而,我想避免重新展示。
      • 我明白了。不知道是否有一种简单的方法可以确定重新显示后 window-endwindow-start 将返回什么。听起来您最终会复制一堆重新显示或窗口计算代码。也许其他人有建议。或者,也许您可​​以完全想到另一种方法。无论如何,我认为这是您遇到错误的原因。
      • 嗯。 . .只是大声思考... 点已成功实现,无需重新显示。由于 new 点是可确定的,也许有一种方法可以根据 window-height、window-width、...来近似 new 目标区域。 . .?这种方法的问题在于,无法知道新的 可见窗口 布局可能包含多少个字符(也就是说,没有重新显示)。我当然希望有一个redisplay-internal 来预览重新显示实际发生时会发生什么。
      【解决方案3】:

      我认为您想使用jit-lock-register 而不是post-command-hook。这样,重新显示代码将在决定窗口启动后回调您,您将能够在显示缓冲区内容之前添加所需的叠加层。

      【讨论】:

      • 谢谢 - 我会阅读 jit-lock-register 并进行试验,看看我是否能弄清楚 begend 是如何确定的,然后一旦我理解那,我将看看如何将其应用于我的自定义叠加功能。这将是一项正在进行的工作。 . .
      猜你喜欢
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-14
      相关资源
      最近更新 更多