2012-11-28 3 views
2

Я читаю «An Introduction to Programming in Emacs Lisp» от Robert J. Chassell. И у меня есть вопрос. В узле «fwd-para while» (объяснение while петли forward-paragraph), он говорит:forward-paragraph в GNU Emacs

Интересно, что счетчик цикла не уменьшается, пока мы не оставить пространство между абзацами, если мы не придем к концу буфера или перестает видеть локальное значение разделителя абзацев.

Я не могу это понять, может кто-нибудь объяснить это мне? Благодарю.

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? Насколько мне известно, состояние разделителя абзацев уже обработано в первом цикле whilewhile.

+0

'(перемещение к левому краю)' может перемещать точку вперед, поэтому '(eobp)' является ложным заранее, не означает, что после этого он снова будет ложным. – phils

+0

Вы имеете в виду, что буфер локальной переменной 'left-margin' может быть (point-max)? – user159

+0

Ну, это может быть, но это не то, что я имею в виду. Я имею в виду, что для любой заданной строки текста текущая точка может находиться слева от столбца с левым полем (который также может быть указан через свойство text, поэтому переменная необязательно релевантна), и поэтому бессмысленно тестировать '(eobp)' как до, так и после перехода на левое поле. – phils

ответ

2

Это не что интересно! Если вы посмотрите на docstring для forward-paragraph, вы увидите, что это:

Возвращает количество абзацев, оставшихся для перемещения.

Это означает, что если вы один абзац от конца буфера, и оценить (forward-paragraph 3), он будет возвращать 2, а это означает, что он сделал шаг вперед на один пункт, а остальные два шага, которые вы просили не может быть приняты.

Чтобы вернуть количество шагов, не предпринятых, forward-paragraph возвращает (сразу после кода кода, который вы указали) значение arg. Таким образом, arg должен быть уменьшен только тогда, когда forward-paragraph действительно продвигается вперед по абзацу. Я уверен, что вы можете выяснить остальное.

(Если вам интересно, где используются возвращаемое значение, это в fill-paragraph, чтобы избежать заполнений несуществующего пункта в конце буфера.)

ETA: Я вижу, что вы добавили три новые вопросы. Вместо того, чтобы отвечать на них, я расскажу вам, как вы можете попытаться ответить на них сами, используя Emacs Lisp debugger, чтобы выполнить код для forward-paragraph и посмотреть, что он на самом деле делает.

  1. Найти исходный код для forward-paragraph набрав C-ч C-F вперед абзацев RET, а затем нажав на ссылку в *Help* буфере.

  2. Перекомпилируйте forward-paragraph для отладки, выполнив команду eval-defun, например, набрав С-М-х.

  3. Включите отладку forward-paragraph, набрав M-х отладки на входе RET вперед пункт RET.

  4. Перейдите в подходящий буфер и запустите forward-paragraph, например, набрав M-}.

  5. Теперь вы находитесь в отладчике, в котором отображается стек вызовов и текущая форма. Вы можете ввести d, чтобы перейти к этой форме и посмотреть оценку ее подформ, или c, чтобы полностью оценить форму и посмотреть ее результат, и q для выхода из отладчика. (См. documentation для получения дополнительных команд отладчика.)

  6. Пройдите через выполнение forward-paragraph, пока вы не поймете, что он делает.

+0

Спасибо, и я отредактировал свои вопросы. – user159

Смежные вопросы