[PATCH] less: improvements to verbose status messages
Ron Yorston
rmy at pobox.com
Tue Jul 21 10:24:12 UTC 2015
Make verbose status messages (-m/-M flags) behave more like the
real `less` command:
- fix display of line numbers so they're correct whether lines are
being truncated (-S flag) or wrapped.
- don't display total lines or percentage when lines are read from
stdin: we don't have that information until we reach EOF. When
we do reach EOF the additional information is displayed.
- when lines are read from a file count the total number of lines
so that we can display percentages. Counting lines is avoided
until the information is actually needed. If the user pages to
EOF the separate read pass can be avoided entirely.
Fixes Bug 7586
function old new delta
m_status_print 200 364 +164
safe_lineno - 41 +41
reinitialize 186 197 +11
read_lines 809 819 +10
less_main 2600 2606 +6
.rodata 156077 156045 -32
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/1 up/down: 232/-32) Total: 200 bytes
Signed-off-by: Ron Yorston <rmy at pobox.com>
---
miscutils/less.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 14 deletions(-)
diff --git a/miscutils/less.c b/miscutils/less.c
index 90c1038..c09930f 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -165,6 +165,11 @@ enum {
enum { pattern_valid = 0 };
#endif
+enum {
+ READING_FILE = -1,
+ READING_STDIN = -2
+};
+
struct globals {
int cur_fline; /* signed */
int kbd_fd; /* fd to get input from */
@@ -188,6 +193,9 @@ struct globals {
unsigned current_file;
char *filename;
char **files;
+#if ENABLE_FEATURE_LESS_FLAGS
+ int num_lines; /* input source if < 0, line count if >= 0 */
+#endif
#if ENABLE_FEATURE_LESS_MARKS
unsigned num_marks;
unsigned mark_lines[15][2];
@@ -229,6 +237,7 @@ struct globals {
#define current_file (G.current_file )
#define filename (G.filename )
#define files (G.files )
+#define num_lines (G.num_lines )
#define num_marks (G.num_marks )
#define mark_lines (G.mark_lines )
#if ENABLE_FEATURE_LESS_REGEXP
@@ -574,6 +583,10 @@ static void read_lines(void)
print_statusline(bb_msg_read_error);
}
}
+#if ENABLE_FEATURE_LESS_FLAGS
+ else if (eof_error == 0)
+ num_lines = max_lineno;
+#endif
fill_match_lines(old_max_fline);
#if ENABLE_FEATURE_LESS_REGEXP
@@ -584,18 +597,25 @@ static void read_lines(void)
}
#if ENABLE_FEATURE_LESS_FLAGS
-/* Interestingly, writing calc_percent as a function saves around 32 bytes
- * on my build. */
-static int calc_percent(void)
+static int safe_lineno(int fline)
{
- unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1);
- return p <= 100 ? p : 100;
+ if (fline >= max_fline)
+ fline = max_fline - 1;
+
+ /* also catches empty file (max_fline == 0) */
+ if (fline < 0)
+ return 0;
+
+ return LINENO(flines[fline]) + 1;
}
/* Print a status line if -M was specified */
static void m_status_print(void)
{
- int percentage;
+ int first, last, fd, count;
+ char buf[4096];
+ ssize_t len, i;
+ unsigned percent;
if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
return;
@@ -604,17 +624,39 @@ static void m_status_print(void)
printf(HIGHLIGHT"%s", filename);
if (num_files > 1)
printf(" (file %i of %i)", current_file, num_files);
- printf(" lines %i-%i/%i ",
- cur_fline + 1, cur_fline + max_displayed_line + 1,
- max_fline + 1);
+
+ first = safe_lineno(cur_fline);
+ last = (option_mask32 & FLAG_S) ?
+ MIN(first + max_displayed_line, max_lineno) :
+ safe_lineno(cur_fline + max_displayed_line);
+ printf(" lines %i-%i", first, last);
+
+ if (num_lines == READING_FILE) {
+ /* count number of lines in file */
+ count = 0;
+ fd = xopen(filename, O_RDONLY);
+ while ((len=safe_read(fd, buf, 4096)) > 0) {
+ for (i=0; i<len; ++i) {
+ if (buf[i] == '\n' && ++count == MAXLINES)
+ break;
+ }
+ }
+ close(fd);
+ num_lines = count;
+ }
+
+ if (num_lines >= 0)
+ printf("/%i", num_lines);
+
if (cur_fline >= (int)(max_fline - max_displayed_line)) {
- printf("(END)"NORMAL);
+ printf(" (END)");
if (num_files > 1 && current_file != num_files)
- printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]);
- return;
+ printf(" - next: %s", files[current_file]);
+ } else if (num_lines > 0) {
+ percent = (100 * last + num_lines/2) / num_lines;
+ printf(" %i%%", percent <= 100 ? percent : 100);
}
- percentage = calc_percent();
- printf("%i%%"NORMAL, percentage);
+ printf(NORMAL);
}
#endif
@@ -915,6 +957,9 @@ static void reinitialize(void)
max_fline = -1;
cur_fline = 0;
max_lineno = 0;
+#if ENABLE_FEATURE_LESS_FLAGS
+ num_lines = filename ? READING_FILE : READING_STDIN;
+#endif
open_file_and_read_lines();
#if ENABLE_FEATURE_LESS_ASK_TERMINAL
if (G.winsize_err)
--
2.4.3
More information about the busybox
mailing list