【问题标题】:forward-paragraph in GNU EmacsGNU Emacs 中的前向段落
【发布时间】:2012-11-28 22:58:52
【问题描述】:

我正在阅读 Robert J. Chassell 的“An Introduction to Programming in Emacs Lisp”。我有一个问题。在节点“fwd-para while”(forward-paragraphwhile 循环的解释)中,它说:

有趣的是,在我们离开段落之间的空间之前,循环计数不会减少,除非我们到达缓冲区的末尾或不再看到段落分隔符的本地值。

我看不懂,谁能给我解释一下?谢谢。

while 循环如下所示:

;; going forwards and not at the end of the buffer
(while (and (> arg 0) (not (eobp)))

  ;; between paragraphs
  ;; Move forward over separator lines...
  (while (and (not (eobp))
              (progn (move-to-left-margin) (not (eobp)))
              (looking-at parsep))
    (forward-line 1))
  ;;  This decrements the loop
  (unless (eobp) (setq arg (1- arg)))
  ;; ... and one more line.
  (forward-line 1)

  (if fill-prefix-regexp
      ;; There is a fill prefix; it overrides parstart;
      ;; we go forward line by line
      (while (and (not (eobp))
                  (progn (move-to-left-margin) (not (eobp)))
                  (not (looking-at parsep))
                  (looking-at fill-prefix-regexp))
        (forward-line 1))

    ;; There is no fill prefix;
    ;; we go forward character by character
    (while (and (re-search-forward sp-parstart nil 1)
                (progn (setq start (match-beginning 0))
                       (goto-char start)
                       (not (eobp)))
                (progn (move-to-left-margin)
                       (not (looking-at parsep)))
                (or (not (looking-at parstart))
                    (and use-hard-newlines
                         (not (get-text-property (1- start) 'hard)))))
      (forward-char 1))

    ;; and if there is no fill prefix and if we are not at the end,
    ;;     go to whatever was found in the regular expression search
    ;;     for sp-parstart
    (if (< (point) (point-max))
        (goto-char start))))

感谢您的编辑和回答。关于前段,我还有另外三个问题:

  1. (progn (move-to-left-margin) (not (eobp))) 是什么意思?如果(not (eobp)) 为真,那么(progn (move-to-left-margin) (not (eobp))) 不应该始终为真吗?

  2. 关于这一行:

    ;; ... and one more line.
    (forward-line 1)
    

    为什么要多转发一行?

  3. 关于本段:

    这个while 循环让我们向前搜索“sp-parstart”,即 可能的空格与本地值的组合 段落或段落分隔符的开头。

    为什么the local value of the start of a paragraph or of a paragraph separator?就我而言,段落分隔符的条件已经在while的第一个while循环中处理过了。

【问题讨论】:

  • (move-to-left-margin) 可能会向前移动点,所以 (eobp) 事先为假并不意味着它会再次为假。
  • 你的意思是缓冲区局部变量left-margin可以是(point-max)吗?
  • 嗯,它可以,但这不是我的意思。我的意思是,对于任何给定的文本行,当前点可能位于左边距列的左侧(也可以通过文本属性指定,因此变量不一定相关),因此在移动到左边距之前和之后测试(eobp) 并不是没有意义的。

标签: emacs elisp


【解决方案1】:

并不有趣!如果您查看forward-paragraph 的文档字符串,您会看到它:

返回要移动的段落数。

这意味着如果你在缓冲区末尾的一个段落,并评估(forward-paragraph 3),它将返回2,这意味着它前进了一个段落,但你请求的其余两个步骤不能被带走。

为了返回未执行的步数,forward-paragraph 返回(就在您引用的代码块之后)值arg。因此,arg 必须仅在 forward-paragraph 实际前进一个段落时递减。我相信你可以弄清楚其余的。

(如果您想知道返回值在哪里使用,它在fill-paragraph 中以避免填充缓冲区末尾不存在的段落。)

ETA:我看到您添加了三个新问题。我将告诉您如何尝试自己回答这些问题,而不是回答它们,方法是使用Emacs Lisp debugger 逐步检查forward-paragraph 的代码,看看它实际上在做什么。

  1. 通过键入 C-h C-f forward-paragraph RET 查找forward-paragraph 的源代码,然后单击*Help* 缓冲区中的链接。

  2. 运行eval-defun命令重新编译forward-paragraph进行调试,例如输入C-M-x

  3. 通过键入 M-x debug-on-entry RET forward-paragraph RET 打开 forward-paragraph 的调试。

  4. 转到合适的缓冲区并运行forward-paragraph,例如键入M-}

  5. 现在您在调试器中,它会显示调用堆栈和正在评估的当前表单。您可以键入 d 进入该表单并查看其子表单的评估,或键入 c 以完全评估该表单并查看其结果,然后 q kbd> 退出调试器。 (有关更多调试器命令,请参阅documentation。)

  6. 逐步执行forward-paragraph,直到您了解它在做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多