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 下使用。