diff options
author | Ron Yorston <rmy@pobox.com> | 2015-07-21 22:28:09 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-07-21 22:28:09 +0200 |
commit | 193ba408a4fd3313b1dc2eb5eb25885cfa4363f6 (patch) | |
tree | 1062a000b0d330756ec8e88e14052d803634f2a9 | |
parent | 35ae2ccb40924efcd0fd0c873cc9e56c58851222 (diff) | |
download | busybox-w32-193ba408a4fd3313b1dc2eb5eb25885cfa4363f6.tar.gz busybox-w32-193ba408a4fd3313b1dc2eb5eb25885cfa4363f6.tar.bz2 busybox-w32-193ba408a4fd3313b1dc2eb5eb25885cfa4363f6.zip |
less: improvements to verbose status messages
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 195 382 +187
safe_lineno - 35 +35
reinitialize 172 182 +10
read_lines 675 685 +10
buffer_fill_and_print 178 169 -9
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/1 up/down: 242/-9) Total: 233 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/less.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 90c103888..dd932c5ed 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -165,6 +165,11 @@ enum { | |||
165 | enum { pattern_valid = 0 }; | 165 | enum { pattern_valid = 0 }; |
166 | #endif | 166 | #endif |
167 | 167 | ||
168 | enum { | ||
169 | READING_FILE = -1, | ||
170 | READING_STDIN = -2 | ||
171 | }; | ||
172 | |||
168 | struct globals { | 173 | struct globals { |
169 | int cur_fline; /* signed */ | 174 | int cur_fline; /* signed */ |
170 | int kbd_fd; /* fd to get input from */ | 175 | int kbd_fd; /* fd to get input from */ |
@@ -188,6 +193,9 @@ struct globals { | |||
188 | unsigned current_file; | 193 | unsigned current_file; |
189 | char *filename; | 194 | char *filename; |
190 | char **files; | 195 | char **files; |
196 | #if ENABLE_FEATURE_LESS_FLAGS | ||
197 | int num_lines; /* input source if < 0, line count if >= 0 */ | ||
198 | #endif | ||
191 | #if ENABLE_FEATURE_LESS_MARKS | 199 | #if ENABLE_FEATURE_LESS_MARKS |
192 | unsigned num_marks; | 200 | unsigned num_marks; |
193 | unsigned mark_lines[15][2]; | 201 | unsigned mark_lines[15][2]; |
@@ -229,6 +237,7 @@ struct globals { | |||
229 | #define current_file (G.current_file ) | 237 | #define current_file (G.current_file ) |
230 | #define filename (G.filename ) | 238 | #define filename (G.filename ) |
231 | #define files (G.files ) | 239 | #define files (G.files ) |
240 | #define num_lines (G.num_lines ) | ||
232 | #define num_marks (G.num_marks ) | 241 | #define num_marks (G.num_marks ) |
233 | #define mark_lines (G.mark_lines ) | 242 | #define mark_lines (G.mark_lines ) |
234 | #if ENABLE_FEATURE_LESS_REGEXP | 243 | #if ENABLE_FEATURE_LESS_REGEXP |
@@ -574,6 +583,10 @@ static void read_lines(void) | |||
574 | print_statusline(bb_msg_read_error); | 583 | print_statusline(bb_msg_read_error); |
575 | } | 584 | } |
576 | } | 585 | } |
586 | #if ENABLE_FEATURE_LESS_FLAGS | ||
587 | else if (eof_error == 0) | ||
588 | num_lines = max_lineno; | ||
589 | #endif | ||
577 | 590 | ||
578 | fill_match_lines(old_max_fline); | 591 | fill_match_lines(old_max_fline); |
579 | #if ENABLE_FEATURE_LESS_REGEXP | 592 | #if ENABLE_FEATURE_LESS_REGEXP |
@@ -584,18 +597,23 @@ static void read_lines(void) | |||
584 | } | 597 | } |
585 | 598 | ||
586 | #if ENABLE_FEATURE_LESS_FLAGS | 599 | #if ENABLE_FEATURE_LESS_FLAGS |
587 | /* Interestingly, writing calc_percent as a function saves around 32 bytes | 600 | static int safe_lineno(int fline) |
588 | * on my build. */ | ||
589 | static int calc_percent(void) | ||
590 | { | 601 | { |
591 | unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); | 602 | if (fline >= max_fline) |
592 | return p <= 100 ? p : 100; | 603 | fline = max_fline - 1; |
604 | |||
605 | /* also catches empty file (max_fline == 0) */ | ||
606 | if (fline < 0) | ||
607 | return 0; | ||
608 | |||
609 | return LINENO(flines[fline]) + 1; | ||
593 | } | 610 | } |
594 | 611 | ||
595 | /* Print a status line if -M was specified */ | 612 | /* Print a status line if -M was specified */ |
596 | static void m_status_print(void) | 613 | static void m_status_print(void) |
597 | { | 614 | { |
598 | int percentage; | 615 | int first, last; |
616 | unsigned percent; | ||
599 | 617 | ||
600 | if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ | 618 | if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ |
601 | return; | 619 | return; |
@@ -604,17 +622,51 @@ static void m_status_print(void) | |||
604 | printf(HIGHLIGHT"%s", filename); | 622 | printf(HIGHLIGHT"%s", filename); |
605 | if (num_files > 1) | 623 | if (num_files > 1) |
606 | printf(" (file %i of %i)", current_file, num_files); | 624 | printf(" (file %i of %i)", current_file, num_files); |
607 | printf(" lines %i-%i/%i ", | 625 | |
608 | cur_fline + 1, cur_fline + max_displayed_line + 1, | 626 | first = safe_lineno(cur_fline); |
609 | max_fline + 1); | 627 | last = (option_mask32 & FLAG_S) |
628 | ? MIN(first + max_displayed_line, max_lineno) | ||
629 | : safe_lineno(cur_fline + max_displayed_line); | ||
630 | printf(" lines %i-%i", first, last); | ||
631 | |||
632 | if (num_lines == READING_FILE) { | ||
633 | int count, fd; | ||
634 | ssize_t len, i; | ||
635 | char buf[4096]; | ||
636 | struct stat stbuf; | ||
637 | |||
638 | /* count number of lines in file */ | ||
639 | count = 0; | ||
640 | fd = open(filename, O_RDONLY); | ||
641 | if (fd < 0) | ||
642 | goto skip; | ||
643 | if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) | ||
644 | goto do_close; | ||
645 | while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { | ||
646 | for (i = 0; i < len; ++i) { | ||
647 | if (buf[i] == '\n' && ++count == MAXLINES) | ||
648 | goto done; | ||
649 | } | ||
650 | } | ||
651 | done: | ||
652 | num_lines = count; | ||
653 | do_close: | ||
654 | close(fd); | ||
655 | skip: ; | ||
656 | } | ||
657 | |||
658 | if (num_lines >= 0) | ||
659 | printf("/%i", num_lines); | ||
660 | |||
610 | if (cur_fline >= (int)(max_fline - max_displayed_line)) { | 661 | if (cur_fline >= (int)(max_fline - max_displayed_line)) { |
611 | printf("(END)"NORMAL); | 662 | printf(" (END)"); |
612 | if (num_files > 1 && current_file != num_files) | 663 | if (num_files > 1 && current_file != num_files) |
613 | printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); | 664 | printf(" - next: %s", files[current_file]); |
614 | return; | 665 | } else if (num_lines > 0) { |
666 | percent = (100 * last + num_lines/2) / num_lines; | ||
667 | printf(" %i%%", percent <= 100 ? percent : 100); | ||
615 | } | 668 | } |
616 | percentage = calc_percent(); | 669 | printf(NORMAL); |
617 | printf("%i%%"NORMAL, percentage); | ||
618 | } | 670 | } |
619 | #endif | 671 | #endif |
620 | 672 | ||
@@ -915,6 +967,9 @@ static void reinitialize(void) | |||
915 | max_fline = -1; | 967 | max_fline = -1; |
916 | cur_fline = 0; | 968 | cur_fline = 0; |
917 | max_lineno = 0; | 969 | max_lineno = 0; |
970 | #if ENABLE_FEATURE_LESS_FLAGS | ||
971 | num_lines = filename ? READING_FILE : READING_STDIN; | ||
972 | #endif | ||
918 | open_file_and_read_lines(); | 973 | open_file_and_read_lines(); |
919 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL | 974 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL |
920 | if (G.winsize_err) | 975 | if (G.winsize_err) |