(defvar word-count-rule-chinese "\\cc"
"A regexp string to match Chinese characters.")
(defvar word-count-rule-nonespace "[^[:space:]]"
"A regexp string to match none pace characters.")
(defvar word-count-rule-ansci "[A-Za-z0-9][A-Za-z0-9[:punct:]]*"
"A regexp string to match none pace characters.")
(defun special-words-count (start end regexp)
"Count the word from START to END with REGEXP."
(let ((count 0))
(save-excursion
(goto-char start)
(while (and (< (point) end) (re-search-forward regexp end t))
(setq count (1+ count))))
count))
;;;###autoload
(defun Chinese-word-count (&optional beg end)
"Chinese user preferred word count.
If BEG = END, count the whole buffer."
(interactive (list (mark) (point)))
(let ((min (if (= beg end) (point-min) beg))
(max (if (= beg end) (point-max) end))
list)
(setq list
(mapcar (lambda (r)
(special-words-count min max r))
(list
word-count-rule-chinese
word-count-rule-nonespace
word-count-rule-ansci
)))
(message "字数:%d,字符数(不计空格):%d,字符数(记空格):%d,非中文单词:%d,中文:%d"
(+ (car list) (car (last list)))
(cadr list)
(- max min)
(car (last list))
(car list))))
(defvar words-count-rule-chinese "\\cc"
"A regexp string to match Chinese characters.")
(defvar words-count-rule-nonespace "[^[:space:]]"
"A regexp string to match none pace characters.")
(defvar words-count-rule-ansci "[A-Za-z0-9][A-Za-z0-9[:punct:]]*"
"A regexp string to match none pace characters.")
(defvar words-count-regexp-list
(list words-count-rule-chinese
words-count-rule-nonespace
words-count-rule-ansci)
"A list for the regexp used in `advance-words-count'.")
(defvar words-count-message-func 'message--words-count
"The function used to format message in `advance-words-count'.")
(defun special--words-count (start end regexp)
"Count the word from START to END with REGEXP."
(let ((count 0))
(save-excursion
(save-restriction
(goto-char start)
(while (and (< (point) end) (re-search-forward regexp end t))
(setq count (1+ count)))))
count))
(defun message--words-count (list start end &optional arg)
"Display the word count message.
Using the LIST passed form `advance-words-count'. START & END are
required to call extra functions, see `count-lines' &
`count-words'. When ARG is specified, display a verbose buffer."
(message
(format
(if arg
"
-----------~*~ Words Count ~*~----------
Word Count .................... %d
Characters (without Space) .... %d
Characters (all) .............. %d
Number of Lines ............... %d
ANSCII Chars .................. %d
%s
========================================
"
"Wc:%d,Ns:%d,Al:%d,Ln:%d,An:%d,%s")
(+ (car list) (car (last list)))
(cadr list)
(- end start)
(count-lines start end)
(car (last list))
(concat
(unless (= 0 (car list))
(format (if arg
" Chinese Chars ................. %d\n"
"Zh:%d,")
(car list)))
(format (if arg
" English Words ................. %d\n"
"En:%d")
(count-words start end))))))
;;;###autoload
(defun advance-words-count (beg end &optional arg)
"Chinese user preferred word count.
If BEG = END, count the whole buffer. If called initeractively,
use minibuffer to display the messages. The optional ARG will be
passed to `message--words-count'.
See also `special-words-count'."
(interactive (if (use-region-p)
(list (region-beginning)
(region-end)
(or current-prefix-arg nil))
(list nil nil (or current-prefix-arg nil))))
(let ((min (or beg (point-min)))
(max (or end (point-max)))
list)
(setq list
(mapcar
(lambda (r) (special--words-count min max r))
words-count-regexp-list))
(if (called-interactively-p 'any)
(message--words-count list min max arg)
list)))
(defmacro words-count-define-func (name message rules &optional bind regexp)
"Define the function used to format the strings displayed.
NAME = Function's name.
MESSAGE = A string used to display.
RULES = A list of functions to form the string.
BIND = A boolean, if ture, bind the function to
`words-count-message-func'.
REGEXP = A list of regexp to call, if not specified, use
`words-count-regexp-list'."
`(progn
(defun ,name (cons &optional arg)
"Format a string to be shown for `message--words-count'.
Using the CONS passed form `advance-words-count'. See
`count-lines' & `count-words'. When ARG is specified, display
verbosely."
(let ,(append
'((start (car cons)))
'((end (cdr cons)))
(if regexp
`(words-count-regexp-list ,regexp))
'(list))
(setq list (advance-words-count start end))
,(append `(format ,message) rules)))
(if ,bind
(setq words-count-message-func (function ,name)))))
例子:
(words-count-define-func users-prefix-func
"lines: %3d non ascii words: %3d chars: %3d"
((count-lines start end)
(car list))
(- end start))
t
(list "[^[:ascii:]]"))