| @@ -21,6 +21,85 @@ |
| * redirected input has been read from stdin |
| */ |
| |
| + | //config:config LESS |
| + | //config: bool "less" |
| + | //config: default y |
| + | //config: help |
| + | //config: 'less' is a pager, meaning that it displays text files. It possesses |
| + | //config: a wide array of features, and is an improvement over 'more'. |
| + | //config: |
| + | //config:config FEATURE_LESS_MAXLINES |
| + | //config: int "Max number of input lines less will try to eat" |
| + | //config: default 9999999 |
| + | //config: depends on LESS |
| + | //config: |
| + | //config:config FEATURE_LESS_BRACKETS |
| + | //config: bool "Enable bracket searching" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: This option adds the capability to search for matching left and right |
| + | //config: brackets, facilitating programming. |
| + | //config: |
| + | //config:config FEATURE_LESS_FLAGS |
| + | //config: bool "Enable extra flags" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: The extra flags provided do the following: |
| + | //config: |
| + | //config: The -M flag enables a more sophisticated status line. |
| + | //config: The -m flag enables a simpler status line with a percentage. |
| + | //config: |
| + | //config:config FEATURE_LESS_MARKS |
| + | //config: bool "Enable marks" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: Marks enable positions in a file to be stored for easy reference. |
| + | //config: |
| + | //config:config FEATURE_LESS_REGEXP |
| + | //config: bool "Enable regular expressions" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: Enable regular expressions, allowing complex file searches. |
| + | //config: |
| + | //config:config FEATURE_LESS_WINCH |
| + | //config: bool "Enable automatic resizing on window size changes" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: Makes less track window size changes. |
| + | //config: |
| + | //config:config FEATURE_LESS_ASK_TERMINAL |
| + | //config: bool "Use 'tell me cursor position' ESC sequence to measure window" |
| + | //config: default y |
| + | //config: depends on FEATURE_LESS_WINCH |
| + | //config: help |
| + | //config: Makes less track window size changes. |
| + | //config: If terminal size can't be retrieved and $LINES/$COLUMNS are not set, |
| + | //config: this option makes less perform a last-ditch effort to find it: |
| + | //config: position cursor to 999,999 and ask terminal to report real |
| + | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. |
| + | //config: |
| + | //config: This is not clean but helps a lot on serial lines and such. |
| + | //config: |
| + | //config:config FEATURE_LESS_DASHCMD |
| + | //config: bool "Enable flag changes ('-' command)" |
| + | //config: default y |
| + | //config: depends on LESS |
| + | //config: help |
| + | //config: This enables the ability to change command-line flags within |
| + | //config: less itself ('-' keyboard command). |
| + | //config: |
| + | //config:config FEATURE_LESS_LINENUMS |
| + | //config: bool "Enable dynamic switching of line numbers" |
| + | //config: default y |
| + | //config: depends on FEATURE_LESS_DASHCMD |
| + | //config: help |
| + | //config: Enables "-N" command. |
| + | |
| //usage:#define less_trivial_usage |
| //usage: "[-EMNmh~I?] [FILE]..." |
| //usage:#define less_full_usage "\n\n" |
| @@ -107,6 +186,9 @@ struct globals { |
| int num_matches; |
| regex_t pattern; |
| smallint pattern_valid; |
| + | #endif |
| + | #if ENABLE_FEATURE_LESS_ASK_TERMINAL |
| + | smallint winsize_err; |
| #endif |
| smallint terminated; |
| struct termios term_orig, term_less; |
| @@ -815,12 +897,17 @@ static void reinitialize(void) |
| cur_fline = 0; |
| max_lineno = 0; |
| open_file_and_read_lines(); |
| + | #if ENABLE_FEATURE_LESS_ASK_TERMINAL |
| + | if (G.winsize_err) |
| + | printf("\033[999;999H" "\033[6n"); |
| + | #endif |
| buffer_fill_and_print(); |
| } |
| |
| - | static int getch_nowait(void) |
| + | static int64_t getch_nowait(void) |
| { |
| int rd; |
| + | int64_t key64; |
| struct pollfd pfd[2]; |
| |
| pfd[0].fd = STDIN_FILENO; |
| @@ -868,8 +955,8 @@ static int getch_nowait(void) |
| |
| /* We have kbd_fd in O_NONBLOCK mode, read inside read_key() |
| * would not block even if there is no input available */ |
| - | rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); |
| - | if (rd == -1) { |
| + | key64 = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); |
| + | if ((int)key64 == -1) { |
| if (errno == EAGAIN) { |
| /* No keyboard input available. Since poll() did return, |
| * we should have input on stdin */ |
| @@ -881,25 +968,29 @@ static int getch_nowait(void) |
| less_exit(0); |
| } |
| set_tty_cooked(); |
| - | return rd; |
| + | return key64; |
| } |
| |
| /* Grab a character from input without requiring the return key. |
| * May return KEYCODE_xxx values. |
| * Note that this function works best with raw input. */ |
| - | static int less_getch(int pos) |
| + | static int64_t less_getch(int pos) |
| { |
| - | int i; |
| + | int64_t key64; |
| + | int key; |
| |
| again: |
| less_gets_pos = pos; |
| - | i = getch_nowait(); |
| + | key = key64 = getch_nowait(); |
| less_gets_pos = -1; |
| |
| - | /* Discard Ctrl-something chars */ |
| - | if (i >= 0 && i < ' ' && i != 0x0d && i != 8) |
| + | /* Discard Ctrl-something chars. |
| + | * (checking only lower 32 bits is a size optimization: |
| + | * upper 32 bits are used only by KEYCODE_CURSOR_POS) |
| + | */ |
| + | if (key >= 0 && key < ' ' && key != 0x0d && key != 8) |
| goto again; |
| - | return i; |
| + | return key; |
| } |
| |
| static char* less_gets(int sz) |
| @@ -1514,8 +1605,6 @@ static void sigwinch_handler(int sig UNUSED_PARAM) |
| int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| int less_main(int argc, char **argv) |
| { |
| - | int keypress; |
| - | |
| INIT_G(); |
| |
| /* TODO: -x: do not interpret backspace, -xx: tab also */ |
| @@ -1558,7 +1647,7 @@ int less_main(int argc, char **argv) |
| term_less.c_cc[VMIN] = 1; |
| term_less.c_cc[VTIME] = 0; |
| |
| - | get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
| + | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
| /* 20: two tabstops + 4 */ |
| if (width < 20 || max_displayed_line < 3) |
| return bb_cat(argv); |
| @@ -1573,11 +1662,14 @@ int less_main(int argc, char **argv) |
| buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); |
| reinitialize(); |
| while (1) { |
| + | int64_t keypress; |
| + | |
| #if ENABLE_FEATURE_LESS_WINCH |
| while (WINCH_COUNTER) { |
| again: |
| winch_counter--; |
| - | get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
| + | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
| + | IF_FEATURE_LESS_ASK_TERMINAL(got_size:) |
| /* 20: two tabstops + 4 */ |
| if (width < 20) |
| width = 20; |
| @@ -1597,8 +1689,18 @@ int less_main(int argc, char **argv) |
| /* This took some time. Loop back and check, |
| * were there another SIGWINCH? */ |
| } |
| - | #endif |
| keypress = less_getch(-1); /* -1: do not position cursor */ |
| + | # if ENABLE_FEATURE_LESS_ASK_TERMINAL |
| + | if ((int32_t)keypress == KEYCODE_CURSOR_POS) { |
| + | uint32_t rc = (keypress >> 32); |
| + | width = (rc & 0x7fff); |
| + | max_displayed_line = ((rc >> 16) & 0x7fff); |
| + | goto got_size; |
| + | } |
| + | # endif |
| + | #else |
| + | keypress = less_getch(-1); /* -1: do not position cursor */ |
| + | #endif |
| keypress_process(keypress); |
| } |
| } |