我怎样才能改进这个Emacs Lisp Intro的“创建索引条目”练习的解决方案?

时间:2011-02-07 23:49:11

标签: emacs lisp elisp

我已经为第11.4节(循环练习)中的练习编写了这个解决方案:

(defun texinfo-index-dfns-in-par ()
  "Create an index entry at the beginning of the paragraph for every '@dfn'."
  (interactive)
  (save-excursion
    (forward-paragraph)
    (let ((bound (point)))
      (backward-paragraph)
      (let ((insert-here (point)))
        (while (search-forward "@dfn{" bound t)
          (let* ((start (point))
                 (end (1- (search-forward "}" bound)))
                 (dfn (buffer-substring start end)))
            (save-excursion
              (goto-char insert-here)
              (newline)
              (setq insert-here (point))
              (insert "@cindex " dfn)
              (while (< insert-here (line-beginning-position))
                (join-line))
              (end-of-line)
              (setq insert-here (point))
              (forward-paragraph)
              (setq bound (point)))))))))

虽然它正在发挥作用,但对我来说感觉很复杂。我想知道如何简化这段代码。我也对其他可能的改进感兴趣。

修改

泰勒的回答很棒。随着范围的缩小,我可以编写更简洁,更清晰的版本:

(defun texinfo-index-dfns-in-par ()
  "Create an index entry at the beginning of the paragraph for every '@dfn'."
  (interactive)
  (save-excursion
    (mark-paragraph)
    (save-restriction
      (narrow-to-region (point) (mark))
      (while (search-forward "@dfn{" nil t)
        (let ((start (point))
              (end (1- (search-forward "}"))))
          (save-excursion
            (goto-char (point-min))
            (insert "\n@cindex " (buffer-substring start end))
            (while (> (line-number-at-pos) 2) (join-line))
            (narrow-to-region (line-end-position) (point-max))))))))

2 个答案:

答案 0 :(得分:3)

要注意的一件事是缩小范围。你可以使用缩小来绕过你正在做的很多弹跳。

(mark-paragraph)
(narrow-to-region)

将函数的范围限制为当前段落并将点移动到开头。然后,您可以开始向前搜索,而无需担心移过当前段落。当你完成后,

(widen)

恢复要查看的其余缓冲区。

答案 1 :(得分:2)

您可以将search-forwardbuffer-substring替换为re-search-forwardmatch-string(注意:未经测试):

(while (re-search-forward "@dfn{\\([^}]+\\)}" nil t)
  (save-excursion
    (goto-char (point-min))
    (insert "\n@cindex " (match-string 1))
    (while (> (line-number-at-pos) 2) (join-line))
    (narrow-to-region (line-end-position) (point-max))))