5

After far too many years of counting the number of characters in the region by doing M-: (- (point) (mark)), I just discovered M-= (count-words-region). Much better! But now I'm looking for a way to obtain the number of bytes that the characters in the region occupy in the buffer's coding system--typically, or always really, UTF-8. Is there an easy way to do this?

For context, I've been doing some code golfing on codegolf.stackexchange.com in a language that supports various Unicode operators, and I need to know how many bytes my submission occupies. So far I've been saving the region to a file, doing ls -l on it, then deleting it. I could easily whip up a function to do this automatically, but it seems rather inelegant.

  • You could also probably open the file in hexl mode, you could then use the regular Emacs commands to count bytes. – wvxvw Jan 8 '17 at 5:56
  • I'm typically in a shell buffer when I want to know the byte count, so hexl-mode isn't really practical. A nice thought though. – Sean Jan 8 '17 at 20:19
5

Sounds like you are asking for something like this:

(defun region-bytes ()
  (interactive)
  (let ((strg  (if (use-region-p)
                   (buffer-substring-no-properties (region-beginning) (region-end))
                 "")))
    (message "Region has %d bytes" (string-bytes strg))))

You might also be interested in showing the region size in the mode line. You can do that with library modeline-posn.el -- see Mode Line Position. One of the style choice is to show the number of bytes in the active region -- just what you are asking for here. The difference is that it would always be shown (when the region is active), instead of being reported as a message only on demand (as per the command above).

3

While Drew's answer will work correctly in many cases (where utf-8 is pervasive and if you don't use DOS-style EOLs), if you want to make it work reliably for "all" buffers, you could do something like the following:

(defun region-bytes (start end)
  "Return the number of bytes used by the region."
  (interactive "r")
  (message "Region has %d bytes"
           (- (bufferpos-to-filepos end 'exact)
              (bufferpos-to-filepos start 'exact))))

and for cases where efficiency is more important than precision, you could pass approximate instead of exact, in which case bufferpos-to-filepos will always be very fast tho it will not handle correctly cases like GBK or utf-2022 encodings.

  • +1. Good to know about bufferpos-to-file-pos. It is apparently available only in Emacs 25 and later. And it apparently presumes that the buffer is associated with a file (?). You speak of "all" buffers, but I imagine the quotes mean (at least) that it is limited to file buffers. – Drew Jan 27 '17 at 3:17
  • The notion of "bytes" here only makes sense with respect to some encoding. bufferpos-to-file-pos uses the encoding specified by buffer-file-coding-system, but other than that it should also work in a non-file buffer (e.g. if you let-bind buffer-file-coding-system around the call). – Stefan Jan 27 '17 at 3:29
  • I see; thanks. I did not bother to look at the code - looked at only the doc. The doc mentions only "the file". It might be more useful if what you say in your comment, or similar, were added. – Drew Jan 27 '17 at 3:31
  • I see also that the doc says that bufferpos-to-file-pos with type exact "may end up re-(en/de)coding a large part of the file/buffer", which might not be desirable in some contexts, for performance reasons. That text seems misleading, BTW, since it suggests that the buffer can be modified, with some of its text changing coding system. If I read the code right, when b-t-f-p re-(en/de)codes the text it puts the result in a different, temporary buffer, and returns the size - the original text does not have its encoding changed. – Drew Feb 5 '17 at 17:07

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.