From: Drew Adams <drew.adams@oracle.com>
To: Marcin Borkowski <mbork@mbork.pl>, Jean Louis <bugs@gnu.support>
Cc: Eric S Fraga <e.fraga@ucl.ac.uk>,
"help-gnu-emacs@gnu.org" <help-gnu-emacs@gnu.org>
Subject: RE: [External] : Re: How to detect words being added and removed to a buffer in a minor mode?
Date: Mon, 21 Nov 2022 18:56:18 +0000 [thread overview]
Message-ID: <SJ0PR10MB5488E5CDDAD5DD64823C42D1F30A9@SJ0PR10MB5488.namprd10.prod.outlook.com> (raw)
In-Reply-To: <87tu2scjmt.fsf@mbork.pl>
[-- Attachment #1: Type: text/plain, Size: 1375 bytes --]
> Would a mode which displays the number of words in the current buffer
> whenever you stop typing for a few seconds be enough? (I am not sure
> how exactly you want to obtain the "number of words typed in today".)
I already mentioned that you can get this for
free in the mode-line, from redisplay, using
library modeline-region.el.
Well, you get it automatically for the active
region, not the whole buffer. To see it for
the full buffer at any time, just use `C-x C-x'.
If someone is interested in instead showing it
always for the full buffer (not only when it's
the active region), that's easily done by
tweaking the source code.
__
Attached is such a quick tweaking (could be
simplified). I just added an option,
`mlr-use-whole-buffer-flag' for this. Set
it to non-nil to continually get full-buffer
(or narrowed-buffer) counts instead of
active-region counts.
Essentially all I did was change uses of
(region-beginning) and (region-end) to
(point-min) and (point-max), and test the
added option for which pair to use.
Just replace the same definitions in
modeline-region.el with the versions in the
attached.
(I won't change the library this way, as I
don't think it's generally useful.)
If all you care about is the number of words
in the buffer, you can considerably pare
down the code - the result will be small.
[-- Attachment #2: throw-modeline-region-BUFFER.el --]
[-- Type: application/octet-stream, Size: 7778 bytes --]
(defcustom mlr-use-whole-buffer-flag nil
"Non-nil means use the whole buffer, not the active region."
:group 'modeline-region :type 'boolean)
(defconst mlr--region-style-default
'(;; Format string
(if mlr-rect-p
(if (and (boundp 'mlr-rectangle-style)
(eq 'rows+cols+words+chars mlr-rectangle-style))
mlr-rows+cols+words+chars-format ; " %d rows, %d cols, %d words, %d chars"
mlr-rows+cols-format) ;" %d rows, %d cols"
(if (eq 'lines+words+chars mlr-non-rectangle-style)
mlr-lines+words+chars-format ; " %d lines, %d words, %d chars"
mlr-lines+chars-format)) ; " %d lines, %d chars"
;; Rows (rectangle) / Lines (region)
(if mlr-rect-p
(1+ (abs (- (line-number-at-pos (region-end)) ; Rows (rectangle)
(line-number-at-pos (region-beginning)))))
(if mlr-use-whole-buffer-flag
(count-lines (point-min) (point-max))
(count-lines (region-beginning) (region-end)))) ; Lines (region)
;; Columns (rectangle) / Chars (short region) or Words (full region)
(if mlr-rect-p
(let ((rpc (save-excursion (rectangle--pos-cols (region-beginning) (region-end)))))
(abs (- (car rpc) (cdr rpc)))) ; Columns (rectangle)
(if (eq 'lines+words+chars mlr-non-rectangle-style)
(if mlr-use-whole-buffer-flag
(count-words (point-min) (point-max))
(count-words (region-beginning) (region-end))) ; Words (full region)
(if mlr-use-whole-buffer-flag
(- (point-max) (point-min))
(- (region-end) (region-beginning))))) ; Chars (short region)
;; Words (rectangle) / Chars (full region)
(if (and mlr-rect-p
(boundp 'mlr-rectangle-style)
(eq 'rows+cols+words+chars mlr-rectangle-style))
(let ((words 0)
beg end this-ws)
(dolist (beg+end (extract-rectangle-bounds (region-beginning) (region-end)))
(setq beg (car beg+end)
end (cdr beg+end)
this-ws (count-words beg end)
words (+ words this-ws))
(unless mlr-count-partial-words-flag
(when (and (not (zerop this-ws))
(char-after (1- beg)) (equal '(2) (syntax-after (1- beg)))
(char-after beg) (equal '(2) (syntax-after beg)))
(setq words (1- words)
this-ws (1- this-ws)))
(when (and (not (zerop this-ws))
(char-after (1- end)) (equal '(2) (syntax-after (1- end)))
(char-after end) (equal '(2) (syntax-after end)))
(setq words (1- words)))))
words) ; Words (rectangle)
(and (eq 'lines+words+chars mlr-non-rectangle-style)
(if mlr-use-whole-buffer-flag
(- (point-max) (point-min))
(- (region-end) (region-beginning))))) ; Chars (full region)
;; Chars (rect)
(and mlr-rect-p
(boundp 'mlr-rectangle-style)
(eq 'rows+cols+words+chars mlr-rectangle-style)
(let ((chars 0)
beg end)
(dolist (beg+end (extract-rectangle-bounds (region-beginning) (region-end)))
(setq beg (car beg+end)
end (cdr beg+end)
chars (+ chars (- end beg))))
chars))) ; Chars (rectangle)
"Default value for option `mlr-region-style'.
It corresponds to the Customize `Value Menu' choice
`Lines (& words) & chars / rows & columns (& words & chars)'.")
(defcustom mlr-region-style mlr--region-style-default
"Mode-line info about the active region.
Choose a style from the `Value Menu':
* `Characters'. Number of characters in region or rectangle.
* `Bytes'. Number of bytes in region or rectangle.
* `Lines (& words) & chars / rows & columns (& words & chars)'.
For a regular region, you see lines and characters.
For a rectangular region you see rows and columns.
This can optionally include words for region and words & chars for
rectangle: see options `mlr-non-rectangle-style' and
`mlr-rectangle-style' (for Emacs 26+).
To change the concrete formatting used, change variables
`mlr-lines+chars-format', `mlr-lines+words+chars-format',
`mlr-rows+cols-format', and `mlr-rows+cols+words+chars-format'.
* `Customized format'. An arbitrary format you specify."
:group 'modeline-region
:type
`(choice
(const :tag "Characters"
(mlr-chars-format
(if (and mlr-rect-p (fboundp 'extract-rectangle-bounds)) ; Emacs 26+
(let ((chars 0)
beg end)
(dolist (beg+end (extract-rectangle-bounds (region-beginning) (region-end)))
(setq beg (car beg+end)
end (cdr beg+end)
chars (+ chars (- end beg))))
chars)
(if mlr-use-whole-buffer-flag
(- (region-end) (region-beginning))
(- (point-max) (point-min))))))
;; Should we use this instead, for calculating bytes? It can sometimes be costly.
;; See https://emacs.stackexchange.com/a/29912/105.
;; (const :tag "Bytes: \"_ bytes\""
;; (" %d bytes"
;; (if (fboundp 'bufferpos-to-filepos) ; Emacs 25+
;; (- (bufferpos-to-filepos (region-end) 'exact)
;; (bufferpos-to-filepos (region-beginning) 'exact))
;; (string-bytes (buffer-substring-no-propertiesw (region-beginning) (region-end))))))
;;
(const :tag "Bytes"
(mlr-bytes-format
(if (and mlr-rect-p (fboundp 'extract-rectangle-bounds)) ; Emacs 26+
(let ((bytes 0)
beg end)
(dolist (beg+end (extract-rectangle-bounds (region-beginning) (region-end)))
(setq beg (car beg+end)
end (cdr beg+end)
bytes (+ bytes (string-bytes (buffer-substring-no-properties beg end)))))
bytes)
(string-bytes (if mlr-use-whole-buffer-flag
(buffer-substring-no-properties (region-beginning) (region-end))
(buffer-substring-no-properties (point-min) (point-max)))))))
;; This is just the single value that's the value of `mlr--region-style-default'.
(restricted-sexp :tag "Lines (& words) & chars / rows & columns (& words & chars)"
:match-alternatives ((lambda (val) (equal val mlr--region-style-default))))
(list :tag "Customized format"
(string :tag "Format string")
(repeat :inline t (sexp :tag "Sexp argument for format string")))))
(defun mlr-show-region-p ()
"Whether to show mode-line region info and highlighting.
Return non-nil if the region is active and nonempty, or emptiness is
OK. Option `mlr-empty-region-flag' non-nil means emptiness is OK.
More precisely, return non-nil for the active region if either of
these conditions is true:
* The region is not empty.
* Option `mlr-empty-region-flag' is non-nil, and the last input did
not use `mouse-1'.
The `mouse-1' test prevents highlighting the mode line whenever you
press `mouse-1' without dragging at least one character."
(ignore-errors
(if mlr-use-whole-buffer-flag
(and (not (eq 'down-mouse-1 (car-safe last-input-event)))
(not (mouse-movement-p last-input-event)))
(and (region-active-p)
(or (> (region-end) (region-beginning))
(and mlr-empty-region-flag
(not (eq 'down-mouse-1 (car-safe last-input-event)))
(not (mouse-movement-p last-input-event))))))))
next prev parent reply other threads:[~2022-11-21 18:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-19 20:44 How to detect words being added and removed to a buffer in a minor mode? Dmitrii Pisarenko
2022-11-21 9:39 ` Eric S Fraga
2022-11-21 10:08 ` Jean Louis
2022-11-21 10:34 ` Emanuel Berg
2022-11-21 11:27 ` Eric S Fraga
2022-11-21 12:40 ` Emanuel Berg
2022-11-21 17:17 ` Marcin Borkowski
2022-11-21 17:21 ` Marcin Borkowski
2022-11-21 18:56 ` Drew Adams [this message]
2022-11-22 15:33 ` Emanuel Berg
2022-11-26 6:14 ` Marcin Borkowski
2022-11-26 14:51 ` Emanuel Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=SJ0PR10MB5488E5CDDAD5DD64823C42D1F30A9@SJ0PR10MB5488.namprd10.prod.outlook.com \
--to=drew.adams@oracle.com \
--cc=bugs@gnu.support \
--cc=e.fraga@ucl.ac.uk \
--cc=help-gnu-emacs@gnu.org \
--cc=mbork@mbork.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.