计算顶层 Sexp 和注释的数目

Emacs 自带了可以计算 Line/Word/Character/Page 的命令,试试计算最外层 Sexp 以及注释的数量,不知道有用没有。

Toplevel Sexp 就是最外层的 Sexp,两个 Toplevel Sexp 之间有文字就算一个注释。比如以下有 2 个 Sexp 和 3 个注释。

;; * 开头

(defun count-sexps ()
  "Count toplevel sexps."
  (interactive)
  (save-excursion
    (let ((count 0))
      (goto-char (point-min))
      (while (setq next (scan-sexps (point) 1))
        (goto-char next)
        (setq count (1+ count)))
      (message "Buffer has %s sexp%s" count (if (= count 1) "" "s"))
      count)))

;; * 连续两个 Toplevel Sexp 之间如果包含任意字符,
;;   表示这儿有一个注释。

(defun count-comments ()
  "Count comments outside toplevel sexps."
  (interactive)
  (let (begs beg ends end points (count 0))
    (save-excursion
      (goto-char (point-min))
      (while (setq end (scan-sexps (point) +1))
        (goto-char end)
        (push end ends))
      (setq ends (nreverse ends))
      (goto-char (point-max))
      (and (nth 4 (syntax-ppss)) (goto-char (line-beginning-position)))
      (while (setq beg (scan-sexps (point) -1))
        (goto-char beg)
        (push beg begs))
      (while begs
        (push (pop begs) points)
        (push (pop ends) points))
      (setq points (nreverse points))
      (setq points (append (list (point-min)) points (list (point-max))))
      (while points
        (goto-char (pop points))
        (and (re-search-forward "[^\n\f]+" (pop points) t)
             (setq count (1+ count)))))
    (message "Buffer has %s comment%s" count (if (= count 1) "" "s"))
    count))

;; * 结尾

上面用到了 scan-sexps,因此对所在的 Major Mode 有要求,比如 count-comments 应该只能在 Lisp 下使用。

1 个赞

如果你用 paredit-mode 的话,有个类似函数 paredit-count-sexps-forward

第二个函数也可以用 parse-sexp-ignore-comments 来实现

1 个赞

我每天都用 ParEdit,但依旧很不了解它,不知道有这个函数。