LINUX.ORG.RU

Человекочитаемые размеры в Midnight Commander

 


0

1

https://midnight-commander.org/ticket/3165
Интересно, почему этот патч не приняли?

Я его адаптировал для современной версии mc:

diff -rU 3 a/lib/util.c b/lib/util.c
--- a/lib/util.c	2019-10-13 18:40:47.000000000 +0000
+++ b/lib/util.c	2019-11-08 14:56:06.000000000 +0000
@@ -415,7 +415,8 @@
  */
 
 void
-size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si)
+size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si,
+                gboolean human_readable)
 {
     /* Avoid taking power for every file.  */
     /* *INDENT-OFF* */
@@ -456,6 +457,8 @@
     static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL };
 
     const char *const *sfx = use_si ? suffix_lc : suffix;
+    unsigned base = use_si ? 1000 : 1024;
+    unsigned human_digits;
     int j = 0;
 
     if (len == 0)
@@ -486,6 +489,9 @@
             size += size_remain;        /* Re-add remainder lost by division/multiplication */
         }
 
+    if (human_readable && len < 5)
+        human_readable = FALSE; /* Human readable form needs 5 characters */
+
     for (j = units; sfx[j] != NULL; j++)
     {
         if (size == 0)
@@ -503,11 +509,28 @@
             break;
         }
 
-        if (size < power10[len - (j > 0 ? 1 : 0)])
+#define DIV_ROUND(a, b) (((a) + ((b)/2))/(b))
+        if ((!human_readable && size < power10[len - (j > 0 ? 1 : 0)]) ||
+            (human_readable && size < 1000))
+         {
+             g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]);
+             break;
+         }
+        else if (human_readable && DIV_ROUND (size, 10) < base && sfx[j + 1])
+        {
+            human_digits = DIV_ROUND (size, 10) * 1000 / base;  /* 0 - 999 */
+            g_snprintf (buffer, len + 1, "%u.%02u%s",
+                        human_digits / 100, human_digits % 100, sfx[j + 1]);
+            break;
+        }
+        else if (human_readable && DIV_ROUND (size, 100) < base && sfx[j + 1])
         {
-            g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]);
+            human_digits = DIV_ROUND (size, 100) * 1000 / base; /* 0 - 999 */
+            g_snprintf (buffer, len + 1, "%u.%01u%s",
+                        human_digits / 10, human_digits % 10, sfx[j + 1]);
             break;
         }
+#undef DIV_ROUND
 
         /* Powers of 1000 or 1024, with rounding.  */
         if (use_si)
diff -rU 3 a/lib/util.h b/lib/util.h
--- a/lib/util.h	2019-10-13 18:40:47.000000000 +0000
+++ b/lib/util.h	2019-11-08 14:57:06.000000000 +0000
@@ -154,7 +154,7 @@
  * not including trailing 0. BUFFER should be at least LEN+1 long.
  *
  * Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */
-void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si);
+void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si, gboolean human_readable);
 const char *string_perm (mode_t mode_bits);
 
 const char *extension (const char *);
diff -rU 3 a/src/filemanager/boxes.c b/src/filemanager/boxes.c
--- a/src/filemanager/boxes.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/filemanager/boxes.c	2019-11-08 14:57:59.000000000 +0000
@@ -646,6 +646,7 @@
                 QUICK_START_GROUPBOX (N_("Main options")),
                     QUICK_CHECKBOX (N_("Show mi&ni-status"), &panels_options.show_mini_info, NULL),
                     QUICK_CHECKBOX (N_("Use SI si&ze units"), &panels_options.kilobyte_si, NULL),
+                    QUICK_CHECKBOX (N_("Human readable &size"), &panels_options.human_readable, NULL),
                     QUICK_CHECKBOX (N_("Mi&x all files"), &panels_options.mix_all_files, NULL),
                     QUICK_CHECKBOX (N_("Show &backup files"), &panels_options.show_backups, NULL),
                     QUICK_CHECKBOX (N_("Show &hidden files"), &panels_options.show_dot_files, NULL),
