1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
;;; matlab-ccount.el --- character count minor mode -*- lexical-binding: t -*-
;; Copyright (C) 2024 Free Software Foundation, Inc.
;; Author: Eric Ludlam
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see https://www.gnu.org/licenses/.
;;; Commentary:
;;
;; Make it easier to participate in the mini-hack contest by showing how many
;; code characters are in your script.
;; https://www.mathworks.com/matlabcentral/contests.html
;;
;; Based on contest rules, comments, newlines, and spaces at EOL don't
;; count toward character counts.
;;; Code:
(easy-mmode-define-minor-mode matlab-character-count-minor-mode
"Toggle character count minor-mode.
When active, this mode shows the # of characters in this buffer.
MATLAB Character counter ignores comments and indentation spaces."
:init-value nil
:lighter (:eval (format " %d" (matlab-count-characters)))
:keymap nil ; empty mode-map
nil ; empty body
)
;;; Character Counting
;;
(defun matlab-count-characters ()
"Return a number that is the number of characters in this buffer.
MATLAB character count will ignore comments, indentation spaces,
and trailing semi-colons so long as there are no chars after the ;"
(save-excursion
(goto-char (point-min))
(let ((all (- (point-max) 1))
(comments 0)
(indents 0)
(trail-semi 0)
(last-land -1))
;; The contest starts with a fresh figure every time. Our
;; script needs to reset any figure we're going to use, so skip that up front.
(while (looking-at "\\(clf\\|figure\\|reset(gcf)\\|clear\\);?")
(goto-char (match-end 0))
(skip-chars-forward "\n\t "))
(setq all (- all (point) -1))
;; Scan for bum syntax across the rest of the system
(while (and (not (eobp)) (re-search-forward "\\s<\\|;?\\s-*$" nil t)
(not (= last-land (point))))
(goto-char (match-beginning 0))
(setq last-land (point))
(cond
((looking-at ";?$")
(setq indents (+ indents (- (match-end 0) (match-beginning 0))))
(goto-char (match-end 0))
(when (not (eobp))
(setq indents (- indents (- (point)
(progn
;; Also skip leading indent on next line
(skip-chars-forward "\n\t ")
(point)))))
)
)
((and (looking-at "\\s-+") (beginning-of-line))
(setq indents (+ indents (- (match-end 0) (match-beginning 0))))
(goto-char (match-end 0))
)
((looking-at "\\s<")
(setq comments (- comments (- (point)
(progn
(forward-comment 100000)
(point))))))
(t
;; Some stuff like . triggers big regex, but isn't in the above.
;; Skip over whatever it is.
(goto-char (match-end 0)))
))
(- all comments indents trail-semi)
)))
(provide 'matlab-ccount)
;;; matlab-ccount.el ends here
;; LocalWords: Ludlam EOL mmode keymap defun setq eobp progn
|