开发者

Formatting an Integer using ISO-prefixes for kB,MB,GB,... and kiB,MiB,GiB,

I looking for the function that prints file size on the mode-line in size-indication-mode. I have searched for size-indication-mode in the source but cannot find a code-references to it. So where is the function that prints for e开发者_StackOverflowxample 22k

when file is approximately 22 kilobytes big?

What about difference between - kilobytes (kB), 1000 bytes, and - kibibytes (KiB), 1024 bytes, as defined at

Shouldn't Emacs support both?

This is of course not that hard to write but why reinvent the wheel?

http://en.wikipedia.org/wiki/Kibibyte


I noticed that emacs dev (bzr) just go a new function, file-size-human-readable() defined. It does just what I asked for.

Some emacs developer must have heard my call :)


See C-hf format-mode-line RET, and C-hv mode-line-format RET.

Enabling size-indication-mode simply causes of %I to be added into the buffer's local mode-line-format string, and the C function takes care of the rest.

You can use %i instead to see the buffer size in bytes.

If you want something to which you can supply an arbitrary value, there's at least one elisp function along these lines provided with Emacs (in the ls-lisp module):

C-hf ls-lisp-format-file-size RET


Here's the function I use.

(defconst number-to-string-approx-suffixes
  '("k" "M" "G" "T" "P" "E" "Z" "Y"))
(defun number-to-string-approx-suffix (n &optional binary)
  "Return an approximate decimal representation of NUMBER as a string,
followed by a multiplier suffix (k, M, G, T, P, E, Z, Y). The representation
is at most 5 characters long for numbers between 0 and 10^19-5*10^16.
Uses a minus sign if negative.
NUMBER may be an integer or a floating point number.
If the optional argument BINARY is non-nil, use 1024 instead of 1000 as
the base multiplier."
  (if (zerop n)
      "0"
    (let ((sign "")
          (b (if binary 1024 1000))
          (suffix "")
          (bigger-suffixes number-to-string-approx-suffixes))
      (if (< n 0)
          (setq n (- n)
                sign "-"))
      (while (and (>= n 9999.5) (consp bigger-suffixes))
        (setq n (/ n b) ; TODO: this is rounding down; nearest would be better
              suffix (car bigger-suffixes)
              bigger-suffixes (cdr bigger-suffixes)))
      (concat sign
                  (if (integerp n)
                  (int-to-string n)
                (number-to-string (floor n)))
              suffix))))

I use it in the size column of the buffer menu.

(defvar Buffer-menu-buffer+size-shorten 'binary)
(defadvice Buffer-menu-buffer+size (before Buffer-menu-shorten-size
                                    compile activate)
  "Shorten the size column in a buffer menu by using multiplier suffixes
\(k, M, G, T\).
This is done only if `Buffer-menu-buffer+size-shorten' is non-nil.
If `Buffer-menu-buffer+size-shorten' is the symbol `binary', use binary
multipliers (powers of 1024). Otherwise use decimal (powers of 1000)
multipliers."
  (if Buffer-menu-buffer+size-shorten
      (let ((binary (eq Buffer-menu-buffer+size-shorten 'binary)))
        (save-match-data
          (if (string-match "^[0-9]+$" size)
              (setq size (number-to-string-approx-suffix (string-to-number size)
                                                         binary)))))))


Ok, I hacked up a solution myself. Should be close to what size-indication-mode provides

(defun number-to-iso-postfixed-string (number &optional binary)
  "Convert NUMBER to ISO-postfixed string.
If BINARY is non-nil use bibytes prefixes KiB, MiB, GiB instead of
kB, MB, GB etc."
  (let ((scale (if binary 1024.0 1000.0))
        (postfix nil))
    (concat (if (< number scale)
                (if (zerop number) "0" (number-to-string number))
                (format "%.1f"
                        (cond ((< number (expt scale 2)) (setq postfix "k") (/ number (expt scale 1)))
                              ((< number (expt scale 3)) (setq postfix "M") (/ number (expt scale 2)))
                              ((< number (expt scale 4)) (setq postfix "G") (/ number (expt scale 3)))
                              ((< number (expt scale 5)) (setq postfix "T") (/ number (expt scale 4)))
                              ((< number (expt scale 6)) (setq postfix "P") (/ number (expt scale 5)))
                              ((< number (expt scale 7)) (setq postfix "E") (/ number (expt scale 6)))
                              (t
                               number)
                              )))
            postfix
            (when (and postfix binary) "i"))))
;; Use: (number-to-iso-postfixed-string 999 nil)
;; Use: (number-to-iso-postfixed-string 1001 nil)
;; Use: (number-to-iso-postfixed-string 1024)
;; Use: (number-to-iso-postfixed-string 1024 t)
;; Use: (number-to-iso-postfixed-string (* 1024 1024) t)
;; Use: (number-to-iso-postfixed-string (* 1024 1023) t)
;; Use: (number-to-iso-postfixed-string (* 1024 1025) t)
;; Use: (number-to-iso-postfixed-string (* 1024.0 1024 1025) t)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