diff -rU 3 a/src/filemanager/chown.c b/src/filemanager/chown.c
--- a/src/filemanager/chown.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/filemanager/chown.c	2019-11-08 14:58:34.000000000 +0000
@@ -438,7 +438,7 @@
         chown_label (0, str_trunc (fname, GW - 4));
         chown_label (1, str_trunc (get_owner (sf_stat.st_uid), GW - 4));
         chown_label (2, str_trunc (get_group (sf_stat.st_gid), GW - 4));
-        size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si);
+        size_trunc_len (buffer, GW - 4, sf_stat.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable);
         chown_label (3, buffer);
         chown_label (4, string_perm (sf_stat.st_mode));
 
diff -rU 3 a/src/filemanager/filegui.c b/src/filemanager/filegui.c
--- a/src/filemanager/filegui.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/filemanager/filegui.c	2019-11-08 15:03:18.000000000 +0000
@@ -524,7 +524,7 @@
     vfs_path_free (p);
     g_free (s1);
     /* new file size */
-    size_trunc_len (s2, sizeof (s2), ui->src_stat->st_size, 0, panels_options.kilobyte_si);
+    size_trunc_len (s2, sizeof (s2), ui->src_stat->st_size, 0, panels_options.kilobyte_si, panels_options.human_readable);
     NEW_LABEL (2, s2);
     /* new file modification date & time */
     s1 = (char *) file_date (ui->src_stat->st_mtime);
@@ -539,7 +539,7 @@
     vfs_path_free (p);
     g_free (s1);
     /* existing file size */
-    size_trunc_len (s2, sizeof (s2), ui->dst_stat->st_size, 0, panels_options.kilobyte_si);
+    size_trunc_len (s2, sizeof (s2), ui->dst_stat->st_size, 0, panels_options.kilobyte_si, panels_options.human_readable);
     NEW_LABEL (6, s2);
     /* existing file modification date & time */
     s1 = (char *) file_date (ui->dst_stat->st_mtime);
@@ -1090,13 +1090,13 @@
 
     if (ui->total_bytes_label != NULL)
     {
-        size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si);
+        size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si, panels_options.human_readable);
 
         if (!ctx->progress_totals_computed)
             g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2);
         else
         {
-            size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si);
+            size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si, panels_options.human_readable);
             g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3);
         }
 
diff -rU 3 a/src/filemanager/info.c b/src/filemanager/info.c
--- a/src/filemanager/info.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/filemanager/info.c	2019-11-08 15:03:49.000000000 +0000
@@ -178,8 +178,8 @@
         {
             char buffer1[6], buffer2[6];
 
-            size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si);
-            size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si);
+            size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si, panels_options.human_readable);
+            size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si, panels_options.human_readable);
             tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2,
                         myfs_stats.total == 0 ? 0 :
                         (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
@@ -237,7 +237,7 @@
 #endif
         {
             char buffer[10];
-            size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si);
+            size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable);
             tty_printf (_("Size:       %s"), buffer);
 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
             tty_printf (ngettext (" (%lu block)", " (%lu blocks)",
diff -rU 3 a/src/filemanager/panel.c b/src/filemanager/panel.c
--- a/src/filemanager/panel.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/filemanager/panel.c	2019-11-08 15:04:16.000000000 +0000
@@ -515,7 +515,7 @@
         format_device_number (buffer, len + 1, fe->st.st_rdev);
     else
 #endif
-        size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si);
+        size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si, panels_options.human_readable);
 
     return buffer;
 }
@@ -1157,9 +1157,9 @@
         char buffer1[6], buffer2[6], tmp[BUF_SMALL];
 
         size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1,
-                        panels_options.kilobyte_si);
+                        panels_options.kilobyte_si, panels_options.human_readable);
         size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1,
