unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
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))))))))


  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

  List information: https://www.gnu.org/software/emacs/

* 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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).