Hello Ron, Please, see inline comment hidden in the patch ;)
2015-07-21 12:24 GMT+02:00 Ron Yorston <[email protected]>: > 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 <[email protected]> > --- > 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; You should break from 'while' too (using evil goto?). No need to continue reading the file if you don't want count > MAXLINES (in fact, in your code, count will be incremented past MAXLINES in the next read). > + } > + } > + 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 Cheers, Xabier Oneca_,,_ _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