-                        panels_options.kilobyte_si);
+                        panels_options.kilobyte_si, panels_options.human_readable);
         g_snprintf (tmp, sizeof (tmp), " %s/%s (%d%%) ", buffer1, buffer2,
                     myfs_stats.total == 0 ? 0 :
                     (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
diff -rU 3 a/src/setup.c b/src/setup.c
--- a/src/setup.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/setup.c	2019-11-08 18:25:32.000000000 +0000
@@ -131,6 +131,7 @@
 panels_options_t panels_options = {
     .show_mini_info = TRUE,
     .kilobyte_si = FALSE,
+    .human_readable = FALSE,
     .mix_all_files = FALSE,
     .show_backups = TRUE,
     .show_dot_files = TRUE,
@@ -410,6 +411,7 @@
 } panels_ini_options[] = {
     { "show_mini_info", &panels_options.show_mini_info },
     { "kilobyte_si", &panels_options.kilobyte_si },
+    { "human_readable", &panels_options.human_readable },
     { "mix_all_files", &panels_options.mix_all_files },
     { "show_backups", &panels_options.show_backups },
     { "show_dot_files", &panels_options.show_dot_files },
diff -rU 3 a/src/setup.h b/src/setup.h
--- a/src/setup.h	2019-10-13 18:40:47.000000000 +0000
+++ b/src/setup.h	2019-11-08 15:05:51.000000000 +0000
@@ -37,6 +37,7 @@
     gboolean show_mini_info;    /* If true, show the mini-info on the panel */
     gboolean kilobyte_si;       /* If TRUE, SI units (1000 based) will be used for larger units
                                  * (kilobyte, megabyte, ...). If FALSE, binary units (1024 based) will be used */
+    gboolean human_readable;    /* If TRUE, at most three digits are used to display the size of the files. */
     gboolean mix_all_files;     /* If FALSE then directories are shown separately from files */
     gboolean show_backups;      /* If TRUE, show files ending in ~ */
     gboolean show_dot_files;    /* If TRUE, show files starting with a dot */
diff -rU 3 a/src/viewer/display.c b/src/viewer/display.c
--- a/src/viewer/display.c	2019-10-13 18:40:47.000000000 +0000
+++ b/src/viewer/display.c	2019-11-08 15:06:24.000000000 +0000
@@ -172,7 +172,7 @@
             char buffer[BUF_TRUNC_LEN + 1];
 
             size_trunc_len (buffer, BUF_TRUNC_LEN, mcview_get_filesize (view), 0,
-                            panels_options.kilobyte_si);
+                            panels_options.kilobyte_si, panels_options.human_readable);
             tty_printf ("%9" PRIuMAX "/%s%s %s", (uintmax_t) view->dpy_end,
                         buffer, mcview_may_still_grow (view) ? "+" : " ",
 #ifdef HAVE_CHARSET

В настройках панели выбираешь опцию «human readable size», работает, на первый взгляд, нормально: https://i.imgur.com/WwthIt7.png

★★★

Последнее исправление: dadd (всего исправлений: 1)

Это работает из коробки, если задать пользовательский формат колонок и ширину колонки с размером файлов 4.

anonymous
()

<sarcasm> Это некорректный формат: правильный вариант, когда разницу в размерах можно прикинуть по количеству цифр. </sarcasm>

Если серьезно, то в mc долгое время продвигали такой подход, как более эргономичный, чем различать 25.1K и 2.51K. В любом случае, с текущими темпами разработки разве что серьезные багфиксы принимаются, к сожалению.

lu4nik ★★★
()
Последнее исправление: lu4nik (всего исправлений: 1)
Ответ на: комментарий от anonymous

Круто, не знал про жесткую установку ширины колонки. Всё, тему можно закрывать.

lu4nik ★★★
()
Ответ на: комментарий от anonymous

10.2M удобнее читать, чем 10752K.

dadd ★★★
() автор топика

отличное приложение, ему еще tvision-фич как в dosNavigator

anonymous
()

Эх, надеялся, что патч будет выводить в человекочитаемом формате размер на информационной панели – обычно так пользуюсь. Спасибо, что указали на 4-х символьное ограничение в столбцах: в жизни бы не догадался, что такая важная опция включается таким неочевидым способом.

rmu ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.