diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-07-25 15:18:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-07-25 15:18:20 +0200 |
commit | 4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe (patch) | |
tree | f39123cd092c53644788dea0636cfe155d4e8cb3 /miscutils/less.c | |
parent | be391e759675b23ccf6e19cb6ea5b819840f3026 (diff) |
less: optionally query terminal size via "ESC [ 6 n". Closes bug 2659.
+7 bytes is not selected, +100 if selected.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/less.c')
-rw-r--r-- | miscutils/less.c | 132 |
1 files changed, 117 insertions, 15 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 46024f9f7..16eb95d56 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -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" @@ -108,6 +187,9 @@ struct globals { 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; char kbd_input[KEYCODE_BUFFER_SIZE]; @@ -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); } } |